Migrate away from AsyncChannel in NetworkAgent

Use two oneway binder interfaces instead.
The interfaces post messages to handlers as was implemented before, but
provide a more strictly defined interface, with less hops between
NetworkAgent, AsyncChannel, and ConnectivityService.

The actual public interface is the NetworkAgent @SystemApi: the binder
interface is an internal implementation detail.

Test: atest FrameworksNetTests CtsNetTestCasesLatestSdk
Bug: 173574274
Merged-In: Ie364ab50f416e7821e70f4539a881eea828e1256

Change-Id: Ie364ab50f416e7821e70f4539a881eea828e1256
This commit is contained in:
Remi NGUYEN VAN
2020-12-23 12:45:08 +09:00
parent 090cbf27ab
commit 77b0c1c72c
8 changed files with 557 additions and 206 deletions

View File

@@ -61,6 +61,7 @@ import android.util.ArrayMap;
import android.util.Log;
import android.util.SparseIntArray;
import com.android.connectivity.aidl.INetworkAgent;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
import com.android.internal.util.Protocol;
@@ -3287,9 +3288,9 @@ public class ConnectivityManager {
@RequiresPermission(anyOf = {
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
android.Manifest.permission.NETWORK_FACTORY})
public Network registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp,
public Network registerNetworkAgent(INetworkAgent na, NetworkInfo ni, LinkProperties lp,
NetworkCapabilities nc, int score, NetworkAgentConfig config) {
return registerNetworkAgent(messenger, ni, lp, nc, score, config, NetworkProvider.ID_NONE);
return registerNetworkAgent(na, ni, lp, nc, score, config, NetworkProvider.ID_NONE);
}
/**
@@ -3300,10 +3301,10 @@ public class ConnectivityManager {
@RequiresPermission(anyOf = {
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
android.Manifest.permission.NETWORK_FACTORY})
public Network registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp,
public Network registerNetworkAgent(INetworkAgent na, NetworkInfo ni, LinkProperties lp,
NetworkCapabilities nc, int score, NetworkAgentConfig config, int providerId) {
try {
return mService.registerNetworkAgent(messenger, ni, lp, nc, score, config, providerId);
return mService.registerNetworkAgent(na, ni, lp, nc, score, config, providerId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}

View File

@@ -37,6 +37,7 @@ import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
import android.os.ResultReceiver;
import com.android.connectivity.aidl.INetworkAgent;
import com.android.internal.net.LegacyVpnInfo;
import com.android.internal.net.VpnConfig;
import com.android.internal.net.VpnInfo;
@@ -164,7 +165,7 @@ interface IConnectivityManager
void declareNetworkRequestUnfulfillable(in NetworkRequest request);
Network registerNetworkAgent(in Messenger messenger, in NetworkInfo ni, in LinkProperties lp,
Network registerNetworkAgent(in INetworkAgent na, in NetworkInfo ni, in LinkProperties lp,
in NetworkCapabilities nc, int score, in NetworkAgentConfig config,
in int factorySerialNumber);

View File

@@ -29,11 +29,12 @@ import android.os.ConditionVariable;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import com.android.connectivity.aidl.INetworkAgent;
import com.android.connectivity.aidl.INetworkAgentRegistry;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.AsyncChannel;
import com.android.internal.util.Protocol;
import java.lang.annotation.Retention;
@@ -94,12 +95,18 @@ public abstract class NetworkAgent {
@Nullable
private volatile Network mNetwork;
@Nullable
private volatile INetworkAgentRegistry mRegistry;
private interface RegistryAction {
void execute(@NonNull INetworkAgentRegistry registry) throws RemoteException;
}
private final Handler mHandler;
private volatile AsyncChannel mAsyncChannel;
private final String LOG_TAG;
private static final boolean DBG = true;
private static final boolean VDBG = false;
private final ArrayList<Message> mPreConnectedQueue = new ArrayList<Message>();
private final ArrayList<RegistryAction> mPreConnectedQueue = new ArrayList<>();
private volatile long mLastBwRefreshTime = 0;
private static final long BW_REFRESH_MIN_WIN_MS = 500;
private boolean mBandwidthUpdateScheduled = false;
@@ -329,6 +336,17 @@ public abstract class NetworkAgent {
*/
public static final int CMD_REMOVE_KEEPALIVE_PACKET_FILTER = BASE + 17;
/**
* Sent by ConnectivityService to the NetworkAgent to complete the bidirectional connection.
* obj = INetworkAgentRegistry
*/
private static final int EVENT_AGENT_CONNECTED = BASE + 18;
/**
* Sent by ConnectivityService to the NetworkAgent to inform the agent that it was disconnected.
*/
private static final int EVENT_AGENT_DISCONNECTED = BASE + 19;
private static NetworkInfo getLegacyNetworkInfo(final NetworkAgentConfig config) {
// The subtype can be changed with (TODO) setLegacySubtype, but it starts
// with 0 (TelephonyManager.NETWORK_TYPE_UNKNOWN) and an empty description.
@@ -402,36 +420,33 @@ public abstract class NetworkAgent {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
if (mAsyncChannel != null) {
case EVENT_AGENT_CONNECTED: {
if (mRegistry != null) {
log("Received new connection while already connected!");
} else {
if (VDBG) log("NetworkAgent fully connected");
AsyncChannel ac = new AsyncChannel();
ac.connected(null, this, msg.replyTo);
ac.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
AsyncChannel.STATUS_SUCCESSFUL);
synchronized (mPreConnectedQueue) {
mAsyncChannel = ac;
for (Message m : mPreConnectedQueue) {
ac.sendMessage(m);
final INetworkAgentRegistry registry = (INetworkAgentRegistry) msg.obj;
mRegistry = registry;
for (RegistryAction a : mPreConnectedQueue) {
try {
a.execute(registry);
} catch (RemoteException e) {
Log.wtf(LOG_TAG, "Communication error with registry", e);
// Fall through
}
}
mPreConnectedQueue.clear();
}
}
break;
}
case AsyncChannel.CMD_CHANNEL_DISCONNECT: {
if (VDBG) log("CMD_CHANNEL_DISCONNECT");
if (mAsyncChannel != null) mAsyncChannel.disconnect();
break;
}
case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
case EVENT_AGENT_DISCONNECTED: {
if (DBG) log("NetworkAgent channel lost");
// let the client know CS is done with us.
onNetworkUnwanted();
synchronized (mPreConnectedQueue) {
mAsyncChannel = null;
mRegistry = null;
}
break;
}
@@ -494,15 +509,7 @@ public abstract class NetworkAgent {
}
case CMD_SET_SIGNAL_STRENGTH_THRESHOLDS: {
ArrayList<Integer> thresholds =
((Bundle) msg.obj).getIntegerArrayList("thresholds");
// TODO: Change signal strength thresholds API to use an ArrayList<Integer>
// rather than convert to int[].
int[] intThresholds = new int[(thresholds != null) ? thresholds.size() : 0];
for (int i = 0; i < intThresholds.length; i++) {
intThresholds[i] = thresholds.get(i);
}
onSignalStrengthThresholdsUpdated(intThresholds);
onSignalStrengthThresholdsUpdated((int[]) msg.obj);
break;
}
case CMD_PREVENT_AUTOMATIC_RECONNECT: {
@@ -541,7 +548,7 @@ public abstract class NetworkAgent {
}
final ConnectivityManager cm = (ConnectivityManager) mInitialConfiguration.context
.getSystemService(Context.CONNECTIVITY_SERVICE);
mNetwork = cm.registerNetworkAgent(new Messenger(mHandler),
mNetwork = cm.registerNetworkAgent(new NetworkAgentBinder(mHandler),
new NetworkInfo(mInitialConfiguration.info),
mInitialConfiguration.properties, mInitialConfiguration.capabilities,
mInitialConfiguration.score, mInitialConfiguration.config, providerId);
@@ -550,6 +557,95 @@ public abstract class NetworkAgent {
return mNetwork;
}
private static class NetworkAgentBinder extends INetworkAgent.Stub {
private final Handler mHandler;
private NetworkAgentBinder(Handler handler) {
mHandler = handler;
}
@Override
public void onRegistered(@NonNull INetworkAgentRegistry registry) {
mHandler.sendMessage(mHandler.obtainMessage(EVENT_AGENT_CONNECTED, registry));
}
@Override
public void onDisconnected() {
mHandler.sendMessage(mHandler.obtainMessage(EVENT_AGENT_DISCONNECTED));
}
@Override
public void onBandwidthUpdateRequested() {
mHandler.sendMessage(mHandler.obtainMessage(CMD_REQUEST_BANDWIDTH_UPDATE));
}
@Override
public void onValidationStatusChanged(
int validationStatus, @Nullable String captivePortalUrl) {
// TODO: consider using a parcelable as argument when the interface is structured
Bundle redirectUrlBundle = new Bundle();
redirectUrlBundle.putString(NetworkAgent.REDIRECT_URL_KEY, captivePortalUrl);
mHandler.sendMessage(mHandler.obtainMessage(CMD_REPORT_NETWORK_STATUS,
validationStatus, 0, redirectUrlBundle));
}
@Override
public void onSaveAcceptUnvalidated(boolean acceptUnvalidated) {
mHandler.sendMessage(mHandler.obtainMessage(CMD_SAVE_ACCEPT_UNVALIDATED,
acceptUnvalidated ? 1 : 0, 0));
}
@Override
public void onStartNattSocketKeepalive(int slot, int intervalDurationMs,
@NonNull NattKeepalivePacketData packetData) {
mHandler.sendMessage(mHandler.obtainMessage(CMD_START_SOCKET_KEEPALIVE,
slot, intervalDurationMs, packetData));
}
@Override
public void onStartTcpSocketKeepalive(int slot, int intervalDurationMs,
@NonNull TcpKeepalivePacketData packetData) {
mHandler.sendMessage(mHandler.obtainMessage(CMD_START_SOCKET_KEEPALIVE,
slot, intervalDurationMs, packetData));
}
@Override
public void onStopSocketKeepalive(int slot) {
mHandler.sendMessage(mHandler.obtainMessage(CMD_STOP_SOCKET_KEEPALIVE, slot, 0));
}
@Override
public void onSignalStrengthThresholdsUpdated(@NonNull int[] thresholds) {
mHandler.sendMessage(mHandler.obtainMessage(
CMD_SET_SIGNAL_STRENGTH_THRESHOLDS, thresholds));
}
@Override
public void onPreventAutomaticReconnect() {
mHandler.sendMessage(mHandler.obtainMessage(CMD_PREVENT_AUTOMATIC_RECONNECT));
}
@Override
public void onAddNattKeepalivePacketFilter(int slot,
@NonNull NattKeepalivePacketData packetData) {
mHandler.sendMessage(mHandler.obtainMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER,
slot, 0, packetData));
}
@Override
public void onAddTcpKeepalivePacketFilter(int slot,
@NonNull TcpKeepalivePacketData packetData) {
mHandler.sendMessage(mHandler.obtainMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER,
slot, 0, packetData));
}
@Override
public void onRemoveKeepalivePacketFilter(int slot) {
mHandler.sendMessage(mHandler.obtainMessage(CMD_REMOVE_KEEPALIVE_PACKET_FILTER,
slot, 0));
}
}
/**
* Register this network agent with a testing harness.
*
@@ -559,13 +655,13 @@ public abstract class NetworkAgent {
*
* @hide
*/
public Messenger registerForTest(final Network network) {
public INetworkAgent registerForTest(final Network network) {
log("Registering NetworkAgent for test");
synchronized (mRegisterLock) {
mNetwork = network;
mInitialConfiguration = null;
}
return new Messenger(mHandler);
return new NetworkAgentBinder(mHandler);
}
/**
@@ -589,29 +685,17 @@ public abstract class NetworkAgent {
return mNetwork;
}
private void queueOrSendMessage(int what, Object obj) {
queueOrSendMessage(what, 0, 0, obj);
}
private void queueOrSendMessage(int what, int arg1, int arg2) {
queueOrSendMessage(what, arg1, arg2, null);
}
private void queueOrSendMessage(int what, int arg1, int arg2, Object obj) {
Message msg = Message.obtain();
msg.what = what;
msg.arg1 = arg1;
msg.arg2 = arg2;
msg.obj = obj;
queueOrSendMessage(msg);
}
private void queueOrSendMessage(Message msg) {
private void queueOrSendMessage(@NonNull RegistryAction action) {
synchronized (mPreConnectedQueue) {
if (mAsyncChannel != null) {
mAsyncChannel.sendMessage(msg);
if (mRegistry != null) {
try {
action.execute(mRegistry);
} catch (RemoteException e) {
Log.wtf(LOG_TAG, "Error executing registry action", e);
// Fall through: the channel is asynchronous and does not report errors back
}
} else {
mPreConnectedQueue.add(msg);
mPreConnectedQueue.add(action);
}
}
}
@@ -622,7 +706,8 @@ public abstract class NetworkAgent {
*/
public final void sendLinkProperties(@NonNull LinkProperties linkProperties) {
Objects.requireNonNull(linkProperties);
queueOrSendMessage(EVENT_NETWORK_PROPERTIES_CHANGED, new LinkProperties(linkProperties));
final LinkProperties lp = new LinkProperties(linkProperties);
queueOrSendMessage(reg -> reg.sendLinkProperties(lp));
}
/**
@@ -647,9 +732,7 @@ public abstract class NetworkAgent {
public final void setUnderlyingNetworks(@Nullable List<Network> underlyingNetworks) {
final ArrayList<Network> underlyingArray = (underlyingNetworks != null)
? new ArrayList<>(underlyingNetworks) : null;
final Bundle bundle = new Bundle();
bundle.putParcelableArrayList(UNDERLYING_NETWORKS_KEY, underlyingArray);
queueOrSendMessage(EVENT_UNDERLYING_NETWORKS_CHANGED, bundle);
queueOrSendMessage(reg -> reg.sendUnderlyingNetworks(underlyingArray));
}
/**
@@ -659,7 +742,7 @@ public abstract class NetworkAgent {
public void markConnected() {
mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null /* reason */,
mNetworkInfo.getExtraInfo());
queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo);
queueOrSendNetworkInfo(mNetworkInfo);
}
/**
@@ -672,7 +755,7 @@ public abstract class NetworkAgent {
// When unregistering an agent nobody should use the extrainfo (or reason) any more.
mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null /* reason */,
null /* extraInfo */);
queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo);
queueOrSendNetworkInfo(mNetworkInfo);
}
/**
@@ -689,7 +772,7 @@ public abstract class NetworkAgent {
@Deprecated
public void setLegacySubtype(final int legacySubtype, @NonNull final String legacySubtypeName) {
mNetworkInfo.setSubtype(legacySubtype, legacySubtypeName);
queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo);
queueOrSendNetworkInfo(mNetworkInfo);
}
/**
@@ -711,7 +794,7 @@ public abstract class NetworkAgent {
@Deprecated
public void setLegacyExtraInfo(@Nullable final String extraInfo) {
mNetworkInfo.setExtraInfo(extraInfo);
queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo);
queueOrSendNetworkInfo(mNetworkInfo);
}
/**
@@ -720,7 +803,11 @@ public abstract class NetworkAgent {
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
public final void sendNetworkInfo(NetworkInfo networkInfo) {
queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, new NetworkInfo(networkInfo));
queueOrSendNetworkInfo(new NetworkInfo(networkInfo));
}
private void queueOrSendNetworkInfo(NetworkInfo networkInfo) {
queueOrSendMessage(reg -> reg.sendNetworkInfo(networkInfo));
}
/**
@@ -731,8 +818,8 @@ public abstract class NetworkAgent {
Objects.requireNonNull(networkCapabilities);
mBandwidthUpdatePending.set(false);
mLastBwRefreshTime = System.currentTimeMillis();
queueOrSendMessage(EVENT_NETWORK_CAPABILITIES_CHANGED,
new NetworkCapabilities(networkCapabilities));
final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
queueOrSendMessage(reg -> reg.sendNetworkCapabilities(nc));
}
/**
@@ -744,7 +831,7 @@ public abstract class NetworkAgent {
if (score < 0) {
throw new IllegalArgumentException("Score must be >= 0");
}
queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, score, 0);
queueOrSendMessage(reg -> reg.sendScore(score));
}
/**
@@ -784,9 +871,8 @@ public abstract class NetworkAgent {
* @hide should move to NetworkAgentConfig.
*/
public void explicitlySelected(boolean explicitlySelected, boolean acceptUnvalidated) {
queueOrSendMessage(EVENT_SET_EXPLICITLY_SELECTED,
explicitlySelected ? 1 : 0,
acceptUnvalidated ? 1 : 0);
queueOrSendMessage(reg -> reg.sendExplicitlySelected(
explicitlySelected, acceptUnvalidated));
}
/**
@@ -909,7 +995,7 @@ public abstract class NetworkAgent {
*/
public final void sendSocketKeepaliveEvent(int slot,
@SocketKeepalive.KeepaliveEvent int event) {
queueOrSendMessage(EVENT_SOCKET_KEEPALIVE, slot, event);
queueOrSendMessage(reg -> reg.sendSocketKeepaliveEvent(slot, event));
}
/** @hide TODO delete once callers have moved to sendSocketKeepaliveEvent */
public void onSocketKeepaliveEvent(int slot, int reason) {

View File

@@ -174,6 +174,7 @@ import android.util.SparseArray;
import android.util.SparseIntArray;
import android.util.Xml;
import com.android.connectivity.aidl.INetworkAgent;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -2018,7 +2019,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
void handleRestrictBackgroundChanged(boolean restrictBackground) {
if (mRestrictBackground == restrictBackground) return;
for (final NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
for (final NetworkAgentInfo nai : mNetworkAgentInfos) {
final boolean curMetered = nai.networkCapabilities.isMetered();
maybeNotifyNetworkBlocked(nai, curMetered, curMetered, mRestrictBackground,
restrictBackground);
@@ -2726,7 +2727,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
*/
private NetworkAgentInfo[] networksSortedById() {
NetworkAgentInfo[] networks = new NetworkAgentInfo[0];
networks = mNetworkAgentInfos.values().toArray(networks);
networks = mNetworkAgentInfos.toArray(networks);
Arrays.sort(networks, Comparator.comparingInt(nai -> nai.network.getNetId()));
return networks;
}
@@ -2772,11 +2773,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
handleAsyncChannelHalfConnect(msg);
break;
}
case AsyncChannel.CMD_CHANNEL_DISCONNECT: {
NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
if (nai != null) nai.asyncChannel.disconnect();
break;
}
case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
handleAsyncChannelDisconnected(msg);
break;
@@ -2786,8 +2782,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
private void maybeHandleNetworkAgentMessage(Message msg) {
NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
if (nai == null) {
final Pair<NetworkAgentInfo, Object> arg = (Pair<NetworkAgentInfo, Object>) msg.obj;
final NetworkAgentInfo nai = arg.first;
if (!mNetworkAgentInfos.contains(nai)) {
if (VDBG) {
log(String.format("%s from unknown NetworkAgent", eventName(msg.what)));
}
@@ -2796,7 +2793,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
switch (msg.what) {
case NetworkAgent.EVENT_NETWORK_CAPABILITIES_CHANGED: {
NetworkCapabilities networkCapabilities = (NetworkCapabilities) msg.obj;
NetworkCapabilities networkCapabilities = (NetworkCapabilities) arg.second;
if (networkCapabilities.hasConnectivityManagedCapability()) {
Log.wtf(TAG, "BUG: " + nai + " has CS-managed capability.");
}
@@ -2813,13 +2810,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
break;
}
case NetworkAgent.EVENT_NETWORK_PROPERTIES_CHANGED: {
LinkProperties newLp = (LinkProperties) msg.obj;
LinkProperties newLp = (LinkProperties) arg.second;
processLinkPropertiesFromAgent(nai, newLp);
handleUpdateLinkProperties(nai, newLp);
break;
}
case NetworkAgent.EVENT_NETWORK_INFO_CHANGED: {
NetworkInfo info = (NetworkInfo) msg.obj;
NetworkInfo info = (NetworkInfo) arg.second;
updateNetworkInfo(nai, info);
break;
}
@@ -2844,7 +2841,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
break;
}
case NetworkAgent.EVENT_SOCKET_KEEPALIVE: {
mKeepaliveTracker.handleEventSocketKeepalive(nai, msg);
mKeepaliveTracker.handleEventSocketKeepalive(nai, msg.arg1, msg.arg2);
break;
}
case NetworkAgent.EVENT_UNDERLYING_NETWORKS_CHANGED: {
@@ -2855,7 +2852,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
final ArrayList<Network> underlying;
try {
underlying = ((Bundle) msg.obj).getParcelableArrayList(
underlying = ((Bundle) arg.second).getParcelableArrayList(
NetworkAgent.UNDERLYING_NETWORKS_KEY);
} catch (NullPointerException | ClassCastException e) {
break;
@@ -2934,8 +2931,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (nai.lastCaptivePortalDetected &&
Settings.Global.CAPTIVE_PORTAL_MODE_AVOID == getCaptivePortalMode()) {
if (DBG) log("Avoiding captive portal network: " + nai.toShortString());
nai.asyncChannel.sendMessage(
NetworkAgent.CMD_PREVENT_AUTOMATIC_RECONNECT);
nai.onPreventAutomaticReconnect();
teardownUnneededNetwork(nai);
break;
}
@@ -3027,13 +3023,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
updateInetCondition(nai);
// Let the NetworkAgent know the state of its network
Bundle redirectUrlBundle = new Bundle();
redirectUrlBundle.putString(NetworkAgent.REDIRECT_URL_KEY, redirectUrl);
// TODO: Evaluate to update partial connectivity to status to NetworkAgent.
nai.asyncChannel.sendMessage(
NetworkAgent.CMD_REPORT_NETWORK_STATUS,
(valid ? NetworkAgent.VALID_NETWORK : NetworkAgent.INVALID_NETWORK),
0, redirectUrlBundle);
nai.onValidationStatusChanged(
valid ? NetworkAgent.VALID_NETWORK : NetworkAgent.INVALID_NETWORK,
redirectUrl);
// If NetworkMonitor detects partial connectivity before
// EVENT_PROMPT_UNVALIDATED arrives, show the partial connectivity notification
@@ -3067,6 +3060,14 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
break;
}
case NetworkAgentInfo.EVENT_AGENT_REGISTERED: {
handleNetworkAgentRegistered(msg);
break;
}
case NetworkAgentInfo.EVENT_AGENT_DISCONNECTED: {
handleNetworkAgentDisconnected(msg);
break;
}
}
return true;
}
@@ -3243,7 +3244,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
private void handlePrivateDnsSettingsChanged() {
final PrivateDnsConfig cfg = mDnsManager.getPrivateDnsConfig();
for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
for (NetworkAgentInfo nai : mNetworkAgentInfos) {
handlePerNetworkPrivateDnsConfig(nai, cfg);
if (networkRequiresPrivateDnsValidation(nai)) {
handleUpdateLinkProperties(nai, new LinkProperties(nai.linkProperties));
@@ -3341,7 +3342,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
private void handleAsyncChannelHalfConnect(Message msg) {
ensureRunningOnConnectivityServiceThread();
final AsyncChannel ac = (AsyncChannel) msg.obj;
if (mNetworkProviderInfos.containsKey(msg.replyTo)) {
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
if (VDBG) log("NetworkFactory connected");
@@ -3353,39 +3353,45 @@ public class ConnectivityService extends IConnectivityManager.Stub
loge("Error connecting NetworkFactory");
mNetworkProviderInfos.remove(msg.obj);
}
} else if (mNetworkAgentInfos.containsKey(msg.replyTo)) {
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
if (VDBG) log("NetworkAgent connected");
// A network agent has requested a connection. Establish the connection.
mNetworkAgentInfos.get(msg.replyTo).asyncChannel.
sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
} else {
loge("Error connecting NetworkAgent");
NetworkAgentInfo nai = mNetworkAgentInfos.remove(msg.replyTo);
if (nai != null) {
final boolean wasDefault = isDefaultNetwork(nai);
synchronized (mNetworkForNetId) {
mNetworkForNetId.remove(nai.network.getNetId());
}
mNetIdManager.releaseNetId(nai.network.getNetId());
// Just in case.
mLegacyTypeTracker.remove(nai, wasDefault);
}
}
private void handleNetworkAgentRegistered(Message msg) {
final NetworkAgentInfo nai = (NetworkAgentInfo) msg.obj;
if (!mNetworkAgentInfos.contains(nai)) {
return;
}
if (msg.arg1 == NetworkAgentInfo.ARG_AGENT_SUCCESS) {
if (VDBG) log("NetworkAgent registered");
} else {
loge("Error connecting NetworkAgent");
mNetworkAgentInfos.remove(nai);
if (nai != null) {
final boolean wasDefault = isDefaultNetwork(nai);
synchronized (mNetworkForNetId) {
mNetworkForNetId.remove(nai.network.getNetId());
}
mNetIdManager.releaseNetId(nai.network.getNetId());
// Just in case.
mLegacyTypeTracker.remove(nai, wasDefault);
}
}
}
// This is a no-op if it's called with a message designating a network that has
private void handleNetworkAgentDisconnected(Message msg) {
NetworkAgentInfo nai = (NetworkAgentInfo) msg.obj;
if (mNetworkAgentInfos.contains(nai)) {
disconnectAndDestroyNetwork(nai);
}
}
// This is a no-op if it's called with a message designating a provider that has
// already been destroyed, because its reference will not be found in the relevant
// maps.
private void handleAsyncChannelDisconnected(Message msg) {
NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
if (nai != null) {
disconnectAndDestroyNetwork(nai);
} else {
NetworkProviderInfo npi = mNetworkProviderInfos.remove(msg.replyTo);
if (DBG && npi != null) log("unregisterNetworkFactory for " + npi.name);
}
NetworkProviderInfo npi = mNetworkProviderInfos.remove(msg.replyTo);
if (DBG && npi != null) log("unregisterNetworkFactory for " + npi.name);
}
// Destroys a network, remove references to it from the internal state managed by
@@ -3429,7 +3435,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
wakeupModifyInterface(iface, nai.networkCapabilities, false);
}
nai.networkMonitor().notifyNetworkDisconnected();
mNetworkAgentInfos.remove(nai.messenger);
mNetworkAgentInfos.remove(nai);
nai.clatd.update();
synchronized (mNetworkForNetId) {
// Remove the NetworkAgent, but don't mark the netId as
@@ -3537,7 +3543,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
mNetworkRequests.put(nri.request, nri);
mNetworkRequestInfoLogs.log("REGISTER " + nri);
if (nri.request.isListen()) {
for (NetworkAgentInfo network : mNetworkAgentInfos.values()) {
for (NetworkAgentInfo network : mNetworkAgentInfos) {
if (nri.request.networkCapabilities.hasSignalStrength() &&
network.satisfiesImmutableCapabilitiesOf(nri.request)) {
updateSignalStrengthThresholds(network, "REGISTER", nri.request);
@@ -3753,7 +3759,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
} else {
// listens don't have a singular affectedNetwork. Check all networks to see
// if this listen request applies and remove it.
for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
for (NetworkAgentInfo nai : mNetworkAgentInfos) {
nai.removeRequest(nri.request.requestId);
if (nri.request.networkCapabilities.hasSignalStrength() &&
nai.satisfiesImmutableCapabilitiesOf(nri.request)) {
@@ -3826,13 +3832,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
if (always) {
nai.asyncChannel.sendMessage(
NetworkAgent.CMD_SAVE_ACCEPT_UNVALIDATED, encodeBool(accept));
nai.onSaveAcceptUnvalidated(accept);
}
if (!accept) {
// Tell the NetworkAgent to not automatically reconnect to the network.
nai.asyncChannel.sendMessage(NetworkAgent.CMD_PREVENT_AUTOMATIC_RECONNECT);
nai.onPreventAutomaticReconnect();
// Teardown the network.
teardownUnneededNetwork(nai);
}
@@ -3863,13 +3868,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
// TODO: Use the current design or save the user choice into IpMemoryStore.
if (always) {
nai.asyncChannel.sendMessage(
NetworkAgent.CMD_SAVE_ACCEPT_UNVALIDATED, encodeBool(accept));
nai.onSaveAcceptUnvalidated(accept);
}
if (!accept) {
// Tell the NetworkAgent to not automatically reconnect to the network.
nai.asyncChannel.sendMessage(NetworkAgent.CMD_PREVENT_AUTOMATIC_RECONNECT);
nai.onPreventAutomaticReconnect();
// Tear down the network.
teardownUnneededNetwork(nai);
} else {
@@ -4007,7 +4011,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
private void rematchForAvoidBadWifiUpdate() {
rematchAllNetworksAndRequests();
for (NetworkAgentInfo nai: mNetworkAgentInfos.values()) {
for (NetworkAgentInfo nai: mNetworkAgentInfos) {
if (nai.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
sendUpdatedScoreToFactories(nai);
}
@@ -4150,7 +4154,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
// to a network that provides no or limited connectivity is not useful, because the user
// cannot use that network except through the notification shown by this method, and the
// notification is only shown if the network is explicitly selected by the user.
nai.asyncChannel.sendMessage(NetworkAgent.CMD_PREVENT_AUTOMATIC_RECONNECT);
nai.onPreventAutomaticReconnect();
// TODO: Evaluate if it's needed to wait 8 seconds for triggering notification when
// NetworkMonitor detects the network is partial connectivity. Need to change the design to
@@ -4802,7 +4806,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
return new VpnInfo[0];
}
List<VpnInfo> infoList = new ArrayList<>();
for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
for (NetworkAgentInfo nai : mNetworkAgentInfos) {
VpnInfo info = createVpnInfo(nai);
if (info != null) {
infoList.add(info);
@@ -4903,7 +4907,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
*/
private void propagateUnderlyingNetworkCapabilities(Network updatedNetwork) {
ensureRunningOnConnectivityServiceThread();
for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
for (NetworkAgentInfo nai : mNetworkAgentInfos) {
if (updatedNetwork == null || hasUnderlyingNetwork(nai, updatedNetwork)) {
updateCapabilitiesForNetwork(nai);
}
@@ -5604,7 +5608,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
mAppOpsManager.checkPackage(callerUid, callerPackageName);
}
private ArrayList<Integer> getSignalStrengthThresholds(@NonNull final NetworkAgentInfo nai) {
private int[] getSignalStrengthThresholds(@NonNull final NetworkAgentInfo nai) {
final SortedSet<Integer> thresholds = new TreeSet<>();
synchronized (nai) {
for (final NetworkRequestInfo nri : mNetworkRequests.values()) {
@@ -5616,14 +5620,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
}
return new ArrayList<>(thresholds);
// TODO: use NetworkStackUtils.convertToIntArray after moving it
return ArrayUtils.convertToIntArray(new ArrayList<>(thresholds));
}
private void updateSignalStrengthThresholds(
NetworkAgentInfo nai, String reason, NetworkRequest request) {
ArrayList<Integer> thresholdsArray = getSignalStrengthThresholds(nai);
Bundle thresholds = new Bundle();
thresholds.putIntegerArrayList("thresholds", thresholdsArray);
final int[] thresholdsArray = getSignalStrengthThresholds(nai);
if (VDBG || (DBG && !"CONNECT".equals(reason))) {
String detail;
@@ -5633,12 +5636,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
detail = reason;
}
log(String.format("updateSignalStrengthThresholds: %s, sending %s to %s",
detail, Arrays.toString(thresholdsArray.toArray()), nai.toShortString()));
detail, Arrays.toString(thresholdsArray), nai.toShortString()));
}
nai.asyncChannel.sendMessage(
android.net.NetworkAgent.CMD_SET_SIGNAL_STRENGTH_THRESHOLDS,
0, 0, thresholds);
nai.onSignalStrengthThresholdsUpdated(thresholdsArray);
}
private void ensureValidNetworkSpecifier(NetworkCapabilities nc) {
@@ -5748,7 +5749,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
nai = mNetworkForNetId.get(network.getNetId());
}
if (nai != null) {
nai.asyncChannel.sendMessage(android.net.NetworkAgent.CMD_REQUEST_BANDWIDTH_UPDATE);
nai.onBandwidthUpdateRequested();
synchronized (mBandwidthRequests) {
final int uid = mDeps.getCallingUid();
Integer uidReqs = mBandwidthRequests.get(uid);
@@ -5991,7 +5992,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
// NetworkAgentInfo keyed off its connecting messenger
// TODO - eval if we can reduce the number of lists/hashmaps/sparsearrays
// NOTE: Only should be accessed on ConnectivityServiceThread, except dump().
private final HashMap<Messenger, NetworkAgentInfo> mNetworkAgentInfos = new HashMap<>();
private final ArraySet<NetworkAgentInfo> mNetworkAgentInfos = new ArraySet<>();
@GuardedBy("mBlockedAppUids")
private final HashSet<Integer> mBlockedAppUids = new HashSet<>();
@@ -6039,17 +6040,17 @@ public class ConnectivityService extends IConnectivityManager.Stub
/**
* Register a new agent. {@see #registerNetworkAgent} below.
*/
public Network registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
public Network registerNetworkAgent(INetworkAgent na, NetworkInfo networkInfo,
LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
int currentScore, NetworkAgentConfig networkAgentConfig) {
return registerNetworkAgent(messenger, networkInfo, linkProperties, networkCapabilities,
return registerNetworkAgent(na, networkInfo, linkProperties, networkCapabilities,
currentScore, networkAgentConfig, NetworkProvider.ID_NONE);
}
/**
* Register a new agent with ConnectivityService to handle a network.
*
* @param messenger a messenger for ConnectivityService to contact the agent asynchronously.
* @param na a reference 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
@@ -6062,7 +6063,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
* @param providerId the ID of the provider owning this NetworkAgent.
* @return the network created for this agent.
*/
public Network registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
public Network registerNetworkAgent(INetworkAgent na, NetworkInfo networkInfo,
LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
int currentScore, NetworkAgentConfig networkAgentConfig, int providerId) {
if (networkCapabilities.hasTransport(TRANSPORT_TEST)) {
@@ -6074,14 +6075,14 @@ public class ConnectivityService extends IConnectivityManager.Stub
final int uid = mDeps.getCallingUid();
final long token = Binder.clearCallingIdentity();
try {
return registerNetworkAgentInternal(messenger, networkInfo, linkProperties,
return registerNetworkAgentInternal(na, networkInfo, linkProperties,
networkCapabilities, currentScore, networkAgentConfig, providerId, uid);
} finally {
Binder.restoreCallingIdentity(token);
}
}
private Network registerNetworkAgentInternal(Messenger messenger, NetworkInfo networkInfo,
private Network registerNetworkAgentInternal(INetworkAgent na, NetworkInfo networkInfo,
LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
int currentScore, NetworkAgentConfig networkAgentConfig, int providerId, int uid) {
if (networkCapabilities.hasTransport(TRANSPORT_TEST)) {
@@ -6097,7 +6098,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
// TODO: Instead of passing mDefaultRequest, provide an API to determine whether a Network
// satisfies mDefaultRequest.
final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
final NetworkAgentInfo nai = new NetworkAgentInfo(na,
new Network(mNetIdManager.reserveNetId()), new NetworkInfo(networkInfo), lp, nc,
currentScore, mContext, mTrackerHandler, new NetworkAgentConfig(networkAgentConfig),
this, mNetd, mDnsResolver, mNMS, providerId, uid);
@@ -6115,7 +6116,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
nai.network, name, new NetworkMonitorCallbacks(nai));
// NetworkAgentInfo registration will finish when the NetworkMonitor is created.
// If the network disconnects or sends any other event before that, messages are deferred by
// NetworkAgent until nai.asyncChannel.connect(), which will be called when finalizing the
// NetworkAgent until nai.connect(), which will be called when finalizing the
// registration.
return nai.network;
}
@@ -6123,7 +6124,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
private void handleRegisterNetworkAgent(NetworkAgentInfo nai, INetworkMonitor networkMonitor) {
nai.onNetworkMonitorCreated(networkMonitor);
if (VDBG) log("Got NetworkAgent Messenger");
mNetworkAgentInfos.put(nai.messenger, nai);
mNetworkAgentInfos.add(nai);
synchronized (mNetworkForNetId) {
mNetworkForNetId.put(nai.network.getNetId(), nai);
}
@@ -6133,7 +6134,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
} catch (RemoteException e) {
e.rethrowAsRuntimeException();
}
nai.asyncChannel.connect(mContext, mTrackerHandler, nai.messenger);
nai.notifyRegistered();
NetworkInfo networkInfo = nai.networkInfo;
updateNetworkInfo(nai, networkInfo);
updateUids(nai, null, nai.networkCapabilities);
@@ -6946,7 +6947,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
break;
}
}
nai.asyncChannel.disconnect();
nai.disconnect();
}
private void handleLingerComplete(NetworkAgentInfo oldNetwork) {
@@ -7136,7 +7137,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
// Gather the list of all relevant agents and sort them by score.
final ArrayList<NetworkAgentInfo> nais = new ArrayList<>();
for (final NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
for (final NetworkAgentInfo nai : mNetworkAgentInfos) {
if (!nai.everConnected) continue;
nais.add(nai);
}
@@ -7171,7 +7172,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
private void applyNetworkReassignment(@NonNull final NetworkReassignment changes,
final long now) {
final Collection<NetworkAgentInfo> nais = mNetworkAgentInfos.values();
final Collection<NetworkAgentInfo> nais = mNetworkAgentInfos;
// Since most of the time there are only 0 or 1 background networks, it would probably
// be more efficient to just use an ArrayList here. TODO : measure performance
@@ -7264,7 +7265,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
updateLegacyTypeTrackerAndVpnLockdownForRematch(oldDefaultNetwork, newDefaultNetwork, nais);
// Tear down all unneeded networks.
for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
for (NetworkAgentInfo nai : mNetworkAgentInfos) {
if (unneeded(nai, UnneededFor.TEARDOWN)) {
if (nai.getLingerExpiry() > 0) {
// This network has active linger timers and no requests, but is not
@@ -7501,7 +7502,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
// This has to happen after matching the requests, because callbacks are just requests.
notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_PRECHECK);
} else if (state == NetworkInfo.State.DISCONNECTED) {
networkAgent.asyncChannel.disconnect();
networkAgent.disconnect();
if (networkAgent.isVPN()) {
updateUids(networkAgent, networkAgent.networkCapabilities, null);
}
@@ -7589,7 +7590,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
* @param newRules The new rules to apply.
*/
private void maybeNotifyNetworkBlockedForNewUidRules(int uid, int newRules) {
for (final NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
for (final NetworkAgentInfo nai : mNetworkAgentInfos) {
final boolean metered = nai.networkCapabilities.isMetered();
final boolean oldBlocked, newBlocked;
// TODO: Consider that doze mode or turn on/off battery saver would deliver lots of uid
@@ -7695,7 +7696,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
ensureRunningOnConnectivityServiceThread();
ArrayList<Network> defaultNetworks = new ArrayList<>();
NetworkAgentInfo defaultNetwork = getDefaultNetwork();
for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
for (NetworkAgentInfo nai : mNetworkAgentInfos) {
if (nai.everConnected && (nai == defaultNetwork || nai.isVPN())) {
defaultNetworks.add(nai.network);
}
@@ -8429,7 +8430,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
return false;
}
for (NetworkAgentInfo virtual : mNetworkAgentInfos.values()) {
for (NetworkAgentInfo virtual : mNetworkAgentInfos) {
if (virtual.supportsUnderlyingNetworks()
&& virtual.networkCapabilities.getOwnerUid() == callbackUid
&& ArrayUtils.contains(virtual.declaredUnderlyingNetworks, nai.network)) {

View File

@@ -18,10 +18,7 @@ package com.android.server.connectivity;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.net.NattSocketKeepalive.NATT_PORT;
import static android.net.NetworkAgent.CMD_ADD_KEEPALIVE_PACKET_FILTER;
import static android.net.NetworkAgent.CMD_REMOVE_KEEPALIVE_PACKET_FILTER;
import static android.net.NetworkAgent.CMD_START_SOCKET_KEEPALIVE;
import static android.net.NetworkAgent.CMD_STOP_SOCKET_KEEPALIVE;
import static android.net.SocketKeepalive.BINDER_DIED;
import static android.net.SocketKeepalive.DATA_RECEIVED;
import static android.net.SocketKeepalive.ERROR_INSUFFICIENT_RESOURCES;
@@ -330,10 +327,9 @@ public class KeepaliveTracker {
Log.d(TAG, "Starting keepalive " + mSlot + " on " + mNai.toShortString());
switch (mType) {
case TYPE_NATT:
mNai.asyncChannel.sendMessage(
CMD_ADD_KEEPALIVE_PACKET_FILTER, slot, 0 /* Unused */, mPacket);
mNai.asyncChannel
.sendMessage(CMD_START_SOCKET_KEEPALIVE, slot, mInterval, mPacket);
final NattKeepalivePacketData nattData = (NattKeepalivePacketData) mPacket;
mNai.onAddNattKeepalivePacketFilter(slot, nattData);
mNai.onStartNattSocketKeepalive(slot, mInterval, nattData);
break;
case TYPE_TCP:
try {
@@ -342,11 +338,10 @@ public class KeepaliveTracker {
handleStopKeepalive(mNai, mSlot, ERROR_INVALID_SOCKET);
return;
}
mNai.asyncChannel.sendMessage(
CMD_ADD_KEEPALIVE_PACKET_FILTER, slot, 0 /* Unused */, mPacket);
final TcpKeepalivePacketData tcpData = (TcpKeepalivePacketData) mPacket;
mNai.onAddTcpKeepalivePacketFilter(slot, tcpData);
// TODO: check result from apf and notify of failure as needed.
mNai.asyncChannel
.sendMessage(CMD_START_SOCKET_KEEPALIVE, slot, mInterval, mPacket);
mNai.onStartTcpSocketKeepalive(slot, mInterval, tcpData);
break;
default:
Log.wtf(TAG, "Starting keepalive with unknown type: " + mType);
@@ -394,9 +389,8 @@ public class KeepaliveTracker {
mTcpController.stopSocketMonitor(mSlot);
// fall through
case TYPE_NATT:
mNai.asyncChannel.sendMessage(CMD_STOP_SOCKET_KEEPALIVE, mSlot);
mNai.asyncChannel.sendMessage(CMD_REMOVE_KEEPALIVE_PACKET_FILTER,
mSlot);
mNai.onStopSocketKeepalive(mSlot);
mNai.onRemoveKeepalivePacketFilter(mSlot);
break;
default:
Log.wtf(TAG, "Stopping keepalive with unknown type: " + mType);
@@ -548,17 +542,13 @@ public class KeepaliveTracker {
}
/** Handle keepalive events from lower layer. */
public void handleEventSocketKeepalive(@NonNull NetworkAgentInfo nai,
@NonNull Message message) {
int slot = message.arg1;
int reason = message.arg2;
public void handleEventSocketKeepalive(@NonNull NetworkAgentInfo nai, int slot, int reason) {
KeepaliveInfo ki = null;
try {
ki = mKeepalives.get(nai).get(slot);
} catch(NullPointerException e) {}
if (ki == null) {
Log.e(TAG, "Event " + message.what + "," + slot + "," + reason
Log.e(TAG, "Event " + NetworkAgent.EVENT_SOCKET_KEEPALIVE + "," + slot + "," + reason
+ " for unknown keepalive " + slot + " on " + nai.toShortString());
return;
}
@@ -601,7 +591,7 @@ public class KeepaliveTracker {
ki.mStartedState = KeepaliveInfo.NOT_STARTED;
cleanupStoppedKeepalive(nai, slot);
} else {
Log.wtf(TAG, "Event " + message.what + "," + slot + "," + reason
Log.wtf(TAG, "Event " + NetworkAgent.EVENT_SOCKET_KEEPALIVE + "," + slot + "," + reason
+ " for keepalive in wrong state: " + ki.toString());
}
}

View File

@@ -27,25 +27,35 @@ import android.net.IDnsResolver;
import android.net.INetd;
import android.net.INetworkMonitor;
import android.net.LinkProperties;
import android.net.NattKeepalivePacketData;
import android.net.Network;
import android.net.NetworkAgent;
import android.net.NetworkAgentConfig;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkMonitorManager;
import android.net.NetworkRequest;
import android.net.NetworkState;
import android.net.TcpKeepalivePacketData;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.INetworkManagementService;
import android.os.Messenger;
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.Log;
import android.util.Pair;
import android.util.SparseArray;
import com.android.internal.util.AsyncChannel;
import com.android.connectivity.aidl.INetworkAgent;
import com.android.connectivity.aidl.INetworkAgentRegistry;
import com.android.internal.util.WakeupMessage;
import com.android.server.ConnectivityService;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.SortedSet;
import java.util.TreeSet;
@@ -221,6 +231,31 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
*/
public static final int EVENT_NETWORK_LINGER_COMPLETE = 1001;
/**
* Inform ConnectivityService that the agent is half-connected.
* arg1 = ARG_AGENT_SUCCESS or ARG_AGENT_FAILURE
* obj = NetworkAgentInfo
* @hide
*/
public static final int EVENT_AGENT_REGISTERED = 1002;
/**
* Inform ConnectivityService that the agent was disconnected.
* obj = NetworkAgentInfo
* @hide
*/
public static final int EVENT_AGENT_DISCONNECTED = 1003;
/**
* Argument for EVENT_AGENT_HALF_CONNECTED indicating failure.
*/
public static final int ARG_AGENT_FAILURE = 0;
/**
* Argument for EVENT_AGENT_HALF_CONNECTED indicating success.
*/
public static final int ARG_AGENT_SUCCESS = 1;
// All linger timers for this network, sorted by expiry time. A linger timer is added whenever
// a request is moved to a network with a better score, regardless of whether the network is or
// was lingering or not.
@@ -262,8 +297,9 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
// report is generated. Once non-null, it will never be null again.
@Nullable private ConnectivityReport mConnectivityReport;
public final Messenger messenger;
public final AsyncChannel asyncChannel;
public final INetworkAgent networkAgent;
// Only accessed from ConnectivityService handler thread
private final AgentDeathMonitor mDeathMonitor = new AgentDeathMonitor();
public final int factorySerialNumber;
@@ -279,13 +315,12 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
private final Context mContext;
private final Handler mHandler;
public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, Network net, NetworkInfo info,
public NetworkAgentInfo(INetworkAgent na, Network net, NetworkInfo info,
LinkProperties lp, NetworkCapabilities nc, int score, Context context,
Handler handler, NetworkAgentConfig config, ConnectivityService connService, INetd netd,
IDnsResolver dnsResolver, INetworkManagementService nms, int factorySerialNumber,
int creatorUid) {
this.messenger = messenger;
asyncChannel = ac;
networkAgent = na;
network = net;
networkInfo = info;
linkProperties = lp;
@@ -300,6 +335,249 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
this.creatorUid = creatorUid;
}
private class AgentDeathMonitor implements IBinder.DeathRecipient {
@Override
public void binderDied() {
notifyDisconnected();
}
}
/**
* Notify the NetworkAgent that it was registered, and should be unregistered if it dies.
*
* Must be called from the ConnectivityService handler thread. A NetworkAgent can only be
* registered once.
*/
public void notifyRegistered() {
try {
networkAgent.asBinder().linkToDeath(mDeathMonitor, 0);
networkAgent.onRegistered(new NetworkAgentMessageHandler(mHandler));
} catch (RemoteException e) {
Log.e(TAG, "Error registering NetworkAgent", e);
maybeUnlinkDeathMonitor();
mHandler.obtainMessage(EVENT_AGENT_REGISTERED, ARG_AGENT_FAILURE, 0, this)
.sendToTarget();
return;
}
mHandler.obtainMessage(EVENT_AGENT_REGISTERED, ARG_AGENT_SUCCESS, 0, this).sendToTarget();
}
/**
* Disconnect the NetworkAgent. Must be called from the ConnectivityService handler thread.
*/
public void disconnect() {
try {
networkAgent.onDisconnected();
} catch (RemoteException e) {
Log.i(TAG, "Error disconnecting NetworkAgent", e);
// Fall through: it's fine if the remote has died
}
notifyDisconnected();
maybeUnlinkDeathMonitor();
}
private void maybeUnlinkDeathMonitor() {
try {
networkAgent.asBinder().unlinkToDeath(mDeathMonitor, 0);
} catch (NoSuchElementException e) {
// Was not linked: ignore
}
}
private void notifyDisconnected() {
// Note this may be called multiple times if ConnectivityService disconnects while the
// NetworkAgent also dies. ConnectivityService ignores disconnects of already disconnected
// agents.
mHandler.obtainMessage(EVENT_AGENT_DISCONNECTED, this).sendToTarget();
}
/**
* Notify the NetworkAgent that bandwidth update was requested.
*/
public void onBandwidthUpdateRequested() {
try {
networkAgent.onBandwidthUpdateRequested();
} catch (RemoteException e) {
Log.e(TAG, "Error sending bandwidth update request event", e);
}
}
/**
* Notify the NetworkAgent that validation status has changed.
*/
public void onValidationStatusChanged(int validationStatus, @Nullable String captivePortalUrl) {
try {
networkAgent.onValidationStatusChanged(validationStatus, captivePortalUrl);
} catch (RemoteException e) {
Log.e(TAG, "Error sending validation status change event", e);
}
}
/**
* Notify the NetworkAgent that the acceptUnvalidated setting should be saved.
*/
public void onSaveAcceptUnvalidated(boolean acceptUnvalidated) {
try {
networkAgent.onSaveAcceptUnvalidated(acceptUnvalidated);
} catch (RemoteException e) {
Log.e(TAG, "Error sending accept unvalidated event", e);
}
}
/**
* Notify the NetworkAgent that NATT socket keepalive should be started.
*/
public void onStartNattSocketKeepalive(int slot, int intervalDurationMs,
@NonNull NattKeepalivePacketData packetData) {
try {
networkAgent.onStartNattSocketKeepalive(slot, intervalDurationMs, packetData);
} catch (RemoteException e) {
Log.e(TAG, "Error sending NATT socket keepalive start event", e);
}
}
/**
* Notify the NetworkAgent that TCP socket keepalive should be started.
*/
public void onStartTcpSocketKeepalive(int slot, int intervalDurationMs,
@NonNull TcpKeepalivePacketData packetData) {
try {
networkAgent.onStartTcpSocketKeepalive(slot, intervalDurationMs, packetData);
} catch (RemoteException e) {
Log.e(TAG, "Error sending TCP socket keepalive start event", e);
}
}
/**
* Notify the NetworkAgent that socket keepalive should be stopped.
*/
public void onStopSocketKeepalive(int slot) {
try {
networkAgent.onStopSocketKeepalive(slot);
} catch (RemoteException e) {
Log.e(TAG, "Error sending TCP socket keepalive stop event", e);
}
}
/**
* Notify the NetworkAgent that signal strength thresholds should be updated.
*/
public void onSignalStrengthThresholdsUpdated(@NonNull int[] thresholds) {
try {
networkAgent.onSignalStrengthThresholdsUpdated(thresholds);
} catch (RemoteException e) {
Log.e(TAG, "Error sending signal strength thresholds event", e);
}
}
/**
* Notify the NetworkAgent that automatic reconnect should be prevented.
*/
public void onPreventAutomaticReconnect() {
try {
networkAgent.onPreventAutomaticReconnect();
} catch (RemoteException e) {
Log.e(TAG, "Error sending prevent automatic reconnect event", e);
}
}
/**
* Notify the NetworkAgent that a NATT keepalive packet filter should be added.
*/
public void onAddNattKeepalivePacketFilter(int slot,
@NonNull NattKeepalivePacketData packetData) {
try {
networkAgent.onAddNattKeepalivePacketFilter(slot, packetData);
} catch (RemoteException e) {
Log.e(TAG, "Error sending add NATT keepalive packet filter event", e);
}
}
/**
* Notify the NetworkAgent that a TCP keepalive packet filter should be added.
*/
public void onAddTcpKeepalivePacketFilter(int slot,
@NonNull TcpKeepalivePacketData packetData) {
try {
networkAgent.onAddTcpKeepalivePacketFilter(slot, packetData);
} catch (RemoteException e) {
Log.e(TAG, "Error sending add TCP keepalive packet filter event", e);
}
}
/**
* Notify the NetworkAgent that a keepalive packet filter should be removed.
*/
public void onRemoveKeepalivePacketFilter(int slot) {
try {
networkAgent.onRemoveKeepalivePacketFilter(slot);
} catch (RemoteException e) {
Log.e(TAG, "Error sending remove keepalive packet filter event", e);
}
}
// TODO: consider moving out of NetworkAgentInfo into its own class
private class NetworkAgentMessageHandler extends INetworkAgentRegistry.Stub {
private final Handler mHandler;
private NetworkAgentMessageHandler(Handler handler) {
mHandler = handler;
}
@Override
public void sendNetworkCapabilities(NetworkCapabilities nc) {
mHandler.obtainMessage(NetworkAgent.EVENT_NETWORK_CAPABILITIES_CHANGED,
new Pair<>(NetworkAgentInfo.this, nc)).sendToTarget();
}
@Override
public void sendLinkProperties(LinkProperties lp) {
mHandler.obtainMessage(NetworkAgent.EVENT_NETWORK_PROPERTIES_CHANGED,
new Pair<>(NetworkAgentInfo.this, lp)).sendToTarget();
}
@Override
public void sendNetworkInfo(NetworkInfo info) {
mHandler.obtainMessage(NetworkAgent.EVENT_NETWORK_INFO_CHANGED,
new Pair<>(NetworkAgentInfo.this, info)).sendToTarget();
}
@Override
public void sendScore(int score) {
mHandler.obtainMessage(NetworkAgent.EVENT_NETWORK_SCORE_CHANGED, score, 0,
new Pair<>(NetworkAgentInfo.this, null)).sendToTarget();
}
@Override
public void sendExplicitlySelected(boolean explicitlySelected, boolean acceptPartial) {
mHandler.obtainMessage(NetworkAgent.EVENT_SET_EXPLICITLY_SELECTED,
explicitlySelected ? 1 : 0, acceptPartial ? 1 : 0,
new Pair<>(NetworkAgentInfo.this, null)).sendToTarget();
}
@Override
public void sendSocketKeepaliveEvent(int slot, int reason) {
mHandler.obtainMessage(NetworkAgent.EVENT_SOCKET_KEEPALIVE,
slot, reason, new Pair<>(NetworkAgentInfo.this, null)).sendToTarget();
}
@Override
public void sendUnderlyingNetworks(@Nullable List<Network> networks) {
final Bundle args = new Bundle();
if (networks instanceof ArrayList<?>) {
args.putParcelableArrayList(NetworkAgent.UNDERLYING_NETWORKS_KEY,
(ArrayList<Network>) networks);
} else {
args.putParcelableArrayList(NetworkAgent.UNDERLYING_NETWORKS_KEY,
networks == null ? null : new ArrayList<>(networks));
}
mHandler.obtainMessage(NetworkAgent.EVENT_UNDERLYING_NETWORKS_CHANGED,
new Pair<>(NetworkAgentInfo.this, args)).sendToTarget();
}
}
/**
* Inform NetworkAgentInfo that a new NetworkMonitor was created.
*/

View File

@@ -7812,8 +7812,7 @@ public class ConnectivityServiceTest {
@Test
public void testCheckConnectivityDiagnosticsPermissionsNetworkStack() throws Exception {
final NetworkAgentInfo naiWithoutUid =
new NetworkAgentInfo(
null, null, null, null, null, new NetworkCapabilities(), 0,
new NetworkAgentInfo(null, null, null, null, new NetworkCapabilities(), 0,
mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID);
mServiceContext.setPermission(
@@ -7828,8 +7827,7 @@ public class ConnectivityServiceTest {
@Test
public void testCheckConnectivityDiagnosticsPermissionsWrongUidPackageName() throws Exception {
final NetworkAgentInfo naiWithoutUid =
new NetworkAgentInfo(
null, null, null, null, null, new NetworkCapabilities(), 0,
new NetworkAgentInfo(null, null, null, null, new NetworkCapabilities(), 0,
mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID);
mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
@@ -7844,8 +7842,7 @@ public class ConnectivityServiceTest {
@Test
public void testCheckConnectivityDiagnosticsPermissionsNoLocationPermission() throws Exception {
final NetworkAgentInfo naiWithoutUid =
new NetworkAgentInfo(
null, null, null, null, null, new NetworkCapabilities(), 0,
new NetworkAgentInfo(null, null, null, null, new NetworkCapabilities(), 0,
mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID);
mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
@@ -7861,8 +7858,7 @@ public class ConnectivityServiceTest {
public void testCheckConnectivityDiagnosticsPermissionsActiveVpn() throws Exception {
final Network network = new Network(NET_ID);
final NetworkAgentInfo naiWithoutUid =
new NetworkAgentInfo(
null, null, network, null, null, new NetworkCapabilities(), 0,
new NetworkAgentInfo(null, network, null, null, new NetworkCapabilities(), 0,
mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID);
setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
@@ -7896,8 +7892,7 @@ public class ConnectivityServiceTest {
final NetworkCapabilities nc = new NetworkCapabilities();
nc.setAdministratorUids(new int[] {Process.myUid()});
final NetworkAgentInfo naiWithUid =
new NetworkAgentInfo(
null, null, null, null, null, nc, 0, mServiceContext, null, null,
new NetworkAgentInfo(null, null, null, null, nc, 0, mServiceContext, null, null,
mService, null, null, null, 0, INVALID_UID);
setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
@@ -7916,8 +7911,7 @@ public class ConnectivityServiceTest {
nc.setOwnerUid(Process.myUid());
nc.setAdministratorUids(new int[] {Process.myUid()});
final NetworkAgentInfo naiWithUid =
new NetworkAgentInfo(
null, null, null, null, null, nc, 0, mServiceContext, null, null,
new NetworkAgentInfo(null, null, null, null, nc, 0, mServiceContext, null, null,
mService, null, null, null, 0, INVALID_UID);
setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,

View File

@@ -353,7 +353,7 @@ public class LingerMonitorTest {
NetworkCapabilities caps = new NetworkCapabilities();
caps.addCapability(0);
caps.addTransportType(transport);
NetworkAgentInfo nai = new NetworkAgentInfo(null, null, new Network(netId), info, null,
NetworkAgentInfo nai = new NetworkAgentInfo(null, new Network(netId), info, null,
caps, 50, mCtx, null, null /* config */, mConnService, mNetd, mDnsResolver, mNMS,
NetworkProvider.ID_NONE, Binder.getCallingUid());
nai.everValidated = true;