1 /* 2 * Copyright (C) 2024 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 package android.net.thread.utils; 17 18 import static android.Manifest.permission.MANAGE_TEST_NETWORKS; 19 20 import static com.android.testutils.RecorderCallback.CallbackEntry.LINK_PROPERTIES_CHANGED; 21 import static com.android.testutils.TestPermissionUtil.runAsShell; 22 23 import android.content.Context; 24 import android.net.ConnectivityManager; 25 import android.net.LinkProperties; 26 import android.net.Network; 27 import android.net.TestNetworkInterface; 28 import android.net.TestNetworkManager; 29 import android.os.Looper; 30 31 import com.android.testutils.TestableNetworkAgent; 32 import com.android.testutils.TestableNetworkCallback; 33 34 import java.io.IOException; 35 import java.time.Duration; 36 37 /** A class that can create/destroy a test network based on TAP interface. */ 38 public final class TapTestNetworkTracker { 39 private static final Duration TIMEOUT = Duration.ofSeconds(2); 40 private final Context mContext; 41 private final Looper mLooper; 42 private TestNetworkInterface mInterface; 43 private TestableNetworkAgent mAgent; 44 private Network mNetwork; 45 private final TestableNetworkCallback mNetworkCallback; 46 private final ConnectivityManager mConnectivityManager; 47 48 /** 49 * Constructs a {@link TapTestNetworkTracker}. 50 * 51 * <p>It creates a TAP interface (e.g. testtap0) and registers a test network using that 52 * interface. It also requests the test network by {@link ConnectivityManager#requestNetwork} so 53 * the test network won't be automatically turned down by {@link 54 * com.android.server.ConnectivityService}. 55 */ TapTestNetworkTracker(Context context, Looper looper)56 public TapTestNetworkTracker(Context context, Looper looper) { 57 mContext = context; 58 mLooper = looper; 59 mConnectivityManager = mContext.getSystemService(ConnectivityManager.class); 60 mNetworkCallback = new TestableNetworkCallback(); 61 runAsShell(MANAGE_TEST_NETWORKS, this::setUpTestNetwork); 62 } 63 64 /** Tears down the test network. */ tearDown()65 public void tearDown() { 66 runAsShell(MANAGE_TEST_NETWORKS, this::tearDownTestNetwork); 67 } 68 69 /** Returns the interface name of the test network. */ getInterfaceName()70 public String getInterfaceName() { 71 return mInterface.getInterfaceName(); 72 } 73 74 /** Returns the {@link android.net.Network} of the test network. */ getNetwork()75 public Network getNetwork() { 76 return mNetwork; 77 } 78 setUpTestNetwork()79 private void setUpTestNetwork() throws Exception { 80 mInterface = mContext.getSystemService(TestNetworkManager.class).createTapInterface(); 81 82 mConnectivityManager.requestNetwork( 83 TestableNetworkAgent.Companion.makeNetworkRequestForInterface( 84 mInterface.getInterfaceName()), 85 mNetworkCallback); 86 87 LinkProperties lp = new LinkProperties(); 88 lp.setInterfaceName(getInterfaceName()); 89 mAgent = 90 TestableNetworkAgent.Companion.createOnInterface( 91 mContext, mLooper, mInterface.getInterfaceName(), TIMEOUT.toMillis()); 92 93 mNetworkCallback.eventuallyExpect( 94 LINK_PROPERTIES_CHANGED, 95 TIMEOUT.toMillis(), 96 l -> !l.getLp().getAddresses().isEmpty()); 97 } 98 tearDownTestNetwork()99 private void tearDownTestNetwork() throws IOException { 100 mConnectivityManager.unregisterNetworkCallback(mNetworkCallback); 101 mAgent.unregister(); 102 mInterface.getFileDescriptor().close(); 103 mAgent.waitForIdle(TIMEOUT.toMillis()); 104 } 105 } 106