Return the registry in registerNetworkAgent.
Also make the network agent registry two way to eliminate reordering possibilities. Test: ConnectivityCoverageTest, CtsNetTests Change-Id: I0fd90716b9f5501bdcdc7ee5165321737a0076ae
This commit is contained in:
parent
520093b251
commit
70ede3260c
9 changed files with 98 additions and 30 deletions
|
|
@ -3952,7 +3952,8 @@ public class ConnectivityManager {
|
|||
@RequiresPermission(anyOf = {
|
||||
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
|
||||
android.Manifest.permission.NETWORK_FACTORY})
|
||||
public Network registerNetworkAgent(@NonNull INetworkAgent na, @NonNull NetworkInfo ni,
|
||||
public NetworkAndAgentRegistryParcelable registerNetworkAgent(
|
||||
@NonNull INetworkAgent na, @NonNull NetworkInfo ni,
|
||||
@NonNull LinkProperties lp, @NonNull NetworkCapabilities nc,
|
||||
@NonNull NetworkScore score, @NonNull NetworkAgentConfig config, int providerId) {
|
||||
return registerNetworkAgent(na, ni, lp, nc, null /* localNetworkConfig */, score, config,
|
||||
|
|
@ -3967,7 +3968,8 @@ public class ConnectivityManager {
|
|||
@RequiresPermission(anyOf = {
|
||||
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
|
||||
android.Manifest.permission.NETWORK_FACTORY})
|
||||
public Network registerNetworkAgent(@NonNull INetworkAgent na, @NonNull NetworkInfo ni,
|
||||
public NetworkAndAgentRegistryParcelable registerNetworkAgent(
|
||||
@NonNull INetworkAgent na, @NonNull NetworkInfo ni,
|
||||
@NonNull LinkProperties lp, @NonNull NetworkCapabilities nc,
|
||||
@Nullable LocalNetworkConfig localNetworkConfig, @NonNull NetworkScore score,
|
||||
@NonNull NetworkAgentConfig config, int providerId) {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import android.net.LinkProperties;
|
|||
import android.net.LocalNetworkConfig;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkAgentConfig;
|
||||
import android.net.NetworkAndAgentRegistryParcelable;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.NetworkRequest;
|
||||
|
|
@ -146,7 +147,8 @@ interface IConnectivityManager
|
|||
|
||||
void declareNetworkRequestUnfulfillable(in NetworkRequest request);
|
||||
|
||||
Network registerNetworkAgent(in INetworkAgent na, in NetworkInfo ni, in LinkProperties lp,
|
||||
NetworkAndAgentRegistryParcelable registerNetworkAgent(
|
||||
in INetworkAgent na, in NetworkInfo ni, in LinkProperties lp,
|
||||
in NetworkCapabilities nc, in NetworkScore score,
|
||||
in LocalNetworkConfig localNetworkConfig, in NetworkAgentConfig config,
|
||||
in int factorySerialNumber);
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import android.net.INetworkAgentRegistry;
|
|||
* @hide
|
||||
*/
|
||||
oneway interface INetworkAgent {
|
||||
void onRegistered(in INetworkAgentRegistry registry);
|
||||
void onRegistered();
|
||||
void onDisconnected();
|
||||
void onBandwidthUpdateRequested();
|
||||
void onValidationStatusChanged(int validationStatus,
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ import android.telephony.data.NrQosSessionAttributes;
|
|||
* Interface for NetworkAgents to send network properties.
|
||||
* @hide
|
||||
*/
|
||||
oneway interface INetworkAgentRegistry {
|
||||
interface INetworkAgentRegistry {
|
||||
void sendNetworkCapabilities(in NetworkCapabilities nc);
|
||||
void sendLinkProperties(in LinkProperties lp);
|
||||
// TODO: consider replacing this by "markConnected()" and removing
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ public abstract class NetworkAgent {
|
|||
@Nullable
|
||||
private volatile Network mNetwork;
|
||||
|
||||
// Null before the agent is registered
|
||||
@Nullable
|
||||
private volatile INetworkAgentRegistry mRegistry;
|
||||
|
||||
|
|
@ -121,6 +122,8 @@ public abstract class NetworkAgent {
|
|||
private NetworkInfo mNetworkInfo;
|
||||
@NonNull
|
||||
private final Object mRegisterLock = new Object();
|
||||
// TODO : move the preconnected queue to the system server and remove this
|
||||
private boolean mConnected = false;
|
||||
|
||||
/**
|
||||
* The ID of the {@link NetworkProvider} that created this object, or
|
||||
|
|
@ -606,16 +609,16 @@ public abstract class NetworkAgent {
|
|||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case EVENT_AGENT_CONNECTED: {
|
||||
if (mRegistry != null) {
|
||||
log("Received new connection while already connected!");
|
||||
} else {
|
||||
if (VDBG) log("NetworkAgent fully connected");
|
||||
synchronized (mPreConnectedQueue) {
|
||||
final INetworkAgentRegistry registry = (INetworkAgentRegistry) msg.obj;
|
||||
mRegistry = registry;
|
||||
// TODO : move the pre-connected queue to the system server, and remove
|
||||
// handling this EVENT_AGENT_CONNECTED message.
|
||||
synchronized (mPreConnectedQueue) {
|
||||
if (mConnected) {
|
||||
log("Received new connection while already connected!");
|
||||
} else {
|
||||
if (VDBG) log("NetworkAgent fully connected");
|
||||
for (RegistryAction a : mPreConnectedQueue) {
|
||||
try {
|
||||
a.execute(registry);
|
||||
a.execute(mRegistry);
|
||||
} catch (RemoteException e) {
|
||||
Log.wtf(LOG_TAG, "Communication error with registry", e);
|
||||
// Fall through
|
||||
|
|
@ -623,6 +626,7 @@ public abstract class NetworkAgent {
|
|||
}
|
||||
mPreConnectedQueue.clear();
|
||||
}
|
||||
mConnected = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -631,7 +635,7 @@ public abstract class NetworkAgent {
|
|||
// let the client know CS is done with us.
|
||||
onNetworkUnwanted();
|
||||
synchronized (mPreConnectedQueue) {
|
||||
mRegistry = null;
|
||||
mConnected = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -758,20 +762,32 @@ public abstract class NetworkAgent {
|
|||
}
|
||||
final ConnectivityManager cm = (ConnectivityManager) mInitialConfiguration.context
|
||||
.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
final NetworkAndAgentRegistryParcelable result;
|
||||
if (mInitialConfiguration.localNetworkConfig == null) {
|
||||
// Call registerNetworkAgent without localNetworkConfig argument to pass
|
||||
// android.net.cts.NetworkAgentTest#testAgentStartsInConnecting in old cts
|
||||
mNetwork = cm.registerNetworkAgent(new NetworkAgentBinder(mHandler),
|
||||
result = cm.registerNetworkAgent(new NetworkAgentBinder(mHandler),
|
||||
new NetworkInfo(mInitialConfiguration.info),
|
||||
mInitialConfiguration.properties, mInitialConfiguration.capabilities,
|
||||
mInitialConfiguration.score, mInitialConfiguration.config, providerId);
|
||||
} else {
|
||||
mNetwork = cm.registerNetworkAgent(new NetworkAgentBinder(mHandler),
|
||||
result = cm.registerNetworkAgent(new NetworkAgentBinder(mHandler),
|
||||
new NetworkInfo(mInitialConfiguration.info),
|
||||
mInitialConfiguration.properties, mInitialConfiguration.capabilities,
|
||||
mInitialConfiguration.localNetworkConfig, mInitialConfiguration.score,
|
||||
mInitialConfiguration.config, providerId);
|
||||
}
|
||||
if (null == result && Process.isApplicationUid(Process.myUid())) {
|
||||
// Let it slide in tests to allow mocking, since NetworkAndAgentRegistryParcelable
|
||||
// is not public and can't be instantiated by CTS. The danger here is that if
|
||||
// this happens in production for some reason the code will crash later instead
|
||||
// of here. If this is a system app, it will still crash as expected.
|
||||
Log.e(LOG_TAG, "registerNetworkAgent returned null. This agent will not work. "
|
||||
+ "Is ConnectivityManager a mock ?");
|
||||
} else {
|
||||
mNetwork = result.network;
|
||||
mRegistry = result.registry;
|
||||
}
|
||||
mInitialConfiguration = null; // All this memory can now be GC'd
|
||||
}
|
||||
return mNetwork;
|
||||
|
|
@ -787,8 +803,8 @@ public abstract class NetworkAgent {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onRegistered(@NonNull INetworkAgentRegistry registry) {
|
||||
mHandler.sendMessage(mHandler.obtainMessage(EVENT_AGENT_CONNECTED, registry));
|
||||
public void onRegistered() {
|
||||
mHandler.sendMessage(mHandler.obtainMessage(EVENT_AGENT_CONNECTED));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -913,11 +929,13 @@ public abstract class NetworkAgent {
|
|||
*
|
||||
* @hide
|
||||
*/
|
||||
public INetworkAgent registerForTest(final Network network) {
|
||||
public INetworkAgent registerForTest(final Network network,
|
||||
final INetworkAgentRegistry registry) {
|
||||
log("Registering NetworkAgent for test");
|
||||
synchronized (mRegisterLock) {
|
||||
mNetwork = network;
|
||||
mInitialConfiguration = null;
|
||||
mRegistry = registry;
|
||||
}
|
||||
return new NetworkAgentBinder(mHandler);
|
||||
}
|
||||
|
|
@ -958,7 +976,7 @@ public abstract class NetworkAgent {
|
|||
FrameworkConnectivityStatsLog.CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED__ERROR_TYPE__TYPE_MESSAGE_QUEUED_BEFORE_CONNECT
|
||||
);
|
||||
}
|
||||
if (mRegistry != null) {
|
||||
if (mConnected) {
|
||||
try {
|
||||
action.execute(mRegistry);
|
||||
} catch (RemoteException e) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (C) 2025 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.net.INetworkAgentRegistry;
|
||||
import android.net.Network;
|
||||
|
||||
/**
|
||||
* A pair of Network and NetworkAgentRegistry.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
@JavaDerive(toString=true)
|
||||
parcelable NetworkAndAgentRegistryParcelable {
|
||||
Network network;
|
||||
INetworkAgentRegistry registry;
|
||||
}
|
||||
|
|
@ -228,6 +228,7 @@ import android.net.NattSocketKeepalive;
|
|||
import android.net.Network;
|
||||
import android.net.NetworkAgent;
|
||||
import android.net.NetworkAgentConfig;
|
||||
import android.net.NetworkAndAgentRegistryParcelable;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.NetworkInfo.DetailedState;
|
||||
|
|
@ -9316,7 +9317,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(INetworkAgent na,
|
||||
public NetworkAndAgentRegistryParcelable registerNetworkAgent(INetworkAgent na,
|
||||
NetworkInfo networkInfo,
|
||||
LinkProperties linkProperties,
|
||||
NetworkCapabilities networkCapabilities,
|
||||
|
|
@ -9359,7 +9360,8 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||
}
|
||||
}
|
||||
|
||||
private Network registerNetworkAgentInternal(INetworkAgent na, NetworkInfo networkInfo,
|
||||
private NetworkAndAgentRegistryParcelable registerNetworkAgentInternal(
|
||||
INetworkAgent na, NetworkInfo networkInfo,
|
||||
LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
|
||||
NetworkScore currentScore, NetworkAgentConfig networkAgentConfig,
|
||||
@Nullable LocalNetworkConfig localNetworkConfig, int providerId,
|
||||
|
|
@ -9391,8 +9393,11 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||
// 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.connect(), which will be called when finalizing the
|
||||
// registration.
|
||||
return nai.network;
|
||||
// registration. TODO : have NetworkAgentInfo defer them instead.
|
||||
final NetworkAndAgentRegistryParcelable result = new NetworkAndAgentRegistryParcelable();
|
||||
result.network = nai.network;
|
||||
result.registry = nai.getRegistry();
|
||||
return result;
|
||||
}
|
||||
|
||||
private void handleRegisterNetworkAgent(NetworkAgentInfo nai, INetworkMonitor networkMonitor) {
|
||||
|
|
|
|||
|
|
@ -639,6 +639,7 @@ public class NetworkAgentInfo implements NetworkRanker.Scoreable {
|
|||
private final ConnectivityService.Dependencies mConnServiceDeps;
|
||||
private final Context mContext;
|
||||
private final Handler mHandler;
|
||||
private final NetworkAgentMessageHandler mRegistry;
|
||||
private final QosCallbackTracker mQosCallbackTracker;
|
||||
private final INetd mNetd;
|
||||
|
||||
|
|
@ -673,6 +674,7 @@ public class NetworkAgentInfo implements NetworkRanker.Scoreable {
|
|||
mNetd = netd;
|
||||
mContext = context;
|
||||
mHandler = handler;
|
||||
mRegistry = new NetworkAgentMessageHandler(mHandler);
|
||||
this.factorySerialNumber = factorySerialNumber;
|
||||
this.creatorUid = creatorUid;
|
||||
mLingerDurationMs = lingerDurationMs;
|
||||
|
|
@ -701,7 +703,7 @@ public class NetworkAgentInfo implements NetworkRanker.Scoreable {
|
|||
public void notifyRegistered() {
|
||||
try {
|
||||
networkAgent.asBinder().linkToDeath(mDeathMonitor, 0);
|
||||
networkAgent.onRegistered(new NetworkAgentMessageHandler(mHandler));
|
||||
networkAgent.onRegistered();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error registering NetworkAgent", e);
|
||||
maybeUnlinkDeathMonitor();
|
||||
|
|
@ -1117,6 +1119,13 @@ public class NetworkAgentInfo implements NetworkRanker.Scoreable {
|
|||
return mNetworkMonitor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the registry in this NetworkAgentInfo.
|
||||
*/
|
||||
public INetworkAgentRegistry getRegistry() {
|
||||
return mRegistry;
|
||||
}
|
||||
|
||||
// Functions for manipulating the requests satisfied by this network.
|
||||
//
|
||||
// These functions must only called on ConnectivityService's main thread.
|
||||
|
|
|
|||
|
|
@ -154,10 +154,10 @@ import java.nio.ByteBuffer
|
|||
import java.security.MessageDigest
|
||||
import java.time.Duration
|
||||
import java.util.Arrays
|
||||
import java.util.Random
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.Executors
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.random.Random
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFailsWith
|
||||
import kotlin.test.assertFalse
|
||||
|
|
@ -266,7 +266,7 @@ class NetworkAgentTest {
|
|||
private class FakeConnectivityService {
|
||||
val mockRegistry = mock(INetworkAgentRegistry::class.java)
|
||||
private var agentField: INetworkAgent? = null
|
||||
private val registry = object : INetworkAgentRegistry.Stub(),
|
||||
val registry: INetworkAgentRegistry = object : INetworkAgentRegistry.Stub(),
|
||||
INetworkAgentRegistry by mockRegistry {
|
||||
// asBinder has implementations in both INetworkAgentRegistry.Stub and mockRegistry, so
|
||||
// it needs to be disambiguated. Just fail the test as it should be unused here.
|
||||
|
|
@ -283,7 +283,7 @@ class NetworkAgentTest {
|
|||
|
||||
fun connect(agent: INetworkAgent) {
|
||||
this.agentField = agent
|
||||
agent.onRegistered(registry)
|
||||
agent.onRegistered()
|
||||
}
|
||||
|
||||
fun disconnect() = agent.onDisconnected()
|
||||
|
|
@ -412,7 +412,8 @@ class NetworkAgentTest {
|
|||
}
|
||||
|
||||
private fun createNetworkAgentWithFakeCS() = createNetworkAgent().also {
|
||||
mFakeConnectivityService.connect(it.registerForTest(Network(FAKE_NET_ID)))
|
||||
val binder = it.registerForTest(Network(FAKE_NET_ID), mFakeConnectivityService.registry)
|
||||
mFakeConnectivityService.connect(binder)
|
||||
}
|
||||
|
||||
private fun TestableNetworkAgent.expectPostConnectionCallbacks(
|
||||
|
|
@ -1614,7 +1615,7 @@ class NetworkAgentTest {
|
|||
val s = Os.socket(AF_INET6, SOCK_DGRAM, 0)
|
||||
net.bindSocket(s)
|
||||
val content = ByteArray(16)
|
||||
Random().nextBytes(content)
|
||||
Random.nextBytes(content)
|
||||
Os.sendto(s, ByteBuffer.wrap(content), 0, REMOTE_ADDRESS, 7 /* port */)
|
||||
val match = reader.poll(DEFAULT_TIMEOUT_MS) {
|
||||
val udpStart = IPV6_HEADER_LEN + UDP_HEADER_LEN
|
||||
|
|
|
|||
Loading…
Reference in a new issue