Merge "Fixed connectivity state in some restricted network scenarios." into nyc-dev
am: 638a6e8140
* commit '638a6e8140a22a0ddb5d5dacb02173795073bd1a':
Fixed connectivity state in some restricted network scenarios.
Change-Id: I5d3fdbbff6d92be9657d3ed466462ca911d20881
This commit is contained in:
@@ -23,5 +23,6 @@ oneway interface INetworkPolicyListener {
|
||||
void onMeteredIfacesChanged(in String[] meteredIfaces);
|
||||
void onRestrictBackgroundChanged(boolean restrictBackground);
|
||||
void onRestrictBackgroundWhitelistChanged(int uid, boolean whitelisted);
|
||||
void onRestrictPowerChanged(boolean restrictPower);
|
||||
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ interface INetworkPolicyManager {
|
||||
/** 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);
|
||||
|
||||
@@ -90,6 +90,10 @@ public class DataSaverController {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRestrictPowerChanged(boolean restrictPower) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRestrictBackgroundWhitelistChanged(int uid, boolean whitelisted) {
|
||||
}
|
||||
|
||||
@@ -30,8 +30,9 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
|
||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
|
||||
import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
|
||||
import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
|
||||
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;
|
||||
@@ -217,6 +218,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
/** 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;
|
||||
@@ -665,9 +669,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
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.toString());
|
||||
loge("unable to register INetworkPolicyListener" + e);
|
||||
}
|
||||
|
||||
final PowerManager powerManager = (PowerManager) context.getSystemService(
|
||||
@@ -919,21 +924,33 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
uidRules = mUidRules.get(uid, RULE_NONE);
|
||||
}
|
||||
|
||||
switch (uidRules) {
|
||||
case RULE_ALLOW_ALL:
|
||||
case RULE_ALLOW_METERED:
|
||||
case RULE_TEMPORARY_ALLOW_METERED:
|
||||
return false;
|
||||
case RULE_REJECT_METERED:
|
||||
return networkMetered;
|
||||
case RULE_REJECT_ALL:
|
||||
return true;
|
||||
case RULE_NONE:
|
||||
default:
|
||||
// When background data is restricted device-wide, the default
|
||||
// behavior for apps should be like RULE_REJECT_METERED
|
||||
return mRestrictBackground ? networkMetered : false;
|
||||
boolean allowed = true;
|
||||
// Check Data Saver Mode first...
|
||||
if (networkMetered) {
|
||||
if ((uidRules & RULE_REJECT_METERED) != 0) {
|
||||
if (LOGD_RULES) Log.d(TAG, "uid " + uid + " is blacklisted");
|
||||
// Explicitly blacklisted.
|
||||
allowed = false;
|
||||
} else {
|
||||
allowed = !mRestrictBackground
|
||||
|| (uidRules & RULE_ALLOW_METERED) != 0
|
||||
|| (uidRules & RULE_TEMPORARY_ALLOW_METERED) != 0;
|
||||
if (LOGD_RULES) Log.d(TAG, "allowed status for uid " + uid + " when"
|
||||
+ " mRestrictBackground=" + mRestrictBackground
|
||||
+ ", whitelisted=" + ((uidRules & RULE_ALLOW_METERED) != 0)
|
||||
+ ", tempWhitelist= + ((uidRules & RULE_TEMPORARY_ALLOW_METERED) != 0)"
|
||||
+ ": " + allowed);
|
||||
}
|
||||
}
|
||||
// ...then Battery Saver Mode.
|
||||
if (allowed && mRestrictPower) {
|
||||
allowed = (uidRules & RULE_ALLOW_ALL) != 0;
|
||||
if (LOGD_RULES) Log.d(TAG, "allowed status for uid " + uid + " when"
|
||||
+ " mRestrictPower=" + mRestrictPower
|
||||
+ ", whitelisted=" + ((uidRules & RULE_ALLOW_ALL) != 0)
|
||||
+ ": " + allowed);
|
||||
}
|
||||
return !allowed;
|
||||
}
|
||||
|
||||
private void maybeLogBlockedNetworkInfo(NetworkInfo ni, int uid) {
|
||||
@@ -1380,7 +1397,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
|
||||
synchronized (mRulesLock) {
|
||||
// skip update when we've already applied rules
|
||||
final int oldRules = mUidRules.get(uid, RULE_ALLOW_ALL);
|
||||
final int oldRules = mUidRules.get(uid, RULE_NONE);
|
||||
if (oldRules == uidRules) return;
|
||||
|
||||
mUidRules.put(uid, uidRules);
|
||||
@@ -1421,6 +1438,18 @@ 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
|
||||
public void onRestrictBackgroundWhitelistChanged(int uid, boolean whitelisted) {
|
||||
if (LOGD_RULES) {
|
||||
@@ -1862,6 +1891,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
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();
|
||||
@@ -3998,9 +4031,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
synchronized(mRulesLock) {
|
||||
uidRules = mUidRules.get(uid, RULE_ALLOW_ALL);
|
||||
}
|
||||
if (uidRules != RULE_ALLOW_ALL) {
|
||||
if ((uidRules & RULE_ALLOW_ALL) == 0) {
|
||||
// we could silently fail or we can filter the available nets to only give
|
||||
// them those they have access to. Chose the more useful
|
||||
// them those they have access to. Chose the more useful option.
|
||||
networkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,6 +169,11 @@ public class ConnectivityController extends StateController implements
|
||||
updateTrackedJobs(-1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRestrictPowerChanged(boolean restrictPower) {
|
||||
updateTrackedJobs(-1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRestrictBackgroundChanged(boolean restrictBackground) {
|
||||
updateTrackedJobs(-1);
|
||||
|
||||
@@ -48,10 +48,12 @@ import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
|
||||
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DENY;
|
||||
import static android.net.NetworkPolicyManager.POLICY_NONE;
|
||||
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
|
||||
import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
|
||||
import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
|
||||
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.computeLastCycleBoundary;
|
||||
@@ -264,6 +266,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
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;
|
||||
@@ -554,9 +557,19 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
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;
|
||||
|
||||
// read policy from disk
|
||||
@@ -2132,6 +2145,15 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
@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);
|
||||
@@ -2795,6 +2817,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
* have permission to use the internet.
|
||||
*
|
||||
* <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);
|
||||
@@ -2817,30 +2843,47 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
// Data Saver status.
|
||||
final boolean isDsBlacklisted = (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0;
|
||||
final boolean isDsWhitelisted = mRestrictBackgroundWhitelistUids.get(uid);
|
||||
int newDsRule = RULE_NONE;
|
||||
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;
|
||||
|
||||
// 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 (isDsBlacklisted) {
|
||||
newDsRule = RULE_REJECT_METERED;
|
||||
} else if (isDsWhitelisted) {
|
||||
newDsRule = RULE_ALLOW_METERED;
|
||||
}
|
||||
// Battery Saver rules
|
||||
if (mRestrictPower) {
|
||||
newBsRule = RULE_ALLOW_ALL;
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
|
||||
final int newUidRules = newDsRule;
|
||||
final int newUidRules = newDsRule | newBsRule;
|
||||
|
||||
if (LOGV) {
|
||||
Log.v(TAG, "updateRuleForRestrictBackgroundLocked(" + uid + "):"
|
||||
+ " isForeground=" +isForeground + ", isBlacklisted: " + isDsBlacklisted
|
||||
+ ", isDsWhitelisted: " + isDsWhitelisted
|
||||
+ ", newUidRule: " + uidRulesToString(newUidRules)
|
||||
+ ", oldUidRule: " + uidRulesToString(oldUidRules));
|
||||
+ ", isBsWhitelisted: " + isBsWhitelisted
|
||||
+ ", newUidRules: " + uidRulesToString(newUidRules)
|
||||
+ ", oldUidRules: " + uidRulesToString(oldUidRules));
|
||||
}
|
||||
|
||||
if (newUidRules == RULE_NONE) {
|
||||
@@ -2849,8 +2892,14 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
mUidRules.put(uid, newUidRules);
|
||||
}
|
||||
|
||||
boolean changed = false;
|
||||
|
||||
// Second step: apply bw changes based on change of state.
|
||||
|
||||
// Apply Data Saver rules.
|
||||
if (newDsRule != oldDsRule) {
|
||||
changed = true;
|
||||
|
||||
if ((newDsRule & RULE_TEMPORARY_ALLOW_METERED) != 0) {
|
||||
// Temporarily whitelist foreground app, removing from blacklist if necessary
|
||||
// (since bw_penalty_box prevails over bw_happy_box).
|
||||
@@ -2895,11 +2944,32 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
+ ": foreground=" + isForeground
|
||||
+ ", whitelisted=" + isDsWhitelisted
|
||||
+ ", blacklisted=" + isDsBlacklisted
|
||||
+ ", newRules=" + uidRulesToString(newUidRules)
|
||||
+ ", oldRules=" + uidRulesToString(oldUidRules));
|
||||
+ ", newRule=" + uidRulesToString(newUidRules)
|
||||
+ ", oldRule=" + uidRulesToString(oldUidRules));
|
||||
}
|
||||
}
|
||||
|
||||
// dispatch changed rule to existing listeners
|
||||
// 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) {
|
||||
if (LOGV) Log.v(TAG, "Allowing non-metered access for UID " + uid);
|
||||
} else if ((newBsRule & 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
|
||||
+ ", newRule=" + uidRulesToString(newUidRules)
|
||||
+ ", oldRule=" + uidRulesToString(oldUidRules));
|
||||
}
|
||||
}
|
||||
|
||||
// Final step: dispatch changed rule to existing listeners
|
||||
if (changed) {
|
||||
mHandler.obtainMessage(MSG_RULES_CHANGED, uid, newUidRules).sendToTarget();
|
||||
}
|
||||
}
|
||||
@@ -2966,6 +3036,16 @@ 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() {
|
||||
@Override
|
||||
public boolean handleMessage(Message msg) {
|
||||
@@ -3013,6 +3093,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
}
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user