Refactor RoutingCoordinator
- This CL puts RoutingCoordinator into staticlibs to make it usable by both Tethering and ConnectivityService on R. - This CL also changes the return type of ConnectivityInternalApi#getRoutingCoordinatorManager() to IBinder so it has fewer dependencies. Bug: 350699020 Test: CI Change-Id: Iba096e940795cd33e61c5141721394ad39e5ce6d
This commit is contained in:
parent
9b0df36ea4
commit
8f2c30664d
14 changed files with 26 additions and 30 deletions
|
|
@ -44,7 +44,6 @@ import android.net.LinkAddress;
|
|||
import android.net.LinkProperties;
|
||||
import android.net.MacAddress;
|
||||
import android.net.RouteInfo;
|
||||
import android.net.RoutingCoordinatorManager;
|
||||
import android.net.TetheredClient;
|
||||
import android.net.TetheringManager;
|
||||
import android.net.TetheringManager.TetheringRequest;
|
||||
|
|
@ -72,6 +71,7 @@ import com.android.internal.util.State;
|
|||
import com.android.modules.utils.build.SdkLevel;
|
||||
import com.android.net.module.util.InterfaceParams;
|
||||
import com.android.net.module.util.NetdUtils;
|
||||
import com.android.net.module.util.RoutingCoordinatorManager;
|
||||
import com.android.net.module.util.SdkUtil.LateSdk;
|
||||
import com.android.net.module.util.SharedLog;
|
||||
import com.android.net.module.util.SyncStateMachine.StateInfo;
|
||||
|
|
|
|||
|
|
@ -91,7 +91,6 @@ import android.net.LinkAddress;
|
|||
import android.net.LinkProperties;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.RoutingCoordinatorManager;
|
||||
import android.net.TetherStatesParcel;
|
||||
import android.net.TetheredClient;
|
||||
import android.net.TetheringCallbackStartedParcel;
|
||||
|
|
@ -138,6 +137,7 @@ import com.android.net.module.util.BaseNetdUnsolicitedEventListener;
|
|||
import com.android.net.module.util.CollectionUtils;
|
||||
import com.android.net.module.util.HandlerUtils;
|
||||
import com.android.net.module.util.NetdUtils;
|
||||
import com.android.net.module.util.RoutingCoordinatorManager;
|
||||
import com.android.net.module.util.SdkUtil.LateSdk;
|
||||
import com.android.net.module.util.SharedLog;
|
||||
import com.android.networkstack.apishim.common.BluetoothPanShim;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ import android.bluetooth.BluetoothAdapter;
|
|||
import android.bluetooth.BluetoothPan;
|
||||
import android.content.Context;
|
||||
import android.net.INetd;
|
||||
import android.net.RoutingCoordinatorManager;
|
||||
import android.net.connectivity.ConnectivityInternalApiUtil;
|
||||
import android.net.ip.IpServer;
|
||||
import android.os.Build;
|
||||
|
|
@ -36,6 +35,7 @@ import androidx.annotation.NonNull;
|
|||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import com.android.modules.utils.build.SdkLevel;
|
||||
import com.android.net.module.util.RoutingCoordinatorManager;
|
||||
import com.android.net.module.util.SdkUtil.LateSdk;
|
||||
import com.android.net.module.util.SharedLog;
|
||||
import com.android.networkstack.apishim.BluetoothPanShimImpl;
|
||||
|
|
@ -132,7 +132,8 @@ public abstract class TetheringDependencies {
|
|||
public LateSdk<RoutingCoordinatorManager> getRoutingCoordinator(Context context) {
|
||||
if (!SdkLevel.isAtLeastS()) return new LateSdk<>(null);
|
||||
return new LateSdk<>(
|
||||
ConnectivityInternalApiUtil.getRoutingCoordinatorManager(context));
|
||||
new RoutingCoordinatorManager(
|
||||
context, ConnectivityInternalApiUtil.getRoutingCoordinator(context)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -73,7 +73,6 @@ import android.net.LinkAddress;
|
|||
import android.net.LinkProperties;
|
||||
import android.net.MacAddress;
|
||||
import android.net.RouteInfo;
|
||||
import android.net.RoutingCoordinatorManager;
|
||||
import android.net.dhcp.DhcpServerCallbacks;
|
||||
import android.net.dhcp.DhcpServingParamsParcel;
|
||||
import android.net.dhcp.IDhcpEventCallbacks;
|
||||
|
|
@ -91,6 +90,7 @@ import androidx.test.runner.AndroidJUnit4;
|
|||
|
||||
import com.android.modules.utils.build.SdkLevel;
|
||||
import com.android.net.module.util.InterfaceParams;
|
||||
import com.android.net.module.util.RoutingCoordinatorManager;
|
||||
import com.android.net.module.util.SdkUtil.LateSdk;
|
||||
import com.android.net.module.util.SharedLog;
|
||||
import com.android.networkstack.tethering.BpfCoordinator;
|
||||
|
|
|
|||
|
|
@ -142,7 +142,6 @@ import android.net.Network;
|
|||
import android.net.NetworkCapabilities;
|
||||
import android.net.NetworkRequest;
|
||||
import android.net.RouteInfo;
|
||||
import android.net.RoutingCoordinatorManager;
|
||||
import android.net.TetherStatesParcel;
|
||||
import android.net.TetheredClient;
|
||||
import android.net.TetheredClient.AddressInfo;
|
||||
|
|
@ -191,6 +190,7 @@ import com.android.internal.util.test.BroadcastInterceptingContext;
|
|||
import com.android.internal.util.test.FakeSettingsProvider;
|
||||
import com.android.net.module.util.CollectionUtils;
|
||||
import com.android.net.module.util.InterfaceParams;
|
||||
import com.android.net.module.util.RoutingCoordinatorManager;
|
||||
import com.android.net.module.util.SdkUtil.LateSdk;
|
||||
import com.android.net.module.util.SharedLog;
|
||||
import com.android.net.module.util.ip.IpNeighborMonitor;
|
||||
|
|
|
|||
|
|
@ -330,7 +330,6 @@ java_library {
|
|||
srcs: [
|
||||
// Files listed here MUST all be annotated with @RequiresApi(Build.VERSION_CODES.S)
|
||||
// or above as appropriate so that API checks are enforced for R+ users of this library
|
||||
"src/android/net/RoutingCoordinatorManager.java",
|
||||
"src/android/net/connectivity/ConnectivityInternalApiUtil.java",
|
||||
],
|
||||
visibility: [
|
||||
|
|
|
|||
|
|
@ -6737,21 +6737,11 @@ public class ConnectivityManager {
|
|||
}
|
||||
}
|
||||
|
||||
private static final Object sRoutingCoordinatorManagerLock = new Object();
|
||||
@GuardedBy("sRoutingCoordinatorManagerLock")
|
||||
private static RoutingCoordinatorManager sRoutingCoordinatorManager = null;
|
||||
/** @hide */
|
||||
@RequiresApi(Build.VERSION_CODES.S)
|
||||
public RoutingCoordinatorManager getRoutingCoordinatorManager() {
|
||||
public IBinder getRoutingCoordinatorService() {
|
||||
try {
|
||||
synchronized (sRoutingCoordinatorManagerLock) {
|
||||
if (null == sRoutingCoordinatorManager) {
|
||||
sRoutingCoordinatorManager = new RoutingCoordinatorManager(mContext,
|
||||
IRoutingCoordinator.Stub.asInterface(
|
||||
mService.getRoutingCoordinatorService()));
|
||||
}
|
||||
return sRoutingCoordinatorManager;
|
||||
}
|
||||
return mService.getRoutingCoordinatorService();
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ package android.net.connectivity;
|
|||
|
||||
import android.content.Context;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.RoutingCoordinatorManager;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
|
||||
|
|
@ -54,8 +53,8 @@ public class ConnectivityInternalApiUtil {
|
|||
* @return an instance of the coordinator manager
|
||||
*/
|
||||
@RequiresApi(Build.VERSION_CODES.S)
|
||||
public static RoutingCoordinatorManager getRoutingCoordinatorManager(Context ctx) {
|
||||
public static IBinder getRoutingCoordinator(Context ctx) {
|
||||
final ConnectivityManager cm = ctx.getSystemService(ConnectivityManager.class);
|
||||
return cm.getRoutingCoordinatorManager();
|
||||
return cm.getRoutingCoordinatorService();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -329,6 +329,7 @@ import com.android.net.module.util.InterfaceParams;
|
|||
import com.android.net.module.util.LinkPropertiesUtils.CompareOrUpdateResult;
|
||||
import com.android.net.module.util.LinkPropertiesUtils.CompareResult;
|
||||
import com.android.net.module.util.LocationPermissionChecker;
|
||||
import com.android.net.module.util.RoutingCoordinatorService;
|
||||
import com.android.net.module.util.PerUidCounter;
|
||||
import com.android.net.module.util.PermissionUtils;
|
||||
import com.android.net.module.util.TcUtils;
|
||||
|
|
@ -368,7 +369,6 @@ import com.android.server.connectivity.PermissionMonitor;
|
|||
import com.android.server.connectivity.ProfileNetworkPreferenceInfo;
|
||||
import com.android.server.connectivity.ProxyTracker;
|
||||
import com.android.server.connectivity.QosCallbackTracker;
|
||||
import com.android.server.connectivity.RoutingCoordinatorService;
|
||||
import com.android.server.connectivity.SatelliteAccessController;
|
||||
import com.android.server.connectivity.UidRangeUtils;
|
||||
import com.android.server.connectivity.VpnNetworkPreferenceInfo;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Copyright (C) 2023 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.net.module.util;
|
||||
|
||||
import android.net.RouteInfo;
|
||||
|
||||
/** @hide */
|
||||
// TODO: b/350630377 - This @Descriptor annotation workaround is to prevent the DESCRIPTOR from
|
||||
// being jarjared which changes the DESCRIPTOR and casues "java.lang.SecurityException: Binder
|
||||
// invocation to an incorrect interface" when calling the IPC.
|
||||
@Descriptor("value=no.jarjar.com.android.net.module.util.IRoutingCoordinator")
|
||||
interface IRoutingCoordinator {
|
||||
/**
|
||||
* Add a route for specific network
|
||||
*
|
||||
* @param netId the network to add the route to
|
||||
* @param route the route to add
|
||||
* @throws ServiceSpecificException in case of failure, with an error code indicating the
|
||||
* cause of the failure.
|
||||
*/
|
||||
void addRoute(int netId, in RouteInfo route);
|
||||
|
||||
/**
|
||||
* Remove a route for specific network
|
||||
*
|
||||
* @param netId the network to remove the route from
|
||||
* @param route the route to remove
|
||||
* @throws ServiceSpecificException in case of failure, with an error code indicating the
|
||||
* cause of the failure.
|
||||
*/
|
||||
void removeRoute(int netId, in RouteInfo route);
|
||||
|
||||
/**
|
||||
* Update a route for specific network
|
||||
*
|
||||
* @param netId the network to update the route for
|
||||
* @param route parcelable with route information
|
||||
* @throws ServiceSpecificException in case of failure, with an error code indicating the
|
||||
* cause of the failure.
|
||||
*/
|
||||
void updateRoute(int netId, in RouteInfo route);
|
||||
|
||||
/**
|
||||
* Adds an interface to a network. The interface must not be assigned to any network, including
|
||||
* the specified network.
|
||||
*
|
||||
* @param netId the network to add the interface to.
|
||||
* @param iface the name of the interface to add.
|
||||
*
|
||||
* @throws ServiceSpecificException in case of failure, with an error code corresponding to the
|
||||
* unix errno.
|
||||
*/
|
||||
void addInterfaceToNetwork(int netId, in String iface);
|
||||
|
||||
/**
|
||||
* Removes an interface from a network. The interface must be assigned to the specified network.
|
||||
*
|
||||
* @param netId the network to remove the interface from.
|
||||
* @param iface the name of the interface to remove.
|
||||
*
|
||||
* @throws ServiceSpecificException in case of failure, with an error code corresponding to the
|
||||
* unix errno.
|
||||
*/
|
||||
void removeInterfaceFromNetwork(int netId, in String iface);
|
||||
|
||||
/**
|
||||
* Add forwarding ip rule
|
||||
*
|
||||
* @param fromIface interface name to add forwarding ip rule
|
||||
* @param toIface interface name to add forwarding ip rule
|
||||
* @throws ServiceSpecificException in case of failure, with an error code indicating the
|
||||
* cause of the failure.
|
||||
*/
|
||||
void addInterfaceForward(in String fromIface, in String toIface);
|
||||
|
||||
/**
|
||||
* Remove forwarding ip rule
|
||||
*
|
||||
* @param fromIface interface name to remove forwarding ip rule
|
||||
* @param toIface interface name to remove forwarding ip rule
|
||||
* @throws ServiceSpecificException in case of failure, with an error code indicating the
|
||||
* cause of the failure.
|
||||
*/
|
||||
void removeInterfaceForward(in String fromIface, in String toIface);
|
||||
}
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* Copyright (C) 2023 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.net.module.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.RouteInfo;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
/**
|
||||
* A manager class for talking to the routing coordinator service.
|
||||
*
|
||||
* This class should only be used by the connectivity and tethering module. This is enforced
|
||||
* by the build rules. Do not change build rules to gain access to this class from elsewhere.
|
||||
* @hide
|
||||
*/
|
||||
@RequiresApi(Build.VERSION_CODES.S)
|
||||
public class RoutingCoordinatorManager {
|
||||
@NonNull final Context mContext;
|
||||
@NonNull final IRoutingCoordinator mService;
|
||||
|
||||
public RoutingCoordinatorManager(@NonNull final Context context,
|
||||
@NonNull final IBinder binder) {
|
||||
mContext = context;
|
||||
mService = IRoutingCoordinator.Stub.asInterface(binder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a route for specific network
|
||||
*
|
||||
* @param netId the network to add the route to
|
||||
* @param route the route to add
|
||||
* @throws ServiceSpecificException in case of failure, with an error code indicating the
|
||||
* cause of the failure.
|
||||
*/
|
||||
public void addRoute(final int netId, final RouteInfo route) {
|
||||
try {
|
||||
mService.addRoute(netId, route);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a route for specific network
|
||||
*
|
||||
* @param netId the network to remove the route from
|
||||
* @param route the route to remove
|
||||
* @throws ServiceSpecificException in case of failure, with an error code indicating the
|
||||
* cause of the failure.
|
||||
*/
|
||||
public void removeRoute(final int netId, final RouteInfo route) {
|
||||
try {
|
||||
mService.removeRoute(netId, route);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a route for specific network
|
||||
*
|
||||
* @param netId the network to update the route for
|
||||
* @param route parcelable with route information
|
||||
* @throws ServiceSpecificException in case of failure, with an error code indicating the
|
||||
* cause of the failure.
|
||||
*/
|
||||
public void updateRoute(final int netId, final RouteInfo route) {
|
||||
try {
|
||||
mService.updateRoute(netId, route);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an interface to a network. The interface must not be assigned to any network, including
|
||||
* the specified network.
|
||||
*
|
||||
* @param netId the network to add the interface to.
|
||||
* @param iface the name of the interface to add.
|
||||
*
|
||||
* @throws ServiceSpecificException in case of failure, with an error code corresponding to the
|
||||
* unix errno.
|
||||
*/
|
||||
public void addInterfaceToNetwork(final int netId, final String iface) {
|
||||
try {
|
||||
mService.addInterfaceToNetwork(netId, iface);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an interface from a network. The interface must be assigned to the specified network.
|
||||
*
|
||||
* @param netId the network to remove the interface from.
|
||||
* @param iface the name of the interface to remove.
|
||||
*
|
||||
* @throws ServiceSpecificException in case of failure, with an error code corresponding to the
|
||||
* unix errno.
|
||||
*/
|
||||
public void removeInterfaceFromNetwork(final int netId, final String iface) {
|
||||
try {
|
||||
mService.removeInterfaceFromNetwork(netId, iface);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add forwarding ip rule
|
||||
*
|
||||
* @param fromIface interface name to add forwarding ip rule
|
||||
* @param toIface interface name to add forwarding ip rule
|
||||
* @throws ServiceSpecificException in case of failure, with an error code indicating the
|
||||
* cause of the failure.
|
||||
*/
|
||||
public void addInterfaceForward(final String fromIface, final String toIface) {
|
||||
try {
|
||||
mService.addInterfaceForward(fromIface, toIface);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove forwarding ip rule
|
||||
*
|
||||
* @param fromIface interface name to remove forwarding ip rule
|
||||
* @param toIface interface name to remove forwarding ip rule
|
||||
* @throws ServiceSpecificException in case of failure, with an error code indicating the
|
||||
* cause of the failure.
|
||||
*/
|
||||
public void removeInterfaceForward(final String fromIface, final String toIface) {
|
||||
try {
|
||||
mService.removeInterfaceForward(fromIface, toIface);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,228 @@
|
|||
/*
|
||||
* Copyright (C) 2023 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.net.module.util;
|
||||
|
||||
import static com.android.net.module.util.NetdUtils.toRouteInfoParcel;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.net.INetd;
|
||||
|
||||
import android.net.RouteInfo;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceSpecificException;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Class to coordinate routing across multiple clients.
|
||||
*
|
||||
* At present this is just a wrapper for netd methods, but it will be used to host some more
|
||||
* coordination logic in the near future. It can be used to pull up some of the routing logic
|
||||
* from netd into Java land.
|
||||
*
|
||||
* Note that usage of this class is not thread-safe. Clients are responsible for their own
|
||||
* synchronization.
|
||||
*/
|
||||
public class RoutingCoordinatorService extends IRoutingCoordinator.Stub {
|
||||
private static final String TAG = RoutingCoordinatorService.class.getSimpleName();
|
||||
private final INetd mNetd;
|
||||
|
||||
public RoutingCoordinatorService(@NonNull INetd netd) {
|
||||
mNetd = netd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a route for specific network
|
||||
*
|
||||
* @param netId the network to add the route to
|
||||
* @param route the route to add
|
||||
* @throws ServiceSpecificException in case of failure, with an error code indicating the
|
||||
* cause of the failure.
|
||||
*/
|
||||
@Override
|
||||
public void addRoute(final int netId, final RouteInfo route)
|
||||
throws ServiceSpecificException, RemoteException {
|
||||
mNetd.networkAddRouteParcel(netId, toRouteInfoParcel(route));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a route for specific network
|
||||
*
|
||||
* @param netId the network to remove the route from
|
||||
* @param route the route to remove
|
||||
* @throws ServiceSpecificException in case of failure, with an error code indicating the
|
||||
* cause of the failure.
|
||||
*/
|
||||
@Override
|
||||
public void removeRoute(final int netId, final RouteInfo route)
|
||||
throws ServiceSpecificException, RemoteException {
|
||||
mNetd.networkRemoveRouteParcel(netId, toRouteInfoParcel(route));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a route for specific network
|
||||
*
|
||||
* @param netId the network to update the route for
|
||||
* @param route parcelable with route information
|
||||
* @throws ServiceSpecificException in case of failure, with an error code indicating the
|
||||
* cause of the failure.
|
||||
*/
|
||||
@Override
|
||||
public void updateRoute(final int netId, final RouteInfo route)
|
||||
throws ServiceSpecificException, RemoteException {
|
||||
mNetd.networkUpdateRouteParcel(netId, toRouteInfoParcel(route));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an interface to a network. The interface must not be assigned to any network, including
|
||||
* the specified network.
|
||||
*
|
||||
* @param netId the network to add the interface to.
|
||||
* @param iface the name of the interface to add.
|
||||
*
|
||||
* @throws ServiceSpecificException in case of failure, with an error code corresponding to the
|
||||
* unix errno.
|
||||
*/
|
||||
@Override
|
||||
public void addInterfaceToNetwork(final int netId, final String iface)
|
||||
throws ServiceSpecificException, RemoteException {
|
||||
mNetd.networkAddInterface(netId, iface);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an interface from a network. The interface must be assigned to the specified network.
|
||||
*
|
||||
* @param netId the network to remove the interface from.
|
||||
* @param iface the name of the interface to remove.
|
||||
*
|
||||
* @throws ServiceSpecificException in case of failure, with an error code corresponding to the
|
||||
* unix errno.
|
||||
*/
|
||||
@Override
|
||||
public void removeInterfaceFromNetwork(final int netId, final String iface)
|
||||
throws ServiceSpecificException, RemoteException {
|
||||
mNetd.networkRemoveInterface(netId, iface);
|
||||
}
|
||||
|
||||
private final Object mIfacesLock = new Object();
|
||||
private static final class ForwardingPair {
|
||||
@NonNull public final String fromIface;
|
||||
@NonNull public final String toIface;
|
||||
ForwardingPair(@NonNull final String fromIface, @NonNull final String toIface) {
|
||||
this.fromIface = fromIface;
|
||||
this.toIface = toIface;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof ForwardingPair)) return false;
|
||||
|
||||
final ForwardingPair that = (ForwardingPair) o;
|
||||
|
||||
return fromIface.equals(that.fromIface) && toIface.equals(that.toIface);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = fromIface.hashCode();
|
||||
result = 2 * result + toIface.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy("mIfacesLock")
|
||||
private final ArraySet<ForwardingPair> mForwardedInterfaces = new ArraySet<>();
|
||||
|
||||
/**
|
||||
* Add forwarding ip rule
|
||||
*
|
||||
* @param fromIface interface name to add forwarding ip rule
|
||||
* @param toIface interface name to add forwarding ip rule
|
||||
* @throws ServiceSpecificException in case of failure, with an error code indicating the
|
||||
* cause of the failure.
|
||||
*/
|
||||
public void addInterfaceForward(final String fromIface, final String toIface)
|
||||
throws ServiceSpecificException, RemoteException {
|
||||
Objects.requireNonNull(fromIface);
|
||||
Objects.requireNonNull(toIface);
|
||||
Log.i(TAG, "Adding interface forward " + fromIface + " → " + toIface);
|
||||
synchronized (mIfacesLock) {
|
||||
if (mForwardedInterfaces.size() == 0) {
|
||||
mNetd.ipfwdEnableForwarding("RoutingCoordinator");
|
||||
}
|
||||
final ForwardingPair fwp = new ForwardingPair(fromIface, toIface);
|
||||
if (mForwardedInterfaces.contains(fwp)) {
|
||||
// TODO: remove if no reports are observed from the below log
|
||||
Log.wtf(TAG, "Forward already exists between ifaces "
|
||||
+ fromIface + " → " + toIface);
|
||||
}
|
||||
mForwardedInterfaces.add(fwp);
|
||||
// Enables NAT for v4 and filters packets from unknown interfaces
|
||||
mNetd.tetherAddForward(fromIface, toIface);
|
||||
mNetd.ipfwdAddInterfaceForward(fromIface, toIface);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove forwarding ip rule
|
||||
*
|
||||
* @param fromIface interface name to remove forwarding ip rule
|
||||
* @param toIface interface name to remove forwarding ip rule
|
||||
* @throws ServiceSpecificException in case of failure, with an error code indicating the
|
||||
* cause of the failure.
|
||||
*/
|
||||
public void removeInterfaceForward(final String fromIface, final String toIface)
|
||||
throws ServiceSpecificException, RemoteException {
|
||||
Objects.requireNonNull(fromIface);
|
||||
Objects.requireNonNull(toIface);
|
||||
Log.i(TAG, "Removing interface forward " + fromIface + " → " + toIface);
|
||||
synchronized (mIfacesLock) {
|
||||
final ForwardingPair fwp = new ForwardingPair(fromIface, toIface);
|
||||
if (!mForwardedInterfaces.contains(fwp)) {
|
||||
// This can happen when an upstream was unregisteredAfterReplacement. The forward
|
||||
// is removed immediately when the upstream is destroyed, but later when the
|
||||
// network actually disconnects CS does not know that and it asks for removal
|
||||
// again.
|
||||
// This can also happen if the network was destroyed before being set as an
|
||||
// upstream, because then CS does not set up the forward rules seeing how the
|
||||
// interface was removed anyway.
|
||||
// Either way, this is benign.
|
||||
Log.i(TAG, "No forward set up between interfaces " + fromIface + " → " + toIface);
|
||||
return;
|
||||
}
|
||||
mForwardedInterfaces.remove(fwp);
|
||||
try {
|
||||
mNetd.ipfwdRemoveInterfaceForward(fromIface, toIface);
|
||||
} catch (RemoteException | ServiceSpecificException e) {
|
||||
Log.e(TAG, "Exception in ipfwdRemoveInterfaceForward", e);
|
||||
}
|
||||
try {
|
||||
mNetd.tetherRemoveForward(fromIface, toIface);
|
||||
} catch (RemoteException | ServiceSpecificException e) {
|
||||
Log.e(TAG, "Exception in tetherRemoveForward", e);
|
||||
}
|
||||
if (mForwardedInterfaces.size() == 0) {
|
||||
mNetd.ipfwdDisableForwarding("RoutingCoordinator");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -27,6 +27,7 @@ android_library {
|
|||
"net-utils-device-common-ip",
|
||||
"net-utils-device-common-struct-base",
|
||||
"net-utils-device-common-wear",
|
||||
"net-utils-service-connectivity",
|
||||
],
|
||||
libs: [
|
||||
"android.test.runner",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright (C) 2023 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.net.module.util
|
||||
|
||||
import android.net.INetd
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
|
||||
import com.android.testutils.DevSdkIgnoreRunner
|
||||
import com.android.testutils.tryTest
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import kotlin.test.assertTrue
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.ArgumentMatchers.any
|
||||
import org.mockito.Mockito.inOrder
|
||||
import org.mockito.Mockito.mock
|
||||
|
||||
@RunWith(DevSdkIgnoreRunner::class)
|
||||
@IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
|
||||
class RoutingCoordinatorServiceTest {
|
||||
val mNetd = mock(INetd::class.java)
|
||||
val mService = RoutingCoordinatorService(mNetd)
|
||||
|
||||
@Test
|
||||
fun testInterfaceForward() {
|
||||
val inOrder = inOrder(mNetd)
|
||||
|
||||
mService.addInterfaceForward("from1", "to1")
|
||||
inOrder.verify(mNetd).ipfwdEnableForwarding(any())
|
||||
inOrder.verify(mNetd).tetherAddForward("from1", "to1")
|
||||
inOrder.verify(mNetd).ipfwdAddInterfaceForward("from1", "to1")
|
||||
|
||||
mService.addInterfaceForward("from2", "to1")
|
||||
inOrder.verify(mNetd).tetherAddForward("from2", "to1")
|
||||
inOrder.verify(mNetd).ipfwdAddInterfaceForward("from2", "to1")
|
||||
|
||||
val hasFailed = AtomicBoolean(false)
|
||||
val prevHandler = Log.setWtfHandler { tag, what, system ->
|
||||
hasFailed.set(true)
|
||||
}
|
||||
tryTest {
|
||||
mService.addInterfaceForward("from2", "to1")
|
||||
assertTrue(hasFailed.get())
|
||||
} cleanup {
|
||||
Log.setWtfHandler(prevHandler)
|
||||
}
|
||||
|
||||
mService.removeInterfaceForward("from1", "to1")
|
||||
inOrder.verify(mNetd).ipfwdRemoveInterfaceForward("from1", "to1")
|
||||
inOrder.verify(mNetd).tetherRemoveForward("from1", "to1")
|
||||
|
||||
mService.removeInterfaceForward("from2", "to1")
|
||||
inOrder.verify(mNetd).ipfwdRemoveInterfaceForward("from2", "to1")
|
||||
inOrder.verify(mNetd).tetherRemoveForward("from2", "to1")
|
||||
|
||||
inOrder.verify(mNetd).ipfwdDisableForwarding(any())
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue