Merge "Tell the factory it is already serving a request."

This commit is contained in:
Chalard Jean
2019-03-13 02:07:29 +00:00
committed by Gerrit Code Review
7 changed files with 189 additions and 77 deletions

View File

@@ -3158,11 +3158,11 @@ public class ConnectivityManager {
} }
} }
/** {@hide} */ /** {@hide} - returns the factory serial number */
@UnsupportedAppUsage @UnsupportedAppUsage
public void registerNetworkFactory(Messenger messenger, String name) { public int registerNetworkFactory(Messenger messenger, String name) {
try { try {
mService.registerNetworkFactory(messenger, name); return mService.registerNetworkFactory(messenger, name);
} catch (RemoteException e) { } catch (RemoteException e) {
throw e.rethrowFromSystemServer(); throw e.rethrowFromSystemServer();
} }
@@ -3178,6 +3178,10 @@ public class ConnectivityManager {
} }
} }
// TODO : remove this method. It is a stopgap measure to help sheperding a number
// of dependent changes that would conflict throughout the automerger graph. Having this
// temporarily helps with the process of going through with all these dependent changes across
// the entire tree.
/** /**
* @hide * @hide
* Register a NetworkAgent with ConnectivityService. * Register a NetworkAgent with ConnectivityService.
@@ -3185,8 +3189,20 @@ public class ConnectivityManager {
*/ */
public int registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp, public int registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp,
NetworkCapabilities nc, int score, NetworkMisc misc) { NetworkCapabilities nc, int score, NetworkMisc misc) {
return registerNetworkAgent(messenger, ni, lp, nc, score, misc,
NetworkFactory.SerialNumber.NONE);
}
/**
* @hide
* Register a NetworkAgent with ConnectivityService.
* @return NetID corresponding to NetworkAgent.
*/
public int registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp,
NetworkCapabilities nc, int score, NetworkMisc misc, int factorySerialNumber) {
try { try {
return mService.registerNetworkAgent(messenger, ni, lp, nc, score, misc); return mService.registerNetworkAgent(messenger, ni, lp, nc, score, misc,
factorySerialNumber);
} catch (RemoteException e) { } catch (RemoteException e) {
throw e.rethrowFromSystemServer(); throw e.rethrowFromSystemServer();
} }

View File

@@ -150,14 +150,14 @@ interface IConnectivityManager
void setAirplaneMode(boolean enable); void setAirplaneMode(boolean enable);
void registerNetworkFactory(in Messenger messenger, in String name); int registerNetworkFactory(in Messenger messenger, in String name);
boolean requestBandwidthUpdate(in Network network); boolean requestBandwidthUpdate(in Network network);
void unregisterNetworkFactory(in Messenger messenger); void unregisterNetworkFactory(in Messenger messenger);
int registerNetworkAgent(in Messenger messenger, in NetworkInfo ni, in LinkProperties lp, int registerNetworkAgent(in Messenger messenger, in NetworkInfo ni, in LinkProperties lp,
in NetworkCapabilities nc, int score, in NetworkMisc misc); in NetworkCapabilities nc, int score, in NetworkMisc misc, in int factorySerialNumber);
NetworkRequest requestNetwork(in NetworkCapabilities networkCapabilities, NetworkRequest requestNetwork(in NetworkCapabilities networkCapabilities,
in Messenger messenger, int timeoutSec, in IBinder binder, int legacy); in Messenger messenger, int timeoutSec, in IBinder binder, int legacy);

View File

@@ -57,6 +57,7 @@ public abstract class NetworkAgent extends Handler {
private static final long BW_REFRESH_MIN_WIN_MS = 500; private static final long BW_REFRESH_MIN_WIN_MS = 500;
private boolean mPollLceScheduled = false; private boolean mPollLceScheduled = false;
private AtomicBoolean mPollLcePending = new AtomicBoolean(false); private AtomicBoolean mPollLcePending = new AtomicBoolean(false);
public final int mFactorySerialNumber;
private static final int BASE = Protocol.BASE_NETWORK_AGENT; private static final int BASE = Protocol.BASE_NETWORK_AGENT;
@@ -212,16 +213,31 @@ public abstract class NetworkAgent extends Handler {
*/ */
public static final int CMD_PREVENT_AUTOMATIC_RECONNECT = BASE + 15; public static final int CMD_PREVENT_AUTOMATIC_RECONNECT = BASE + 15;
// TODO : remove these two constructors. They are a stopgap measure to help sheperding a number
// of dependent changes that would conflict throughout the automerger graph. Having these
// temporarily helps with the process of going through with all these dependent changes across
// the entire tree.
public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
NetworkCapabilities nc, LinkProperties lp, int score) { NetworkCapabilities nc, LinkProperties lp, int score) {
this(looper, context, logTag, ni, nc, lp, score, null); this(looper, context, logTag, ni, nc, lp, score, null, NetworkFactory.SerialNumber.NONE);
}
public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) {
this(looper, context, logTag, ni, nc, lp, score, misc, NetworkFactory.SerialNumber.NONE);
} }
public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) { NetworkCapabilities nc, LinkProperties lp, int score, int factorySerialNumber) {
this(looper, context, logTag, ni, nc, lp, score, null, factorySerialNumber);
}
public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc,
int factorySerialNumber) {
super(looper); super(looper);
LOG_TAG = logTag; LOG_TAG = logTag;
mContext = context; mContext = context;
mFactorySerialNumber = factorySerialNumber;
if (ni == null || nc == null || lp == null) { if (ni == null || nc == null || lp == null) {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
@@ -230,7 +246,8 @@ public abstract class NetworkAgent extends Handler {
ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService( ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(
Context.CONNECTIVITY_SERVICE); Context.CONNECTIVITY_SERVICE);
netId = cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni), netId = cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni),
new LinkProperties(lp), new NetworkCapabilities(nc), score, misc); new LinkProperties(lp), new NetworkCapabilities(nc), score, misc,
factorySerialNumber);
} }
@Override @Override

