summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Rohr <prohr@google.com>2022-03-30 15:15:34 +0200
committerRemi NGUYEN VAN <reminv@google.com>2022-03-31 02:03:53 +0000
commit9fe3c9736406a35421ad8582f7148d34f90ac7ef (patch)
tree13f4a3881fc99fd0050781e1dc3962d5da6789a1
parentbad3d2ddaec0468fedd8067a86385abd7c7173e5 (diff)
downloadethernet-9fe3c9736406a35421ad8582f7148d34f90ac7ef.tar.gz
Move f/o/n/ethernet to p/m/Connectivity
Test: TH Bug: 222234190 Merged-In: I4dd5a6ccd3294af838abcfc5ca08b76f1c002155 Change-Id: Iea43a76d84002a5a587fa735b692d8b6ce6fd12e
-rw-r--r--Android.bp32
-rw-r--r--TEST_MAPPING12
-rw-r--r--java/com/android/server/ethernet/EthernetConfigStore.java88
-rw-r--r--java/com/android/server/ethernet/EthernetNetworkAgent.java65
-rw-r--r--java/com/android/server/ethernet/EthernetNetworkFactory.java785
-rw-r--r--java/com/android/server/ethernet/EthernetService.java47
-rw-r--r--java/com/android/server/ethernet/EthernetServiceImpl.java299
-rw-r--r--java/com/android/server/ethernet/EthernetTracker.java942
-rw-r--r--tests/Android.bp53
-rw-r--r--tests/AndroidManifest.xml28
-rw-r--r--tests/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java783
-rw-r--r--tests/java/com/android/server/ethernet/EthernetServiceImplTest.java372
-rw-r--r--tests/java/com/android/server/ethernet/EthernetTrackerTest.java456
13 files changed, 0 insertions, 3962 deletions
diff --git a/Android.bp b/Android.bp
deleted file mode 100644
index c429a6f..0000000
--- a/Android.bp
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (C) 2014 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.
-
-// Build the java code
-// ============================================================
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-filegroup {
- name: "ethernet-service-updatable-sources",
- srcs: [
- "java/**/*.java",
- ],
- path: "java",
- visibility: [
- "//frameworks/opt/net/ethernet/tests",
- "//packages/modules/Connectivity/service-t",
- ],
-}
diff --git a/TEST_MAPPING b/TEST_MAPPING
deleted file mode 100644
index 24c152b..0000000
--- a/TEST_MAPPING
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "presubmit": [
- {
- "name": "EthernetServiceTests"
- }
- ],
- "imports": [
- {
- "path": "packages/modules/Connectivity"
- }
- ]
-}
diff --git a/java/com/android/server/ethernet/EthernetConfigStore.java b/java/com/android/server/ethernet/EthernetConfigStore.java
deleted file mode 100644
index 6b623f4..0000000
--- a/java/com/android/server/ethernet/EthernetConfigStore.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2014 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 com.android.server.ethernet;
-
-import android.annotation.Nullable;
-import android.net.IpConfiguration;
-import android.os.Environment;
-import android.util.ArrayMap;
-
-import com.android.server.net.IpConfigStore;
-
-
-/**
- * This class provides an API to store and manage Ethernet network configuration.
- */
-public class EthernetConfigStore {
- private static final String ipConfigFile = Environment.getDataDirectory() +
- "/misc/ethernet/ipconfig.txt";
-
- private IpConfigStore mStore = new IpConfigStore();
- private ArrayMap<String, IpConfiguration> mIpConfigurations;
- private IpConfiguration mIpConfigurationForDefaultInterface;
- private final Object mSync = new Object();
-
- public EthernetConfigStore() {
- mIpConfigurations = new ArrayMap<>(0);
- }
-
- public void read() {
- synchronized (mSync) {
- ArrayMap<String, IpConfiguration> configs =
- IpConfigStore.readIpConfigurations(ipConfigFile);
-
- // This configuration may exist in old file versions when there was only a single active
- // Ethernet interface.
- if (configs.containsKey("0")) {
- mIpConfigurationForDefaultInterface = configs.remove("0");
- }
-
- mIpConfigurations = configs;
- }
- }
-
- public void write(String iface, IpConfiguration config) {
- boolean modified;
-
- synchronized (mSync) {
- if (config == null) {
- modified = mIpConfigurations.remove(iface) != null;
- } else {
- IpConfiguration oldConfig = mIpConfigurations.put(iface, config);
- modified = !config.equals(oldConfig);
- }
-
- if (modified) {
- mStore.writeIpConfigurations(ipConfigFile, mIpConfigurations);
- }
- }
- }
-
- public ArrayMap<String, IpConfiguration> getIpConfigurations() {
- synchronized (mSync) {
- return new ArrayMap<>(mIpConfigurations);
- }
- }
-
- @Nullable
- public IpConfiguration getIpConfigurationForDefaultInterface() {
- synchronized (mSync) {
- return mIpConfigurationForDefaultInterface == null
- ? null : new IpConfiguration(mIpConfigurationForDefaultInterface);
- }
- }
-}
diff --git a/java/com/android/server/ethernet/EthernetNetworkAgent.java b/java/com/android/server/ethernet/EthernetNetworkAgent.java
deleted file mode 100644
index 57fbce7..0000000
--- a/java/com/android/server/ethernet/EthernetNetworkAgent.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2021 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 com.android.server.ethernet;
-
-import android.content.Context;
-import android.net.LinkProperties;
-import android.net.NetworkAgent;
-import android.net.NetworkAgentConfig;
-import android.net.NetworkCapabilities;
-import android.net.NetworkProvider;
-import android.net.NetworkScore;
-import android.os.Looper;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-
-public class EthernetNetworkAgent extends NetworkAgent {
-
- private static final String TAG = "EthernetNetworkAgent";
-
- public interface Callbacks {
- void onNetworkUnwanted();
- }
-
- private final Callbacks mCallbacks;
-
- EthernetNetworkAgent(
- @NonNull Context context,
- @NonNull Looper looper,
- @NonNull NetworkCapabilities nc,
- @NonNull LinkProperties lp,
- @NonNull NetworkAgentConfig config,
- @Nullable NetworkProvider provider,
- @NonNull Callbacks cb) {
- super(context, looper, TAG, nc, lp, new NetworkScore.Builder().build(), config, provider);
- mCallbacks = cb;
- }
-
- @Override
- public void onNetworkUnwanted() {
- mCallbacks.onNetworkUnwanted();
- }
-
- // sendLinkProperties is final in NetworkAgent, so it cannot be mocked.
- public void sendLinkPropertiesImpl(LinkProperties lp) {
- sendLinkProperties(lp);
- }
-
- public Callbacks getCallbacks() {
- return mCallbacks;
- }
-}
diff --git a/java/com/android/server/ethernet/EthernetNetworkFactory.java b/java/com/android/server/ethernet/EthernetNetworkFactory.java
deleted file mode 100644
index d910629..0000000
--- a/java/com/android/server/ethernet/EthernetNetworkFactory.java
+++ /dev/null
@@ -1,785 +0,0 @@
-/*
- * Copyright (C) 2014 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 com.android.server.ethernet;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.Context;
-import android.content.res.Resources;
-import android.net.ConnectivityManager;
-import android.net.ConnectivityResources;
-import android.net.EthernetManager;
-import android.net.EthernetNetworkSpecifier;
-import android.net.EthernetNetworkManagementException;
-import android.net.INetworkInterfaceOutcomeReceiver;
-import android.net.IpConfiguration;
-import android.net.IpConfiguration.IpAssignment;
-import android.net.IpConfiguration.ProxySettings;
-import android.net.LinkProperties;
-import android.net.Network;
-import android.net.NetworkAgentConfig;
-import android.net.NetworkCapabilities;
-import android.net.NetworkFactory;
-import android.net.NetworkProvider;
-import android.net.NetworkRequest;
-import android.net.NetworkSpecifier;
-import android.net.ip.IIpClient;
-import android.net.ip.IpClientCallbacks;
-import android.net.ip.IpClientManager;
-import android.net.ip.IpClientUtil;
-import android.net.shared.ProvisioningConfiguration;
-import android.os.ConditionVariable;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.RemoteException;
-import android.text.TextUtils;
-import android.util.AndroidRuntimeException;
-import android.util.Log;
-import android.util.SparseArray;
-
-import com.android.connectivity.resources.R;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.IndentingPrintWriter;
-import com.android.net.module.util.InterfaceParams;
-
-import java.io.FileDescriptor;
-import java.util.Objects;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * {@link NetworkFactory} that represents Ethernet networks.
- *
- * This class reports a static network score of 70 when it is tracking an interface and that
- * interface's link is up, and a score of 0 otherwise.
- */
-public class EthernetNetworkFactory extends NetworkFactory {
- private final static String TAG = EthernetNetworkFactory.class.getSimpleName();
- final static boolean DBG = true;
-
- private final static int NETWORK_SCORE = 70;
- private static final String NETWORK_TYPE = "Ethernet";
- private static final String LEGACY_TCP_BUFFER_SIZES =
- "524288,1048576,3145728,524288,1048576,2097152";
-
- private final ConcurrentHashMap<String, NetworkInterfaceState> mTrackingInterfaces =
- new ConcurrentHashMap<>();
- private final Handler mHandler;
- private final Context mContext;
- final Dependencies mDeps;
-
- public static class Dependencies {
- public void makeIpClient(Context context, String iface, IpClientCallbacks callbacks) {
- IpClientUtil.makeIpClient(context, iface, callbacks);
- }
-
- public IpClientManager makeIpClientManager(@NonNull final IIpClient ipClient) {
- return new IpClientManager(ipClient, TAG);
- }
-
- public EthernetNetworkAgent makeEthernetNetworkAgent(Context context, Looper looper,
- NetworkCapabilities nc, LinkProperties lp, NetworkAgentConfig config,
- NetworkProvider provider, EthernetNetworkAgent.Callbacks cb) {
- return new EthernetNetworkAgent(context, looper, nc, lp, config, provider, cb);
- }
-
- public InterfaceParams getNetworkInterfaceByName(String name) {
- return InterfaceParams.getByName(name);
- }
-
- // TODO: remove legacy resource fallback after migrating its overlays.
- private String getPlatformTcpBufferSizes(Context context) {
- final Resources r = context.getResources();
- final int resId = r.getIdentifier("config_ethernet_tcp_buffers", "string",
- context.getPackageName());
- return r.getString(resId);
- }
-
- public String getTcpBufferSizesFromResource(Context context) {
- final String tcpBufferSizes;
- final String platformTcpBufferSizes = getPlatformTcpBufferSizes(context);
- if (!LEGACY_TCP_BUFFER_SIZES.equals(platformTcpBufferSizes)) {
- // Platform resource is not the historical default: use the overlay.
- tcpBufferSizes = platformTcpBufferSizes;
- } else {
- final ConnectivityResources resources = new ConnectivityResources(context);
- tcpBufferSizes = resources.get().getString(R.string.config_ethernet_tcp_buffers);
- }
- return tcpBufferSizes;
- }
- }
-
- public static class ConfigurationException extends AndroidRuntimeException {
- public ConfigurationException(String msg) {
- super(msg);
- }
- }
-
- public EthernetNetworkFactory(Handler handler, Context context) {
- this(handler, context, new Dependencies());
- }
-
- @VisibleForTesting
- EthernetNetworkFactory(Handler handler, Context context, Dependencies deps) {
- super(handler.getLooper(), context, NETWORK_TYPE, createDefaultNetworkCapabilities());
-
- mHandler = handler;
- mContext = context;
- mDeps = deps;
-
- setScoreFilter(NETWORK_SCORE);
- }
-
- @Override
- public boolean acceptRequest(NetworkRequest request) {
- if (DBG) {
- Log.d(TAG, "acceptRequest, request: " + request);
- }
-
- return networkForRequest(request) != null;
- }
-
- @Override
- protected void needNetworkFor(NetworkRequest networkRequest) {
- NetworkInterfaceState network = networkForRequest(networkRequest);
-
- if (network == null) {
- Log.e(TAG, "needNetworkFor, failed to get a network for " + networkRequest);
- return;
- }
-
- if (++network.refCount == 1) {
- network.start();
- }
- }
-
- @Override
- protected void releaseNetworkFor(NetworkRequest networkRequest) {
- NetworkInterfaceState network = networkForRequest(networkRequest);
- if (network == null) {
- Log.e(TAG, "releaseNetworkFor, failed to get a network for " + networkRequest);
- return;
- }
-
- if (--network.refCount == 0) {
- network.stop();
- }
- }
-
- /**
- * Returns an array of available interface names. The array is sorted: unrestricted interfaces
- * goes first, then sorted by name.
- */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- protected String[] getAvailableInterfaces(boolean includeRestricted) {
- return mTrackingInterfaces.values()
- .stream()
- .filter(iface -> !iface.isRestricted() || includeRestricted)
- .sorted((iface1, iface2) -> {
- int r = Boolean.compare(iface1.isRestricted(), iface2.isRestricted());
- return r == 0 ? iface1.name.compareTo(iface2.name) : r;
- })
- .map(iface -> iface.name)
- .toArray(String[]::new);
- }
-
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- protected void addInterface(@NonNull final String ifaceName, @NonNull final String hwAddress,
- @NonNull final IpConfiguration ipConfig,
- @NonNull final NetworkCapabilities capabilities) {
- if (mTrackingInterfaces.containsKey(ifaceName)) {
- Log.e(TAG, "Interface with name " + ifaceName + " already exists.");
- return;
- }
-
- final NetworkCapabilities nc = new NetworkCapabilities.Builder(capabilities)
- .setNetworkSpecifier(new EthernetNetworkSpecifier(ifaceName))
- .build();
-
- if (DBG) {
- Log.d(TAG, "addInterface, iface: " + ifaceName + ", capabilities: " + nc);
- }
-
- final NetworkInterfaceState iface = new NetworkInterfaceState(
- ifaceName, hwAddress, mHandler, mContext, ipConfig, nc, this, mDeps);
- mTrackingInterfaces.put(ifaceName, iface);
- updateCapabilityFilter();
- }
-
- @VisibleForTesting
- protected int getInterfaceState(@NonNull String iface) {
- final NetworkInterfaceState interfaceState = mTrackingInterfaces.get(iface);
- if (interfaceState == null) {
- return EthernetManager.STATE_ABSENT;
- } else if (!interfaceState.mLinkUp) {
- return EthernetManager.STATE_LINK_DOWN;
- } else {
- return EthernetManager.STATE_LINK_UP;
- }
- }
-
- /**
- * Update a network's configuration and restart it if necessary.
- *
- * @param ifaceName the interface name of the network to be updated.
- * @param ipConfig the desired {@link IpConfiguration} for the given network or null. If
- * {@code null} is passed, the existing IpConfiguration is not updated.
- * @param capabilities the desired {@link NetworkCapabilities} for the given network. If
- * {@code null} is passed, then the network's current
- * {@link NetworkCapabilities} will be used in support of existing APIs as
- * the public API does not allow this.
- * @param listener an optional {@link INetworkInterfaceOutcomeReceiver} to notify callers of
- * completion.
- */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- protected void updateInterface(@NonNull final String ifaceName,
- @Nullable final IpConfiguration ipConfig,
- @Nullable final NetworkCapabilities capabilities,
- @Nullable final INetworkInterfaceOutcomeReceiver listener) {
- if (!hasInterface(ifaceName)) {
- maybeSendNetworkManagementCallbackForUntracked(ifaceName, listener);
- return;
- }
-
- final NetworkInterfaceState iface = mTrackingInterfaces.get(ifaceName);
- iface.updateInterface(ipConfig, capabilities, listener);
- mTrackingInterfaces.put(ifaceName, iface);
- updateCapabilityFilter();
- }
-
- private static NetworkCapabilities mixInCapabilities(NetworkCapabilities nc,
- NetworkCapabilities addedNc) {
- final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder(nc);
- for (int transport : addedNc.getTransportTypes()) builder.addTransportType(transport);
- for (int capability : addedNc.getCapabilities()) builder.addCapability(capability);
- return builder.build();
- }
-
- private void updateCapabilityFilter() {
- NetworkCapabilities capabilitiesFilter = createDefaultNetworkCapabilities();
- for (NetworkInterfaceState iface: mTrackingInterfaces.values()) {
- capabilitiesFilter = mixInCapabilities(capabilitiesFilter, iface.mCapabilities);
- }
-
- if (DBG) Log.d(TAG, "updateCapabilityFilter: " + capabilitiesFilter);
- setCapabilityFilter(capabilitiesFilter);
- }
-
- private static NetworkCapabilities createDefaultNetworkCapabilities() {
- return NetworkCapabilities.Builder
- .withoutDefaultCapabilities()
- .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET).build();
- }
-
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- protected void removeInterface(String interfaceName) {
- NetworkInterfaceState iface = mTrackingInterfaces.remove(interfaceName);
- if (iface != null) {
- iface.maybeSendNetworkManagementCallbackForAbort();
- iface.stop();
- }
-
- updateCapabilityFilter();
- }
-
- /** Returns true if state has been modified */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- protected boolean updateInterfaceLinkState(@NonNull final String ifaceName, final boolean up,
- @Nullable final INetworkInterfaceOutcomeReceiver listener) {
- if (!hasInterface(ifaceName)) {
- maybeSendNetworkManagementCallbackForUntracked(ifaceName, listener);
- return false;
- }
-
- if (DBG) {
- Log.d(TAG, "updateInterfaceLinkState, iface: " + ifaceName + ", up: " + up);
- }
-
- NetworkInterfaceState iface = mTrackingInterfaces.get(ifaceName);
- return iface.updateLinkState(up, listener);
- }
-
- private void maybeSendNetworkManagementCallbackForUntracked(
- String ifaceName, INetworkInterfaceOutcomeReceiver listener) {
- maybeSendNetworkManagementCallback(listener, null,
- new EthernetNetworkManagementException(
- ifaceName + " can't be updated as it is not available."));
- }
-
- @VisibleForTesting
- protected boolean hasInterface(String ifaceName) {
- return mTrackingInterfaces.containsKey(ifaceName);
- }
-
- private NetworkInterfaceState networkForRequest(NetworkRequest request) {
- String requestedIface = null;
-
- NetworkSpecifier specifier = request.getNetworkSpecifier();
- if (specifier instanceof EthernetNetworkSpecifier) {
- requestedIface = ((EthernetNetworkSpecifier) specifier)
- .getInterfaceName();
- }
-
- NetworkInterfaceState network = null;
- if (!TextUtils.isEmpty(requestedIface)) {
- NetworkInterfaceState n = mTrackingInterfaces.get(requestedIface);
- if (n != null && request.canBeSatisfiedBy(n.mCapabilities)) {
- network = n;
- }
- } else {
- for (NetworkInterfaceState n : mTrackingInterfaces.values()) {
- if (request.canBeSatisfiedBy(n.mCapabilities) && n.mLinkUp) {
- network = n;
- break;
- }
- }
- }
-
- if (DBG) {
- Log.i(TAG, "networkForRequest, request: " + request + ", network: " + network);
- }
-
- return network;
- }
-
- private static void maybeSendNetworkManagementCallback(
- @Nullable final INetworkInterfaceOutcomeReceiver listener,
- @Nullable final String iface,
- @Nullable final EthernetNetworkManagementException e) {
- if (null == listener) {
- return;
- }
-
- try {
- if (iface != null) {
- listener.onResult(iface);
- } else {
- listener.onError(e);
- }
- } catch (RemoteException re) {
- Log.e(TAG, "Can't send onComplete for network management callback", re);
- }
- }
-
- @VisibleForTesting
- static class NetworkInterfaceState {
- final String name;
-
- private final String mHwAddress;
- private final Handler mHandler;
- private final Context mContext;
- private final NetworkFactory mNetworkFactory;
- private final Dependencies mDeps;
-
- private static String sTcpBufferSizes = null; // Lazy initialized.
-
- private boolean mLinkUp;
- private int mLegacyType;
- private LinkProperties mLinkProperties = new LinkProperties();
-
- private volatile @Nullable IpClientManager mIpClient;
- private @NonNull NetworkCapabilities mCapabilities;
- private @Nullable EthernetIpClientCallback mIpClientCallback;
- private @Nullable EthernetNetworkAgent mNetworkAgent;
- private @Nullable IpConfiguration mIpConfig;
-
- /**
- * A map of TRANSPORT_* types to legacy transport types available for each type an ethernet
- * interface could propagate.
- *
- * There are no legacy type equivalents to LOWPAN or WIFI_AWARE. These types are set to
- * TYPE_NONE to match the behavior of their own network factories.
- */
- private static final SparseArray<Integer> sTransports = new SparseArray();
- static {
- sTransports.put(NetworkCapabilities.TRANSPORT_ETHERNET,
- ConnectivityManager.TYPE_ETHERNET);
- sTransports.put(NetworkCapabilities.TRANSPORT_BLUETOOTH,
- ConnectivityManager.TYPE_BLUETOOTH);
- sTransports.put(NetworkCapabilities.TRANSPORT_WIFI, ConnectivityManager.TYPE_WIFI);
- sTransports.put(NetworkCapabilities.TRANSPORT_CELLULAR,
- ConnectivityManager.TYPE_MOBILE);
- sTransports.put(NetworkCapabilities.TRANSPORT_LOWPAN, ConnectivityManager.TYPE_NONE);
- sTransports.put(NetworkCapabilities.TRANSPORT_WIFI_AWARE,
- ConnectivityManager.TYPE_NONE);
- }
-
- long refCount = 0;
-
- private class EthernetIpClientCallback extends IpClientCallbacks {
- private final ConditionVariable mIpClientStartCv = new ConditionVariable(false);
- private final ConditionVariable mIpClientShutdownCv = new ConditionVariable(false);
- @Nullable INetworkInterfaceOutcomeReceiver mNetworkManagementListener;
-
- EthernetIpClientCallback(@Nullable final INetworkInterfaceOutcomeReceiver listener) {
- mNetworkManagementListener = listener;
- }
-
- @Override
- public void onIpClientCreated(IIpClient ipClient) {
- mIpClient = mDeps.makeIpClientManager(ipClient);
- mIpClientStartCv.open();
- }
-
- private void awaitIpClientStart() {
- mIpClientStartCv.block();
- }
-
- private void awaitIpClientShutdown() {
- mIpClientShutdownCv.block();
- }
-
- // At the time IpClient is stopped, an IpClient event may have already been posted on
- // the back of the handler and is awaiting execution. Once that event is executed, the
- // associated callback object may not be valid anymore
- // (NetworkInterfaceState#mIpClientCallback points to a different object / null).
- private boolean isCurrentCallback() {
- return this == mIpClientCallback;
- }
-
- private void handleIpEvent(final @NonNull Runnable r) {
- mHandler.post(() -> {
- if (!isCurrentCallback()) {
- Log.i(TAG, "Ignoring stale IpClientCallbacks " + this);
- return;
- }
- r.run();
- });
- }
-
- @Override
- public void onProvisioningSuccess(LinkProperties newLp) {
- handleIpEvent(() -> onIpLayerStarted(newLp, mNetworkManagementListener));
- }
-
- @Override
- public void onProvisioningFailure(LinkProperties newLp) {
- // This cannot happen due to provisioning timeout, because our timeout is 0. It can
- // happen due to errors while provisioning or on provisioning loss.
- handleIpEvent(() -> onIpLayerStopped(mNetworkManagementListener));
- }
-
- @Override
- public void onLinkPropertiesChange(LinkProperties newLp) {
- handleIpEvent(() -> updateLinkProperties(newLp));
- }
-
- @Override
- public void onReachabilityLost(String logMsg) {
- handleIpEvent(() -> updateNeighborLostEvent(logMsg));
- }
-
- @Override
- public void onQuit() {
- mIpClient = null;
- mIpClientShutdownCv.open();
- }
- }
-
- NetworkInterfaceState(String ifaceName, String hwAddress, Handler handler, Context context,
- @NonNull IpConfiguration ipConfig, @NonNull NetworkCapabilities capabilities,
- NetworkFactory networkFactory, Dependencies deps) {
- name = ifaceName;
- mIpConfig = Objects.requireNonNull(ipConfig);
- mCapabilities = Objects.requireNonNull(capabilities);
- mLegacyType = getLegacyType(mCapabilities);
- mHandler = handler;
- mContext = context;
- mNetworkFactory = networkFactory;
- mDeps = deps;
- mHwAddress = hwAddress;
- }
-
- /**
- * Determines the legacy transport type from a NetworkCapabilities transport type. Defaults
- * to legacy TYPE_NONE if there is no known conversion
- */
- private static int getLegacyType(int transport) {
- return sTransports.get(transport, ConnectivityManager.TYPE_NONE);
- }
-
- private static int getLegacyType(@NonNull final NetworkCapabilities capabilities) {
- final int[] transportTypes = capabilities.getTransportTypes();
- if (transportTypes.length > 0) {
- return getLegacyType(transportTypes[0]);
- }
-
- // Should never happen as transport is always one of ETHERNET or a valid override
- throw new ConfigurationException("Network Capabilities do not have an associated "
- + "transport type.");
- }
-
- private void setCapabilities(@NonNull final NetworkCapabilities capabilities) {
- mCapabilities = new NetworkCapabilities(capabilities);
- mLegacyType = getLegacyType(mCapabilities);
- }
-
- void updateInterface(@Nullable final IpConfiguration ipConfig,
- @Nullable final NetworkCapabilities capabilities,
- @Nullable final INetworkInterfaceOutcomeReceiver listener) {
- if (DBG) {
- Log.d(TAG, "updateInterface, iface: " + name
- + ", ipConfig: " + ipConfig + ", old ipConfig: " + mIpConfig
- + ", capabilities: " + capabilities + ", old capabilities: " + mCapabilities
- + ", listener: " + listener
- );
- }
-
- if (null != ipConfig){
- mIpConfig = ipConfig;
- }
- if (null != capabilities) {
- setCapabilities(capabilities);
- }
- // Send an abort callback if a request is filed before the previous one has completed.
- maybeSendNetworkManagementCallbackForAbort();
- // TODO: Update this logic to only do a restart if required. Although a restart may
- // be required due to the capabilities or ipConfiguration values, not all
- // capabilities changes require a restart.
- restart(listener);
- }
-
- boolean isRestricted() {
- return !mCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
- }
-
- private void start() {
- start(null);
- }
-
- private void start(@Nullable final INetworkInterfaceOutcomeReceiver listener) {
- if (mIpClient != null) {
- if (DBG) Log.d(TAG, "IpClient already started");
- return;
- }
- if (DBG) {
- Log.d(TAG, String.format("Starting Ethernet IpClient(%s)", name));
- }
-
- mIpClientCallback = new EthernetIpClientCallback(listener);
- mDeps.makeIpClient(mContext, name, mIpClientCallback);
- mIpClientCallback.awaitIpClientStart();
-
- if (sTcpBufferSizes == null) {
- sTcpBufferSizes = mDeps.getTcpBufferSizesFromResource(mContext);
- }
- provisionIpClient(mIpClient, mIpConfig, sTcpBufferSizes);
- }
-
- void onIpLayerStarted(@NonNull final LinkProperties linkProperties,
- @Nullable final INetworkInterfaceOutcomeReceiver listener) {
- if (mNetworkAgent != null) {
- Log.e(TAG, "Already have a NetworkAgent - aborting new request");
- stop();
- return;
- }
- mLinkProperties = linkProperties;
-
- // Create our NetworkAgent.
- final NetworkAgentConfig config = new NetworkAgentConfig.Builder()
- .setLegacyType(mLegacyType)
- .setLegacyTypeName(NETWORK_TYPE)
- .setLegacyExtraInfo(mHwAddress)
- .build();
- mNetworkAgent = mDeps.makeEthernetNetworkAgent(mContext, mHandler.getLooper(),
- mCapabilities, mLinkProperties, config, mNetworkFactory.getProvider(),
- new EthernetNetworkAgent.Callbacks() {
- @Override
- public void onNetworkUnwanted() {
- // if mNetworkAgent is null, we have already called stop.
- if (mNetworkAgent == null) return;
-
- if (this == mNetworkAgent.getCallbacks()) {
- stop();
- } else {
- Log.d(TAG, "Ignoring unwanted as we have a more modern " +
- "instance");
- }
- }
- });
- mNetworkAgent.register();
- mNetworkAgent.markConnected();
- realizeNetworkManagementCallback(name, null);
- }
-
- void onIpLayerStopped(@Nullable final INetworkInterfaceOutcomeReceiver listener) {
- // There is no point in continuing if the interface is gone as stop() will be triggered
- // by removeInterface() when processed on the handler thread and start() won't
- // work for a non-existent interface.
- if (null == mDeps.getNetworkInterfaceByName(name)) {
- if (DBG) Log.d(TAG, name + " is no longer available.");
- // Send a callback in case a provisioning request was in progress.
- maybeSendNetworkManagementCallbackForAbort();
- return;
- }
- restart(listener);
- }
-
- private void maybeSendNetworkManagementCallbackForAbort() {
- realizeNetworkManagementCallback(null,
- new EthernetNetworkManagementException(
- "The IP provisioning request has been aborted."));
- }
-
- // Must be called on the handler thread
- private void realizeNetworkManagementCallback(@Nullable final String iface,
- @Nullable final EthernetNetworkManagementException e) {
- ensureRunningOnEthernetHandlerThread();
- if (null == mIpClientCallback) {
- return;
- }
-
- EthernetNetworkFactory.maybeSendNetworkManagementCallback(
- mIpClientCallback.mNetworkManagementListener, iface, e);
- // Only send a single callback per listener.
- mIpClientCallback.mNetworkManagementListener = null;
- }
-
- private void ensureRunningOnEthernetHandlerThread() {
- if (mHandler.getLooper().getThread() != Thread.currentThread()) {
- throw new IllegalStateException(
- "Not running on the Ethernet thread: "
- + Thread.currentThread().getName());
- }
- }
-
- void updateLinkProperties(LinkProperties linkProperties) {
- mLinkProperties = linkProperties;
- if (mNetworkAgent != null) {
- mNetworkAgent.sendLinkPropertiesImpl(linkProperties);
- }
- }
-
- void updateNeighborLostEvent(String logMsg) {
- Log.i(TAG, "updateNeighborLostEvent " + logMsg);
- // Reachability lost will be seen only if the gateway is not reachable.
- // Since ethernet FW doesn't have the mechanism to scan for new networks
- // like WiFi, simply restart.
- // If there is a better network, that will become default and apps
- // will be able to use internet. If ethernet gets connected again,
- // and has backhaul connectivity, it will become default.
- restart();
- }
-
- /** Returns true if state has been modified */
- boolean updateLinkState(final boolean up,
- @Nullable final INetworkInterfaceOutcomeReceiver listener) {
- if (mLinkUp == up) {
- EthernetNetworkFactory.maybeSendNetworkManagementCallback(listener, null,
- new EthernetNetworkManagementException(
- "No changes with requested link state " + up + " for " + name));
- return false;
- }
- mLinkUp = up;
-
- if (!up) { // was up, goes down
- // Send an abort on a provisioning request callback if necessary before stopping.
- maybeSendNetworkManagementCallbackForAbort();
- stop();
- // If only setting the interface down, send a callback to signal completion.
- EthernetNetworkFactory.maybeSendNetworkManagementCallback(listener, name, null);
- } else { // was down, goes up
- stop();
- start(listener);
- }
-
- return true;
- }
-
- void stop() {
- // Invalidate all previous start requests
- if (mIpClient != null) {
- mIpClient.shutdown();
- mIpClientCallback.awaitIpClientShutdown();
- mIpClient = null;
- }
- mIpClientCallback = null;
-
- if (mNetworkAgent != null) {
- mNetworkAgent.unregister();
- mNetworkAgent = null;
- }
- mLinkProperties.clear();
- }
-
- private static void provisionIpClient(@NonNull final IpClientManager ipClient,
- @NonNull final IpConfiguration config, @NonNull final String tcpBufferSizes) {
- if (config.getProxySettings() == ProxySettings.STATIC ||
- config.getProxySettings() == ProxySettings.PAC) {
- ipClient.setHttpProxy(config.getHttpProxy());
- }
-
- if (!TextUtils.isEmpty(tcpBufferSizes)) {
- ipClient.setTcpBufferSizes(tcpBufferSizes);
- }
-
- ipClient.startProvisioning(createProvisioningConfiguration(config));
- }
-
- private static ProvisioningConfiguration createProvisioningConfiguration(
- @NonNull final IpConfiguration config) {
- if (config.getIpAssignment() == IpAssignment.STATIC) {
- return new ProvisioningConfiguration.Builder()
- .withStaticConfiguration(config.getStaticIpConfiguration())
- .build();
- }
- return new ProvisioningConfiguration.Builder()
- .withProvisioningTimeoutMs(0)
- .build();
- }
-
- void restart() {
- restart(null);
- }
-
- void restart(@Nullable final INetworkInterfaceOutcomeReceiver listener) {
- if (DBG) Log.d(TAG, "reconnecting Ethernet");
- stop();
- start(listener);
- }
-
- @Override
- public String toString() {
- return getClass().getSimpleName() + "{ "
- + "refCount: " + refCount + ", "
- + "iface: " + name + ", "
- + "up: " + mLinkUp + ", "
- + "hwAddress: " + mHwAddress + ", "
- + "networkCapabilities: " + mCapabilities + ", "
- + "networkAgent: " + mNetworkAgent + ", "
- + "ipClient: " + mIpClient + ","
- + "linkProperties: " + mLinkProperties
- + "}";
- }
- }
-
- void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) {
- super.dump(fd, pw, args);
- pw.println(getClass().getSimpleName());
- pw.println("Tracking interfaces:");
- pw.increaseIndent();
- for (String iface: mTrackingInterfaces.keySet()) {
- NetworkInterfaceState ifaceState = mTrackingInterfaces.get(iface);
- pw.println(iface + ":" + ifaceState);
- pw.increaseIndent();
- if (null == ifaceState.mIpClient) {
- pw.println("IpClient is null");
- }
- pw.decreaseIndent();
- }
- pw.decreaseIndent();
- }
-}
diff --git a/java/com/android/server/ethernet/EthernetService.java b/java/com/android/server/ethernet/EthernetService.java
deleted file mode 100644
index d405fd5..0000000
--- a/java/com/android/server/ethernet/EthernetService.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2014 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 com.android.server.ethernet;
-
-import android.content.Context;
-import android.net.INetd;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.IBinder;
-
-import java.util.Objects;
-
-// TODO: consider renaming EthernetServiceImpl to EthernetService and deleting this file.
-public final class EthernetService {
- private static final String TAG = "EthernetService";
- private static final String THREAD_NAME = "EthernetServiceThread";
-
- private static INetd getNetd(Context context) {
- final INetd netd =
- INetd.Stub.asInterface((IBinder) context.getSystemService(Context.NETD_SERVICE));
- Objects.requireNonNull(netd, "could not get netd instance");
- return netd;
- }
-
- public static EthernetServiceImpl create(Context context) {
- final HandlerThread handlerThread = new HandlerThread(THREAD_NAME);
- handlerThread.start();
- final Handler handler = new Handler(handlerThread.getLooper());
- final EthernetNetworkFactory factory = new EthernetNetworkFactory(handler, context);
- return new EthernetServiceImpl(context, handler,
- new EthernetTracker(context, handler, factory, getNetd(context)));
- }
-}
diff --git a/java/com/android/server/ethernet/EthernetServiceImpl.java b/java/com/android/server/ethernet/EthernetServiceImpl.java
deleted file mode 100644
index 5e830ad..0000000
--- a/java/com/android/server/ethernet/EthernetServiceImpl.java
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Copyright (C) 2014 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 com.android.server.ethernet;
-
-import static android.net.NetworkCapabilities.TRANSPORT_TEST;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.net.IEthernetManager;
-import android.net.IEthernetServiceListener;
-import android.net.INetworkInterfaceOutcomeReceiver;
-import android.net.ITetheredInterfaceCallback;
-import android.net.EthernetNetworkUpdateRequest;
-import android.net.IpConfiguration;
-import android.net.NetworkCapabilities;
-import android.os.Binder;
-import android.os.Handler;
-import android.os.RemoteException;
-import android.util.Log;
-import android.util.PrintWriterPrinter;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.IndentingPrintWriter;
-import com.android.net.module.util.PermissionUtils;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.List;
-import java.util.Objects;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * EthernetServiceImpl handles remote Ethernet operation requests by implementing
- * the IEthernetManager interface.
- */
-public class EthernetServiceImpl extends IEthernetManager.Stub {
- private static final String TAG = "EthernetServiceImpl";
-
- @VisibleForTesting
- final AtomicBoolean mStarted = new AtomicBoolean(false);
- private final Context mContext;
- private final Handler mHandler;
- private final EthernetTracker mTracker;
-
- EthernetServiceImpl(@NonNull final Context context, @NonNull final Handler handler,
- @NonNull final EthernetTracker tracker) {
- mContext = context;
- mHandler = handler;
- mTracker = tracker;
- }
-
- private void enforceAutomotiveDevice(final @NonNull String methodName) {
- PermissionUtils.enforceSystemFeature(mContext, PackageManager.FEATURE_AUTOMOTIVE,
- methodName + " is only available on automotive devices.");
- }
-
- private boolean checkUseRestrictedNetworksPermission() {
- return PermissionUtils.checkAnyPermissionOf(mContext,
- android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS);
- }
-
- public void start() {
- Log.i(TAG, "Starting Ethernet service");
- mTracker.start();
- mStarted.set(true);
- }
-
- private void throwIfEthernetNotStarted() {
- if (!mStarted.get()) {
- throw new IllegalStateException("System isn't ready to change ethernet configurations");
- }
- }
-
- @Override
- public String[] getAvailableInterfaces() throws RemoteException {
- PermissionUtils.enforceAccessNetworkStatePermission(mContext, TAG);
- return mTracker.getInterfaces(checkUseRestrictedNetworksPermission());
- }
-
- /**
- * Get Ethernet configuration
- * @return the Ethernet Configuration, contained in {@link IpConfiguration}.
- */
- @Override
- public IpConfiguration getConfiguration(String iface) {
- PermissionUtils.enforceAccessNetworkStatePermission(mContext, TAG);
- if (mTracker.isRestrictedInterface(iface)) {
- PermissionUtils.enforceRestrictedNetworkPermission(mContext, TAG);
- }
-
- return new IpConfiguration(mTracker.getIpConfiguration(iface));
- }
-
- /**
- * Set Ethernet configuration
- */
- @Override
- public void setConfiguration(String iface, IpConfiguration config) {
- throwIfEthernetNotStarted();
-
- PermissionUtils.enforceNetworkStackPermission(mContext);
- if (mTracker.isRestrictedInterface(iface)) {
- PermissionUtils.enforceRestrictedNetworkPermission(mContext, TAG);
- }
-
- // TODO: this does not check proxy settings, gateways, etc.
- // Fix this by making IpConfiguration a complete representation of static configuration.
- mTracker.updateIpConfiguration(iface, new IpConfiguration(config));
- }
-
- /**
- * Indicates whether given interface is available.
- */
- @Override
- public boolean isAvailable(String iface) {
- PermissionUtils.enforceAccessNetworkStatePermission(mContext, TAG);
- if (mTracker.isRestrictedInterface(iface)) {
- PermissionUtils.enforceRestrictedNetworkPermission(mContext, TAG);
- }
-
- return mTracker.isTrackingInterface(iface);
- }
-
- /**
- * Adds a listener.
- * @param listener A {@link IEthernetServiceListener} to add.
- */
- public void addListener(IEthernetServiceListener listener) throws RemoteException {
- Objects.requireNonNull(listener, "listener must not be null");
- PermissionUtils.enforceAccessNetworkStatePermission(mContext, TAG);
- mTracker.addListener(listener, checkUseRestrictedNetworksPermission());
- }
-
- /**
- * Removes a listener.
- * @param listener A {@link IEthernetServiceListener} to remove.
- */
- public void removeListener(IEthernetServiceListener listener) {
- if (listener == null) {
- throw new IllegalArgumentException("listener must not be null");
- }
- PermissionUtils.enforceAccessNetworkStatePermission(mContext, TAG);
- mTracker.removeListener(listener);
- }
-
- @Override
- public void setIncludeTestInterfaces(boolean include) {
- PermissionUtils.enforceNetworkStackPermissionOr(mContext,
- android.Manifest.permission.NETWORK_SETTINGS);
- mTracker.setIncludeTestInterfaces(include);
- }
-
- @Override
- public void requestTetheredInterface(ITetheredInterfaceCallback callback) {
- Objects.requireNonNull(callback, "callback must not be null");
- PermissionUtils.enforceNetworkStackPermissionOr(mContext,
- android.Manifest.permission.NETWORK_SETTINGS);
- mTracker.requestTetheredInterface(callback);
- }
-
- @Override
- public void releaseTetheredInterface(ITetheredInterfaceCallback callback) {
- Objects.requireNonNull(callback, "callback must not be null");
- PermissionUtils.enforceNetworkStackPermissionOr(mContext,
- android.Manifest.permission.NETWORK_SETTINGS);
- mTracker.releaseTetheredInterface(callback);
- }
-
- @Override
- protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
- final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump EthernetService from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
-
- pw.println("Current Ethernet state: ");
- pw.increaseIndent();
- mTracker.dump(fd, pw, args);
- pw.decreaseIndent();
-
- pw.println("Handler:");
- pw.increaseIndent();
- mHandler.dump(new PrintWriterPrinter(pw), "EthernetServiceImpl");
- pw.decreaseIndent();
- }
-
- private void enforceNetworkManagementPermission() {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.MANAGE_ETHERNET_NETWORKS,
- "EthernetServiceImpl");
- }
-
- private void enforceManageTestNetworksPermission() {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.MANAGE_TEST_NETWORKS,
- "EthernetServiceImpl");
- }
-
- private void maybeValidateTestCapabilities(final String iface,
- @Nullable final NetworkCapabilities nc) {
- if (!mTracker.isValidTestInterface(iface)) {
- return;
- }
- // For test interfaces, only null or capabilities that include TRANSPORT_TEST are
- // allowed.
- if (nc != null && !nc.hasTransport(TRANSPORT_TEST)) {
- throw new IllegalArgumentException(
- "Updates to test interfaces must have NetworkCapabilities.TRANSPORT_TEST.");
- }
- }
-
- private void enforceAdminPermission(final String iface, boolean enforceAutomotive,
- final String logMessage) {
- if (mTracker.isValidTestInterface(iface)) {
- enforceManageTestNetworksPermission();
- } else {
- enforceNetworkManagementPermission();
- if (enforceAutomotive) {
- enforceAutomotiveDevice(logMessage);
- }
- }
- }
-
- @Override
- public void updateConfiguration(@NonNull final String iface,
- @NonNull final EthernetNetworkUpdateRequest request,
- @Nullable final INetworkInterfaceOutcomeReceiver listener) {
- Objects.requireNonNull(iface);
- Objects.requireNonNull(request);
- throwIfEthernetNotStarted();
-
- // TODO: validate that iface is listed in overlay config_ethernet_interfaces
- // only automotive devices are allowed to set the NetworkCapabilities using this API
- enforceAdminPermission(iface, request.getNetworkCapabilities() != null,
- "updateConfiguration() with non-null capabilities");
- maybeValidateTestCapabilities(iface, request.getNetworkCapabilities());
-
- mTracker.updateConfiguration(
- iface, request.getIpConfiguration(), request.getNetworkCapabilities(), listener);
- }
-
- @Override
- public void connectNetwork(@NonNull final String iface,
- @Nullable final INetworkInterfaceOutcomeReceiver listener) {
- Log.i(TAG, "connectNetwork called with: iface=" + iface + ", listener=" + listener);
- Objects.requireNonNull(iface);
- throwIfEthernetNotStarted();
-
- enforceAdminPermission(iface, true, "connectNetwork()");
-
- mTracker.connectNetwork(iface, listener);
- }
-
- @Override
- public void disconnectNetwork(@NonNull final String iface,
- @Nullable final INetworkInterfaceOutcomeReceiver listener) {
- Log.i(TAG, "disconnectNetwork called with: iface=" + iface + ", listener=" + listener);
- Objects.requireNonNull(iface);
- throwIfEthernetNotStarted();
-
- enforceAdminPermission(iface, true, "connectNetwork()");
-
- mTracker.disconnectNetwork(iface, listener);
- }
-
- @Override
- public void setEthernetEnabled(boolean enabled) {
- PermissionUtils.enforceNetworkStackPermissionOr(mContext,
- android.Manifest.permission.NETWORK_SETTINGS);
-
- mTracker.setEthernetEnabled(enabled);
- }
-
- @Override
- public List<String> getInterfaceList() {
- PermissionUtils.enforceAccessNetworkStatePermission(mContext, TAG);
- return mTracker.getInterfaceList();
- }
-}
diff --git a/java/com/android/server/ethernet/EthernetTracker.java b/java/com/android/server/ethernet/EthernetTracker.java
deleted file mode 100644
index c291b3f..0000000
--- a/java/com/android/server/ethernet/EthernetTracker.java
+++ /dev/null
@@ -1,942 +0,0 @@
-/*
- * Copyright (C) 2018 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 com.android.server.ethernet;
-
-import static android.net.EthernetManager.ETHERNET_STATE_DISABLED;
-import static android.net.EthernetManager.ETHERNET_STATE_ENABLED;
-import static android.net.TestNetworkManager.TEST_TAP_PREFIX;
-
-import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.Context;
-import android.content.res.Resources;
-import android.net.ConnectivityResources;
-import android.net.EthernetManager;
-import android.net.IEthernetServiceListener;
-import android.net.INetworkInterfaceOutcomeReceiver;
-import android.net.INetd;
-import android.net.ITetheredInterfaceCallback;
-import android.net.InterfaceConfigurationParcel;
-import android.net.IpConfiguration;
-import android.net.IpConfiguration.IpAssignment;
-import android.net.IpConfiguration.ProxySettings;
-import android.net.LinkAddress;
-import android.net.NetworkCapabilities;
-import android.net.StaticIpConfiguration;
-import android.os.ConditionVariable;
-import android.os.Handler;
-import android.os.RemoteCallbackList;
-import android.os.RemoteException;
-import android.os.ServiceSpecificException;
-import android.text.TextUtils;
-import android.util.ArrayMap;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.IndentingPrintWriter;
-import com.android.net.module.util.BaseNetdUnsolicitedEventListener;
-import com.android.net.module.util.NetdUtils;
-import com.android.net.module.util.PermissionUtils;
-
-import java.io.FileDescriptor;
-import java.net.InetAddress;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * Tracks Ethernet interfaces and manages interface configurations.
- *
- * <p>Interfaces may have different {@link android.net.NetworkCapabilities}. This mapping is defined
- * in {@code config_ethernet_interfaces}. Notably, some interfaces could be marked as restricted by
- * not specifying {@link android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED} flag.
- * Interfaces could have associated {@link android.net.IpConfiguration}.
- * Ethernet Interfaces may be present at boot time or appear after boot (e.g., for Ethernet adapters
- * connected over USB). This class supports multiple interfaces. When an interface appears on the
- * system (or is present at boot time) this class will start tracking it and bring it up. Only
- * interfaces whose names match the {@code config_ethernet_iface_regex} regular expression are
- * tracked.
- *
- * <p>All public or package private methods must be thread-safe unless stated otherwise.
- */
-@VisibleForTesting(visibility = PACKAGE)
-public class EthernetTracker {
- private static final int INTERFACE_MODE_CLIENT = 1;
- private static final int INTERFACE_MODE_SERVER = 2;
-
- private static final String TAG = EthernetTracker.class.getSimpleName();
- private static final boolean DBG = EthernetNetworkFactory.DBG;
-
- private static final String TEST_IFACE_REGEXP = TEST_TAP_PREFIX + "\\d+";
- private static final String LEGACY_IFACE_REGEXP = "eth\\d";
-
- /**
- * Interface names we track. This is a product-dependent regular expression, plus,
- * if setIncludeTestInterfaces is true, any test interfaces.
- */
- private volatile String mIfaceMatch;
- /**
- * Track test interfaces if true, don't track otherwise.
- */
- private boolean mIncludeTestInterfaces = false;
-
- /** Mapping between {iface name | mac address} -> {NetworkCapabilities} */
- private final ConcurrentHashMap<String, NetworkCapabilities> mNetworkCapabilities =
- new ConcurrentHashMap<>();
- private final ConcurrentHashMap<String, IpConfiguration> mIpConfigurations =
- new ConcurrentHashMap<>();
-
- private final Context mContext;
- private final INetd mNetd;
- private final Handler mHandler;
- private final EthernetNetworkFactory mFactory;
- private final EthernetConfigStore mConfigStore;
- private final Dependencies mDeps;
-
- private final RemoteCallbackList<IEthernetServiceListener> mListeners =
- new RemoteCallbackList<>();
- private final TetheredInterfaceRequestList mTetheredInterfaceRequests =
- new TetheredInterfaceRequestList();
-
- // Used only on the handler thread
- private String mDefaultInterface;
- private int mDefaultInterfaceMode = INTERFACE_MODE_CLIENT;
- // Tracks whether clients were notified that the tethered interface is available
- private boolean mTetheredInterfaceWasAvailable = false;
- private volatile IpConfiguration mIpConfigForDefaultInterface;
-
- private int mEthernetState = ETHERNET_STATE_ENABLED;
-
- private class TetheredInterfaceRequestList extends
- RemoteCallbackList<ITetheredInterfaceCallback> {
- @Override
- public void onCallbackDied(ITetheredInterfaceCallback cb, Object cookie) {
- mHandler.post(EthernetTracker.this::maybeUntetherDefaultInterface);
- }
- }
-
- public static class Dependencies {
- // TODO: remove legacy resource fallback after migrating its overlays.
- private String getPlatformRegexResource(Context context) {
- final Resources r = context.getResources();
- final int resId =
- r.getIdentifier("config_ethernet_iface_regex", "string", context.getPackageName());
- return r.getString(resId);
- }
-
- // TODO: remove legacy resource fallback after migrating its overlays.
- private String[] getPlatformInterfaceConfigs(Context context) {
- final Resources r = context.getResources();
- final int resId = r.getIdentifier("config_ethernet_interfaces", "array",
- context.getPackageName());
- return r.getStringArray(resId);
- }
-
- public String getInterfaceRegexFromResource(Context context) {
- final String platformRegex = getPlatformRegexResource(context);
- final String match;
- if (!LEGACY_IFACE_REGEXP.equals(platformRegex)) {
- // Platform resource is not the historical default: use the overlay
- match = platformRegex;
- } else {
- final ConnectivityResources resources = new ConnectivityResources(context);
- match = resources.get().getString(
- com.android.connectivity.resources.R.string.config_ethernet_iface_regex);
- }
- return match;
- }
-
- public String[] getInterfaceConfigFromResource(Context context) {
- final String[] platformInterfaceConfigs = getPlatformInterfaceConfigs(context);
- final String[] interfaceConfigs;
- if (platformInterfaceConfigs.length != 0) {
- // Platform resource is not the historical default: use the overlay
- interfaceConfigs = platformInterfaceConfigs;
- } else {
- final ConnectivityResources resources = new ConnectivityResources(context);
- interfaceConfigs = resources.get().getStringArray(
- com.android.connectivity.resources.R.array.config_ethernet_interfaces);
- }
- return interfaceConfigs;
- }
- }
-
- EthernetTracker(@NonNull final Context context, @NonNull final Handler handler,
- @NonNull final EthernetNetworkFactory factory, @NonNull final INetd netd) {
- this(context, handler, factory, netd, new Dependencies());
- }
-
- @VisibleForTesting
- EthernetTracker(@NonNull final Context context, @NonNull final Handler handler,
- @NonNull final EthernetNetworkFactory factory, @NonNull final INetd netd,
- @NonNull final Dependencies deps) {
- mContext = context;
- mHandler = handler;
- mFactory = factory;
- mNetd = netd;
- mDeps = deps;
-
- // Interface match regex.
- updateIfaceMatchRegexp();
-
- // Read default Ethernet interface configuration from resources
- final String[] interfaceConfigs = mDeps.getInterfaceConfigFromResource(context);
- for (String strConfig : interfaceConfigs) {
- parseEthernetConfig(strConfig);
- }
-
- mConfigStore = new EthernetConfigStore();
- }
-
- void start() {
- mFactory.register();
- mConfigStore.read();
-
- // Default interface is just the first one we want to track.
- mIpConfigForDefaultInterface = mConfigStore.getIpConfigurationForDefaultInterface();
- final ArrayMap<String, IpConfiguration> configs = mConfigStore.getIpConfigurations();
- for (int i = 0; i < configs.size(); i++) {
- mIpConfigurations.put(configs.keyAt(i), configs.valueAt(i));
- }
-
- try {
- PermissionUtils.enforceNetworkStackPermission(mContext);
- mNetd.registerUnsolicitedEventListener(new InterfaceObserver());
- } catch (RemoteException | ServiceSpecificException e) {
- Log.e(TAG, "Could not register InterfaceObserver " + e);
- }
-
- mHandler.post(this::trackAvailableInterfaces);
- }
-
- void updateIpConfiguration(String iface, IpConfiguration ipConfiguration) {
- if (DBG) {
- Log.i(TAG, "updateIpConfiguration, iface: " + iface + ", cfg: " + ipConfiguration);
- }
- writeIpConfiguration(iface, ipConfiguration);
- mHandler.post(() -> {
- mFactory.updateInterface(iface, ipConfiguration, null, null);
- broadcastInterfaceStateChange(iface);
- });
- }
-
- private void writeIpConfiguration(@NonNull final String iface,
- @NonNull final IpConfiguration ipConfig) {
- mConfigStore.write(iface, ipConfig);
- mIpConfigurations.put(iface, ipConfig);
- }
-
- private IpConfiguration getIpConfigurationForCallback(String iface, int state) {
- return (state == EthernetManager.STATE_ABSENT) ? null : getOrCreateIpConfiguration(iface);
- }
-
- private void ensureRunningOnEthernetServiceThread() {
- if (mHandler.getLooper().getThread() != Thread.currentThread()) {
- throw new IllegalStateException(
- "Not running on EthernetService thread: "
- + Thread.currentThread().getName());
- }
- }
-
- /**
- * Broadcast the link state or IpConfiguration change of existing Ethernet interfaces to all
- * listeners.
- */
- protected void broadcastInterfaceStateChange(@NonNull String iface) {
- ensureRunningOnEthernetServiceThread();
- final int state = mFactory.getInterfaceState(iface);
- final int role = getInterfaceRole(iface);
- final IpConfiguration config = getIpConfigurationForCallback(iface, state);
- final int n = mListeners.beginBroadcast();
- for (int i = 0; i < n; i++) {
- try {
- mListeners.getBroadcastItem(i).onInterfaceStateChanged(iface, state, role, config);
- } catch (RemoteException e) {
- // Do nothing here.
- }
- }
- mListeners.finishBroadcast();
- }
-
- /**
- * Unicast the interface state or IpConfiguration change of existing Ethernet interfaces to a
- * specific listener.
- */
- protected void unicastInterfaceStateChange(@NonNull IEthernetServiceListener listener,
- @NonNull String iface) {
- ensureRunningOnEthernetServiceThread();
- final int state = mFactory.getInterfaceState(iface);
- final int role = getInterfaceRole(iface);
- final IpConfiguration config = getIpConfigurationForCallback(iface, state);
- try {
- listener.onInterfaceStateChanged(iface, state, role, config);
- } catch (RemoteException e) {
- // Do nothing here.
- }
- }
-
- @VisibleForTesting(visibility = PACKAGE)
- protected void updateConfiguration(@NonNull final String iface,
- @Nullable final IpConfiguration ipConfig,
- @Nullable final NetworkCapabilities capabilities,
- @Nullable final INetworkInterfaceOutcomeReceiver listener) {
- if (DBG) {
- Log.i(TAG, "updateConfiguration, iface: " + iface + ", capabilities: " + capabilities
- + ", ipConfig: " + ipConfig);
- }
-
- final IpConfiguration localIpConfig = ipConfig == null
- ? null : new IpConfiguration(ipConfig);
- if (ipConfig != null) {
- writeIpConfiguration(iface, localIpConfig);
- }
-
- if (null != capabilities) {
- mNetworkCapabilities.put(iface, capabilities);
- }
- mHandler.post(() -> {
- mFactory.updateInterface(iface, localIpConfig, capabilities, listener);
- broadcastInterfaceStateChange(iface);
- });
- }
-
- @VisibleForTesting(visibility = PACKAGE)
- protected void connectNetwork(@NonNull final String iface,
- @Nullable final INetworkInterfaceOutcomeReceiver listener) {
- mHandler.post(() -> updateInterfaceState(iface, true, listener));
- }
-
- @VisibleForTesting(visibility = PACKAGE)
- protected void disconnectNetwork(@NonNull final String iface,
- @Nullable final INetworkInterfaceOutcomeReceiver listener) {
- mHandler.post(() -> updateInterfaceState(iface, false, listener));
- }
-
- IpConfiguration getIpConfiguration(String iface) {
- return mIpConfigurations.get(iface);
- }
-
- @VisibleForTesting(visibility = PACKAGE)
- protected boolean isTrackingInterface(String iface) {
- return mFactory.hasInterface(iface);
- }
-
- String[] getInterfaces(boolean includeRestricted) {
- return mFactory.getAvailableInterfaces(includeRestricted);
- }
-
- List<String> getInterfaceList() {
- final List<String> interfaceList = new ArrayList<String>();
- final String[] ifaces;
- try {
- ifaces = mNetd.interfaceGetList();
- } catch (RemoteException e) {
- Log.e(TAG, "Could not get list of interfaces " + e);
- return interfaceList;
- }
- final String ifaceMatch = mIfaceMatch;
- for (String iface : ifaces) {
- if (iface.matches(ifaceMatch)) interfaceList.add(iface);
- }
- return interfaceList;
- }
-
- /**
- * Returns true if given interface was configured as restricted (doesn't have
- * NET_CAPABILITY_NOT_RESTRICTED) capability. Otherwise, returns false.
- */
- boolean isRestrictedInterface(String iface) {
- final NetworkCapabilities nc = mNetworkCapabilities.get(iface);
- return nc != null && !nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
- }
-
- void addListener(IEthernetServiceListener listener, boolean canUseRestrictedNetworks) {
- mHandler.post(() -> {
- if (!mListeners.register(listener, new ListenerInfo(canUseRestrictedNetworks))) {
- // Remote process has already died
- return;
- }
- for (String iface : getInterfaces(canUseRestrictedNetworks)) {
- unicastInterfaceStateChange(listener, iface);
- }
-
- unicastEthernetStateChange(listener, mEthernetState);
- });
- }
-
- void removeListener(IEthernetServiceListener listener) {
- mHandler.post(() -> mListeners.unregister(listener));
- }
-
- public void setIncludeTestInterfaces(boolean include) {
- mHandler.post(() -> {
- mIncludeTestInterfaces = include;
- updateIfaceMatchRegexp();
- mHandler.post(() -> trackAvailableInterfaces());
- });
- }
-
- public void requestTetheredInterface(ITetheredInterfaceCallback callback) {
- mHandler.post(() -> {
- if (!mTetheredInterfaceRequests.register(callback)) {
- // Remote process has already died
- return;
- }
- if (mDefaultInterfaceMode == INTERFACE_MODE_SERVER) {
- if (mTetheredInterfaceWasAvailable) {
- notifyTetheredInterfaceAvailable(callback, mDefaultInterface);
- }
- return;
- }
-
- setDefaultInterfaceMode(INTERFACE_MODE_SERVER);
- });
- }
-
- public void releaseTetheredInterface(ITetheredInterfaceCallback callback) {
- mHandler.post(() -> {
- mTetheredInterfaceRequests.unregister(callback);
- maybeUntetherDefaultInterface();
- });
- }
-
- private void notifyTetheredInterfaceAvailable(ITetheredInterfaceCallback cb, String iface) {
- try {
- cb.onAvailable(iface);
- } catch (RemoteException e) {
- Log.e(TAG, "Error sending tethered interface available callback", e);
- }
- }
-
- private void notifyTetheredInterfaceUnavailable(ITetheredInterfaceCallback cb) {
- try {
- cb.onUnavailable();
- } catch (RemoteException e) {
- Log.e(TAG, "Error sending tethered interface available callback", e);
- }
- }
-
- private void maybeUntetherDefaultInterface() {
- if (mTetheredInterfaceRequests.getRegisteredCallbackCount() > 0) return;
- if (mDefaultInterfaceMode == INTERFACE_MODE_CLIENT) return;
- setDefaultInterfaceMode(INTERFACE_MODE_CLIENT);
- }
-
- private void setDefaultInterfaceMode(int mode) {
- Log.d(TAG, "Setting default interface mode to " + mode);
- mDefaultInterfaceMode = mode;
- if (mDefaultInterface != null) {
- removeInterface(mDefaultInterface);
- addInterface(mDefaultInterface);
- }
- }
-
- private int getInterfaceRole(final String iface) {
- if (!mFactory.hasInterface(iface)) return EthernetManager.ROLE_NONE;
- final int mode = getInterfaceMode(iface);
- return (mode == INTERFACE_MODE_CLIENT)
- ? EthernetManager.ROLE_CLIENT
- : EthernetManager.ROLE_SERVER;
- }
-
- private int getInterfaceMode(final String iface) {
- if (iface.equals(mDefaultInterface)) {
- return mDefaultInterfaceMode;
- }
- return INTERFACE_MODE_CLIENT;
- }
-
- private void removeInterface(String iface) {
- mFactory.removeInterface(iface);
- maybeUpdateServerModeInterfaceState(iface, false);
- }
-
- private void stopTrackingInterface(String iface) {
- removeInterface(iface);
- if (iface.equals(mDefaultInterface)) {
- mDefaultInterface = null;
- }
- broadcastInterfaceStateChange(iface);
- }
-
- private void addInterface(String iface) {
- InterfaceConfigurationParcel config = null;
- // Bring up the interface so we get link status indications.
- try {
- PermissionUtils.enforceNetworkStackPermission(mContext);
- NetdUtils.setInterfaceUp(mNetd, iface);
- config = NetdUtils.getInterfaceConfigParcel(mNetd, iface);
- } catch (IllegalStateException e) {
- // Either the system is crashing or the interface has disappeared. Just ignore the
- // error; we haven't modified any state because we only do that if our calls succeed.
- Log.e(TAG, "Error upping interface " + iface, e);
- }
-
- if (config == null) {
- Log.e(TAG, "Null interface config parcelable for " + iface + ". Bailing out.");
- return;
- }
-
- final String hwAddress = config.hwAddr;
-
- NetworkCapabilities nc = mNetworkCapabilities.get(iface);
- if (nc == null) {
- // Try to resolve using mac address
- nc = mNetworkCapabilities.get(hwAddress);
- if (nc == null) {
- final boolean isTestIface = iface.matches(TEST_IFACE_REGEXP);
- nc = createDefaultNetworkCapabilities(isTestIface);
- }
- }
-
- final int mode = getInterfaceMode(iface);
- if (mode == INTERFACE_MODE_CLIENT) {
- IpConfiguration ipConfiguration = getOrCreateIpConfiguration(iface);
- Log.d(TAG, "Tracking interface in client mode: " + iface);
- mFactory.addInterface(iface, hwAddress, ipConfiguration, nc);
- } else {
- maybeUpdateServerModeInterfaceState(iface, true);
- }
-
- // Note: if the interface already has link (e.g., if we crashed and got
- // restarted while it was running), we need to fake a link up notification so we
- // start configuring it.
- if (NetdUtils.hasFlag(config, "running")) {
- updateInterfaceState(iface, true);
- }
- }
-
- private void updateInterfaceState(String iface, boolean up) {
- updateInterfaceState(iface, up, null /* listener */);
- }
-
- private void updateInterfaceState(@NonNull final String iface, final boolean up,
- @Nullable final INetworkInterfaceOutcomeReceiver listener) {
- final int mode = getInterfaceMode(iface);
- final boolean factoryLinkStateUpdated = (mode == INTERFACE_MODE_CLIENT)
- && mFactory.updateInterfaceLinkState(iface, up, listener);
-
- if (factoryLinkStateUpdated) {
- broadcastInterfaceStateChange(iface);
- }
- }
-
- private void maybeUpdateServerModeInterfaceState(String iface, boolean available) {
- if (available == mTetheredInterfaceWasAvailable || !iface.equals(mDefaultInterface)) return;
-
- Log.d(TAG, (available ? "Tracking" : "No longer tracking")
- + " interface in server mode: " + iface);
-
- final int pendingCbs = mTetheredInterfaceRequests.beginBroadcast();
- for (int i = 0; i < pendingCbs; i++) {
- ITetheredInterfaceCallback item = mTetheredInterfaceRequests.getBroadcastItem(i);
- if (available) {
- notifyTetheredInterfaceAvailable(item, iface);
- } else {
- notifyTetheredInterfaceUnavailable(item);
- }
- }
- mTetheredInterfaceRequests.finishBroadcast();
- mTetheredInterfaceWasAvailable = available;
- }
-
- private void maybeTrackInterface(String iface) {
- if (!iface.matches(mIfaceMatch)) {
- return;
- }
-
- // If we don't already track this interface, and if this interface matches
- // our regex, start tracking it.
- if (mFactory.hasInterface(iface) || iface.equals(mDefaultInterface)) {
- if (DBG) Log.w(TAG, "Ignoring already-tracked interface " + iface);
- return;
- }
- if (DBG) Log.i(TAG, "maybeTrackInterface: " + iface);
-
- // TODO: avoid making an interface default if it has configured NetworkCapabilities.
- if (mDefaultInterface == null) {
- mDefaultInterface = iface;
- }
-
- if (mIpConfigForDefaultInterface != null) {
- updateIpConfiguration(iface, mIpConfigForDefaultInterface);
- mIpConfigForDefaultInterface = null;
- }
-
- addInterface(iface);
-
- broadcastInterfaceStateChange(iface);
- }
-
- private void trackAvailableInterfaces() {
- try {
- final String[] ifaces = mNetd.interfaceGetList();
- for (String iface : ifaces) {
- maybeTrackInterface(iface);
- }
- } catch (RemoteException | ServiceSpecificException e) {
- Log.e(TAG, "Could not get list of interfaces " + e);
- }
- }
-
- private class InterfaceObserver extends BaseNetdUnsolicitedEventListener {
-
- @Override
- public void onInterfaceLinkStateChanged(String iface, boolean up) {
- if (DBG) {
- Log.i(TAG, "interfaceLinkStateChanged, iface: " + iface + ", up: " + up);
- }
- mHandler.post(() -> updateInterfaceState(iface, up));
- }
-
- @Override
- public void onInterfaceAdded(String iface) {
- if (DBG) {
- Log.i(TAG, "onInterfaceAdded, iface: " + iface);
- }
- mHandler.post(() -> maybeTrackInterface(iface));
- }
-
- @Override
- public void onInterfaceRemoved(String iface) {
- if (DBG) {
- Log.i(TAG, "onInterfaceRemoved, iface: " + iface);
- }
- mHandler.post(() -> stopTrackingInterface(iface));
- }
- }
-
- private static class ListenerInfo {
-
- boolean canUseRestrictedNetworks = false;
-
- ListenerInfo(boolean canUseRestrictedNetworks) {
- this.canUseRestrictedNetworks = canUseRestrictedNetworks;
- }
- }
-
- /**
- * Parses an Ethernet interface configuration
- *
- * @param configString represents an Ethernet configuration in the following format: {@code
- * <interface name|mac address>;[Network Capabilities];[IP config];[Override Transport]}
- */
- private void parseEthernetConfig(String configString) {
- final EthernetTrackerConfig config = createEthernetTrackerConfig(configString);
- NetworkCapabilities nc = createNetworkCapabilities(
- !TextUtils.isEmpty(config.mCapabilities) /* clear default capabilities */,
- config.mCapabilities, config.mTransport).build();
- mNetworkCapabilities.put(config.mIface, nc);
-
- if (null != config.mIpConfig) {
- IpConfiguration ipConfig = parseStaticIpConfiguration(config.mIpConfig);
- mIpConfigurations.put(config.mIface, ipConfig);
- }
- }
-
- @VisibleForTesting
- static EthernetTrackerConfig createEthernetTrackerConfig(@NonNull final String configString) {
- Objects.requireNonNull(configString, "EthernetTrackerConfig requires non-null config");
- return new EthernetTrackerConfig(configString.split(";", /* limit of tokens */ 4));
- }
-
- private static NetworkCapabilities createDefaultNetworkCapabilities(boolean isTestIface) {
- NetworkCapabilities.Builder builder = createNetworkCapabilities(
- false /* clear default capabilities */, null, null)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED);
-
- if (isTestIface) {
- builder.addTransportType(NetworkCapabilities.TRANSPORT_TEST);
- } else {
- builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
- }
-
- return builder.build();
- }
-
- /**
- * Parses a static list of network capabilities
- *
- * @param clearDefaultCapabilities Indicates whether or not to clear any default capabilities
- * @param commaSeparatedCapabilities A comma separated string list of integer encoded
- * NetworkCapability.NET_CAPABILITY_* values
- * @param overrideTransport A string representing a single integer encoded override transport
- * type. Must be one of the NetworkCapability.TRANSPORT_*
- * values. TRANSPORT_VPN is not supported. Errors with input
- * will cause the override to be ignored.
- */
- @VisibleForTesting
- static NetworkCapabilities.Builder createNetworkCapabilities(
- boolean clearDefaultCapabilities, @Nullable String commaSeparatedCapabilities,
- @Nullable String overrideTransport) {
-
- final NetworkCapabilities.Builder builder = clearDefaultCapabilities
- ? NetworkCapabilities.Builder.withoutDefaultCapabilities()
- : new NetworkCapabilities.Builder();
-
- // Determine the transport type. If someone has tried to define an override transport then
- // attempt to add it. Since we can only have one override, all errors with it will
- // gracefully default back to TRANSPORT_ETHERNET and warn the user. VPN is not allowed as an
- // override type. Wifi Aware and LoWPAN are currently unsupported as well.
- int transport = NetworkCapabilities.TRANSPORT_ETHERNET;
- if (!TextUtils.isEmpty(overrideTransport)) {
- try {
- int parsedTransport = Integer.valueOf(overrideTransport);
- if (parsedTransport == NetworkCapabilities.TRANSPORT_VPN
- || parsedTransport == NetworkCapabilities.TRANSPORT_WIFI_AWARE
- || parsedTransport == NetworkCapabilities.TRANSPORT_LOWPAN) {
- Log.e(TAG, "Override transport '" + parsedTransport + "' is not supported. "
- + "Defaulting to TRANSPORT_ETHERNET");
- } else {
- transport = parsedTransport;
- }
- } catch (NumberFormatException nfe) {
- Log.e(TAG, "Override transport type '" + overrideTransport + "' "
- + "could not be parsed. Defaulting to TRANSPORT_ETHERNET");
- }
- }
-
- // Apply the transport. If the user supplied a valid number that is not a valid transport
- // then adding will throw an exception. Default back to TRANSPORT_ETHERNET if that happens
- try {
- builder.addTransportType(transport);
- } catch (IllegalArgumentException iae) {
- Log.e(TAG, transport + " is not a valid NetworkCapability.TRANSPORT_* value. "
- + "Defaulting to TRANSPORT_ETHERNET");
- builder.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET);
- }
-
- builder.setLinkUpstreamBandwidthKbps(100 * 1000);
- builder.setLinkDownstreamBandwidthKbps(100 * 1000);
-
- if (!TextUtils.isEmpty(commaSeparatedCapabilities)) {
- for (String strNetworkCapability : commaSeparatedCapabilities.split(",")) {
- if (!TextUtils.isEmpty(strNetworkCapability)) {
- try {
- builder.addCapability(Integer.valueOf(strNetworkCapability));
- } catch (NumberFormatException nfe) {
- Log.e(TAG, "Capability '" + strNetworkCapability + "' could not be parsed");
- } catch (IllegalArgumentException iae) {
- Log.e(TAG, strNetworkCapability + " is not a valid "
- + "NetworkCapability.NET_CAPABILITY_* value");
- }
- }
- }
- }
- // Ethernet networks have no way to update the following capabilities, so they always
- // have them.
- builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
- builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED);
- builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED);
-
- return builder;
- }
-
- /**
- * Parses static IP configuration.
- *
- * @param staticIpConfig represents static IP configuration in the following format: {@code
- * ip=<ip-address/mask> gateway=<ip-address> dns=<comma-sep-ip-addresses>
- * domains=<comma-sep-domains>}
- */
- @VisibleForTesting
- static IpConfiguration parseStaticIpConfiguration(String staticIpConfig) {
- final StaticIpConfiguration.Builder staticIpConfigBuilder =
- new StaticIpConfiguration.Builder();
-
- for (String keyValueAsString : staticIpConfig.trim().split(" ")) {
- if (TextUtils.isEmpty(keyValueAsString)) continue;
-
- String[] pair = keyValueAsString.split("=");
- if (pair.length != 2) {
- throw new IllegalArgumentException("Unexpected token: " + keyValueAsString
- + " in " + staticIpConfig);
- }
-
- String key = pair[0];
- String value = pair[1];
-
- switch (key) {
- case "ip":
- staticIpConfigBuilder.setIpAddress(new LinkAddress(value));
- break;
- case "domains":
- staticIpConfigBuilder.setDomains(value);
- break;
- case "gateway":
- staticIpConfigBuilder.setGateway(InetAddress.parseNumericAddress(value));
- break;
- case "dns": {
- ArrayList<InetAddress> dnsAddresses = new ArrayList<>();
- for (String address: value.split(",")) {
- dnsAddresses.add(InetAddress.parseNumericAddress(address));
- }
- staticIpConfigBuilder.setDnsServers(dnsAddresses);
- break;
- }
- default : {
- throw new IllegalArgumentException("Unexpected key: " + key
- + " in " + staticIpConfig);
- }
- }
- }
- return createIpConfiguration(staticIpConfigBuilder.build());
- }
-
- private static IpConfiguration createIpConfiguration(
- @NonNull final StaticIpConfiguration staticIpConfig) {
- return new IpConfiguration.Builder().setStaticIpConfiguration(staticIpConfig).build();
- }
-
- private IpConfiguration getOrCreateIpConfiguration(String iface) {
- IpConfiguration ret = mIpConfigurations.get(iface);
- if (ret != null) return ret;
- ret = new IpConfiguration();
- ret.setIpAssignment(IpAssignment.DHCP);
- ret.setProxySettings(ProxySettings.NONE);
- return ret;
- }
-
- private void updateIfaceMatchRegexp() {
- final String match = mDeps.getInterfaceRegexFromResource(mContext);
- mIfaceMatch = mIncludeTestInterfaces
- ? "(" + match + "|" + TEST_IFACE_REGEXP + ")"
- : match;
- Log.d(TAG, "Interface match regexp set to '" + mIfaceMatch + "'");
- }
-
- /**
- * Validate if a given interface is valid for testing.
- *
- * @param iface the name of the interface to validate.
- * @return {@code true} if test interfaces are enabled and the given {@code iface} has a test
- * interface prefix, {@code false} otherwise.
- */
- public boolean isValidTestInterface(@NonNull final String iface) {
- return mIncludeTestInterfaces && iface.matches(TEST_IFACE_REGEXP);
- }
-
- private void postAndWaitForRunnable(Runnable r) {
- final ConditionVariable cv = new ConditionVariable();
- if (mHandler.post(() -> {
- r.run();
- cv.open();
- })) {
- cv.block(2000L);
- }
- }
-
- @VisibleForTesting(visibility = PACKAGE)
- protected void setEthernetEnabled(boolean enabled) {
- mHandler.post(() -> {
- int newState = enabled ? ETHERNET_STATE_ENABLED : ETHERNET_STATE_DISABLED;
- if (mEthernetState == newState) return;
-
- mEthernetState = newState;
-
- if (enabled) {
- trackAvailableInterfaces();
- } else {
- // TODO: maybe also disable server mode interface as well.
- untrackFactoryInterfaces();
- }
- broadcastEthernetStateChange(mEthernetState);
- });
- }
-
- private void untrackFactoryInterfaces() {
- for (String iface : mFactory.getAvailableInterfaces(true /* includeRestricted */)) {
- stopTrackingInterface(iface);
- }
- }
-
- private void unicastEthernetStateChange(@NonNull IEthernetServiceListener listener,
- int state) {
- ensureRunningOnEthernetServiceThread();
- try {
- listener.onEthernetStateChanged(state);
- } catch (RemoteException e) {
- // Do nothing here.
- }
- }
-
- private void broadcastEthernetStateChange(int state) {
- ensureRunningOnEthernetServiceThread();
- final int n = mListeners.beginBroadcast();
- for (int i = 0; i < n; i++) {
- try {
- mListeners.getBroadcastItem(i).onEthernetStateChanged(state);
- } catch (RemoteException e) {
- // Do nothing here.
- }
- }
- mListeners.finishBroadcast();
- }
-
- void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) {
- postAndWaitForRunnable(() -> {
- pw.println(getClass().getSimpleName());
- pw.println("Ethernet interface name filter: " + mIfaceMatch);
- pw.println("Default interface: " + mDefaultInterface);
- pw.println("Default interface mode: " + mDefaultInterfaceMode);
- pw.println("Tethered interface requests: "
- + mTetheredInterfaceRequests.getRegisteredCallbackCount());
- pw.println("Listeners: " + mListeners.getRegisteredCallbackCount());
- pw.println("IP Configurations:");
- pw.increaseIndent();
- for (String iface : mIpConfigurations.keySet()) {
- pw.println(iface + ": " + mIpConfigurations.get(iface));
- }
- pw.decreaseIndent();
- pw.println();
-
- pw.println("Network Capabilities:");
- pw.increaseIndent();
- for (String iface : mNetworkCapabilities.keySet()) {
- pw.println(iface + ": " + mNetworkCapabilities.get(iface));
- }
- pw.decreaseIndent();
- pw.println();
-
- mFactory.dump(fd, pw, args);
- });
- }
-
- @VisibleForTesting
- static class EthernetTrackerConfig {
- final String mIface;
- final String mCapabilities;
- final String mIpConfig;
- final String mTransport;
-
- EthernetTrackerConfig(@NonNull final String[] tokens) {
- Objects.requireNonNull(tokens, "EthernetTrackerConfig requires non-null tokens");
- mIface = tokens[0];
- mCapabilities = tokens.length > 1 ? tokens[1] : null;
- mIpConfig = tokens.length > 2 && !TextUtils.isEmpty(tokens[2]) ? tokens[2] : null;
- mTransport = tokens.length > 3 ? tokens[3] : null;
- }
- }
-}
diff --git a/tests/Android.bp b/tests/Android.bp
deleted file mode 100644
index 6cfebdc..0000000
--- a/tests/Android.bp
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (C) 2018 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 {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-// TODO: merge the tests into service-connectivity tests after
-// ethernet service migration completes. So far just import the
-// ethernet service source to fix the dependencies.
-android_test {
- name: "EthernetServiceTests",
-
- srcs: [
- ":ethernet-service-updatable-sources",
- ":services.connectivity-ethernet-sources",
- "java/**/*.java",
- ],
-
- certificate: "platform",
- platform_apis: true,
-
- libs: [
- "android.test.runner",
- "android.test.base",
- "android.test.mock",
- "framework-connectivity.impl",
- "framework-connectivity-t.impl",
- "ServiceConnectivityResources",
- ],
-
- static_libs: [
- "androidx.test.rules",
- "frameworks-base-testutils",
- "mockito-target-minus-junit4",
- "net-tests-utils",
- "services.core",
- "services.net",
- ],
- test_suites: ["general-tests"],
-}
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
deleted file mode 100644
index cd875b0..0000000
--- a/tests/AndroidManifest.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2018 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
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.server.ethernet.tests">
-
- <application>
- <uses-library android:name="android.test.runner" />
- </application>
-
- <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.server.ethernet.tests"
- android:label="Ethernet Service Tests" />
-</manifest>
diff --git a/tests/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java b/tests/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java
deleted file mode 100644
index 4d3e4d3..0000000
--- a/tests/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java
+++ /dev/null
@@ -1,783 +0,0 @@
-/*
- * Copyright (C) 2020 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 com.android.server.ethernet;
-
-import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNotSame;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.argThat;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.ArgumentMatchers.same;
-import static org.mockito.Mockito.clearInvocations;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.annotation.NonNull;
-import android.app.test.MockAnswerUtil.AnswerWithArguments;
-import android.content.Context;
-import android.content.res.Resources;
-import android.net.ConnectivityManager;
-import android.net.EthernetNetworkSpecifier;
-import android.net.EthernetNetworkManagementException;
-import android.net.INetworkInterfaceOutcomeReceiver;
-import android.net.IpConfiguration;
-import android.net.LinkAddress;
-import android.net.LinkProperties;
-import android.net.Network;
-import android.net.NetworkAgentConfig;
-import android.net.NetworkCapabilities;
-import android.net.NetworkProvider;
-import android.net.NetworkRequest;
-import android.net.StaticIpConfiguration;
-import android.net.ip.IpClientCallbacks;
-import android.net.ip.IpClientManager;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.test.TestLooper;
-import android.util.Pair;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.connectivity.resources.R;
-import com.android.net.module.util.InterfaceParams;
-
-import com.android.testutils.DevSdkIgnoreRule;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.Objects;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.TimeUnit;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class EthernetNetworkFactoryTest {
- private static final int TIMEOUT_MS = 2_000;
- private static final String TEST_IFACE = "test123";
- private static final INetworkInterfaceOutcomeReceiver NULL_LISTENER = null;
- private static final String IP_ADDR = "192.0.2.2/25";
- private static final LinkAddress LINK_ADDR = new LinkAddress(IP_ADDR);
- private static final String HW_ADDR = "01:02:03:04:05:06";
- private TestLooper mLooper;
- private Handler mHandler;
- private EthernetNetworkFactory mNetFactory = null;
- private IpClientCallbacks mIpClientCallbacks;
- @Mock private Context mContext;
- @Mock private Resources mResources;
- @Mock private EthernetNetworkFactory.Dependencies mDeps;
- @Mock private IpClientManager mIpClient;
- @Mock private EthernetNetworkAgent mNetworkAgent;
- @Mock private InterfaceParams mInterfaceParams;
- @Mock private Network mMockNetwork;
-
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
- setupNetworkAgentMock();
- setupIpClientMock();
- setupContext();
- }
-
- //TODO: Move away from usage of TestLooper in order to move this logic back into @Before.
- private void initEthernetNetworkFactory() {
- mLooper = new TestLooper();
- mHandler = new Handler(mLooper.getLooper());
- mNetFactory = new EthernetNetworkFactory(mHandler, mContext, mDeps);
- }
-
- private void setupNetworkAgentMock() {
- when(mDeps.makeEthernetNetworkAgent(any(), any(), any(), any(), any(), any(), any()))
- .thenAnswer(new AnswerWithArguments() {
- public EthernetNetworkAgent answer(
- Context context,
- Looper looper,
- NetworkCapabilities nc,
- LinkProperties lp,
- NetworkAgentConfig config,
- NetworkProvider provider,
- EthernetNetworkAgent.Callbacks cb) {
- when(mNetworkAgent.getCallbacks()).thenReturn(cb);
- when(mNetworkAgent.getNetwork())
- .thenReturn(mMockNetwork);
- return mNetworkAgent;
- }
- }
- );
- }
-
- private void setupIpClientMock() throws Exception {
- doAnswer(inv -> {
- // these tests only support one concurrent IpClient, so make sure we do not accidentally
- // create a mess.
- assertNull("An IpClient has already been created.", mIpClientCallbacks);
-
- mIpClientCallbacks = inv.getArgument(2);
- mIpClientCallbacks.onIpClientCreated(null);
- mLooper.dispatchAll();
- return null;
- }).when(mDeps).makeIpClient(any(Context.class), anyString(), any());
-
- doAnswer(inv -> {
- mIpClientCallbacks.onQuit();
- mLooper.dispatchAll();
- mIpClientCallbacks = null;
- return null;
- }).when(mIpClient).shutdown();
-
- when(mDeps.makeIpClientManager(any())).thenReturn(mIpClient);
- }
-
- private void triggerOnProvisioningSuccess() {
- mIpClientCallbacks.onProvisioningSuccess(new LinkProperties());
- mLooper.dispatchAll();
- }
-
- private void triggerOnProvisioningFailure() {
- mIpClientCallbacks.onProvisioningFailure(new LinkProperties());
- mLooper.dispatchAll();
- }
-
- private void triggerOnReachabilityLost() {
- mIpClientCallbacks.onReachabilityLost("ReachabilityLost");
- mLooper.dispatchAll();
- }
-
- private void setupContext() {
- when(mDeps.getTcpBufferSizesFromResource(eq(mContext))).thenReturn("");
- }
-
- @After
- public void tearDown() {
- // looper is shared with the network agents, so there may still be messages to dispatch on
- // tear down.
- mLooper.dispatchAll();
- }
-
- private NetworkCapabilities createDefaultFilterCaps() {
- return NetworkCapabilities.Builder.withoutDefaultCapabilities()
- .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
- .build();
- }
-
- private NetworkCapabilities.Builder createInterfaceCapsBuilder(final int transportType) {
- return new NetworkCapabilities.Builder()
- .addTransportType(transportType)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED);
- }
-
- private NetworkRequest.Builder createDefaultRequestBuilder() {
- return new NetworkRequest.Builder()
- .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
- }
-
- private NetworkRequest createDefaultRequest() {
- return createDefaultRequestBuilder().build();
- }
-
- private IpConfiguration createDefaultIpConfig() {
- IpConfiguration ipConfig = new IpConfiguration();
- ipConfig.setIpAssignment(IpConfiguration.IpAssignment.DHCP);
- ipConfig.setProxySettings(IpConfiguration.ProxySettings.NONE);
- return ipConfig;
- }
-
- /**
- * Create an {@link IpConfiguration} with an associated {@link StaticIpConfiguration}.
- *
- * @return {@link IpConfiguration} with its {@link StaticIpConfiguration} set.
- */
- private IpConfiguration createStaticIpConfig() {
- final IpConfiguration ipConfig = new IpConfiguration();
- ipConfig.setIpAssignment(IpConfiguration.IpAssignment.STATIC);
- ipConfig.setStaticIpConfiguration(
- new StaticIpConfiguration.Builder().setIpAddress(LINK_ADDR).build());
- return ipConfig;
- }
-
- // creates an interface with provisioning in progress (since updating the interface link state
- // automatically starts the provisioning process)
- private void createInterfaceUndergoingProvisioning(String iface) {
- // Default to the ethernet transport type.
- createInterfaceUndergoingProvisioning(iface, NetworkCapabilities.TRANSPORT_ETHERNET);
- }
-
- private void createInterfaceUndergoingProvisioning(
- @NonNull final String iface, final int transportType) {
- final IpConfiguration ipConfig = createDefaultIpConfig();
- mNetFactory.addInterface(iface, HW_ADDR, ipConfig,
- createInterfaceCapsBuilder(transportType).build());
- assertTrue(mNetFactory.updateInterfaceLinkState(iface, true, NULL_LISTENER));
- verifyStart(ipConfig);
- clearInvocations(mDeps);
- clearInvocations(mIpClient);
- }
-
- // creates a provisioned interface
- private void createAndVerifyProvisionedInterface(String iface) throws Exception {
- // Default to the ethernet transport type.
- createAndVerifyProvisionedInterface(iface, NetworkCapabilities.TRANSPORT_ETHERNET,
- ConnectivityManager.TYPE_ETHERNET);
- }
-
- private void createVerifyAndRemoveProvisionedInterface(final int transportType,
- final int expectedLegacyType) throws Exception {
- createAndVerifyProvisionedInterface(TEST_IFACE, transportType,
- expectedLegacyType);
- mNetFactory.removeInterface(TEST_IFACE);
- }
-
- private void createAndVerifyProvisionedInterface(
- @NonNull final String iface, final int transportType, final int expectedLegacyType)
- throws Exception {
- createInterfaceUndergoingProvisioning(iface, transportType);
- triggerOnProvisioningSuccess();
- // provisioning succeeded, verify that the network agent is created, registered, marked
- // as connected and legacy type are correctly set.
- final ArgumentCaptor<NetworkCapabilities> ncCaptor = ArgumentCaptor.forClass(
- NetworkCapabilities.class);
- verify(mDeps).makeEthernetNetworkAgent(any(), any(), ncCaptor.capture(), any(),
- argThat(x -> x.getLegacyType() == expectedLegacyType), any(), any());
- assertEquals(
- new EthernetNetworkSpecifier(iface), ncCaptor.getValue().getNetworkSpecifier());
- verifyNetworkAgentRegistersAndConnects();
- clearInvocations(mDeps);
- clearInvocations(mNetworkAgent);
- }
-
- // creates an unprovisioned interface
- private void createUnprovisionedInterface(String iface) throws Exception {
- // To create an unprovisioned interface, provision and then "stop" it, i.e. stop its
- // NetworkAgent and IpClient. One way this can be done is by provisioning an interface and
- // then calling onNetworkUnwanted.
- createAndVerifyProvisionedInterface(iface);
-
- mNetworkAgent.getCallbacks().onNetworkUnwanted();
- mLooper.dispatchAll();
- verifyStop();
-
- clearInvocations(mIpClient);
- clearInvocations(mNetworkAgent);
- }
-
- @Test
- public void testAcceptRequest() throws Exception {
- initEthernetNetworkFactory();
- createInterfaceUndergoingProvisioning(TEST_IFACE);
- assertTrue(mNetFactory.acceptRequest(createDefaultRequest()));
-
- NetworkRequest wifiRequest = createDefaultRequestBuilder()
- .removeTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
- .addTransportType(NetworkCapabilities.TRANSPORT_WIFI).build();
- assertFalse(mNetFactory.acceptRequest(wifiRequest));
- }
-
- @Test
- public void testUpdateInterfaceLinkStateForActiveProvisioningInterface() throws Exception {
- initEthernetNetworkFactory();
- createInterfaceUndergoingProvisioning(TEST_IFACE);
- final TestNetworkManagementListener listener = new TestNetworkManagementListener();
-
- // verify that the IpClient gets shut down when interface state changes to down.
- final boolean ret =
- mNetFactory.updateInterfaceLinkState(TEST_IFACE, false /* up */, listener);
-
- assertTrue(ret);
- verify(mIpClient).shutdown();
- assertEquals(listener.expectOnResult(), TEST_IFACE);
- }
-
- @Test
- public void testUpdateInterfaceLinkStateForProvisionedInterface() throws Exception {
- initEthernetNetworkFactory();
- createAndVerifyProvisionedInterface(TEST_IFACE);
- final TestNetworkManagementListener listener = new TestNetworkManagementListener();
-
- final boolean ret =
- mNetFactory.updateInterfaceLinkState(TEST_IFACE, false /* up */, listener);
-
- assertTrue(ret);
- verifyStop();
- assertEquals(listener.expectOnResult(), TEST_IFACE);
- }
-
- @Test
- public void testUpdateInterfaceLinkStateForUnprovisionedInterface() throws Exception {
- initEthernetNetworkFactory();
- createUnprovisionedInterface(TEST_IFACE);
- final TestNetworkManagementListener listener = new TestNetworkManagementListener();
-
- final boolean ret =
- mNetFactory.updateInterfaceLinkState(TEST_IFACE, false /* up */, listener);
-
- assertTrue(ret);
- // There should not be an active IPClient or NetworkAgent.
- verify(mDeps, never()).makeIpClient(any(), any(), any());
- verify(mDeps, never())
- .makeEthernetNetworkAgent(any(), any(), any(), any(), any(), any(), any());
- assertEquals(listener.expectOnResult(), TEST_IFACE);
- }
-
- @Test
- public void testUpdateInterfaceLinkStateForNonExistingInterface() throws Exception {
- initEthernetNetworkFactory();
- final TestNetworkManagementListener listener = new TestNetworkManagementListener();
-
- // if interface was never added, link state cannot be updated.
- final boolean ret =
- mNetFactory.updateInterfaceLinkState(TEST_IFACE, true /* up */, listener);
-
- assertFalse(ret);
- verifyNoStopOrStart();
- listener.expectOnErrorWithMessage("can't be updated as it is not available");
- }
-
- @Test
- public void testUpdateInterfaceLinkStateWithNoChanges() throws Exception {
- initEthernetNetworkFactory();
- createAndVerifyProvisionedInterface(TEST_IFACE);
- final TestNetworkManagementListener listener = new TestNetworkManagementListener();
-
- final boolean ret =
- mNetFactory.updateInterfaceLinkState(TEST_IFACE, true /* up */, listener);
-
- assertFalse(ret);
- verifyNoStopOrStart();
- listener.expectOnErrorWithMessage("No changes");
- }
-
- @Test
- public void testNeedNetworkForOnProvisionedInterface() throws Exception {
- initEthernetNetworkFactory();
- createAndVerifyProvisionedInterface(TEST_IFACE);
- mNetFactory.needNetworkFor(createDefaultRequest());
- verify(mIpClient, never()).startProvisioning(any());
- }
-
- @Test
- public void testNeedNetworkForOnUnprovisionedInterface() throws Exception {
- initEthernetNetworkFactory();
- createUnprovisionedInterface(TEST_IFACE);
- mNetFactory.needNetworkFor(createDefaultRequest());
- verify(mIpClient).startProvisioning(any());
-
- triggerOnProvisioningSuccess();
- verifyNetworkAgentRegistersAndConnects();
- }
-
- @Test
- public void testNeedNetworkForOnInterfaceUndergoingProvisioning() throws Exception {
- initEthernetNetworkFactory();
- createInterfaceUndergoingProvisioning(TEST_IFACE);
- mNetFactory.needNetworkFor(createDefaultRequest());
- verify(mIpClient, never()).startProvisioning(any());
-
- triggerOnProvisioningSuccess();
- verifyNetworkAgentRegistersAndConnects();
- }
-
- @Test
- public void testProvisioningLoss() throws Exception {
- initEthernetNetworkFactory();
- when(mDeps.getNetworkInterfaceByName(TEST_IFACE)).thenReturn(mInterfaceParams);
- createAndVerifyProvisionedInterface(TEST_IFACE);
-
- triggerOnProvisioningFailure();
- verifyStop();
- // provisioning loss should trigger a retry, since the interface is still there
- verify(mIpClient).startProvisioning(any());
- }
-
- @Test
- public void testProvisioningLossForDisappearedInterface() throws Exception {
- initEthernetNetworkFactory();
- // mocked method returns null by default, but just to be explicit in the test:
- when(mDeps.getNetworkInterfaceByName(eq(TEST_IFACE))).thenReturn(null);
-
- createAndVerifyProvisionedInterface(TEST_IFACE);
- triggerOnProvisioningFailure();
-
- // the interface disappeared and getNetworkInterfaceByName returns null, we should not retry
- verify(mIpClient, never()).startProvisioning(any());
- verifyNoStopOrStart();
- }
-
- private void verifyNoStopOrStart() {
- verify(mNetworkAgent, never()).register();
- verify(mIpClient, never()).shutdown();
- verify(mNetworkAgent, never()).unregister();
- verify(mIpClient, never()).startProvisioning(any());
- }
-
- @Test
- public void testIpClientIsNotStartedWhenLinkIsDown() throws Exception {
- initEthernetNetworkFactory();
- createUnprovisionedInterface(TEST_IFACE);
- mNetFactory.updateInterfaceLinkState(TEST_IFACE, false, NULL_LISTENER);
-
- mNetFactory.needNetworkFor(createDefaultRequest());
-
- verify(mDeps, never()).makeIpClient(any(), any(), any());
-
- // BUG(b/191854824): requesting a network with a specifier (Android Auto use case) should
- // not start an IpClient when the link is down, but fixing this may make matters worse by
- // tiggering b/197548738.
- NetworkRequest specificNetRequest = new NetworkRequest.Builder()
- .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
- .setNetworkSpecifier(new EthernetNetworkSpecifier(TEST_IFACE))
- .build();
- mNetFactory.needNetworkFor(specificNetRequest);
- mNetFactory.releaseNetworkFor(specificNetRequest);
-
- mNetFactory.updateInterfaceLinkState(TEST_IFACE, true, NULL_LISTENER);
- // TODO: change to once when b/191854824 is fixed.
- verify(mDeps, times(2)).makeIpClient(any(), eq(TEST_IFACE), any());
- }
-
- @Test
- public void testLinkPropertiesChanged() throws Exception {
- initEthernetNetworkFactory();
- createAndVerifyProvisionedInterface(TEST_IFACE);
-
- LinkProperties lp = new LinkProperties();
- mIpClientCallbacks.onLinkPropertiesChange(lp);
- mLooper.dispatchAll();
- verify(mNetworkAgent).sendLinkPropertiesImpl(same(lp));
- }
-
- @Test
- public void testNetworkUnwanted() throws Exception {
- initEthernetNetworkFactory();
- createAndVerifyProvisionedInterface(TEST_IFACE);
-
- mNetworkAgent.getCallbacks().onNetworkUnwanted();
- mLooper.dispatchAll();
- verifyStop();
- }
-
- @Test
- public void testNetworkUnwantedWithStaleNetworkAgent() throws Exception {
- initEthernetNetworkFactory();
- // ensures provisioning is restarted after provisioning loss
- when(mDeps.getNetworkInterfaceByName(TEST_IFACE)).thenReturn(mInterfaceParams);
- createAndVerifyProvisionedInterface(TEST_IFACE);
-
- EthernetNetworkAgent.Callbacks oldCbs = mNetworkAgent.getCallbacks();
- // replace network agent in EthernetNetworkFactory
- // Loss of provisioning will restart the ip client and network agent.
- triggerOnProvisioningFailure();
- verify(mDeps).makeIpClient(any(), any(), any());
-
- triggerOnProvisioningSuccess();
- verify(mDeps).makeEthernetNetworkAgent(any(), any(), any(), any(), any(), any(), any());
-
- // verify that unwanted is ignored
- clearInvocations(mIpClient);
- clearInvocations(mNetworkAgent);
- oldCbs.onNetworkUnwanted();
- verify(mIpClient, never()).shutdown();
- verify(mNetworkAgent, never()).unregister();
- }
-
- @Test
- public void testTransportOverrideIsCorrectlySet() throws Exception {
- initEthernetNetworkFactory();
- // createProvisionedInterface() has verifications in place for transport override
- // functionality which for EthernetNetworkFactory is network score and legacy type mappings.
- createVerifyAndRemoveProvisionedInterface(NetworkCapabilities.TRANSPORT_ETHERNET,
- ConnectivityManager.TYPE_ETHERNET);
- createVerifyAndRemoveProvisionedInterface(NetworkCapabilities.TRANSPORT_BLUETOOTH,
- ConnectivityManager.TYPE_BLUETOOTH);
- createVerifyAndRemoveProvisionedInterface(NetworkCapabilities.TRANSPORT_WIFI,
- ConnectivityManager.TYPE_WIFI);
- createVerifyAndRemoveProvisionedInterface(NetworkCapabilities.TRANSPORT_CELLULAR,
- ConnectivityManager.TYPE_MOBILE);
- createVerifyAndRemoveProvisionedInterface(NetworkCapabilities.TRANSPORT_LOWPAN,
- ConnectivityManager.TYPE_NONE);
- createVerifyAndRemoveProvisionedInterface(NetworkCapabilities.TRANSPORT_WIFI_AWARE,
- ConnectivityManager.TYPE_NONE);
- createVerifyAndRemoveProvisionedInterface(NetworkCapabilities.TRANSPORT_TEST,
- ConnectivityManager.TYPE_NONE);
- }
-
- @Test
- public void testReachabilityLoss() throws Exception {
- initEthernetNetworkFactory();
- createAndVerifyProvisionedInterface(TEST_IFACE);
-
- triggerOnReachabilityLost();
-
- // Reachability loss should trigger a stop and start, since the interface is still there
- verifyRestart(createDefaultIpConfig());
- }
-
- private IpClientCallbacks getStaleIpClientCallbacks() throws Exception {
- createAndVerifyProvisionedInterface(TEST_IFACE);
- final IpClientCallbacks staleIpClientCallbacks = mIpClientCallbacks;
- mNetFactory.removeInterface(TEST_IFACE);
- verifyStop();
- assertNotSame(mIpClientCallbacks, staleIpClientCallbacks);
- return staleIpClientCallbacks;
- }
-
- @Test
- public void testIgnoreOnIpLayerStartedCallbackForStaleCallback() throws Exception {
- initEthernetNetworkFactory();
- final IpClientCallbacks staleIpClientCallbacks = getStaleIpClientCallbacks();
-
- staleIpClientCallbacks.onProvisioningSuccess(new LinkProperties());
- mLooper.dispatchAll();
-
- verify(mIpClient, never()).startProvisioning(any());
- verify(mNetworkAgent, never()).register();
- }
-
- @Test
- public void testIgnoreOnIpLayerStoppedCallbackForStaleCallback() throws Exception {
- initEthernetNetworkFactory();
- when(mDeps.getNetworkInterfaceByName(TEST_IFACE)).thenReturn(mInterfaceParams);
- final IpClientCallbacks staleIpClientCallbacks = getStaleIpClientCallbacks();
-
- staleIpClientCallbacks.onProvisioningFailure(new LinkProperties());
- mLooper.dispatchAll();
-
- verify(mIpClient, never()).startProvisioning(any());
- }
-
- @Test
- public void testIgnoreLinkPropertiesCallbackForStaleCallback() throws Exception {
- initEthernetNetworkFactory();
- final IpClientCallbacks staleIpClientCallbacks = getStaleIpClientCallbacks();
- final LinkProperties lp = new LinkProperties();
-
- staleIpClientCallbacks.onLinkPropertiesChange(lp);
- mLooper.dispatchAll();
-
- verify(mNetworkAgent, never()).sendLinkPropertiesImpl(eq(lp));
- }
-
- @Test
- public void testIgnoreNeighborLossCallbackForStaleCallback() throws Exception {
- initEthernetNetworkFactory();
- final IpClientCallbacks staleIpClientCallbacks = getStaleIpClientCallbacks();
-
- staleIpClientCallbacks.onReachabilityLost("Neighbor Lost");
- mLooper.dispatchAll();
-
- verify(mIpClient, never()).startProvisioning(any());
- verify(mNetworkAgent, never()).register();
- }
-
- private void verifyRestart(@NonNull final IpConfiguration ipConfig) {
- verifyStop();
- verifyStart(ipConfig);
- }
-
- private void verifyStart(@NonNull final IpConfiguration ipConfig) {
- verify(mDeps).makeIpClient(any(Context.class), anyString(), any());
- verify(mIpClient).startProvisioning(
- argThat(x -> Objects.equals(x.mStaticIpConfig, ipConfig.getStaticIpConfiguration()))
- );
- }
-
- private void verifyStop() {
- verify(mIpClient).shutdown();
- verify(mNetworkAgent).unregister();
- }
-
- private void verifyNetworkAgentRegistersAndConnects() {
- verify(mNetworkAgent).register();
- verify(mNetworkAgent).markConnected();
- }
-
- private static final class TestNetworkManagementListener
- implements INetworkInterfaceOutcomeReceiver {
- private final CompletableFuture<String> mResult = new CompletableFuture<>();
- private final CompletableFuture<EthernetNetworkManagementException> mError =
- new CompletableFuture<>();
-
- @Override
- public void onResult(@NonNull String iface) {
- mResult.complete(iface);
- }
-
- @Override
- public void onError(@NonNull EthernetNetworkManagementException exception) {
- mError.complete(exception);
- }
-
- String expectOnResult() throws Exception {
- return mResult.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
- }
-
- EthernetNetworkManagementException expectOnError() throws Exception {
- return mError.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
- }
-
- void expectOnErrorWithMessage(String msg) throws Exception {
- assertTrue(expectOnError().getMessage().contains(msg));
- }
-
- @Override
- public IBinder asBinder() {
- return null;
- }
- }
-
- @Test
- public void testUpdateInterfaceCallsListenerCorrectlyOnSuccess() throws Exception {
- initEthernetNetworkFactory();
- createAndVerifyProvisionedInterface(TEST_IFACE);
- final NetworkCapabilities capabilities = createDefaultFilterCaps();
- final IpConfiguration ipConfiguration = createStaticIpConfig();
- final TestNetworkManagementListener listener = new TestNetworkManagementListener();
-
- mNetFactory.updateInterface(TEST_IFACE, ipConfiguration, capabilities, listener);
- triggerOnProvisioningSuccess();
-
- assertEquals(listener.expectOnResult(), TEST_IFACE);
- }
-
- @DevSdkIgnoreRule.IgnoreUpTo(SC_V2) // TODO: Use to Build.VERSION_CODES.SC_V2 when available
- @Test
- public void testUpdateInterfaceAbortsOnConcurrentRemoveInterface() throws Exception {
- initEthernetNetworkFactory();
- verifyNetworkManagementCallIsAbortedWhenInterrupted(
- TEST_IFACE,
- () -> mNetFactory.removeInterface(TEST_IFACE));
- }
-
- @DevSdkIgnoreRule.IgnoreUpTo(SC_V2) // TODO: Use to Build.VERSION_CODES.SC_V2 when available
- @Test
- public void testUpdateInterfaceAbortsOnConcurrentUpdateInterfaceLinkState() throws Exception {
- initEthernetNetworkFactory();
- verifyNetworkManagementCallIsAbortedWhenInterrupted(
- TEST_IFACE,
- () -> mNetFactory.updateInterfaceLinkState(TEST_IFACE, false, NULL_LISTENER));
- }
-
- @DevSdkIgnoreRule.IgnoreUpTo(SC_V2) // TODO: Use to Build.VERSION_CODES.SC_V2 when available
- @Test
- public void testUpdateInterfaceCallsListenerCorrectlyOnConcurrentRequests() throws Exception {
- initEthernetNetworkFactory();
- final NetworkCapabilities capabilities = createDefaultFilterCaps();
- final IpConfiguration ipConfiguration = createStaticIpConfig();
- final TestNetworkManagementListener successfulListener =
- new TestNetworkManagementListener();
-
- // If two calls come in before the first one completes, the first listener will be aborted
- // and the second one will be successful.
- verifyNetworkManagementCallIsAbortedWhenInterrupted(
- TEST_IFACE,
- () -> {
- mNetFactory.updateInterface(
- TEST_IFACE, ipConfiguration, capabilities, successfulListener);
- triggerOnProvisioningSuccess();
- });
-
- assertEquals(successfulListener.expectOnResult(), TEST_IFACE);
- }
-
- private void verifyNetworkManagementCallIsAbortedWhenInterrupted(
- @NonNull final String iface,
- @NonNull final Runnable interruptingRunnable) throws Exception {
- createAndVerifyProvisionedInterface(iface);
- final NetworkCapabilities capabilities = createDefaultFilterCaps();
- final IpConfiguration ipConfiguration = createStaticIpConfig();
- final TestNetworkManagementListener failedListener = new TestNetworkManagementListener();
-
- // An active update request will be aborted on interrupt prior to provisioning completion.
- mNetFactory.updateInterface(iface, ipConfiguration, capabilities, failedListener);
- interruptingRunnable.run();
-
- failedListener.expectOnErrorWithMessage("aborted");
- }
-
- @Test
- public void testUpdateInterfaceRestartsAgentCorrectly() throws Exception {
- initEthernetNetworkFactory();
- createAndVerifyProvisionedInterface(TEST_IFACE);
- final NetworkCapabilities capabilities = createDefaultFilterCaps();
- final IpConfiguration ipConfiguration = createStaticIpConfig();
- final TestNetworkManagementListener listener = new TestNetworkManagementListener();
-
- mNetFactory.updateInterface(TEST_IFACE, ipConfiguration, capabilities, listener);
- triggerOnProvisioningSuccess();
-
- assertEquals(listener.expectOnResult(), TEST_IFACE);
- verify(mDeps).makeEthernetNetworkAgent(any(), any(),
- eq(capabilities), any(), any(), any(), any());
- verifyRestart(ipConfiguration);
- }
-
- @Test
- public void testUpdateInterfaceForNonExistingInterface() throws Exception {
- initEthernetNetworkFactory();
- // No interface exists due to not calling createAndVerifyProvisionedInterface(...).
- final NetworkCapabilities capabilities = createDefaultFilterCaps();
- final IpConfiguration ipConfiguration = createStaticIpConfig();
- final TestNetworkManagementListener listener = new TestNetworkManagementListener();
-
- mNetFactory.updateInterface(TEST_IFACE, ipConfiguration, capabilities, listener);
-
- verifyNoStopOrStart();
- listener.expectOnErrorWithMessage("can't be updated as it is not available");
- }
-
- @Test
- public void testUpdateInterfaceWithNullIpConfiguration() throws Exception {
- initEthernetNetworkFactory();
- createAndVerifyProvisionedInterface(TEST_IFACE);
-
- final IpConfiguration initialIpConfig = createStaticIpConfig();
- mNetFactory.updateInterface(TEST_IFACE, initialIpConfig, null /*capabilities*/,
- null /*listener*/);
- triggerOnProvisioningSuccess();
- verifyRestart(initialIpConfig);
-
- // TODO: have verifyXyz functions clear invocations.
- clearInvocations(mDeps);
- clearInvocations(mIpClient);
- clearInvocations(mNetworkAgent);
-
-
- // verify that sending a null ipConfig does not update the current ipConfig.
- mNetFactory.updateInterface(TEST_IFACE, null /*ipConfig*/, null /*capabilities*/,
- null /*listener*/);
- triggerOnProvisioningSuccess();
- verifyRestart(initialIpConfig);
- }
-}
diff --git a/tests/java/com/android/server/ethernet/EthernetServiceImplTest.java b/tests/java/com/android/server/ethernet/EthernetServiceImplTest.java
deleted file mode 100644
index dd1f1ed..0000000
--- a/tests/java/com/android/server/ethernet/EthernetServiceImplTest.java
+++ /dev/null
@@ -1,372 +0,0 @@
-/*
- * Copyright (C) 2021 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 com.android.server.ethernet;
-
-import static android.net.NetworkCapabilities.TRANSPORT_TEST;
-
-import static org.junit.Assert.assertThrows;
-import static org.junit.Assert.fail;
-
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.ArgumentMatchers.isNull;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.Manifest;
-import android.annotation.NonNull;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.net.INetworkInterfaceOutcomeReceiver;
-import android.net.EthernetNetworkUpdateRequest;
-import android.net.IpConfiguration;
-import android.net.NetworkCapabilities;
-import android.os.Handler;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class EthernetServiceImplTest {
- private static final String TEST_IFACE = "test123";
- private static final EthernetNetworkUpdateRequest UPDATE_REQUEST =
- new EthernetNetworkUpdateRequest.Builder()
- .setIpConfiguration(new IpConfiguration())
- .setNetworkCapabilities(new NetworkCapabilities.Builder().build())
- .build();
- private static final EthernetNetworkUpdateRequest UPDATE_REQUEST_WITHOUT_CAPABILITIES =
- new EthernetNetworkUpdateRequest.Builder()
- .setIpConfiguration(new IpConfiguration())
- .build();
- private static final EthernetNetworkUpdateRequest UPDATE_REQUEST_WITHOUT_IP_CONFIG =
- new EthernetNetworkUpdateRequest.Builder()
- .setNetworkCapabilities(new NetworkCapabilities.Builder().build())
- .build();
- private static final INetworkInterfaceOutcomeReceiver NULL_LISTENER = null;
- private EthernetServiceImpl mEthernetServiceImpl;
- @Mock private Context mContext;
- @Mock private Handler mHandler;
- @Mock private EthernetTracker mEthernetTracker;
- @Mock private PackageManager mPackageManager;
-
- @Before
- public void setup() {
- MockitoAnnotations.initMocks(this);
- doReturn(mPackageManager).when(mContext).getPackageManager();
- mEthernetServiceImpl = new EthernetServiceImpl(mContext, mHandler, mEthernetTracker);
- mEthernetServiceImpl.mStarted.set(true);
- toggleAutomotiveFeature(true);
- shouldTrackIface(TEST_IFACE, true);
- }
-
- private void toggleAutomotiveFeature(final boolean isEnabled) {
- doReturn(isEnabled)
- .when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
- }
-
- private void shouldTrackIface(@NonNull final String iface, final boolean shouldTrack) {
- doReturn(shouldTrack).when(mEthernetTracker).isTrackingInterface(iface);
- }
-
- @Test
- public void testSetConfigurationRejectsWhenEthNotStarted() {
- mEthernetServiceImpl.mStarted.set(false);
- assertThrows(IllegalStateException.class, () -> {
- mEthernetServiceImpl.setConfiguration("" /* iface */, new IpConfiguration());
- });
- }
-
- @Test
- public void testUpdateConfigurationRejectsWhenEthNotStarted() {
- mEthernetServiceImpl.mStarted.set(false);
- assertThrows(IllegalStateException.class, () -> {
- mEthernetServiceImpl.updateConfiguration(
- "" /* iface */, UPDATE_REQUEST, null /* listener */);
- });
- }
-
- @Test
- public void testConnectNetworkRejectsWhenEthNotStarted() {
- mEthernetServiceImpl.mStarted.set(false);
- assertThrows(IllegalStateException.class, () -> {
- mEthernetServiceImpl.connectNetwork("" /* iface */, null /* listener */);
- });
- }
-
- @Test
- public void testDisconnectNetworkRejectsWhenEthNotStarted() {
- mEthernetServiceImpl.mStarted.set(false);
- assertThrows(IllegalStateException.class, () -> {
- mEthernetServiceImpl.disconnectNetwork("" /* iface */, null /* listener */);
- });
- }
-
- @Test
- public void testUpdateConfigurationRejectsNullIface() {
- assertThrows(NullPointerException.class, () -> {
- mEthernetServiceImpl.updateConfiguration(null, UPDATE_REQUEST, NULL_LISTENER);
- });
- }
-
- @Test
- public void testConnectNetworkRejectsNullIface() {
- assertThrows(NullPointerException.class, () -> {
- mEthernetServiceImpl.connectNetwork(null /* iface */, NULL_LISTENER);
- });
- }
-
- @Test
- public void testDisconnectNetworkRejectsNullIface() {
- assertThrows(NullPointerException.class, () -> {
- mEthernetServiceImpl.disconnectNetwork(null /* iface */, NULL_LISTENER);
- });
- }
-
- @Test
- public void testUpdateConfigurationWithCapabilitiesRejectsWithoutAutomotiveFeature() {
- toggleAutomotiveFeature(false);
- assertThrows(UnsupportedOperationException.class, () -> {
- mEthernetServiceImpl.updateConfiguration(TEST_IFACE, UPDATE_REQUEST, NULL_LISTENER);
- });
- }
-
- @Test
- public void testUpdateConfigurationWithCapabilitiesWithAutomotiveFeature() {
- toggleAutomotiveFeature(false);
- mEthernetServiceImpl.updateConfiguration(TEST_IFACE, UPDATE_REQUEST_WITHOUT_CAPABILITIES,
- NULL_LISTENER);
- verify(mEthernetTracker).updateConfiguration(eq(TEST_IFACE),
- eq(UPDATE_REQUEST_WITHOUT_CAPABILITIES.getIpConfiguration()),
- eq(UPDATE_REQUEST_WITHOUT_CAPABILITIES.getNetworkCapabilities()), isNull());
- }
-
- @Test
- public void testConnectNetworkRejectsWithoutAutomotiveFeature() {
- toggleAutomotiveFeature(false);
- assertThrows(UnsupportedOperationException.class, () -> {
- mEthernetServiceImpl.connectNetwork("" /* iface */, NULL_LISTENER);
- });
- }
-
- @Test
- public void testDisconnectNetworkRejectsWithoutAutomotiveFeature() {
- toggleAutomotiveFeature(false);
- assertThrows(UnsupportedOperationException.class, () -> {
- mEthernetServiceImpl.disconnectNetwork("" /* iface */, NULL_LISTENER);
- });
- }
-
- private void denyManageEthPermission() {
- doThrow(new SecurityException("")).when(mContext)
- .enforceCallingOrSelfPermission(
- eq(Manifest.permission.MANAGE_ETHERNET_NETWORKS), anyString());
- }
-
- private void denyManageTestNetworksPermission() {
- doThrow(new SecurityException("")).when(mContext)
- .enforceCallingOrSelfPermission(
- eq(Manifest.permission.MANAGE_TEST_NETWORKS), anyString());
- }
-
- @Test
- public void testUpdateConfigurationRejectsWithoutManageEthPermission() {
- denyManageEthPermission();
- assertThrows(SecurityException.class, () -> {
- mEthernetServiceImpl.updateConfiguration(TEST_IFACE, UPDATE_REQUEST, NULL_LISTENER);
- });
- }
-
- @Test
- public void testConnectNetworkRejectsWithoutManageEthPermission() {
- denyManageEthPermission();
- assertThrows(SecurityException.class, () -> {
- mEthernetServiceImpl.connectNetwork(TEST_IFACE, NULL_LISTENER);
- });
- }
-
- @Test
- public void testDisconnectNetworkRejectsWithoutManageEthPermission() {
- denyManageEthPermission();
- assertThrows(SecurityException.class, () -> {
- mEthernetServiceImpl.disconnectNetwork(TEST_IFACE, NULL_LISTENER);
- });
- }
-
- private void enableTestInterface() {
- when(mEthernetTracker.isValidTestInterface(eq(TEST_IFACE))).thenReturn(true);
- }
-
- @Test
- public void testUpdateConfigurationRejectsTestRequestWithoutTestPermission() {
- enableTestInterface();
- denyManageTestNetworksPermission();
- assertThrows(SecurityException.class, () -> {
- mEthernetServiceImpl.updateConfiguration(TEST_IFACE, UPDATE_REQUEST, NULL_LISTENER);
- });
- }
-
- @Test
- public void testConnectNetworkRejectsTestRequestWithoutTestPermission() {
- enableTestInterface();
- denyManageTestNetworksPermission();
- assertThrows(SecurityException.class, () -> {
- mEthernetServiceImpl.connectNetwork(TEST_IFACE, NULL_LISTENER);
- });
- }
-
- @Test
- public void testDisconnectNetworkRejectsTestRequestWithoutTestPermission() {
- enableTestInterface();
- denyManageTestNetworksPermission();
- assertThrows(SecurityException.class, () -> {
- mEthernetServiceImpl.disconnectNetwork(TEST_IFACE, NULL_LISTENER);
- });
- }
-
- @Test
- public void testUpdateConfiguration() {
- mEthernetServiceImpl.updateConfiguration(TEST_IFACE, UPDATE_REQUEST, NULL_LISTENER);
- verify(mEthernetTracker).updateConfiguration(
- eq(TEST_IFACE),
- eq(UPDATE_REQUEST.getIpConfiguration()),
- eq(UPDATE_REQUEST.getNetworkCapabilities()), eq(NULL_LISTENER));
- }
-
- @Test
- public void testConnectNetwork() {
- mEthernetServiceImpl.connectNetwork(TEST_IFACE, NULL_LISTENER);
- verify(mEthernetTracker).connectNetwork(eq(TEST_IFACE), eq(NULL_LISTENER));
- }
-
- @Test
- public void testDisconnectNetwork() {
- mEthernetServiceImpl.disconnectNetwork(TEST_IFACE, NULL_LISTENER);
- verify(mEthernetTracker).disconnectNetwork(eq(TEST_IFACE), eq(NULL_LISTENER));
- }
-
- @Test
- public void testUpdateConfigurationAcceptsTestRequestWithNullCapabilities() {
- enableTestInterface();
- final EthernetNetworkUpdateRequest request =
- new EthernetNetworkUpdateRequest
- .Builder()
- .setIpConfiguration(new IpConfiguration()).build();
- mEthernetServiceImpl.updateConfiguration(TEST_IFACE, request, NULL_LISTENER);
- verify(mEthernetTracker).updateConfiguration(eq(TEST_IFACE),
- eq(request.getIpConfiguration()),
- eq(request.getNetworkCapabilities()), isNull());
- }
-
- @Test
- public void testUpdateConfigurationAcceptsRequestWithNullIpConfiguration() {
- mEthernetServiceImpl.updateConfiguration(TEST_IFACE, UPDATE_REQUEST_WITHOUT_IP_CONFIG,
- NULL_LISTENER);
- verify(mEthernetTracker).updateConfiguration(eq(TEST_IFACE),
- eq(UPDATE_REQUEST_WITHOUT_IP_CONFIG.getIpConfiguration()),
- eq(UPDATE_REQUEST_WITHOUT_IP_CONFIG.getNetworkCapabilities()), isNull());
- }
-
- @Test
- public void testUpdateConfigurationRejectsInvalidTestRequest() {
- enableTestInterface();
- assertThrows(IllegalArgumentException.class, () -> {
- mEthernetServiceImpl.updateConfiguration(TEST_IFACE, UPDATE_REQUEST, NULL_LISTENER);
- });
- }
-
- private EthernetNetworkUpdateRequest createTestNetworkUpdateRequest() {
- final NetworkCapabilities nc = new NetworkCapabilities
- .Builder(UPDATE_REQUEST.getNetworkCapabilities())
- .addTransportType(TRANSPORT_TEST).build();
-
- return new EthernetNetworkUpdateRequest
- .Builder(UPDATE_REQUEST)
- .setNetworkCapabilities(nc).build();
- }
-
- @Test
- public void testUpdateConfigurationForTestRequestDoesNotRequireAutoOrEthernetPermission() {
- enableTestInterface();
- toggleAutomotiveFeature(false);
- denyManageEthPermission();
- final EthernetNetworkUpdateRequest request = createTestNetworkUpdateRequest();
-
- mEthernetServiceImpl.updateConfiguration(TEST_IFACE, request, NULL_LISTENER);
- verify(mEthernetTracker).updateConfiguration(
- eq(TEST_IFACE),
- eq(request.getIpConfiguration()),
- eq(request.getNetworkCapabilities()), eq(NULL_LISTENER));
- }
-
- @Test
- public void testConnectNetworkForTestRequestDoesNotRequireAutoOrNetPermission() {
- enableTestInterface();
- toggleAutomotiveFeature(false);
- denyManageEthPermission();
-
- mEthernetServiceImpl.connectNetwork(TEST_IFACE, NULL_LISTENER);
- verify(mEthernetTracker).connectNetwork(eq(TEST_IFACE), eq(NULL_LISTENER));
- }
-
- @Test
- public void testDisconnectNetworkForTestRequestDoesNotRequireAutoOrNetPermission() {
- enableTestInterface();
- toggleAutomotiveFeature(false);
- denyManageEthPermission();
-
- mEthernetServiceImpl.disconnectNetwork(TEST_IFACE, NULL_LISTENER);
- verify(mEthernetTracker).disconnectNetwork(eq(TEST_IFACE), eq(NULL_LISTENER));
- }
-
- private void denyPermissions(String... permissions) {
- for (String permission: permissions) {
- doReturn(PackageManager.PERMISSION_DENIED).when(mContext)
- .checkCallingOrSelfPermission(eq(permission));
- }
- }
-
- @Test
- public void testSetEthernetEnabled() {
- denyPermissions(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
- mEthernetServiceImpl.setEthernetEnabled(true);
- verify(mEthernetTracker).setEthernetEnabled(true);
- reset(mEthernetTracker);
-
- denyPermissions(Manifest.permission.NETWORK_STACK);
- mEthernetServiceImpl.setEthernetEnabled(false);
- verify(mEthernetTracker).setEthernetEnabled(false);
- reset(mEthernetTracker);
-
- denyPermissions(Manifest.permission.NETWORK_SETTINGS);
- try {
- mEthernetServiceImpl.setEthernetEnabled(true);
- fail("Should get SecurityException");
- } catch (SecurityException e) { }
- verify(mEthernetTracker, never()).setEthernetEnabled(false);
- }
-}
diff --git a/tests/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/java/com/android/server/ethernet/EthernetTrackerTest.java
deleted file mode 100644
index b1831c4..0000000
--- a/tests/java/com/android/server/ethernet/EthernetTrackerTest.java
+++ /dev/null
@@ -1,456 +0,0 @@
-/*
- * Copyright (C) 2018 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 com.android.server.ethernet;
-
-import static android.net.TestNetworkManager.TEST_TAP_PREFIX;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertThrows;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.net.EthernetManager;
-import android.net.InetAddresses;
-import android.net.INetworkInterfaceOutcomeReceiver;
-import android.net.IEthernetServiceListener;
-import android.net.INetd;
-import android.net.IpConfiguration;
-import android.net.IpConfiguration.IpAssignment;
-import android.net.IpConfiguration.ProxySettings;
-import android.net.InterfaceConfigurationParcel;
-import android.net.LinkAddress;
-import android.net.NetworkCapabilities;
-import android.net.StaticIpConfiguration;
-import android.os.HandlerThread;
-import android.os.RemoteException;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.connectivity.resources.R;
-import com.android.testutils.HandlerUtils;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.net.InetAddress;
-import java.util.ArrayList;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class EthernetTrackerTest {
- private static final String TEST_IFACE = "test123";
- private static final int TIMEOUT_MS = 1_000;
- private static final String THREAD_NAME = "EthernetServiceThread";
- private static final INetworkInterfaceOutcomeReceiver NULL_LISTENER = null;
- private EthernetTracker tracker;
- private HandlerThread mHandlerThread;
- @Mock private Context mContext;
- @Mock private EthernetNetworkFactory mFactory;
- @Mock private INetd mNetd;
- @Mock private EthernetTracker.Dependencies mDeps;
-
- @Before
- public void setUp() throws RemoteException {
- MockitoAnnotations.initMocks(this);
- initMockResources();
- when(mFactory.updateInterfaceLinkState(anyString(), anyBoolean(), any())).thenReturn(false);
- when(mNetd.interfaceGetList()).thenReturn(new String[0]);
- mHandlerThread = new HandlerThread(THREAD_NAME);
- mHandlerThread.start();
- tracker = new EthernetTracker(mContext, mHandlerThread.getThreadHandler(), mFactory, mNetd,
- mDeps);
- }
-
- @After
- public void cleanUp() {
- mHandlerThread.quitSafely();
- }
-
- private void initMockResources() {
- when(mDeps.getInterfaceRegexFromResource(eq(mContext))).thenReturn("");
- when(mDeps.getInterfaceConfigFromResource(eq(mContext))).thenReturn(new String[0]);
- }
-
- private void waitForIdle() {
- HandlerUtils.waitForIdle(mHandlerThread, TIMEOUT_MS);
- }
-
- /**
- * Test: Creation of various valid static IP configurations
- */
- @Test
- public void createStaticIpConfiguration() {
- // Empty gives default StaticIPConfiguration object
- assertStaticConfiguration(new StaticIpConfiguration(), "");
-
- // Setting only the IP address properly cascades and assumes defaults
- assertStaticConfiguration(new StaticIpConfiguration.Builder()
- .setIpAddress(new LinkAddress("192.0.2.10/24")).build(), "ip=192.0.2.10/24");
-
- final ArrayList<InetAddress> dnsAddresses = new ArrayList<>();
- dnsAddresses.add(InetAddresses.parseNumericAddress("4.4.4.4"));
- dnsAddresses.add(InetAddresses.parseNumericAddress("8.8.8.8"));
- // Setting other fields properly cascades them
- assertStaticConfiguration(new StaticIpConfiguration.Builder()
- .setIpAddress(new LinkAddress("192.0.2.10/24"))
- .setDnsServers(dnsAddresses)
- .setGateway(InetAddresses.parseNumericAddress("192.0.2.1"))
- .setDomains("android").build(),
- "ip=192.0.2.10/24 dns=4.4.4.4,8.8.8.8 gateway=192.0.2.1 domains=android");
-
- // Verify order doesn't matter
- assertStaticConfiguration(new StaticIpConfiguration.Builder()
- .setIpAddress(new LinkAddress("192.0.2.10/24"))
- .setDnsServers(dnsAddresses)
- .setGateway(InetAddresses.parseNumericAddress("192.0.2.1"))
- .setDomains("android").build(),
- "domains=android ip=192.0.2.10/24 gateway=192.0.2.1 dns=4.4.4.4,8.8.8.8 ");
- }
-
- /**
- * Test: Attempt creation of various bad static IP configurations
- */
- @Test
- public void createStaticIpConfiguration_Bad() {
- assertStaticConfigurationFails("ip=192.0.2.1/24 gateway= blah=20.20.20.20"); // Unknown key
- assertStaticConfigurationFails("ip=192.0.2.1"); // mask is missing
- assertStaticConfigurationFails("ip=a.b.c"); // not a valid ip address
- assertStaticConfigurationFails("dns=4.4.4.4,1.2.3.A"); // not valid ip address in dns
- assertStaticConfigurationFails("="); // Key and value is empty
- assertStaticConfigurationFails("ip="); // Value is empty
- assertStaticConfigurationFails("ip=192.0.2.1/24 gateway="); // Gateway is empty
- }
-
- private void assertStaticConfigurationFails(String config) {
- try {
- EthernetTracker.parseStaticIpConfiguration(config);
- fail("Expected to fail: " + config);
- } catch (IllegalArgumentException e) {
- // expected
- }
- }
-
- private void assertStaticConfiguration(StaticIpConfiguration expectedStaticIpConfig,
- String configAsString) {
- final IpConfiguration expectedIpConfiguration = new IpConfiguration();
- expectedIpConfiguration.setIpAssignment(IpAssignment.STATIC);
- expectedIpConfiguration.setProxySettings(ProxySettings.NONE);
- expectedIpConfiguration.setStaticIpConfiguration(expectedStaticIpConfig);
-
- assertEquals(expectedIpConfiguration,
- EthernetTracker.parseStaticIpConfiguration(configAsString));
- }
-
- private NetworkCapabilities.Builder makeEthernetCapabilitiesBuilder(boolean clearAll) {
- final NetworkCapabilities.Builder builder =
- clearAll ? NetworkCapabilities.Builder.withoutDefaultCapabilities()
- : new NetworkCapabilities.Builder();
- return builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED);
- }
-
- /**
- * Test: Attempt to create a capabilties with various valid sets of capabilities/transports
- */
- @Test
- public void createNetworkCapabilities() {
-
- // Particularly common expected results
- NetworkCapabilities defaultEthernetCleared =
- makeEthernetCapabilitiesBuilder(true /* clearAll */)
- .setLinkUpstreamBandwidthKbps(100000)
- .setLinkDownstreamBandwidthKbps(100000)
- .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
- .build();
-
- NetworkCapabilities ethernetClearedWithCommonCaps =
- makeEthernetCapabilitiesBuilder(true /* clearAll */)
- .setLinkUpstreamBandwidthKbps(100000)
- .setLinkDownstreamBandwidthKbps(100000)
- .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
- .addCapability(12)
- .addCapability(13)
- .addCapability(14)
- .addCapability(15)
- .build();
-
- // Empty capabilities and transports lists with a "please clear defaults" should
- // yield an empty capabilities set with TRANPORT_ETHERNET
- assertParsedNetworkCapabilities(defaultEthernetCleared, true, "", "");
-
- // Empty capabilities and transports without the clear defaults flag should return the
- // default capabilities set with TRANSPORT_ETHERNET
- assertParsedNetworkCapabilities(
- makeEthernetCapabilitiesBuilder(false /* clearAll */)
- .setLinkUpstreamBandwidthKbps(100000)
- .setLinkDownstreamBandwidthKbps(100000)
- .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
- .build(),
- false, "", "");
-
- // A list of capabilities without the clear defaults flag should return the default
- // capabilities, mixed with the desired capabilities, and TRANSPORT_ETHERNET
- assertParsedNetworkCapabilities(
- makeEthernetCapabilitiesBuilder(false /* clearAll */)
- .setLinkUpstreamBandwidthKbps(100000)
- .setLinkDownstreamBandwidthKbps(100000)
- .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
- .addCapability(11)
- .addCapability(12)
- .build(),
- false, "11,12", "");
-
- // Adding a list of capabilities with a clear defaults will leave exactly those capabilities
- // with a default TRANSPORT_ETHERNET since no overrides are specified
- assertParsedNetworkCapabilities(ethernetClearedWithCommonCaps, true, "12,13,14,15", "");
-
- // Adding any invalid capabilities to the list will cause them to be ignored
- assertParsedNetworkCapabilities(ethernetClearedWithCommonCaps, true, "12,13,14,15,65,73", "");
- assertParsedNetworkCapabilities(ethernetClearedWithCommonCaps, true, "12,13,14,15,abcdefg", "");
-
- // Adding a valid override transport will remove the default TRANSPORT_ETHERNET transport
- // and apply only the override to the capabiltities object
- assertParsedNetworkCapabilities(
- makeEthernetCapabilitiesBuilder(true /* clearAll */)
- .setLinkUpstreamBandwidthKbps(100000)
- .setLinkDownstreamBandwidthKbps(100000)
- .addTransportType(0)
- .build(),
- true, "", "0");
- assertParsedNetworkCapabilities(
- makeEthernetCapabilitiesBuilder(true /* clearAll */)
- .setLinkUpstreamBandwidthKbps(100000)
- .setLinkDownstreamBandwidthKbps(100000)
- .addTransportType(1)
- .build(),
- true, "", "1");
- assertParsedNetworkCapabilities(
- makeEthernetCapabilitiesBuilder(true /* clearAll */)
- .setLinkUpstreamBandwidthKbps(100000)
- .setLinkDownstreamBandwidthKbps(100000)
- .addTransportType(2)
- .build(),
- true, "", "2");
- assertParsedNetworkCapabilities(
- makeEthernetCapabilitiesBuilder(true /* clearAll */)
- .setLinkUpstreamBandwidthKbps(100000)
- .setLinkDownstreamBandwidthKbps(100000)
- .addTransportType(3)
- .build(),
- true, "", "3");
-
- // "4" is TRANSPORT_VPN, which is unsupported. Should default back to TRANPORT_ETHERNET
- assertParsedNetworkCapabilities(defaultEthernetCleared, true, "", "4");
-
- // "5" is TRANSPORT_WIFI_AWARE, which is currently supported due to no legacy TYPE_NONE
- // conversion. When that becomes available, this test must be updated
- assertParsedNetworkCapabilities(defaultEthernetCleared, true, "", "5");
-
- // "6" is TRANSPORT_LOWPAN, which is currently supported due to no legacy TYPE_NONE
- // conversion. When that becomes available, this test must be updated
- assertParsedNetworkCapabilities(defaultEthernetCleared, true, "", "6");
-
- // Adding an invalid override transport will leave the transport as TRANSPORT_ETHERNET
- assertParsedNetworkCapabilities(defaultEthernetCleared,true, "", "100");
- assertParsedNetworkCapabilities(defaultEthernetCleared, true, "", "abcdefg");
-
- // Ensure the adding of both capabilities and transports work
- assertParsedNetworkCapabilities(
- makeEthernetCapabilitiesBuilder(true /* clearAll */)
- .setLinkUpstreamBandwidthKbps(100000)
- .setLinkDownstreamBandwidthKbps(100000)
- .addCapability(12)
- .addCapability(13)
- .addCapability(14)
- .addCapability(15)
- .addTransportType(3)
- .build(),
- true, "12,13,14,15", "3");
-
- // Ensure order does not matter for capability list
- assertParsedNetworkCapabilities(ethernetClearedWithCommonCaps, true, "13,12,15,14", "");
- }
-
- private void assertParsedNetworkCapabilities(NetworkCapabilities expectedNetworkCapabilities,
- boolean clearCapabilties, String configCapabiltiies,String configTransports) {
- assertEquals(expectedNetworkCapabilities,
- EthernetTracker.createNetworkCapabilities(clearCapabilties, configCapabiltiies,
- configTransports).build());
- }
-
- @Test
- public void testCreateEthernetTrackerConfigReturnsCorrectValue() {
- final String capabilities = "2";
- final String ipConfig = "3";
- final String transport = "4";
- final String configString = String.join(";", TEST_IFACE, capabilities, ipConfig, transport);
-
- final EthernetTracker.EthernetTrackerConfig config =
- EthernetTracker.createEthernetTrackerConfig(configString);
-
- assertEquals(TEST_IFACE, config.mIface);
- assertEquals(capabilities, config.mCapabilities);
- assertEquals(ipConfig, config.mIpConfig);
- assertEquals(transport, config.mTransport);
- }
-
- @Test
- public void testCreateEthernetTrackerConfigThrowsNpeWithNullInput() {
- assertThrows(NullPointerException.class,
- () -> EthernetTracker.createEthernetTrackerConfig(null));
- }
-
- @Test
- public void testUpdateConfiguration() {
- final NetworkCapabilities capabilities = new NetworkCapabilities.Builder().build();
- final LinkAddress linkAddr = new LinkAddress("192.0.2.2/25");
- final StaticIpConfiguration staticIpConfig =
- new StaticIpConfiguration.Builder().setIpAddress(linkAddr).build();
- final IpConfiguration ipConfig =
- new IpConfiguration.Builder().setStaticIpConfiguration(staticIpConfig).build();
- final INetworkInterfaceOutcomeReceiver listener = null;
-
- tracker.updateConfiguration(TEST_IFACE, ipConfig, capabilities, listener);
- waitForIdle();
-
- verify(mFactory).updateInterface(
- eq(TEST_IFACE), eq(ipConfig), eq(capabilities), eq(listener));
- }
-
- @Test
- public void testConnectNetworkCorrectlyCallsFactory() {
- tracker.connectNetwork(TEST_IFACE, NULL_LISTENER);
- waitForIdle();
-
- verify(mFactory).updateInterfaceLinkState(eq(TEST_IFACE), eq(true /* up */),
- eq(NULL_LISTENER));
- }
-
- @Test
- public void testDisconnectNetworkCorrectlyCallsFactory() {
- tracker.disconnectNetwork(TEST_IFACE, NULL_LISTENER);
- waitForIdle();
-
- verify(mFactory).updateInterfaceLinkState(eq(TEST_IFACE), eq(false /* up */),
- eq(NULL_LISTENER));
- }
-
- @Test
- public void testIsValidTestInterfaceIsFalseWhenTestInterfacesAreNotIncluded() {
- final String validIfaceName = TEST_TAP_PREFIX + "123";
- tracker.setIncludeTestInterfaces(false);
- waitForIdle();
-
- final boolean isValidTestInterface = tracker.isValidTestInterface(validIfaceName);
-
- assertFalse(isValidTestInterface);
- }
-
- @Test
- public void testIsValidTestInterfaceIsFalseWhenTestInterfaceNameIsInvalid() {
- final String invalidIfaceName = "123" + TEST_TAP_PREFIX;
- tracker.setIncludeTestInterfaces(true);
- waitForIdle();
-
- final boolean isValidTestInterface = tracker.isValidTestInterface(invalidIfaceName);
-
- assertFalse(isValidTestInterface);
- }
-
- @Test
- public void testIsValidTestInterfaceIsTrueWhenTestInterfacesIncludedAndValidName() {
- final String validIfaceName = TEST_TAP_PREFIX + "123";
- tracker.setIncludeTestInterfaces(true);
- waitForIdle();
-
- final boolean isValidTestInterface = tracker.isValidTestInterface(validIfaceName);
-
- assertTrue(isValidTestInterface);
- }
-
- public static class EthernetStateListener extends IEthernetServiceListener.Stub {
- @Override
- public void onEthernetStateChanged(int state) { }
-
- @Override
- public void onInterfaceStateChanged(String iface, int state, int role,
- IpConfiguration configuration) { }
- }
-
- @Test
- public void testListenEthernetStateChange() throws Exception {
- final String testIface = "testtap123";
- final String testHwAddr = "11:22:33:44:55:66";
- final InterfaceConfigurationParcel ifaceParcel = new InterfaceConfigurationParcel();
- ifaceParcel.ifName = testIface;
- ifaceParcel.hwAddr = testHwAddr;
- ifaceParcel.flags = new String[] {INetd.IF_STATE_UP};
-
- tracker.setIncludeTestInterfaces(true);
- waitForIdle();
-
- when(mNetd.interfaceGetList()).thenReturn(new String[] {testIface});
- when(mNetd.interfaceGetCfg(eq(testIface))).thenReturn(ifaceParcel);
- doReturn(new String[] {testIface}).when(mFactory).getAvailableInterfaces(anyBoolean());
- doReturn(EthernetManager.STATE_LINK_UP).when(mFactory).getInterfaceState(eq(testIface));
-
- final EthernetStateListener listener = spy(new EthernetStateListener());
- tracker.addListener(listener, true /* canUseRestrictedNetworks */);
- // Check default state.
- waitForIdle();
- verify(listener).onInterfaceStateChanged(eq(testIface), eq(EthernetManager.STATE_LINK_UP),
- anyInt(), any());
- verify(listener).onEthernetStateChanged(eq(EthernetManager.ETHERNET_STATE_ENABLED));
- reset(listener);
-
- doReturn(EthernetManager.STATE_ABSENT).when(mFactory).getInterfaceState(eq(testIface));
- tracker.setEthernetEnabled(false);
- waitForIdle();
- verify(mFactory).removeInterface(eq(testIface));
- verify(listener).onEthernetStateChanged(eq(EthernetManager.ETHERNET_STATE_DISABLED));
- verify(listener).onInterfaceStateChanged(eq(testIface), eq(EthernetManager.STATE_ABSENT),
- anyInt(), any());
- reset(listener);
-
- doReturn(EthernetManager.STATE_LINK_UP).when(mFactory).getInterfaceState(eq(testIface));
- tracker.setEthernetEnabled(true);
- waitForIdle();
- verify(mFactory).addInterface(eq(testIface), eq(testHwAddr), any(), any());
- verify(listener).onEthernetStateChanged(eq(EthernetManager.ETHERNET_STATE_ENABLED));
- verify(listener).onInterfaceStateChanged(eq(testIface), eq(EthernetManager.STATE_LINK_UP),
- anyInt(), any());
- }
-}