Merge "Merge "docs: App Translation API updates" into mnc-docs am: 1ede811143 am: ec6effa1b0 am: 70f2e39008 am: e60af6b9e2" into nyc-dev
diff --git a/core/java/android/net/INetworkPolicyListener.aidl b/core/java/android/net/INetworkPolicyListener.aidl
index 6523192..812f1fe 100644
--- a/core/java/android/net/INetworkPolicyListener.aidl
+++ b/core/java/android/net/INetworkPolicyListener.aidl
@@ -23,6 +23,5 @@
void onMeteredIfacesChanged(in String[] meteredIfaces);
void onRestrictBackgroundChanged(boolean restrictBackground);
void onRestrictBackgroundWhitelistChanged(int uid, boolean whitelisted);
- void onRestrictPowerChanged(boolean restrictPower);
}
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index fc9b8dd..224ff5b 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -54,7 +54,6 @@
/** Control if background data is restricted system-wide. */
void setRestrictBackground(boolean restrictBackground);
boolean getRestrictBackground();
- boolean getRestrictPower();
/** Callback used to change internal state on tethering */
void onTetheringChanged(String iface, boolean tethering);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverController.java
index 0bca241..e6e189f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverController.java
@@ -91,10 +91,6 @@
}
@Override
- public void onRestrictPowerChanged(boolean restrictPower) {
- }
-
- @Override
public void onRestrictBackgroundWhitelistChanged(int uid, boolean whitelisted) {
}
};
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 8763b93..53b2942 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -33,6 +33,7 @@
import static android.net.NetworkPolicyManager.MASK_METERED_NETWORKS;
import static android.net.NetworkPolicyManager.MASK_ALL_NETWORKS;
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_TEMPORARY_ALLOW_METERED;
import static android.net.NetworkPolicyManager.uidRulesToString;
@@ -218,9 +219,6 @@
/** Flag indicating if background data is restricted. */
@GuardedBy("mRulesLock")
private boolean mRestrictBackground;
- /** Flag indicating if background data is restricted due to battery savings. */
- @GuardedBy("mRulesLock")
- private boolean mRestrictPower;
final private Context mContext;
private int mNetworkPreference;
@@ -669,7 +667,6 @@
try {
mPolicyManager.setConnectivityListener(mPolicyListener);
mRestrictBackground = mPolicyManager.getRestrictBackground();
- mRestrictPower = mPolicyManager.getRestrictPower();
} catch (RemoteException e) {
// ouch, no rules updates means some processes may never get network
loge("unable to register INetworkPolicyListener" + e);
@@ -942,13 +939,11 @@
+ ": " + allowed);
}
}
- // ...then Battery Saver Mode.
- if (allowed && mRestrictPower) {
- allowed = (uidRules & RULE_ALLOW_ALL) != 0;
+ // ...then power restrictions.
+ if (allowed) {
+ allowed = (uidRules & RULE_REJECT_ALL) == 0;
if (LOGD_RULES) Log.d(TAG, "allowed status for uid " + uid + " when"
- + " mRestrictPower=" + mRestrictPower
- + ", whitelisted=" + ((uidRules & RULE_ALLOW_ALL) != 0)
- + ": " + allowed);
+ + " rule is " + uidRulesToString(uidRules) + ": " + allowed);
}
return !allowed;
}
@@ -1400,7 +1395,11 @@
final int oldRules = mUidRules.get(uid, RULE_NONE);
if (oldRules == uidRules) return;
- mUidRules.put(uid, uidRules);
+ if (uidRules == RULE_NONE) {
+ mUidRules.delete(uid);
+ } else {
+ mUidRules.put(uid, uidRules);
+ }
}
// TODO: notify UID when it has requested targeted updates
@@ -1439,18 +1438,6 @@
}
@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
public void onRestrictBackgroundWhitelistChanged(int uid, boolean whitelisted) {
if (LOGD_RULES) {
// caller is NPMS, since we only register with them
@@ -1891,10 +1878,6 @@
pw.println(mRestrictBackground);
pw.println();
- pw.print("Restrict power: ");
- pw.println(mRestrictPower);
- pw.println();
-
pw.println("Status for known UIDs:");
pw.increaseIndent();
final int size = mUidRules.size();
diff --git a/services/core/java/com/android/server/job/controllers/ConnectivityController.java b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
index e0179dc..9fd22686 100644
--- a/services/core/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
@@ -170,11 +170,6 @@
}
@Override
- public void onRestrictPowerChanged(boolean restrictPower) {
- updateTrackedJobs(-1);
- }
-
- @Override
public void onRestrictBackgroundChanged(boolean restrictBackground) {
updateTrackedJobs(-1);
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 344ba17..4bdc237 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -266,7 +266,6 @@
private static final int MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED = 9;
private static final int MSG_UPDATE_INTERFACE_QUOTA = 10;
private static final int MSG_REMOVE_INTERFACE_QUOTA = 11;
- private static final int MSG_RESTRICT_POWER_CHANGED = 12;
private final Context mContext;
private final IActivityManager mActivityManager;
@@ -557,18 +556,9 @@
updateRulesForGlobalChangeLocked(true);
}
}
- mHandler.obtainMessage(MSG_RESTRICT_POWER_CHANGED,
- enabled ? 1 : 0, 0).sendToTarget();
}
});
- final boolean oldRestrictPower = mRestrictPower;
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;
@@ -740,7 +730,7 @@
if (LOGV) Slog.v(TAG, "ACTION_UID_REMOVED for uid=" + uid);
synchronized (mRulesLock) {
mUidPolicy.delete(uid);
- updateRuleForRestrictBackgroundLocked(uid);
+ updateRestrictionRulesForUidLocked(uid);
writePolicyLocked();
}
}
@@ -1729,7 +1719,7 @@
mUidPolicy.put(uid, policy);
// uid policy changed, recompute rules and persist policy.
- updateRuleForRestrictBackgroundLocked(uid);
+ updateRulesForDataUsageRestrictionsLocked(uid);
if (persist) {
writePolicyLocked();
}
@@ -2036,7 +2026,7 @@
}
if (needFirewallRules) {
// Only update firewall rules if necessary...
- updateRuleForRestrictBackgroundLocked(uid);
+ updateRulesForDataUsageRestrictionsLocked(uid);
}
// ...but always persists the whitelist request.
writePolicyLocked();
@@ -2081,7 +2071,7 @@
}
if (needFirewallRules) {
// Only update firewall rules if necessary...
- updateRuleForRestrictBackgroundLocked(uid, uidDeleted);
+ updateRulesForDataUsageRestrictionsLocked(uid, uidDeleted);
}
if (updateNow) {
// ...but always persists the whitelist request.
@@ -2146,15 +2136,6 @@
}
@Override
- public boolean getRestrictPower() {
- mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
-
- synchronized (mRulesLock) {
- return mRestrictPower;
- }
- }
-
- @Override
public void setDeviceIdleMode(boolean enabled) {
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
@@ -2446,6 +2427,11 @@
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) {
// only really in foreground when screen is also on
return mScreenOn && state <= ActivityManager.PROCESS_STATE_TOP;
@@ -2453,7 +2439,8 @@
/**
* 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) {
final int oldUidState = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
@@ -2463,12 +2450,16 @@
updateRestrictBackgroundRulesOnUidStatusChangedLocked(uid, oldUidState, uidState);
if (isProcStateAllowedWhileIdleOrPowerSaveMode(oldUidState)
!= isProcStateAllowedWhileIdleOrPowerSaveMode(uidState) ) {
+ if (isUidIdle(uid)) {
+ updateRuleForAppIdleLocked(uid);
+ }
if (mDeviceIdleMode) {
updateRuleForDeviceIdleLocked(uid);
}
if (mRestrictPower) {
updateRuleForRestrictPowerLocked(uid);
}
+ updateRulesForPowerRestrictionsLocked(uid);
}
updateNetworkStats(uid, isUidStateForegroundLocked(uidState));
}
@@ -2488,6 +2479,7 @@
if (mRestrictPower) {
updateRuleForRestrictPowerLocked(uid);
}
+ updateRulesForPowerRestrictionsLocked(uid);
updateNetworkStats(uid, false);
}
}
@@ -2509,7 +2501,7 @@
final boolean newForeground =
isProcStateAllowedWhileOnRestrictBackgroundLocked(newUidState);
if (oldForeground != newForeground) {
- updateRuleForRestrictBackgroundLocked(uid);
+ updateRulesForDataUsageRestrictionsLocked(uid);
}
}
@@ -2600,6 +2592,10 @@
enableFirewallChainLocked(chain, enabled);
}
+ private void updateRulesForNonMeteredNetworksLocked() {
+
+ }
+
private boolean isWhitelistedBatterySaverLocked(int uid) {
final int appId = UserHandle.getAppId(uid);
return mPowerSaveTempWhitelistAppIds.get(appId) || mPowerSaveWhitelistAppIds.get(appId);
@@ -2646,7 +2642,8 @@
if (!isUidValidForBlacklistRules(uid)) return;
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);
} else {
setUidFirewallRule(FIREWALL_CHAIN_STANDBY, uid, FIREWALL_RULE_DEFAULT);
@@ -2701,7 +2698,8 @@
for (int j = 0; j < appsSize; j++) {
final ApplicationInfo app = apps.get(j);
final int uid = UserHandle.getUid(user.id, app.uid);
- updateRuleForRestrictBackgroundLocked(uid);
+ updateRulesForDataUsageRestrictionsLocked(uid);
+ updateRulesForPowerRestrictionsLocked(uid);
}
}
}
@@ -2713,9 +2711,12 @@
for (int j = mPowerSaveTempWhitelistAppIds.size() - 1; j >= 0; j--) {
int appId = mPowerSaveTempWhitelistAppIds.keyAt(j);
int uid = UserHandle.getUid(user.id, appId);
+ // Update external firewall rules.
updateRuleForAppIdleLocked(uid);
updateRuleForDeviceIdleLocked(uid);
updateRuleForRestrictPowerLocked(uid);
+ // Update internal rules.
+ updateRulesForPowerRestrictionsLocked(uid);
}
}
}
@@ -2769,15 +2770,27 @@
/**
* 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>
+ * <li>Doze mode
+ * <li>App idle mode
* <li>Battery Saver Mode (also referred as power save).
* <li>Data Saver Mode (The Feature Formerly Known As 'Restrict Background Data').
* </ul>
+ *
+ * <p>This method changes both the external firewall rules and the internal state.
*/
private void updateRestrictionRulesForUidLocked(int uid) {
+ // Methods below only changes the firewall rules for the power-related modes.
+ updateRuleForDeviceIdleLocked(uid);
+ updateRuleForAppIdleLocked(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 @@
* {@link #setUidPolicy(int, int)} and {@link #addRestrictBackgroundWhitelistedUid(int)} /
* {@link #removeRestrictBackgroundWhitelistedUid(int)} methods (for blacklist and whitelist
* 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
* Data Saver Mode flips or UID state changes) that might affect the foreground app, since the
* following rules should also be applied:
@@ -2818,19 +2831,16 @@
*
* <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) {
- updateRuleForRestrictBackgroundLocked(uid, false);
+ private void updateRulesForDataUsageRestrictionsLocked(int uid) {
+ 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.
*/
- private void updateRuleForRestrictBackgroundLocked(int uid, boolean uidDeleted) {
+ private void updateRulesForDataUsageRestrictionsLocked(int uid, boolean uidDeleted) {
if (!uidDeleted && !isUidValidForWhitelistRules(uid)) {
if (LOGD) Slog.d(TAG, "no need to update restrict data rules for uid " + uid);
return;
@@ -2840,50 +2850,36 @@
final int oldUidRules = mUidRules.get(uid, RULE_NONE);
final boolean isForeground = isUidForegroundOnRestrictBackgroundLocked(uid);
- // Data Saver status.
- final boolean isDsBlacklisted = (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0;
- final boolean isDsWhitelisted = mRestrictBackgroundWhitelistUids.get(uid);
- final int oldDsRule = oldUidRules & MASK_METERED_NETWORKS;
- int newDsRule = RULE_NONE;
-
- // Battery Saver status.
- final boolean isBsWhitelisted = isWhitelistedBatterySaverLocked(uid);
- final int oldBsRule = oldUidRules & MASK_ALL_NETWORKS;
- int newBsRule = RULE_NONE;
+ final boolean isBlacklisted = (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0;
+ final boolean isWhitelisted = mRestrictBackgroundWhitelistUids.get(uid);
+ final int oldRule = oldUidRules & MASK_METERED_NETWORKS;
+ int newRule = RULE_NONE;
// First step: define the new rule based on user restrictions and foreground state.
if (isForeground) {
- // Data Saver rules
- if (isDsBlacklisted || (mRestrictBackground && !isDsWhitelisted)) {
- newDsRule = RULE_TEMPORARY_ALLOW_METERED;
- } else if (isDsWhitelisted) {
- newDsRule = RULE_ALLOW_METERED;
- }
- // Battery Saver rules
- if (mRestrictPower) {
- newBsRule = RULE_ALLOW_ALL;
+ if (isBlacklisted || (mRestrictBackground && !isWhitelisted)) {
+ newRule = RULE_TEMPORARY_ALLOW_METERED;
+ } else if (isWhitelisted) {
+ newRule = RULE_ALLOW_METERED;
}
} else {
- // Data Saver rules
- if (isDsBlacklisted) {
- newDsRule = RULE_REJECT_METERED;
- } else if (mRestrictBackground && isDsWhitelisted) {
- newDsRule = RULE_ALLOW_METERED;
- }
- // Battery Saver rules
- if (mRestrictPower) {
- newBsRule = isBsWhitelisted ? RULE_ALLOW_ALL : RULE_REJECT_ALL;
+ if (isBlacklisted) {
+ newRule = RULE_REJECT_METERED;
+ } else if (mRestrictBackground && isWhitelisted) {
+ newRule = RULE_ALLOW_METERED;
}
}
- final int newUidRules = newDsRule | newBsRule;
+ final int newUidRules = newRule | (oldUidRules & MASK_ALL_NETWORKS);
if (LOGV) {
- Log.v(TAG, "updateRuleForRestrictBackgroundLocked(" + uid + "):"
- + " isForeground=" +isForeground + ", isBlacklisted: " + isDsBlacklisted
- + ", isDsWhitelisted: " + isDsWhitelisted
- + ", isBsWhitelisted: " + isBsWhitelisted
- + ", newUidRules: " + uidRulesToString(newUidRules)
- + ", oldUidRules: " + uidRulesToString(oldUidRules));
+ Log.v(TAG, "updateRuleForRestrictBackgroundLocked(" + uid + ")"
+ + ": isForeground=" +isForeground
+ + ", isBlacklisted=" + isBlacklisted
+ + ", isWhitelisted=" + isWhitelisted
+ + ", oldRule=" + uidRulesToString(oldRule)
+ + ", newRule=" + uidRulesToString(newRule)
+ + ", newUidRules=" + uidRulesToString(newUidRules)
+ + ", oldUidRules=" + uidRulesToString(oldUidRules));
}
if (newUidRules == RULE_NONE) {
@@ -2895,12 +2891,10 @@
boolean changed = false;
// Second step: apply bw changes based on change of state.
-
- // Apply Data Saver rules.
- if (newDsRule != oldDsRule) {
+ if (newRule != oldRule) {
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
// (since bw_penalty_box prevails over bw_happy_box).
@@ -2908,68 +2902,132 @@
// TODO: if statement below is used to avoid an unnecessary call to netd / iptables,
// but ideally it should be just:
// setMeteredNetworkBlacklist(uid, isBlacklisted);
- if (isDsBlacklisted) {
+ if (isBlacklisted) {
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.
// TODO: if statements below are used to avoid unnecessary calls to netd / iptables,
// but ideally they should be just:
// setMeteredNetworkWhitelist(uid, isWhitelisted);
// setMeteredNetworkBlacklist(uid, isBlacklisted);
- if (!isDsWhitelisted) {
+ if (!isWhitelisted) {
setMeteredNetworkWhitelist(uid, false);
}
- if (isDsBlacklisted) {
+ if (isBlacklisted) {
setMeteredNetworkBlacklist(uid, true);
}
- } else if ((newDsRule & RULE_REJECT_METERED) != 0
- || (oldDsRule & RULE_REJECT_METERED) != 0) {
+ } else if ((newRule & RULE_REJECT_METERED) != 0
+ || (oldRule & RULE_REJECT_METERED) != 0) {
// Flip state because app was explicitly added or removed to blacklist.
- setMeteredNetworkBlacklist(uid, isDsBlacklisted);
- if ((oldDsRule & RULE_REJECT_METERED) != 0 && isDsWhitelisted) {
+ setMeteredNetworkBlacklist(uid, isBlacklisted);
+ if ((oldRule & RULE_REJECT_METERED) != 0 && isWhitelisted) {
// Since blacklist prevails over whitelist, we need to handle the special case
// where app is whitelisted and blacklisted at the same time (although such
// scenario should be blocked by the UI), then blacklist is removed.
- setMeteredNetworkWhitelist(uid, isDsWhitelisted);
+ setMeteredNetworkWhitelist(uid, isWhitelisted);
}
- } else if ((newDsRule & RULE_ALLOW_METERED) != 0
- || (oldDsRule & RULE_ALLOW_METERED) != 0) {
+ } else if ((newRule & RULE_ALLOW_METERED) != 0
+ || (oldRule & RULE_ALLOW_METERED) != 0) {
// Flip state because app was explicitly added or removed to whitelist.
- setMeteredNetworkWhitelist(uid, isDsWhitelisted);
+ setMeteredNetworkWhitelist(uid, isWhitelisted);
} 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
+ ": foreground=" + isForeground
- + ", whitelisted=" + isDsWhitelisted
- + ", blacklisted=" + isDsBlacklisted
+ + ", whitelisted=" + isWhitelisted
+ + ", blacklisted=" + isBlacklisted
+ ", newRule=" + uidRulesToString(newUidRules)
+ ", oldRule=" + uidRulesToString(oldUidRules));
}
+
+ // Dispatch changed rule to existing listeners.
+ mHandler.obtainMessage(MSG_RULES_CHANGED, uid, newUidRules).sendToTarget();
+ }
+ }
+
+ /**
+ * Updates the power-related part of the {@link #mUidRules} for a given map, and notify external
+ * listeners in case of change.
+ * <p>
+ * There are 3 power-related rules that affects whether an app has background access on
+ * 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;
}
- // Apply Battery Saver rules.
- // NOTE: the firewall rules are changed outside this method, but it's still necessary to
- // send the MSG_RULES_CHANGED so ConnectivityService can update its internal status.
- if (newBsRule != oldBsRule) {
- changed = true;
- if (newBsRule == RULE_NONE || (newBsRule & RULE_ALLOW_ALL) != 0) {
+ 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);
- } 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);
} else {
// All scenarios should have been covered above
Log.wtf(TAG, "Unexpected change of non-metered UID state for " + uid
+ ": foreground=" + isForeground
- + ", whitelisted=" + isBsWhitelisted
+ + ", whitelisted=" + isWhitelisted
+ ", newRule=" + uidRulesToString(newUidRules)
+ ", oldRule=" + uidRulesToString(oldUidRules));
}
- }
-
- // Final step: dispatch changed rule to existing listeners
- if (changed) {
mHandler.obtainMessage(MSG_RULES_CHANGED, uid, newUidRules).sendToTarget();
}
}
@@ -2982,8 +3040,10 @@
try {
final int uid = mContext.getPackageManager().getPackageUidAsUser(packageName,
PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
+ if (LOGV) Log.v(TAG, "onAppIdleStateChanged(): uid=" + uid + ", idle=" + idle);
synchronized (mRulesLock) {
updateRuleForAppIdleLocked(uid);
+ updateRulesForPowerRestrictionsLocked(uid);
}
} catch (NameNotFoundException nnfe) {
}
@@ -3036,16 +3096,6 @@
}
}
- private void dispatchRestrictPowerChanged(INetworkPolicyListener listener,
- boolean restrictPower) {
- if (listener != null) {
- try {
- listener.onRestrictPowerChanged(restrictPower);
- } catch (RemoteException ignored) {
- }
- }
- }
-
private Handler.Callback mHandlerCallback = new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
@@ -3093,11 +3143,6 @@
}
return true;
}
- case MSG_RESTRICT_POWER_CHANGED: {
- final boolean restrictPower = msg.arg1 != 0;
- dispatchRestrictPowerChanged(mConnectivityListener, restrictPower);
- return true;
- }
case MSG_RESTRICT_BACKGROUND_CHANGED: {
final boolean restrictBackground = msg.arg1 != 0;
dispatchRestrictBackgroundChanged(mConnectivityListener, restrictBackground);
@@ -3410,6 +3455,7 @@
if (LOGV) Slog.v(TAG, "onPackageRemoved: " + packageName + " ->" + uid);
synchronized (mRulesLock) {
removeRestrictBackgroundWhitelistedUidLocked(uid, true, true);
+ updateRestrictionRulesForUidLocked(uid);
}
}
}
diff --git a/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java
index 4cbfd9c..7079b9e 100644
--- a/services/net/java/android/net/apf/ApfFilter.java
+++ b/services/net/java/android/net/apf/ApfFilter.java
@@ -567,18 +567,21 @@
private void generateArpFilterLocked(ApfGenerator gen) throws IllegalInstructionException {
// Here's a basic summary of what the ARP filter program does:
//
- // if it's not an ARP IPv4 request:
- // pass
- // if it's not a request for our IPv4 address:
- // drop
+ // if interface has IPv4 address:
+ // if it's not an ARP IPv4 request:
+ // pass
+ // if it's not a request for our IPv4 address:
+ // drop
// pass
- // if it's not an ARP IPv4 request, pass
- gen.addLoadImmediate(Register.R0, ARP_HEADER_OFFSET);
- gen.addJumpIfBytesNotEqual(Register.R0, ARP_IPV4_REQUEST_HEADER, gen.PASS_LABEL);
- // if it's not a request for our IPv4 address, drop
- gen.addLoadImmediate(Register.R0, ARP_TARGET_IP_ADDRESS_OFFSET);
- gen.addJumpIfBytesNotEqual(Register.R0, mIPv4Address, gen.DROP_LABEL);
+ if (mIPv4Address != null) {
+ // if it's not an ARP IPv4 request, pass
+ gen.addLoadImmediate(Register.R0, ARP_HEADER_OFFSET);
+ gen.addJumpIfBytesNotEqual(Register.R0, ARP_IPV4_REQUEST_HEADER, gen.PASS_LABEL);
+ // if it's not a request for our IPv4 address, drop
+ gen.addLoadImmediate(Register.R0, ARP_TARGET_IP_ADDRESS_OFFSET);
+ gen.addJumpIfBytesNotEqual(Register.R0, mIPv4Address, gen.DROP_LABEL);
+ }
// Otherwise, pass
gen.addJump(gen.PASS_LABEL);
@@ -674,6 +677,7 @@
* <li>Drop IPv4 broadcast packets, except DHCP destined to our MAC,
* <li>Drop IPv4 multicast packets, if mMulticastFilter,
* <li>Pass all other IPv4 packets,
+ * <li>Drop all broadcast non-IP non-ARP packets.
* <li>Pass all non-ICMPv6 IPv6 packets,
* <li>Pass all non-IPv4 and non-IPv6 packets,
* <li>Drop IPv6 ICMPv6 NAs to ff02::1.
@@ -690,24 +694,21 @@
// Here's a basic summary of what the initial program does:
//
// if it's ARP:
- // inesrt ARP filter to drop or pass these appropriately
+ // insert ARP filter to drop or pass these appropriately
// if it's IPv4:
// insert IPv4 filter to drop or pass these appropriately
// if it's not IPv6:
+ // if it's broadcast:
+ // drop
// pass
// insert IPv6 filter to drop, pass, or fall off the end for ICMPv6 packets
+ // Add ARP filters:
+ String skipArpFiltersLabel = "skipArpFilters";
gen.addLoad16(Register.R0, ETH_ETHERTYPE_OFFSET);
-
- if (mIPv4Address != null) {
- // Add ARP filters:
- String skipArpFiltersLabel = "skipArpFilters";
- // If not ARP, skip ARP filters
- // NOTE: Relies on R0 containing ethertype.
- gen.addJumpIfR0NotEquals(ETH_P_ARP, skipArpFiltersLabel);
- generateArpFilterLocked(gen);
- gen.defineLabel(skipArpFiltersLabel);
- }
+ gen.addJumpIfR0NotEquals(ETH_P_ARP, skipArpFiltersLabel);
+ generateArpFilterLocked(gen);
+ gen.defineLabel(skipArpFiltersLabel);
// Add IPv4 filters:
String skipIPv4FiltersLabel = "skipIPv4Filters";
@@ -715,16 +716,23 @@
// execute the ARP filter, since that filter does not fall through, but either drops or
// passes.
gen.addJumpIfR0NotEquals(ETH_P_IP, skipIPv4FiltersLabel);
- // NOTE: Relies on R1 being initialized to 0.
generateIPv4FilterLocked(gen);
gen.defineLabel(skipIPv4FiltersLabel);
- // Add IPv6 filters:
- // If not IPv6, pass
+ // Check for IPv6:
// NOTE: Relies on R0 containing ethertype. This is safe because if we got here, we did not
// execute the ARP or IPv4 filters, since those filters do not fall through, but either
// drop or pass.
- gen.addJumpIfR0NotEquals(ETH_P_IPV6, gen.PASS_LABEL);
+ String ipv6FilterLabel = "IPv6Filters";
+ gen.addJumpIfR0Equals(ETH_P_IPV6, ipv6FilterLabel);
+
+ // Drop non-IP non-ARP broadcasts, pass the rest
+ gen.addLoadImmediate(Register.R0, ETH_DEST_ADDR_OFFSET);
+ gen.addJumpIfBytesNotEqual(Register.R0, ETH_BROADCAST_MAC_ADDRESS, gen.PASS_LABEL);
+ gen.addJump(gen.DROP_LABEL);
+
+ // Add IPv6 filters:
+ gen.defineLabel(ipv6FilterLabel);
generateIPv6FilterLocked(gen);
return gen;
}