View File

@@ -84,6 +84,7 @@ import android.net.Network;
import android.net.NetworkAgent; import android.net.NetworkAgent;
import android.net.NetworkCapabilities; import android.net.NetworkCapabilities;
import android.net.NetworkConfig; import android.net.NetworkConfig;
import android.net.NetworkFactory;
import android.net.NetworkInfo; import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState; import android.net.NetworkInfo.DetailedState;
import android.net.NetworkMisc; import android.net.NetworkMisc;
@@ -2892,8 +2893,17 @@ public class ConnectivityService extends IConnectivityManager.Stub
for (NetworkRequestInfo nri : mNetworkRequests.values()) { for (NetworkRequestInfo nri : mNetworkRequests.values()) {
if (nri.request.isListen()) continue; if (nri.request.isListen()) continue;
NetworkAgentInfo nai = getNetworkForRequest(nri.request.requestId); NetworkAgentInfo nai = getNetworkForRequest(nri.request.requestId);
ac.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, final int score;
(nai != null ? nai.getCurrentScore() : 0), 0, nri.request); final int serial;
if (nai != null) {
score = nai.getCurrentScore();
serial = nai.factorySerialNumber;
} else {
score = 0;
serial = NetworkFactory.SerialNumber.NONE;
}
ac.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score, serial,
nri.request);
} }
} else { } else {
loge("Error connecting NetworkFactory"); loge("Error connecting NetworkFactory");
@@ -2991,7 +3001,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
NetworkAgentInfo currentNetwork = getNetworkForRequest(request.requestId); NetworkAgentInfo currentNetwork = getNetworkForRequest(request.requestId);
if (currentNetwork != null && currentNetwork.network.netId == nai.network.netId) { if (currentNetwork != null && currentNetwork.network.netId == nai.network.netId) {
clearNetworkForRequest(request.requestId); clearNetworkForRequest(request.requestId);
sendUpdatedScoreToFactories(request, 0); sendUpdatedScoreToFactories(request, null);
} }
} }
nai.clearLingerState(); nai.clearLingerState();
@@ -3068,7 +3078,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
} }
rematchAllNetworksAndRequests(null, 0); rematchAllNetworksAndRequests(null, 0);
if (nri.request.isRequest() && getNetworkForRequest(nri.request.requestId) == null) { if (nri.request.isRequest() && getNetworkForRequest(nri.request.requestId) == null) {
sendUpdatedScoreToFactories(nri.request, 0); sendUpdatedScoreToFactories(nri.request, null);
} }
} }
@@ -4843,11 +4853,14 @@ public class ConnectivityService extends IConnectivityManager.Stub
public final String name; public final String name;
public final Messenger messenger; public final Messenger messenger;
public final AsyncChannel asyncChannel; public final AsyncChannel asyncChannel;
public final int factorySerialNumber;
public NetworkFactoryInfo(String name, Messenger messenger, AsyncChannel asyncChannel) { NetworkFactoryInfo(String name, Messenger messenger, AsyncChannel asyncChannel,
int factorySerialNumber) {
this.name = name; this.name = name;
this.messenger = messenger; this.messenger = messenger;
this.asyncChannel = asyncChannel; this.asyncChannel = asyncChannel;
this.factorySerialNumber = factorySerialNumber;
} }
} }
@@ -5208,10 +5221,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
} }
@Override @Override
public void registerNetworkFactory(Messenger messenger, String name) { public int registerNetworkFactory(Messenger messenger, String name) {
enforceConnectivityInternalPermission(); enforceConnectivityInternalPermission();
NetworkFactoryInfo nfi = new NetworkFactoryInfo(name, messenger, new AsyncChannel()); NetworkFactoryInfo nfi = new NetworkFactoryInfo(name, messenger, new AsyncChannel(),
NetworkFactory.SerialNumber.nextSerialNumber());
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, nfi)); mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, nfi));
return nfi.factorySerialNumber;
} }
private void handleRegisterNetworkFactory(NetworkFactoryInfo nfi) { private void handleRegisterNetworkFactory(NetworkFactoryInfo nfi) {
@@ -5316,9 +5331,35 @@ public class ConnectivityService extends IConnectivityManager.Stub
return nri.request.requestId == mDefaultRequest.requestId; return nri.request.requestId == mDefaultRequest.requestId;
} }
// TODO : remove this method. It's a stopgap measure to help sheperding a number of dependent
// changes that would conflict throughout the automerger graph. Having this method temporarily
// helps with the process of going through with all these dependent changes across the entire
// tree.
public int registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo, public int registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
LinkProperties linkProperties, NetworkCapabilities networkCapabilities, LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
int currentScore, NetworkMisc networkMisc) { int currentScore, NetworkMisc networkMisc) {
return registerNetworkAgent(messenger, networkInfo, linkProperties, networkCapabilities,
currentScore, networkMisc, NetworkFactory.SerialNumber.NONE);
}
/**
* Register a new agent with ConnectivityService to handle a network.
*
* @param messenger a messenger for ConnectivityService to contact the agent asynchronously.
* @param networkInfo the initial info associated with this network. It can be updated later :
* see {@link #updateNetworkInfo}.
* @param linkProperties the initial link properties of this network. They can be updated
* later : see {@link #updateLinkProperties}.
* @param networkCapabilities the initial capabilites of this network. They can be updated
* later : see {@link #updateNetworkCapabilities}.
* @param currentScore the initial score of the network. See
* {@link NetworkAgentInfo#getCurrentScore}.
* @param networkMisc metadata about the network. This is never updated.
* @param factorySerialNumber the serial number of the factory owning this NetworkAgent.
*/
public int registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
int currentScore, NetworkMisc networkMisc, int factorySerialNumber) {
enforceConnectivityInternalPermission(); enforceConnectivityInternalPermission();
LinkProperties lp = new LinkProperties(linkProperties); LinkProperties lp = new LinkProperties(linkProperties);
@@ -5328,7 +5369,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
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(reserveNetId()), new NetworkInfo(networkInfo), lp, nc, currentScore,
mContext, mTrackerHandler, new NetworkMisc(networkMisc), this, mNetd, mNMS); mContext, mTrackerHandler, new NetworkMisc(networkMisc), this, mNetd, 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.networkCapabilities = mixInCapabilities(nai, nc); nai.networkCapabilities = mixInCapabilities(nai, nc);
final String extraInfo = networkInfo.getExtraInfo(); final String extraInfo = networkInfo.getExtraInfo();
@@ -5755,17 +5797,23 @@ public class ConnectivityService extends IConnectivityManager.Stub
NetworkRequest nr = nai.requestAt(i); NetworkRequest nr = nai.requestAt(i);
// Don't send listening requests to factories. b/17393458 // Don't send listening requests to factories. b/17393458
if (nr.isListen()) continue; if (nr.isListen()) continue;
sendUpdatedScoreToFactories(nr, nai.getCurrentScore()); sendUpdatedScoreToFactories(nr, nai);
} }
} }
private void sendUpdatedScoreToFactories(NetworkRequest networkRequest, int score) { private void sendUpdatedScoreToFactories(NetworkRequest networkRequest, NetworkAgentInfo nai) {
int score = 0;
int serial = 0;
if (nai != null) {
score = nai.getCurrentScore();
serial = nai.factorySerialNumber;
}
if (VDBG || DDBG){ if (VDBG || DDBG){
log("sending new Min Network Score(" + score + "): " + networkRequest.toString()); log("sending new Min Network Score(" + score + "): " + networkRequest.toString());
} }
for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) { for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score, 0, nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score,
networkRequest); serial, networkRequest);
} }
} }
@@ -6043,7 +6091,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
// TODO - this could get expensive if we have a lot of requests for this // TODO - this could get expensive if we have a lot of requests for this
// network. Think about if there is a way to reduce this. Push // network. Think about if there is a way to reduce this. Push
// netid->request mapping to each factory? // netid->request mapping to each factory?
sendUpdatedScoreToFactories(nri.request, score); sendUpdatedScoreToFactories(nri.request, newNetwork);
if (isDefaultRequest(nri)) { if (isDefaultRequest(nri)) {
isNewDefault = true; isNewDefault = true;
oldDefaultNetwork = currentNetwork; oldDefaultNetwork = currentNetwork;
@@ -6067,7 +6115,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
newNetwork.removeRequest(nri.request.requestId); newNetwork.removeRequest(nri.request.requestId);
if (currentNetwork == newNetwork) { if (currentNetwork == newNetwork) {
clearNetworkForRequest(nri.request.requestId); clearNetworkForRequest(nri.request.requestId);
sendUpdatedScoreToFactories(nri.request, 0); sendUpdatedScoreToFactories(nri.request, null);
} else { } else {
Slog.wtf(TAG, "BUG: Removing request " + nri.request.requestId + " from " + Slog.wtf(TAG, "BUG: Removing request " + nri.request.requestId + " from " +
newNetwork.name() + newNetwork.name() +

View File

@@ -238,6 +238,8 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
public final Messenger messenger; public final Messenger messenger;
public final AsyncChannel asyncChannel; public final AsyncChannel asyncChannel;
public final int factorySerialNumber;
// Used by ConnectivityService to keep track of 464xlat. // Used by ConnectivityService to keep track of 464xlat.
public final Nat464Xlat clatd; public final Nat464Xlat clatd;
@@ -253,7 +255,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, Network net, NetworkInfo info, public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, Network net, NetworkInfo info,
LinkProperties lp, NetworkCapabilities nc, int score, Context context, Handler handler, LinkProperties lp, NetworkCapabilities nc, int score, Context context, Handler handler,
NetworkMisc misc, ConnectivityService connService, INetd netd, NetworkMisc misc, ConnectivityService connService, INetd netd,
INetworkManagementService nms) { INetworkManagementService nms, int factorySerialNumber) {
this.messenger = messenger; this.messenger = messenger;
asyncChannel = ac; asyncChannel = ac;
network = net; network = net;
@@ -266,6 +268,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
mContext = context; mContext = context;
mHandler = handler; mHandler = handler;
networkMisc = misc; networkMisc = misc;
this.factorySerialNumber = factorySerialNumber;
} }
/** /**

View File

@@ -511,7 +511,7 @@ public class ConnectivityServiceTest {
mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext, mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
"Mock-" + typeName, mNetworkInfo, mNetworkCapabilities, "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
linkProperties, mScore, new NetworkMisc()) { linkProperties, mScore, new NetworkMisc(), NetworkFactory.SerialNumber.NONE) {
@Override @Override
public void unwanted() { mDisconnected.open(); } public void unwanted() { mDisconnected.open(); }
@@ -746,7 +746,7 @@ public class ConnectivityServiceTest {
/** /**
* A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
* operations have been processed. Before ConnectivityService can add or remove any requests, * operations have been processed. Before ConnectivityService can add or remove any requests,
* the factory must be told to expect those operations by calling expectAddRequests or * the factory must be told to expect those operations by calling expectAddRequestsWithScores or
* expectRemoveRequests. * expectRemoveRequests.
*/ */
private static class MockNetworkFactory extends NetworkFactory { private static class MockNetworkFactory extends NetworkFactory {
@@ -755,14 +755,16 @@ public class ConnectivityServiceTest {
private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false); private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
// Used to expect that requests be removed or added on a separate thread, without sleeping. // Used to expect that requests be removed or added on a separate thread, without sleeping.
// Callers can call either expectAddRequests() or expectRemoveRequests() exactly once, then // Callers can call either expectAddRequestsWithScores() or expectRemoveRequests() exactly
// cause some other thread to add or remove requests, then call waitForRequests(). We can // once, then cause some other thread to add or remove requests, then call
// either expect requests to be added or removed, but not both, because CountDownLatch can // waitForRequests().
// only count in one direction. // It is not possible to wait for both add and remove requests. When adding, the queue
private CountDownLatch mExpectations; // contains the expected score. When removing, the value is unused, all matters is the
// number of objects in the queue.
private final LinkedBlockingQueue<Integer> mExpectations;
// Whether we are currently expecting requests to be added or removed. Valid only if // Whether we are currently expecting requests to be added or removed. Valid only if
// mExpectations is non-null. // mExpectations is non-empty.
private boolean mExpectingAdditions; private boolean mExpectingAdditions;
// Used to collect the networks requests managed by this factory. This is a duplicate of // Used to collect the networks requests managed by this factory. This is a duplicate of
@@ -772,6 +774,7 @@ public class ConnectivityServiceTest {
public MockNetworkFactory(Looper looper, Context context, String logTag, public MockNetworkFactory(Looper looper, Context context, String logTag,
NetworkCapabilities filter) { NetworkCapabilities filter) {
super(looper, context, logTag, filter); super(looper, context, logTag, filter);
mExpectations = new LinkedBlockingQueue<>();
} }
public int getMyRequestCount() { public int getMyRequestCount() {
@@ -803,38 +806,44 @@ public class ConnectivityServiceTest {
} }
@Override @Override
protected void handleAddRequest(NetworkRequest request, int score) { protected void handleAddRequest(NetworkRequest request, int score,
int factorySerialNumber) {
synchronized (mExpectations) {
final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
assertNotNull("Added more requests than expected (" + request + " score : "
+ score + ")", expectedScore);
// If we're expecting anything, we must be expecting additions. // If we're expecting anything, we must be expecting additions.
if (mExpectations != null && !mExpectingAdditions) { if (!mExpectingAdditions) {
fail("Can't add requests while expecting requests to be removed"); fail("Can't add requests while expecting requests to be removed");
} }
if (expectedScore != score) {
fail("Expected score was " + expectedScore + " but actual was " + score
+ " in added request");
}
// Add the request. // Add the request.
mNetworkRequests.put(request.requestId, request); mNetworkRequests.put(request.requestId, request);
super.handleAddRequest(request, score); super.handleAddRequest(request, score, factorySerialNumber);
mExpectations.notify();
// Reduce the number of request additions we're waiting for.
if (mExpectingAdditions) {
assertTrue("Added more requests than expected", mExpectations.getCount() > 0);
mExpectations.countDown();
} }
} }
@Override @Override
protected void handleRemoveRequest(NetworkRequest request) { protected void handleRemoveRequest(NetworkRequest request) {
synchronized (mExpectations) {
final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
assertTrue("Removed more requests than expected", expectedScore != null);
// If we're expecting anything, we must be expecting removals. // If we're expecting anything, we must be expecting removals.
if (mExpectations != null && mExpectingAdditions) { if (mExpectingAdditions) {
fail("Can't remove requests while expecting requests to be added"); fail("Can't remove requests while expecting requests to be added");
} }
// Remove the request. // Remove the request.
mNetworkRequests.remove(request.requestId); mNetworkRequests.remove(request.requestId);
super.handleRemoveRequest(request); super.handleRemoveRequest(request);
mExpectations.notify();
// Reduce the number of request removals we're waiting for.
if (!mExpectingAdditions) {
assertTrue("Removed more requests than expected", mExpectations.getCount() > 0);
mExpectations.countDown();
} }
} }
@@ -844,35 +853,42 @@ public class ConnectivityServiceTest {
} }
private void assertNoExpectations() { private void assertNoExpectations() {
if (mExpectations != null) { if (mExpectations.size() != 0) {
fail("Can't add expectation, " + mExpectations.getCount() + " already pending"); fail("Can't add expectation, " + mExpectations.size() + " already pending");
} }
} }
// Expects that count requests will be added. // Expects that requests with the specified scores will be added.
public void expectAddRequests(final int count) { public void expectAddRequestsWithScores(final int... scores) {
assertNoExpectations(); assertNoExpectations();
mExpectingAdditions = true; mExpectingAdditions = true;
mExpectations = new CountDownLatch(count); for (int score : scores) {
mExpectations.add(score);
}
} }
// Expects that count requests will be removed. // Expects that count requests will be removed.
public void expectRemoveRequests(final int count) { public void expectRemoveRequests(final int count) {
assertNoExpectations(); assertNoExpectations();
mExpectingAdditions = false; mExpectingAdditions = false;
mExpectations = new CountDownLatch(count); for (int i = 0; i < count; ++i) {
mExpectations.add(0); // For removals the score is ignored so any value will do.
}
} }
// Waits for the expected request additions or removals to happen within a timeout. // Waits for the expected request additions or removals to happen within a timeout.
public void waitForRequests() throws InterruptedException { public void waitForRequests() throws InterruptedException {
assertNotNull("Nothing to wait for", mExpectations); final long deadline = SystemClock.elapsedRealtime() + TIMEOUT_MS;
mExpectations.await(TIMEOUT_MS, TimeUnit.MILLISECONDS); synchronized (mExpectations) {
final long count = mExpectations.getCount(); while (mExpectations.size() > 0 && SystemClock.elapsedRealtime() < deadline) {
mExpectations.wait(deadline - SystemClock.elapsedRealtime());
}
}
final long count = mExpectations.size();
final String msg = count + " requests still not " + final String msg = count + " requests still not " +
(mExpectingAdditions ? "added" : "removed") + (mExpectingAdditions ? "added" : "removed") +
" after " + TIMEOUT_MS + " ms"; " after " + TIMEOUT_MS + " ms";
assertEquals(msg, 0, count); assertEquals(msg, 0, count);
mExpectations = null;
} }
public SparseArray<NetworkRequest> waitForNetworkRequests(final int count) public SparseArray<NetworkRequest> waitForNetworkRequests(final int count)
@@ -2329,6 +2345,12 @@ public class ConnectivityServiceTest {
callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent); callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
} }
private int[] makeIntArray(final int size, final int value) {
final int[] array = new int[size];
Arrays.fill(array, value);
return array;
}
private void tryNetworkFactoryRequests(int capability) throws Exception { private void tryNetworkFactoryRequests(int capability) throws Exception {
// Verify NOT_RESTRICTED is set appropriately // Verify NOT_RESTRICTED is set appropriately
final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability) final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
@@ -2350,7 +2372,7 @@ public class ConnectivityServiceTest {
mServiceContext, "testFactory", filter); mServiceContext, "testFactory", filter);
testFactory.setScoreFilter(40); testFactory.setScoreFilter(40);
ConditionVariable cv = testFactory.getNetworkStartedCV(); ConditionVariable cv = testFactory.getNetworkStartedCV();
testFactory.expectAddRequests(1); testFactory.expectAddRequestsWithScores(0);
testFactory.register(); testFactory.register();
testFactory.waitForNetworkRequests(1); testFactory.waitForNetworkRequests(1);
int expectedRequestCount = 1; int expectedRequestCount = 1;
@@ -2361,7 +2383,7 @@ public class ConnectivityServiceTest {
assertFalse(testFactory.getMyStartRequested()); assertFalse(testFactory.getMyStartRequested());
NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build(); NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
networkCallback = new NetworkCallback(); networkCallback = new NetworkCallback();
testFactory.expectAddRequests(1); testFactory.expectAddRequestsWithScores(0); // New request
mCm.requestNetwork(request, networkCallback); mCm.requestNetwork(request, networkCallback);
expectedRequestCount++; expectedRequestCount++;
testFactory.waitForNetworkRequests(expectedRequestCount); testFactory.waitForNetworkRequests(expectedRequestCount);
@@ -2381,7 +2403,7 @@ public class ConnectivityServiceTest {
// When testAgent connects, ConnectivityService will re-send us all current requests with // When testAgent connects, ConnectivityService will re-send us all current requests with
// the new score. There are expectedRequestCount such requests, and we must wait for all of // the new score. There are expectedRequestCount such requests, and we must wait for all of
// them. // them.
testFactory.expectAddRequests(expectedRequestCount); testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 50));
testAgent.connect(false); testAgent.connect(false);
testAgent.addCapability(capability); testAgent.addCapability(capability);
waitFor(cv); waitFor(cv);
@@ -2389,7 +2411,7 @@ public class ConnectivityServiceTest {
assertFalse(testFactory.getMyStartRequested()); assertFalse(testFactory.getMyStartRequested());
// Bring in a bunch of requests. // Bring in a bunch of requests.
testFactory.expectAddRequests(10); testFactory.expectAddRequestsWithScores(makeIntArray(10, 50));
assertEquals(expectedRequestCount, testFactory.getMyRequestCount()); assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
ConnectivityManager.NetworkCallback[] networkCallbacks = ConnectivityManager.NetworkCallback[] networkCallbacks =
new ConnectivityManager.NetworkCallback[10]; new ConnectivityManager.NetworkCallback[10];
@@ -2412,8 +2434,11 @@ public class ConnectivityServiceTest {
// Drop the higher scored network. // Drop the higher scored network.
cv = testFactory.getNetworkStartedCV(); cv = testFactory.getNetworkStartedCV();
// With the default network disconnecting, the requests are sent with score 0 to factories.
testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 0));
testAgent.disconnect(); testAgent.disconnect();
waitFor(cv); waitFor(cv);
testFactory.waitForNetworkRequests(expectedRequestCount);
assertEquals(expectedRequestCount, testFactory.getMyRequestCount()); assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
assertTrue(testFactory.getMyStartRequested()); assertTrue(testFactory.getMyStartRequested());
@@ -3336,22 +3361,23 @@ public class ConnectivityServiceTest {
testFactory.setScoreFilter(40); testFactory.setScoreFilter(40);
// Register the factory and expect it to start looking for a network. // Register the factory and expect it to start looking for a network.
testFactory.expectAddRequests(1); testFactory.expectAddRequestsWithScores(0); // Score 0 as the request is not served yet.
testFactory.register(); testFactory.register();
testFactory.waitForNetworkRequests(1); testFactory.waitForNetworkRequests(1);
assertTrue(testFactory.getMyStartRequested()); assertTrue(testFactory.getMyStartRequested());
// Bring up wifi. The factory stops looking for a network. // Bring up wifi. The factory stops looking for a network.
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
testFactory.expectAddRequests(2); // Because the default request changes score twice. // Score 60 - 40 penalty for not validated yet, then 60 when it validates
testFactory.expectAddRequestsWithScores(20, 60);
mWiFiNetworkAgent.connect(true); mWiFiNetworkAgent.connect(true);
testFactory.waitForNetworkRequests(1); testFactory.waitForRequests();
assertFalse(testFactory.getMyStartRequested()); assertFalse(testFactory.getMyStartRequested());
ContentResolver cr = mServiceContext.getContentResolver(); ContentResolver cr = mServiceContext.getContentResolver();
// Turn on mobile data always on. The factory starts looking again. // Turn on mobile data always on. The factory starts looking again.
testFactory.expectAddRequests(1); testFactory.expectAddRequestsWithScores(0); // Always on requests comes up with score 0
setAlwaysOnNetworks(true); setAlwaysOnNetworks(true);
testFactory.waitForNetworkRequests(2); testFactory.waitForNetworkRequests(2);
assertTrue(testFactory.getMyStartRequested()); assertTrue(testFactory.getMyStartRequested());
@@ -3359,7 +3385,7 @@ public class ConnectivityServiceTest {
// Bring up cell data and check that the factory stops looking. // Bring up cell data and check that the factory stops looking.
assertLength(1, mCm.getAllNetworks()); assertLength(1, mCm.getAllNetworks());
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
testFactory.expectAddRequests(2); // Because the cell request changes score twice. testFactory.expectAddRequestsWithScores(10, 50); // Unvalidated, then validated
mCellNetworkAgent.connect(true); mCellNetworkAgent.connect(true);
cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
testFactory.waitForNetworkRequests(2); testFactory.waitForNetworkRequests(2);
@@ -3673,7 +3699,7 @@ public class ConnectivityServiceTest {
testFactory.setScoreFilter(40); testFactory.setScoreFilter(40);
// Register the factory and expect it to receive the default request. // Register the factory and expect it to receive the default request.
testFactory.expectAddRequests(1); testFactory.expectAddRequestsWithScores(0); // default request score is 0, not served yet
testFactory.register(); testFactory.register();
SparseArray<NetworkRequest> requests = testFactory.waitForNetworkRequests(1); SparseArray<NetworkRequest> requests = testFactory.waitForNetworkRequests(1);
@@ -3681,7 +3707,7 @@ public class ConnectivityServiceTest {
int origRequestId = requests.valueAt(0).requestId; int origRequestId = requests.valueAt(0).requestId;
// Now file the test request and expect it. // Now file the test request and expect it.
testFactory.expectAddRequests(1); testFactory.expectAddRequestsWithScores(0);
mCm.requestNetwork(nr, networkCallback); mCm.requestNetwork(nr, networkCallback);
requests = testFactory.waitForNetworkRequests(2); // have 2 requests at this point requests = testFactory.waitForNetworkRequests(2); // have 2 requests at this point

View File

@@ -35,6 +35,7 @@ import android.net.ConnectivityManager;
import android.net.INetd; import android.net.INetd;
import android.net.Network; import android.net.Network;
import android.net.NetworkCapabilities; import android.net.NetworkCapabilities;
import android.net.NetworkFactory;
import android.net.NetworkInfo; import android.net.NetworkInfo;
import android.net.NetworkMisc; import android.net.NetworkMisc;
import android.os.INetworkManagementService; import android.os.INetworkManagementService;
@@ -352,7 +353,8 @@ public class LingerMonitorTest {
caps.addCapability(0); caps.addCapability(0);
caps.addTransportType(transport); caps.addTransportType(transport);
NetworkAgentInfo nai = new NetworkAgentInfo(null, null, new Network(netId), info, null, NetworkAgentInfo nai = new NetworkAgentInfo(null, null, new Network(netId), info, null,
caps, 50, mCtx, null, mMisc, mConnService, mNetd, mNMS); caps, 50, mCtx, null, mMisc, mConnService, mNetd, mNMS,
NetworkFactory.SerialNumber.NONE);
nai.everValidated = true; nai.everValidated = true;
return nai; return nai;
} }