Add LocalNetworkInfo and send callbacks when it changes
Test: CSLocalAgentTest Change-Id: I8caca97b891081f9212a01d428a34ed1a08d5126
This commit is contained in:
20
framework/aidl-export/android/net/LocalNetworkInfo.aidl
Normal file
20
framework/aidl-export/android/net/LocalNetworkInfo.aidl
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2023 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 android.net;
|
||||||
|
|
||||||
|
parcelable LocalNetworkInfo;
|
||||||
@@ -23,6 +23,7 @@ android\.net\.IConnectivityDiagnosticsCallback(\$.+)?
|
|||||||
# of these classes must be protected by a check for >= S SDK.
|
# of these classes must be protected by a check for >= S SDK.
|
||||||
# It's unlikely anybody else declares a hidden class with this name ?
|
# It's unlikely anybody else declares a hidden class with this name ?
|
||||||
android\.net\.RoutingCoordinatorManager(\$.+)?
|
android\.net\.RoutingCoordinatorManager(\$.+)?
|
||||||
|
android\.net\.LocalNetworkInfo(\$.+)?
|
||||||
|
|
||||||
# KeepaliveUtils is used by ConnectivityManager CTS
|
# KeepaliveUtils is used by ConnectivityManager CTS
|
||||||
# TODO: move into service-connectivity so framework-connectivity stops using
|
# TODO: move into service-connectivity so framework-connectivity stops using
|
||||||
|
|||||||
@@ -3963,16 +3963,21 @@ public class ConnectivityManager {
|
|||||||
* @param network The {@link Network} of the satisfying network.
|
* @param network The {@link Network} of the satisfying network.
|
||||||
* @param networkCapabilities The {@link NetworkCapabilities} of the satisfying network.
|
* @param networkCapabilities The {@link NetworkCapabilities} of the satisfying network.
|
||||||
* @param linkProperties The {@link LinkProperties} of the satisfying network.
|
* @param linkProperties The {@link LinkProperties} of the satisfying network.
|
||||||
|
* @param localInfo The {@link LocalNetworkInfo} of the satisfying network, or null
|
||||||
|
* if this network is not a local network.
|
||||||
* @param blocked Whether access to the {@link Network} is blocked due to system policy.
|
* @param blocked Whether access to the {@link Network} is blocked due to system policy.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public final void onAvailable(@NonNull Network network,
|
public final void onAvailable(@NonNull Network network,
|
||||||
@NonNull NetworkCapabilities networkCapabilities,
|
@NonNull NetworkCapabilities networkCapabilities,
|
||||||
@NonNull LinkProperties linkProperties, @BlockedReason int blocked) {
|
@NonNull LinkProperties linkProperties,
|
||||||
|
@Nullable LocalNetworkInfo localInfo,
|
||||||
|
@BlockedReason int blocked) {
|
||||||
// Internally only this method is called when a new network is available, and
|
// Internally only this method is called when a new network is available, and
|
||||||
// it calls the callback in the same way and order that older versions used
|
// it calls the callback in the same way and order that older versions used
|
||||||
// to call so as not to change the behavior.
|
// to call so as not to change the behavior.
|
||||||
onAvailable(network, networkCapabilities, linkProperties, blocked != 0);
|
onAvailable(network, networkCapabilities, linkProperties, blocked != 0);
|
||||||
|
if (null != localInfo) onLocalNetworkInfoChanged(network, localInfo);
|
||||||
onBlockedStatusChanged(network, blocked);
|
onBlockedStatusChanged(network, blocked);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3989,7 +3994,8 @@ public class ConnectivityManager {
|
|||||||
*/
|
*/
|
||||||
public void onAvailable(@NonNull Network network,
|
public void onAvailable(@NonNull Network network,
|
||||||
@NonNull NetworkCapabilities networkCapabilities,
|
@NonNull NetworkCapabilities networkCapabilities,
|
||||||
@NonNull LinkProperties linkProperties, boolean blocked) {
|
@NonNull LinkProperties linkProperties,
|
||||||
|
boolean blocked) {
|
||||||
onAvailable(network);
|
onAvailable(network);
|
||||||
if (!networkCapabilities.hasCapability(
|
if (!networkCapabilities.hasCapability(
|
||||||
NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)) {
|
NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)) {
|
||||||
@@ -4115,6 +4121,19 @@ public class ConnectivityManager {
|
|||||||
public void onLinkPropertiesChanged(@NonNull Network network,
|
public void onLinkPropertiesChanged(@NonNull Network network,
|
||||||
@NonNull LinkProperties linkProperties) {}
|
@NonNull LinkProperties linkProperties) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when there is a change in the {@link LocalNetworkInfo} for this network.
|
||||||
|
*
|
||||||
|
* This is only called for local networks, that is those with the
|
||||||
|
* NET_CAPABILITY_LOCAL_NETWORK network capability.
|
||||||
|
*
|
||||||
|
* @param network the {@link Network} whose local network info has changed.
|
||||||
|
* @param localNetworkInfo the new {@link LocalNetworkInfo} for this network.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public void onLocalNetworkInfoChanged(@NonNull Network network,
|
||||||
|
@NonNull LocalNetworkInfo localNetworkInfo) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the network the framework connected to for this request suspends data
|
* Called when the network the framework connected to for this request suspends data
|
||||||
* transmission temporarily.
|
* transmission temporarily.
|
||||||
@@ -4230,6 +4249,8 @@ public class ConnectivityManager {
|
|||||||
public static final int CALLBACK_RESUMED = 10;
|
public static final int CALLBACK_RESUMED = 10;
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public static final int CALLBACK_BLK_CHANGED = 11;
|
public static final int CALLBACK_BLK_CHANGED = 11;
|
||||||
|
/** @hide */
|
||||||
|
public static final int CALLBACK_LOCAL_NETWORK_INFO_CHANGED = 12;
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public static String getCallbackName(int whichCallback) {
|
public static String getCallbackName(int whichCallback) {
|
||||||
@@ -4245,6 +4266,7 @@ public class ConnectivityManager {
|
|||||||
case CALLBACK_SUSPENDED: return "CALLBACK_SUSPENDED";
|
case CALLBACK_SUSPENDED: return "CALLBACK_SUSPENDED";
|
||||||
case CALLBACK_RESUMED: return "CALLBACK_RESUMED";
|
case CALLBACK_RESUMED: return "CALLBACK_RESUMED";
|
||||||
case CALLBACK_BLK_CHANGED: return "CALLBACK_BLK_CHANGED";
|
case CALLBACK_BLK_CHANGED: return "CALLBACK_BLK_CHANGED";
|
||||||
|
case CALLBACK_LOCAL_NETWORK_INFO_CHANGED: return "CALLBACK_LOCAL_NETWORK_INFO_CHANGED";
|
||||||
default:
|
default:
|
||||||
return Integer.toString(whichCallback);
|
return Integer.toString(whichCallback);
|
||||||
}
|
}
|
||||||
@@ -4299,7 +4321,8 @@ public class ConnectivityManager {
|
|||||||
case CALLBACK_AVAILABLE: {
|
case CALLBACK_AVAILABLE: {
|
||||||
NetworkCapabilities cap = getObject(message, NetworkCapabilities.class);
|
NetworkCapabilities cap = getObject(message, NetworkCapabilities.class);
|
||||||
LinkProperties lp = getObject(message, LinkProperties.class);
|
LinkProperties lp = getObject(message, LinkProperties.class);
|
||||||
callback.onAvailable(network, cap, lp, message.arg1);
|
LocalNetworkInfo lni = getObject(message, LocalNetworkInfo.class);
|
||||||
|
callback.onAvailable(network, cap, lp, lni, message.arg1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CALLBACK_LOSING: {
|
case CALLBACK_LOSING: {
|
||||||
@@ -4324,6 +4347,11 @@ public class ConnectivityManager {
|
|||||||
callback.onLinkPropertiesChanged(network, lp);
|
callback.onLinkPropertiesChanged(network, lp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case CALLBACK_LOCAL_NETWORK_INFO_CHANGED: {
|
||||||
|
final LocalNetworkInfo info = getObject(message, LocalNetworkInfo.class);
|
||||||
|
callback.onLocalNetworkInfoChanged(network, info);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case CALLBACK_SUSPENDED: {
|
case CALLBACK_SUSPENDED: {
|
||||||
callback.onNetworkSuspended(network);
|
callback.onNetworkSuspended(network);
|
||||||
break;
|
break;
|
||||||
|
|||||||
96
framework/src/android/net/LocalNetworkInfo.java
Normal file
96
framework/src/android/net/LocalNetworkInfo.java
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 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 android.net;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
import android.annotation.Nullable;
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information about a local network.
|
||||||
|
*
|
||||||
|
* This is sent to ConnectivityManager.NetworkCallback.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
// TODO : make public
|
||||||
|
public final class LocalNetworkInfo implements Parcelable {
|
||||||
|
@Nullable private final Network mUpstreamNetwork;
|
||||||
|
|
||||||
|
public LocalNetworkInfo(@Nullable final Network upstreamNetwork) {
|
||||||
|
this.mUpstreamNetwork = upstreamNetwork;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the upstream network, or null if none.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public Network getUpstreamNetwork() {
|
||||||
|
return mUpstreamNetwork;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(@NonNull final Parcel dest, final int flags) {
|
||||||
|
dest.writeParcelable(mUpstreamNetwork, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "LocalNetworkInfo { upstream=" + mUpstreamNetwork + " }";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final @NonNull Creator<LocalNetworkInfo> CREATOR = new Creator<>() {
|
||||||
|
public LocalNetworkInfo createFromParcel(Parcel in) {
|
||||||
|
final Network upstreamNetwork = in.readParcelable(null);
|
||||||
|
return new LocalNetworkInfo(upstreamNetwork);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LocalNetworkInfo[] newArray(final int size) {
|
||||||
|
return new LocalNetworkInfo[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder for LocalNetworkInfo
|
||||||
|
*/
|
||||||
|
public static final class Builder {
|
||||||
|
@Nullable private Network mUpstreamNetwork;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the upstream network, or null if none.
|
||||||
|
* @return the builder
|
||||||
|
*/
|
||||||
|
@NonNull public Builder setUpstreamNetwork(@Nullable final Network network) {
|
||||||
|
mUpstreamNetwork = network;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the LocalNetworkInfo
|
||||||
|
*/
|
||||||
|
@NonNull public LocalNetworkInfo build() {
|
||||||
|
return new LocalNetworkInfo(mUpstreamNetwork);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -168,6 +168,7 @@ import android.net.IpMemoryStore;
|
|||||||
import android.net.IpPrefix;
|
import android.net.IpPrefix;
|
||||||
import android.net.LinkProperties;
|
import android.net.LinkProperties;
|
||||||
import android.net.LocalNetworkConfig;
|
import android.net.LocalNetworkConfig;
|
||||||
|
import android.net.LocalNetworkInfo;
|
||||||
import android.net.MatchAllNetworkSpecifier;
|
import android.net.MatchAllNetworkSpecifier;
|
||||||
import android.net.NativeNetworkConfig;
|
import android.net.NativeNetworkConfig;
|
||||||
import android.net.NativeNetworkType;
|
import android.net.NativeNetworkType;
|
||||||
@@ -4183,7 +4184,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
}
|
}
|
||||||
case NetworkAgent.EVENT_LOCAL_NETWORK_CONFIG_CHANGED: {
|
case NetworkAgent.EVENT_LOCAL_NETWORK_CONFIG_CHANGED: {
|
||||||
final LocalNetworkConfig config = (LocalNetworkConfig) arg.second;
|
final LocalNetworkConfig config = (LocalNetworkConfig) arg.second;
|
||||||
updateLocalNetworkConfig(nai, nai.localNetworkConfig, config);
|
handleUpdateLocalNetworkConfig(nai, nai.localNetworkConfig, config);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NetworkAgent.EVENT_NETWORK_SCORE_CHANGED: {
|
case NetworkAgent.EVENT_NETWORK_SCORE_CHANGED: {
|
||||||
@@ -4946,7 +4947,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
notifyIfacesChangedForNetworkStats();
|
notifyIfacesChangedForNetworkStats();
|
||||||
// If this was a local network forwarded to some upstream, or if some local network was
|
// If this was a local network forwarded to some upstream, or if some local network was
|
||||||
// forwarded to this nai, then disable forwarding rules now.
|
// forwarded to this nai, then disable forwarding rules now.
|
||||||
maybeDisableForwardRulesForDisconnectingNai(nai);
|
maybeDisableForwardRulesForDisconnectingNai(nai, true /* sendCallbacks */);
|
||||||
// If this is a local network with an upstream selector, remove the associated network
|
// If this is a local network with an upstream selector, remove the associated network
|
||||||
// request.
|
// request.
|
||||||
if (nai.isLocalNetwork()) {
|
if (nai.isLocalNetwork()) {
|
||||||
@@ -5069,7 +5070,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void maybeDisableForwardRulesForDisconnectingNai(
|
private void maybeDisableForwardRulesForDisconnectingNai(
|
||||||
@NonNull final NetworkAgentInfo disconnecting) {
|
@NonNull final NetworkAgentInfo disconnecting, final boolean sendCallbacks) {
|
||||||
// Step 1 : maybe this network was the upstream for one or more local networks.
|
// Step 1 : maybe this network was the upstream for one or more local networks.
|
||||||
for (final NetworkAgentInfo local : mNetworkAgentInfos) {
|
for (final NetworkAgentInfo local : mNetworkAgentInfos) {
|
||||||
if (!local.isLocalNetwork()) continue;
|
if (!local.isLocalNetwork()) continue;
|
||||||
@@ -5082,6 +5083,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
final NetworkAgentInfo satisfier = nri.getSatisfier();
|
final NetworkAgentInfo satisfier = nri.getSatisfier();
|
||||||
if (disconnecting != satisfier) continue;
|
if (disconnecting != satisfier) continue;
|
||||||
removeLocalNetworkUpstream(local, disconnecting);
|
removeLocalNetworkUpstream(local, disconnecting);
|
||||||
|
// Set the satisfier to null immediately so that the LOCAL_NETWORK_CHANGED callback
|
||||||
|
// correctly contains null as an upstream.
|
||||||
|
if (sendCallbacks) {
|
||||||
|
nri.setSatisfier(null, null);
|
||||||
|
notifyNetworkCallbacks(local,
|
||||||
|
ConnectivityManager.CALLBACK_LOCAL_NETWORK_INFO_CHANGED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 2 : maybe this is a local network that had an upstream.
|
// Step 2 : maybe this is a local network that had an upstream.
|
||||||
@@ -5148,8 +5156,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
mDscpPolicyTracker.removeAllDscpPolicies(nai, false);
|
mDscpPolicyTracker.removeAllDscpPolicies(nai, false);
|
||||||
}
|
}
|
||||||
// Remove any forwarding rules to and from the interface for this network, since
|
// Remove any forwarding rules to and from the interface for this network, since
|
||||||
// the interface is going to go away.
|
// the interface is going to go away. Don't send the callbacks however ; if the network
|
||||||
maybeDisableForwardRulesForDisconnectingNai(nai);
|
// was is being disconnected the callbacks have already been sent, and if it is being
|
||||||
|
// destroyed pending replacement they will be sent when it is disconnected.
|
||||||
|
maybeDisableForwardRulesForDisconnectingNai(nai, false /* sendCallbacks */);
|
||||||
try {
|
try {
|
||||||
mNetd.networkDestroy(nai.network.getNetId());
|
mNetd.networkDestroy(nai.network.getNetId());
|
||||||
} catch (RemoteException | ServiceSpecificException e) {
|
} catch (RemoteException | ServiceSpecificException e) {
|
||||||
@@ -8320,7 +8330,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (nai.isLocalNetwork()) {
|
if (nai.isLocalNetwork()) {
|
||||||
updateLocalNetworkConfig(nai, null /* oldConfig */, nai.localNetworkConfig);
|
handleUpdateLocalNetworkConfig(nai, null /* oldConfig */, nai.localNetworkConfig);
|
||||||
}
|
}
|
||||||
nai.notifyRegistered();
|
nai.notifyRegistered();
|
||||||
NetworkInfo networkInfo = nai.networkInfo;
|
NetworkInfo networkInfo = nai.networkInfo;
|
||||||
@@ -8988,7 +8998,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
}
|
}
|
||||||
|
|
||||||
// oldConfig is null iff this is the original registration of the local network config
|
// oldConfig is null iff this is the original registration of the local network config
|
||||||
private void updateLocalNetworkConfig(@NonNull final NetworkAgentInfo nai,
|
private void handleUpdateLocalNetworkConfig(@NonNull final NetworkAgentInfo nai,
|
||||||
@Nullable final LocalNetworkConfig oldConfig,
|
@Nullable final LocalNetworkConfig oldConfig,
|
||||||
@NonNull final LocalNetworkConfig newConfig) {
|
@NonNull final LocalNetworkConfig newConfig) {
|
||||||
if (!nai.isLocalNetwork()) {
|
if (!nai.isLocalNetwork()) {
|
||||||
@@ -9021,6 +9031,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
// If there is an old satisfier, but no new request, then remove the old upstream.
|
// If there is an old satisfier, but no new request, then remove the old upstream.
|
||||||
removeLocalNetworkUpstream(nai, oldSatisfier);
|
removeLocalNetworkUpstream(nai, oldSatisfier);
|
||||||
nai.localNetworkConfig = configBuilder.build();
|
nai.localNetworkConfig = configBuilder.build();
|
||||||
|
// When there is a new request, the rematch sees the new request and sends the
|
||||||
|
// LOCAL_NETWORK_INFO_CHANGED callbacks accordingly.
|
||||||
|
// But here there is no new request, so the rematch won't see anything. Send
|
||||||
|
// callbacks to apps now to tell them about the loss of upstream.
|
||||||
|
notifyNetworkCallbacks(nai,
|
||||||
|
ConnectivityManager.CALLBACK_LOCAL_NETWORK_INFO_CHANGED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9042,12 +9058,14 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
nri.setSatisfier(oldSatisfier, nr);
|
nri.setSatisfier(oldSatisfier, nr);
|
||||||
}
|
}
|
||||||
nai.localNetworkConfig = configBuilder.build();
|
nai.localNetworkConfig = configBuilder.build();
|
||||||
|
// handleRegisterNetworkRequest causes a rematch. The rematch must happen after
|
||||||
|
// nai.localNetworkConfig is set, since it will base its callbacks on the old
|
||||||
|
// satisfier and the new request.
|
||||||
handleRegisterNetworkRequest(nri);
|
handleRegisterNetworkRequest(nri);
|
||||||
} else {
|
} else {
|
||||||
configBuilder.setUpstreamSelector(oldRequest);
|
configBuilder.setUpstreamSelector(oldRequest);
|
||||||
nai.localNetworkConfig = configBuilder.build();
|
nai.localNetworkConfig = configBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -9378,6 +9396,21 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
releasePendingNetworkRequestWithDelay(pendingIntent);
|
releasePendingNetworkRequestWithDelay(pendingIntent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private LocalNetworkInfo localNetworkInfoForNai(@NonNull final NetworkAgentInfo nai) {
|
||||||
|
if (!nai.isLocalNetwork()) return null;
|
||||||
|
final Network upstream;
|
||||||
|
final NetworkRequest selector = nai.localNetworkConfig.getUpstreamSelector();
|
||||||
|
if (null == selector) {
|
||||||
|
upstream = null;
|
||||||
|
} else {
|
||||||
|
final NetworkRequestInfo upstreamNri = mNetworkRequests.get(selector);
|
||||||
|
final NetworkAgentInfo satisfier = upstreamNri.getSatisfier();
|
||||||
|
upstream = (null == satisfier) ? null : satisfier.network;
|
||||||
|
}
|
||||||
|
return new LocalNetworkInfo.Builder().setUpstreamNetwork(upstream).build();
|
||||||
|
}
|
||||||
|
|
||||||
// networkAgent is only allowed to be null if notificationType is
|
// networkAgent is only allowed to be null if notificationType is
|
||||||
// CALLBACK_UNAVAIL. This is because UNAVAIL is about no network being
|
// CALLBACK_UNAVAIL. This is because UNAVAIL is about no network being
|
||||||
// available, while all other cases are about some particular network.
|
// available, while all other cases are about some particular network.
|
||||||
@@ -9413,6 +9446,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
putParcelable(bundle, nc);
|
putParcelable(bundle, nc);
|
||||||
putParcelable(bundle, linkPropertiesRestrictedForCallerPermissions(
|
putParcelable(bundle, linkPropertiesRestrictedForCallerPermissions(
|
||||||
networkAgent.linkProperties, nri.mPid, nri.mUid));
|
networkAgent.linkProperties, nri.mPid, nri.mUid));
|
||||||
|
// The local network info is often null, so can't use the static putParcelable
|
||||||
|
// method here.
|
||||||
|
bundle.putParcelable(LocalNetworkInfo.class.getSimpleName(),
|
||||||
|
localNetworkInfoForNai(networkAgent));
|
||||||
// For this notification, arg1 contains the blocked status.
|
// For this notification, arg1 contains the blocked status.
|
||||||
msg.arg1 = arg1;
|
msg.arg1 = arg1;
|
||||||
break;
|
break;
|
||||||
@@ -9444,6 +9481,14 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
msg.arg1 = arg1;
|
msg.arg1 = arg1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ConnectivityManager.CALLBACK_LOCAL_NETWORK_INFO_CHANGED: {
|
||||||
|
if (!networkAgent.isLocalNetwork()) {
|
||||||
|
Log.wtf(TAG, "Callback for local info for a non-local network");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
putParcelable(bundle, localNetworkInfoForNai(networkAgent));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
msg.what = notificationType;
|
msg.what = notificationType;
|
||||||
msg.setData(bundle);
|
msg.setData(bundle);
|
||||||
@@ -10077,6 +10122,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
loge("Can't update forwarding rules", e);
|
loge("Can't update forwarding rules", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOCAL_NETWORK_INFO_CHANGED);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateLegacyTypeTrackerAndVpnLockdownForRematch(changes, nais);
|
updateLegacyTypeTrackerAndVpnLockdownForRematch(changes, nais);
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.android.testutils
|
|||||||
|
|
||||||
import android.net.ConnectivityManager.NetworkCallback
|
import android.net.ConnectivityManager.NetworkCallback
|
||||||
import android.net.LinkProperties
|
import android.net.LinkProperties
|
||||||
|
import android.net.LocalNetworkInfo
|
||||||
import android.net.Network
|
import android.net.Network
|
||||||
import android.net.NetworkCapabilities
|
import android.net.NetworkCapabilities
|
||||||
import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED
|
import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED
|
||||||
@@ -28,6 +29,7 @@ import com.android.testutils.RecorderCallback.CallbackEntry.BlockedStatus
|
|||||||
import com.android.testutils.RecorderCallback.CallbackEntry.BlockedStatusInt
|
import com.android.testutils.RecorderCallback.CallbackEntry.BlockedStatusInt
|
||||||
import com.android.testutils.RecorderCallback.CallbackEntry.CapabilitiesChanged
|
import com.android.testutils.RecorderCallback.CallbackEntry.CapabilitiesChanged
|
||||||
import com.android.testutils.RecorderCallback.CallbackEntry.LinkPropertiesChanged
|
import com.android.testutils.RecorderCallback.CallbackEntry.LinkPropertiesChanged
|
||||||
|
import com.android.testutils.RecorderCallback.CallbackEntry.LocalInfoChanged
|
||||||
import com.android.testutils.RecorderCallback.CallbackEntry.Losing
|
import com.android.testutils.RecorderCallback.CallbackEntry.Losing
|
||||||
import com.android.testutils.RecorderCallback.CallbackEntry.Lost
|
import com.android.testutils.RecorderCallback.CallbackEntry.Lost
|
||||||
import com.android.testutils.RecorderCallback.CallbackEntry.Resumed
|
import com.android.testutils.RecorderCallback.CallbackEntry.Resumed
|
||||||
@@ -68,6 +70,10 @@ open class RecorderCallback private constructor(
|
|||||||
override val network: Network,
|
override val network: Network,
|
||||||
val lp: LinkProperties
|
val lp: LinkProperties
|
||||||
) : CallbackEntry()
|
) : CallbackEntry()
|
||||||
|
data class LocalInfoChanged(
|
||||||
|
override val network: Network,
|
||||||
|
val info: LocalNetworkInfo
|
||||||
|
) : CallbackEntry()
|
||||||
data class Suspended(override val network: Network) : CallbackEntry()
|
data class Suspended(override val network: Network) : CallbackEntry()
|
||||||
data class Resumed(override val network: Network) : CallbackEntry()
|
data class Resumed(override val network: Network) : CallbackEntry()
|
||||||
data class Losing(override val network: Network, val maxMsToLive: Int) : CallbackEntry()
|
data class Losing(override val network: Network, val maxMsToLive: Int) : CallbackEntry()
|
||||||
@@ -94,6 +100,8 @@ open class RecorderCallback private constructor(
|
|||||||
@JvmField
|
@JvmField
|
||||||
val LINK_PROPERTIES_CHANGED = LinkPropertiesChanged::class
|
val LINK_PROPERTIES_CHANGED = LinkPropertiesChanged::class
|
||||||
@JvmField
|
@JvmField
|
||||||
|
val LOCAL_INFO_CHANGED = LocalInfoChanged::class
|
||||||
|
@JvmField
|
||||||
val SUSPENDED = Suspended::class
|
val SUSPENDED = Suspended::class
|
||||||
@JvmField
|
@JvmField
|
||||||
val RESUMED = Resumed::class
|
val RESUMED = Resumed::class
|
||||||
@@ -131,6 +139,11 @@ open class RecorderCallback private constructor(
|
|||||||
history.add(LinkPropertiesChanged(network, lp))
|
history.add(LinkPropertiesChanged(network, lp))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onLocalNetworkInfoChanged(network: Network, info: LocalNetworkInfo) {
|
||||||
|
Log.d(TAG, "onLocalNetworkInfoChanged $network $info")
|
||||||
|
history.add(LocalInfoChanged(network, info))
|
||||||
|
}
|
||||||
|
|
||||||
override fun onBlockedStatusChanged(network: Network, blocked: Boolean) {
|
override fun onBlockedStatusChanged(network: Network, blocked: Boolean) {
|
||||||
Log.d(TAG, "onBlockedStatusChanged $network $blocked")
|
Log.d(TAG, "onBlockedStatusChanged $network $blocked")
|
||||||
history.add(BlockedStatus(network, blocked))
|
history.add(BlockedStatus(network, blocked))
|
||||||
@@ -430,37 +443,63 @@ open class TestableNetworkCallback private constructor(
|
|||||||
suspended: Boolean = false,
|
suspended: Boolean = false,
|
||||||
validated: Boolean? = true,
|
validated: Boolean? = true,
|
||||||
blocked: Boolean = false,
|
blocked: Boolean = false,
|
||||||
|
upstream: Network? = null,
|
||||||
tmt: Long = defaultTimeoutMs
|
tmt: Long = defaultTimeoutMs
|
||||||
) {
|
) {
|
||||||
expectAvailableCallbacksCommon(net, suspended, validated, tmt)
|
expectAvailableCallbacksCommon(net, suspended, validated, upstream, tmt)
|
||||||
expect<BlockedStatus>(net, tmt) { it.blocked == blocked }
|
expect<BlockedStatus>(net, tmt) { it.blocked == blocked }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For backward compatibility, add a method that allows callers to specify a timeout but
|
||||||
|
// no upstream.
|
||||||
|
fun expectAvailableCallbacks(
|
||||||
|
net: Network,
|
||||||
|
suspended: Boolean = false,
|
||||||
|
validated: Boolean? = true,
|
||||||
|
blocked: Boolean = false,
|
||||||
|
tmt: Long = defaultTimeoutMs
|
||||||
|
) = expectAvailableCallbacks(net, suspended, validated, blocked, upstream = null, tmt = tmt)
|
||||||
|
|
||||||
fun expectAvailableCallbacks(
|
fun expectAvailableCallbacks(
|
||||||
net: Network,
|
net: Network,
|
||||||
suspended: Boolean,
|
suspended: Boolean,
|
||||||
validated: Boolean,
|
validated: Boolean,
|
||||||
blockedReason: Int,
|
blockedReason: Int,
|
||||||
|
upstream: Network? = null,
|
||||||
tmt: Long
|
tmt: Long
|
||||||
) {
|
) {
|
||||||
expectAvailableCallbacksCommon(net, suspended, validated, tmt)
|
expectAvailableCallbacksCommon(net, suspended, validated, upstream, tmt)
|
||||||
expect<BlockedStatusInt>(net) { it.reason == blockedReason }
|
expect<BlockedStatusInt>(net) { it.reason == blockedReason }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For backward compatibility, add a method that allows callers to specify a timeout but
|
||||||
|
// no upstream.
|
||||||
|
fun expectAvailableCallbacks(
|
||||||
|
net: Network,
|
||||||
|
suspended: Boolean = false,
|
||||||
|
validated: Boolean = true,
|
||||||
|
blockedReason: Int,
|
||||||
|
tmt: Long = defaultTimeoutMs
|
||||||
|
) = expectAvailableCallbacks(net, suspended, validated, blockedReason, upstream = null, tmt)
|
||||||
|
|
||||||
private fun expectAvailableCallbacksCommon(
|
private fun expectAvailableCallbacksCommon(
|
||||||
net: Network,
|
net: Network,
|
||||||
suspended: Boolean,
|
suspended: Boolean,
|
||||||
validated: Boolean?,
|
validated: Boolean?,
|
||||||
|
upstream: Network?,
|
||||||
tmt: Long
|
tmt: Long
|
||||||
) {
|
) {
|
||||||
expect<Available>(net, tmt)
|
expect<Available>(net, tmt)
|
||||||
if (suspended) {
|
if (suspended) {
|
||||||
expect<Suspended>(net, tmt)
|
expect<Suspended>(net, tmt)
|
||||||
}
|
}
|
||||||
expect<CapabilitiesChanged>(net, tmt) {
|
val caps = expect<CapabilitiesChanged>(net, tmt) {
|
||||||
validated == null || validated == it.caps.hasCapability(NET_CAPABILITY_VALIDATED)
|
validated == null || validated == it.caps.hasCapability(NET_CAPABILITY_VALIDATED)
|
||||||
}
|
}.caps
|
||||||
expect<LinkPropertiesChanged>(net, tmt)
|
expect<LinkPropertiesChanged>(net, tmt)
|
||||||
|
if (caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK)) {
|
||||||
|
expect<LocalInfoChanged>(net, tmt) { it.info.upstreamNetwork == upstream }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Backward compatibility for existing Java code. Use named arguments instead and remove all
|
// Backward compatibility for existing Java code. Use named arguments instead and remove all
|
||||||
@@ -507,13 +546,15 @@ open class TestableNetworkCallback private constructor(
|
|||||||
val network: Network
|
val network: Network
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JvmOverloads
|
||||||
fun expectAvailableCallbacks(
|
fun expectAvailableCallbacks(
|
||||||
n: HasNetwork,
|
n: HasNetwork,
|
||||||
suspended: Boolean,
|
suspended: Boolean,
|
||||||
validated: Boolean,
|
validated: Boolean,
|
||||||
blocked: Boolean,
|
blocked: Boolean,
|
||||||
|
upstream: Network? = null,
|
||||||
timeoutMs: Long
|
timeoutMs: Long
|
||||||
) = expectAvailableCallbacks(n.network, suspended, validated, blocked, timeoutMs)
|
) = expectAvailableCallbacks(n.network, suspended, validated, blocked, upstream, timeoutMs)
|
||||||
|
|
||||||
fun expectAvailableAndSuspendedCallbacks(n: HasNetwork, expectValidated: Boolean) {
|
fun expectAvailableAndSuspendedCallbacks(n: HasNetwork, expectValidated: Boolean) {
|
||||||
expectAvailableAndSuspendedCallbacks(n.network, expectValidated)
|
expectAvailableAndSuspendedCallbacks(n.network, expectValidated)
|
||||||
|
|||||||
@@ -38,10 +38,7 @@ import android.net.RouteInfo
|
|||||||
import android.os.Build
|
import android.os.Build
|
||||||
import com.android.testutils.DevSdkIgnoreRule
|
import com.android.testutils.DevSdkIgnoreRule
|
||||||
import com.android.testutils.DevSdkIgnoreRunner
|
import com.android.testutils.DevSdkIgnoreRunner
|
||||||
import com.android.testutils.RecorderCallback.CallbackEntry.Available
|
import com.android.testutils.RecorderCallback.CallbackEntry.LocalInfoChanged
|
||||||
import com.android.testutils.RecorderCallback.CallbackEntry.BlockedStatus
|
|
||||||
import com.android.testutils.RecorderCallback.CallbackEntry.CapabilitiesChanged
|
|
||||||
import com.android.testutils.RecorderCallback.CallbackEntry.LinkPropertiesChanged
|
|
||||||
import com.android.testutils.RecorderCallback.CallbackEntry.Lost
|
import com.android.testutils.RecorderCallback.CallbackEntry.Lost
|
||||||
import com.android.testutils.TestableNetworkCallback
|
import com.android.testutils.TestableNetworkCallback
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
@@ -114,10 +111,7 @@ class CSLocalAgentTests : CSTest() {
|
|||||||
.build(),
|
.build(),
|
||||||
lnc = LocalNetworkConfig.Builder().build())
|
lnc = LocalNetworkConfig.Builder().build())
|
||||||
agent.connect()
|
agent.connect()
|
||||||
cb.expect<Available>(agent.network)
|
cb.expectAvailableCallbacks(agent.network, validated = false)
|
||||||
cb.expect<CapabilitiesChanged>(agent.network)
|
|
||||||
cb.expect<LinkPropertiesChanged>(agent.network)
|
|
||||||
cb.expect<BlockedStatus>(agent.network)
|
|
||||||
agent.sendNetworkCapabilities(NetworkCapabilities.Builder().build())
|
agent.sendNetworkCapabilities(NetworkCapabilities.Builder().build())
|
||||||
cb.expect<Lost>(agent.network)
|
cb.expect<Lost>(agent.network)
|
||||||
|
|
||||||
@@ -125,10 +119,7 @@ class CSLocalAgentTests : CSTest() {
|
|||||||
.build(),
|
.build(),
|
||||||
lnc = null)
|
lnc = null)
|
||||||
agent2.connect()
|
agent2.connect()
|
||||||
cb.expect<Available>(agent2.network)
|
cb.expectAvailableCallbacks(agent2.network, validated = false)
|
||||||
cb.expect<CapabilitiesChanged>(agent2.network)
|
|
||||||
cb.expect<LinkPropertiesChanged>(agent2.network)
|
|
||||||
cb.expect<BlockedStatus>(agent2.network)
|
|
||||||
agent2.sendNetworkCapabilities(NetworkCapabilities.Builder()
|
agent2.sendNetworkCapabilities(NetworkCapabilities.Builder()
|
||||||
.addCapability(NET_CAPABILITY_LOCAL_NETWORK)
|
.addCapability(NET_CAPABILITY_LOCAL_NETWORK)
|
||||||
.build())
|
.build())
|
||||||
@@ -153,10 +144,11 @@ class CSLocalAgentTests : CSTest() {
|
|||||||
)
|
)
|
||||||
localAgent.connect()
|
localAgent.connect()
|
||||||
|
|
||||||
cb.expect<Available>(localAgent.network)
|
cb.expectAvailableCallbacks(localAgent.network, validated = false)
|
||||||
cb.expect<CapabilitiesChanged>(localAgent.network)
|
|
||||||
cb.expect<LinkPropertiesChanged>(localAgent.network)
|
val wifiAgent = Agent(score = keepScore(), lp = lp("wifi0"),
|
||||||
cb.expect<BlockedStatus>(localAgent.network)
|
nc = nc(TRANSPORT_WIFI, NET_CAPABILITY_INTERNET))
|
||||||
|
wifiAgent.connect()
|
||||||
|
|
||||||
val newLnc = LocalNetworkConfig.Builder()
|
val newLnc = LocalNetworkConfig.Builder()
|
||||||
.setUpstreamSelector(NetworkRequest.Builder()
|
.setUpstreamSelector(NetworkRequest.Builder()
|
||||||
@@ -165,6 +157,21 @@ class CSLocalAgentTests : CSTest() {
|
|||||||
.build()
|
.build()
|
||||||
localAgent.sendLocalNetworkConfig(newLnc)
|
localAgent.sendLocalNetworkConfig(newLnc)
|
||||||
|
|
||||||
|
cb.expect<LocalInfoChanged>(localAgent.network) {
|
||||||
|
it.info.upstreamNetwork == wifiAgent.network
|
||||||
|
}
|
||||||
|
|
||||||
|
localAgent.sendLocalNetworkConfig(LocalNetworkConfig.Builder().build())
|
||||||
|
cb.expect<LocalInfoChanged>(localAgent.network) { it.info.upstreamNetwork == null }
|
||||||
|
|
||||||
|
localAgent.sendLocalNetworkConfig(newLnc)
|
||||||
|
cb.expect<LocalInfoChanged>(localAgent.network) {
|
||||||
|
it.info.upstreamNetwork == wifiAgent.network
|
||||||
|
}
|
||||||
|
|
||||||
|
wifiAgent.disconnect()
|
||||||
|
cb.expect<LocalInfoChanged>(localAgent.network) { it.info.upstreamNetwork == null }
|
||||||
|
|
||||||
localAgent.disconnect()
|
localAgent.disconnect()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,6 +211,9 @@ class CSLocalAgentTests : CSTest() {
|
|||||||
wifiAgent.connect()
|
wifiAgent.connect()
|
||||||
|
|
||||||
cb.expectAvailableCallbacks(wifiAgent.network, validated = false)
|
cb.expectAvailableCallbacks(wifiAgent.network, validated = false)
|
||||||
|
cb.expect<LocalInfoChanged>(localAgent.network) {
|
||||||
|
it.info.upstreamNetwork == wifiAgent.network
|
||||||
|
}
|
||||||
|
|
||||||
clearInvocations(netd)
|
clearInvocations(netd)
|
||||||
val inOrder = inOrder(netd)
|
val inOrder = inOrder(netd)
|
||||||
@@ -218,6 +228,7 @@ class CSLocalAgentTests : CSTest() {
|
|||||||
wifiAgent2.connect()
|
wifiAgent2.connect()
|
||||||
|
|
||||||
cb.expectAvailableCallbacks(wifiAgent2.network, validated = false)
|
cb.expectAvailableCallbacks(wifiAgent2.network, validated = false)
|
||||||
|
cb.expect<LocalInfoChanged> { it.info.upstreamNetwork == wifiAgent2.network }
|
||||||
cb.expect<Lost> { it.network == wifiAgent.network }
|
cb.expect<Lost> { it.network == wifiAgent.network }
|
||||||
|
|
||||||
inOrder.verify(netd).ipfwdAddInterfaceForward("local0", wifiIface2)
|
inOrder.verify(netd).ipfwdAddInterfaceForward("local0", wifiIface2)
|
||||||
@@ -252,7 +263,10 @@ class CSLocalAgentTests : CSTest() {
|
|||||||
nc = nc(TRANSPORT_WIFI, NET_CAPABILITY_INTERNET))
|
nc = nc(TRANSPORT_WIFI, NET_CAPABILITY_INTERNET))
|
||||||
wifiAgent.connect()
|
wifiAgent.connect()
|
||||||
|
|
||||||
cb.expectAvailableCallbacksUnvalidated(wifiAgent)
|
cb.expectAvailableCallbacks(wifiAgent.network, validated = false)
|
||||||
|
cb.expect<LocalInfoChanged>(localAgent.network) {
|
||||||
|
it.info.upstreamNetwork == wifiAgent.network
|
||||||
|
}
|
||||||
|
|
||||||
clearInvocations(netd)
|
clearInvocations(netd)
|
||||||
wifiAgent.unregisterAfterReplacement(TIMEOUT_MS.toInt())
|
wifiAgent.unregisterAfterReplacement(TIMEOUT_MS.toInt())
|
||||||
@@ -260,6 +274,7 @@ class CSLocalAgentTests : CSTest() {
|
|||||||
verify(netd).networkDestroy(wifiAgent.network.netId)
|
verify(netd).networkDestroy(wifiAgent.network.netId)
|
||||||
verify(netd).ipfwdRemoveInterfaceForward("local0", "wifi0")
|
verify(netd).ipfwdRemoveInterfaceForward("local0", "wifi0")
|
||||||
|
|
||||||
|
cb.expect<LocalInfoChanged>(localAgent.network) { it.info.upstreamNetwork == null }
|
||||||
cb.expect<Lost> { it.network == wifiAgent.network }
|
cb.expect<Lost> { it.network == wifiAgent.network }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,7 +309,12 @@ class CSLocalAgentTests : CSTest() {
|
|||||||
val wifiAgent = Agent(lp = lp("wifi0"), nc = nc(TRANSPORT_WIFI, NET_CAPABILITY_INTERNET))
|
val wifiAgent = Agent(lp = lp("wifi0"), nc = nc(TRANSPORT_WIFI, NET_CAPABILITY_INTERNET))
|
||||||
wifiAgent.connect()
|
wifiAgent.connect()
|
||||||
|
|
||||||
cb.expectAvailableCallbacksUnvalidated(wifiAgent)
|
cb.expectAvailableCallbacks(wifiAgent.network, validated = false)
|
||||||
|
listOf(cb, localCb).forEach {
|
||||||
|
it.expect<LocalInfoChanged>(localAgent.network) {
|
||||||
|
it.info.upstreamNetwork == wifiAgent.network
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
verify(netd).ipfwdAddInterfaceForward("local0", "wifi0")
|
verify(netd).ipfwdAddInterfaceForward("local0", "wifi0")
|
||||||
|
|
||||||
@@ -303,8 +323,10 @@ class CSLocalAgentTests : CSTest() {
|
|||||||
val localAgent2 = Agent(nc = localNc, lp = lp("local0"), lnc = lnc, score = localScore)
|
val localAgent2 = Agent(nc = localNc, lp = lp("local0"), lnc = lnc, score = localScore)
|
||||||
localAgent2.connect()
|
localAgent2.connect()
|
||||||
|
|
||||||
localCb.expectAvailableCallbacks(localAgent2.network, validated = false)
|
localCb.expectAvailableCallbacks(localAgent2.network,
|
||||||
cb.expectAvailableCallbacks(localAgent2.network, validated = false)
|
validated = false, upstream = wifiAgent.network)
|
||||||
|
cb.expectAvailableCallbacks(localAgent2.network,
|
||||||
|
validated = false, upstream = wifiAgent.network)
|
||||||
cb.expect<Lost> { it.network == localAgent.network }
|
cb.expect<Lost> { it.network == localAgent.network }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,9 +338,11 @@ class CSLocalAgentTests : CSTest() {
|
|||||||
|
|
||||||
val wifiAgent = Agent(lp = lp("wifi0"), nc = nc(TRANSPORT_WIFI, NET_CAPABILITY_INTERNET))
|
val wifiAgent = Agent(lp = lp("wifi0"), nc = nc(TRANSPORT_WIFI, NET_CAPABILITY_INTERNET))
|
||||||
wifiAgent.connect()
|
wifiAgent.connect()
|
||||||
cb.expectAvailableCallbacksUnvalidated(wifiAgent)
|
cb.expectAvailableCallbacks(wifiAgent.network, validated = false)
|
||||||
|
|
||||||
// Set up a local agent that should forward its traffic to the best wifi upstream.
|
// Unregister wifi pending replacement, then set up a local agent that would have
|
||||||
|
// this network as its upstream.
|
||||||
|
wifiAgent.unregisterAfterReplacement(LONG_TIMEOUT_MS)
|
||||||
val localAgent = Agent(nc = nc(TRANSPORT_WIFI, NET_CAPABILITY_LOCAL_NETWORK),
|
val localAgent = Agent(nc = nc(TRANSPORT_WIFI, NET_CAPABILITY_LOCAL_NETWORK),
|
||||||
lp = lp("local0"),
|
lp = lp("local0"),
|
||||||
lnc = LocalNetworkConfig.Builder()
|
lnc = LocalNetworkConfig.Builder()
|
||||||
@@ -331,14 +355,18 @@ class CSLocalAgentTests : CSTest() {
|
|||||||
.build())
|
.build())
|
||||||
)
|
)
|
||||||
|
|
||||||
// ...but destroy the wifi agent before connecting it
|
// Connect the local agent. The zombie wifi is its upstream, but the stack doesn't
|
||||||
wifiAgent.unregisterAfterReplacement(LONG_TIMEOUT_MS)
|
// tell netd to add the forward since the wifi0 interface has gone.
|
||||||
|
|
||||||
localAgent.connect()
|
localAgent.connect()
|
||||||
cb.expectAvailableCallbacks(localAgent.network, validated = false)
|
cb.expectAvailableCallbacks(localAgent.network,
|
||||||
|
validated = false, upstream = wifiAgent.network)
|
||||||
|
|
||||||
verify(netd).ipfwdAddInterfaceForward("local0", "wifi0")
|
verify(netd, never()).ipfwdAddInterfaceForward("local0", "wifi0")
|
||||||
verify(netd).ipfwdRemoveInterfaceForward("local0", "wifi0")
|
|
||||||
|
// Disconnect wifi without a replacement. Expect an update with upstream null.
|
||||||
|
wifiAgent.disconnect()
|
||||||
|
verify(netd, never()).ipfwdAddInterfaceForward("local0", "wifi0")
|
||||||
|
cb.expect<LocalInfoChanged> { it.info.upstreamNetwork == null }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -366,19 +394,34 @@ class CSLocalAgentTests : CSTest() {
|
|||||||
val wifiAgentDun = Agent(score = keepScore(), lp = lp("wifi1"),
|
val wifiAgentDun = Agent(score = keepScore(), lp = lp("wifi1"),
|
||||||
nc = nc(TRANSPORT_WIFI, NET_CAPABILITY_INTERNET, NET_CAPABILITY_DUN))
|
nc = nc(TRANSPORT_WIFI, NET_CAPABILITY_INTERNET, NET_CAPABILITY_DUN))
|
||||||
|
|
||||||
|
val cb = TestableNetworkCallback()
|
||||||
|
cm.registerNetworkCallback(NetworkRequest.Builder()
|
||||||
|
.addCapability(NET_CAPABILITY_LOCAL_NETWORK)
|
||||||
|
.build(),
|
||||||
|
cb)
|
||||||
|
cb.expectAvailableCallbacks(localAgent.network, validated = false)
|
||||||
|
|
||||||
val inOrder = inOrder(netd)
|
val inOrder = inOrder(netd)
|
||||||
inOrder.verify(netd, never()).ipfwdAddInterfaceForward(any(), any())
|
inOrder.verify(netd, never()).ipfwdAddInterfaceForward(any(), any())
|
||||||
|
cb.assertNoCallback()
|
||||||
|
|
||||||
wifiAgent.connect()
|
wifiAgent.connect()
|
||||||
inOrder.verify(netd, never()).ipfwdAddInterfaceForward(any(), any())
|
inOrder.verify(netd, never()).ipfwdAddInterfaceForward(any(), any())
|
||||||
|
cb.assertNoCallback()
|
||||||
|
|
||||||
cellAgentDun.connect()
|
cellAgentDun.connect()
|
||||||
inOrder.verify(netd).ipfwdEnableForwarding(any())
|
inOrder.verify(netd).ipfwdEnableForwarding(any())
|
||||||
inOrder.verify(netd).ipfwdAddInterfaceForward("local0", "cell0")
|
inOrder.verify(netd).ipfwdAddInterfaceForward("local0", "cell0")
|
||||||
|
cb.expect<LocalInfoChanged>(localAgent.network) {
|
||||||
|
it.info.upstreamNetwork == cellAgentDun.network
|
||||||
|
}
|
||||||
|
|
||||||
wifiAgentDun.connect()
|
wifiAgentDun.connect()
|
||||||
inOrder.verify(netd).ipfwdRemoveInterfaceForward("local0", "cell0")
|
inOrder.verify(netd).ipfwdRemoveInterfaceForward("local0", "cell0")
|
||||||
inOrder.verify(netd).ipfwdAddInterfaceForward("local0", "wifi1")
|
inOrder.verify(netd).ipfwdAddInterfaceForward("local0", "wifi1")
|
||||||
|
cb.expect<LocalInfoChanged>(localAgent.network) {
|
||||||
|
it.info.upstreamNetwork == wifiAgentDun.network
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure sending the same config again doesn't do anything
|
// Make sure sending the same config again doesn't do anything
|
||||||
repeat(5) {
|
repeat(5) {
|
||||||
@@ -387,6 +430,10 @@ class CSLocalAgentTests : CSTest() {
|
|||||||
inOrder.verifyNoMoreInteractions()
|
inOrder.verifyNoMoreInteractions()
|
||||||
|
|
||||||
wifiAgentDun.disconnect()
|
wifiAgentDun.disconnect()
|
||||||
|
cb.expect<LocalInfoChanged>(localAgent.network) { it.info.upstreamNetwork == null }
|
||||||
|
cb.expect<LocalInfoChanged>(localAgent.network) {
|
||||||
|
it.info.upstreamNetwork == cellAgentDun.network
|
||||||
|
}
|
||||||
inOrder.verify(netd).ipfwdRemoveInterfaceForward("local0", "wifi1")
|
inOrder.verify(netd).ipfwdRemoveInterfaceForward("local0", "wifi1")
|
||||||
// This can take a little bit of time because it needs to wait for the rematch
|
// This can take a little bit of time because it needs to wait for the rematch
|
||||||
inOrder.verify(netd, timeout(MEDIUM_TIMEOUT_MS)).ipfwdAddInterfaceForward("local0", "cell0")
|
inOrder.verify(netd, timeout(MEDIUM_TIMEOUT_MS)).ipfwdAddInterfaceForward("local0", "cell0")
|
||||||
@@ -394,15 +441,35 @@ class CSLocalAgentTests : CSTest() {
|
|||||||
cellAgentDun.disconnect()
|
cellAgentDun.disconnect()
|
||||||
inOrder.verify(netd).ipfwdRemoveInterfaceForward("local0", "cell0")
|
inOrder.verify(netd).ipfwdRemoveInterfaceForward("local0", "cell0")
|
||||||
inOrder.verify(netd).ipfwdDisableForwarding(any())
|
inOrder.verify(netd).ipfwdDisableForwarding(any())
|
||||||
|
cb.expect<LocalInfoChanged>(localAgent.network) { it.info.upstreamNetwork == null }
|
||||||
|
|
||||||
val wifiAgentDun2 = Agent(score = keepScore(), lp = lp("wifi2"),
|
val wifiAgentDun2 = Agent(score = keepScore(), lp = lp("wifi2"),
|
||||||
nc = nc(TRANSPORT_WIFI, NET_CAPABILITY_INTERNET, NET_CAPABILITY_DUN))
|
nc = nc(TRANSPORT_WIFI, NET_CAPABILITY_INTERNET, NET_CAPABILITY_DUN))
|
||||||
wifiAgentDun2.connect()
|
wifiAgentDun2.connect()
|
||||||
inOrder.verify(netd).ipfwdEnableForwarding(any())
|
inOrder.verify(netd).ipfwdEnableForwarding(any())
|
||||||
inOrder.verify(netd).ipfwdAddInterfaceForward("local0", "wifi2")
|
inOrder.verify(netd).ipfwdAddInterfaceForward("local0", "wifi2")
|
||||||
|
cb.expect<LocalInfoChanged>(localAgent.network) {
|
||||||
|
it.info.upstreamNetwork == wifiAgentDun2.network
|
||||||
|
}
|
||||||
|
|
||||||
localAgent.disconnect()
|
wifiAgentDun2.disconnect()
|
||||||
inOrder.verify(netd).ipfwdRemoveInterfaceForward("local0", "wifi2")
|
inOrder.verify(netd).ipfwdRemoveInterfaceForward("local0", "wifi2")
|
||||||
inOrder.verify(netd).ipfwdDisableForwarding(any())
|
inOrder.verify(netd).ipfwdDisableForwarding(any())
|
||||||
|
cb.expect<LocalInfoChanged>(localAgent.network) { it.info.upstreamNetwork == null }
|
||||||
|
|
||||||
|
val wifiAgentDun3 = Agent(score = keepScore(), lp = lp("wifi3"),
|
||||||
|
nc = nc(TRANSPORT_WIFI, NET_CAPABILITY_INTERNET, NET_CAPABILITY_DUN))
|
||||||
|
wifiAgentDun3.connect()
|
||||||
|
inOrder.verify(netd).ipfwdEnableForwarding(any())
|
||||||
|
inOrder.verify(netd).ipfwdAddInterfaceForward("local0", "wifi3")
|
||||||
|
cb.expect<LocalInfoChanged>(localAgent.network) {
|
||||||
|
it.info.upstreamNetwork == wifiAgentDun3.network
|
||||||
|
}
|
||||||
|
|
||||||
|
localAgent.disconnect()
|
||||||
|
inOrder.verify(netd).ipfwdRemoveInterfaceForward("local0", "wifi3")
|
||||||
|
inOrder.verify(netd).ipfwdDisableForwarding(any())
|
||||||
|
cb.expect<Lost>(localAgent.network)
|
||||||
|
cb.assertNoCallback()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user