Merge "Move back networking policy logic into NetworkPolicyManagerService" into oc-dev

This commit is contained in:
Hugo Benichi
2017-04-04 00:50:20 +00:00
committed by Android (Google) Code Review
2 changed files with 34 additions and 143 deletions

View File

@@ -29,13 +29,6 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; 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.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;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.app.BroadcastOptions; import android.app.BroadcastOptions;
@@ -104,7 +97,6 @@ import android.security.Credentials;
import android.security.KeyStore; import android.security.KeyStore;
import android.telephony.TelephonyManager; import android.telephony.TelephonyManager;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.ArraySet;
import android.util.LocalLog; import android.util.LocalLog;
import android.util.LocalLog.ReadOnlyLocalLog; import android.util.LocalLog.ReadOnlyLocalLog;
import android.util.Log; import android.util.Log;
@@ -130,6 +122,7 @@ import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.MessageUtils; import com.android.internal.util.MessageUtils;
import com.android.internal.util.WakeupMessage; import com.android.internal.util.WakeupMessage;
import com.android.internal.util.XmlUtils; import com.android.internal.util.XmlUtils;
import com.android.server.LocalServices;
import com.android.server.am.BatteryStatsService; import com.android.server.am.BatteryStatsService;
import com.android.server.connectivity.DataConnectionStats; import com.android.server.connectivity.DataConnectionStats;
import com.android.server.connectivity.KeepaliveTracker; import com.android.server.connectivity.KeepaliveTracker;
@@ -147,6 +140,7 @@ import com.android.server.connectivity.Tethering;
import com.android.server.connectivity.Vpn; import com.android.server.connectivity.Vpn;
import com.android.server.net.BaseNetworkObserver; import com.android.server.net.BaseNetworkObserver;
import com.android.server.net.LockdownVpnTracker; import com.android.server.net.LockdownVpnTracker;
import com.android.server.net.NetworkPolicyManagerInternal;
import com.google.android.collect.Lists; import com.google.android.collect.Lists;
@@ -221,18 +215,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
private boolean mLockdownEnabled; private boolean mLockdownEnabled;
private LockdownVpnTracker mLockdownTracker; private LockdownVpnTracker mLockdownTracker;
/** Lock around {@link #mUidRules} and {@link #mMeteredIfaces}. */
private Object mRulesLock = new Object();
/** Currently active network rules by UID. */
@GuardedBy("mRulesLock")
private SparseIntArray mUidRules = new SparseIntArray();
/** Set of ifaces that are costly. */
@GuardedBy("mRulesLock")
private ArraySet<String> mMeteredIfaces = new ArraySet<>();
/** Flag indicating if background data is restricted. */
@GuardedBy("mRulesLock")
private boolean mRestrictBackground;
final private Context mContext; final private Context mContext;
private int mNetworkPreference; private int mNetworkPreference;
// 0 is full bad, 100 is full good // 0 is full bad, 100 is full good
@@ -246,6 +228,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
private INetworkManagementService mNetd; private INetworkManagementService mNetd;
private INetworkStatsService mStatsService; private INetworkStatsService mStatsService;
private INetworkPolicyManager mPolicyManager; private INetworkPolicyManager mPolicyManager;
private NetworkPolicyManagerInternal mPolicyManagerInternal;
private String mCurrentTcpBufferSizes; private String mCurrentTcpBufferSizes;
@@ -715,12 +698,15 @@ public class ConnectivityService extends IConnectivityManager.Stub
mNetd = checkNotNull(netManager, "missing INetworkManagementService"); mNetd = checkNotNull(netManager, "missing INetworkManagementService");
mStatsService = checkNotNull(statsService, "missing INetworkStatsService"); mStatsService = checkNotNull(statsService, "missing INetworkStatsService");
mPolicyManager = checkNotNull(policyManager, "missing INetworkPolicyManager"); mPolicyManager = checkNotNull(policyManager, "missing INetworkPolicyManager");
mPolicyManagerInternal = checkNotNull(
LocalServices.getService(NetworkPolicyManagerInternal.class),
"missing NetworkPolicyManagerInternal");
mKeyStore = KeyStore.getInstance(); mKeyStore = KeyStore.getInstance();
mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
try { try {
mPolicyManager.setConnectivityListener(mPolicyListener); mPolicyManager.registerListener(mPolicyListener);
mRestrictBackground = mPolicyManager.getRestrictBackground();
} 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);
@@ -991,51 +977,22 @@ public class ConnectivityService extends IConnectivityManager.Stub
private boolean isNetworkWithLinkPropertiesBlocked(LinkProperties lp, int uid, private boolean isNetworkWithLinkPropertiesBlocked(LinkProperties lp, int uid,
boolean ignoreBlocked) { boolean ignoreBlocked) {
// Networks aren't blocked when ignoring blocked status // Networks aren't blocked when ignoring blocked status
if (ignoreBlocked) return false; if (ignoreBlocked) {
return false;
}
// Networks are never blocked for system services // Networks are never blocked for system services
if (isSystem(uid)) return false; // TODO: consider moving this check to NetworkPolicyManagerInternal.isUidNetworkingBlocked.
if (isSystem(uid)) {
final boolean networkMetered; return false;
final int uidRules; }
synchronized (mVpns) { synchronized (mVpns) {
final Vpn vpn = mVpns.get(UserHandle.getUserId(uid)); final Vpn vpn = mVpns.get(UserHandle.getUserId(uid));
if (vpn != null && vpn.isBlockingUid(uid)) { if (vpn != null && vpn.isBlockingUid(uid)) {
return true; return true;
} }
} }
final String iface = (lp == null ? "" : lp.getInterfaceName()); final String iface = (lp == null ? "" : lp.getInterfaceName());
synchronized (mRulesLock) { return mPolicyManagerInternal.isUidNetworkingBlocked(uid, iface);
networkMetered = mMeteredIfaces.contains(iface);
uidRules = mUidRules.get(uid, RULE_NONE);
}
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 power restrictions.
if (allowed) {
allowed = (uidRules & RULE_REJECT_ALL) == 0;
if (LOGD_RULES) Log.d(TAG, "allowed status for uid " + uid + " when"
+ " rule is " + uidRulesToString(uidRules) + ": " + allowed);
}
return !allowed;
} }
private void maybeLogBlockedNetworkInfo(NetworkInfo ni, int uid) { private void maybeLogBlockedNetworkInfo(NetworkInfo ni, int uid) {
@@ -1481,67 +1438,24 @@ public class ConnectivityService extends IConnectivityManager.Stub
return true; return true;
} }
private INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() { private final INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
@Override @Override
public void onUidRulesChanged(int uid, int uidRules) { public void onUidRulesChanged(int uid, int uidRules) {
// caller is NPMS, since we only register with them
if (LOGD_RULES) {
log("onUidRulesChanged(uid=" + uid + ", uidRules=" + uidRules + ")");
}
synchronized (mRulesLock) {
// skip update when we've already applied rules
final int oldRules = mUidRules.get(uid, RULE_NONE);
if (oldRules == uidRules) return;
if (uidRules == RULE_NONE) {
mUidRules.delete(uid);
} else {
mUidRules.put(uid, uidRules);
}
}
// TODO: notify UID when it has requested targeted updates // TODO: notify UID when it has requested targeted updates
} }
@Override @Override
public void onMeteredIfacesChanged(String[] meteredIfaces) { public void onMeteredIfacesChanged(String[] meteredIfaces) {
// caller is NPMS, since we only register with them
if (LOGD_RULES) {
log("onMeteredIfacesChanged(ifaces=" + Arrays.toString(meteredIfaces) + ")");
}
synchronized (mRulesLock) {
mMeteredIfaces.clear();
for (String iface : meteredIfaces) {
mMeteredIfaces.add(iface);
}
}
} }
@Override @Override
public void onRestrictBackgroundChanged(boolean restrictBackground) { public void onRestrictBackgroundChanged(boolean restrictBackground) {
// caller is NPMS, since we only register with them // TODO: relocate this specific callback in Tethering.
if (LOGD_RULES) {
log("onRestrictBackgroundChanged(restrictBackground=" + restrictBackground + ")");
}
synchronized (mRulesLock) {
mRestrictBackground = restrictBackground;
}
if (restrictBackground) { if (restrictBackground) {
log("onRestrictBackgroundChanged(true): disabling tethering"); log("onRestrictBackgroundChanged(true): disabling tethering");
mTethering.untetherAll(); mTethering.untetherAll();
} }
} }
@Override @Override
public void onUidPoliciesChanged(int uid, int uidPolicies) { public void onUidPoliciesChanged(int uid, int uidPolicies) {
// caller is NPMS, since we only register with them
if (LOGD_RULES) {
log("onUidRulesChanged(uid=" + uid + ", uidPolicies=" + uidPolicies + ")");
}
} }
}; };
@@ -1976,33 +1890,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
pw.decreaseIndent(); pw.decreaseIndent();
pw.println(); pw.println();
pw.println("Metered Interfaces:");
pw.increaseIndent();
for (String value : mMeteredIfaces) {
pw.println(value);
}
pw.decreaseIndent();
pw.println();
pw.print("Restrict background: ");
pw.println(mRestrictBackground);
pw.println();
pw.println("Status for known UIDs:");
pw.increaseIndent();
final int size = mUidRules.size();
for (int i = 0; i < size; i++) {
final int uid = mUidRules.keyAt(i);
pw.print("UID=");
pw.print(uid);
final int uidRules = mUidRules.get(uid, RULE_NONE);
pw.print(" rules=");
pw.print(uidRulesToString(uidRules));
pw.println();
}
pw.println();
pw.decreaseIndent();
pw.println("Network Requests:"); pw.println("Network Requests:");
pw.increaseIndent(); pw.increaseIndent();
for (NetworkRequestInfo nri : mNetworkRequests.values()) { for (NetworkRequestInfo nri : mNetworkRequests.values()) {
@@ -3437,6 +3324,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
Slog.e(TAG, s); Slog.e(TAG, s);
} }
private static void loge(String s, Throwable t) {
Slog.e(TAG, s, t);
}
private static <T> T checkNotNull(T value, String message) { private static <T> T checkNotNull(T value, String message) {
if (value == null) { if (value == null) {
throw new NullPointerException(message); throw new NullPointerException(message);
@@ -4197,20 +4088,16 @@ public class ConnectivityService extends IConnectivityManager.Stub
private void enforceMeteredApnPolicy(NetworkCapabilities networkCapabilities) { private void enforceMeteredApnPolicy(NetworkCapabilities networkCapabilities) {
final int uid = Binder.getCallingUid(); final int uid = Binder.getCallingUid();
if (isSystem(uid)) { if (isSystem(uid)) {
// Exemption for system uid.
return; return;
} }
// if UID is restricted, don't allow them to bring up metered APNs if (networkCapabilities.hasCapability(NET_CAPABILITY_NOT_METERED)) {
if (networkCapabilities.hasCapability(NET_CAPABILITY_NOT_METERED) == false) { // Policy already enforced.
final int uidRules; return;
synchronized(mRulesLock) { }
uidRules = mUidRules.get(uid, RULE_ALLOW_ALL); if (mPolicyManagerInternal.isUidRestrictedOnMeteredNetworks(uid)) {
} // If UID is restricted, don't allow them to bring up metered APNs.
if (mRestrictBackground && (uidRules & RULE_ALLOW_METERED) == 0 networkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
&& (uidRules & RULE_TEMPORARY_ALLOW_METERED) == 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 option.
networkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
}
} }
} }

View File

@@ -80,6 +80,7 @@ import com.android.server.connectivity.NetworkAgentInfo;
import com.android.server.connectivity.NetworkMonitor; import com.android.server.connectivity.NetworkMonitor;
import com.android.server.connectivity.NetworkMonitor.CaptivePortalProbeResult; import com.android.server.connectivity.NetworkMonitor.CaptivePortalProbeResult;
import com.android.server.net.NetworkPinner; import com.android.server.net.NetworkPinner;
import com.android.server.net.NetworkPolicyManagerInternal;
import java.net.InetAddress; import java.net.InetAddress;
import java.util.ArrayList; import java.util.ArrayList;
@@ -713,6 +714,9 @@ public class ConnectivityServiceTest extends AndroidTestCase {
} }
mServiceContext = new MockContext(getContext()); mServiceContext = new MockContext(getContext());
LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
LocalServices.addService(
NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
mService = new WrappedConnectivityService(mServiceContext, mService = new WrappedConnectivityService(mServiceContext,
mock(INetworkManagementService.class), mock(INetworkManagementService.class),
mock(INetworkStatsService.class), mock(INetworkStatsService.class),