diff --git a/Android.bp b/Android.bp index 79734df6a9b9..a476278a087e 100644 --- a/Android.bp +++ b/Android.bp @@ -201,6 +201,7 @@ java_defaults { "core/java/android/net/INetworkScoreService.aidl", "core/java/android/net/INetworkStatsService.aidl", "core/java/android/net/INetworkStatsSession.aidl", + "core/java/android/net/ITestNetworkManager.aidl", "core/java/android/net/ITetheringStatsProvider.aidl", "core/java/android/net/nsd/INsdManager.aidl", "core/java/android/nfc/IAppCallback.aidl", diff --git a/api/test-current.txt b/api/test-current.txt index 400046bad74a..7dfccda1ab34 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -703,6 +703,21 @@ package android.net { field public static final android.os.Parcelable.Creator CREATOR; } + public final class TestNetworkInterface implements android.os.Parcelable { + ctor public TestNetworkInterface(android.os.ParcelFileDescriptor, String); + method public int describeContents(); + method public android.os.ParcelFileDescriptor getFileDescriptor(); + method public String getInterfaceName(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + + public class TestNetworkManager { + method public android.net.TestNetworkInterface createTunInterface(@NonNull android.net.LinkAddress[]); + method public void setupTestNetwork(@NonNull String, @NonNull android.os.IBinder); + method public void teardownTestNetwork(@NonNull android.net.Network); + } + public class TrafficStats { method public static long getLoopbackRxBytes(); method public static long getLoopbackRxPackets(); diff --git a/core/java/android/net/ITestNetworkManager.aidl b/core/java/android/net/ITestNetworkManager.aidl new file mode 100644 index 000000000000..119a30cb2ddb --- /dev/null +++ b/core/java/android/net/ITestNetworkManager.aidl @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2018, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.net.LinkAddress; +import android.net.TestNetworkInterface; +import android.os.IBinder; +import android.os.ParcelFileDescriptor; + +/** + * Interface that allows for creation and management of test-only networks. + * + * @hide + */ +interface ITestNetworkManager +{ + TestNetworkInterface createTunInterface(in LinkAddress[] linkAddrs); + + void setupTestNetwork(in String iface, in IBinder binder); + + void teardownTestNetwork(int netId); +} diff --git a/core/java/android/net/TestNetworkInterface.aidl b/core/java/android/net/TestNetworkInterface.aidl new file mode 100644 index 000000000000..e1f4f9f794eb --- /dev/null +++ b/core/java/android/net/TestNetworkInterface.aidl @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2019 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; + +/** @hide */ +parcelable TestNetworkInterface; diff --git a/core/java/android/net/TestNetworkInterface.java b/core/java/android/net/TestNetworkInterface.java new file mode 100644 index 000000000000..30e68f5b9854 --- /dev/null +++ b/core/java/android/net/TestNetworkInterface.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2019 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.annotation.TestApi; +import android.os.Parcel; +import android.os.ParcelFileDescriptor; +import android.os.Parcelable; + +/** + * This class is used to return the interface name and fd of the test interface + * + * @hide + */ +@TestApi +public final class TestNetworkInterface implements Parcelable { + private static final String TAG = "TestNetworkInterface"; + + private final ParcelFileDescriptor mFileDescriptor; + private final String mInterfaceName; + + @Override + public int describeContents() { + return (mFileDescriptor != null) ? Parcelable.CONTENTS_FILE_DESCRIPTOR : 0; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeParcelable(mFileDescriptor, PARCELABLE_WRITE_RETURN_VALUE); + out.writeString(mInterfaceName); + } + + public TestNetworkInterface(ParcelFileDescriptor pfd, String intf) { + mFileDescriptor = pfd; + mInterfaceName = intf; + } + + private TestNetworkInterface(Parcel in) { + mFileDescriptor = in.readParcelable(ParcelFileDescriptor.class.getClassLoader()); + mInterfaceName = in.readString(); + } + + public ParcelFileDescriptor getFileDescriptor() { + return mFileDescriptor; + } + + public String getInterfaceName() { + return mInterfaceName; + } + + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + public TestNetworkInterface createFromParcel(Parcel in) { + return new TestNetworkInterface(in); + } + + public TestNetworkInterface[] newArray(int size) { + return new TestNetworkInterface[size]; + } + }; +} diff --git a/core/java/android/net/TestNetworkManager.java b/core/java/android/net/TestNetworkManager.java new file mode 100644 index 000000000000..cd58e6641e51 --- /dev/null +++ b/core/java/android/net/TestNetworkManager.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.net; + +import android.annotation.NonNull; +import android.annotation.TestApi; +import android.content.Context; +import android.os.IBinder; +import android.os.RemoteException; + +import com.android.internal.util.Preconditions; + +/** + * Class that allows creation and management of per-app, test-only networks + * + * @hide + */ +@TestApi +public class TestNetworkManager { + @NonNull private static final String TAG = TestNetworkManager.class.getSimpleName(); + + @NonNull private final ITestNetworkManager mService; + @NonNull private final Context mContext; + + /** @hide */ + public TestNetworkManager(@NonNull Context context, @NonNull ITestNetworkManager service) { + mContext = Preconditions.checkNotNull(context, "missing Context"); + mService = Preconditions.checkNotNull(service, "missing ITestNetworkManager"); + } + + /** + * Teardown the capability-limited, testing-only network for a given interface + * + * @param network The test network that should be torn down + * @hide + */ + @TestApi + public void teardownTestNetwork(@NonNull Network network) { + try { + mService.teardownTestNetwork(network.netId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Sets up a capability-limited, testing-only network for a given interface + * + * @param iface the name of the interface to be used for the Network LinkProperties. + * @param binder A binder object guarding the lifecycle of this test network. + * @hide + */ + @TestApi + public void setupTestNetwork(@NonNull String iface, @NonNull IBinder binder) { + try { + mService.setupTestNetwork(iface, binder); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Create a tun interface for testing purposes + * + * @param linkAddrs an array of LinkAddresses to assign to the TUN interface + * @return A ParcelFileDescriptor of the underlying TUN interface. Close this to tear down the + * TUN interface. + * @hide + */ + @TestApi + public TestNetworkInterface createTunInterface(@NonNull LinkAddress[] linkAddrs) { + try { + return mService.createTunInterface(linkAddrs); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } +} diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java new file mode 100644 index 000000000000..013e9cc06371 --- /dev/null +++ b/services/core/java/com/android/server/TestNetworkService.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server; + +import static com.android.internal.util.Preconditions.checkNotNull; + +import android.annotation.NonNull; +import android.content.Context; +import android.net.INetd; +import android.net.ITestNetworkManager; +import android.net.LinkAddress; +import android.net.TestNetworkInterface; +import android.net.util.NetdService; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.IBinder; +import android.os.INetworkManagementService; +import android.util.Log; + +import com.android.internal.annotations.VisibleForTesting; + +/** @hide */ +class TestNetworkService extends ITestNetworkManager.Stub { + @NonNull private static final String TAG = TestNetworkService.class.getSimpleName(); + @NonNull private static final String TEST_NETWORK_TYPE = "TEST_NETWORK"; + + @NonNull private final Context mContext; + @NonNull private final INetworkManagementService mNMS; + @NonNull private final INetd mNetd; + + @NonNull private final HandlerThread mHandlerThread; + @NonNull private final Handler mHandler; + + @VisibleForTesting + protected TestNetworkService( + @NonNull Context context, @NonNull INetworkManagementService netManager) { + Log.d(TAG, "TestNetworkService starting up"); + + mHandlerThread = new HandlerThread("TestNetworkServiceThread"); + mHandlerThread.start(); + mHandler = new Handler(mHandlerThread.getLooper()); + + mContext = checkNotNull(context, "missing Context"); + mNMS = checkNotNull(netManager, "missing INetworkManagementService"); + mNetd = NetdService.getInstance(); + } + + /** + * Create a TUN interface with the given interface name and link addresses + * + *

This method will return the FileDescriptor to the TUN interface. Close it to tear down the + * TUN interface. + */ + @Override + public synchronized TestNetworkInterface createTunInterface(@NonNull LinkAddress[] linkAddrs) { + return null; + } + + /** + * Sets up a Network with extremely limited privileges, guarded by the MANAGE_TEST_NETWORKS + * permission. + * + *

This method provides a Network that is useful only for testing. + */ + @Override + public synchronized void setupTestNetwork(@NonNull String iface, @NonNull IBinder binder) {} + + /** Teardown a test network */ + @Override + public synchronized void teardownTestNetwork(int netId) {} +}