Empty merge of sc-v2-dev-plus-aosp-without-vendor@8084891
Bug: 214455710
Merged-In: Idd3b7875a24643d245d0f4bb6f2f4c459898116e
Change-Id: I74463ff94a96d5c0807ef33b41b74dc580b039cb
diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java
index b556f6c..a15fec4 100644
--- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java
+++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java
@@ -21,11 +21,13 @@
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.EthernetNetworkSpecifier;
-import android.net.IInternalNetworkManagementListener;
+import android.net.IEthernetNetworkManagementListener;
+import android.net.EthernetNetworkManagementException;
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;
@@ -193,24 +195,19 @@
* {@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 IInternalNetworkManagementListener} to notify callers of
+ * @param listener an optional {@link IEthernetNetworkManagementListener} to notify callers of
* completion.
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
protected void updateInterface(@NonNull final String ifaceName,
@NonNull final IpConfiguration ipConfig,
@Nullable final NetworkCapabilities capabilities,
- @Nullable final IInternalNetworkManagementListener listener) {
+ @Nullable final IEthernetNetworkManagementListener listener) {
enforceInterfaceIsTracked(ifaceName);
final NetworkInterfaceState iface = mTrackingInterfaces.get(ifaceName);
- // TODO: The listener will have issues if called in quick succession for the same interface
- // before the IP layer restarts. Update the listener logic to address multiple successive
- // calls for a particular interface.
- iface.mNetworkManagementListener = listener;
- if (iface.updateInterface(ipConfig, capabilities)) {
- mTrackingInterfaces.put(ifaceName, iface);
- updateCapabilityFilter();
- }
+ iface.updateInterface(ipConfig, capabilities, listener);
+ mTrackingInterfaces.put(ifaceName, iface);
+ updateCapabilityFilter();
}
private void enforceInterfaceIsTracked(@NonNull final String ifaceName) {
@@ -247,6 +244,7 @@
void removeInterface(String interfaceName) {
NetworkInterfaceState iface = mTrackingInterfaces.remove(interfaceName);
if (iface != null) {
+ iface.maybeSendNetworkManagementCallbackForAbort();
iface.stop();
}
@@ -254,8 +252,13 @@
}
/** Returns true if state has been modified */
- boolean updateInterfaceLinkState(String ifaceName, boolean up) {
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ protected boolean updateInterfaceLinkState(@NonNull final String ifaceName, final boolean up,
+ @Nullable final IEthernetNetworkManagementListener listener) {
if (!mTrackingInterfaces.containsKey(ifaceName)) {
+ maybeSendNetworkManagementCallback(listener, null,
+ new EthernetNetworkManagementException(
+ ifaceName + " can't be updated as it is not available."));
return false;
}
@@ -264,7 +267,7 @@
}
NetworkInterfaceState iface = mTrackingInterfaces.get(ifaceName);
- return iface.updateLinkState(up);
+ return iface.updateLinkState(up, listener);
}
boolean hasInterface(String ifaceName) {
@@ -302,6 +305,21 @@
return network;
}
+ private static void maybeSendNetworkManagementCallback(
+ @Nullable final IEthernetNetworkManagementListener listener,
+ @Nullable final Network network,
+ @Nullable final EthernetNetworkManagementException e) {
+ if (null == listener) {
+ return;
+ }
+
+ try {
+ listener.onComplete(network, e);
+ } catch (RemoteException re) {
+ Log.e(TAG, "Can't send onComplete for network management callback", re);
+ }
+ }
+
@VisibleForTesting
static class NetworkInterfaceState {
final String name;
@@ -320,8 +338,7 @@
private volatile @Nullable IpClientManager mIpClient;
private @NonNull NetworkCapabilities mCapabilities;
- private @Nullable IpClientCallbacksImpl mIpClientCallback;
- private @Nullable IInternalNetworkManagementListener mNetworkManagementListener;
+ private @Nullable EthernetIpClientCallback mIpClientCallback;
private @Nullable EthernetNetworkAgent mNetworkAgent;
private @Nullable IpConfiguration mIpConfig;
@@ -348,9 +365,14 @@
long refCount = 0;
- private class IpClientCallbacksImpl extends IpClientCallbacks {
+ private class EthernetIpClientCallback extends IpClientCallbacks {
private final ConditionVariable mIpClientStartCv = new ConditionVariable(false);
private final ConditionVariable mIpClientShutdownCv = new ConditionVariable(false);
+ @Nullable IEthernetNetworkManagementListener mNetworkManagementListener;
+
+ EthernetIpClientCallback(@Nullable final IEthernetNetworkManagementListener listener) {
+ mNetworkManagementListener = listener;
+ }
@Override
public void onIpClientCreated(IIpClient ipClient) {
@@ -368,12 +390,12 @@
@Override
public void onProvisioningSuccess(LinkProperties newLp) {
- mHandler.post(() -> onIpLayerStarted(newLp));
+ mHandler.post(() -> onIpLayerStarted(newLp, mNetworkManagementListener));
}
@Override
public void onProvisioningFailure(LinkProperties newLp) {
- mHandler.post(() -> onIpLayerStopped(newLp));
+ mHandler.post(() -> onIpLayerStopped(mNetworkManagementListener));
}
@Override
@@ -431,30 +453,25 @@
mLegacyType = getLegacyType(mCapabilities);
}
- boolean updateInterface(@NonNull final IpConfiguration ipConfig,
- @Nullable final NetworkCapabilities capabilities) {
- final boolean shouldUpdateIpConfig = !Objects.equals(mIpConfig, ipConfig);
- final boolean shouldUpdateCapabilities = null != capabilities
- && !Objects.equals(mCapabilities, capabilities);
+ void updateInterface(@NonNull final IpConfiguration ipConfig,
+ @Nullable final NetworkCapabilities capabilities,
+ @Nullable final IEthernetNetworkManagementListener listener) {
if (DBG) {
Log.d(TAG, "updateInterface, iface: " + name
- + ", shouldUpdateIpConfig: " + shouldUpdateIpConfig
- + ", shouldUpdateCapabilities: " + shouldUpdateCapabilities
+ ", ipConfig: " + ipConfig + ", old ipConfig: " + mIpConfig
+ ", capabilities: " + capabilities + ", old capabilities: " + mCapabilities
+ + ", listener: " + listener
);
}
- if (shouldUpdateIpConfig) { mIpConfig = ipConfig; };
- if (shouldUpdateCapabilities) { setCapabilities(capabilities); };
- if (shouldUpdateIpConfig || shouldUpdateCapabilities) {
- // 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();
- return true;
- }
- return false;
+ mIpConfig = ipConfig;
+ 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() {
@@ -462,6 +479,10 @@
}
private void start() {
+ start(null);
+ }
+
+ private void start(@Nullable final IEthernetNetworkManagementListener listener) {
if (mIpClient != null) {
if (DBG) Log.d(TAG, "IpClient already started");
return;
@@ -470,9 +491,10 @@
Log.d(TAG, String.format("Starting Ethernet IpClient(%s)", name));
}
- mIpClientCallback = new IpClientCallbacksImpl();
+ mIpClientCallback = new EthernetIpClientCallback(listener);
mDeps.makeIpClient(mContext, name, mIpClientCallback);
mIpClientCallback.awaitIpClientStart();
+
if (sTcpBufferSizes == null) {
sTcpBufferSizes = mContext.getResources().getString(
com.android.internal.R.string.config_ethernet_tcp_buffers);
@@ -480,7 +502,16 @@
provisionIpClient(mIpClient, mIpConfig, sTcpBufferSizes);
}
- void onIpLayerStarted(LinkProperties linkProperties) {
+ void onIpLayerStarted(@NonNull final LinkProperties linkProperties,
+ @Nullable final IEthernetNetworkManagementListener listener) {
+ if(mIpClient == null) {
+ // This call comes from a message posted on the handler thread, but the IpClient has
+ // since been stopped such as may be the case if updateInterfaceLinkState() is
+ // queued on the handler thread prior. As network management callbacks are sent in
+ // stop(), there is no need to send them again here.
+ if (DBG) Log.d(TAG, "IpClient is not initialized.");
+ return;
+ }
if (mNetworkAgent != null) {
Log.e(TAG, "Already have a NetworkAgent - aborting new request");
stop();
@@ -512,33 +543,61 @@
});
mNetworkAgent.register();
mNetworkAgent.markConnected();
- sendNetworkManagementCallback();
+ realizeNetworkManagementCallback(mNetworkAgent.getNetwork(), null);
}
- private void sendNetworkManagementCallback() {
- if (null != mNetworkManagementListener) {
- try {
- mNetworkManagementListener.onComplete(mNetworkAgent.getNetwork(), null);
- } catch (RemoteException e) {
- Log.e(TAG, "Can't send onComplete for network management callback", e);
- } finally {
- mNetworkManagementListener = null;
- }
+ void onIpLayerStopped(@Nullable final IEthernetNetworkManagementListener listener) {
+ // This cannot happen due to provisioning timeout, because our timeout is 0. It can
+ // happen due to errors while provisioning or on provisioning loss.
+ if(mIpClient == null) {
+ if (DBG) Log.d(TAG, "IpClient is not initialized.");
+ return;
}
+ // 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);
}
- void onIpLayerStopped(LinkProperties linkProperties) {
- // This cannot happen due to provisioning timeout, because our timeout is 0. It can only
- // happen if we're provisioned and we lose provisioning.
- stop();
- // If the interface has disappeared provisioning will fail over and over again, so
- // there is no point in starting again
- if (null != mDeps.getNetworkInterfaceByName(name)) {
- start();
+ 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 Network network,
+ @Nullable final EthernetNetworkManagementException e) {
+ ensureRunningOnEthernetHandlerThread();
+ if (null == mIpClientCallback) {
+ return;
+ }
+
+ EthernetNetworkFactory.maybeSendNetworkManagementCallback(
+ mIpClientCallback.mNetworkManagementListener, network, 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) {
+ if(mIpClient == null) {
+ if (DBG) Log.d(TAG, "IpClient is not initialized.");
+ return;
+ }
mLinkProperties = linkProperties;
if (mNetworkAgent != null) {
mNetworkAgent.sendLinkPropertiesImpl(linkProperties);
@@ -546,6 +605,10 @@
}
void updateNeighborLostEvent(String logMsg) {
+ if(mIpClient == null) {
+ if (DBG) Log.d(TAG, "IpClient is not initialized.");
+ return;
+ }
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
@@ -557,13 +620,27 @@
}
/** Returns true if state has been modified */
- boolean updateLinkState(boolean up) {
- if (mLinkUp == up) return false;
+ boolean updateLinkState(final boolean up,
+ @Nullable final IEthernetNetworkManagementListener listener) {
+ if (mLinkUp == up) {
+ EthernetNetworkFactory.maybeSendNetworkManagementCallback(listener, null,
+ new EthernetNetworkManagementException(
+ "No changes with requested link state " + up + " for " + name));
+ return false;
+ }
mLinkUp = up;
- stop();
- if (up) {
- start();
+ if (!up) { // was up, goes down
+ // Save an instance of the current network to use with the callback before stop().
+ final Network network = mNetworkAgent != null ? mNetworkAgent.getNetwork() : null;
+ // 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, network, null);
+ } else { // was down, goes up
+ stop();
+ start(listener);
}
return true;
@@ -611,10 +688,14 @@
.build();
}
- void restart(){
+ void restart() {
+ restart(null);
+ }
+
+ void restart(@Nullable final IEthernetNetworkManagementListener listener){
if (DBG) Log.d(TAG, "reconnecting Ethernet");
stop();
- start();
+ start(listener);
}
@Override
diff --git a/service-t/src/com/android/server/ethernet/EthernetService.java b/service-t/src/com/android/server/ethernet/EthernetService.java
index 492a55a..e6fee9e 100644
--- a/service-t/src/com/android/server/ethernet/EthernetService.java
+++ b/service-t/src/com/android/server/ethernet/EthernetService.java
@@ -18,7 +18,6 @@
import android.content.Context;
import android.net.INetd;
-import android.net.util.NetdService;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
@@ -41,11 +40,12 @@
final EthernetNetworkFactory factory = new EthernetNetworkFactory(handler, context);
mImpl = new EthernetServiceImpl(
context, handler,
- new EthernetTracker(context, handler, factory, getNetd()));
+ new EthernetTracker(context, handler, factory, getNetd(context)));
}
- private INetd getNetd() {
- final INetd netd = NetdService.getInstance();
+ private 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;
}
diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java
index b284477..ffd6d40 100644
--- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java
+++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java
@@ -22,9 +22,9 @@
import android.content.pm.PackageManager;
import android.net.IEthernetManager;
import android.net.IEthernetServiceListener;
-import android.net.IInternalNetworkManagementListener;
+import android.net.IEthernetNetworkManagementListener;
import android.net.ITetheredInterfaceCallback;
-import android.net.InternalNetworkUpdateRequest;
+import android.net.EthernetNetworkUpdateRequest;
import android.net.IpConfiguration;
import android.os.Binder;
import android.os.Handler;
@@ -208,6 +208,12 @@
pw.decreaseIndent();
}
+ private void enforceNetworkManagementPermission() {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.MANAGE_ETHERNET_NETWORKS,
+ "EthernetServiceImpl");
+ }
+
/**
* Validate the state of ethernet for APIs tied to network management.
*
@@ -216,19 +222,19 @@
*/
private void validateNetworkManagementState(@NonNull final String iface,
final @NonNull String methodName) {
+ enforceAutomotiveDevice(methodName);
+ enforceNetworkManagementPermission();
logIfEthernetNotStarted();
- // TODO: add permission check here for MANAGE_INTERNAL_NETWORKS when it's available.
Objects.requireNonNull(iface, "Pass a non-null iface.");
Objects.requireNonNull(methodName, "Pass a non-null methodName.");
- enforceAutomotiveDevice(methodName);
enforceInterfaceIsTracked(iface);
}
@Override
public void updateConfiguration(@NonNull final String iface,
- @NonNull final InternalNetworkUpdateRequest request,
- @Nullable final IInternalNetworkManagementListener listener) {
+ @NonNull final EthernetNetworkUpdateRequest request,
+ @Nullable final IEthernetNetworkManagementListener listener) {
Log.i(TAG, "updateConfiguration called with: iface=" + iface
+ ", request=" + request + ", listener=" + listener);
validateNetworkManagementState(iface, "updateConfiguration()");
@@ -240,15 +246,17 @@
@Override
public void connectNetwork(@NonNull final String iface,
- @Nullable final IInternalNetworkManagementListener listener) {
+ @Nullable final IEthernetNetworkManagementListener listener) {
Log.i(TAG, "connectNetwork called with: iface=" + iface + ", listener=" + listener);
validateNetworkManagementState(iface, "connectNetwork()");
+ mTracker.connectNetwork(iface, listener);
}
@Override
public void disconnectNetwork(@NonNull final String iface,
- @Nullable final IInternalNetworkManagementListener listener) {
+ @Nullable final IEthernetNetworkManagementListener listener) {
Log.i(TAG, "disconnectNetwork called with: iface=" + iface + ", listener=" + listener);
validateNetworkManagementState(iface, "disconnectNetwork()");
+ mTracker.disconnectNetwork(iface, listener);
}
}
diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java
index 0b6547d..6c8e6d3 100644
--- a/service-t/src/com/android/server/ethernet/EthernetTracker.java
+++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java
@@ -24,7 +24,7 @@
import android.annotation.Nullable;
import android.content.Context;
import android.net.IEthernetServiceListener;
-import android.net.IInternalNetworkManagementListener;
+import android.net.IEthernetNetworkManagementListener;
import android.net.INetd;
import android.net.ITetheredInterfaceCallback;
import android.net.InterfaceConfigurationParcel;
@@ -34,6 +34,7 @@
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;
@@ -177,7 +178,7 @@
protected void updateConfiguration(@NonNull final String iface,
@NonNull final StaticIpConfiguration staticIpConfig,
@NonNull final NetworkCapabilities capabilities,
- @Nullable final IInternalNetworkManagementListener listener) {
+ @Nullable final IEthernetNetworkManagementListener listener) {
if (DBG) {
Log.i(TAG, "updateConfiguration, iface: " + iface + ", capabilities: " + capabilities
+ ", staticIpConfig: " + staticIpConfig);
@@ -189,6 +190,18 @@
mFactory.updateInterface(iface, ipConfig, capabilities, listener));
}
+ @VisibleForTesting(visibility = PACKAGE)
+ protected void connectNetwork(@NonNull final String iface,
+ @Nullable final IEthernetNetworkManagementListener listener) {
+ mHandler.post(() -> updateInterfaceState(iface, true, listener));
+ }
+
+ @VisibleForTesting(visibility = PACKAGE)
+ protected void disconnectNetwork(@NonNull final String iface,
+ @Nullable final IEthernetNetworkManagementListener listener) {
+ mHandler.post(() -> updateInterfaceState(iface, false, listener));
+ }
+
IpConfiguration getIpConfiguration(String iface) {
return mIpConfigurations.get(iface);
}
@@ -353,9 +366,14 @@
}
private void updateInterfaceState(String iface, boolean up) {
+ updateInterfaceState(iface, up, null /* listener */);
+ }
+
+ private void updateInterfaceState(@NonNull final String iface, final boolean up,
+ @Nullable final IEthernetNetworkManagementListener listener) {
final int mode = getInterfaceMode(iface);
final boolean factoryLinkStateUpdated = (mode == INTERFACE_MODE_CLIENT)
- && mFactory.updateInterfaceLinkState(iface, up);
+ && mFactory.updateInterfaceLinkState(iface, up, listener);
if (factoryLinkStateUpdated) {
boolean restricted = isRestrictedInterface(iface);
@@ -662,7 +680,13 @@
}
private void postAndWaitForRunnable(Runnable r) {
- mHandler.runWithScissors(r, 2000L /* timeout */);
+ final ConditionVariable cv = new ConditionVariable();
+ if (mHandler.post(() -> {
+ r.run();
+ cv.open();
+ })) {
+ cv.block(2000L);
+ }
}
void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) {
diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java
index 44ed26c..e10497e 100644
--- a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java
+++ b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java
@@ -16,11 +16,13 @@
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.assertNull;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.argThat;
@@ -38,8 +40,8 @@
import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.EthernetNetworkSpecifier;
-import android.net.IInternalNetworkManagementListener;
-import android.net.InternalNetworkManagementException;
+import android.net.IEthernetNetworkManagementListener;
+import android.net.EthernetNetworkManagementException;
import android.net.IpConfiguration;
import android.net.LinkAddress;
import android.net.LinkProperties;
@@ -63,6 +65,8 @@
import com.android.internal.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;
@@ -72,19 +76,18 @@
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
@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 IEthernetNetworkManagementListener 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 final TestLooper mLooper = new TestLooper();
+ private TestLooper mLooper;
private Handler mHandler;
private EthernetNetworkFactory mNetFactory = null;
private IpClientCallbacks mIpClientCallbacks;
@@ -99,14 +102,18 @@
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- mHandler = new Handler(mLooper.getLooper());
- mNetFactory = new EthernetNetworkFactory(mHandler, mContext, mDeps);
-
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() {
@@ -231,7 +238,7 @@
final IpConfiguration ipConfig = createDefaultIpConfig();
mNetFactory.addInterface(iface, HW_ADDR, ipConfig,
createInterfaceCapsBuilder(transportType).build());
- assertTrue(mNetFactory.updateInterfaceLinkState(iface, true));
+ assertTrue(mNetFactory.updateInterfaceLinkState(iface, true, NULL_LISTENER));
verifyStart(ipConfig);
clearInvocations(mDeps);
clearInvocations(mIpClient);
@@ -288,6 +295,7 @@
@Test
public void testAcceptRequest() throws Exception {
+ initEthernetNetworkFactory();
createInterfaceUndergoingProvisioning(TEST_IFACE);
assertTrue(mNetFactory.acceptRequest(createDefaultRequest()));
@@ -299,38 +307,81 @@
@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.
- assertTrue(mNetFactory.updateInterfaceLinkState(TEST_IFACE, false));
+ final boolean ret =
+ mNetFactory.updateInterfaceLinkState(TEST_IFACE, false /* up */, listener);
+
+ assertTrue(ret);
verify(mIpClient).shutdown();
+ assertSuccessfulListener(listener, null);
}
@Test
public void testUpdateInterfaceLinkStateForProvisionedInterface() throws Exception {
+ initEthernetNetworkFactory();
createAndVerifyProvisionedInterface(TEST_IFACE);
- assertTrue(mNetFactory.updateInterfaceLinkState(TEST_IFACE, false));
+ final TestNetworkManagementListener listener = new TestNetworkManagementListener();
+
+ final boolean ret =
+ mNetFactory.updateInterfaceLinkState(TEST_IFACE, false /* up */, listener);
+
+ assertTrue(ret);
verifyStop();
+ assertSuccessfulListener(listener, mMockNetwork);
}
@Test
public void testUpdateInterfaceLinkStateForUnprovisionedInterface() throws Exception {
+ initEthernetNetworkFactory();
createUnprovisionedInterface(TEST_IFACE);
- assertTrue(mNetFactory.updateInterfaceLinkState(TEST_IFACE, false));
+ 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());
+ assertSuccessfulListener(listener, null);
}
@Test
public void testUpdateInterfaceLinkStateForNonExistingInterface() throws Exception {
+ initEthernetNetworkFactory();
+ final TestNetworkManagementListener listener = new TestNetworkManagementListener();
+
// if interface was never added, link state cannot be updated.
- assertFalse(mNetFactory.updateInterfaceLinkState("eth1", true));
- verify(mDeps, never()).makeIpClient(any(), any(), any());
+ final boolean ret =
+ mNetFactory.updateInterfaceLinkState(TEST_IFACE, true /* up */, listener);
+
+ assertFalse(ret);
+ verifyNoStopOrStart();
+ assertFailedListener(listener, "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();
+ assertFailedListener(listener, "No changes");
}
@Test
public void testNeedNetworkForOnProvisionedInterface() throws Exception {
+ initEthernetNetworkFactory();
createAndVerifyProvisionedInterface(TEST_IFACE);
mNetFactory.needNetworkFor(createDefaultRequest());
verify(mIpClient, never()).startProvisioning(any());
@@ -338,6 +389,7 @@
@Test
public void testNeedNetworkForOnUnprovisionedInterface() throws Exception {
+ initEthernetNetworkFactory();
createUnprovisionedInterface(TEST_IFACE);
mNetFactory.needNetworkFor(createDefaultRequest());
verify(mIpClient).startProvisioning(any());
@@ -348,6 +400,7 @@
@Test
public void testNeedNetworkForOnInterfaceUndergoingProvisioning() throws Exception {
+ initEthernetNetworkFactory();
createInterfaceUndergoingProvisioning(TEST_IFACE);
mNetFactory.needNetworkFor(createDefaultRequest());
verify(mIpClient, never()).startProvisioning(any());
@@ -358,6 +411,7 @@
@Test
public void testProvisioningLoss() throws Exception {
+ initEthernetNetworkFactory();
when(mDeps.getNetworkInterfaceByName(TEST_IFACE)).thenReturn(mInterfaceParams);
createAndVerifyProvisionedInterface(TEST_IFACE);
@@ -369,20 +423,30 @@
@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();
- verifyStop();
+
// 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);
+ mNetFactory.updateInterfaceLinkState(TEST_IFACE, false, NULL_LISTENER);
mNetFactory.needNetworkFor(createDefaultRequest());
@@ -392,13 +456,15 @@
.build();
mNetFactory.needNetworkFor(specificNetRequest);
- // TODO(b/155707957): BUG: IPClient should not be started when the interface link state
- // is down.
- verify(mDeps).makeIpClient(any(), any(), any());
+ verify(mDeps, never()).makeIpClient(any(), any(), any());
+
+ mNetFactory.updateInterfaceLinkState(TEST_IFACE, true, NULL_LISTENER);
+ verify(mDeps).makeIpClient(any(), eq(TEST_IFACE), any());
}
@Test
public void testLinkPropertiesChanged() throws Exception {
+ initEthernetNetworkFactory();
createAndVerifyProvisionedInterface(TEST_IFACE);
LinkProperties lp = new LinkProperties();
@@ -409,6 +475,7 @@
@Test
public void testNetworkUnwanted() throws Exception {
+ initEthernetNetworkFactory();
createAndVerifyProvisionedInterface(TEST_IFACE);
mNetworkAgent.getCallbacks().onNetworkUnwanted();
@@ -418,6 +485,7 @@
@Test
public void testNetworkUnwantedWithStaleNetworkAgent() throws Exception {
+ initEthernetNetworkFactory();
// ensures provisioning is restarted after provisioning loss
when(mDeps.getNetworkInterfaceByName(TEST_IFACE)).thenReturn(mInterfaceParams);
createAndVerifyProvisionedInterface(TEST_IFACE);
@@ -441,6 +509,7 @@
@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,
@@ -461,6 +530,7 @@
@Test
public void testReachabilityLoss() throws Exception {
+ initEthernetNetworkFactory();
createAndVerifyProvisionedInterface(TEST_IFACE);
triggerOnReachabilityLost();
@@ -469,6 +539,72 @@
verifyRestart(createDefaultIpConfig());
}
+ @Test
+ public void testIgnoreOnIpLayerStartedCallbackAfterIpClientHasStopped() throws Exception {
+ initEthernetNetworkFactory();
+ createAndVerifyProvisionedInterface(TEST_IFACE);
+ mIpClientCallbacks.onProvisioningFailure(new LinkProperties());
+ mIpClientCallbacks.onProvisioningSuccess(new LinkProperties());
+ mLooper.dispatchAll();
+ verifyStop();
+
+ // ipClient has been shut down first, we should not retry
+ verify(mIpClient, never()).startProvisioning(any());
+ verify(mNetworkAgent, never()).register();
+ }
+
+ @Test
+ public void testIgnoreOnIpLayerStoppedCallbackAfterIpClientHasStopped() throws Exception {
+ initEthernetNetworkFactory();
+ createAndVerifyProvisionedInterface(TEST_IFACE);
+ when(mDeps.getNetworkInterfaceByName(TEST_IFACE)).thenReturn(mInterfaceParams);
+ mIpClientCallbacks.onProvisioningFailure(new LinkProperties());
+ mIpClientCallbacks.onProvisioningFailure(new LinkProperties());
+ mLooper.dispatchAll();
+ verifyStop();
+
+ // ipClient has been shut down first, we should not retry
+ verify(mIpClient).startProvisioning(any());
+ }
+
+ @Test
+ public void testIgnoreLinkPropertiesCallbackAfterIpClientHasStopped() throws Exception {
+ initEthernetNetworkFactory();
+ createAndVerifyProvisionedInterface(TEST_IFACE);
+ LinkProperties lp = new LinkProperties();
+
+ // The test requires the two proceeding methods to happen one after the other in ENF and
+ // verifies onLinkPropertiesChange doesn't complete execution for a downed interface.
+ // Posting is necessary as updateInterfaceLinkState with false will set mIpClientCallbacks
+ // to null which will throw an NPE in the test if executed synchronously.
+ mHandler.post(() -> mNetFactory.updateInterfaceLinkState(TEST_IFACE, false, NULL_LISTENER));
+ mIpClientCallbacks.onLinkPropertiesChange(lp);
+ mLooper.dispatchAll();
+
+ verifyStop();
+ // ipClient has been shut down first, we should not update
+ verify(mNetworkAgent, never()).sendLinkPropertiesImpl(same(lp));
+ }
+
+ @Test
+ public void testIgnoreNeighborLossCallbackAfterIpClientHasStopped() throws Exception {
+ initEthernetNetworkFactory();
+ createAndVerifyProvisionedInterface(TEST_IFACE);
+
+ // The test requires the two proceeding methods to happen one after the other in ENF and
+ // verifies onReachabilityLost doesn't complete execution for a downed interface.
+ // Posting is necessary as updateInterfaceLinkState with false will set mIpClientCallbacks
+ // to null which will throw an NPE in the test if executed synchronously.
+ mHandler.post(() -> mNetFactory.updateInterfaceLinkState(TEST_IFACE, false, NULL_LISTENER));
+ mIpClientCallbacks.onReachabilityLost("Neighbor Lost");
+ mLooper.dispatchAll();
+
+ verifyStop();
+ // ipClient has been shut down first, we should not update
+ verify(mIpClient, never()).startProvisioning(any());
+ verify(mNetworkAgent, never()).register();
+ }
+
private void verifyRestart(@NonNull final IpConfiguration ipConfig) {
verifyStop();
verifyStart(ipConfig);
@@ -492,17 +628,17 @@
}
private static final class TestNetworkManagementListener
- implements IInternalNetworkManagementListener {
- private final CompletableFuture<Pair<Network, InternalNetworkManagementException>> mDone
+ implements IEthernetNetworkManagementListener {
+ private final CompletableFuture<Pair<Network, EthernetNetworkManagementException>> mDone
= new CompletableFuture<>();
@Override
public void onComplete(final Network network,
- final InternalNetworkManagementException exception) {
+ final EthernetNetworkManagementException exception) {
mDone.complete(new Pair<>(network, exception));
}
- Pair<Network, InternalNetworkManagementException> expectOnComplete() throws Exception {
+ Pair<Network, EthernetNetworkManagementException> expectOnComplete() throws Exception {
return mDone.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
}
@@ -514,6 +650,7 @@
@Test
public void testUpdateInterfaceCallsListenerCorrectlyOnSuccess() throws Exception {
+ initEthernetNetworkFactory();
createAndVerifyProvisionedInterface(TEST_IFACE);
final NetworkCapabilities capabilities = createDefaultFilterCaps();
final IpConfiguration ipConfiguration = createStaticIpConfig();
@@ -522,13 +659,86 @@
mNetFactory.updateInterface(TEST_IFACE, ipConfiguration, capabilities, listener);
triggerOnProvisioningSuccess();
- final Pair<Network, InternalNetworkManagementException> ret = listener.expectOnComplete();
- assertEquals(mMockNetwork, ret.first);
- assertNull(ret.second);
+ assertSuccessfulListener(listener, mMockNetwork);
+ }
+
+ @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();
+ });
+
+ assertSuccessfulListener(successfulListener, mMockNetwork);
+ }
+
+ private void assertSuccessfulListener(
+ @NonNull final TestNetworkManagementListener successfulListener,
+ @NonNull final Network expectedNetwork) throws Exception {
+ final Pair<Network, EthernetNetworkManagementException> successfulResult =
+ successfulListener.expectOnComplete();
+ assertEquals(expectedNetwork, successfulResult.first);
+ assertNull(successfulResult.second);
+ }
+
+ private void assertFailedListener(@NonNull final TestNetworkManagementListener failedListener,
+ @NonNull final String errMsg)
+ throws Exception {
+ final Pair<Network, EthernetNetworkManagementException> failedResult =
+ failedListener.expectOnComplete();
+ assertNull(failedResult.first);
+ assertNotNull(failedResult.second);
+ assertTrue(failedResult.second.getMessage().contains(errMsg));
+ }
+
+ 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();
+
+ assertFailedListener(failedListener, "aborted");
}
@Test
public void testUpdateInterfaceRestartsAgentCorrectly() throws Exception {
+ initEthernetNetworkFactory();
createAndVerifyProvisionedInterface(TEST_IFACE);
final NetworkCapabilities capabilities = createDefaultFilterCaps();
final IpConfiguration ipConfiguration = createStaticIpConfig();
diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java
index 1c08883..0ac28c4 100644
--- a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java
+++ b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java
@@ -18,15 +18,18 @@
import static org.junit.Assert.assertThrows;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.verify;
+import android.Manifest;
import android.annotation.NonNull;
import android.content.Context;
import android.content.pm.PackageManager;
-import android.net.IInternalNetworkManagementListener;
-import android.net.InternalNetworkUpdateRequest;
+import android.net.IEthernetNetworkManagementListener;
+import android.net.EthernetNetworkUpdateRequest;
import android.net.IpConfiguration;
import android.net.NetworkCapabilities;
import android.net.StaticIpConfiguration;
@@ -45,10 +48,10 @@
@SmallTest
public class EthernetServiceImplTest {
private static final String TEST_IFACE = "test123";
- private static final InternalNetworkUpdateRequest UPDATE_REQUEST =
- new InternalNetworkUpdateRequest(
+ private static final EthernetNetworkUpdateRequest UPDATE_REQUEST =
+ new EthernetNetworkUpdateRequest(
new StaticIpConfiguration(), new NetworkCapabilities.Builder().build());
- private static final IInternalNetworkManagementListener NULL_LISTENER = null;
+ private static final IEthernetNetworkManagementListener NULL_LISTENER = null;
private EthernetServiceImpl mEthernetServiceImpl;
@Mock private Context mContext;
@Mock private Handler mHandler;
@@ -65,6 +68,15 @@
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);
@@ -143,11 +155,6 @@
});
}
- private void toggleAutomotiveFeature(final boolean isEnabled) {
- doReturn(isEnabled)
- .when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
- }
-
@Test
public void testUpdateConfigurationRejectsWithUntrackedIface() {
shouldTrackIface(TEST_IFACE, false);
@@ -172,8 +179,34 @@
});
}
- private void shouldTrackIface(@NonNull final String iface, final boolean shouldTrack) {
- doReturn(shouldTrack).when(mEthernetTracker).isTrackingInterface(iface);
+ private void denyManageEthPermission() {
+ doThrow(new SecurityException("")).when(mContext)
+ .enforceCallingOrSelfPermission(
+ eq(Manifest.permission.MANAGE_ETHERNET_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);
+ });
}
@Test
@@ -184,4 +217,16 @@
eq(UPDATE_REQUEST.getIpConfig()),
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));
+ }
}
diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java
index 5aca2e4..14f34d0 100644
--- a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java
+++ b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java
@@ -19,14 +19,18 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.res.Resources;
import android.net.InetAddresses;
-import android.net.IInternalNetworkManagementListener;
+import android.net.IEthernetNetworkManagementListener;
import android.net.INetd;
import android.net.IpConfiguration;
import android.net.IpConfiguration.IpAssignment;
@@ -55,8 +59,10 @@
@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 IEthernetNetworkManagementListener NULL_LISTENER = null;
private EthernetTracker tracker;
private HandlerThread mHandlerThread;
@Mock private Context mContext;
@@ -68,6 +74,7 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
initMockResources();
+ when(mFactory.updateInterfaceLinkState(anyString(), anyBoolean(), any())).thenReturn(false);
mHandlerThread = new HandlerThread(THREAD_NAME);
mHandlerThread.start();
tracker = new EthernetTracker(mContext, mHandlerThread.getThreadHandler(), mFactory, mNetd);
@@ -294,16 +301,15 @@
@Test
public void testCreateEthernetTrackerConfigReturnsCorrectValue() {
- final String iface = "1";
final String capabilities = "2";
final String ipConfig = "3";
final String transport = "4";
- final String configString = String.join(";", iface, capabilities, ipConfig, transport);
+ final String configString = String.join(";", TEST_IFACE, capabilities, ipConfig, transport);
final EthernetTracker.EthernetTrackerConfig config =
EthernetTracker.createEthernetTrackerConfig(configString);
- assertEquals(iface, config.mIface);
+ assertEquals(TEST_IFACE, config.mIface);
assertEquals(capabilities, config.mCapabilities);
assertEquals(ipConfig, config.mIpConfig);
assertEquals(transport, config.mTransport);
@@ -317,16 +323,33 @@
@Test
public void testUpdateConfiguration() {
- final String iface = "testiface";
final NetworkCapabilities capabilities = new NetworkCapabilities.Builder().build();
final StaticIpConfiguration staticIpConfig = new StaticIpConfiguration();
- final IInternalNetworkManagementListener listener = null;
+ final IEthernetNetworkManagementListener listener = null;
- tracker.updateConfiguration(iface, staticIpConfig, capabilities, listener);
+ tracker.updateConfiguration(TEST_IFACE, staticIpConfig, capabilities, listener);
waitForIdle();
verify(mFactory).updateInterface(
- eq(iface), eq(EthernetTracker.createIpConfiguration(staticIpConfig)),
+ eq(TEST_IFACE), eq(EthernetTracker.createIpConfiguration(staticIpConfig)),
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));
+ }
}