[automerger skipped] Merge "Revert "Revert "Change network management listener to outcome re..."" am: 8e8ef76e1e -s ours am: 986c62c881 -s ours am: 5fbe51cdb6 -s ours
am skip reason: Merged-In Id8fadfed9fcfd22f04f6d7c3460b5956e571e01f with SHA-1 edba41c6bd is already in history
Original change: https://android-review.googlesource.com/c/platform/frameworks/opt/net/ethernet/+/2031103
Change-Id: I48cc6ef28a9cbeb8d23d7ba42277735c38ae32f8
diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java
index ef3abba..342d507 100644
--- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java
+++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java
@@ -24,8 +24,8 @@
import android.net.ConnectivityResources;
import android.net.EthernetManager;
import android.net.EthernetNetworkSpecifier;
-import android.net.IEthernetNetworkManagementListener;
import android.net.EthernetNetworkManagementException;
+import android.net.INetworkInterfaceOutcomeReceiver;
import android.net.IpConfiguration;
import android.net.IpConfiguration.IpAssignment;
import android.net.IpConfiguration.ProxySettings;
@@ -183,7 +183,8 @@
* Returns an array of available interface names. The array is sorted: unrestricted interfaces
* goes first, then sorted by name.
*/
- String[] getAvailableInterfaces(boolean includeRestricted) {
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ protected String[] getAvailableInterfaces(boolean includeRestricted) {
return mTrackingInterfaces.values()
.stream()
.filter(iface -> !iface.isRestricted() || includeRestricted)
@@ -195,7 +196,8 @@
.toArray(String[]::new);
}
- void addInterface(@NonNull final String ifaceName, @NonNull final String hwAddress,
+ @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)) {
@@ -239,14 +241,14 @@
* {@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 IEthernetNetworkManagementListener} to notify callers of
+ * @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 IEthernetNetworkManagementListener listener) {
+ @Nullable final INetworkInterfaceOutcomeReceiver listener) {
if (!hasInterface(ifaceName)) {
maybeSendNetworkManagementCallbackForUntracked(ifaceName, listener);
return;
@@ -282,7 +284,8 @@
.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET).build();
}
- void removeInterface(String interfaceName) {
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ protected void removeInterface(String interfaceName) {
NetworkInterfaceState iface = mTrackingInterfaces.remove(interfaceName);
if (iface != null) {
iface.maybeSendNetworkManagementCallbackForAbort();
@@ -295,7 +298,7 @@
/** Returns true if state has been modified */
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
protected boolean updateInterfaceLinkState(@NonNull final String ifaceName, final boolean up,
- @Nullable final IEthernetNetworkManagementListener listener) {
+ @Nullable final INetworkInterfaceOutcomeReceiver listener) {
if (!hasInterface(ifaceName)) {
maybeSendNetworkManagementCallbackForUntracked(ifaceName, listener);
return false;
@@ -310,7 +313,7 @@
}
private void maybeSendNetworkManagementCallbackForUntracked(
- String ifaceName, IEthernetNetworkManagementListener listener) {
+ String ifaceName, INetworkInterfaceOutcomeReceiver listener) {
maybeSendNetworkManagementCallback(listener, null,
new EthernetNetworkManagementException(
ifaceName + " can't be updated as it is not available."));
@@ -353,15 +356,19 @@
}
private static void maybeSendNetworkManagementCallback(
- @Nullable final IEthernetNetworkManagementListener listener,
- @Nullable final Network network,
+ @Nullable final INetworkInterfaceOutcomeReceiver listener,
+ @Nullable final String iface,
@Nullable final EthernetNetworkManagementException e) {
if (null == listener) {
return;
}
try {
- listener.onComplete(network, e);
+ 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);
}
@@ -415,9 +422,9 @@
private class EthernetIpClientCallback extends IpClientCallbacks {
private final ConditionVariable mIpClientStartCv = new ConditionVariable(false);
private final ConditionVariable mIpClientShutdownCv = new ConditionVariable(false);
- @Nullable IEthernetNetworkManagementListener mNetworkManagementListener;
+ @Nullable INetworkInterfaceOutcomeReceiver mNetworkManagementListener;
- EthernetIpClientCallback(@Nullable final IEthernetNetworkManagementListener listener) {
+ EthernetIpClientCallback(@Nullable final INetworkInterfaceOutcomeReceiver listener) {
mNetworkManagementListener = listener;
}
@@ -502,7 +509,7 @@
void updateInterface(@Nullable final IpConfiguration ipConfig,
@Nullable final NetworkCapabilities capabilities,
- @Nullable final IEthernetNetworkManagementListener listener) {
+ @Nullable final INetworkInterfaceOutcomeReceiver listener) {
if (DBG) {
Log.d(TAG, "updateInterface, iface: " + name
+ ", ipConfig: " + ipConfig + ", old ipConfig: " + mIpConfig
@@ -533,7 +540,7 @@
start(null);
}
- private void start(@Nullable final IEthernetNetworkManagementListener listener) {
+ private void start(@Nullable final INetworkInterfaceOutcomeReceiver listener) {
if (mIpClient != null) {
if (DBG) Log.d(TAG, "IpClient already started");
return;
@@ -553,7 +560,7 @@
}
void onIpLayerStarted(@NonNull final LinkProperties linkProperties,
- @Nullable final IEthernetNetworkManagementListener listener) {
+ @Nullable final INetworkInterfaceOutcomeReceiver 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
@@ -593,10 +600,10 @@
});
mNetworkAgent.register();
mNetworkAgent.markConnected();
- realizeNetworkManagementCallback(mNetworkAgent.getNetwork(), null);
+ realizeNetworkManagementCallback(name, null);
}
- void onIpLayerStopped(@Nullable final IEthernetNetworkManagementListener listener) {
+ void onIpLayerStopped(@Nullable final INetworkInterfaceOutcomeReceiver 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) {
@@ -622,7 +629,7 @@
}
// Must be called on the handler thread
- private void realizeNetworkManagementCallback(@Nullable final Network network,
+ private void realizeNetworkManagementCallback(@Nullable final String iface,
@Nullable final EthernetNetworkManagementException e) {
ensureRunningOnEthernetHandlerThread();
if (null == mIpClientCallback) {
@@ -630,7 +637,7 @@
}
EthernetNetworkFactory.maybeSendNetworkManagementCallback(
- mIpClientCallback.mNetworkManagementListener, network, e);
+ mIpClientCallback.mNetworkManagementListener, iface, e);
// Only send a single callback per listener.
mIpClientCallback.mNetworkManagementListener = null;
}
@@ -671,7 +678,7 @@
/** Returns true if state has been modified */
boolean updateLinkState(final boolean up,
- @Nullable final IEthernetNetworkManagementListener listener) {
+ @Nullable final INetworkInterfaceOutcomeReceiver listener) {
if (mLinkUp == up) {
EthernetNetworkFactory.maybeSendNetworkManagementCallback(listener, null,
new EthernetNetworkManagementException(
@@ -681,13 +688,11 @@
mLinkUp = up;
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);
+ EthernetNetworkFactory.maybeSendNetworkManagementCallback(listener, name, null);
} else { // was down, goes up
stop();
start(listener);
@@ -742,7 +747,7 @@
restart(null);
}
- void restart(@Nullable final IEthernetNetworkManagementListener listener){
+ void restart(@Nullable final INetworkInterfaceOutcomeReceiver listener) {
if (DBG) Log.d(TAG, "reconnecting Ethernet");
stop();
start(listener);
diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java
index 50b4684..5e830ad 100644
--- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java
+++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java
@@ -24,7 +24,7 @@
import android.content.pm.PackageManager;
import android.net.IEthernetManager;
import android.net.IEthernetServiceListener;
-import android.net.IEthernetNetworkManagementListener;
+import android.net.INetworkInterfaceOutcomeReceiver;
import android.net.ITetheredInterfaceCallback;
import android.net.EthernetNetworkUpdateRequest;
import android.net.IpConfiguration;
@@ -41,6 +41,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -243,7 +244,7 @@
@Override
public void updateConfiguration(@NonNull final String iface,
@NonNull final EthernetNetworkUpdateRequest request,
- @Nullable final IEthernetNetworkManagementListener listener) {
+ @Nullable final INetworkInterfaceOutcomeReceiver listener) {
Objects.requireNonNull(iface);
Objects.requireNonNull(request);
throwIfEthernetNotStarted();
@@ -260,7 +261,7 @@
@Override
public void connectNetwork(@NonNull final String iface,
- @Nullable final IEthernetNetworkManagementListener listener) {
+ @Nullable final INetworkInterfaceOutcomeReceiver listener) {
Log.i(TAG, "connectNetwork called with: iface=" + iface + ", listener=" + listener);
Objects.requireNonNull(iface);
throwIfEthernetNotStarted();
@@ -272,7 +273,7 @@
@Override
public void disconnectNetwork(@NonNull final String iface,
- @Nullable final IEthernetNetworkManagementListener listener) {
+ @Nullable final INetworkInterfaceOutcomeReceiver listener) {
Log.i(TAG, "disconnectNetwork called with: iface=" + iface + ", listener=" + listener);
Objects.requireNonNull(iface);
throwIfEthernetNotStarted();
@@ -281,4 +282,18 @@
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/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java
index 074c81b..abb1635 100644
--- a/service-t/src/com/android/server/ethernet/EthernetTracker.java
+++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java
@@ -16,6 +16,8 @@
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;
@@ -27,7 +29,7 @@
import android.net.ConnectivityResources;
import android.net.EthernetManager;
import android.net.IEthernetServiceListener;
-import android.net.IEthernetNetworkManagementListener;
+import android.net.INetworkInterfaceOutcomeReceiver;
import android.net.INetd;
import android.net.ITetheredInterfaceCallback;
import android.net.InterfaceConfigurationParcel;
@@ -55,6 +57,7 @@
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;
@@ -88,7 +91,8 @@
* Interface names we track. This is a product-dependent regular expression, plus,
* if setIncludeTestInterfaces is true, any test interfaces.
*/
- private String mIfaceMatch;
+ private volatile String mIfaceMatch;
+
/**
* Track test interfaces if true, don't track otherwise.
*/
@@ -119,6 +123,8 @@
private boolean mTetheredInterfaceWasAvailable = false;
private volatile IpConfiguration mIpConfigForDefaultInterface;
+ private int mEthernetState = ETHERNET_STATE_ENABLED;
+
private class TetheredInterfaceRequestList extends
RemoteCallbackList<ITetheredInterfaceCallback> {
@Override
@@ -291,7 +297,7 @@
protected void updateConfiguration(@NonNull final String iface,
@Nullable final IpConfiguration ipConfig,
@Nullable final NetworkCapabilities capabilities,
- @Nullable final IEthernetNetworkManagementListener listener) {
+ @Nullable final INetworkInterfaceOutcomeReceiver listener) {
if (DBG) {
Log.i(TAG, "updateConfiguration, iface: " + iface + ", capabilities: " + capabilities
+ ", ipConfig: " + ipConfig);
@@ -314,13 +320,13 @@
@VisibleForTesting(visibility = PACKAGE)
protected void connectNetwork(@NonNull final String iface,
- @Nullable final IEthernetNetworkManagementListener listener) {
+ @Nullable final INetworkInterfaceOutcomeReceiver listener) {
mHandler.post(() -> updateInterfaceState(iface, true, listener));
}
@VisibleForTesting(visibility = PACKAGE)
protected void disconnectNetwork(@NonNull final String iface,
- @Nullable final IEthernetNetworkManagementListener listener) {
+ @Nullable final INetworkInterfaceOutcomeReceiver listener) {
mHandler.post(() -> updateInterfaceState(iface, false, listener));
}
@@ -337,6 +343,22 @@
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.
@@ -355,6 +377,8 @@
for (String iface : getInterfaces(canUseRestrictedNetworks)) {
unicastInterfaceStateChange(listener, iface);
}
+
+ unicastEthernetStateChange(listener, mEthernetState);
});
}
@@ -505,7 +529,7 @@
}
private void updateInterfaceState(@NonNull final String iface, final boolean up,
- @Nullable final IEthernetNetworkManagementListener listener) {
+ @Nullable final INetworkInterfaceOutcomeReceiver listener) {
final int mode = getInterfaceMode(iface);
final boolean factoryLinkStateUpdated = (mode == INTERFACE_MODE_CLIENT)
&& mFactory.updateInterfaceLinkState(iface, up, listener);
@@ -825,6 +849,53 @@
}
}
+ @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());
diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java
index e256add..2d5bd1d 100644
--- a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java
+++ b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java
@@ -41,8 +41,8 @@
import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.EthernetNetworkSpecifier;
-import android.net.IEthernetNetworkManagementListener;
import android.net.EthernetNetworkManagementException;
+import android.net.INetworkInterfaceOutcomeReceiver;
import android.net.IpConfiguration;
import android.net.LinkAddress;
import android.net.LinkProperties;
@@ -85,7 +85,7 @@
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 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";
@@ -316,7 +316,7 @@
assertTrue(ret);
verify(mIpClient).shutdown();
- assertSuccessfulListener(listener, null);
+ assertEquals(listener.expectOnResult(), TEST_IFACE);
}
@Test
@@ -330,7 +330,7 @@
assertTrue(ret);
verifyStop();
- assertSuccessfulListener(listener, mMockNetwork);
+ assertEquals(listener.expectOnResult(), TEST_IFACE);
}
@Test
@@ -347,7 +347,7 @@
verify(mDeps, never()).makeIpClient(any(), any(), any());
verify(mDeps, never())
.makeEthernetNetworkAgent(any(), any(), any(), any(), any(), any(), any());
- assertSuccessfulListener(listener, null);
+ assertEquals(listener.expectOnResult(), TEST_IFACE);
}
@Test
@@ -361,7 +361,7 @@
assertFalse(ret);
verifyNoStopOrStart();
- assertFailedListener(listener, "can't be updated as it is not available");
+ listener.expectOnErrorWithMessage("can't be updated as it is not available");
}
@Test
@@ -375,7 +375,7 @@
assertFalse(ret);
verifyNoStopOrStart();
- assertFailedListener(listener, "No changes");
+ listener.expectOnErrorWithMessage("No changes");
}
@Test
@@ -632,18 +632,31 @@
}
private static final class TestNetworkManagementListener
- implements IEthernetNetworkManagementListener {
- private final CompletableFuture<Pair<Network, EthernetNetworkManagementException>> mDone
- = new CompletableFuture<>();
+ implements INetworkInterfaceOutcomeReceiver {
+ private final CompletableFuture<String> mResult = new CompletableFuture<>();
+ private final CompletableFuture<EthernetNetworkManagementException> mError =
+ new CompletableFuture<>();
@Override
- public void onComplete(final Network network,
- final EthernetNetworkManagementException exception) {
- mDone.complete(new Pair<>(network, exception));
+ public void onResult(@NonNull String iface) {
+ mResult.complete(iface);
}
- Pair<Network, EthernetNetworkManagementException> expectOnComplete() throws Exception {
- return mDone.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ @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
@@ -663,7 +676,7 @@
mNetFactory.updateInterface(TEST_IFACE, ipConfiguration, capabilities, listener);
triggerOnProvisioningSuccess();
- assertSuccessfulListener(listener, mMockNetwork);
+ assertEquals(listener.expectOnResult(), TEST_IFACE);
}
@DevSdkIgnoreRule.IgnoreUpTo(SC_V2) // TODO: Use to Build.VERSION_CODES.SC_V2 when available
@@ -703,26 +716,7 @@
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));
+ assertEquals(successfulListener.expectOnResult(), TEST_IFACE);
}
private void verifyNetworkManagementCallIsAbortedWhenInterrupted(
@@ -737,7 +731,7 @@
mNetFactory.updateInterface(iface, ipConfiguration, capabilities, failedListener);
interruptingRunnable.run();
- assertFailedListener(failedListener, "aborted");
+ failedListener.expectOnErrorWithMessage("aborted");
}
@Test
@@ -751,7 +745,7 @@
mNetFactory.updateInterface(TEST_IFACE, ipConfiguration, capabilities, listener);
triggerOnProvisioningSuccess();
- listener.expectOnComplete();
+ assertEquals(listener.expectOnResult(), TEST_IFACE);
verify(mDeps).makeEthernetNetworkAgent(any(), any(),
eq(capabilities), any(), any(), any(), any());
verifyRestart(ipConfiguration);
@@ -768,7 +762,7 @@
mNetFactory.updateInterface(TEST_IFACE, ipConfiguration, capabilities, listener);
verifyNoStopOrStart();
- assertFailedListener(listener, "can't be updated as it is not available");
+ listener.expectOnErrorWithMessage("can't be updated as it is not available");
}
@Test
diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java
index 2131f7f..dd1f1ed 100644
--- a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java
+++ b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java
@@ -19,12 +19,15 @@
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;
@@ -32,7 +35,7 @@
import android.annotation.NonNull;
import android.content.Context;
import android.content.pm.PackageManager;
-import android.net.IEthernetNetworkManagementListener;
+import android.net.INetworkInterfaceOutcomeReceiver;
import android.net.EthernetNetworkUpdateRequest;
import android.net.IpConfiguration;
import android.net.NetworkCapabilities;
@@ -64,7 +67,7 @@
new EthernetNetworkUpdateRequest.Builder()
.setNetworkCapabilities(new NetworkCapabilities.Builder().build())
.build();
- private static final IEthernetNetworkManagementListener NULL_LISTENER = null;
+ private static final INetworkInterfaceOutcomeReceiver NULL_LISTENER = null;
private EthernetServiceImpl mEthernetServiceImpl;
@Mock private Context mContext;
@Mock private Handler mHandler;
@@ -339,4 +342,31 @@
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/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java
index ef70d94..b1831c4 100644
--- a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java
+++ b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java
@@ -25,19 +25,26 @@
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.IEthernetNetworkManagementListener;
+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;
@@ -66,7 +73,7 @@
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 static final INetworkInterfaceOutcomeReceiver NULL_LISTENER = null;
private EthernetTracker tracker;
private HandlerThread mHandlerThread;
@Mock private Context mContext;
@@ -334,7 +341,7 @@
new StaticIpConfiguration.Builder().setIpAddress(linkAddr).build();
final IpConfiguration ipConfig =
new IpConfiguration.Builder().setStaticIpConfiguration(staticIpConfig).build();
- final IEthernetNetworkManagementListener listener = null;
+ final INetworkInterfaceOutcomeReceiver listener = null;
tracker.updateConfiguration(TEST_IFACE, ipConfig, capabilities, listener);
waitForIdle();
@@ -393,4 +400,57 @@
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());
+ }
}