Return the registry in registerNetworkAgent.

This is a resubmit of
I0fd90716b9f5501bdcdc7ee5165321737a0076ae
which did not account for testing of this private method
in Telephony tests.

Also make the network agent registry two way to eliminate
reordering possibilities.

Test: ConnectivityCoverageTest, CtsNetTests
Change-Id: I9ca025b1369dcb1202f906d5cff79e3d935b40da
This commit is contained in:
Chalard Jean 2025-03-03 11:59:31 +09:00
commit 80d4326d76
6 changed files with 104 additions and 32 deletions

View file

@ -1252,9 +1252,13 @@ public class ConnectivityManager {
* {@link ConnectivityManager#registerNetworkAgent}
* @hide
*/
public static Network registerNetworkAgentResult(
public static NetworkAndAgentRegistryParcelable registerNetworkAgentResult(
@Nullable final Network network, @Nullable final INetworkAgentRegistry registry) {
return network;
final NetworkAndAgentRegistryParcelable result =
new NetworkAndAgentRegistryParcelable();
result.network = network;
result.registry = registry;
return result;
}
}
@ -3968,7 +3972,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,
@ -3983,7 +3988,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) {

View file

@ -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);

View file

@ -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,

View file

@ -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

View file

@ -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) {

View file

@ -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;
}