Merge "Extract test utilities for ConnectivityService" am: ecaff61c4b am: 9e23af5f90

am: 6d34ffb4e6

Change-Id: Ib760ef922a440d54bab8c1647d8444ab2a717094
This commit is contained in:
Remi NGUYEN VAN
2019-08-06 15:57:04 -07:00
committed by android-build-merger
8 changed files with 947 additions and 739 deletions

View File

@@ -150,7 +150,6 @@ import android.util.Log;
import android.util.Pair; import android.util.Pair;
import android.util.Slog; import android.util.Slog;
import android.util.SparseArray; import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray; import android.util.SparseIntArray;
import android.util.Xml; import android.util.Xml;
@@ -168,7 +167,6 @@ import com.android.internal.util.AsyncChannel;
import com.android.internal.util.DumpUtils; import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter; 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.XmlUtils; import com.android.internal.util.XmlUtils;
import com.android.server.am.BatteryStatsService; import com.android.server.am.BatteryStatsService;
import com.android.server.connectivity.AutodestructReference; import com.android.server.connectivity.AutodestructReference;
@@ -305,7 +303,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
/** Flag indicating if background data is restricted. */ /** Flag indicating if background data is restricted. */
private boolean mRestrictBackground; private boolean mRestrictBackground;
final private Context mContext; private final Context mContext;
private final Dependencies mDeps;
// 0 is full bad, 100 is full good // 0 is full bad, 100 is full good
private int mDefaultInetConditionPublished = 0; private int mDefaultInetConditionPublished = 0;
@@ -586,11 +585,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
private NetworkNotificationManager mNotifier; private NetworkNotificationManager mNotifier;
private LingerMonitor mLingerMonitor; private LingerMonitor mLingerMonitor;
// sequence number for Networks; keep in sync with system/netd/NetworkController.cpp
private static final int MIN_NET_ID = 100; // some reserved marks
private static final int MAX_NET_ID = 65535 - 0x0400; // Top 1024 bits reserved by IpSecService
private int mNextNetId = MIN_NET_ID;
// sequence number of NetworkRequests // sequence number of NetworkRequests
private int mNextNetworkRequestId = 1; private int mNextNetworkRequestId = 1;
@@ -834,19 +828,113 @@ public class ConnectivityService extends IConnectivityManager.Stub
} }
}; };
/**
* Dependencies of ConnectivityService, for injection in tests.
*/
@VisibleForTesting
public static class Dependencies {
/**
* Get system properties to use in ConnectivityService.
*/
public MockableSystemProperties getSystemProperties() {
return new MockableSystemProperties();
}
/**
* Create a HandlerThread to use in ConnectivityService.
*/
public HandlerThread makeHandlerThread() {
return new HandlerThread("ConnectivityServiceThread");
}
/**
* Get a reference to the NetworkStackClient.
*/
public NetworkStackClient getNetworkStack() {
return NetworkStackClient.getInstance();
}
/**
* @see Tethering
*/
public Tethering makeTethering(@NonNull Context context,
@NonNull INetworkManagementService nms,
@NonNull INetworkStatsService statsService,
@NonNull INetworkPolicyManager policyManager,
@NonNull TetheringDependencies tetheringDeps) {
return new Tethering(context, nms, statsService, policyManager,
IoThread.get().getLooper(), getSystemProperties(), tetheringDeps);
}
/**
* @see ProxyTracker
*/
public ProxyTracker makeProxyTracker(@NonNull Context context,
@NonNull Handler connServiceHandler) {
return new ProxyTracker(context, connServiceHandler, EVENT_PROXY_HAS_CHANGED);
}
/**
* @see NetIdManager
*/
public NetIdManager makeNetIdManager() {
return new NetIdManager();
}
/**
* @see NetworkUtils#queryUserAccess(int, int)
*/
public boolean queryUserAccess(int uid, int netId) {
return NetworkUtils.queryUserAccess(uid, netId);
}
/**
* @see MultinetworkPolicyTracker
*/
public MultinetworkPolicyTracker makeMultinetworkPolicyTracker(
@NonNull Context c, @NonNull Handler h, @NonNull Runnable r) {
return new MultinetworkPolicyTracker(c, h, r);
}
/**
* @see ServiceManager#checkService(String)
*/
public boolean hasService(@NonNull String name) {
return ServiceManager.checkService(name) != null;
}
/**
* @see IpConnectivityMetrics.Logger
*/
public IpConnectivityMetrics.Logger getMetricsLogger() {
return checkNotNull(LocalServices.getService(IpConnectivityMetrics.Logger.class),
"no IpConnectivityMetrics service");
}
/**
* @see IpConnectivityMetrics
*/
public IIpConnectivityMetrics getIpConnectivityMetrics() {
return IIpConnectivityMetrics.Stub.asInterface(
ServiceManager.getService(IpConnectivityLog.SERVICE_NAME));
}
}
public ConnectivityService(Context context, INetworkManagementService netManager, public ConnectivityService(Context context, INetworkManagementService netManager,
INetworkStatsService statsService, INetworkPolicyManager policyManager) { INetworkStatsService statsService, INetworkPolicyManager policyManager) {
this(context, netManager, statsService, policyManager, this(context, netManager, statsService, policyManager, getDnsResolver(),
getDnsResolver(), new IpConnectivityLog(), NetdService.getInstance()); new IpConnectivityLog(), NetdService.getInstance(), new Dependencies());
} }
@VisibleForTesting @VisibleForTesting
protected ConnectivityService(Context context, INetworkManagementService netManager, protected ConnectivityService(Context context, INetworkManagementService netManager,
INetworkStatsService statsService, INetworkPolicyManager policyManager, INetworkStatsService statsService, INetworkPolicyManager policyManager,
IDnsResolver dnsresolver, IpConnectivityLog logger, INetd netd) { IDnsResolver dnsresolver, IpConnectivityLog logger, INetd netd, Dependencies deps) {
if (DBG) log("ConnectivityService starting up"); if (DBG) log("ConnectivityService starting up");
mSystemProperties = getSystemProperties(); mDeps = checkNotNull(deps, "missing Dependencies");
mSystemProperties = mDeps.getSystemProperties();
mNetIdManager = mDeps.makeNetIdManager();
mMetricsLog = logger; mMetricsLog = logger;
mDefaultRequest = createDefaultInternetRequestForTransport(-1, NetworkRequest.Type.REQUEST); mDefaultRequest = createDefaultInternetRequestForTransport(-1, NetworkRequest.Type.REQUEST);
@@ -863,7 +951,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
mDefaultWifiRequest = createDefaultInternetRequestForTransport( mDefaultWifiRequest = createDefaultInternetRequestForTransport(
NetworkCapabilities.TRANSPORT_WIFI, NetworkRequest.Type.BACKGROUND_REQUEST); NetworkCapabilities.TRANSPORT_WIFI, NetworkRequest.Type.BACKGROUND_REQUEST);
mHandlerThread = new HandlerThread("ConnectivityServiceThread"); mHandlerThread = mDeps.makeHandlerThread();
mHandlerThread.start(); mHandlerThread.start();
mHandler = new InternalHandler(mHandlerThread.getLooper()); mHandler = new InternalHandler(mHandlerThread.getLooper());
mTrackerHandler = new NetworkStateTrackerHandler(mHandlerThread.getLooper()); mTrackerHandler = new NetworkStateTrackerHandler(mHandlerThread.getLooper());
@@ -881,7 +969,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
LocalServices.getService(NetworkPolicyManagerInternal.class), LocalServices.getService(NetworkPolicyManagerInternal.class),
"missing NetworkPolicyManagerInternal"); "missing NetworkPolicyManagerInternal");
mDnsResolver = checkNotNull(dnsresolver, "missing IDnsResolver"); mDnsResolver = checkNotNull(dnsresolver, "missing IDnsResolver");
mProxyTracker = makeProxyTracker(); mProxyTracker = mDeps.makeProxyTracker(mContext, mHandler);
mNetd = netd; mNetd = netd;
mKeyStore = KeyStore.getInstance(); mKeyStore = KeyStore.getInstance();
@@ -949,7 +1037,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
// Do the same for Ethernet, since it's often not specified in the configs, although many // Do the same for Ethernet, since it's often not specified in the configs, although many
// devices can use it via USB host adapters. // devices can use it via USB host adapters.
if (mNetConfigs[TYPE_ETHERNET] == null && hasService(Context.ETHERNET_SERVICE)) { if (mNetConfigs[TYPE_ETHERNET] == null && mDeps.hasService(Context.ETHERNET_SERVICE)) {
mLegacyTypeTracker.addSupportedType(TYPE_ETHERNET); mLegacyTypeTracker.addSupportedType(TYPE_ETHERNET);
mNetworksDefined++; mNetworksDefined++;
} }
@@ -969,7 +1057,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
mTethering = makeTethering(); mTethering = deps.makeTethering(mContext, mNMS, mStatsService, mPolicyManager,
makeTetheringDependencies());
mPermissionMonitor = new PermissionMonitor(mContext, mNetd); mPermissionMonitor = new PermissionMonitor(mContext, mNetd);
@@ -1028,7 +1117,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
LingerMonitor.DEFAULT_NOTIFICATION_RATE_LIMIT_MILLIS); LingerMonitor.DEFAULT_NOTIFICATION_RATE_LIMIT_MILLIS);
mLingerMonitor = new LingerMonitor(mContext, mNotifier, dailyLimit, rateLimit); mLingerMonitor = new LingerMonitor(mContext, mNotifier, dailyLimit, rateLimit);
mMultinetworkPolicyTracker = createMultinetworkPolicyTracker( mMultinetworkPolicyTracker = mDeps.makeMultinetworkPolicyTracker(
mContext, mHandler, () -> rematchForAvoidBadWifiUpdate()); mContext, mHandler, () -> rematchForAvoidBadWifiUpdate());
mMultinetworkPolicyTracker.start(); mMultinetworkPolicyTracker.start();
@@ -1038,10 +1127,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
registerPrivateDnsSettingsCallbacks(); registerPrivateDnsSettingsCallbacks();
} }
@VisibleForTesting private TetheringDependencies makeTetheringDependencies() {
protected Tethering makeTethering() { return new TetheringDependencies() {
// TODO: Move other elements into @Overridden getters.
final TetheringDependencies deps = new TetheringDependencies() {
@Override @Override
public boolean isTetheringSupported() { public boolean isTetheringSupported() {
return ConnectivityService.this.isTetheringSupported(); return ConnectivityService.this.isTetheringSupported();
@@ -1051,14 +1138,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
return mDefaultRequest; return mDefaultRequest;
} }
}; };
return new Tethering(mContext, mNMS, mStatsService, mPolicyManager,
IoThread.get().getLooper(), new MockableSystemProperties(),
deps);
}
@VisibleForTesting
protected ProxyTracker makeProxyTracker() {
return new ProxyTracker(mContext, mHandler, EVENT_PROXY_HAS_CHANGED);
} }
private static NetworkCapabilities createDefaultNetworkCapabilitiesForUid(int uid) { private static NetworkCapabilities createDefaultNetworkCapabilitiesForUid(int uid) {
@@ -1150,22 +1229,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
return mNextNetworkRequestId++; return mNextNetworkRequestId++;
} }
@VisibleForTesting
protected int reserveNetId() {
synchronized (mNetworkForNetId) {
for (int i = MIN_NET_ID; i <= MAX_NET_ID; i++) {
int netId = mNextNetId;
if (++mNextNetId > MAX_NET_ID) mNextNetId = MIN_NET_ID;
// Make sure NetID unused. http://b/16815182
if (!mNetIdInUse.get(netId)) {
mNetIdInUse.put(netId, true);
return netId;
}
}
}
throw new IllegalStateException("No free netIds");
}
private NetworkState getFilteredNetworkState(int networkType, int uid) { private NetworkState getFilteredNetworkState(int networkType, int uid) {
if (mLegacyTypeTracker.isTypeSupported(networkType)) { if (mLegacyTypeTracker.isTypeSupported(networkType)) {
final NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType); final NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
@@ -1797,11 +1860,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
} }
}; };
@VisibleForTesting private void registerNetdEventCallback() {
protected void registerNetdEventCallback() { final IIpConnectivityMetrics ipConnectivityMetrics = mDeps.getIpConnectivityMetrics();
final IIpConnectivityMetrics ipConnectivityMetrics =
IIpConnectivityMetrics.Stub.asInterface(
ServiceManager.getService(IpConnectivityLog.SERVICE_NAME));
if (ipConnectivityMetrics == null) { if (ipConnectivityMetrics == null) {
Slog.wtf(TAG, "Missing IIpConnectivityMetrics"); Slog.wtf(TAG, "Missing IIpConnectivityMetrics");
return; return;
@@ -2237,12 +2297,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
protected static final String DEFAULT_TCP_BUFFER_SIZES = "4096,87380,110208,4096,16384,110208"; protected static final String DEFAULT_TCP_BUFFER_SIZES = "4096,87380,110208,4096,16384,110208";
private static final String DEFAULT_TCP_RWND_KEY = "net.tcp.default_init_rwnd"; private static final String DEFAULT_TCP_RWND_KEY = "net.tcp.default_init_rwnd";
// Overridden for testing purposes to avoid writing to SystemProperties.
@VisibleForTesting
protected MockableSystemProperties getSystemProperties() {
return new MockableSystemProperties();
}
private void updateTcpBufferSizes(String tcpBufferSizes) { private void updateTcpBufferSizes(String tcpBufferSizes) {
String[] values = null; String[] values = null;
if (tcpBufferSizes != null) { if (tcpBufferSizes != null) {
@@ -2632,8 +2686,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
} }
if (valid != nai.lastValidated) { if (valid != nai.lastValidated) {
if (wasDefault) { if (wasDefault) {
metricsLogger().defaultNetworkMetrics().logDefaultNetworkValidity( mDeps.getMetricsLogger()
SystemClock.elapsedRealtime(), valid); .defaultNetworkMetrics().logDefaultNetworkValidity(
SystemClock.elapsedRealtime(), valid);
} }
final int oldScore = nai.getCurrentScore(); final int oldScore = nai.getCurrentScore();
nai.lastValidated = valid; nai.lastValidated = valid;
@@ -2968,8 +3023,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
final boolean wasDefault = isDefaultNetwork(nai); final boolean wasDefault = isDefaultNetwork(nai);
synchronized (mNetworkForNetId) { synchronized (mNetworkForNetId) {
mNetworkForNetId.remove(nai.network.netId); mNetworkForNetId.remove(nai.network.netId);
mNetIdInUse.delete(nai.network.netId);
} }
mNetIdManager.releaseNetId(nai.network.netId);
// Just in case. // Just in case.
mLegacyTypeTracker.remove(nai, wasDefault); mLegacyTypeTracker.remove(nai, wasDefault);
} }
@@ -3016,7 +3071,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
// if there is a fallback. Taken together, the two form a X -> 0, 0 -> Y sequence // if there is a fallback. Taken together, the two form a X -> 0, 0 -> Y sequence
// whose timestamps tell how long it takes to recover a default network. // whose timestamps tell how long it takes to recover a default network.
long now = SystemClock.elapsedRealtime(); long now = SystemClock.elapsedRealtime();
metricsLogger().defaultNetworkMetrics().logDefaultNetworkEvent(now, null, nai); mDeps.getMetricsLogger().defaultNetworkMetrics().logDefaultNetworkEvent(now, null, nai);
} }
notifyIfacesChangedForNetworkStats(); notifyIfacesChangedForNetworkStats();
// TODO - we shouldn't send CALLBACK_LOST to requests that can be satisfied // TODO - we shouldn't send CALLBACK_LOST to requests that can be satisfied
@@ -3070,9 +3125,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
destroyNativeNetwork(nai); destroyNativeNetwork(nai);
mDnsManager.removeNetwork(nai.network); mDnsManager.removeNetwork(nai.network);
} }
synchronized (mNetworkForNetId) { mNetIdManager.releaseNetId(nai.network.netId);
mNetIdInUse.delete(nai.network.netId);
}
} }
private boolean createNativeNetwork(@NonNull NetworkAgentInfo networkAgent) { private boolean createNativeNetwork(@NonNull NetworkAgentInfo networkAgent) {
@@ -4156,7 +4209,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
return null; return null;
} }
return getLinkPropertiesProxyInfo(activeNetwork); return getLinkPropertiesProxyInfo(activeNetwork);
} else if (queryUserAccess(Binder.getCallingUid(), network.netId)) { } else if (mDeps.queryUserAccess(Binder.getCallingUid(), network.netId)) {
// Don't call getLinkProperties() as it requires ACCESS_NETWORK_STATE permission, which // Don't call getLinkProperties() as it requires ACCESS_NETWORK_STATE permission, which
// caller may not have. // caller may not have.
return getLinkPropertiesProxyInfo(network); return getLinkPropertiesProxyInfo(network);
@@ -4165,10 +4218,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
return null; return null;
} }
@VisibleForTesting
protected boolean queryUserAccess(int uid, int netId) {
return NetworkUtils.queryUserAccess(uid, netId);
}
private ProxyInfo getLinkPropertiesProxyInfo(Network network) { private ProxyInfo getLinkPropertiesProxyInfo(Network network) {
final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network); final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
@@ -4761,7 +4810,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
final long ident = Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity();
try { try {
// Concatenate the range of types onto the range of NetIDs. // Concatenate the range of types onto the range of NetIDs.
int id = MAX_NET_ID + 1 + (networkType - ConnectivityManager.TYPE_NONE); int id = NetIdManager.MAX_NET_ID + 1 + (networkType - ConnectivityManager.TYPE_NONE);
mNotifier.setProvNotificationVisible(visible, id, action); mNotifier.setProvNotificationVisible(visible, id, action);
} finally { } finally {
Binder.restoreCallingIdentity(ident); Binder.restoreCallingIdentity(ident);
@@ -5372,10 +5421,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
@GuardedBy("mNetworkForNetId") @GuardedBy("mNetworkForNetId")
private final SparseArray<NetworkAgentInfo> mNetworkForNetId = new SparseArray<>(); private final SparseArray<NetworkAgentInfo> mNetworkForNetId = new SparseArray<>();
// NOTE: Accessed on multiple threads, synchronized with mNetworkForNetId. // NOTE: Accessed on multiple threads, synchronized with mNetworkForNetId.
// An entry is first added to mNetIdInUse, prior to mNetworkForNetId, so // An entry is first reserved with NetIdManager, prior to being added to mNetworkForNetId, so
// there may not be a strict 1:1 correlation between the two. // there may not be a strict 1:1 correlation between the two.
@GuardedBy("mNetworkForNetId") private final NetIdManager mNetIdManager;
private final SparseBooleanArray mNetIdInUse = new SparseBooleanArray();
// NetworkAgentInfo keyed off its connecting messenger // NetworkAgentInfo keyed off its connecting messenger
// TODO - eval if we can reduce the number of lists/hashmaps/sparsearrays // TODO - eval if we can reduce the number of lists/hashmaps/sparsearrays
@@ -5477,9 +5525,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
// satisfies mDefaultRequest. // satisfies mDefaultRequest.
final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities); final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(), final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
new Network(reserveNetId()), new NetworkInfo(networkInfo), lp, nc, currentScore, new Network(mNetIdManager.reserveNetId()), new NetworkInfo(networkInfo), lp, nc,
mContext, mTrackerHandler, new NetworkMisc(networkMisc), this, mNetd, mDnsResolver, currentScore, mContext, mTrackerHandler, new NetworkMisc(networkMisc), this, mNetd,
mNMS, factorySerialNumber); mDnsResolver, mNMS, factorySerialNumber);
// Make sure the network capabilities reflect what the agent info says. // Make sure the network capabilities reflect what the agent info says.
nai.setNetworkCapabilities(mixInCapabilities(nai, nc)); nai.setNetworkCapabilities(mixInCapabilities(nai, nc));
final String extraInfo = networkInfo.getExtraInfo(); final String extraInfo = networkInfo.getExtraInfo();
@@ -5488,7 +5536,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (DBG) log("registerNetworkAgent " + nai); if (DBG) log("registerNetworkAgent " + nai);
final long token = Binder.clearCallingIdentity(); final long token = Binder.clearCallingIdentity();
try { try {
getNetworkStack().makeNetworkMonitor( mDeps.getNetworkStack().makeNetworkMonitor(
nai.network, name, new NetworkMonitorCallbacks(nai)); nai.network, name, new NetworkMonitorCallbacks(nai));
} finally { } finally {
Binder.restoreCallingIdentity(token); Binder.restoreCallingIdentity(token);
@@ -5500,11 +5548,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
return nai.network.netId; return nai.network.netId;
} }
@VisibleForTesting
protected NetworkStackClient getNetworkStack() {
return NetworkStackClient.getInstance();
}
private void handleRegisterNetworkAgent(NetworkAgentInfo nai, INetworkMonitor networkMonitor) { private void handleRegisterNetworkAgent(NetworkAgentInfo nai, INetworkMonitor networkMonitor) {
nai.onNetworkMonitorCreated(networkMonitor); nai.onNetworkMonitorCreated(networkMonitor);
if (VDBG) log("Got NetworkAgent Messenger"); if (VDBG) log("Got NetworkAgent Messenger");
@@ -6313,7 +6356,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
// Notify system services that this network is up. // Notify system services that this network is up.
makeDefault(newNetwork); makeDefault(newNetwork);
// Log 0 -> X and Y -> X default network transitions, where X is the new default. // Log 0 -> X and Y -> X default network transitions, where X is the new default.
metricsLogger().defaultNetworkMetrics().logDefaultNetworkEvent( mDeps.getMetricsLogger().defaultNetworkMetrics().logDefaultNetworkEvent(
now, newNetwork, oldDefaultNetwork); now, newNetwork, oldDefaultNetwork);
// Have a new default network, release the transition wakelock in // Have a new default network, release the transition wakelock in
scheduleReleaseNetworkTransitionWakelock(); scheduleReleaseNetworkTransitionWakelock();
@@ -6990,27 +7033,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
return nwm.getWatchlistConfigHash(); return nwm.getWatchlistConfigHash();
} }
@VisibleForTesting
MultinetworkPolicyTracker createMultinetworkPolicyTracker(Context c, Handler h, Runnable r) {
return new MultinetworkPolicyTracker(c, h, r);
}
@VisibleForTesting
public WakeupMessage makeWakeupMessage(Context c, Handler h, String s, int cmd, Object obj) {
return new WakeupMessage(c, h, s, cmd, 0, 0, obj);
}
@VisibleForTesting
public boolean hasService(String name) {
return ServiceManager.checkService(name) != null;
}
@VisibleForTesting
protected IpConnectivityMetrics.Logger metricsLogger() {
return checkNotNull(LocalServices.getService(IpConnectivityMetrics.Logger.class),
"no IpConnectivityMetrics service");
}
private void logNetworkEvent(NetworkAgentInfo nai, int evtype) { private void logNetworkEvent(NetworkAgentInfo nai, int evtype) {
int[] transports = nai.networkCapabilities.getTransportTypes(); int[] transports = nai.networkCapabilities.getTransportTypes();
mMetricsLog.log(nai.network.netId, transports, new NetworkEvent(evtype)); mMetricsLog.log(nai.network.netId, transports, new NetworkEvent(evtype));

View File

@@ -0,0 +1,76 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server;
import android.annotation.NonNull;
import android.util.SparseBooleanArray;
import com.android.internal.annotations.GuardedBy;
/**
* Class used to reserve and release net IDs.
*
* <p>Instances of this class are thread-safe.
*/
public class NetIdManager {
// Sequence number for Networks; keep in sync with system/netd/NetworkController.cpp
public static final int MIN_NET_ID = 100; // some reserved marks
// Top IDs reserved by IpSecService
public static final int MAX_NET_ID = 65535 - IpSecService.TUN_INTF_NETID_RANGE;
@GuardedBy("mNetIdInUse")
private final SparseBooleanArray mNetIdInUse = new SparseBooleanArray();
@GuardedBy("mNetIdInUse")
private int mLastNetId = MIN_NET_ID - 1;
/**
* Get the first netId that follows the provided lastId and is available.
*/
private static int getNextAvailableNetIdLocked(
int lastId, @NonNull SparseBooleanArray netIdInUse) {
int netId = lastId;
for (int i = MIN_NET_ID; i <= MAX_NET_ID; i++) {
netId = netId < MAX_NET_ID ? netId + 1 : MIN_NET_ID;
if (!netIdInUse.get(netId)) {
return netId;
}
}
throw new IllegalStateException("No free netIds");
}
/**
* Reserve a new ID for a network.
*/
public int reserveNetId() {
synchronized (mNetIdInUse) {
mLastNetId = getNextAvailableNetIdLocked(mLastNetId, mNetIdInUse);
// Make sure NetID unused. http://b/16815182
mNetIdInUse.put(mLastNetId, true);
return mLastNetId;
}
}
/**
* Clear a previously reserved ID for a network.
*/
public void releaseNetId(int id) {
synchronized (mNetIdInUse) {
mNetIdInUse.delete(id);
}
}
}

View File

@@ -580,10 +580,12 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
} }
if (newExpiry > 0) { if (newExpiry > 0) {
mLingerMessage = mConnService.makeWakeupMessage( mLingerMessage = new WakeupMessage(
mContext, mHandler, mContext, mHandler,
"NETWORK_LINGER_COMPLETE." + network.netId, "NETWORK_LINGER_COMPLETE." + network.netId /* cmdName */,
EVENT_NETWORK_LINGER_COMPLETE, this); EVENT_NETWORK_LINGER_COMPLETE /* cmd */,
0 /* arg1 (unused) */, 0 /* arg2 (unused) */,
this /* obj (NetworkAgentInfo) */);
mLingerMessage.schedule(newExpiry); mLingerMessage.schedule(newExpiry);
} }

