• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.net.ip;
18 
19 import static android.net.INetd.IF_STATE_DOWN;
20 import static android.net.INetd.IF_STATE_UP;
21 import static android.net.RouteInfo.RTN_UNICAST;
22 import static android.net.TetheringManager.CONNECTIVITY_SCOPE_GLOBAL;
23 import static android.net.TetheringManager.CONNECTIVITY_SCOPE_LOCAL;
24 import static android.net.TetheringManager.TETHERING_BLUETOOTH;
25 import static android.net.TetheringManager.TETHERING_NCM;
26 import static android.net.TetheringManager.TETHERING_USB;
27 import static android.net.TetheringManager.TETHERING_WIFI;
28 import static android.net.TetheringManager.TETHERING_WIFI_P2P;
29 import static android.net.TetheringManager.TETHER_ERROR_ENABLE_FORWARDING_ERROR;
30 import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
31 import static android.net.TetheringManager.TETHER_ERROR_SERVICE_UNAVAIL;
32 import static android.net.TetheringManager.TETHER_ERROR_TETHER_IFACE_ERROR;
33 import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
34 import static android.net.ip.IpServer.STATE_AVAILABLE;
35 import static android.net.ip.IpServer.STATE_LOCAL_ONLY;
36 import static android.net.ip.IpServer.STATE_TETHERED;
37 import static android.net.ip.IpServer.STATE_UNAVAILABLE;
38 import static android.net.ip.IpServer.getTetherableIpv6Prefixes;
39 
40 import static com.android.modules.utils.build.SdkLevel.isAtLeastT;
41 import static com.android.modules.utils.build.SdkLevel.isAtLeastV;
42 import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH;
43 import static com.android.networkstack.tethering.TetheringConfiguration.TETHERING_LOCAL_NETWORK_AGENT;
44 
45 import static org.junit.Assert.assertEquals;
46 import static org.junit.Assert.assertFalse;
47 import static org.junit.Assert.assertNotEquals;
48 import static org.junit.Assert.assertNotNull;
49 import static org.junit.Assert.assertTrue;
50 import static org.junit.Assert.fail;
51 import static org.mockito.ArgumentMatchers.anyInt;
52 import static org.mockito.ArgumentMatchers.argThat;
53 import static org.mockito.ArgumentMatchers.any;
54 import static org.mockito.ArgumentMatchers.anyString;
55 import static org.mockito.ArgumentMatchers.eq;
56 import static org.mockito.Mockito.clearInvocations;
57 import static org.mockito.Mockito.doAnswer;
58 import static org.mockito.Mockito.doNothing;
59 import static org.mockito.Mockito.doReturn;
60 import static org.mockito.Mockito.doThrow;
61 import static org.mockito.Mockito.inOrder;
62 import static org.mockito.Mockito.mock;
63 import static org.mockito.Mockito.never;
64 import static org.mockito.Mockito.reset;
65 import static org.mockito.Mockito.timeout;
66 import static org.mockito.Mockito.times;
67 import static org.mockito.Mockito.verify;
68 import static org.mockito.Mockito.verifyNoMoreInteractions;
69 import static org.mockito.Mockito.when;
70 
71 import android.content.Context;
72 import android.net.INetd;
73 import android.net.InetAddresses;
74 import android.net.InterfaceConfigurationParcel;
75 import android.net.IpPrefix;
76 import android.net.LinkAddress;
77 import android.net.LinkProperties;
78 import android.net.MacAddress;
79 import android.net.Network;
80 import android.net.NetworkAgent;
81 import android.net.RouteInfo;
82 import android.net.TetheringManager.TetheringRequest;
83 import android.net.dhcp.DhcpServerCallbacks;
84 import android.net.dhcp.DhcpServingParamsParcel;
85 import android.net.dhcp.IDhcpEventCallbacks;
86 import android.net.dhcp.IDhcpServer;
87 import android.net.dhcp.IDhcpServerCallbacks;
88 import android.net.ip.RouterAdvertisementDaemon.RaParams;
89 import android.os.Build;
90 import android.os.Handler;
91 import android.os.RemoteException;
92 import android.os.ServiceSpecificException;
93 import android.os.test.TestLooper;
94 import android.text.TextUtils;
95 import android.util.ArrayMap;
96 
97 import androidx.test.filters.SmallTest;
98 import androidx.test.runner.AndroidJUnit4;
99 
100 import com.android.net.module.util.InterfaceParams;
101 import com.android.net.module.util.RoutingCoordinatorManager;
102 import com.android.net.module.util.SharedLog;
103 import com.android.networkstack.tethering.BpfCoordinator;
104 import com.android.networkstack.tethering.TetheringConfiguration;
105 import com.android.networkstack.tethering.metrics.TetheringMetrics;
106 import com.android.networkstack.tethering.util.InterfaceSet;
107 import com.android.networkstack.tethering.util.PrefixUtils;
108 import com.android.testutils.DevSdkIgnoreRule;
109 import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
110 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
111 import com.android.testutils.com.android.testutils.SetFeatureFlagsRule;
112 
113 import org.junit.Before;
114 import org.junit.Rule;
115 import org.junit.Test;
116 import org.junit.runner.RunWith;
117 import org.mockito.ArgumentCaptor;
118 import org.mockito.Captor;
119 import org.mockito.InOrder;
120 import org.mockito.Mock;
121 import org.mockito.MockitoAnnotations;
122 
123 import java.net.Inet4Address;
124 import java.net.InetAddress;
125 import java.util.List;
126 import java.util.Set;
127 
128 @RunWith(AndroidJUnit4.class)
129 @SmallTest
130 public class IpServerTest {
131     @Rule
132     public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule();
133 
134     final ArrayMap<String, Boolean> mFeatureFlags = new ArrayMap<>();
135     // This will set feature flags from @FeatureFlag annotations
136     // into the map before setUp() runs.
137     @Rule
138     public final SetFeatureFlagsRule mSetFeatureFlagsRule =
139             new SetFeatureFlagsRule((name, enabled) -> {
140                 mFeatureFlags.put(name, enabled);
141                 return null;
142             }, (name) -> mFeatureFlags.getOrDefault(name, false));
143 
144     private static final String IFACE_NAME = "testnet1";
145     private static final String UPSTREAM_IFACE = "upstream0";
146     private static final String UPSTREAM_IFACE2 = "upstream1";
147     private static final String IPSEC_IFACE = "ipsec0";
148     private static final int NO_UPSTREAM = 0;
149     private static final int UPSTREAM_IFINDEX = 101;
150     private static final int UPSTREAM_IFINDEX2 = 102;
151     private static final int IPSEC_IFINDEX = 103;
152     private static final String BLUETOOTH_IFACE_ADDR = "192.168.44.1";
153     private static final int BLUETOOTH_DHCP_PREFIX_LENGTH = 24;
154     private static final int DHCP_LEASE_TIME_SECS = 3600;
155     private static final boolean DEFAULT_USING_BPF_OFFLOAD = true;
156     private static final int DEFAULT_SUBNET_PREFIX_LENGTH = 0;
157     private static final int P2P_SUBNET_PREFIX_LENGTH = 25;
158     private static final String LEGACY_WIFI_P2P_IFACE_ADDRESS = "192.168.49.1/24";
159 
160     private static final InterfaceParams TEST_IFACE_PARAMS = new InterfaceParams(
161             IFACE_NAME, 42 /* index */, MacAddress.ALL_ZEROS_ADDRESS, 1500 /* defaultMtu */);
162     private static final InterfaceParams UPSTREAM_IFACE_PARAMS = new InterfaceParams(
163             UPSTREAM_IFACE, UPSTREAM_IFINDEX, MacAddress.ALL_ZEROS_ADDRESS, 1500 /* defaultMtu */);
164     private static final InterfaceParams UPSTREAM_IFACE_PARAMS2 = new InterfaceParams(
165             UPSTREAM_IFACE2, UPSTREAM_IFINDEX2, MacAddress.ALL_ZEROS_ADDRESS,
166             1500 /* defaultMtu */);
167     private static final InterfaceParams IPSEC_IFACE_PARAMS = new InterfaceParams(
168             IPSEC_IFACE, IPSEC_IFINDEX, MacAddress.ALL_ZEROS_ADDRESS, 1500 /* defaultMtu */);
169 
170     private static final int MAKE_DHCPSERVER_TIMEOUT_MS = 1000;
171 
172     private final LinkAddress mTestAddress = new LinkAddress("192.168.42.5/24");
173     private final IpPrefix mBluetoothPrefix = new IpPrefix("192.168.44.0/24");
174 
175     private static final Set<LinkAddress> NO_ADDRESSES = Set.of();
176     private static final Set<IpPrefix> NO_PREFIXES = Set.of();
177     private static final Set<LinkAddress> UPSTREAM_ADDRESSES =
178             Set.of(new LinkAddress("2001:db8:0:1234::168/64"));
179     private static final Set<IpPrefix> UPSTREAM_PREFIXES =
180             Set.of(new IpPrefix("2001:db8:0:1234::/64"));
181     private static final Set<LinkAddress> UPSTREAM_ADDRESSES2 = Set.of(
182             new LinkAddress("2001:db8:0:1234::168/64"),
183             new LinkAddress("2001:db8:0:abcd::168/64"));
184     private static final Set<IpPrefix> UPSTREAM_PREFIXES2 = Set.of(
185             new IpPrefix("2001:db8:0:1234::/64"), new IpPrefix("2001:db8:0:abcd::/64"));
186     private static final int TEST_NET_ID = 123;
187 
188     @Mock private INetd mNetd;
189     @Mock private IpServer.Callback mCallback;
190     @Mock private SharedLog mSharedLog;
191     @Mock private IDhcpServer mDhcpServer;
192     @Mock private DadProxy mDadProxy;
193     @Mock private RouterAdvertisementDaemon mRaDaemon;
194     @Mock private IpServer.Dependencies mDependencies;
195     @Mock private RoutingCoordinatorManager mRoutingCoordinatorManager;
196     @Mock private TetheringConfiguration mTetherConfig;
197     @Mock private TetheringMetrics mTetheringMetrics;
198     @Mock private BpfCoordinator mBpfCoordinator;
199     @Mock private Context mContext;
200     @Mock private NetworkAgent mNetworkAgent;
201 
202     @Captor private ArgumentCaptor<DhcpServingParamsParcel> mDhcpParamsCaptor;
203 
204     private TestLooper mLooper;
205     private Handler mHandler;
206     private final ArgumentCaptor<LinkProperties> mLinkPropertiesCaptor =
207             ArgumentCaptor.forClass(LinkProperties.class);
208     private IpServer mIpServer;
209     private InterfaceConfigurationParcel mInterfaceConfiguration;
210 
initStateMachine(int interfaceType)211     private void initStateMachine(int interfaceType) throws Exception {
212         initStateMachine(interfaceType, false /* usingLegacyDhcp */, DEFAULT_USING_BPF_OFFLOAD);
213     }
214 
initStateMachine(int interfaceType, boolean usingLegacyDhcp, boolean usingBpfOffload)215     private void initStateMachine(int interfaceType, boolean usingLegacyDhcp,
216             boolean usingBpfOffload) throws Exception {
217         initStateMachine(interfaceType, usingLegacyDhcp, usingBpfOffload,
218                 false /* shouldEnableWifiP2pDedicatedIp */);
219     }
220 
initStateMachine(int interfaceType, boolean usingLegacyDhcp, boolean usingBpfOffload, boolean shouldEnableWifiP2pDedicatedIp)221     private void initStateMachine(int interfaceType, boolean usingLegacyDhcp,
222             boolean usingBpfOffload, boolean shouldEnableWifiP2pDedicatedIp) throws Exception {
223         when(mDependencies.getDadProxy(any(), any())).thenReturn(mDadProxy);
224         when(mDependencies.getRouterAdvertisementDaemon(any())).thenReturn(mRaDaemon);
225         when(mDependencies.getInterfaceParams(IFACE_NAME)).thenReturn(TEST_IFACE_PARAMS);
226         when(mDependencies.getInterfaceParams(UPSTREAM_IFACE)).thenReturn(UPSTREAM_IFACE_PARAMS);
227         when(mDependencies.getInterfaceParams(UPSTREAM_IFACE2)).thenReturn(UPSTREAM_IFACE_PARAMS2);
228         when(mDependencies.getInterfaceParams(IPSEC_IFACE)).thenReturn(IPSEC_IFACE_PARAMS);
229         doAnswer(
230                 invocation -> mFeatureFlags.getOrDefault((String) invocation.getArgument(1), false)
231         ).when(mDependencies).isFeatureEnabled(any(), anyString());
232         if (isAtLeastV()) {
233             when(mDependencies.makeNetworkAgent(any(), any(), anyString(), anyInt(), any()))
234                     .thenReturn(mNetworkAgent);
235             // Mock the returned network and modifying the status.
236             final Network network = mock(Network.class);
237             doReturn(TEST_NET_ID).when(network).getNetId();
238             doReturn(network).when(mNetworkAgent).register();
239             doReturn(network).when(mNetworkAgent).getNetwork();
240         }
241 
242         mInterfaceConfiguration = new InterfaceConfigurationParcel();
243         mInterfaceConfiguration.flags = new String[0];
244         if (interfaceType == TETHERING_BLUETOOTH) {
245             mInterfaceConfiguration.ipv4Addr = BLUETOOTH_IFACE_ADDR;
246             mInterfaceConfiguration.prefixLength = BLUETOOTH_DHCP_PREFIX_LENGTH;
247         }
248 
249         when(mTetherConfig.isBpfOffloadEnabled()).thenReturn(usingBpfOffload);
250         when(mTetherConfig.useLegacyDhcpServer()).thenReturn(usingLegacyDhcp);
251         when(mTetherConfig.getP2pLeasesSubnetPrefixLength()).thenReturn(P2P_SUBNET_PREFIX_LENGTH);
252         when(mTetherConfig.shouldEnableWifiP2pDedicatedIp())
253                 .thenReturn(shouldEnableWifiP2pDedicatedIp);
254         when(mBpfCoordinator.isUsingBpfOffload()).thenReturn(usingBpfOffload);
255         mIpServer = createIpServer(interfaceType);
256         mIpServer.start();
257 
258         // Starting the state machine always puts us in a consistent state and notifies
259         // the rest of the world that we've changed from an unknown to available state.
260         mLooper.dispatchAll();
261         reset(mNetd, mCallback);
262 
263         when(mRaDaemon.start()).thenReturn(true);
264     }
265 
initTetheredStateMachine(int interfaceType, String upstreamIface)266     private void initTetheredStateMachine(int interfaceType, String upstreamIface)
267             throws Exception {
268         initTetheredStateMachine(interfaceType, upstreamIface, NO_ADDRESSES, false,
269                 DEFAULT_USING_BPF_OFFLOAD);
270     }
271 
initTetheredStateMachine(int interfaceType, String upstreamIface, Set<LinkAddress> upstreamAddresses, boolean usingLegacyDhcp, boolean usingBpfOffload)272     private void initTetheredStateMachine(int interfaceType, String upstreamIface,
273             Set<LinkAddress> upstreamAddresses, boolean usingLegacyDhcp, boolean usingBpfOffload)
274             throws Exception {
275         initStateMachine(interfaceType, usingLegacyDhcp, usingBpfOffload);
276         dispatchCommand(IpServer.CMD_TETHER_REQUESTED, 0, 0,
277                 createMockTetheringRequest(CONNECTIVITY_SCOPE_GLOBAL));
278         verify(mBpfCoordinator).addIpServer(mIpServer);
279         if (upstreamIface != null) {
280             InterfaceParams interfaceParams = mDependencies.getInterfaceParams(upstreamIface);
281             assertNotNull("missing upstream interface: " + upstreamIface, interfaceParams);
282             LinkProperties lp = new LinkProperties();
283             lp.setInterfaceName(upstreamIface);
284             lp.setLinkAddresses(upstreamAddresses);
285             dispatchTetherConnectionChanged(upstreamIface, lp, 0);
286             Set<IpPrefix> upstreamPrefixes = getTetherableIpv6Prefixes(lp.getLinkAddresses());
287             // One is called when handling CMD_TETHER_CONNECTION_CHANGED and the other one is called
288             // when upstream's LinkProperties is updated (updateUpstreamIPv6LinkProperties)
289             verify(mBpfCoordinator, times(2)).maybeAddUpstreamToLookupTable(
290                     interfaceParams.index, upstreamIface);
291             verify(mBpfCoordinator).updateIpv6UpstreamInterface(
292                     mIpServer, interfaceParams.index, upstreamPrefixes);
293         }
294         reset(mNetd, mBpfCoordinator, mCallback, mRoutingCoordinatorManager);
295         when(mRoutingCoordinatorManager.requestStickyDownstreamAddress(anyInt(), anyInt(),
296                 any())).thenReturn(mTestAddress);
297     }
298 
299     @SuppressWarnings("DoNotCall") // Ignore warning for synchronous to call to Thread.run()
setUpDhcpServer()300     private void setUpDhcpServer() throws Exception {
301         doAnswer(inv -> {
302             final IDhcpServerCallbacks cb = inv.getArgument(2);
303             new Thread(() -> {
304                 try {
305                     cb.onDhcpServerCreated(STATUS_SUCCESS, mDhcpServer);
306                 } catch (RemoteException e) {
307                     fail(e.getMessage());
308                 }
309             }).run();
310             return null;
311         }).when(mDependencies).makeDhcpServer(any(), mDhcpParamsCaptor.capture(), any());
312     }
313 
setUp()314     @Before public void setUp() throws Exception {
315         MockitoAnnotations.initMocks(this);
316         when(mSharedLog.forSubComponent(anyString())).thenReturn(mSharedLog);
317         when(mRoutingCoordinatorManager.requestStickyDownstreamAddress(anyInt(), anyInt(),
318                 any())).thenReturn(mTestAddress);
319         when(mRoutingCoordinatorManager.requestDownstreamAddress(any())).thenReturn(mTestAddress);
320         when(mTetherConfig.isBpfOffloadEnabled()).thenReturn(DEFAULT_USING_BPF_OFFLOAD);
321         when(mTetherConfig.useLegacyDhcpServer()).thenReturn(false /* default value */);
322 
323         setUpDhcpServer();
324     }
325 
326     // In order to interact with syncSM from the test, IpServer must be created in test thread.
createIpServer(final int interfaceType)327     private IpServer createIpServer(final int interfaceType) {
328         mLooper = new TestLooper();
329         mHandler = new Handler(mLooper.getLooper());
330         return new IpServer(IFACE_NAME, mContext, mHandler, interfaceType, mSharedLog, mNetd,
331                 mBpfCoordinator, mRoutingCoordinatorManager, mCallback, mTetherConfig,
332                 mTetheringMetrics, mDependencies);
333     }
334 
335     @Test
startsOutAvailable()336     public void startsOutAvailable() throws Exception {
337         mIpServer = createIpServer(TETHERING_BLUETOOTH);
338         mIpServer.start();
339         mLooper.dispatchAll();
340         verify(mCallback).updateInterfaceState(
341                 mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
342         verify(mCallback).updateLinkProperties(eq(mIpServer), any(LinkProperties.class));
343         verifyNoMoreInteractions(mCallback, mNetd);
344     }
345 
346     @Test
shouldDoNothingUntilRequested()347     public void shouldDoNothingUntilRequested() throws Exception {
348         initStateMachine(TETHERING_BLUETOOTH);
349         final int [] noOp_commands = {
350             IpServer.CMD_TETHER_UNREQUESTED,
351             IpServer.CMD_IP_FORWARDING_ENABLE_ERROR,
352             IpServer.CMD_IP_FORWARDING_DISABLE_ERROR,
353             IpServer.CMD_START_TETHERING_ERROR,
354             IpServer.CMD_STOP_TETHERING_ERROR,
355             IpServer.CMD_SET_DNS_FORWARDERS_ERROR,
356             IpServer.CMD_TETHER_CONNECTION_CHANGED
357         };
358         for (int command : noOp_commands) {
359             // None of these commands should trigger us to request action from
360             // the rest of the system.
361             dispatchCommand(command);
362             verifyNoMoreInteractions(mNetd, mCallback);
363         }
364     }
365 
366     @Test
handlesImmediateInterfaceDown()367     public void handlesImmediateInterfaceDown() throws Exception {
368         initStateMachine(TETHERING_BLUETOOTH);
369 
370         dispatchCommand(IpServer.CMD_INTERFACE_DOWN);
371         verify(mCallback).updateInterfaceState(
372                 mIpServer, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR);
373         verify(mCallback).updateLinkProperties(eq(mIpServer), any(LinkProperties.class));
374         verifyNoMoreInteractions(mNetd, mCallback);
375     }
376 
isTetheringNetworkAgentFeatureEnabled()377     private boolean isTetheringNetworkAgentFeatureEnabled() {
378         return isAtLeastV() && mFeatureFlags.getOrDefault(TETHERING_LOCAL_NETWORK_AGENT, false);
379     }
380 
381     @Test
canBeTetheredAsBluetooth()382     public void canBeTetheredAsBluetooth() throws Exception {
383         initStateMachine(TETHERING_BLUETOOTH);
384 
385         dispatchCommand(IpServer.CMD_TETHER_REQUESTED, 0, 0,
386                 createMockTetheringRequest(CONNECTIVITY_SCOPE_GLOBAL));
387         InOrder inOrder = inOrder(mCallback, mNetd, mRoutingCoordinatorManager);
388         if (isAtLeastT()) {
389             inOrder.verify(mRoutingCoordinatorManager)
390                     .requestStickyDownstreamAddress(
391                             eq(TETHERING_BLUETOOTH),
392                             eq(CONNECTIVITY_SCOPE_GLOBAL),
393                             any());
394             inOrder.verify(mRoutingCoordinatorManager, never()).requestDownstreamAddress(any());
395             inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg ->
396                     IFACE_NAME.equals(cfg.ifName) && assertContainsFlag(cfg.flags, IF_STATE_UP)));
397         }
398         inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
399         if (isTetheringNetworkAgentFeatureEnabled()) {
400             inOrder.verify(mNetd, never()).networkAddInterface(anyInt(), anyString());
401             inOrder.verify(mNetd, never())
402                     .networkAddRoute(anyInt(), anyString(), anyString(), anyString());
403         } else {
404             inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
405             // One for ipv4 route, one for ipv6 link local route.
406             inOrder.verify(mNetd, times(2))
407                     .networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME), any(), any());
408         }
409         inOrder.verify(mCallback).updateInterfaceState(
410                 mIpServer, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
411         inOrder.verify(mCallback).updateLinkProperties(
412                 eq(mIpServer), any(LinkProperties.class));
413         verifyNoMoreInteractions(mNetd, mCallback);
414     }
415 
416     @Test
canUnrequestTethering()417     public void canUnrequestTethering() throws Exception {
418         initTetheredStateMachine(TETHERING_BLUETOOTH, null);
419 
420         dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED);
421         InOrder inOrder = inOrder(mCallback, mNetd, mRoutingCoordinatorManager);
422         inOrder.verify(mNetd).tetherApplyDnsInterfaces();
423         inOrder.verify(mNetd).tetherInterfaceRemove(IFACE_NAME);
424         if (isTetheringNetworkAgentFeatureEnabled()) {
425             inOrder.verify(mNetd, never()).networkRemoveInterface(anyInt(), anyString());
426         } else {
427             inOrder.verify(mNetd).networkRemoveInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
428         }
429         // One is ipv4 address clear (set to 0.0.0.0), another is set interface down which only
430         // happen after T. Before T, the interface configuration control in bluetooth side.
431         if (isAtLeastT()) {
432             inOrder.verify(mNetd).interfaceSetCfg(
433                     argThat(cfg -> assertContainsFlag(cfg.flags, IF_STATE_DOWN)));
434         }
435         inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg -> cfg.flags.length == 0));
436         inOrder.verify(mRoutingCoordinatorManager).releaseDownstream(any());
437         inOrder.verify(mCallback).updateInterfaceState(
438                 mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
439         inOrder.verify(mCallback).updateLinkProperties(
440                 eq(mIpServer), any(LinkProperties.class));
441         verify(mTetheringMetrics).updateErrorCode(eq(TETHERING_BLUETOOTH),
442                 eq(TETHER_ERROR_NO_ERROR));
443         verify(mTetheringMetrics).sendReport(eq(TETHERING_BLUETOOTH));
444         verifyNoMoreInteractions(mNetd, mCallback, mRoutingCoordinatorManager);
445     }
446 
447     @Test
canBeTetheredAsUsb()448     public void canBeTetheredAsUsb() throws Exception {
449         initStateMachine(TETHERING_USB);
450 
451         dispatchCommand(IpServer.CMD_TETHER_REQUESTED, 0, 0,
452                 createMockTetheringRequest(CONNECTIVITY_SCOPE_GLOBAL));
453         InOrder inOrder = inOrder(mCallback, mNetd, mRoutingCoordinatorManager);
454         inOrder.verify(mRoutingCoordinatorManager).requestStickyDownstreamAddress(anyInt(),
455                 eq(CONNECTIVITY_SCOPE_GLOBAL), any());
456         inOrder.verify(mRoutingCoordinatorManager, never()).requestDownstreamAddress(any());
457         inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg ->
458                 IFACE_NAME.equals(cfg.ifName) && assertContainsFlag(cfg.flags, IF_STATE_UP)));
459         inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
460         if (isTetheringNetworkAgentFeatureEnabled()) {
461             inOrder.verify(mNetd, never()).networkAddInterface(anyInt(), anyString());
462             inOrder.verify(mNetd, never())
463                     .networkAddRoute(anyInt(), anyString(), anyString(), anyString());
464         } else {
465             inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
466             inOrder.verify(mNetd, times(2))
467                     .networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME), any(), any());
468         }
469         inOrder.verify(mCallback).updateInterfaceState(
470                 mIpServer, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
471         inOrder.verify(mCallback).updateLinkProperties(
472                 eq(mIpServer), mLinkPropertiesCaptor.capture());
473         assertIPv4AddressAndDirectlyConnectedRoute(mLinkPropertiesCaptor.getValue());
474         verifyNoMoreInteractions(mNetd, mCallback, mRoutingCoordinatorManager);
475     }
476 
477     @Test
canBeTetheredAsWifiP2p_NotUsingDedicatedIp()478     public void canBeTetheredAsWifiP2p_NotUsingDedicatedIp() throws Exception {
479         initStateMachine(TETHERING_WIFI_P2P);
480 
481         dispatchCommand(IpServer.CMD_TETHER_REQUESTED, 0, 0,
482                 createMockTetheringRequest(CONNECTIVITY_SCOPE_LOCAL));
483         InOrder inOrder = inOrder(mCallback, mNetd, mRoutingCoordinatorManager);
484         inOrder.verify(mRoutingCoordinatorManager).requestStickyDownstreamAddress(anyInt(),
485                 eq(CONNECTIVITY_SCOPE_LOCAL), any());
486         inOrder.verify(mRoutingCoordinatorManager, never()).requestDownstreamAddress(any());
487         inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg ->
488                   IFACE_NAME.equals(cfg.ifName) && assertNotContainsFlag(cfg.flags, IF_STATE_UP)));
489         inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
490         inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
491         inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME),
492                 any(), any());
493         inOrder.verify(mCallback).updateInterfaceState(
494                 mIpServer, STATE_LOCAL_ONLY, TETHER_ERROR_NO_ERROR);
495         inOrder.verify(mCallback).updateLinkProperties(
496                 eq(mIpServer), mLinkPropertiesCaptor.capture());
497         assertIPv4AddressAndDirectlyConnectedRoute(mLinkPropertiesCaptor.getValue());
498         verifyNoMoreInteractions(mNetd, mCallback, mRoutingCoordinatorManager);
499     }
500 
501     @Test
canBeTetheredAsWifiP2p_UsingDedicatedIp()502     public void canBeTetheredAsWifiP2p_UsingDedicatedIp() throws Exception {
503         initStateMachine(TETHERING_WIFI_P2P, false /* usingLegacyDhcp */, DEFAULT_USING_BPF_OFFLOAD,
504                 true /* shouldEnableWifiP2pDedicatedIp */);
505 
506         dispatchCommand(IpServer.CMD_TETHER_REQUESTED, 0, 0,
507                 createMockTetheringRequest(CONNECTIVITY_SCOPE_LOCAL));
508         InOrder inOrder = inOrder(mCallback, mNetd, mRoutingCoordinatorManager);
509         // When using WiFi P2p dedicated IP, the IpServer just picks the IP address without
510         // requesting for it at RoutingCoordinatorManager.
511         inOrder.verify(mRoutingCoordinatorManager, never())
512                 .requestStickyDownstreamAddress(anyInt(), anyInt(), any());
513         inOrder.verify(mRoutingCoordinatorManager, never()).requestDownstreamAddress(any());
514         inOrder.verify(mNetd).interfaceSetCfg(argThat(cfg ->
515                 IFACE_NAME.equals(cfg.ifName) && assertNotContainsFlag(cfg.flags, IF_STATE_UP)));
516         inOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
517         inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
518         inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME),
519                 any(), any());
520         inOrder.verify(mCallback).updateInterfaceState(
521                 mIpServer, STATE_LOCAL_ONLY, TETHER_ERROR_NO_ERROR);
522         inOrder.verify(mCallback).updateLinkProperties(
523                 eq(mIpServer), mLinkPropertiesCaptor.capture());
524         assertIPv4AddressAndDirectlyConnectedRoute(mLinkPropertiesCaptor.getValue());
525         assertEquals(List.of(new LinkAddress(LEGACY_WIFI_P2P_IFACE_ADDRESS)),
526                 mLinkPropertiesCaptor.getValue().getLinkAddresses());
527         verifyNoMoreInteractions(mNetd, mCallback, mRoutingCoordinatorManager);
528     }
529 
530     @Test
handlesFirstUpstreamChange()531     public void handlesFirstUpstreamChange() throws Exception {
532         initTetheredStateMachine(TETHERING_BLUETOOTH, null);
533 
534         // Telling the state machine about its upstream interface triggers
535         // a little more configuration.
536         dispatchTetherConnectionChanged(UPSTREAM_IFACE);
537         InOrder inOrder = inOrder(mBpfCoordinator, mRoutingCoordinatorManager);
538 
539         // Add the forwarding pair <IFACE_NAME, UPSTREAM_IFACE>.
540         inOrder.verify(mBpfCoordinator).maybeAddUpstreamToLookupTable(UPSTREAM_IFINDEX,
541                 UPSTREAM_IFACE);
542         inOrder.verify(mBpfCoordinator).maybeAttachProgram(IFACE_NAME, UPSTREAM_IFACE);
543         inOrder.verify(mRoutingCoordinatorManager).addInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
544 
545         verifyNoMoreInteractions(mCallback, mBpfCoordinator, mRoutingCoordinatorManager);
546     }
547 
548     @Test
handlesChangingUpstream()549     public void handlesChangingUpstream() throws Exception {
550         initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE);
551 
552         clearInvocations(mBpfCoordinator, mRoutingCoordinatorManager);
553         dispatchTetherConnectionChanged(UPSTREAM_IFACE2);
554         InOrder inOrder = inOrder(mBpfCoordinator, mRoutingCoordinatorManager);
555 
556         // Remove the forwarding pair <IFACE_NAME, UPSTREAM_IFACE>.
557         inOrder.verify(mBpfCoordinator).maybeDetachProgram(IFACE_NAME, UPSTREAM_IFACE);
558         inOrder.verify(mRoutingCoordinatorManager)
559                 .removeInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
560 
561         // Add the forwarding pair <IFACE_NAME, UPSTREAM_IFACE2>.
562         inOrder.verify(mBpfCoordinator).maybeAddUpstreamToLookupTable(UPSTREAM_IFINDEX2,
563                 UPSTREAM_IFACE2);
564         inOrder.verify(mBpfCoordinator).maybeAttachProgram(IFACE_NAME, UPSTREAM_IFACE2);
565         inOrder.verify(mRoutingCoordinatorManager).addInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2);
566 
567         verifyNoMoreInteractions(mCallback, mBpfCoordinator, mRoutingCoordinatorManager);
568     }
569 
570     @Test
handlesChangingUpstreamNatFailure()571     public void handlesChangingUpstreamNatFailure() throws Exception {
572         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
573 
574         doThrow(RuntimeException.class)
575                 .when(mRoutingCoordinatorManager)
576                 .addInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2);
577 
578         dispatchTetherConnectionChanged(UPSTREAM_IFACE2);
579         InOrder inOrder = inOrder(mBpfCoordinator, mRoutingCoordinatorManager);
580 
581         // Remove the forwarding pair <IFACE_NAME, UPSTREAM_IFACE>.
582         inOrder.verify(mBpfCoordinator).maybeDetachProgram(IFACE_NAME, UPSTREAM_IFACE);
583         inOrder.verify(mRoutingCoordinatorManager)
584                 .removeInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
585 
586         // Add the forwarding pair <IFACE_NAME, UPSTREAM_IFACE2> and expect that failed on
587         // addInterfaceForward.
588         inOrder.verify(mBpfCoordinator).maybeAddUpstreamToLookupTable(UPSTREAM_IFINDEX2,
589                 UPSTREAM_IFACE2);
590         inOrder.verify(mBpfCoordinator).maybeAttachProgram(IFACE_NAME, UPSTREAM_IFACE2);
591         inOrder.verify(mRoutingCoordinatorManager).addInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2);
592 
593         // Remove the forwarding pair <IFACE_NAME, UPSTREAM_IFACE2> to fallback.
594         inOrder.verify(mBpfCoordinator).maybeDetachProgram(IFACE_NAME, UPSTREAM_IFACE2);
595         inOrder.verify(mRoutingCoordinatorManager)
596                 .removeInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2);
597     }
598 
599     @Test
handlesChangingUpstreamInterfaceForwardingFailure()600     public void handlesChangingUpstreamInterfaceForwardingFailure() throws Exception {
601         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
602 
603         doThrow(RuntimeException.class)
604                 .when(mRoutingCoordinatorManager)
605                 .addInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2);
606 
607         dispatchTetherConnectionChanged(UPSTREAM_IFACE2);
608         InOrder inOrder = inOrder(mBpfCoordinator, mRoutingCoordinatorManager);
609 
610         // Remove the forwarding pair <IFACE_NAME, UPSTREAM_IFACE>.
611         inOrder.verify(mBpfCoordinator).maybeDetachProgram(IFACE_NAME, UPSTREAM_IFACE);
612         inOrder.verify(mRoutingCoordinatorManager)
613                 .removeInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
614 
615         // Add the forwarding pair <IFACE_NAME, UPSTREAM_IFACE2> and expect that failed on
616         // ipfwdAddInterfaceForward.
617         inOrder.verify(mBpfCoordinator).maybeAddUpstreamToLookupTable(UPSTREAM_IFINDEX2,
618                 UPSTREAM_IFACE2);
619         inOrder.verify(mBpfCoordinator).maybeAttachProgram(IFACE_NAME, UPSTREAM_IFACE2);
620         inOrder.verify(mRoutingCoordinatorManager).addInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2);
621 
622         // Remove the forwarding pair <IFACE_NAME, UPSTREAM_IFACE2> to fallback.
623         inOrder.verify(mBpfCoordinator).maybeDetachProgram(IFACE_NAME, UPSTREAM_IFACE2);
624         inOrder.verify(mRoutingCoordinatorManager)
625                 .removeInterfaceForward(IFACE_NAME, UPSTREAM_IFACE2);
626     }
627 
628     @Test
canUnrequestTetheringWithUpstream()629     public void canUnrequestTetheringWithUpstream() throws Exception {
630         initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE);
631 
632         clearInvocations(
633                 mNetd, mCallback, mBpfCoordinator, mRoutingCoordinatorManager);
634         dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED);
635         InOrder inOrder = inOrder(mNetd, mCallback, mBpfCoordinator, mRoutingCoordinatorManager);
636         inOrder.verify(mBpfCoordinator).maybeDetachProgram(IFACE_NAME, UPSTREAM_IFACE);
637         inOrder.verify(mRoutingCoordinatorManager)
638                 .removeInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
639         inOrder.verify(mBpfCoordinator).updateIpv6UpstreamInterface(
640                 mIpServer, NO_UPSTREAM, NO_PREFIXES);
641         // When tethering stops, upstream interface is set to zero and thus clearing all upstream
642         // rules. Downstream rules are needed to be cleared explicitly by calling
643         // BpfCoordinator#clearAllIpv6Rules in TetheredState#exit.
644         inOrder.verify(mBpfCoordinator).clearAllIpv6Rules(mIpServer);
645         inOrder.verify(mNetd).tetherApplyDnsInterfaces();
646         inOrder.verify(mNetd).tetherInterfaceRemove(IFACE_NAME);
647         if (isTetheringNetworkAgentFeatureEnabled()) {
648             inOrder.verify(mNetd, never()).networkRemoveInterface(anyInt(), anyString());
649         } else {
650             inOrder.verify(mNetd).networkRemoveInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
651         }
652         inOrder.verify(mNetd, times(isAtLeastT() ? 2 : 1)).interfaceSetCfg(
653                 argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
654         inOrder.verify(mRoutingCoordinatorManager).releaseDownstream(any());
655         inOrder.verify(mBpfCoordinator).tetherOffloadClientClear(mIpServer);
656         inOrder.verify(mBpfCoordinator).removeIpServer(mIpServer);
657         inOrder.verify(mCallback).updateInterfaceState(
658                 mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
659         inOrder.verify(mCallback).updateLinkProperties(
660                 eq(mIpServer), any(LinkProperties.class));
661         verifyNoMoreInteractions(mNetd, mCallback, mRoutingCoordinatorManager, mBpfCoordinator);
662     }
663 
664     @Test
interfaceDownLeadsToUnavailable()665     public void interfaceDownLeadsToUnavailable() throws Exception {
666         for (boolean shouldThrow : new boolean[]{true, false}) {
667             initTetheredStateMachine(TETHERING_USB, null);
668 
669             if (shouldThrow) {
670                 doThrow(RemoteException.class).when(mNetd).tetherInterfaceRemove(IFACE_NAME);
671             }
672             dispatchCommand(IpServer.CMD_INTERFACE_DOWN);
673             InOrder usbTeardownOrder = inOrder(mNetd, mCallback);
674             // Currently IpServer interfaceSetCfg twice to stop IPv4. One just set interface down
675             // Another one is set IPv4 to 0.0.0.0/0 as clearng ipv4 address.
676             usbTeardownOrder.verify(mNetd, times(2)).interfaceSetCfg(
677                     argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
678             usbTeardownOrder.verify(mCallback).updateInterfaceState(
679                     mIpServer, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR);
680             usbTeardownOrder.verify(mCallback).updateLinkProperties(
681                     eq(mIpServer), mLinkPropertiesCaptor.capture());
682             assertNoAddressesNorRoutes(mLinkPropertiesCaptor.getValue());
683         }
684     }
685 
686     @Test
usbShouldBeTornDownOnTetherError()687     public void usbShouldBeTornDownOnTetherError() throws Exception {
688         initStateMachine(TETHERING_USB);
689 
690         doThrow(RemoteException.class).when(mNetd).tetherInterfaceAdd(IFACE_NAME);
691         dispatchCommand(IpServer.CMD_TETHER_REQUESTED, 0, 0,
692                 createMockTetheringRequest(CONNECTIVITY_SCOPE_GLOBAL));
693         InOrder usbTeardownOrder = inOrder(mNetd, mCallback);
694         usbTeardownOrder.verify(mNetd).interfaceSetCfg(
695                 argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
696         usbTeardownOrder.verify(mNetd).tetherInterfaceAdd(IFACE_NAME);
697 
698         usbTeardownOrder.verify(mNetd, times(2)).interfaceSetCfg(
699                 argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
700         usbTeardownOrder.verify(mCallback).updateInterfaceState(
701                 mIpServer, STATE_AVAILABLE, TETHER_ERROR_TETHER_IFACE_ERROR);
702         usbTeardownOrder.verify(mCallback).updateLinkProperties(
703                 eq(mIpServer), mLinkPropertiesCaptor.capture());
704         assertNoAddressesNorRoutes(mLinkPropertiesCaptor.getValue());
705         verify(mTetheringMetrics).updateErrorCode(eq(TETHERING_USB),
706                 eq(TETHER_ERROR_TETHER_IFACE_ERROR));
707         verify(mTetheringMetrics).sendReport(eq(TETHERING_USB));
708     }
709 
710     @Test
shouldTearDownUsbOnUpstreamError()711     public void shouldTearDownUsbOnUpstreamError() throws Exception {
712         initTetheredStateMachine(TETHERING_USB, null);
713 
714         doThrow(RuntimeException.class)
715                 .when(mRoutingCoordinatorManager)
716                 .addInterfaceForward(anyString(), anyString());
717         dispatchTetherConnectionChanged(UPSTREAM_IFACE);
718         InOrder usbTeardownOrder = inOrder(mNetd, mCallback, mRoutingCoordinatorManager);
719         usbTeardownOrder
720                 .verify(mRoutingCoordinatorManager)
721                 .addInterfaceForward(IFACE_NAME, UPSTREAM_IFACE);
722 
723         usbTeardownOrder.verify(mNetd, times(2)).interfaceSetCfg(
724                 argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
725         usbTeardownOrder.verify(mCallback).updateInterfaceState(
726                 mIpServer, STATE_AVAILABLE, TETHER_ERROR_ENABLE_FORWARDING_ERROR);
727         usbTeardownOrder.verify(mCallback).updateLinkProperties(
728                 eq(mIpServer), mLinkPropertiesCaptor.capture());
729         assertNoAddressesNorRoutes(mLinkPropertiesCaptor.getValue());
730         verify(mTetheringMetrics).updateErrorCode(eq(TETHERING_USB),
731                 eq(TETHER_ERROR_ENABLE_FORWARDING_ERROR));
732         verify(mTetheringMetrics).sendReport(eq(TETHERING_USB));
733     }
734 
735     @Test
ignoresDuplicateUpstreamNotifications()736     public void ignoresDuplicateUpstreamNotifications() throws Exception {
737         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
738 
739         verifyNoMoreInteractions(mNetd, mCallback);
740 
741         for (int i = 0; i < 5; i++) {
742             dispatchTetherConnectionChanged(UPSTREAM_IFACE);
743             verifyNoMoreInteractions(mNetd, mCallback);
744         }
745     }
746 
747     @Test
startsDhcpServer()748     public void startsDhcpServer() throws Exception {
749         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
750         dispatchTetherConnectionChanged(UPSTREAM_IFACE);
751 
752         assertDhcpStarted(PrefixUtils.asIpPrefix(mTestAddress));
753     }
754 
755     @Test
startsDhcpServerOnBluetooth()756     public void startsDhcpServerOnBluetooth() throws Exception {
757         initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE);
758         dispatchTetherConnectionChanged(UPSTREAM_IFACE);
759 
760         if (isAtLeastT()) {
761             assertDhcpStarted(PrefixUtils.asIpPrefix(mTestAddress));
762         } else {
763             assertDhcpStarted(mBluetoothPrefix);
764         }
765     }
766 
767     @Test
startsDhcpServerOnWifiP2p()768     public void startsDhcpServerOnWifiP2p() throws Exception {
769         initTetheredStateMachine(TETHERING_WIFI_P2P, UPSTREAM_IFACE);
770         dispatchTetherConnectionChanged(UPSTREAM_IFACE);
771 
772         assertDhcpStarted(PrefixUtils.asIpPrefix(mTestAddress));
773     }
774 
775     @Test
startsDhcpServerOnNcm()776     public void startsDhcpServerOnNcm() throws Exception {
777         initStateMachine(TETHERING_NCM);
778         dispatchCommand(IpServer.CMD_TETHER_REQUESTED, 0, 0,
779                 createMockTetheringRequest(CONNECTIVITY_SCOPE_LOCAL));
780         dispatchTetherConnectionChanged(UPSTREAM_IFACE);
781 
782         assertDhcpStarted(new IpPrefix("192.168.42.0/24"));
783     }
784 
785     @Test
testOnNewPrefixRequest()786     public void testOnNewPrefixRequest() throws Exception {
787         initStateMachine(TETHERING_NCM);
788         dispatchCommand(IpServer.CMD_TETHER_REQUESTED, 0, 0,
789                 createMockTetheringRequest(CONNECTIVITY_SCOPE_LOCAL));
790 
791         final IDhcpEventCallbacks eventCallbacks;
792         final ArgumentCaptor<IDhcpEventCallbacks> dhcpEventCbsCaptor =
793                  ArgumentCaptor.forClass(IDhcpEventCallbacks.class);
794         verify(mDhcpServer, timeout(MAKE_DHCPSERVER_TIMEOUT_MS).times(1)).startWithCallbacks(
795                 any(), dhcpEventCbsCaptor.capture());
796         eventCallbacks = dhcpEventCbsCaptor.getValue();
797         assertDhcpStarted(new IpPrefix("192.168.42.0/24"));
798 
799         final ArgumentCaptor<LinkProperties> lpCaptor =
800                 ArgumentCaptor.forClass(LinkProperties.class);
801         InOrder inOrder = inOrder(mNetd, mCallback, mRoutingCoordinatorManager);
802         inOrder.verify(mRoutingCoordinatorManager).requestStickyDownstreamAddress(anyInt(),
803                 eq(CONNECTIVITY_SCOPE_LOCAL), any());
804         inOrder.verify(mRoutingCoordinatorManager, never()).requestDownstreamAddress(any());
805         inOrder.verify(mNetd).networkAddInterface(INetd.LOCAL_NET_ID, IFACE_NAME);
806         // One for ipv4 route, one for ipv6 link local route.
807         inOrder.verify(mNetd, times(2)).networkAddRoute(eq(INetd.LOCAL_NET_ID), eq(IFACE_NAME),
808                 any(), any());
809         inOrder.verify(mCallback).updateInterfaceState(
810                 mIpServer, STATE_LOCAL_ONLY, TETHER_ERROR_NO_ERROR);
811         inOrder.verify(mCallback).updateLinkProperties(eq(mIpServer), lpCaptor.capture());
812         verifyNoMoreInteractions(mCallback, mRoutingCoordinatorManager);
813 
814         // Simulate the DHCP server receives DHCPDECLINE on MirrorLink and then signals
815         // onNewPrefixRequest callback.
816         final LinkAddress newAddress = new LinkAddress("192.168.100.125/24");
817         when(mRoutingCoordinatorManager.requestDownstreamAddress(any())).thenReturn(newAddress);
818         eventCallbacks.onNewPrefixRequest(new IpPrefix("192.168.42.0/24"));
819         mLooper.dispatchAll();
820 
821         inOrder.verify(mRoutingCoordinatorManager, never())
822                 .requestStickyDownstreamAddress(anyInt(), anyInt(), any());
823         inOrder.verify(mRoutingCoordinatorManager).requestDownstreamAddress(any());
824         inOrder.verify(mNetd).tetherApplyDnsInterfaces();
825         inOrder.verify(mCallback).updateLinkProperties(eq(mIpServer), lpCaptor.capture());
826         verifyNoMoreInteractions(mCallback);
827 
828         final LinkProperties linkProperties = lpCaptor.getValue();
829         final List<LinkAddress> linkAddresses = linkProperties.getLinkAddresses();
830         assertEquals(1, linkProperties.getLinkAddresses().size());
831         assertEquals(1, linkProperties.getRoutes().size());
832         final IpPrefix prefix = new IpPrefix(linkAddresses.get(0).getAddress(),
833                 linkAddresses.get(0).getPrefixLength());
834         assertNotEquals(prefix, new IpPrefix("192.168.42.0/24"));
835 
836         verify(mDhcpServer).updateParams(mDhcpParamsCaptor.capture(), any());
837         assertDhcpServingParams(mDhcpParamsCaptor.getValue(), prefix);
838     }
839 
840     @Test
doesNotStartDhcpServerIfDisabled()841     public void doesNotStartDhcpServerIfDisabled() throws Exception {
842         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, NO_ADDRESSES,
843                 true /* usingLegacyDhcp */, DEFAULT_USING_BPF_OFFLOAD);
844         dispatchTetherConnectionChanged(UPSTREAM_IFACE);
845 
846         verify(mDependencies, never()).makeDhcpServer(any(), any(), any());
847     }
848 
849     @Test
ipv6UpstreamInterfaceChanges()850     public void ipv6UpstreamInterfaceChanges() throws Exception {
851         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, UPSTREAM_ADDRESSES,
852                 false /* usingLegacyDhcp */, DEFAULT_USING_BPF_OFFLOAD);
853 
854         // Upstream interface changes result in updating the rules.
855         LinkProperties lp = new LinkProperties();
856         lp.setInterfaceName(UPSTREAM_IFACE2);
857         lp.setLinkAddresses(UPSTREAM_ADDRESSES);
858         dispatchTetherConnectionChanged(UPSTREAM_IFACE2, lp, -1);
859         verify(mBpfCoordinator).updateIpv6UpstreamInterface(
860                 mIpServer, UPSTREAM_IFINDEX2, UPSTREAM_PREFIXES);
861         reset(mBpfCoordinator);
862 
863         // Upstream link addresses change result in updating the rules.
864         LinkProperties lp2 = new LinkProperties();
865         lp2.setInterfaceName(UPSTREAM_IFACE2);
866         lp2.setLinkAddresses(UPSTREAM_ADDRESSES2);
867         dispatchTetherConnectionChanged(UPSTREAM_IFACE2, lp2, -1);
868         verify(mBpfCoordinator).updateIpv6UpstreamInterface(
869                 mIpServer, UPSTREAM_IFINDEX2, UPSTREAM_PREFIXES2);
870         reset(mBpfCoordinator);
871 
872         // When the upstream is lost, rules are removed.
873         dispatchTetherConnectionChanged(null, null, 0);
874         // Upstream clear function is called two times by:
875         // - processMessage CMD_TETHER_CONNECTION_CHANGED for the upstream is lost.
876         // - processMessage CMD_IPV6_TETHER_UPDATE for the IPv6 upstream is lost.
877         // See dispatchTetherConnectionChanged.
878         verify(mBpfCoordinator, times(2)).updateIpv6UpstreamInterface(
879                 mIpServer, NO_UPSTREAM, NO_PREFIXES);
880         reset(mBpfCoordinator);
881 
882         // If the upstream is IPv4-only, no rules are added.
883         dispatchTetherConnectionChanged(UPSTREAM_IFACE);
884         verify(mBpfCoordinator, never()).updateIpv6UpstreamInterface(
885                 mIpServer, NO_UPSTREAM, NO_PREFIXES);
886         reset(mBpfCoordinator);
887 
888         // Rules are added again once upstream IPv6 connectivity is available.
889         lp.setInterfaceName(UPSTREAM_IFACE);
890         dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1);
891         verify(mBpfCoordinator).updateIpv6UpstreamInterface(
892                 mIpServer, UPSTREAM_IFINDEX, UPSTREAM_PREFIXES);
893         reset(mBpfCoordinator);
894 
895         // If upstream IPv6 connectivity is lost, rules are removed.
896         dispatchTetherConnectionChanged(UPSTREAM_IFACE, null, 0);
897         verify(mBpfCoordinator).updateIpv6UpstreamInterface(
898                 mIpServer, NO_UPSTREAM, NO_PREFIXES);
899         reset(mBpfCoordinator);
900 
901         // When upstream IPv6 connectivity comes back, rules are added.
902         lp.setInterfaceName(UPSTREAM_IFACE);
903         dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1);
904         verify(mBpfCoordinator).updateIpv6UpstreamInterface(
905                 mIpServer, UPSTREAM_IFINDEX, UPSTREAM_PREFIXES);
906         reset(mBpfCoordinator);
907 
908         // When the downstream interface goes down, rules are removed.
909         mIpServer.stop();
910         mLooper.dispatchAll();
911         verify(mBpfCoordinator).clearAllIpv6Rules(mIpServer);
912         verify(mBpfCoordinator).removeIpServer(mIpServer);
913         verify(mBpfCoordinator).updateIpv6UpstreamInterface(
914                 mIpServer, NO_UPSTREAM, NO_PREFIXES);
915         reset(mBpfCoordinator);
916     }
917 
918     @Test
removeIpServerWhenInterfaceDown()919     public void removeIpServerWhenInterfaceDown() throws Exception {
920         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, UPSTREAM_ADDRESSES,
921                 false /* usingLegacyDhcp */, DEFAULT_USING_BPF_OFFLOAD);
922 
923         mIpServer.stop();
924         mLooper.dispatchAll();
925         verify(mBpfCoordinator).removeIpServer(mIpServer);
926     }
927 
buildIpv6OnlyLinkProperties(final String iface)928     private LinkProperties buildIpv6OnlyLinkProperties(final String iface) {
929         final LinkProperties linkProp = new LinkProperties();
930         linkProp.setInterfaceName(iface);
931         linkProp.addLinkAddress(new LinkAddress("2001:db8::1/64"));
932         linkProp.addRoute(new RouteInfo(new IpPrefix("::/0"), null, iface, RTN_UNICAST));
933         final InetAddress dns = InetAddresses.parseNumericAddress("2001:4860:4860::8888");
934         linkProp.addDnsServer(dns);
935 
936         return linkProp;
937     }
938 
939     @Test
testAdjustTtlValue()940     public void testAdjustTtlValue() throws Exception {
941         final ArgumentCaptor<RaParams> raParamsCaptor =
942                 ArgumentCaptor.forClass(RaParams.class);
943         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
944         verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture());
945         final RaParams noV6Params = raParamsCaptor.getValue();
946         assertEquals(65, noV6Params.hopLimit);
947         reset(mRaDaemon);
948 
949         when(mNetd.getProcSysNet(
950                 INetd.IPV6, INetd.CONF, UPSTREAM_IFACE, "hop_limit")).thenReturn("64");
951         final LinkProperties lp = buildIpv6OnlyLinkProperties(UPSTREAM_IFACE);
952         dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, 1);
953         verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture());
954         final RaParams nonCellularParams = raParamsCaptor.getValue();
955         assertEquals(65, nonCellularParams.hopLimit);
956         reset(mRaDaemon);
957 
958         dispatchTetherConnectionChanged(UPSTREAM_IFACE, null, 0);
959         verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture());
960         final RaParams noUpstream = raParamsCaptor.getValue();
961         assertEquals(65, nonCellularParams.hopLimit);
962         reset(mRaDaemon);
963 
964         dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1);
965         verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture());
966         final RaParams cellularParams = raParamsCaptor.getValue();
967         assertEquals(63, cellularParams.hopLimit);
968         reset(mRaDaemon);
969     }
970 
971     @Test
testStopObsoleteDhcpServer()972     public void testStopObsoleteDhcpServer() throws Exception {
973         final ArgumentCaptor<DhcpServerCallbacks> cbCaptor =
974                 ArgumentCaptor.forClass(DhcpServerCallbacks.class);
975         doNothing().when(mDependencies).makeDhcpServer(any(), mDhcpParamsCaptor.capture(),
976                 cbCaptor.capture());
977         initStateMachine(TETHERING_WIFI);
978         dispatchCommand(IpServer.CMD_TETHER_REQUESTED, 0, 0,
979                 createMockTetheringRequest(CONNECTIVITY_SCOPE_GLOBAL));
980         verify(mDhcpServer, never()).startWithCallbacks(any(), any());
981 
982         // No stop dhcp server because dhcp server is not created yet.
983         dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED);
984         verify(mDhcpServer, never()).stop(any());
985 
986         // Stop obsolete dhcp server.
987         try {
988             final DhcpServerCallbacks cb = cbCaptor.getValue();
989             cb.onDhcpServerCreated(STATUS_SUCCESS, mDhcpServer);
990             mLooper.dispatchAll();
991         } catch (RemoteException e) {
992             fail(e.getMessage());
993         }
994         verify(mDhcpServer).stop(any());
995     }
996 
assertDhcpServingParams(final DhcpServingParamsParcel params, final IpPrefix prefix)997     private void assertDhcpServingParams(final DhcpServingParamsParcel params,
998             final IpPrefix prefix) {
999         // Last address byte is random
1000         assertTrue(prefix.contains(intToInet4AddressHTH(params.serverAddr)));
1001         assertEquals(prefix.getPrefixLength(), params.serverAddrPrefixLength);
1002         assertEquals(1, params.defaultRouters.length);
1003         assertEquals(params.serverAddr, params.defaultRouters[0]);
1004         assertEquals(1, params.dnsServers.length);
1005         assertEquals(params.serverAddr, params.dnsServers[0]);
1006         assertEquals(DHCP_LEASE_TIME_SECS, params.dhcpLeaseTimeSecs);
1007         if (mIpServer.interfaceType() == TETHERING_NCM) {
1008             assertTrue(params.changePrefixOnDecline);
1009         }
1010 
1011         if (mIpServer.interfaceType() == TETHERING_WIFI_P2P) {
1012             assertEquals(P2P_SUBNET_PREFIX_LENGTH, params.leasesSubnetPrefixLength);
1013         } else {
1014             assertEquals(DEFAULT_SUBNET_PREFIX_LENGTH, params.leasesSubnetPrefixLength);
1015         }
1016     }
1017 
assertDhcpStarted(IpPrefix expectedPrefix)1018     private void assertDhcpStarted(IpPrefix expectedPrefix) throws Exception {
1019         verify(mDependencies, times(1)).makeDhcpServer(eq(IFACE_NAME), any(), any());
1020         verify(mDhcpServer, timeout(MAKE_DHCPSERVER_TIMEOUT_MS).times(1)).startWithCallbacks(
1021                 any(), any());
1022         assertDhcpServingParams(mDhcpParamsCaptor.getValue(), expectedPrefix);
1023     }
1024 
createMockTetheringRequest(int connectivityScope)1025     private TetheringRequest createMockTetheringRequest(int connectivityScope) {
1026         TetheringRequest request = mock(TetheringRequest.class);
1027         when(request.getConnectivityScope()).thenReturn(connectivityScope);
1028         return request;
1029     }
1030 
1031     /**
1032      * Send a command to the state machine under test, and run the event loop to idle.
1033      *
1034      * @param command One of the IpServer.CMD_* constants.
1035      * @param arg1    An additional argument to pass.
1036      * @param arg2    An additional argument to pass.
1037      * @param obj     An additional object to pass.
1038      */
dispatchCommand(int command, int arg1, int arg2, Object obj)1039     private void dispatchCommand(int command, int arg1, int arg2, Object obj) {
1040         mIpServer.sendMessage(command, arg1, arg2, obj);
1041         mLooper.dispatchAll();
1042     }
1043 
1044     /**
1045      * Send a command to the state machine under test, and run the event loop to idle.
1046      *
1047      * @param command One of the IpServer.CMD_* constants.
1048      */
dispatchCommand(int command)1049     private void dispatchCommand(int command) {
1050         mIpServer.sendMessage(command);
1051         mLooper.dispatchAll();
1052     }
1053 
1054     /**
1055      * Special override to tell the state machine that the upstream interface has changed.
1056      *
1057      * @see #dispatchCommand(int)
1058      * @param upstreamIface String name of upstream interface (or null)
1059      * @param v6lp IPv6 LinkProperties of the upstream interface, or null for an IPv4-only upstream.
1060      */
dispatchTetherConnectionChanged(String upstreamIface, LinkProperties v6lp, int ttlAdjustment)1061     private void dispatchTetherConnectionChanged(String upstreamIface, LinkProperties v6lp,
1062             int ttlAdjustment) {
1063         dispatchTetherConnectionChanged(upstreamIface);
1064         mIpServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, ttlAdjustment, 0, v6lp);
1065         mLooper.dispatchAll();
1066     }
1067 
dispatchTetherConnectionChanged(String upstreamIface)1068     private void dispatchTetherConnectionChanged(String upstreamIface) {
1069         final InterfaceSet ifs = (upstreamIface != null) ? new InterfaceSet(upstreamIface) : null;
1070         mIpServer.sendMessage(IpServer.CMD_TETHER_CONNECTION_CHANGED, ifs);
1071         mLooper.dispatchAll();
1072     }
1073 
assertIPv4AddressAndDirectlyConnectedRoute(LinkProperties lp)1074     private void assertIPv4AddressAndDirectlyConnectedRoute(LinkProperties lp) {
1075         // Find the first IPv4 LinkAddress.
1076         LinkAddress addr4 = null;
1077         for (LinkAddress addr : lp.getLinkAddresses()) {
1078             if (!(addr.getAddress() instanceof Inet4Address)) continue;
1079             addr4 = addr;
1080             break;
1081         }
1082         assertNotNull("missing IPv4 address", addr4);
1083 
1084         final IpPrefix destination = new IpPrefix(addr4.getAddress(), addr4.getPrefixLength());
1085         // Assert the presence of the associated directly connected route.
1086         final RouteInfo directlyConnected = new RouteInfo(destination, null, lp.getInterfaceName(),
1087                 RouteInfo.RTN_UNICAST);
1088         assertTrue("missing directly connected route: '" + directlyConnected.toString() + "'",
1089                    lp.getRoutes().contains(directlyConnected));
1090     }
1091 
assertNoAddressesNorRoutes(LinkProperties lp)1092     private void assertNoAddressesNorRoutes(LinkProperties lp) {
1093         assertTrue(lp.getLinkAddresses().isEmpty());
1094         assertTrue(lp.getRoutes().isEmpty());
1095         // We also check that interface name is non-empty, because we should
1096         // never see an empty interface name in any LinkProperties update.
1097         assertFalse(TextUtils.isEmpty(lp.getInterfaceName()));
1098     }
1099 
assertContainsFlag(String[] flags, String match)1100     private boolean assertContainsFlag(String[] flags, String match) {
1101         for (String flag : flags) {
1102             if (flag.equals(match)) return true;
1103         }
1104         return false;
1105     }
1106 
assertNotContainsFlag(String[] flags, String match)1107     private boolean assertNotContainsFlag(String[] flags, String match) {
1108         for (String flag : flags) {
1109             if (flag.equals(match)) {
1110                 fail("Unexpected flag: " + match);
1111                 return false;
1112             }
1113         }
1114         return true;
1115     }
1116 
1117     @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
1118     @SetFeatureFlagsRule.FeatureFlag(name = TETHERING_LOCAL_NETWORK_AGENT)
1119     @Test
testTetheringNetworkAgent_tetheringAgentEnabled()1120     public void testTetheringNetworkAgent_tetheringAgentEnabled() throws Exception {
1121         doTestTetheringNetworkAgent(CONNECTIVITY_SCOPE_GLOBAL, true);
1122     }
1123 
1124     @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
1125     @SetFeatureFlagsRule.FeatureFlag(name = TETHERING_LOCAL_NETWORK_AGENT, enabled = false)
1126     @Test
testTetheringNetworkAgent_tetheringAgentDisabled()1127     public void testTetheringNetworkAgent_tetheringAgentDisabled() throws Exception {
1128         doTestTetheringNetworkAgent(CONNECTIVITY_SCOPE_GLOBAL, false);
1129     }
1130 
1131     // Verify Tethering Network Agent feature doesn't affect Wi-fi P2P Group Owner although
1132     // the code is mostly shared.
1133     @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
1134     @SetFeatureFlagsRule.FeatureFlag(name = TETHERING_LOCAL_NETWORK_AGENT)
1135     @Test
testTetheringNetworkAgent_p2pGroupOwnerAgentDisabled()1136     public void testTetheringNetworkAgent_p2pGroupOwnerAgentDisabled() throws Exception {
1137         doTestTetheringNetworkAgent(CONNECTIVITY_SCOPE_LOCAL, false);
1138     }
1139 
doTestTetheringNetworkAgent(int scope, boolean expectAgentEnabled)1140     private void doTestTetheringNetworkAgent(int scope, boolean expectAgentEnabled)
1141             throws Exception {
1142         initStateMachine(TETHERING_USB);
1143 
1144         final InOrder inOrder = inOrder(mNetworkAgent, mNetd);
1145         dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED,
1146                 0, createMockTetheringRequest(scope));
1147 
1148         inOrder.verify(mNetworkAgent, expectAgentEnabled ? times(1) : never()).register();
1149         inOrder.verify(mNetd, times(1)).tetherInterfaceAdd(anyString());
1150         if (expectAgentEnabled) {
1151             inOrder.verify(mNetd, never()).networkAddInterface(anyInt(), anyString());
1152             inOrder.verify(mNetd, never()).networkAddRoute(anyInt(), anyString(), any(), any());
1153             inOrder.verify(mNetworkAgent, times(1)).sendLinkProperties(any());
1154             inOrder.verify(mNetworkAgent, times(1)).markConnected();
1155         } else {
1156             inOrder.verify(mNetd, times(1)).networkAddInterface(anyInt(), anyString());
1157             inOrder.verify(mNetd, times(2)).networkAddRoute(anyInt(), anyString(), any(), any());
1158             inOrder.verify(mNetworkAgent, never()).sendLinkProperties(any());
1159             inOrder.verify(mNetworkAgent, never()).markConnected();
1160         }
1161 
1162         dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED);
1163         if (expectAgentEnabled) {
1164             inOrder.verify(mNetworkAgent, times(1)).unregister();
1165             inOrder.verify(mNetd, never()).networkRemoveInterface(anyInt(), anyString());
1166         } else {
1167             inOrder.verify(mNetworkAgent, never()).unregister();
1168             inOrder.verify(mNetd, times(1)).networkRemoveInterface(anyInt(), anyString());
1169         }
1170     }
1171 
1172     // Verify if the registration failed, tethering can be gracefully shutdown.
1173     @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
1174     @SetFeatureFlagsRule.FeatureFlag(name = TETHERING_LOCAL_NETWORK_AGENT)
1175     @Test
testTetheringNetworkAgent_registerThrows()1176     public void testTetheringNetworkAgent_registerThrows() throws Exception {
1177         initStateMachine(TETHERING_USB);
1178 
1179         final InOrder inOrder = inOrder(mNetworkAgent, mNetd, mCallback);
1180         doReturn(null).when(mNetworkAgent).getNetwork();
1181         doThrow(IllegalStateException.class).when(mNetworkAgent).register();
1182         dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED,
1183                 0, createMockTetheringRequest(CONNECTIVITY_SCOPE_GLOBAL));
1184 
1185         inOrder.verify(mNetworkAgent).register();
1186         inOrder.verify(mNetd, never()).networkCreate(any());
1187         inOrder.verify(mNetworkAgent, never()).sendLinkProperties(any());
1188         inOrder.verify(mNetworkAgent, never()).markConnected();
1189         inOrder.verify(mNetworkAgent, never()).unregister();
1190         inOrder.verify(mNetd, never()).networkDestroy(anyInt());
1191         inOrder.verify(mCallback).updateInterfaceState(
1192                 mIpServer, STATE_AVAILABLE, TETHER_ERROR_SERVICE_UNAVAIL);
1193     }
1194 
1195     // Verify if the network creation failed, tethering can be gracefully shutdown.
1196     @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
1197     @SetFeatureFlagsRule.FeatureFlag(name = TETHERING_LOCAL_NETWORK_AGENT)
1198     @Test
testTetheringNetworkAgent_netdThrows()1199     public void testTetheringNetworkAgent_netdThrows() throws Exception {
1200         initStateMachine(TETHERING_USB);
1201 
1202         final InOrder inOrder = inOrder(mNetworkAgent, mNetd, mCallback);
1203         doThrow(ServiceSpecificException.class).when(mNetd).tetherInterfaceAdd(any());
1204         dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED,
1205                 0, createMockTetheringRequest(CONNECTIVITY_SCOPE_GLOBAL));
1206 
1207         inOrder.verify(mNetworkAgent).register();
1208         inOrder.verify(mNetd, never()).networkCreate(any());
1209         inOrder.verify(mNetworkAgent, never()).sendLinkProperties(any());
1210         inOrder.verify(mNetworkAgent, never()).markConnected();
1211         inOrder.verify(mNetworkAgent).unregister();
1212         inOrder.verify(mNetd, never()).networkDestroy(anyInt());
1213         inOrder.verify(mCallback).updateInterfaceState(
1214                 mIpServer, STATE_AVAILABLE, TETHER_ERROR_TETHER_IFACE_ERROR);
1215     }
1216 
1217     // Verify when IPv6 address update, set routes accordingly.
1218     @IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
1219     @SetFeatureFlagsRule.FeatureFlag(name = TETHERING_LOCAL_NETWORK_AGENT)
1220     @Test
testTetheringNetworkAgent_ipv6AddressUpdate()1221     public void testTetheringNetworkAgent_ipv6AddressUpdate() throws Exception {
1222         initStateMachine(TETHERING_USB);
1223 
1224         final InOrder inOrder = inOrder(mNetworkAgent, mNetd);
1225         dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED,
1226                 0, createMockTetheringRequest(CONNECTIVITY_SCOPE_GLOBAL));
1227 
1228         inOrder.verify(mNetworkAgent).register();
1229         inOrder.verify(mNetd, never()).networkCreate(any());
1230         inOrder.verify(mNetd, never()).networkAddRoute(anyInt(), anyString(), any(), any());
1231 
1232         // Ipv6 link local route won't show up in the LinkProperties, so just
1233         // verify ipv4 route.
1234         final ArgumentCaptor<LinkProperties> lpCaptor =
1235                 ArgumentCaptor.forClass(LinkProperties.class);
1236         inOrder.verify(mNetworkAgent).sendLinkProperties(lpCaptor.capture());
1237         final RouteInfo expectedIpv4Route = new RouteInfo(PrefixUtils.asIpPrefix(mTestAddress),
1238                 null, IFACE_NAME, RouteInfo.RTN_UNICAST);
1239         assertRoutes(List.of(expectedIpv4Route), lpCaptor.getValue().getRoutes());
1240         assertEquals(IFACE_NAME, lpCaptor.getValue().getInterfaceName());
1241 
1242         inOrder.verify(mNetworkAgent).markConnected();
1243 
1244         // Mock ipv4-only upstream show up.
1245         dispatchTetherConnectionChanged(UPSTREAM_IFACE);
1246         inOrder.verifyNoMoreInteractions();
1247 
1248         // Verify LinkProperties is updated when IPv6 connectivity is available.
1249         final LinkProperties lp = new LinkProperties();
1250         lp.setInterfaceName(UPSTREAM_IFACE);
1251         lp.setLinkAddresses(UPSTREAM_ADDRESSES);
1252         dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1);
1253         inOrder.verify(mNetd, never()).networkAddRoute(anyInt(), anyString(), any(), any());
1254         inOrder.verify(mNetworkAgent).sendLinkProperties(lpCaptor.capture());
1255 
1256         // Expect one Ipv4 route, plus one Ipv6 route.
1257         final RouteInfo expectedIpv6Route = new RouteInfo(UPSTREAM_PREFIXES.toArray(
1258                 new IpPrefix[0])[0], null, IFACE_NAME, RouteInfo.RTN_UNICAST);
1259         assertRoutes(List.of(expectedIpv4Route, expectedIpv6Route),
1260                 lpCaptor.getValue().getRoutes());
1261         assertEquals(IFACE_NAME, lpCaptor.getValue().getInterfaceName());
1262 
1263         dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED);
1264         inOrder.verify(mNetworkAgent).unregister();
1265         inOrder.verify(mNetd, never()).networkDestroy(anyInt());
1266     }
1267 
assertRoutes(List<RouteInfo> expectedRoutes, List<RouteInfo> actualRoutes)1268     private void assertRoutes(List<RouteInfo> expectedRoutes, List<RouteInfo> actualRoutes) {
1269         assertTrue("Expected Routes: " + expectedRoutes + ", but got: " + actualRoutes,
1270                 expectedRoutes.equals(actualRoutes));
1271     }
1272 
1273     @Test @IgnoreUpTo(Build.VERSION_CODES.R)
dadProxyUpdates()1274     public void dadProxyUpdates() throws Exception {
1275         InOrder inOrder = inOrder(mDadProxy);
1276         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
1277         inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS);
1278 
1279         // Add an upstream without IPv6.
1280         dispatchTetherConnectionChanged(UPSTREAM_IFACE, null, 0);
1281         inOrder.verify(mDadProxy).setUpstreamIface(null);
1282 
1283         // Add IPv6 to the upstream.
1284         LinkProperties lp = new LinkProperties();
1285         lp.setInterfaceName(UPSTREAM_IFACE);
1286         dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, 0);
1287         inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS);
1288 
1289         // Change upstream.
1290         // New linkproperties is needed, otherwise changing the iface has no impact.
1291         LinkProperties lp2 = new LinkProperties();
1292         lp2.setInterfaceName(UPSTREAM_IFACE2);
1293         dispatchTetherConnectionChanged(UPSTREAM_IFACE2, lp2, 0);
1294         inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS2);
1295 
1296         // Lose IPv6 on the upstream...
1297         dispatchTetherConnectionChanged(UPSTREAM_IFACE2, null, 0);
1298         inOrder.verify(mDadProxy).setUpstreamIface(null);
1299 
1300         // ... and regain it on a different upstream.
1301         dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, 0);
1302         inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS);
1303 
1304         // Lose upstream.
1305         dispatchTetherConnectionChanged(null, null, 0);
1306         inOrder.verify(mDadProxy).setUpstreamIface(null);
1307 
1308         // Regain upstream.
1309         dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, 0);
1310         inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS);
1311 
1312         // Stop tethering.
1313         mIpServer.stop();
1314         mLooper.dispatchAll();
1315     }
1316 
checkDadProxyEnabled(boolean expectEnabled)1317     private void checkDadProxyEnabled(boolean expectEnabled) throws Exception {
1318         initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
1319         InOrder inOrder = inOrder(mDadProxy);
1320         // Add IPv6 to the upstream.
1321         LinkProperties lp = new LinkProperties();
1322         lp.setInterfaceName(UPSTREAM_IFACE);
1323         if (expectEnabled) {
1324             inOrder.verify(mDadProxy).setUpstreamIface(UPSTREAM_IFACE_PARAMS);
1325         } else {
1326             inOrder.verifyNoMoreInteractions();
1327         }
1328         // Stop tethering.
1329         mIpServer.stop();
1330         mLooper.dispatchAll();
1331         if (expectEnabled) {
1332             inOrder.verify(mDadProxy).stop();
1333         }
1334         else {
1335             verify(mDependencies, never()).getDadProxy(any(), any());
1336         }
1337     }
1338     @Test @IgnoreAfter(Build.VERSION_CODES.R)
testDadProxyUpdates_DisabledUpToR()1339     public void testDadProxyUpdates_DisabledUpToR() throws Exception {
1340         checkDadProxyEnabled(false);
1341     }
1342     @Test @IgnoreUpTo(Build.VERSION_CODES.R)
testDadProxyUpdates_EnabledAfterR()1343     public void testDadProxyUpdates_EnabledAfterR() throws Exception {
1344         checkDadProxyEnabled(true);
1345     }
1346 }
1347