Implement the new added EthernetManager APIs.
EthernetManager is moving to the connectivity mainline module and some of its hidden methods are being exposed as module-lib APIs. This CL updates the implementation. 1. Rename onAvailabilityChanged to onInterfaceStateChanged in IEthernetServiceListener.aidl, to match the name of the public callback method. 2. Add the interface state, role and IpConfiguration to the callback, so that clients can use this information without having to call synchronous methods. 3. Call the new callback whenever any of the above parameters changes, or when a callback is registered. Also make some package-private methods in EthernetNetworkFactory protected @VisibleForTesting because otherwise mockito can't mock them. Bug: 210586283 Test: m Test: atest EthernetServiceTests EthernetTetheringTest Change-Id: Ib27bf119b0d61b78f19b6447a38b4468d8035c78 Merged-In: Ib27bf119b0d61b78f19b6447a38b4468d8035c78
This commit is contained in:
@@ -20,6 +20,7 @@ import android.annotation.NonNull;
|
|||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
|
import android.net.EthernetManager;
|
||||||
import android.net.EthernetNetworkSpecifier;
|
import android.net.EthernetNetworkSpecifier;
|
||||||
import android.net.IEthernetNetworkManagementListener;
|
import android.net.IEthernetNetworkManagementListener;
|
||||||
import android.net.EthernetNetworkManagementException;
|
import android.net.EthernetNetworkManagementException;
|
||||||
@@ -186,6 +187,18 @@ public class EthernetNetworkFactory extends NetworkFactory {
|
|||||||
updateCapabilityFilter();
|
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.
|
* Update a network's configuration and restart it if necessary.
|
||||||
*
|
*
|
||||||
@@ -270,7 +283,8 @@ public class EthernetNetworkFactory extends NetworkFactory {
|
|||||||
return iface.updateLinkState(up, listener);
|
return iface.updateLinkState(up, listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean hasInterface(String ifaceName) {
|
@VisibleForTesting
|
||||||
|
protected boolean hasInterface(String ifaceName) {
|
||||||
return mTrackingInterfaces.containsKey(ifaceName);
|
return mTrackingInterfaces.containsKey(ifaceName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -143,10 +143,8 @@ public class EthernetServiceImpl extends IEthernetManager.Stub {
|
|||||||
* Adds a listener.
|
* Adds a listener.
|
||||||
* @param listener A {@link IEthernetServiceListener} to add.
|
* @param listener A {@link IEthernetServiceListener} to add.
|
||||||
*/
|
*/
|
||||||
public void addListener(IEthernetServiceListener listener) {
|
public void addListener(IEthernetServiceListener listener) throws RemoteException {
|
||||||
if (listener == null) {
|
Objects.requireNonNull(listener, "listener must not be null");
|
||||||
throw new IllegalArgumentException("listener must not be null");
|
|
||||||
}
|
|
||||||
PermissionUtils.enforceAccessNetworkStatePermission(mContext, TAG);
|
PermissionUtils.enforceAccessNetworkStatePermission(mContext, TAG);
|
||||||
mTracker.addListener(listener, checkUseRestrictedNetworksPermission());
|
mTracker.addListener(listener, checkUseRestrictedNetworksPermission());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import static com.android.internal.annotations.VisibleForTesting.Visibility.PACK
|
|||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.net.EthernetManager;
|
||||||
import android.net.IEthernetServiceListener;
|
import android.net.IEthernetServiceListener;
|
||||||
import android.net.IEthernetNetworkManagementListener;
|
import android.net.IEthernetNetworkManagementListener;
|
||||||
import android.net.INetd;
|
import android.net.INetd;
|
||||||
@@ -165,7 +166,10 @@ public class EthernetTracker {
|
|||||||
Log.i(TAG, "updateIpConfiguration, iface: " + iface + ", cfg: " + ipConfiguration);
|
Log.i(TAG, "updateIpConfiguration, iface: " + iface + ", cfg: " + ipConfiguration);
|
||||||
}
|
}
|
||||||
writeIpConfiguration(iface, ipConfiguration);
|
writeIpConfiguration(iface, ipConfiguration);
|
||||||
mHandler.post(() -> mFactory.updateInterface(iface, ipConfiguration, null, null));
|
mHandler.post(() -> {
|
||||||
|
mFactory.updateInterface(iface, ipConfiguration, null, null);
|
||||||
|
broadcastInterfaceStateChange(iface);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeIpConfiguration(@NonNull final String iface,
|
private void writeIpConfiguration(@NonNull final String iface,
|
||||||
@@ -174,6 +178,55 @@ public class EthernetTracker {
|
|||||||
mIpConfigurations.put(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)
|
@VisibleForTesting(visibility = PACKAGE)
|
||||||
protected void updateConfiguration(@NonNull final String iface,
|
protected void updateConfiguration(@NonNull final String iface,
|
||||||
@NonNull final StaticIpConfiguration staticIpConfig,
|
@NonNull final StaticIpConfiguration staticIpConfig,
|
||||||
@@ -186,8 +239,10 @@ public class EthernetTracker {
|
|||||||
final IpConfiguration ipConfig = createIpConfiguration(staticIpConfig);
|
final IpConfiguration ipConfig = createIpConfiguration(staticIpConfig);
|
||||||
writeIpConfiguration(iface, ipConfig);
|
writeIpConfiguration(iface, ipConfig);
|
||||||
mNetworkCapabilities.put(iface, capabilities);
|
mNetworkCapabilities.put(iface, capabilities);
|
||||||
mHandler.post(() ->
|
mHandler.post(() -> {
|
||||||
mFactory.updateInterface(iface, ipConfig, capabilities, listener));
|
mFactory.updateInterface(iface, ipConfig, capabilities, listener);
|
||||||
|
broadcastInterfaceStateChange(iface);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting(visibility = PACKAGE)
|
@VisibleForTesting(visibility = PACKAGE)
|
||||||
@@ -225,11 +280,19 @@ public class EthernetTracker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void addListener(IEthernetServiceListener listener, boolean canUseRestrictedNetworks) {
|
void addListener(IEthernetServiceListener listener, boolean canUseRestrictedNetworks) {
|
||||||
mListeners.register(listener, new ListenerInfo(canUseRestrictedNetworks));
|
mHandler.post(() -> {
|
||||||
|
if (!mListeners.register(listener, new ListenerInfo(canUseRestrictedNetworks))) {
|
||||||
|
// Remote process has already died
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (String iface : getInterfaces(canUseRestrictedNetworks)) {
|
||||||
|
unicastInterfaceStateChange(listener, iface);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeListener(IEthernetServiceListener listener) {
|
void removeListener(IEthernetServiceListener listener) {
|
||||||
mListeners.unregister(listener);
|
mHandler.post(() -> mListeners.unregister(listener));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIncludeTestInterfaces(boolean include) {
|
public void setIncludeTestInterfaces(boolean include) {
|
||||||
@@ -295,6 +358,14 @@ public class EthernetTracker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
private int getInterfaceMode(final String iface) {
|
||||||
if (iface.equals(mDefaultInterface)) {
|
if (iface.equals(mDefaultInterface)) {
|
||||||
return mDefaultInterfaceMode;
|
return mDefaultInterfaceMode;
|
||||||
@@ -312,6 +383,7 @@ public class EthernetTracker {
|
|||||||
if (iface.equals(mDefaultInterface)) {
|
if (iface.equals(mDefaultInterface)) {
|
||||||
mDefaultInterface = null;
|
mDefaultInterface = null;
|
||||||
}
|
}
|
||||||
|
broadcastInterfaceStateChange(iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addInterface(String iface) {
|
private void addInterface(String iface) {
|
||||||
@@ -346,11 +418,7 @@ public class EthernetTracker {
|
|||||||
|
|
||||||
final int mode = getInterfaceMode(iface);
|
final int mode = getInterfaceMode(iface);
|
||||||
if (mode == INTERFACE_MODE_CLIENT) {
|
if (mode == INTERFACE_MODE_CLIENT) {
|
||||||
IpConfiguration ipConfiguration = mIpConfigurations.get(iface);
|
IpConfiguration ipConfiguration = getOrCreateIpConfiguration(iface);
|
||||||
if (ipConfiguration == null) {
|
|
||||||
ipConfiguration = createDefaultIpConfiguration();
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.d(TAG, "Tracking interface in client mode: " + iface);
|
Log.d(TAG, "Tracking interface in client mode: " + iface);
|
||||||
mFactory.addInterface(iface, hwAddress, ipConfiguration, nc);
|
mFactory.addInterface(iface, hwAddress, ipConfiguration, nc);
|
||||||
} else {
|
} else {
|
||||||
@@ -376,22 +444,7 @@ public class EthernetTracker {
|
|||||||
&& mFactory.updateInterfaceLinkState(iface, up, listener);
|
&& mFactory.updateInterfaceLinkState(iface, up, listener);
|
||||||
|
|
||||||
if (factoryLinkStateUpdated) {
|
if (factoryLinkStateUpdated) {
|
||||||
boolean restricted = isRestrictedInterface(iface);
|
broadcastInterfaceStateChange(iface);
|
||||||
int n = mListeners.beginBroadcast();
|
|
||||||
for (int i = 0; i < n; i++) {
|
|
||||||
try {
|
|
||||||
if (restricted) {
|
|
||||||
ListenerInfo listenerInfo = (ListenerInfo) mListeners.getBroadcastCookie(i);
|
|
||||||
if (!listenerInfo.canUseRestrictedNetworks) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mListeners.getBroadcastItem(i).onAvailabilityChanged(iface, up);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
// Do nothing here.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mListeners.finishBroadcast();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -438,6 +491,8 @@ public class EthernetTracker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addInterface(iface);
|
addInterface(iface);
|
||||||
|
|
||||||
|
broadcastInterfaceStateChange(iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void trackAvailableInterfaces() {
|
private void trackAvailableInterfaces() {
|
||||||
@@ -463,11 +518,17 @@ public class EthernetTracker {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInterfaceAdded(String iface) {
|
public void onInterfaceAdded(String iface) {
|
||||||
|
if (DBG) {
|
||||||
|
Log.i(TAG, "onInterfaceAdded, iface: " + iface);
|
||||||
|
}
|
||||||
mHandler.post(() -> maybeTrackInterface(iface));
|
mHandler.post(() -> maybeTrackInterface(iface));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInterfaceRemoved(String iface) {
|
public void onInterfaceRemoved(String iface) {
|
||||||
|
if (DBG) {
|
||||||
|
Log.i(TAG, "onInterfaceRemoved, iface: " + iface);
|
||||||
|
}
|
||||||
mHandler.post(() -> stopTrackingInterface(iface));
|
mHandler.post(() -> stopTrackingInterface(iface));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -663,8 +724,10 @@ public class EthernetTracker {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IpConfiguration createDefaultIpConfiguration() {
|
private IpConfiguration getOrCreateIpConfiguration(String iface) {
|
||||||
final IpConfiguration ret = new IpConfiguration();
|
IpConfiguration ret = mIpConfigurations.get(iface);
|
||||||
|
if (ret != null) return ret;
|
||||||
|
ret = new IpConfiguration();
|
||||||
ret.setIpAssignment(IpAssignment.DHCP);
|
ret.setIpAssignment(IpAssignment.DHCP);
|
||||||
ret.setProxySettings(ProxySettings.NONE);
|
ret.setProxySettings(ProxySettings.NONE);
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
Reference in New Issue
Block a user