View File

@@ -56,6 +56,7 @@ android_test {
"androidx.test.rules", "androidx.test.rules",
"FrameworksNetCommonTests", "FrameworksNetCommonTests",
"frameworks-base-testutils", "frameworks-base-testutils",
"frameworks-net-integration-testutils",
"framework-protos", "framework-protos",
"mockito-target-minus-junit4", "mockito-target-minus-junit4",
"net-tests-utils", "net-tests-utils",

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.server
import android.net.ConnectivityManager.TYPE_BLUETOOTH
import android.net.ConnectivityManager.TYPE_ETHERNET
import android.net.ConnectivityManager.TYPE_MOBILE
import android.net.ConnectivityManager.TYPE_NONE
import android.net.ConnectivityManager.TYPE_TEST
import android.net.ConnectivityManager.TYPE_VPN
import android.net.ConnectivityManager.TYPE_WIFI
import android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH
import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
import android.net.NetworkCapabilities.TRANSPORT_ETHERNET
import android.net.NetworkCapabilities.TRANSPORT_TEST
import android.net.NetworkCapabilities.TRANSPORT_VPN
import android.net.NetworkCapabilities.TRANSPORT_WIFI
fun transportToLegacyType(transport: Int) = when (transport) {
TRANSPORT_BLUETOOTH -> TYPE_BLUETOOTH
TRANSPORT_CELLULAR -> TYPE_MOBILE
TRANSPORT_ETHERNET -> TYPE_ETHERNET
TRANSPORT_TEST -> TYPE_TEST
TRANSPORT_VPN -> TYPE_VPN
TRANSPORT_WIFI -> TYPE_WIFI
else -> TYPE_NONE
}

View File

@@ -0,0 +1,267 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
import static com.android.server.ConnectivityServiceTestUtilsKt.transportToLegacyType;
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkAgent;
import android.net.NetworkCapabilities;
import android.net.NetworkFactory;
import android.net.NetworkInfo;
import android.net.NetworkMisc;
import android.net.NetworkSpecifier;
import android.net.SocketKeepalive;
import android.net.UidRange;
import android.os.ConditionVariable;
import android.os.HandlerThread;
import android.os.Message;
import android.util.Log;
import com.android.server.connectivity.ConnectivityConstants;
import com.android.testutils.HandlerUtilsKt;
import com.android.testutils.TestableNetworkCallback;
import java.util.Set;
public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork {
private final NetworkInfo mNetworkInfo;
private final NetworkCapabilities mNetworkCapabilities;
private final HandlerThread mHandlerThread;
private final Context mContext;
private final String mLogTag;
private final ConditionVariable mDisconnected = new ConditionVariable();
private final ConditionVariable mPreventReconnectReceived = new ConditionVariable();
private int mScore;
private NetworkAgent mNetworkAgent;
private int mStartKeepaliveError = SocketKeepalive.ERROR_UNSUPPORTED;
private int mStopKeepaliveError = SocketKeepalive.NO_KEEPALIVE;
private Integer mExpectedKeepaliveSlot = null;
public NetworkAgentWrapper(int transport, LinkProperties linkProperties, Context context)
throws Exception {
final int type = transportToLegacyType(transport);
final String typeName = ConnectivityManager.getNetworkTypeName(type);
mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
mNetworkCapabilities = new NetworkCapabilities();
mNetworkCapabilities.addTransportType(transport);
switch (transport) {
case TRANSPORT_ETHERNET:
mScore = 70;
break;
case TRANSPORT_WIFI:
mScore = 60;
break;
case TRANSPORT_CELLULAR:
mScore = 50;
break;
case TRANSPORT_WIFI_AWARE:
mScore = 20;
break;
case TRANSPORT_VPN:
mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_VPN);
mScore = ConnectivityConstants.VPN_DEFAULT_SCORE;
break;
default:
throw new UnsupportedOperationException("unimplemented network type");
}
mContext = context;
mLogTag = "Mock-" + typeName;
mHandlerThread = new HandlerThread(mLogTag);
mHandlerThread.start();
mNetworkAgent = makeNetworkAgent(linkProperties);
}
protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties)
throws Exception {
return new InstrumentedNetworkAgent(this, linkProperties);
}
public static class InstrumentedNetworkAgent extends NetworkAgent {
private final NetworkAgentWrapper mWrapper;
public InstrumentedNetworkAgent(NetworkAgentWrapper wrapper, LinkProperties lp) {
super(wrapper.mHandlerThread.getLooper(), wrapper.mContext, wrapper.mLogTag,
wrapper.mNetworkInfo, wrapper.mNetworkCapabilities, lp, wrapper.mScore,
new NetworkMisc(), NetworkFactory.SerialNumber.NONE);
mWrapper = wrapper;
}
@Override
public void unwanted() {
mWrapper.mDisconnected.open();
}
@Override
public void startSocketKeepalive(Message msg) {
int slot = msg.arg1;
if (mWrapper.mExpectedKeepaliveSlot != null) {
assertEquals((int) mWrapper.mExpectedKeepaliveSlot, slot);
}
onSocketKeepaliveEvent(slot, mWrapper.mStartKeepaliveError);
}
@Override
public void stopSocketKeepalive(Message msg) {
onSocketKeepaliveEvent(msg.arg1, mWrapper.mStopKeepaliveError);
}
@Override
protected void preventAutomaticReconnect() {
mWrapper.mPreventReconnectReceived.open();
}
@Override
protected void addKeepalivePacketFilter(Message msg) {
Log.i(mWrapper.mLogTag, "Add keepalive packet filter.");
}
@Override
protected void removeKeepalivePacketFilter(Message msg) {
Log.i(mWrapper.mLogTag, "Remove keepalive packet filter.");
}
}
public void adjustScore(int change) {
mScore += change;
mNetworkAgent.sendNetworkScore(mScore);
}
public int getScore() {
return mScore;
}
public void explicitlySelected(boolean explicitlySelected, boolean acceptUnvalidated) {
mNetworkAgent.explicitlySelected(explicitlySelected, acceptUnvalidated);
}
public void addCapability(int capability) {
mNetworkCapabilities.addCapability(capability);
mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
}
public void removeCapability(int capability) {
mNetworkCapabilities.removeCapability(capability);
mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
}
public void setUids(Set<UidRange> uids) {
mNetworkCapabilities.setUids(uids);
mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
}
public void setSignalStrength(int signalStrength) {
mNetworkCapabilities.setSignalStrength(signalStrength);
mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
}
public void setNetworkSpecifier(NetworkSpecifier networkSpecifier) {
mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
}
public void setNetworkCapabilities(NetworkCapabilities nc, boolean sendToConnectivityService) {
mNetworkCapabilities.set(nc);
if (sendToConnectivityService) {
mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
}
}
public void connect() {
assertNotEquals("MockNetworkAgents can only be connected once",
getNetworkInfo().getDetailedState(), NetworkInfo.DetailedState.CONNECTED);
mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
mNetworkAgent.sendNetworkInfo(mNetworkInfo);
}
public void suspend() {
mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.SUSPENDED, null, null);
mNetworkAgent.sendNetworkInfo(mNetworkInfo);
}
public void resume() {
mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
mNetworkAgent.sendNetworkInfo(mNetworkInfo);
}
public void disconnect() {
mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null);
mNetworkAgent.sendNetworkInfo(mNetworkInfo);
}
@Override
public Network getNetwork() {
return new Network(mNetworkAgent.netId);
}
public void expectPreventReconnectReceived(long timeoutMs) {
assertTrue(mPreventReconnectReceived.block(timeoutMs));
}
public void expectDisconnected(long timeoutMs) {
assertTrue(mDisconnected.block(timeoutMs));
}
public void sendLinkProperties(LinkProperties lp) {
mNetworkAgent.sendLinkProperties(lp);
}
public void setStartKeepaliveEvent(int reason) {
mStartKeepaliveError = reason;
}
public void setStopKeepaliveEvent(int reason) {
mStopKeepaliveError = reason;
}
public void setExpectedKeepaliveSlot(Integer slot) {
mExpectedKeepaliveSlot = slot;
}
public NetworkAgent getNetworkAgent() {
return mNetworkAgent;
}
public NetworkInfo getNetworkInfo() {
return mNetworkInfo;
}
public NetworkCapabilities getNetworkCapabilities() {
return mNetworkCapabilities;
}
public void waitForIdle(long timeoutMs) {
HandlerUtilsKt.waitForIdle(mHandlerThread, timeoutMs);
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.server
import java.util.concurrent.atomic.AtomicInteger
/**
* A [NetIdManager] that generates ID starting from [NetIdManager.MAX_NET_ID] and decreasing, rather
* than starting from [NetIdManager.MIN_NET_ID] and increasing.
*
* Useful for testing ConnectivityService, to minimize the risk of test ConnectivityService netIDs
* overlapping with netIDs used by the real ConnectivityService on the device.
*
* IDs may still overlap if many networks have been used on the device (so the "real" netIDs
* are close to MAX_NET_ID), but this is typically not the case when running unit tests. Also, there
* is no way to fully solve the overlap issue without altering ID allocation in non-test code, as
* the real ConnectivityService could start using netIds that have been used by the test in the
* past.
*/
class TestNetIdManager : NetIdManager() {
private val nextId = AtomicInteger(MAX_NET_ID)
override fun reserveNetId() = nextId.decrementAndGet()
override fun releaseNetId(id: Int) = Unit
}

File diff suppressed because it is too large Load Diff