Add a routing coordinator class
Test: In followup changes : RoutingCoordinatorManagerTest Change-Id: Ia6811d614e02123a072c7638291828745abae051
This commit is contained in:
@@ -44,6 +44,7 @@ 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.TetheringRequestParcel;
|
||||
@@ -71,6 +72,7 @@ import com.android.internal.util.StateMachine;
|
||||
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.SdkUtil.LateSdk;
|
||||
import com.android.net.module.util.SharedLog;
|
||||
import com.android.net.module.util.ip.InterfaceController;
|
||||
import com.android.net.module.util.ip.IpNeighborMonitor;
|
||||
@@ -245,6 +247,11 @@ public class IpServer extends StateMachine {
|
||||
private final INetd mNetd;
|
||||
@NonNull
|
||||
private final BpfCoordinator mBpfCoordinator;
|
||||
// Contains null if the connectivity module is unsupported, as the routing coordinator is not
|
||||
// available. Must use LateSdk because MessageUtils enumerates fields in this class, so it
|
||||
// must be able to find all classes at runtime.
|
||||
@NonNull
|
||||
private final LateSdk<RoutingCoordinatorManager> mRoutingCoordinator;
|
||||
private final Callback mCallback;
|
||||
private final InterfaceController mInterfaceCtrl;
|
||||
private final PrivateAddressCoordinator mPrivateAddressCoordinator;
|
||||
@@ -307,13 +314,15 @@ public class IpServer extends StateMachine {
|
||||
// object. It helps to reduce the arguments of the constructor.
|
||||
public IpServer(
|
||||
String ifaceName, Looper looper, int interfaceType, SharedLog log,
|
||||
INetd netd, @NonNull BpfCoordinator coordinator, Callback callback,
|
||||
INetd netd, @NonNull BpfCoordinator bpfCoordinator,
|
||||
@Nullable LateSdk<RoutingCoordinatorManager> routingCoordinator, Callback callback,
|
||||
TetheringConfiguration config, PrivateAddressCoordinator addressCoordinator,
|
||||
TetheringMetrics tetheringMetrics, Dependencies deps) {
|
||||
super(ifaceName, looper);
|
||||
mLog = log.forSubComponent(ifaceName);
|
||||
mNetd = netd;
|
||||
mBpfCoordinator = coordinator;
|
||||
mBpfCoordinator = bpfCoordinator;
|
||||
mRoutingCoordinator = routingCoordinator;
|
||||
mCallback = callback;
|
||||
mInterfaceCtrl = new InterfaceController(ifaceName, mNetd, mLog);
|
||||
mIfaceName = ifaceName;
|
||||
@@ -807,23 +816,33 @@ public class IpServer extends StateMachine {
|
||||
for (RouteInfo route : toBeRemoved) mLinkProperties.removeRoute(route);
|
||||
}
|
||||
|
||||
private void addRoutesToLocalNetwork(@NonNull final List<RouteInfo> toBeAdded) {
|
||||
private void addInterfaceToNetwork(final int netId, @NonNull final String ifaceName) {
|
||||
try {
|
||||
// It's safe to call networkAddInterface() even if
|
||||
// the interface is already in the local_network.
|
||||
mNetd.networkAddInterface(INetd.LOCAL_NET_ID, mIfaceName);
|
||||
try {
|
||||
// Add routes from local network. Note that adding routes that
|
||||
// already exist does not cause an error (EEXIST is silently ignored).
|
||||
NetdUtils.addRoutesToLocalNetwork(mNetd, mIfaceName, toBeAdded);
|
||||
} catch (IllegalStateException e) {
|
||||
mLog.e("Failed to add IPv4/v6 routes to local table: " + e);
|
||||
return;
|
||||
if (null != mRoutingCoordinator.value) {
|
||||
// TODO : remove this call in favor of using the LocalNetworkConfiguration
|
||||
// correctly, which will let ConnectivityService do it automatically.
|
||||
mRoutingCoordinator.value.addInterfaceToNetwork(netId, ifaceName);
|
||||
} else {
|
||||
mNetd.networkAddInterface(netId, ifaceName);
|
||||
}
|
||||
} catch (ServiceSpecificException | RemoteException e) {
|
||||
mLog.e("Failed to add " + mIfaceName + " to local table: ", e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void addRoutesToLocalNetwork(@NonNull final List<RouteInfo> toBeAdded) {
|
||||
// It's safe to call addInterfaceToNetwork() even if
|
||||
// the interface is already in the local_network.
|
||||
addInterfaceToNetwork(INetd.LOCAL_NET_ID, mIfaceName);
|
||||
try {
|
||||
// Add routes from local network. Note that adding routes that
|
||||
// already exist does not cause an error (EEXIST is silently ignored).
|
||||
NetdUtils.addRoutesToLocalNetwork(mNetd, mIfaceName, toBeAdded);
|
||||
} catch (IllegalStateException e) {
|
||||
mLog.e("Failed to add IPv4/v6 routes to local table: " + e);
|
||||
return;
|
||||
}
|
||||
|
||||
for (RouteInfo route : toBeAdded) mLinkProperties.addRoute(route);
|
||||
}
|
||||
|
||||
@@ -90,6 +90,7 @@ 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;
|
||||
@@ -136,6 +137,7 @@ import com.android.modules.utils.build.SdkLevel;
|
||||
import com.android.net.module.util.BaseNetdUnsolicitedEventListener;
|
||||
import com.android.net.module.util.CollectionUtils;
|
||||
import com.android.net.module.util.NetdUtils;
|
||||
import com.android.net.module.util.SdkUtil.LateSdk;
|
||||
import com.android.net.module.util.SharedLog;
|
||||
import com.android.networkstack.apishim.common.BluetoothPanShim;
|
||||
import com.android.networkstack.apishim.common.BluetoothPanShim.TetheredInterfaceCallbackShim;
|
||||
@@ -250,6 +252,10 @@ public class Tethering {
|
||||
private final Handler mHandler;
|
||||
private final INetd mNetd;
|
||||
private final NetdCallback mNetdCallback;
|
||||
// Contains null if the connectivity module is unsupported, as the routing coordinator is not
|
||||
// available. Must use LateSdk because MessageUtils enumerates fields in this class, so it
|
||||
// must be able to find all classes at runtime.
|
||||
@NonNull private final LateSdk<RoutingCoordinatorManager> mRoutingCoordinator;
|
||||
private final UserRestrictionActionListener mTetheringRestriction;
|
||||
private final ActiveDataSubIdListener mActiveDataSubIdListener;
|
||||
private final ConnectedClientsTracker mConnectedClientsTracker;
|
||||
@@ -296,6 +302,7 @@ public class Tethering {
|
||||
mDeps = deps;
|
||||
mContext = mDeps.getContext();
|
||||
mNetd = mDeps.getINetd(mContext);
|
||||
mRoutingCoordinator = mDeps.getRoutingCoordinator(mContext);
|
||||
mLooper = mDeps.getTetheringLooper();
|
||||
mNotificationUpdater = mDeps.getNotificationUpdater(mContext, mLooper);
|
||||
mTetheringMetrics = mDeps.getTetheringMetrics();
|
||||
@@ -2835,8 +2842,9 @@ public class Tethering {
|
||||
mLog.i("adding IpServer for: " + iface);
|
||||
final TetherState tetherState = new TetherState(
|
||||
new IpServer(iface, mLooper, interfaceType, mLog, mNetd, mBpfCoordinator,
|
||||
makeControlCallback(), mConfig, mPrivateAddressCoordinator,
|
||||
mTetheringMetrics, mDeps.getIpServerDependencies()), isNcm);
|
||||
mRoutingCoordinator, makeControlCallback(), mConfig,
|
||||
mPrivateAddressCoordinator, mTetheringMetrics,
|
||||
mDeps.getIpServerDependencies()), isNcm);
|
||||
mTetherStates.put(iface, tetherState);
|
||||
tetherState.ipServer.start();
|
||||
}
|
||||
|
||||
@@ -16,11 +16,14 @@
|
||||
|
||||
package com.android.networkstack.tethering;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.usage.NetworkStatsManager;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothPan;
|
||||
import android.content.Context;
|
||||
import android.net.INetd;
|
||||
import android.net.RoutingCoordinatorManager;
|
||||
import android.net.connectivity.TiramisuConnectivityInternalApiUtil;
|
||||
import android.net.ip.IpServer;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
@@ -33,6 +36,8 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import com.android.internal.util.StateMachine;
|
||||
import com.android.modules.utils.build.SdkLevel;
|
||||
import com.android.net.module.util.SdkUtil.LateSdk;
|
||||
import com.android.net.module.util.SharedLog;
|
||||
import com.android.networkstack.apishim.BluetoothPanShimImpl;
|
||||
import com.android.networkstack.apishim.common.BluetoothPanShim;
|
||||
@@ -121,6 +126,16 @@ public abstract class TetheringDependencies {
|
||||
(IBinder) context.getSystemService(Context.NETD_SERVICE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the routing coordinator, or null if below S.
|
||||
*/
|
||||
@Nullable
|
||||
public LateSdk<RoutingCoordinatorManager> getRoutingCoordinator(Context context) {
|
||||
if (!SdkLevel.isAtLeastS()) return new LateSdk<>(null);
|
||||
return new LateSdk<>(
|
||||
TiramisuConnectivityInternalApiUtil.getRoutingCoordinatorManager(context));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a reference to the TetheringNotificationUpdater to be used by tethering.
|
||||
*/
|
||||
@@ -135,7 +150,7 @@ public abstract class TetheringDependencies {
|
||||
public abstract Looper getTetheringLooper();
|
||||
|
||||
/**
|
||||
* Get Context of TetheringSerice.
|
||||
* Get Context of TetheringService.
|
||||
*/
|
||||
public abstract Context getContext();
|
||||
|
||||
|
||||
@@ -62,6 +62,7 @@ import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.inOrder;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.spy;
|
||||
@@ -80,6 +81,7 @@ import android.net.LinkAddress;
|
||||
import android.net.LinkProperties;
|
||||
import android.net.MacAddress;
|
||||
import android.net.RouteInfo;
|
||||
import android.net.RoutingCoordinatorManager;
|
||||
import android.net.TetherOffloadRuleParcel;
|
||||
import android.net.TetherStatsParcel;
|
||||
import android.net.dhcp.DhcpServerCallbacks;
|
||||
@@ -99,9 +101,11 @@ import androidx.annotation.Nullable;
|
||||
import androidx.test.filters.SmallTest;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.modules.utils.build.SdkLevel;
|
||||
import com.android.net.module.util.BpfMap;
|
||||
import com.android.net.module.util.InterfaceParams;
|
||||
import com.android.net.module.util.NetworkStackConstants;
|
||||
import com.android.net.module.util.SdkUtil.LateSdk;
|
||||
import com.android.net.module.util.SharedLog;
|
||||
import com.android.net.module.util.Struct.S32;
|
||||
import com.android.net.module.util.bpf.Tether4Key;
|
||||
@@ -193,6 +197,8 @@ public class IpServerTest {
|
||||
@Mock private IpNeighborMonitor mIpNeighborMonitor;
|
||||
@Mock private IpServer.Dependencies mDependencies;
|
||||
@Mock private PrivateAddressCoordinator mAddressCoordinator;
|
||||
private final LateSdk<RoutingCoordinatorManager> mRoutingCoordinatorManager =
|
||||
new LateSdk<>(SdkLevel.isAtLeastS() ? mock(RoutingCoordinatorManager.class) : null);
|
||||
@Mock private NetworkStatsManager mStatsManager;
|
||||
@Mock private TetheringConfiguration mTetherConfig;
|
||||
@Mock private ConntrackMonitor mConntrackMonitor;
|
||||
@@ -249,7 +255,8 @@ public class IpServerTest {
|
||||
mBpfCoordinator = spy(new BpfCoordinator(mBpfDeps));
|
||||
mIpServer = new IpServer(
|
||||
IFACE_NAME, mLooper.getLooper(), interfaceType, mSharedLog, mNetd, mBpfCoordinator,
|
||||
mCallback, mTetherConfig, mAddressCoordinator, mTetheringMetrics, mDependencies);
|
||||
mRoutingCoordinatorManager, mCallback, mTetherConfig, mAddressCoordinator,
|
||||
mTetheringMetrics, mDependencies);
|
||||
mIpServer.start();
|
||||
mNeighborEventConsumer = neighborCaptor.getValue();
|
||||
|
||||
@@ -396,8 +403,8 @@ public class IpServerTest {
|
||||
when(mDependencies.getIpNeighborMonitor(any(), any(), any()))
|
||||
.thenReturn(mIpNeighborMonitor);
|
||||
mIpServer = new IpServer(IFACE_NAME, mLooper.getLooper(), TETHERING_BLUETOOTH, mSharedLog,
|
||||
mNetd, mBpfCoordinator, mCallback, mTetherConfig, mAddressCoordinator,
|
||||
mTetheringMetrics, mDependencies);
|
||||
mNetd, mBpfCoordinator, mRoutingCoordinatorManager, mCallback, mTetherConfig,
|
||||
mAddressCoordinator, mTetheringMetrics, mDependencies);
|
||||
mIpServer.start();
|
||||
mLooper.dispatchAll();
|
||||
verify(mCallback).updateInterfaceState(
|
||||
|
||||
@@ -142,6 +142,7 @@ 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 +192,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.SdkUtil.LateSdk;
|
||||
import com.android.net.module.util.SharedLog;
|
||||
import com.android.net.module.util.ip.IpNeighborMonitor;
|
||||
import com.android.networkstack.apishim.common.BluetoothPanShim;
|
||||
@@ -482,6 +484,12 @@ public class TetheringTest {
|
||||
return mEntitleMgr;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public LateSdk<RoutingCoordinatorManager> getRoutingCoordinator(final Context context) {
|
||||
return new LateSdk<>(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TetheringConfiguration generateTetheringConfiguration(Context ctx, SharedLog log,
|
||||
int subId) {
|
||||
|
||||
@@ -292,17 +292,20 @@ java_genrule {
|
||||
// Library providing limited APIs within the connectivity module, so that R+ components like
|
||||
// Tethering have a controlled way to depend on newer components like framework-connectivity that
|
||||
// are not loaded on R.
|
||||
// Note that this target needs to have access to hidden classes, and as such needs to list
|
||||
// the full libraries instead of the .impl lib (which only expose API classes).
|
||||
java_library {
|
||||
name: "connectivity-internal-api-util",
|
||||
sdk_version: "module_current",
|
||||
libs: [
|
||||
"androidx.annotation_annotation",
|
||||
"framework-connectivity.impl",
|
||||
"framework-connectivity-pre-jarjar",
|
||||
],
|
||||
jarjar_rules: ":framework-connectivity-jarjar-rules",
|
||||
srcs: [
|
||||
// Files listed here MUST all be annotated with @RequiresApi(Build.VERSION_CODES.TIRAMISU),
|
||||
// so that API checks are enforced for R+ users of this library
|
||||
// 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/TiramisuConnectivityInternalApiUtil.java",
|
||||
],
|
||||
visibility: [
|
||||
|
||||
@@ -14,6 +14,15 @@ android\.net\.INetworkAgentRegistry(\$.+)?
|
||||
# TODO: move files to android.net.connectivity.visiblefortesting
|
||||
android\.net\.IConnectivityDiagnosticsCallback(\$.+)?
|
||||
|
||||
# Classes used by tethering as a hidden API are compiled as a lib in target
|
||||
# connectivity-internal-api-util. Because it's used by tethering, it can't
|
||||
# be jarjared. Classes in android.net.connectivity are exempt from being
|
||||
# listed here because they are already in the target package and as such
|
||||
# are already not jarjared.
|
||||
# Because Tethering can be installed on R without Connectivity, any use
|
||||
# of these classes must be protected by a check for >= S SDK.
|
||||
# It's unlikely anybody else declares a hidden class with this name ?
|
||||
android\.net\.RoutingCoordinatorManager(\$.+)?
|
||||
|
||||
# KeepaliveUtils is used by ConnectivityManager CTS
|
||||
# TODO: move into service-connectivity so framework-connectivity stops using
|
||||
|
||||
@@ -29,6 +29,7 @@ import android.annotation.CallbackExecutor;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.RequiresApi;
|
||||
import android.annotation.RequiresPermission;
|
||||
import android.annotation.SdkConstant;
|
||||
import android.annotation.SdkConstant.SdkConstantType;
|
||||
@@ -6174,4 +6175,24 @@ public class ConnectivityManager {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
private static final Object sRoutingCoordinatorManagerLock = new Object();
|
||||
@GuardedBy("sRoutingCoordinatorManagerLock")
|
||||
private static RoutingCoordinatorManager sRoutingCoordinatorManager = null;
|
||||
/** @hide */
|
||||
@RequiresApi(Build.VERSION_CODES.S)
|
||||
public RoutingCoordinatorManager getRoutingCoordinatorManager() {
|
||||
try {
|
||||
synchronized (sRoutingCoordinatorManagerLock) {
|
||||
if (null == sRoutingCoordinatorManager) {
|
||||
sRoutingCoordinatorManager = new RoutingCoordinatorManager(mContext,
|
||||
IRoutingCoordinator.Stub.asInterface(
|
||||
mService.getRoutingCoordinatorService()));
|
||||
}
|
||||
return sRoutingCoordinatorManager;
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,4 +259,6 @@ interface IConnectivityManager
|
||||
void setVpnNetworkPreference(String session, in UidRange[] ranges);
|
||||
|
||||
void setTestLowTcpPollingTimerForKeepalive(long timeMs);
|
||||
|
||||
IBinder getRoutingCoordinatorService();
|
||||
}
|
||||
|
||||
75
framework/src/android/net/IRoutingCoordinator.aidl
Normal file
75
framework/src/android/net/IRoutingCoordinator.aidl
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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 android.net;
|
||||
|
||||
import android.net.RouteInfo;
|
||||
|
||||
/** @hide */
|
||||
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);
|
||||
}
|
||||
@@ -584,7 +584,7 @@ public final class RouteInfo implements Parcelable {
|
||||
}
|
||||
RouteKey p = (RouteKey) o;
|
||||
// No need to do anything special for scoped addresses. Inet6Address#equals does not
|
||||
// consider the scope ID, but the netd route IPCs (e.g., INetd#networkAddRouteParcel)
|
||||
// consider the scope ID, but the route IPCs (e.g., RoutingCoordinatorManager#addRoute)
|
||||
// and the kernel ignore scoped addresses both in the prefix and in the nexthop and only
|
||||
// look at RTA_OIF.
|
||||
return Objects.equals(p.mDestination, mDestination)
|
||||
|
||||
126
framework/src/android/net/RoutingCoordinatorManager.java
Normal file
126
framework/src/android/net/RoutingCoordinatorManager.java
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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 android.net;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
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 IRoutingCoordinator service) {
|
||||
mContext = context;
|
||||
mService = service;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ package android.net.connectivity;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.RoutingCoordinatorManager;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
|
||||
@@ -34,15 +35,28 @@ import androidx.annotation.RequiresApi;
|
||||
* linter).
|
||||
* @hide
|
||||
*/
|
||||
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
||||
// TODO : rename this so that it doesn't reference "Tiramisu" since it can be used in S.
|
||||
@RequiresApi(Build.VERSION_CODES.S)
|
||||
public class TiramisuConnectivityInternalApiUtil {
|
||||
|
||||
/**
|
||||
* Get a service binder token for
|
||||
* {@link com.android.server.connectivity.wear.CompanionDeviceManagerProxyService}.
|
||||
*/
|
||||
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
||||
public static IBinder getCompanionDeviceManagerProxyService(Context ctx) {
|
||||
final ConnectivityManager cm = ctx.getSystemService(ConnectivityManager.class);
|
||||
return cm.getCompanionDeviceManagerProxyService();
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain a routing coordinator manager from a context, possibly cross-module.
|
||||
* @param ctx the context
|
||||
* @return an instance of the coordinator manager
|
||||
*/
|
||||
@RequiresApi(Build.VERSION_CODES.S)
|
||||
public static RoutingCoordinatorManager getRoutingCoordinatorManager(Context ctx) {
|
||||
final ConnectivityManager cm = ctx.getSystemService(ConnectivityManager.class);
|
||||
return cm.getRoutingCoordinatorManager();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,7 +199,6 @@ import android.net.QosFilter;
|
||||
import android.net.QosSocketFilter;
|
||||
import android.net.QosSocketInfo;
|
||||
import android.net.RouteInfo;
|
||||
import android.net.RouteInfoParcel;
|
||||
import android.net.SocketKeepalive;
|
||||
import android.net.TetheringManager;
|
||||
import android.net.TransportInfo;
|
||||
@@ -330,6 +329,7 @@ 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.UidRangeUtils;
|
||||
import com.android.server.connectivity.VpnNetworkPreferenceInfo;
|
||||
import com.android.server.connectivity.wear.CompanionDeviceManagerProxyService;
|
||||
@@ -493,6 +493,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
@GuardedBy("mTNSLock")
|
||||
private TestNetworkService mTNS;
|
||||
private final CompanionDeviceManagerProxyService mCdmps;
|
||||
private final RoutingCoordinatorService mRoutingCoordinatorService;
|
||||
|
||||
private final Object mTNSLock = new Object();
|
||||
|
||||
@@ -1826,6 +1827,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
mCdmps = null;
|
||||
}
|
||||
|
||||
mRoutingCoordinatorService = new RoutingCoordinatorService(netd);
|
||||
|
||||
mDestroyFrozenSockets = mDeps.isAtLeastU()
|
||||
&& mDeps.isFeatureEnabled(context, KEY_DESTROY_FROZEN_SOCKETS_VERSION);
|
||||
mDelayDestroyFrozenSockets = mDeps.isAtLeastU()
|
||||
@@ -8515,7 +8518,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
for (final String iface : interfaceDiff.added) {
|
||||
try {
|
||||
if (DBG) log("Adding iface " + iface + " to network " + netId);
|
||||
mNetd.networkAddInterface(netId, iface);
|
||||
mRoutingCoordinatorService.addInterfaceToNetwork(netId, iface);
|
||||
wakeupModifyInterface(iface, nai, true);
|
||||
mDeps.reportNetworkInterfaceForTransports(mContext, iface,
|
||||
nai.networkCapabilities.getTransportTypes());
|
||||
@@ -8528,45 +8531,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
try {
|
||||
if (DBG) log("Removing iface " + iface + " from network " + netId);
|
||||
wakeupModifyInterface(iface, nai, false);
|
||||
mNetd.networkRemoveInterface(netId, iface);
|
||||
mRoutingCoordinatorService.removeInterfaceFromNetwork(netId, iface);
|
||||
} catch (Exception e) {
|
||||
loge("Exception removing interface: " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: move to frameworks/libs/net.
|
||||
private RouteInfoParcel convertRouteInfo(RouteInfo route) {
|
||||
final String nextHop;
|
||||
|
||||
switch (route.getType()) {
|
||||
case RouteInfo.RTN_UNICAST:
|
||||
if (route.hasGateway()) {
|
||||
nextHop = route.getGateway().getHostAddress();
|
||||
} else {
|
||||
nextHop = INetd.NEXTHOP_NONE;
|
||||
}
|
||||
break;
|
||||
case RouteInfo.RTN_UNREACHABLE:
|
||||
nextHop = INetd.NEXTHOP_UNREACHABLE;
|
||||
break;
|
||||
case RouteInfo.RTN_THROW:
|
||||
nextHop = INetd.NEXTHOP_THROW;
|
||||
break;
|
||||
default:
|
||||
nextHop = INetd.NEXTHOP_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
final RouteInfoParcel rip = new RouteInfoParcel();
|
||||
rip.ifName = route.getInterface();
|
||||
rip.destination = route.getDestination().toString();
|
||||
rip.nextHop = nextHop;
|
||||
rip.mtu = route.getMtu();
|
||||
|
||||
return rip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Have netd update routes from oldLp to newLp.
|
||||
* @return true if routes changed between oldLp and newLp
|
||||
@@ -8587,10 +8558,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
if (route.hasGateway()) continue;
|
||||
if (VDBG || DDBG) log("Adding Route [" + route + "] to network " + netId);
|
||||
try {
|
||||
mNetd.networkAddRouteParcel(netId, convertRouteInfo(route));
|
||||
mRoutingCoordinatorService.addRoute(netId, route);
|
||||
} catch (Exception e) {
|
||||
if ((route.getDestination().getAddress() instanceof Inet4Address) || VDBG) {
|
||||
loge("Exception in networkAddRouteParcel for non-gateway: " + e);
|
||||
loge("Exception in addRoute for non-gateway: " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8598,10 +8569,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
if (!route.hasGateway()) continue;
|
||||
if (VDBG || DDBG) log("Adding Route [" + route + "] to network " + netId);
|
||||
try {
|
||||
mNetd.networkAddRouteParcel(netId, convertRouteInfo(route));
|
||||
mRoutingCoordinatorService.addRoute(netId, route);
|
||||
} catch (Exception e) {
|
||||
if ((route.getGateway() instanceof Inet4Address) || VDBG) {
|
||||
loge("Exception in networkAddRouteParcel for gateway: " + e);
|
||||
loge("Exception in addRoute for gateway: " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8609,18 +8580,18 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
for (RouteInfo route : routeDiff.removed) {
|
||||
if (VDBG || DDBG) log("Removing Route [" + route + "] from network " + netId);
|
||||
try {
|
||||
mNetd.networkRemoveRouteParcel(netId, convertRouteInfo(route));
|
||||
mRoutingCoordinatorService.removeRoute(netId, route);
|
||||
} catch (Exception e) {
|
||||
loge("Exception in networkRemoveRouteParcel: " + e);
|
||||
loge("Exception in removeRoute: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
for (RouteInfo route : routeDiff.updated) {
|
||||
if (VDBG || DDBG) log("Updating Route [" + route + "] from network " + netId);
|
||||
try {
|
||||
mNetd.networkUpdateRouteParcel(netId, convertRouteInfo(route));
|
||||
mRoutingCoordinatorService.updateRoute(netId, route);
|
||||
} catch (Exception e) {
|
||||
loge("Exception in networkUpdateRouteParcel: " + e);
|
||||
loge("Exception in updateRoute: " + e);
|
||||
}
|
||||
}
|
||||
return !routeDiff.added.isEmpty() || !routeDiff.removed.isEmpty()
|
||||
@@ -10261,7 +10232,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
// If a rate limit has been configured and is applicable to this network (network
|
||||
// provides internet connectivity), apply it. The tc police filter cannot be attached
|
||||
// before the clsact qdisc is added which happens as part of updateLinkProperties ->
|
||||
// updateInterfaces -> INetd#networkAddInterface.
|
||||
// updateInterfaces -> RoutingCoordinatorManager#addInterfaceToNetwork
|
||||
// Note: in case of a system server crash, the NetworkController constructor in netd
|
||||
// (called when netd starts up) deletes the clsact qdisc of all interfaces.
|
||||
if (canNetworkBeRateLimited(networkAgent) && mIngressRateLimit >= 0) {
|
||||
@@ -12740,4 +12711,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
enforceNetworkStackPermission(mContext);
|
||||
return mCdmps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder getRoutingCoordinatorService() {
|
||||
enforceNetworkStackPermission(mContext);
|
||||
return mRoutingCoordinatorService;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* 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.server.connectivity;
|
||||
|
||||
import static com.android.net.module.util.NetdUtils.toRouteInfoParcel;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.content.Context;
|
||||
import android.net.INetd;
|
||||
import android.net.IRoutingCoordinator;
|
||||
import android.net.RouteInfo;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceSpecificException;
|
||||
|
||||
/**
|
||||
* 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 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);
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import android.net.INetd;
|
||||
import android.net.InterfaceConfigurationParcel;
|
||||
import android.net.IpPrefix;
|
||||
import android.net.RouteInfo;
|
||||
import android.net.RouteInfoParcel;
|
||||
import android.net.TetherConfigParcel;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceSpecificException;
|
||||
@@ -278,4 +279,38 @@ public class NetdUtils {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a RouteInfo into a RouteInfoParcel.
|
||||
*/
|
||||
public static RouteInfoParcel toRouteInfoParcel(RouteInfo route) {
|
||||
final String nextHop;
|
||||
|
||||
switch (route.getType()) {
|
||||
case RouteInfo.RTN_UNICAST:
|
||||
if (route.hasGateway()) {
|
||||
nextHop = route.getGateway().getHostAddress();
|
||||
} else {
|
||||
nextHop = INetd.NEXTHOP_NONE;
|
||||
}
|
||||
break;
|
||||
case RouteInfo.RTN_UNREACHABLE:
|
||||
nextHop = INetd.NEXTHOP_UNREACHABLE;
|
||||
break;
|
||||
case RouteInfo.RTN_THROW:
|
||||
nextHop = INetd.NEXTHOP_THROW;
|
||||
break;
|
||||
default:
|
||||
nextHop = INetd.NEXTHOP_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
final RouteInfoParcel rip = new RouteInfoParcel();
|
||||
rip.ifName = route.getInterface();
|
||||
rip.destination = route.getDestination().toString();
|
||||
rip.nextHop = nextHop;
|
||||
rip.mtu = route.getMtu();
|
||||
|
||||
return rip;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Utilities to deal with multiple SDKs in a single mainline module.
|
||||
* @hide
|
||||
*/
|
||||
public class SdkUtil {
|
||||
/**
|
||||
* Holder class taking advantage of erasure to avoid reflection running into class not found
|
||||
* exceptions.
|
||||
*
|
||||
* This is useful to store a reference to a class that might not be present at runtime when
|
||||
* fields are examined through reflection. An example is the MessageUtils class, which tries
|
||||
* to get all fields in a class and therefore will try to load any class for which there
|
||||
* is a member. Another example would be arguments or return values of methods in tests,
|
||||
* when the testing framework uses reflection to list methods and their arguments.
|
||||
*
|
||||
* In these cases, LateSdk<T> can be used to hide type T from reflection, since it's erased
|
||||
* and it becomes a vanilla LateSdk in Java bytecode. The T still can't be instantiated at
|
||||
* runtime of course, but runtime tests will avoid that.
|
||||
*
|
||||
* @param <T> The held type
|
||||
* @hide
|
||||
*/
|
||||
public static class LateSdk<T> {
|
||||
@Nullable public final T value;
|
||||
public LateSdk(@Nullable final T value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user