diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-05-10 07:12:29 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-05-10 07:12:29 +0000 |
commit | 4a6f21b73798c78485ae11183418f9d16aa8260c (patch) | |
tree | 13f4a3881fc99fd0050781e1dc3962d5da6789a1 | |
parent | f2f8b6e4aa71af126110959286b9c38ed43b095b (diff) | |
parent | fc8ce7ca9464228ef08bb79d05b3e4d4fc058d4b (diff) | |
download | ethernet-android13-mainline-conscrypt-release.tar.gz |
Snap for 8564071 from fc8ce7ca9464228ef08bb79d05b3e4d4fc058d4b to mainline-conscrypt-releaseaml_con_331413000aml_con_331411000aml_con_331312000aml_con_331115000aml_con_331011010android13-mainline-conscrypt-release
Change-Id: I1dc0ce38b4d458551549b2e9f70c1cf94632f1fa
-rw-r--r-- | Android.bp | 36 | ||||
-rw-r--r-- | java/com/android/server/ethernet/EthernetConfigStore.java | 88 | ||||
-rw-r--r-- | java/com/android/server/ethernet/EthernetNetworkFactory.java | 634 | ||||
-rw-r--r-- | java/com/android/server/ethernet/EthernetService.java | 45 | ||||
-rw-r--r-- | java/com/android/server/ethernet/EthernetServiceImpl.java | 210 | ||||
-rw-r--r-- | java/com/android/server/ethernet/EthernetTracker.java | 675 | ||||
-rw-r--r-- | tests/Android.bp | 37 | ||||
-rw-r--r-- | tests/AndroidManifest.xml | 28 | ||||
-rw-r--r-- | tests/java/com/android/server/ethernet/EthernetTrackerTest.java | 245 |
9 files changed, 0 insertions, 1998 deletions
diff --git a/Android.bp b/Android.bp deleted file mode 100644 index c3393bc..0000000 --- a/Android.bp +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (C) 2014 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Build the java code -// ============================================================ - -package { - default_applicable_licenses: ["Android-Apache-2.0"], -} - -java_library { - name: "ethernet-service", - installable: true, - - aidl: { - local_include_dirs: ["java"], - }, - srcs: [ - "java/**/*.java", - "java/**/I*.aidl", - "java/**/*.logtags", - ], - - libs: ["services"], -} diff --git a/java/com/android/server/ethernet/EthernetConfigStore.java b/java/com/android/server/ethernet/EthernetConfigStore.java deleted file mode 100644 index 6b623f4..0000000 --- a/java/com/android/server/ethernet/EthernetConfigStore.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.ethernet; - -import android.annotation.Nullable; -import android.net.IpConfiguration; -import android.os.Environment; -import android.util.ArrayMap; - -import com.android.server.net.IpConfigStore; - - -/** - * This class provides an API to store and manage Ethernet network configuration. - */ -public class EthernetConfigStore { - private static final String ipConfigFile = Environment.getDataDirectory() + - "/misc/ethernet/ipconfig.txt"; - - private IpConfigStore mStore = new IpConfigStore(); - private ArrayMap<String, IpConfiguration> mIpConfigurations; - private IpConfiguration mIpConfigurationForDefaultInterface; - private final Object mSync = new Object(); - - public EthernetConfigStore() { - mIpConfigurations = new ArrayMap<>(0); - } - - public void read() { - synchronized (mSync) { - ArrayMap<String, IpConfiguration> configs = - IpConfigStore.readIpConfigurations(ipConfigFile); - - // This configuration may exist in old file versions when there was only a single active - // Ethernet interface. - if (configs.containsKey("0")) { - mIpConfigurationForDefaultInterface = configs.remove("0"); - } - - mIpConfigurations = configs; - } - } - - public void write(String iface, IpConfiguration config) { - boolean modified; - - synchronized (mSync) { - if (config == null) { - modified = mIpConfigurations.remove(iface) != null; - } else { - IpConfiguration oldConfig = mIpConfigurations.put(iface, config); - modified = !config.equals(oldConfig); - } - - if (modified) { - mStore.writeIpConfigurations(ipConfigFile, mIpConfigurations); - } - } - } - - public ArrayMap<String, IpConfiguration> getIpConfigurations() { - synchronized (mSync) { - return new ArrayMap<>(mIpConfigurations); - } - } - - @Nullable - public IpConfiguration getIpConfigurationForDefaultInterface() { - synchronized (mSync) { - return mIpConfigurationForDefaultInterface == null - ? null : new IpConfiguration(mIpConfigurationForDefaultInterface); - } - } -} diff --git a/java/com/android/server/ethernet/EthernetNetworkFactory.java b/java/com/android/server/ethernet/EthernetNetworkFactory.java deleted file mode 100644 index 28b24f1..0000000 --- a/java/com/android/server/ethernet/EthernetNetworkFactory.java +++ /dev/null @@ -1,634 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.ethernet; - -import static com.android.internal.util.Preconditions.checkNotNull; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.Context; -import android.net.ConnectivityManager; -import android.net.EthernetNetworkSpecifier; -import android.net.IpConfiguration; -import android.net.IpConfiguration.IpAssignment; -import android.net.IpConfiguration.ProxySettings; -import android.net.LinkProperties; -import android.net.NetworkAgent; -import android.net.NetworkAgentConfig; -import android.net.NetworkCapabilities; -import android.net.NetworkFactory; -import android.net.NetworkRequest; -import android.net.NetworkSpecifier; -import android.net.ip.IIpClient; -import android.net.ip.IpClientCallbacks; -import android.net.ip.IpClientUtil; -import android.net.shared.ProvisioningConfiguration; -import android.net.util.InterfaceParams; -import android.os.ConditionVariable; -import android.os.Handler; -import android.os.RemoteException; -import android.text.TextUtils; -import android.util.AndroidRuntimeException; -import android.util.Log; -import android.util.SparseArray; - -import com.android.internal.util.IndentingPrintWriter; - -import java.io.FileDescriptor; -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; - -/** - * {@link NetworkFactory} that represents Ethernet networks. - * - * This class reports a static network score of 70 when it is tracking an interface and that - * interface's link is up, and a score of 0 otherwise. - */ -public class EthernetNetworkFactory extends NetworkFactory { - private final static String TAG = EthernetNetworkFactory.class.getSimpleName(); - final static boolean DBG = true; - - private final static int NETWORK_SCORE = 70; - private static final String NETWORK_TYPE = "Ethernet"; - - private final ConcurrentHashMap<String, NetworkInterfaceState> mTrackingInterfaces = - new ConcurrentHashMap<>(); - private final Handler mHandler; - private final Context mContext; - - public static class ConfigurationException extends AndroidRuntimeException { - public ConfigurationException(String msg) { - super(msg); - } - } - - public EthernetNetworkFactory(Handler handler, Context context, NetworkCapabilities filter) { - super(handler.getLooper(), context, NETWORK_TYPE, filter); - - mHandler = handler; - mContext = context; - - setScoreFilter(NETWORK_SCORE); - } - - @Override - public boolean acceptRequest(NetworkRequest request) { - if (DBG) { - Log.d(TAG, "acceptRequest, request: " + request); - } - - return networkForRequest(request) != null; - } - - @Override - protected void needNetworkFor(NetworkRequest networkRequest) { - NetworkInterfaceState network = networkForRequest(networkRequest); - - if (network == null) { - Log.e(TAG, "needNetworkFor, failed to get a network for " + networkRequest); - return; - } - - if (++network.refCount == 1) { - network.start(); - } - } - - @Override - protected void releaseNetworkFor(NetworkRequest networkRequest) { - NetworkInterfaceState network = networkForRequest(networkRequest); - if (network == null) { - Log.e(TAG, "releaseNetworkFor, failed to get a network for " + networkRequest); - return; - } - - if (--network.refCount == 0) { - network.stop(); - } - } - - /** - * Returns an array of available interface names. The array is sorted: unrestricted interfaces - * goes first, then sorted by name. - */ - String[] getAvailableInterfaces(boolean includeRestricted) { - return mTrackingInterfaces.values() - .stream() - .filter(iface -> !iface.isRestricted() || includeRestricted) - .sorted((iface1, iface2) -> { - int r = Boolean.compare(iface1.isRestricted(), iface2.isRestricted()); - return r == 0 ? iface1.name.compareTo(iface2.name) : r; - }) - .map(iface -> iface.name) - .toArray(String[]::new); - } - - void addInterface(String ifaceName, String hwAddress, NetworkCapabilities capabilities, - IpConfiguration ipConfiguration) { - if (mTrackingInterfaces.containsKey(ifaceName)) { - Log.e(TAG, "Interface with name " + ifaceName + " already exists."); - return; - } - - if (DBG) { - Log.d(TAG, "addInterface, iface: " + ifaceName + ", capabilities: " + capabilities); - } - - NetworkInterfaceState iface = new NetworkInterfaceState( - ifaceName, hwAddress, mHandler, mContext, capabilities, this); - iface.setIpConfig(ipConfiguration); - mTrackingInterfaces.put(ifaceName, iface); - - updateCapabilityFilter(); - } - - private static NetworkCapabilities mixInCapabilities(NetworkCapabilities nc, - NetworkCapabilities addedNc) { - final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder(nc); - for (int transport : addedNc.getTransportTypes()) builder.addTransportType(transport); - for (int capability : addedNc.getCapabilities()) builder.addCapability(capability); - return builder.build(); - } - - private void updateCapabilityFilter() { - NetworkCapabilities capabilitiesFilter = - NetworkCapabilities.Builder.withoutDefaultCapabilities() - .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) - .build(); - - for (NetworkInterfaceState iface: mTrackingInterfaces.values()) { - capabilitiesFilter = mixInCapabilities(capabilitiesFilter, iface.mCapabilities); - } - - if (DBG) Log.d(TAG, "updateCapabilityFilter: " + capabilitiesFilter); - setCapabilityFilter(capabilitiesFilter); - } - - void removeInterface(String interfaceName) { - NetworkInterfaceState iface = mTrackingInterfaces.remove(interfaceName); - if (iface != null) { - iface.stop(); - } - - updateCapabilityFilter(); - } - - /** Returns true if state has been modified */ - boolean updateInterfaceLinkState(String ifaceName, boolean up) { - if (!mTrackingInterfaces.containsKey(ifaceName)) { - return false; - } - - if (DBG) { - Log.d(TAG, "updateInterfaceLinkState, iface: " + ifaceName + ", up: " + up); - } - - NetworkInterfaceState iface = mTrackingInterfaces.get(ifaceName); - return iface.updateLinkState(up); - } - - boolean hasInterface(String interfacName) { - return mTrackingInterfaces.containsKey(interfacName); - } - - void updateIpConfiguration(String iface, IpConfiguration ipConfiguration) { - NetworkInterfaceState network = mTrackingInterfaces.get(iface); - if (network != null) { - network.setIpConfig(ipConfiguration); - } - } - - private NetworkInterfaceState networkForRequest(NetworkRequest request) { - String requestedIface = null; - - NetworkSpecifier specifier = request.getNetworkSpecifier(); - if (specifier instanceof EthernetNetworkSpecifier) { - requestedIface = ((EthernetNetworkSpecifier) specifier) - .getInterfaceName(); - } - - NetworkInterfaceState network = null; - if (!TextUtils.isEmpty(requestedIface)) { - NetworkInterfaceState n = mTrackingInterfaces.get(requestedIface); - if (n != null && request.canBeSatisfiedBy(n.mCapabilities)) { - network = n; - } - } else { - for (NetworkInterfaceState n : mTrackingInterfaces.values()) { - if (request.canBeSatisfiedBy(n.mCapabilities) && n.mLinkUp) { - network = n; - break; - } - } - } - - if (DBG) { - Log.i(TAG, "networkForRequest, request: " + request + ", network: " + network); - } - - return network; - } - - private static class NetworkInterfaceState { - final String name; - - private final String mHwAddress; - private final NetworkCapabilities mCapabilities; - private final Handler mHandler; - private final Context mContext; - private final NetworkFactory mNetworkFactory; - private final int mLegacyType; - - private static String sTcpBufferSizes = null; // Lazy initialized. - - private boolean mLinkUp; - private LinkProperties mLinkProperties = new LinkProperties(); - - private volatile @Nullable IIpClient mIpClient; - private @Nullable IpClientCallbacksImpl mIpClientCallback; - private @Nullable NetworkAgent mNetworkAgent; - private @Nullable IpConfiguration mIpConfig; - - /** - * An object to contain all transport type information, including base network score and - * the legacy transport type it maps to (if any) - */ - private static class TransportInfo { - final int mLegacyType; - final int mScore; - - private TransportInfo(int legacyType, int score) { - mLegacyType = legacyType; - mScore = score; - } - } - - /** - * A map of TRANSPORT_* types to TransportInfo, making scoring and legacy type information - * available for each type an ethernet interface could propagate. - * - * Unfortunately, base scores for the various transports are not yet centrally located. - * They've been lifted from the corresponding NetworkFactory files in the meantime. - * - * Additionally, there are no legacy type equivalents to LOWPAN or WIFI_AWARE. These types - * are set to TYPE_NONE to match the behavior of their own network factories. - */ - private static final SparseArray<TransportInfo> sTransports = new SparseArray(); - static { - // LowpanInterfaceTracker.NETWORK_SCORE - sTransports.put(NetworkCapabilities.TRANSPORT_LOWPAN, - new TransportInfo(ConnectivityManager.TYPE_NONE, 30)); - // WifiAwareDataPathStateManager.NETWORK_FACTORY_SCORE_AVAIL - sTransports.put(NetworkCapabilities.TRANSPORT_WIFI_AWARE, - new TransportInfo(ConnectivityManager.TYPE_NONE, 1)); - // EthernetNetworkFactory.NETWORK_SCORE - sTransports.put(NetworkCapabilities.TRANSPORT_ETHERNET, - new TransportInfo(ConnectivityManager.TYPE_ETHERNET, 70)); - // BluetoothTetheringNetworkFactory.NETWORK_SCORE - sTransports.put(NetworkCapabilities.TRANSPORT_BLUETOOTH, - new TransportInfo(ConnectivityManager.TYPE_BLUETOOTH, 69)); - // WifiNetworkFactory.SCORE_FILTER / NetworkAgent.WIFI_BASE_SCORE - sTransports.put(NetworkCapabilities.TRANSPORT_WIFI, - new TransportInfo(ConnectivityManager.TYPE_WIFI, 60)); - // TelephonyNetworkFactory.TELEPHONY_NETWORK_SCORE - sTransports.put(NetworkCapabilities.TRANSPORT_CELLULAR, - new TransportInfo(ConnectivityManager.TYPE_MOBILE, 50)); - } - - long refCount = 0; - - private class IpClientCallbacksImpl extends IpClientCallbacks { - private final ConditionVariable mIpClientStartCv = new ConditionVariable(false); - private final ConditionVariable mIpClientShutdownCv = new ConditionVariable(false); - - @Override - public void onIpClientCreated(IIpClient ipClient) { - mIpClient = ipClient; - mIpClientStartCv.open(); - } - - private void awaitIpClientStart() { - mIpClientStartCv.block(); - } - - private void awaitIpClientShutdown() { - mIpClientShutdownCv.block(); - } - - @Override - public void onProvisioningSuccess(LinkProperties newLp) { - mHandler.post(() -> onIpLayerStarted(newLp)); - } - - @Override - public void onProvisioningFailure(LinkProperties newLp) { - mHandler.post(() -> onIpLayerStopped(newLp)); - } - - @Override - public void onLinkPropertiesChange(LinkProperties newLp) { - mHandler.post(() -> updateLinkProperties(newLp)); - } - - @Override - public void onQuit() { - mIpClient = null; - mIpClientShutdownCv.open(); - } - } - - private static void shutdownIpClient(IIpClient ipClient) { - try { - ipClient.shutdown(); - } catch (RemoteException e) { - Log.e(TAG, "Error stopping IpClient", e); - } - } - - NetworkInterfaceState(String ifaceName, String hwAddress, Handler handler, Context context, - @NonNull NetworkCapabilities capabilities, NetworkFactory networkFactory) { - name = ifaceName; - mCapabilities = checkNotNull(capabilities); - mHandler = handler; - mContext = context; - mNetworkFactory = networkFactory; - int legacyType = ConnectivityManager.TYPE_NONE; - int[] transportTypes = mCapabilities.getTransportTypes(); - - if (transportTypes.length > 0) { - legacyType = getLegacyType(transportTypes[0]); - } else { - // Should never happen as transport is always one of ETHERNET or a valid override - throw new ConfigurationException("Network Capabilities do not have an associated " - + "transport type."); - } - - mHwAddress = hwAddress; - mLegacyType = legacyType; - } - - void setIpConfig(IpConfiguration ipConfig) { - if (Objects.equals(this.mIpConfig, ipConfig)) { - if (DBG) Log.d(TAG, "ipConfig have not changed,so ignore setIpConfig"); - return; - } - this.mIpConfig = ipConfig; - if (mNetworkAgent != null) { - restart(); - } - } - - boolean satisfied(NetworkCapabilities requestedCapabilities) { - return requestedCapabilities.satisfiedByNetworkCapabilities(mCapabilities); - } - - boolean isRestricted() { - return !mCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); - } - - /** - * Determines the legacy transport type from a NetworkCapabilities transport type. Defaults - * to legacy TYPE_NONE if there is no known conversion - */ - private static int getLegacyType(int transport) { - TransportInfo transportInfo = sTransports.get(transport, /* if dne */ null); - if (transportInfo != null) { - return transportInfo.mLegacyType; - } - return ConnectivityManager.TYPE_NONE; - } - - /** - * Determines the network score based on the transport associated with the interface. - * Ethernet interfaces could propagate a transport types forward. Since we can't - * get more information about the statuses of the interfaces on the other end of the local - * interface, we'll best-effort assign the score as the base score of the assigned transport - * when the link is up. When the link is down, the score is set to zero. - * - * This function is called with the purpose of assigning and updating the network score of - * the member NetworkAgent. - */ - private int getNetworkScore() { - // never set the network score below 0. - if (!mLinkUp) { - return 0; - } - - int[] transportTypes = mCapabilities.getTransportTypes(); - if (transportTypes.length < 1) { - Log.w(TAG, "Network interface '" + mLinkProperties.getInterfaceName() + "' has no " - + "transport type associated with it. Score set to zero"); - return 0; - } - TransportInfo transportInfo = sTransports.get(transportTypes[0], /* if dne */ null); - if (transportInfo != null) { - return transportInfo.mScore; - } - return 0; - } - - private void start() { - if (mIpClient != null) { - if (DBG) Log.d(TAG, "IpClient already started"); - return; - } - if (DBG) { - Log.d(TAG, String.format("Starting Ethernet IpClient(%s)", name)); - } - - mIpClientCallback = new IpClientCallbacksImpl(); - IpClientUtil.makeIpClient(mContext, name, mIpClientCallback); - mIpClientCallback.awaitIpClientStart(); - if (sTcpBufferSizes == null) { - sTcpBufferSizes = mContext.getResources().getString( - com.android.internal.R.string.config_ethernet_tcp_buffers); - } - provisionIpClient(mIpClient, mIpConfig, sTcpBufferSizes); - } - - void onIpLayerStarted(LinkProperties linkProperties) { - if (mNetworkAgent != null) { - Log.e(TAG, "Already have a NetworkAgent - aborting new request"); - stop(); - return; - } - mLinkProperties = linkProperties; - - // Create our NetworkAgent. - final NetworkAgentConfig config = new NetworkAgentConfig.Builder() - .setLegacyType(mLegacyType) - .setLegacyTypeName(NETWORK_TYPE) - .setLegacyExtraInfo(mHwAddress) - .build(); - mNetworkAgent = new NetworkAgent(mContext, mHandler.getLooper(), - NETWORK_TYPE, mCapabilities, mLinkProperties, - getNetworkScore(), config, mNetworkFactory.getProvider()) { - public void unwanted() { - if (this == mNetworkAgent) { - stop(); - } else if (mNetworkAgent != null) { - Log.d(TAG, "Ignoring unwanted as we have a more modern " + - "instance"); - } // Otherwise, we've already called stop. - } - }; - mNetworkAgent.register(); - mNetworkAgent.markConnected(); - } - - 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 != InterfaceParams.getByName(name)) { - start(); - } - } - - void updateLinkProperties(LinkProperties linkProperties) { - mLinkProperties = linkProperties; - if (mNetworkAgent != null) { - mNetworkAgent.sendLinkProperties(linkProperties); - } - } - - /** Returns true if state has been modified */ - boolean updateLinkState(boolean up) { - if (mLinkUp == up) return false; - mLinkUp = up; - - stop(); - if (up) { - start(); - } - - return true; - } - - void stop() { - // Invalidate all previous start requests - if (mIpClient != null) { - shutdownIpClient(mIpClient); - mIpClientCallback.awaitIpClientShutdown(); - mIpClient = null; - } - mIpClientCallback = null; - - if (mNetworkAgent != null) { - mNetworkAgent.unregister(); - mNetworkAgent = null; - } - mLinkProperties.clear(); - } - - private void updateAgent() { - if (mNetworkAgent == null) return; - if (DBG) { - Log.i(TAG, "Updating mNetworkAgent with: " + - mCapabilities + ", " + - mLinkProperties); - } - mNetworkAgent.sendNetworkCapabilities(mCapabilities); - mNetworkAgent.sendLinkProperties(mLinkProperties); - - // As a note, getNetworkScore() is fairly expensive to calculate. This is fine for now - // since the agent isn't updated frequently. Consider caching the score in the future if - // agent updating is required more often - mNetworkAgent.sendNetworkScore(getNetworkScore()); - } - - private static void provisionIpClient(IIpClient ipClient, IpConfiguration config, - String tcpBufferSizes) { - if (config.getProxySettings() == ProxySettings.STATIC || - config.getProxySettings() == ProxySettings.PAC) { - try { - ipClient.setHttpProxy(config.getHttpProxy()); - } catch (RemoteException e) { - e.rethrowFromSystemServer(); - } - } - - if (!TextUtils.isEmpty(tcpBufferSizes)) { - try { - ipClient.setTcpBufferSizes(tcpBufferSizes); - } catch (RemoteException e) { - e.rethrowFromSystemServer(); - } - } - - final ProvisioningConfiguration provisioningConfiguration; - if (config.getIpAssignment() == IpAssignment.STATIC) { - provisioningConfiguration = new ProvisioningConfiguration.Builder() - .withStaticConfiguration(config.getStaticIpConfiguration()) - .build(); - } else { - provisioningConfiguration = new ProvisioningConfiguration.Builder() - .withProvisioningTimeoutMs(0) - .build(); - } - - try { - ipClient.startProvisioning(provisioningConfiguration.toStableParcelable()); - } catch (RemoteException e) { - e.rethrowFromSystemServer(); - } - } - - void restart(){ - if (DBG) Log.d(TAG, "reconnecting Etherent"); - stop(); - start(); - } - - @Override - public String toString() { - return getClass().getSimpleName() + "{ " - + "refCount: " + refCount + ", " - + "iface: " + name + ", " - + "up: " + mLinkUp + ", " - + "hwAddress: " + mHwAddress + ", " - + "networkCapabilities: " + mCapabilities + ", " - + "networkAgent: " + mNetworkAgent + ", " - + "score: " + getNetworkScore() + ", " - + "ipClient: " + mIpClient + "," - + "linkProperties: " + mLinkProperties - + "}"; - } - } - - void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) { - super.dump(fd, pw, args); - pw.println(getClass().getSimpleName()); - pw.println("Tracking interfaces:"); - pw.increaseIndent(); - for (String iface: mTrackingInterfaces.keySet()) { - NetworkInterfaceState ifaceState = mTrackingInterfaces.get(iface); - pw.println(iface + ":" + ifaceState); - pw.increaseIndent(); - final IIpClient ipClient = ifaceState.mIpClient; - if (ipClient != null) { - IpClientUtil.dumpIpClient(ipClient, fd, pw, args); - } else { - pw.println("IpClient is null"); - } - pw.decreaseIndent(); - } - pw.decreaseIndent(); - } -} diff --git a/java/com/android/server/ethernet/EthernetService.java b/java/com/android/server/ethernet/EthernetService.java deleted file mode 100644 index 2448146..0000000 --- a/java/com/android/server/ethernet/EthernetService.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.ethernet; - -import android.content.Context; -import android.util.Log; -import com.android.server.SystemService; - -public final class EthernetService extends SystemService { - - private static final String TAG = "EthernetService"; - final EthernetServiceImpl mImpl; - - public EthernetService(Context context) { - super(context); - mImpl = new EthernetServiceImpl(context); - } - - @Override - public void onStart() { - Log.i(TAG, "Registering service " + Context.ETHERNET_SERVICE); - publishBinderService(Context.ETHERNET_SERVICE, mImpl); - } - - @Override - public void onBootPhase(int phase) { - if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { - mImpl.start(); - } - } -} diff --git a/java/com/android/server/ethernet/EthernetServiceImpl.java b/java/com/android/server/ethernet/EthernetServiceImpl.java deleted file mode 100644 index c06f61e..0000000 --- a/java/com/android/server/ethernet/EthernetServiceImpl.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.ethernet; - -import android.content.Context; -import android.content.pm.PackageManager; -import android.net.IEthernetManager; -import android.net.IEthernetServiceListener; -import android.net.ITetheredInterfaceCallback; -import android.net.IpConfiguration; -import android.net.NetworkStack; -import android.os.Binder; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.RemoteException; -import android.provider.Settings; -import android.util.Log; -import android.util.PrintWriterPrinter; - -import com.android.internal.util.IndentingPrintWriter; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * EthernetServiceImpl handles remote Ethernet operation requests by implementing - * the IEthernetManager interface. - */ -public class EthernetServiceImpl extends IEthernetManager.Stub { - private static final String TAG = "EthernetServiceImpl"; - - private final Context mContext; - private final AtomicBoolean mStarted = new AtomicBoolean(false); - - private Handler mHandler; - private EthernetTracker mTracker; - - public EthernetServiceImpl(Context context) { - mContext = context; - } - - private void enforceAccessPermission() { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.ACCESS_NETWORK_STATE, - "EthernetService"); - } - - private void enforceUseRestrictedNetworksPermission() { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS, - "ConnectivityService"); - } - - private boolean checkUseRestrictedNetworksPermission() { - return mContext.checkCallingOrSelfPermission( - android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS) - == PackageManager.PERMISSION_GRANTED; - } - - public void start() { - Log.i(TAG, "Starting Ethernet service"); - - HandlerThread handlerThread = new HandlerThread("EthernetServiceThread"); - handlerThread.start(); - mHandler = new Handler(handlerThread.getLooper()); - - mTracker = new EthernetTracker(mContext, mHandler); - mTracker.start(); - - mStarted.set(true); - } - - @Override - public String[] getAvailableInterfaces() throws RemoteException { - enforceAccessPermission(); - - return mTracker.getInterfaces(checkUseRestrictedNetworksPermission()); - } - - /** - * Get Ethernet configuration - * @return the Ethernet Configuration, contained in {@link IpConfiguration}. - */ - @Override - public IpConfiguration getConfiguration(String iface) { - enforceAccessPermission(); - - if (mTracker.isRestrictedInterface(iface)) { - enforceUseRestrictedNetworksPermission(); - } - - return new IpConfiguration(mTracker.getIpConfiguration(iface)); - } - - /** - * Set Ethernet configuration - */ - @Override - public void setConfiguration(String iface, IpConfiguration config) { - if (!mStarted.get()) { - Log.w(TAG, "System isn't ready enough to change ethernet configuration"); - } - - NetworkStack.checkNetworkStackPermission(mContext); - - if (mTracker.isRestrictedInterface(iface)) { - enforceUseRestrictedNetworksPermission(); - } - - // TODO: this does not check proxy settings, gateways, etc. - // Fix this by making IpConfiguration a complete representation of static configuration. - mTracker.updateIpConfiguration(iface, new IpConfiguration(config)); - } - - /** - * Indicates whether given interface is available. - */ - @Override - public boolean isAvailable(String iface) { - enforceAccessPermission(); - - if (mTracker.isRestrictedInterface(iface)) { - enforceUseRestrictedNetworksPermission(); - } - - return mTracker.isTrackingInterface(iface); - } - - /** - * Adds a listener. - * @param listener A {@link IEthernetServiceListener} to add. - */ - public void addListener(IEthernetServiceListener listener) { - if (listener == null) { - throw new IllegalArgumentException("listener must not be null"); - } - enforceAccessPermission(); - mTracker.addListener(listener, checkUseRestrictedNetworksPermission()); - } - - /** - * Removes a listener. - * @param listener A {@link IEthernetServiceListener} to remove. - */ - public void removeListener(IEthernetServiceListener listener) { - if (listener == null) { - throw new IllegalArgumentException("listener must not be null"); - } - enforceAccessPermission(); - mTracker.removeListener(listener); - } - - @Override - public void setIncludeTestInterfaces(boolean include) { - NetworkStack.checkNetworkStackPermissionOr(mContext, - android.Manifest.permission.NETWORK_SETTINGS); - mTracker.setIncludeTestInterfaces(include); - } - - @Override - public void requestTetheredInterface(ITetheredInterfaceCallback callback) { - NetworkStack.checkNetworkStackPermissionOr(mContext, - android.Manifest.permission.NETWORK_SETTINGS); - mTracker.requestTetheredInterface(callback); - } - - @Override - public void releaseTetheredInterface(ITetheredInterfaceCallback callback) { - NetworkStack.checkNetworkStackPermissionOr(mContext, - android.Manifest.permission.NETWORK_SETTINGS); - mTracker.releaseTetheredInterface(callback); - } - - @Override - protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { - final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); - if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) - != PackageManager.PERMISSION_GRANTED) { - pw.println("Permission Denial: can't dump EthernetService from pid=" - + Binder.getCallingPid() - + ", uid=" + Binder.getCallingUid()); - return; - } - - pw.println("Current Ethernet state: "); - pw.increaseIndent(); - mTracker.dump(fd, pw, args); - pw.decreaseIndent(); - - pw.println("Handler:"); - pw.increaseIndent(); - mHandler.dump(new PrintWriterPrinter(pw), "EthernetServiceImpl"); - pw.decreaseIndent(); - } -} diff --git a/java/com/android/server/ethernet/EthernetTracker.java b/java/com/android/server/ethernet/EthernetTracker.java deleted file mode 100644 index b2b60fc..0000000 --- a/java/com/android/server/ethernet/EthernetTracker.java +++ /dev/null @@ -1,675 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.ethernet; - -import static android.net.TestNetworkManager.TEST_TAP_PREFIX; - -import android.annotation.Nullable; -import android.content.Context; -import android.net.IEthernetServiceListener; -import android.net.INetd; -import android.net.ITetheredInterfaceCallback; -import android.net.InterfaceConfiguration; -import android.net.IpConfiguration; -import android.net.IpConfiguration.IpAssignment; -import android.net.IpConfiguration.ProxySettings; -import android.net.LinkAddress; -import android.net.NetworkCapabilities; -import android.net.NetworkStack; -import android.net.StaticIpConfiguration; -import android.os.Handler; -import android.os.IBinder; -import android.os.INetworkManagementService; -import android.os.RemoteCallbackList; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.text.TextUtils; -import android.util.ArrayMap; -import android.util.Log; -import android.net.util.NetdService; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.IndentingPrintWriter; -import com.android.net.module.util.NetdUtils; -import com.android.server.net.BaseNetworkObserver; - -import java.io.FileDescriptor; -import java.net.InetAddress; -import java.util.ArrayList; -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Tracks Ethernet interfaces and manages interface configurations. - * - * <p>Interfaces may have different {@link android.net.NetworkCapabilities}. This mapping is defined - * in {@code config_ethernet_interfaces}. Notably, some interfaces could be marked as restricted by - * not specifying {@link android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED} flag. - * Interfaces could have associated {@link android.net.IpConfiguration}. - * Ethernet Interfaces may be present at boot time or appear after boot (e.g., for Ethernet adapters - * connected over USB). This class supports multiple interfaces. When an interface appears on the - * system (or is present at boot time) this class will start tracking it and bring it up. Only - * interfaces whose names match the {@code config_ethernet_iface_regex} regular expression are - * tracked. - * - * <p>All public or package private methods must be thread-safe unless stated otherwise. - */ -final class EthernetTracker { - private static final int INTERFACE_MODE_CLIENT = 1; - private static final int INTERFACE_MODE_SERVER = 2; - - private final static String TAG = EthernetTracker.class.getSimpleName(); - private final static boolean DBG = EthernetNetworkFactory.DBG; - - private static final String TEST_IFACE_REGEXP = TEST_TAP_PREFIX + "\\d+"; - - /** - * Interface names we track. This is a product-dependent regular expression, plus, - * if setIncludeTestInterfaces is true, any test interfaces. - */ - private String mIfaceMatch; - private boolean mIncludeTestInterfaces = false; - - /** Mapping between {iface name | mac address} -> {NetworkCapabilities} */ - private final ConcurrentHashMap<String, NetworkCapabilities> mNetworkCapabilities = - new ConcurrentHashMap<>(); - private final ConcurrentHashMap<String, IpConfiguration> mIpConfigurations = - new ConcurrentHashMap<>(); - - private final Context mContext; - private final INetworkManagementService mNMService; - private final INetd mNetd; - private final Handler mHandler; - private final EthernetNetworkFactory mFactory; - private final EthernetConfigStore mConfigStore; - - private final RemoteCallbackList<IEthernetServiceListener> mListeners = - new RemoteCallbackList<>(); - private final TetheredInterfaceRequestList mTetheredInterfaceRequests = - new TetheredInterfaceRequestList(); - - // Used only on the handler thread - private String mDefaultInterface; - private int mDefaultInterfaceMode = INTERFACE_MODE_CLIENT; - // Tracks whether clients were notified that the tethered interface is available - private boolean mTetheredInterfaceWasAvailable = false; - private volatile IpConfiguration mIpConfigForDefaultInterface; - - private class TetheredInterfaceRequestList extends RemoteCallbackList<ITetheredInterfaceCallback> { - @Override - public void onCallbackDied(ITetheredInterfaceCallback cb, Object cookie) { - mHandler.post(EthernetTracker.this::maybeUntetherDefaultInterface); - } - } - - EthernetTracker(Context context, Handler handler) { - mContext = context; - mHandler = handler; - - // The services we use. - IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); - mNMService = INetworkManagementService.Stub.asInterface(b); - mNetd = Objects.requireNonNull(NetdService.getInstance(), "could not get netd instance"); - - // Interface match regex. - updateIfaceMatchRegexp(); - - // Read default Ethernet interface configuration from resources - final String[] interfaceConfigs = context.getResources().getStringArray( - com.android.internal.R.array.config_ethernet_interfaces); - for (String strConfig : interfaceConfigs) { - parseEthernetConfig(strConfig); - } - - mConfigStore = new EthernetConfigStore(); - - NetworkCapabilities nc = createNetworkCapabilities(true /* clear default capabilities */); - mFactory = new EthernetNetworkFactory(handler, context, nc); - mFactory.register(); - } - - void start() { - mConfigStore.read(); - - // Default interface is just the first one we want to track. - mIpConfigForDefaultInterface = mConfigStore.getIpConfigurationForDefaultInterface(); - final ArrayMap<String, IpConfiguration> configs = mConfigStore.getIpConfigurations(); - for (int i = 0; i < configs.size(); i++) { - mIpConfigurations.put(configs.keyAt(i), configs.valueAt(i)); - } - - try { - mNMService.registerObserver(new InterfaceObserver()); - } catch (RemoteException e) { - Log.e(TAG, "Could not register InterfaceObserver " + e); - } - - mHandler.post(this::trackAvailableInterfaces); - } - - void updateIpConfiguration(String iface, IpConfiguration ipConfiguration) { - if (DBG) { - Log.i(TAG, "updateIpConfiguration, iface: " + iface + ", cfg: " + ipConfiguration); - } - - mConfigStore.write(iface, ipConfiguration); - mIpConfigurations.put(iface, ipConfiguration); - - mHandler.post(() -> mFactory.updateIpConfiguration(iface, ipConfiguration)); - } - - IpConfiguration getIpConfiguration(String iface) { - return mIpConfigurations.get(iface); - } - - boolean isTrackingInterface(String iface) { - return mFactory.hasInterface(iface); - } - - String[] getInterfaces(boolean includeRestricted) { - return mFactory.getAvailableInterfaces(includeRestricted); - } - - /** - * Returns true if given interface was configured as restricted (doesn't have - * NET_CAPABILITY_NOT_RESTRICTED) capability. Otherwise, returns false. - */ - boolean isRestrictedInterface(String iface) { - final NetworkCapabilities nc = mNetworkCapabilities.get(iface); - return nc != null && !nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); - } - - void addListener(IEthernetServiceListener listener, boolean canUseRestrictedNetworks) { - mListeners.register(listener, new ListenerInfo(canUseRestrictedNetworks)); - } - - void removeListener(IEthernetServiceListener listener) { - mListeners.unregister(listener); - } - - public void setIncludeTestInterfaces(boolean include) { - mHandler.post(() -> { - mIncludeTestInterfaces = include; - updateIfaceMatchRegexp(); - mHandler.post(() -> trackAvailableInterfaces()); - }); - } - - public void requestTetheredInterface(ITetheredInterfaceCallback callback) { - mHandler.post(() -> { - if (!mTetheredInterfaceRequests.register(callback)) { - // Remote process has already died - return; - } - if (mDefaultInterfaceMode == INTERFACE_MODE_SERVER) { - if (mTetheredInterfaceWasAvailable) { - notifyTetheredInterfaceAvailable(callback, mDefaultInterface); - } - return; - } - - setDefaultInterfaceMode(INTERFACE_MODE_SERVER); - }); - } - - public void releaseTetheredInterface(ITetheredInterfaceCallback callback) { - mHandler.post(() -> { - mTetheredInterfaceRequests.unregister(callback); - maybeUntetherDefaultInterface(); - }); - } - - private void notifyTetheredInterfaceAvailable(ITetheredInterfaceCallback cb, String iface) { - try { - cb.onAvailable(iface); - } catch (RemoteException e) { - Log.e(TAG, "Error sending tethered interface available callback", e); - } - } - - private void notifyTetheredInterfaceUnavailable(ITetheredInterfaceCallback cb) { - try { - cb.onUnavailable(); - } catch (RemoteException e) { - Log.e(TAG, "Error sending tethered interface available callback", e); - } - } - - private void maybeUntetherDefaultInterface() { - if (mTetheredInterfaceRequests.getRegisteredCallbackCount() > 0) return; - if (mDefaultInterfaceMode == INTERFACE_MODE_CLIENT) return; - setDefaultInterfaceMode(INTERFACE_MODE_CLIENT); - } - - private void setDefaultInterfaceMode(int mode) { - Log.d(TAG, "Setting default interface mode to " + mode); - mDefaultInterfaceMode = mode; - if (mDefaultInterface != null) { - removeInterface(mDefaultInterface); - addInterface(mDefaultInterface); - } - } - - private int getInterfaceMode(final String iface) { - if (iface.equals(mDefaultInterface)) { - return mDefaultInterfaceMode; - } - return INTERFACE_MODE_CLIENT; - } - - private void removeInterface(String iface) { - mFactory.removeInterface(iface); - maybeUpdateServerModeInterfaceState(iface, false); - } - - private void stopTrackingInterface(String iface) { - removeInterface(iface); - if (iface.equals(mDefaultInterface)) { - mDefaultInterface = null; - } - } - - private void addInterface(String iface) { - InterfaceConfiguration config = null; - // Bring up the interface so we get link status indications. - try { - NetworkStack.checkNetworkStackPermission(mContext); - NetdUtils.setInterfaceUp(mNetd, iface); - config = mNMService.getInterfaceConfig(iface); - } catch (RemoteException | IllegalStateException e) { - // Either the system is crashing or the interface has disappeared. Just ignore the - // error; we haven't modified any state because we only do that if our calls succeed. - Log.e(TAG, "Error upping interface " + iface, e); - } - - if (config == null) { - Log.e(TAG, "Null interface config for " + iface + ". Bailing out."); - return; - } - - final String hwAddress = config.getHardwareAddress(); - - NetworkCapabilities nc = mNetworkCapabilities.get(iface); - if (nc == null) { - // Try to resolve using mac address - nc = mNetworkCapabilities.get(hwAddress); - if (nc == null) { - final boolean isTestIface = iface.matches(TEST_IFACE_REGEXP); - nc = createDefaultNetworkCapabilities(isTestIface); - } - } - - final int mode = getInterfaceMode(iface); - if (mode == INTERFACE_MODE_CLIENT) { - IpConfiguration ipConfiguration = mIpConfigurations.get(iface); - if (ipConfiguration == null) { - ipConfiguration = createDefaultIpConfiguration(); - } - - Log.d(TAG, "Tracking interface in client mode: " + iface); - mFactory.addInterface(iface, hwAddress, nc, ipConfiguration); - } else { - maybeUpdateServerModeInterfaceState(iface, true); - } - - // Note: if the interface already has link (e.g., if we crashed and got - // restarted while it was running), we need to fake a link up notification so we - // start configuring it. - if (config.hasFlag("running")) { - updateInterfaceState(iface, true); - } - } - - private void updateInterfaceState(String iface, boolean up) { - final int mode = getInterfaceMode(iface); - final boolean factoryLinkStateUpdated = (mode == INTERFACE_MODE_CLIENT) - && mFactory.updateInterfaceLinkState(iface, up); - - if (factoryLinkStateUpdated) { - boolean restricted = isRestrictedInterface(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(); - } - } - - private void maybeUpdateServerModeInterfaceState(String iface, boolean available) { - if (available == mTetheredInterfaceWasAvailable || !iface.equals(mDefaultInterface)) return; - - Log.d(TAG, (available ? "Tracking" : "No longer tracking") - + " interface in server mode: " + iface); - - final int pendingCbs = mTetheredInterfaceRequests.beginBroadcast(); - for (int i = 0; i < pendingCbs; i++) { - ITetheredInterfaceCallback item = mTetheredInterfaceRequests.getBroadcastItem(i); - if (available) { - notifyTetheredInterfaceAvailable(item, iface); - } else { - notifyTetheredInterfaceUnavailable(item); - } - } - mTetheredInterfaceRequests.finishBroadcast(); - mTetheredInterfaceWasAvailable = available; - } - - private void maybeTrackInterface(String iface) { - if (!iface.matches(mIfaceMatch)) { - return; - } - - // If we don't already track this interface, and if this interface matches - // our regex, start tracking it. - if (mFactory.hasInterface(iface) || iface.equals(mDefaultInterface)) { - if (DBG) Log.w(TAG, "Ignoring already-tracked interface " + iface); - return; - } - if (DBG) Log.i(TAG, "maybeTrackInterface: " + iface); - - // TODO: avoid making an interface default if it has configured NetworkCapabilities. - if (mDefaultInterface == null) { - mDefaultInterface = iface; - } - - if (mIpConfigForDefaultInterface != null) { - updateIpConfiguration(iface, mIpConfigForDefaultInterface); - mIpConfigForDefaultInterface = null; - } - - addInterface(iface); - } - - private void trackAvailableInterfaces() { - try { - final String[] ifaces = mNMService.listInterfaces(); - for (String iface : ifaces) { - maybeTrackInterface(iface); - } - } catch (RemoteException | IllegalStateException e) { - Log.e(TAG, "Could not get list of interfaces " + e); - } - } - - - private class InterfaceObserver extends BaseNetworkObserver { - - @Override - public void interfaceLinkStateChanged(String iface, boolean up) { - if (DBG) { - Log.i(TAG, "interfaceLinkStateChanged, iface: " + iface + ", up: " + up); - } - mHandler.post(() -> updateInterfaceState(iface, up)); - } - - @Override - public void interfaceAdded(String iface) { - mHandler.post(() -> maybeTrackInterface(iface)); - } - - @Override - public void interfaceRemoved(String iface) { - mHandler.post(() -> stopTrackingInterface(iface)); - } - } - - private static class ListenerInfo { - - boolean canUseRestrictedNetworks = false; - - ListenerInfo(boolean canUseRestrictedNetworks) { - this.canUseRestrictedNetworks = canUseRestrictedNetworks; - } - } - - /** - * Parses an Ethernet interface configuration - * - * @param configString represents an Ethernet configuration in the following format: {@code - * <interface name|mac address>;[Network Capabilities];[IP config];[Override Transport]} - */ - private void parseEthernetConfig(String configString) { - String[] tokens = configString.split(";", /* limit of tokens */ 4); - String name = tokens[0]; - String capabilities = tokens.length > 1 ? tokens[1] : null; - String transport = tokens.length > 3 ? tokens[3] : null; - NetworkCapabilities nc = createNetworkCapabilities( - !TextUtils.isEmpty(capabilities) /* clear default capabilities */, capabilities, - transport).build(); - mNetworkCapabilities.put(name, nc); - - if (tokens.length > 2 && !TextUtils.isEmpty(tokens[2])) { - IpConfiguration ipConfig = parseStaticIpConfiguration(tokens[2]); - mIpConfigurations.put(name, ipConfig); - } - } - - private static NetworkCapabilities createDefaultNetworkCapabilities(boolean isTestIface) { - NetworkCapabilities.Builder builder = createNetworkCapabilities( - false /* clear default capabilities */, null, null) - .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) - .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED) - .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING) - .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED) - .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED) - .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); - - if (isTestIface) { - builder.addTransportType(NetworkCapabilities.TRANSPORT_TEST); - } else { - builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); - } - - return builder.build(); - } - - private static NetworkCapabilities createNetworkCapabilities(boolean clearDefaultCapabilities) { - return createNetworkCapabilities(clearDefaultCapabilities, null, null).build(); - } - - /** - * Parses a static list of network capabilities - * - * @param clearDefaultCapabilities Indicates whether or not to clear any default capabilities - * @param commaSeparatedCapabilities A comma separated string list of integer encoded - * NetworkCapability.NET_CAPABILITY_* values - * @param overrideTransport A string representing a single integer encoded override transport - * type. Must be one of the NetworkCapability.TRANSPORT_* - * values. TRANSPORT_VPN is not supported. Errors with input - * will cause the override to be ignored. - */ - @VisibleForTesting - static NetworkCapabilities.Builder createNetworkCapabilities( - boolean clearDefaultCapabilities, @Nullable String commaSeparatedCapabilities, - @Nullable String overrideTransport) { - - final NetworkCapabilities.Builder builder = clearDefaultCapabilities - ? NetworkCapabilities.Builder.withoutDefaultCapabilities() - : new NetworkCapabilities.Builder(); - - // Determine the transport type. If someone has tried to define an override transport then - // attempt to add it. Since we can only have one override, all errors with it will - // gracefully default back to TRANSPORT_ETHERNET and warn the user. VPN is not allowed as an - // override type. Wifi Aware and LoWPAN are currently unsupported as well. - int transport = NetworkCapabilities.TRANSPORT_ETHERNET; - if (!TextUtils.isEmpty(overrideTransport)) { - try { - int parsedTransport = Integer.valueOf(overrideTransport); - if (parsedTransport == NetworkCapabilities.TRANSPORT_VPN - || parsedTransport == NetworkCapabilities.TRANSPORT_WIFI_AWARE - || parsedTransport == NetworkCapabilities.TRANSPORT_LOWPAN) { - Log.e(TAG, "Override transport '" + parsedTransport + "' is not supported. " - + "Defaulting to TRANSPORT_ETHERNET"); - } else { - transport = parsedTransport; - } - } catch (NumberFormatException nfe) { - Log.e(TAG, "Override transport type '" + overrideTransport + "' " - + "could not be parsed. Defaulting to TRANSPORT_ETHERNET"); - } - } - - // Apply the transport. If the user supplied a valid number that is not a valid transport - // then adding will throw an exception. Default back to TRANSPORT_ETHERNET if that happens - try { - builder.addTransportType(transport); - } catch (IllegalArgumentException iae) { - Log.e(TAG, transport + " is not a valid NetworkCapability.TRANSPORT_* value. " - + "Defaulting to TRANSPORT_ETHERNET"); - builder.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET); - } - - builder.setLinkUpstreamBandwidthKbps(100 * 1000); - builder.setLinkDownstreamBandwidthKbps(100 * 1000); - - if (!TextUtils.isEmpty(commaSeparatedCapabilities)) { - for (String strNetworkCapability : commaSeparatedCapabilities.split(",")) { - if (!TextUtils.isEmpty(strNetworkCapability)) { - try { - builder.addCapability(Integer.valueOf(strNetworkCapability)); - } catch (NumberFormatException nfe) { - Log.e(TAG, "Capability '" + strNetworkCapability + "' could not be parsed"); - } catch (IllegalArgumentException iae) { - Log.e(TAG, strNetworkCapability + " is not a valid " - + "NetworkCapability.NET_CAPABILITY_* value"); - } - } - } - } - // Ethernet networks have no way to update the following capabilities, so they always - // have them. - builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING); - builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED); - builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED); - - return builder; - } - - /** - * Parses static IP configuration. - * - * @param staticIpConfig represents static IP configuration in the following format: {@code - * ip=<ip-address/mask> gateway=<ip-address> dns=<comma-sep-ip-addresses> - * domains=<comma-sep-domains>} - */ - @VisibleForTesting - static IpConfiguration parseStaticIpConfiguration(String staticIpConfig) { - final StaticIpConfiguration.Builder staticIpConfigBuilder = - new StaticIpConfiguration.Builder(); - - for (String keyValueAsString : staticIpConfig.trim().split(" ")) { - if (TextUtils.isEmpty(keyValueAsString)) continue; - - String[] pair = keyValueAsString.split("="); - if (pair.length != 2) { - throw new IllegalArgumentException("Unexpected token: " + keyValueAsString - + " in " + staticIpConfig); - } - - String key = pair[0]; - String value = pair[1]; - - switch (key) { - case "ip": - staticIpConfigBuilder.setIpAddress(new LinkAddress(value)); - break; - case "domains": - staticIpConfigBuilder.setDomains(value); - break; - case "gateway": - staticIpConfigBuilder.setGateway(InetAddress.parseNumericAddress(value)); - break; - case "dns": { - ArrayList<InetAddress> dnsAddresses = new ArrayList<>(); - for (String address: value.split(",")) { - dnsAddresses.add(InetAddress.parseNumericAddress(address)); - } - staticIpConfigBuilder.setDnsServers(dnsAddresses); - break; - } - default : { - throw new IllegalArgumentException("Unexpected key: " + key - + " in " + staticIpConfig); - } - } - } - final IpConfiguration ret = new IpConfiguration(); - ret.setIpAssignment(IpAssignment.STATIC); - ret.setProxySettings(ProxySettings.NONE); - ret.setStaticIpConfiguration(staticIpConfigBuilder.build()); - return ret; - } - - private static IpConfiguration createDefaultIpConfiguration() { - final IpConfiguration ret = new IpConfiguration(); - ret.setIpAssignment(IpAssignment.DHCP); - ret.setProxySettings(ProxySettings.NONE); - return ret; - } - - private void updateIfaceMatchRegexp() { - final String match = mContext.getResources().getString( - com.android.internal.R.string.config_ethernet_iface_regex); - mIfaceMatch = mIncludeTestInterfaces - ? "(" + match + "|" + TEST_IFACE_REGEXP + ")" - : match; - Log.d(TAG, "Interface match regexp set to '" + mIfaceMatch + "'"); - } - - private void postAndWaitForRunnable(Runnable r) { - mHandler.runWithScissors(r, 2000L /* timeout */); - } - - void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) { - postAndWaitForRunnable(() -> { - pw.println(getClass().getSimpleName()); - pw.println("Ethernet interface name filter: " + mIfaceMatch); - pw.println("Default interface: " + mDefaultInterface); - pw.println("Default interface mode: " + mDefaultInterfaceMode); - pw.println("Tethered interface requests: " - + mTetheredInterfaceRequests.getRegisteredCallbackCount()); - pw.println("Listeners: " + mListeners.getRegisteredCallbackCount()); - pw.println("IP Configurations:"); - pw.increaseIndent(); - for (String iface : mIpConfigurations.keySet()) { - pw.println(iface + ": " + mIpConfigurations.get(iface)); - } - pw.decreaseIndent(); - pw.println(); - - pw.println("Network Capabilities:"); - pw.increaseIndent(); - for (String iface : mNetworkCapabilities.keySet()) { - pw.println(iface + ": " + mNetworkCapabilities.get(iface)); - } - pw.decreaseIndent(); - pw.println(); - - mFactory.dump(fd, pw, args); - }); - } -} diff --git a/tests/Android.bp b/tests/Android.bp deleted file mode 100644 index 4b2d270..0000000 --- a/tests/Android.bp +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (C) 2018 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -package { - default_applicable_licenses: ["Android-Apache-2.0"], -} - -android_test { - name: "EthernetServiceTests", - - srcs: ["java/**/*.java"], - - certificate: "platform", - platform_apis: true, - - libs: [ - "android.test.runner", - "android.test.base", - ], - - static_libs: [ - "androidx.test.rules", - "ethernet-service", - ], -} diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml deleted file mode 100644 index 302bb6c..0000000 --- a/tests/AndroidManifest.xml +++ /dev/null @@ -1,28 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - ~ Copyright (C) 2018 The Android Open Source Project - ~ - ~ Licensed under the Apache License, Version 2.0 (the "License"); - ~ you may not use this file except in compliance with the License. - ~ You may obtain a copy of the License at - ~ - ~ http://www.apache.org/licenses/LICENSE-2.0 - ~ - ~ Unless required by applicable law or agreed to in writing, software - ~ distributed under the License is distributed on an "AS IS" BASIS, - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ~ See the License for the specific language governing permissions and - ~ limitations under the License - --> - -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.server.ethernet.tests"> - - <application android:label="EthernetServiceTests"> - <uses-library android:name="android.test.runner" /> - </application> - - <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" - android:targetPackage="com.android.server.ethernet.tests" - android:label="Ethernet Service Tests" /> -</manifest> diff --git a/tests/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/java/com/android/server/ethernet/EthernetTrackerTest.java deleted file mode 100644 index ee9f349..0000000 --- a/tests/java/com/android/server/ethernet/EthernetTrackerTest.java +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.ethernet; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -import android.net.InetAddresses; -import android.net.IpConfiguration; -import android.net.IpConfiguration.IpAssignment; -import android.net.IpConfiguration.ProxySettings; -import android.net.LinkAddress; -import android.net.NetworkCapabilities; -import android.net.StaticIpConfiguration; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.net.InetAddress; -import java.util.ArrayList; - -@SmallTest -@RunWith(AndroidJUnit4.class) -public class EthernetTrackerTest { - /** - * Test: Creation of various valid static IP configurations - */ - @Test - public void createStaticIpConfiguration() { - // Empty gives default StaticIPConfiguration object - assertStaticConfiguration(new StaticIpConfiguration(), ""); - - // Setting only the IP address properly cascades and assumes defaults - assertStaticConfiguration(new StaticIpConfiguration.Builder() - .setIpAddress(new LinkAddress("192.0.2.10/24")).build(), "ip=192.0.2.10/24"); - - final ArrayList<InetAddress> dnsAddresses = new ArrayList<>(); - dnsAddresses.add(InetAddresses.parseNumericAddress("4.4.4.4")); - dnsAddresses.add(InetAddresses.parseNumericAddress("8.8.8.8")); - // Setting other fields properly cascades them - assertStaticConfiguration(new StaticIpConfiguration.Builder() - .setIpAddress(new LinkAddress("192.0.2.10/24")) - .setDnsServers(dnsAddresses) - .setGateway(InetAddresses.parseNumericAddress("192.0.2.1")) - .setDomains("android").build(), - "ip=192.0.2.10/24 dns=4.4.4.4,8.8.8.8 gateway=192.0.2.1 domains=android"); - - // Verify order doesn't matter - assertStaticConfiguration(new StaticIpConfiguration.Builder() - .setIpAddress(new LinkAddress("192.0.2.10/24")) - .setDnsServers(dnsAddresses) - .setGateway(InetAddresses.parseNumericAddress("192.0.2.1")) - .setDomains("android").build(), - "domains=android ip=192.0.2.10/24 gateway=192.0.2.1 dns=4.4.4.4,8.8.8.8 "); - } - - /** - * Test: Attempt creation of various bad static IP configurations - */ - @Test - public void createStaticIpConfiguration_Bad() { - assertStaticConfigurationFails("ip=192.0.2.1/24 gateway= blah=20.20.20.20"); // Unknown key - assertStaticConfigurationFails("ip=192.0.2.1"); // mask is missing - assertStaticConfigurationFails("ip=a.b.c"); // not a valid ip address - assertStaticConfigurationFails("dns=4.4.4.4,1.2.3.A"); // not valid ip address in dns - assertStaticConfigurationFails("="); // Key and value is empty - assertStaticConfigurationFails("ip="); // Value is empty - assertStaticConfigurationFails("ip=192.0.2.1/24 gateway="); // Gateway is empty - } - - private void assertStaticConfigurationFails(String config) { - try { - EthernetTracker.parseStaticIpConfiguration(config); - fail("Expected to fail: " + config); - } catch (IllegalArgumentException e) { - // expected - } - } - - private void assertStaticConfiguration(StaticIpConfiguration expectedStaticIpConfig, - String configAsString) { - final IpConfiguration expectedIpConfiguration = new IpConfiguration(); - expectedIpConfiguration.setIpAssignment(IpAssignment.STATIC); - expectedIpConfiguration.setProxySettings(ProxySettings.NONE); - expectedIpConfiguration.setStaticIpConfiguration(expectedStaticIpConfig); - - assertEquals(expectedIpConfiguration, - EthernetTracker.parseStaticIpConfiguration(configAsString)); - } - - private NetworkCapabilities.Builder makeEthernetCapabilitiesBuilder(boolean clearAll) { - final NetworkCapabilities.Builder builder = - clearAll ? NetworkCapabilities.Builder.withoutDefaultCapabilities() - : new NetworkCapabilities.Builder(); - return builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING) - .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED) - .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED); - } - - /** - * Test: Attempt to create a capabilties with various valid sets of capabilities/transports - */ - @Test - public void createNetworkCapabilities() { - - // Particularly common expected results - NetworkCapabilities defaultEthernetCleared = - makeEthernetCapabilitiesBuilder(true /* clearAll */) - .setLinkUpstreamBandwidthKbps(100000) - .setLinkDownstreamBandwidthKbps(100000) - .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) - .build(); - - NetworkCapabilities ethernetClearedWithCommonCaps = - makeEthernetCapabilitiesBuilder(true /* clearAll */) - .setLinkUpstreamBandwidthKbps(100000) - .setLinkDownstreamBandwidthKbps(100000) - .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) - .addCapability(12) - .addCapability(13) - .addCapability(14) - .addCapability(15) - .build(); - - // Empty capabilities and transports lists with a "please clear defaults" should - // yield an empty capabilities set with TRANPORT_ETHERNET - assertParsedNetworkCapabilities(defaultEthernetCleared, true, "", ""); - - // Empty capabilities and transports without the clear defaults flag should return the - // default capabilities set with TRANSPORT_ETHERNET - assertParsedNetworkCapabilities( - makeEthernetCapabilitiesBuilder(false /* clearAll */) - .setLinkUpstreamBandwidthKbps(100000) - .setLinkDownstreamBandwidthKbps(100000) - .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) - .build(), - false, "", ""); - - // A list of capabilities without the clear defaults flag should return the default - // capabilities, mixed with the desired capabilities, and TRANSPORT_ETHERNET - assertParsedNetworkCapabilities( - makeEthernetCapabilitiesBuilder(false /* clearAll */) - .setLinkUpstreamBandwidthKbps(100000) - .setLinkDownstreamBandwidthKbps(100000) - .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) - .addCapability(11) - .addCapability(12) - .build(), - false, "11,12", ""); - - // Adding a list of capabilities with a clear defaults will leave exactly those capabilities - // with a default TRANSPORT_ETHERNET since no overrides are specified - assertParsedNetworkCapabilities(ethernetClearedWithCommonCaps, true, "12,13,14,15", ""); - - // Adding any invalid capabilities to the list will cause them to be ignored - assertParsedNetworkCapabilities(ethernetClearedWithCommonCaps, true, "12,13,14,15,65,73", ""); - assertParsedNetworkCapabilities(ethernetClearedWithCommonCaps, true, "12,13,14,15,abcdefg", ""); - - // Adding a valid override transport will remove the default TRANSPORT_ETHERNET transport - // and apply only the override to the capabiltities object - assertParsedNetworkCapabilities( - makeEthernetCapabilitiesBuilder(true /* clearAll */) - .setLinkUpstreamBandwidthKbps(100000) - .setLinkDownstreamBandwidthKbps(100000) - .addTransportType(0) - .build(), - true, "", "0"); - assertParsedNetworkCapabilities( - makeEthernetCapabilitiesBuilder(true /* clearAll */) - .setLinkUpstreamBandwidthKbps(100000) - .setLinkDownstreamBandwidthKbps(100000) - .addTransportType(1) - .build(), - true, "", "1"); - assertParsedNetworkCapabilities( - makeEthernetCapabilitiesBuilder(true /* clearAll */) - .setLinkUpstreamBandwidthKbps(100000) - .setLinkDownstreamBandwidthKbps(100000) - .addTransportType(2) - .build(), - true, "", "2"); - assertParsedNetworkCapabilities( - makeEthernetCapabilitiesBuilder(true /* clearAll */) - .setLinkUpstreamBandwidthKbps(100000) - .setLinkDownstreamBandwidthKbps(100000) - .addTransportType(3) - .build(), - true, "", "3"); - - // "4" is TRANSPORT_VPN, which is unsupported. Should default back to TRANPORT_ETHERNET - assertParsedNetworkCapabilities(defaultEthernetCleared, true, "", "4"); - - // "5" is TRANSPORT_WIFI_AWARE, which is currently supported due to no legacy TYPE_NONE - // conversion. When that becomes available, this test must be updated - assertParsedNetworkCapabilities(defaultEthernetCleared, true, "", "5"); - - // "6" is TRANSPORT_LOWPAN, which is currently supported due to no legacy TYPE_NONE - // conversion. When that becomes available, this test must be updated - assertParsedNetworkCapabilities(defaultEthernetCleared, true, "", "6"); - - // Adding an invalid override transport will leave the transport as TRANSPORT_ETHERNET - assertParsedNetworkCapabilities(defaultEthernetCleared,true, "", "100"); - assertParsedNetworkCapabilities(defaultEthernetCleared, true, "", "abcdefg"); - - // Ensure the adding of both capabilities and transports work - assertParsedNetworkCapabilities( - makeEthernetCapabilitiesBuilder(true /* clearAll */) - .setLinkUpstreamBandwidthKbps(100000) - .setLinkDownstreamBandwidthKbps(100000) - .addCapability(12) - .addCapability(13) - .addCapability(14) - .addCapability(15) - .addTransportType(3) - .build(), - true, "12,13,14,15", "3"); - - // Ensure order does not matter for capability list - assertParsedNetworkCapabilities(ethernetClearedWithCommonCaps, true, "13,12,15,14", ""); - } - - private void assertParsedNetworkCapabilities(NetworkCapabilities expectedNetworkCapabilities, - boolean clearCapabilties, String configCapabiltiies,String configTransports) { - assertEquals(expectedNetworkCapabilities, - EthernetTracker.createNetworkCapabilities(clearCapabilties, configCapabiltiies, - configTransports).build()); - } -} |