Support requesting async LinkProperties/NetworkCapabilities updates
Bug: 9580643 Change-Id: I1d7ba7645c20d7d53f6eef777dfce43727940f13
This commit is contained in:
@@ -1034,6 +1034,26 @@ public class ConnectivityManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request that this callback be invoked at ConnectivityService's earliest
|
||||||
|
* convenience with the current satisfying network's LinkProperties.
|
||||||
|
* If no such network exists no callback invocation is performed.
|
||||||
|
*
|
||||||
|
* The callback must have been registered with #requestNetwork() or
|
||||||
|
* #registerDefaultNetworkCallback(); callbacks registered with
|
||||||
|
* registerNetworkCallback() are not specific to any particular Network so
|
||||||
|
* do not cause any updates.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public void requestLinkProperties(NetworkCallback networkCallback) {
|
||||||
|
try {
|
||||||
|
mService.requestLinkProperties(networkCallback.networkRequest);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
throw e.rethrowFromSystemServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the {@link android.net.NetworkCapabilities} for the given {@link Network}. This
|
* Get the {@link android.net.NetworkCapabilities} for the given {@link Network}. This
|
||||||
* will return {@code null} if the network is unknown.
|
* will return {@code null} if the network is unknown.
|
||||||
@@ -1051,6 +1071,26 @@ public class ConnectivityManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request that this callback be invoked at ConnectivityService's earliest
|
||||||
|
* convenience with the current satisfying network's NetworkCapabilities.
|
||||||
|
* If no such network exists no callback invocation is performed.
|
||||||
|
*
|
||||||
|
* The callback must have been registered with #requestNetwork() or
|
||||||
|
* #registerDefaultNetworkCallback(); callbacks registered with
|
||||||
|
* registerNetworkCallback() are not specific to any particular Network so
|
||||||
|
* do not cause any updates.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public void requestNetworkCapabilities(NetworkCallback networkCallback) {
|
||||||
|
try {
|
||||||
|
mService.requestNetworkCapabilities(networkCallback.networkRequest);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
throw e.rethrowFromSystemServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the URL that should be used for resolving whether a captive portal is present.
|
* Gets the URL that should be used for resolving whether a captive portal is present.
|
||||||
* 1. This URL should respond with a 204 response to a GET request to indicate no captive
|
* 1. This URL should respond with a 204 response to a GET request to indicate no captive
|
||||||
|
|||||||
@@ -156,6 +156,8 @@ interface IConnectivityManager
|
|||||||
void pendingListenForNetwork(in NetworkCapabilities networkCapabilities,
|
void pendingListenForNetwork(in NetworkCapabilities networkCapabilities,
|
||||||
in PendingIntent operation);
|
in PendingIntent operation);
|
||||||
|
|
||||||
|
void requestLinkProperties(in NetworkRequest networkRequest);
|
||||||
|
void requestNetworkCapabilities(in NetworkRequest networkRequest);
|
||||||
void releaseNetworkRequest(in NetworkRequest networkRequest);
|
void releaseNetworkRequest(in NetworkRequest networkRequest);
|
||||||
|
|
||||||
void setAcceptUnvalidated(in Network network, boolean accept, boolean always);
|
void setAcceptUnvalidated(in Network network, boolean accept, boolean always);
|
||||||
|
|||||||
@@ -303,7 +303,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* indicates a timeout period is over - check if we had a network yet or not
|
* indicates a timeout period is over - check if we had a network yet or not
|
||||||
* and if not, call the timeout calback (but leave the request live until they
|
* and if not, call the timeout callback (but leave the request live until they
|
||||||
* cancel it.
|
* cancel it.
|
||||||
* includes a NetworkRequestInfo
|
* includes a NetworkRequestInfo
|
||||||
*/
|
*/
|
||||||
@@ -380,6 +380,16 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
*/
|
*/
|
||||||
private static final int EVENT_REGISTER_NETWORK_LISTENER_WITH_INTENT = 31;
|
private static final int EVENT_REGISTER_NETWORK_LISTENER_WITH_INTENT = 31;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates a caller has requested to have its callback invoked with
|
||||||
|
* the latest LinkProperties or NetworkCapabilities.
|
||||||
|
*
|
||||||
|
* arg1 = UID of caller
|
||||||
|
* obj = NetworkRequest
|
||||||
|
*/
|
||||||
|
private static final int EVENT_REQUEST_LINKPROPERTIES = 32;
|
||||||
|
private static final int EVENT_REQUEST_NETCAPABILITIES = 33;
|
||||||
|
|
||||||
/** Handler thread used for both of the handlers below. */
|
/** Handler thread used for both of the handlers below. */
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
protected final HandlerThread mHandlerThread;
|
protected final HandlerThread mHandlerThread;
|
||||||
@@ -2447,13 +2457,54 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid) {
|
private NetworkRequestInfo getNriForAppRequest(
|
||||||
NetworkRequestInfo nri = mNetworkRequests.get(request);
|
NetworkRequest request, int callingUid, String requestedOperation) {
|
||||||
|
final NetworkRequestInfo nri = mNetworkRequests.get(request);
|
||||||
|
|
||||||
if (nri != null) {
|
if (nri != null) {
|
||||||
if (Process.SYSTEM_UID != callingUid && nri.mUid != callingUid) {
|
if (Process.SYSTEM_UID != callingUid && nri.mUid != callingUid) {
|
||||||
if (DBG) log("Attempt to release unowned NetworkRequest " + request);
|
log(String.format("UID %d attempted to %s for unowned request %s",
|
||||||
return;
|
callingUid, requestedOperation, nri));
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nri;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleRequestCallbackUpdate(NetworkRequest request, int callingUid,
|
||||||
|
String description, int callbackType) {
|
||||||
|
final NetworkRequestInfo nri = getNriForAppRequest(request, callingUid, description);
|
||||||
|
if (nri == null) return;
|
||||||
|
|
||||||
|
final NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
|
||||||
|
// The network that is satisfying this request may have changed since
|
||||||
|
// the application requested the update.
|
||||||
|
//
|
||||||
|
// - If the request is no longer satisfied, don't send any updates.
|
||||||
|
// - If the request is satisfied by a different network, it is the
|
||||||
|
// caller's responsibility to check that the Network object in the
|
||||||
|
// callback matches the network that was returned in the last
|
||||||
|
// onAvailable() callback for this request.
|
||||||
|
if (nai == null) return;
|
||||||
|
callCallbackForRequest(nri, nai, callbackType, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleRequestLinkProperties(NetworkRequest request, int callingUid) {
|
||||||
|
handleRequestCallbackUpdate(request, callingUid,
|
||||||
|
"request LinkProperties", ConnectivityManager.CALLBACK_IP_CHANGED);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleRequestNetworkCapabilities(NetworkRequest request, int callingUid) {
|
||||||
|
handleRequestCallbackUpdate(request, callingUid,
|
||||||
|
"request NetworkCapabilities", ConnectivityManager.CALLBACK_CAP_CHANGED);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid) {
|
||||||
|
final NetworkRequestInfo nri = getNriForAppRequest(
|
||||||
|
request, callingUid, "release NetworkRequest");
|
||||||
|
if (nri == null) return;
|
||||||
|
|
||||||
if (VDBG || (DBG && nri.request.isRequest())) log("releasing " + request);
|
if (VDBG || (DBG && nri.request.isRequest())) log("releasing " + request);
|
||||||
nri.unlinkDeathRecipient();
|
nri.unlinkDeathRecipient();
|
||||||
mNetworkRequests.remove(request);
|
mNetworkRequests.remove(request);
|
||||||
@@ -2547,7 +2598,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
}
|
}
|
||||||
callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_RELEASED, 0);
|
callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_RELEASED, 0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setAcceptUnvalidated(Network network, boolean accept, boolean always) {
|
public void setAcceptUnvalidated(Network network, boolean accept, boolean always) {
|
||||||
@@ -2709,6 +2759,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
handleMobileDataAlwaysOn();
|
handleMobileDataAlwaysOn();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case EVENT_REQUEST_LINKPROPERTIES:
|
||||||
|
handleRequestLinkProperties((NetworkRequest) msg.obj, msg.arg1);
|
||||||
|
break;
|
||||||
|
case EVENT_REQUEST_NETCAPABILITIES:
|
||||||
|
handleRequestNetworkCapabilities((NetworkRequest) msg.obj, msg.arg1);
|
||||||
|
break;
|
||||||
// Sent by KeepaliveTracker to process an app request on the state machine thread.
|
// Sent by KeepaliveTracker to process an app request on the state machine thread.
|
||||||
case NetworkAgent.CMD_START_PACKET_KEEPALIVE: {
|
case NetworkAgent.CMD_START_PACKET_KEEPALIVE: {
|
||||||
mKeepaliveTracker.handleStartKeepalive(msg);
|
mKeepaliveTracker.handleStartKeepalive(msg);
|
||||||
@@ -4169,11 +4225,27 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri));
|
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void requestLinkProperties(NetworkRequest networkRequest) {
|
||||||
|
ensureNetworkRequestHasType(networkRequest);
|
||||||
|
if (networkRequest.type == NetworkRequest.Type.LISTEN) return;
|
||||||
|
mHandler.sendMessage(mHandler.obtainMessage(
|
||||||
|
EVENT_REQUEST_LINKPROPERTIES, getCallingUid(), 0, networkRequest));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void requestNetworkCapabilities(NetworkRequest networkRequest) {
|
||||||
|
ensureNetworkRequestHasType(networkRequest);
|
||||||
|
if (networkRequest.type == NetworkRequest.Type.LISTEN) return;
|
||||||
|
mHandler.sendMessage(mHandler.obtainMessage(
|
||||||
|
EVENT_REQUEST_NETCAPABILITIES, getCallingUid(), 0, networkRequest));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void releaseNetworkRequest(NetworkRequest networkRequest) {
|
public void releaseNetworkRequest(NetworkRequest networkRequest) {
|
||||||
ensureNetworkRequestHasType(networkRequest);
|
ensureNetworkRequestHasType(networkRequest);
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST, getCallingUid(),
|
mHandler.sendMessage(mHandler.obtainMessage(
|
||||||
0, networkRequest));
|
EVENT_RELEASE_NETWORK_REQUEST, getCallingUid(), 0, networkRequest));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1040,6 +1040,8 @@ public class ConnectivityServiceTest extends AndroidTestCase {
|
|||||||
enum CallbackState {
|
enum CallbackState {
|
||||||
NONE,
|
NONE,
|
||||||
AVAILABLE,
|
AVAILABLE,
|
||||||
|
NETWORK_CAPABILITIES,
|
||||||
|
LINK_PROPERTIES,
|
||||||
LOSING,
|
LOSING,
|
||||||
LOST
|
LOST
|
||||||
}
|
}
|
||||||
@@ -1072,18 +1074,21 @@ public class ConnectivityServiceTest extends AndroidTestCase {
|
|||||||
}
|
}
|
||||||
private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
|
private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
|
||||||
|
|
||||||
private void setLastCallback(CallbackState state, Network network, Object o) {
|
protected void setLastCallback(CallbackState state, Network network, Object o) {
|
||||||
mCallbacks.offer(new CallbackInfo(state, network, o));
|
mCallbacks.offer(new CallbackInfo(state, network, o));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onAvailable(Network network) {
|
public void onAvailable(Network network) {
|
||||||
setLastCallback(CallbackState.AVAILABLE, network, null);
|
setLastCallback(CallbackState.AVAILABLE, network, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onLosing(Network network, int maxMsToLive) {
|
public void onLosing(Network network, int maxMsToLive) {
|
||||||
setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
|
setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onLost(Network network) {
|
public void onLost(Network network) {
|
||||||
setLastCallback(CallbackState.LOST, network, null);
|
setLastCallback(CallbackState.LOST, network, null);
|
||||||
}
|
}
|
||||||
@@ -1744,6 +1749,67 @@ public class ConnectivityServiceTest extends AndroidTestCase {
|
|||||||
defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
|
defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class TestRequestUpdateCallback extends TestNetworkCallback {
|
||||||
|
@Override
|
||||||
|
public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) {
|
||||||
|
setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) {
|
||||||
|
setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@LargeTest
|
||||||
|
public void testRequestCallbackUpdates() throws Exception {
|
||||||
|
// File a network request for mobile.
|
||||||
|
final TestNetworkCallback cellNetworkCallback = new TestRequestUpdateCallback();
|
||||||
|
final NetworkRequest cellRequest = new NetworkRequest.Builder()
|
||||||
|
.addTransportType(TRANSPORT_CELLULAR).build();
|
||||||
|
mCm.requestNetwork(cellRequest, cellNetworkCallback);
|
||||||
|
|
||||||
|
// Bring up the mobile network.
|
||||||
|
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
|
||||||
|
mCellNetworkAgent.connect(true);
|
||||||
|
|
||||||
|
// We should get onAvailable().
|
||||||
|
cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
|
||||||
|
// We should get onCapabilitiesChanged(), when the mobile network successfully validates.
|
||||||
|
cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, mCellNetworkAgent);
|
||||||
|
cellNetworkCallback.assertNoCallback();
|
||||||
|
|
||||||
|
// Update LinkProperties.
|
||||||
|
final LinkProperties lp = new LinkProperties();
|
||||||
|
lp.setInterfaceName("foonet_data0");
|
||||||
|
mCellNetworkAgent.sendLinkProperties(lp);
|
||||||
|
// We should get onLinkPropertiesChanged().
|
||||||
|
cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
|
||||||
|
cellNetworkCallback.assertNoCallback();
|
||||||
|
|
||||||
|
// Register a garden variety default network request.
|
||||||
|
final TestNetworkCallback dfltNetworkCallback = new TestRequestUpdateCallback();
|
||||||
|
mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
|
||||||
|
// Only onAvailable() is called; no other information is delivered.
|
||||||
|
dfltNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
|
||||||
|
dfltNetworkCallback.assertNoCallback();
|
||||||
|
|
||||||
|
// Request a NetworkCapabilities update; only the requesting callback is notified.
|
||||||
|
mCm.requestNetworkCapabilities(dfltNetworkCallback);
|
||||||
|
dfltNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, mCellNetworkAgent);
|
||||||
|
cellNetworkCallback.assertNoCallback();
|
||||||
|
dfltNetworkCallback.assertNoCallback();
|
||||||
|
|
||||||
|
// Request a LinkProperties update; only the requesting callback is notified.
|
||||||
|
mCm.requestLinkProperties(dfltNetworkCallback);
|
||||||
|
dfltNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
|
||||||
|
cellNetworkCallback.assertNoCallback();
|
||||||
|
dfltNetworkCallback.assertNoCallback();
|
||||||
|
|
||||||
|
mCm.unregisterNetworkCallback(dfltNetworkCallback);
|
||||||
|
mCm.unregisterNetworkCallback(cellNetworkCallback);
|
||||||
|
}
|
||||||
|
|
||||||
@SmallTest
|
@SmallTest
|
||||||
public void testRequestBenchmark() throws Exception {
|
public void testRequestBenchmark() throws Exception {
|
||||||
// Benchmarks connecting and switching performance in the presence of a large number of
|
// Benchmarks connecting and switching performance in the presence of a large number of
|
||||||
|
|||||||
Reference in New Issue
Block a user