Skip to content
Snippets Groups Projects
Commit 198a3d49 authored by Handa Wang's avatar Handa Wang
Browse files

add hidden method setTestNetworkAsUpstream

`setTestNetworkAsUpstream` allows to specify a test network as the upstream of Thread network. This is going to be used in Thread integration tests. E.g. android.net.thread.BorderRoutingTest.

Bug: 295843010
Test: atest android.net.thread.BorderRoutingTest

Change-Id: I66474e2aa5b3434c4c66078a1d6bd6e522e32ae5
parent 44049a39
No related branches found
No related tags found
No related merge requests found
......@@ -38,6 +38,8 @@ interface IThreadNetworkController {
void scheduleMigration(in PendingOperationalDataset pendingOpDataset, in IOperationReceiver receiver);
void leave(in IOperationReceiver receiver);
void setTestNetworkAsUpstream(in String testNetworkInterfaceName, in IOperationReceiver receiver);
int getThreadVersion();
void createRandomizedDataset(String networkName, IActiveOperationalDatasetReceiver receiver);
}
......@@ -31,6 +31,7 @@ import android.os.OutcomeReceiver;
import android.os.RemoteException;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
......@@ -499,6 +500,31 @@ public final class ThreadNetworkController {
}
}
/**
* Sets to use a specified test network as the upstream.
*
* @param testNetworkInterfaceName The name of the test network interface. When it's null,
* forbids using test network as an upstream.
* @param executor the executor to execute {@code receiver}
* @param receiver the receiver to receive result of this operation
* @hide
*/
@VisibleForTesting
@RequiresPermission("android.permission.THREAD_NETWORK_PRIVILEGED")
public void setTestNetworkAsUpstream(
@Nullable String testNetworkInterfaceName,
@NonNull @CallbackExecutor Executor executor,
@NonNull OutcomeReceiver<Void, ThreadNetworkException> receiver) {
requireNonNull(executor, "executor cannot be null");
requireNonNull(receiver, "receiver cannot be null");
try {
mControllerService.setTestNetworkAsUpstream(
testNetworkInterfaceName, new OperationReceiverProxy(executor, receiver));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
private static <T> void propagateError(
Executor executor,
OutcomeReceiver<T, ThreadNetworkException> receiver,
......
......@@ -53,14 +53,15 @@ import static com.android.server.thread.openthread.IOtDaemon.TUN_IF_NAME;
import android.Manifest.permission;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.LocalNetworkConfig;
import android.net.MulticastRoutingConfig;
import android.net.LocalNetworkInfo;
import android.net.MulticastRoutingConfig;
import android.net.Network;
import android.net.NetworkAgent;
import android.net.NetworkAgentConfig;
......@@ -69,6 +70,7 @@ import android.net.NetworkProvider;
import android.net.NetworkRequest;
import android.net.NetworkScore;
import android.net.RouteInfo;
import android.net.TestNetworkSpecifier;
import android.net.thread.ActiveOperationalDataset;
import android.net.thread.ActiveOperationalDataset.SecurityPolicy;
import android.net.thread.IActiveOperationalDatasetReceiver;
......@@ -91,12 +93,12 @@ import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.ServiceManagerWrapper;
import com.android.server.thread.openthread.BorderRouterConfigurationParcel;
import com.android.server.thread.openthread.IOtDaemon;
import com.android.server.thread.openthread.IOtDaemonCallback;
import com.android.server.thread.openthread.IOtStatusReceiver;
import com.android.server.thread.openthread.Ipv6AddressInfo;
import com.android.server.thread.openthread.OtDaemonState;
import com.android.server.thread.openthread.BorderRouterConfigurationParcel;
import java.io.IOException;
import java.net.Inet6Address;
......@@ -147,9 +149,10 @@ final class ThreadNetworkControllerService extends IThreadNetworkController.Stub
private MulticastRoutingConfig mUpstreamMulticastRoutingConfig = CONFIG_FORWARD_NONE;
private MulticastRoutingConfig mDownstreamMulticastRoutingConfig = CONFIG_FORWARD_NONE;
private Network mUpstreamNetwork;
private final NetworkRequest mUpstreamNetworkRequest;
private NetworkRequest mUpstreamNetworkRequest;
private UpstreamNetworkCallback mUpstreamNetworkCallback;
private TestNetworkSpecifier mUpstreamTestNetworkSpecifier;
private final HashMap<Network, String> mNetworkToInterface;
private final LocalNetworkConfig mLocalNetworkConfig;
private BorderRouterConfigurationParcel mBorderRouterConfig;
......@@ -168,16 +171,7 @@ final class ThreadNetworkControllerService extends IThreadNetworkController.Stub
mOtDaemonSupplier = otDaemonSupplier;
mConnectivityManager = connectivityManager;
mTunIfController = tunIfController;
mUpstreamNetworkRequest =
new NetworkRequest.Builder()
.clearCapabilities()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
.build();
mLocalNetworkConfig =
new LocalNetworkConfig.Builder()
.setUpstreamSelector(mUpstreamNetworkRequest)
.build();
mUpstreamNetworkRequest = newUpstreamNetworkRequest();
mNetworkToInterface = new HashMap<Network, String>();
mBorderRouterConfig = new BorderRouterConfigurationParcel();
}
......@@ -237,6 +231,60 @@ final class ThreadNetworkControllerService extends IThreadNetworkController.Stub
LinkAddress.LIFETIME_PERMANENT /* expirationTime */);
}
private NetworkRequest newUpstreamNetworkRequest() {
NetworkRequest.Builder builder = new NetworkRequest.Builder().clearCapabilities();
if (mUpstreamTestNetworkSpecifier != null) {
return builder.addTransportType(NetworkCapabilities.TRANSPORT_TEST)
.setNetworkSpecifier(mUpstreamTestNetworkSpecifier)
.build();
}
return builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build();
}
private LocalNetworkConfig newLocalNetworkConfig() {
return new LocalNetworkConfig.Builder()
.setUpstreamMulticastRoutingConfig(mUpstreamMulticastRoutingConfig)
.setDownstreamMulticastRoutingConfig(mDownstreamMulticastRoutingConfig)
.setUpstreamSelector(mUpstreamNetworkRequest)
.build();
}
@Override
public void setTestNetworkAsUpstream(
@Nullable String testNetworkInterfaceName, @NonNull IOperationReceiver receiver) {
enforceAllCallingPermissionsGranted(PERMISSION_THREAD_NETWORK_PRIVILEGED);
Log.i(TAG, "setTestNetworkAsUpstream: " + testNetworkInterfaceName);
mHandler.post(() -> setTestNetworkAsUpstreamInternal(testNetworkInterfaceName, receiver));
}
private void setTestNetworkAsUpstreamInternal(
@Nullable String testNetworkInterfaceName, @NonNull IOperationReceiver receiver) {
checkOnHandlerThread();
TestNetworkSpecifier testNetworkSpecifier = null;
if (testNetworkInterfaceName != null) {
testNetworkSpecifier = new TestNetworkSpecifier(testNetworkInterfaceName);
}
if (!Objects.equals(mUpstreamTestNetworkSpecifier, testNetworkSpecifier)) {
cancelRequestUpstreamNetwork();
mUpstreamTestNetworkSpecifier = testNetworkSpecifier;
mUpstreamNetworkRequest = newUpstreamNetworkRequest();
requestUpstreamNetwork();
sendLocalNetworkConfig();
}
try {
receiver.onSuccess();
} catch (RemoteException ignored) {
// do nothing if the client is dead
}
}
private void initializeOtDaemon() {
try {
getOtDaemon();
......@@ -289,45 +337,63 @@ final class ThreadNetworkControllerService extends IThreadNetworkController.Stub
}
private void requestUpstreamNetwork() {
if (mUpstreamNetworkCallback != null) {
throw new AssertionError("The upstream network request is already there.");
}
mUpstreamNetworkCallback = new UpstreamNetworkCallback();
mConnectivityManager.registerNetworkCallback(
mUpstreamNetworkRequest,
new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(@NonNull Network network) {
Log.i(TAG, "onAvailable: " + network);
}
mUpstreamNetworkRequest, mUpstreamNetworkCallback, mHandler);
}
@Override
public void onLost(@NonNull Network network) {
Log.i(TAG, "onLost: " + network);
}
private void cancelRequestUpstreamNetwork() {
if (mUpstreamNetworkCallback == null) {
throw new AssertionError("The upstream network request null.");
}
mNetworkToInterface.clear();
mConnectivityManager.unregisterNetworkCallback(mUpstreamNetworkCallback);
mUpstreamNetworkCallback = null;
}
@Override
public void onLinkPropertiesChanged(
@NonNull Network network, @NonNull LinkProperties linkProperties) {
Log.i(
TAG,
String.format(
"onLinkPropertiesChanged: {network: %s, interface: %s}",
network, linkProperties.getInterfaceName()));
mNetworkToInterface.put(network, linkProperties.getInterfaceName());
if (network.equals(mUpstreamNetwork)) {
enableBorderRouting(mNetworkToInterface.get(mUpstreamNetwork));
}
}
},
mHandler);
private final class UpstreamNetworkCallback extends ConnectivityManager.NetworkCallback {
@Override
public void onAvailable(@NonNull Network network) {
checkOnHandlerThread();
Log.i(TAG, "onAvailable: " + network);
}
@Override
public void onLost(@NonNull Network network) {
checkOnHandlerThread();
Log.i(TAG, "onLost: " + network);
}
@Override
public void onLinkPropertiesChanged(
@NonNull Network network, @NonNull LinkProperties linkProperties) {
checkOnHandlerThread();
Log.i(
TAG,
String.format(
"onLinkPropertiesChanged: {network: %s, interface: %s}",
network, linkProperties.getInterfaceName()));
mNetworkToInterface.put(network, linkProperties.getInterfaceName());
if (network.equals(mUpstreamNetwork)) {
enableBorderRouting(mNetworkToInterface.get(mUpstreamNetwork));
}
}
}
private final class ThreadNetworkCallback extends ConnectivityManager.NetworkCallback {
@Override
public void onAvailable(@NonNull Network network) {
checkOnHandlerThread();
Log.i(TAG, "onAvailable: Thread network Available");
}
@Override
public void onLocalNetworkInfoChanged(
@NonNull Network network, @NonNull LocalNetworkInfo localNetworkInfo) {
checkOnHandlerThread();
Log.i(TAG, "onLocalNetworkInfoChanged: " + localNetworkInfo);
if (localNetworkInfo.getUpstreamNetwork() == null) {
mUpstreamNetwork = null;
......@@ -370,7 +436,7 @@ final class ThreadNetworkControllerService extends IThreadNetworkController.Stub
TAG,
netCaps,
mLinkProperties,
mLocalNetworkConfig,
newLocalNetworkConfig(),
score,
new NetworkAgentConfig.Builder().build(),
mNetworkProvider) {};
......@@ -754,20 +820,9 @@ final class ThreadNetworkControllerService extends IThreadNetworkController.Stub
if (mNetworkAgent == null) {
return;
}
final LocalNetworkConfig.Builder configBuilder = new LocalNetworkConfig.Builder();
LocalNetworkConfig localNetworkConfig =
configBuilder
.setUpstreamMulticastRoutingConfig(mUpstreamMulticastRoutingConfig)
.setDownstreamMulticastRoutingConfig(mDownstreamMulticastRoutingConfig)
.setUpstreamSelector(mUpstreamNetworkRequest)
.build();
final LocalNetworkConfig localNetworkConfig = newLocalNetworkConfig();
mNetworkAgent.sendLocalNetworkConfig(localNetworkConfig);
Log.d(
TAG,
"Sent localNetworkConfig with upstreamConfig "
+ mUpstreamMulticastRoutingConfig
+ " downstreamConfig"
+ mDownstreamMulticastRoutingConfig);
Log.d(TAG, "Sent localNetworkConfig: " + localNetworkConfig);
}
private void handleMulticastForwardingStateChanged(boolean isEnabled) {
......@@ -800,8 +855,8 @@ final class ThreadNetworkControllerService extends IThreadNetworkController.Stub
MulticastRoutingConfig newDownstreamConfig;
MulticastRoutingConfig.Builder builder;
if (mDownstreamMulticastRoutingConfig.getForwardingMode() !=
MulticastRoutingConfig.FORWARD_SELECTED) {
if (mDownstreamMulticastRoutingConfig.getForwardingMode()
!= MulticastRoutingConfig.FORWARD_SELECTED) {
Log.e(
TAG,
"Ignore multicast listening address updates when downstream multicast "
......@@ -809,8 +864,8 @@ final class ThreadNetworkControllerService extends IThreadNetworkController.Stub
// Don't update the address set if downstream multicast forwarding is disabled.
return;
}
if (isAdded ==
mDownstreamMulticastRoutingConfig.getListeningAddresses().contains(address)) {
if (isAdded
== mDownstreamMulticastRoutingConfig.getListeningAddresses().contains(address)) {
return;
}
......
......@@ -28,11 +28,6 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doAnswer;
import android.net.thread.IActiveOperationalDatasetReceiver;
import android.net.thread.IOperationReceiver;
import android.net.thread.IOperationalDatasetCallback;
import android.net.thread.IStateCallback;
import android.net.thread.IThreadNetworkController;
import android.net.thread.ThreadNetworkController.OperationalDatasetCallback;
import android.net.thread.ThreadNetworkController.StateCallback;
import android.os.Binder;
......@@ -111,6 +106,11 @@ public final class ThreadNetworkControllerTest {
return (IOperationReceiver) invocation.getArguments()[1];
}
private static IOperationReceiver getSetTestNetworkAsUpstreamReceiver(
InvocationOnMock invocation) {
return (IOperationReceiver) invocation.getArguments()[1];
}
private static IActiveOperationalDatasetReceiver getCreateDatasetReceiver(
InvocationOnMock invocation) {
return (IActiveOperationalDatasetReceiver) invocation.getArguments()[1];
......@@ -359,4 +359,27 @@ public final class ThreadNetworkControllerTest {
assertThat(errorCallbackUid.get()).isNotEqualTo(SYSTEM_UID);
assertThat(errorCallbackUid.get()).isEqualTo(Process.myUid());
}
@Test
public void setTestNetworkAsUpstream_callbackIsInvokedWithCallingAppIdentity()
throws Exception {
setBinderUid(SYSTEM_UID);
AtomicInteger callbackUid = new AtomicInteger(0);
doAnswer(
invoke -> {
getSetTestNetworkAsUpstreamReceiver(invoke).onSuccess();
return null;
})
.when(mMockService)
.setTestNetworkAsUpstream(anyString(), any(IOperationReceiver.class));
mController.setTestNetworkAsUpstream(
null, Runnable::run, v -> callbackUid.set(Binder.getCallingUid()));
mController.setTestNetworkAsUpstream(
new String("test0"), Runnable::run, v -> callbackUid.set(Binder.getCallingUid()));
assertThat(callbackUid.get()).isNotEqualTo(SYSTEM_UID);
assertThat(callbackUid.get()).isEqualTo(Process.myUid());
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment