diff --git a/Tethering/common/TetheringLib/api/system-current.txt b/Tethering/common/TetheringLib/api/system-current.txt index 844ff6471a2baade958af68342e38fe2f6a735ae..a287b428dbfe27420e626ed8edd2254ae356e14c 100644 --- a/Tethering/common/TetheringLib/api/system-current.txt +++ b/Tethering/common/TetheringLib/api/system-current.txt @@ -95,13 +95,16 @@ package android.net { method public default void onUpstreamChanged(@Nullable android.net.Network); } - public static class TetheringManager.TetheringRequest { + public static final class TetheringManager.TetheringRequest implements android.os.Parcelable { + method @FlaggedApi("com.android.net.flags.tethering_request_with_soft_ap_config") public int describeContents(); method @Nullable public android.net.LinkAddress getClientStaticIpv4Address(); method public int getConnectivityScope(); method @Nullable public android.net.LinkAddress getLocalIpv4Address(); method public boolean getShouldShowEntitlementUi(); method public int getTetheringType(); method public boolean isExemptFromEntitlementCheck(); + method @FlaggedApi("com.android.net.flags.tethering_request_with_soft_ap_config") public void writeToParcel(@NonNull android.os.Parcel, int); + field @FlaggedApi("com.android.net.flags.tethering_request_with_soft_ap_config") @NonNull public static final android.os.Parcelable.Creator<android.net.TetheringManager.TetheringRequest> CREATOR; } public static class TetheringManager.TetheringRequest.Builder { diff --git a/Tethering/common/TetheringLib/src/android/net/TetheringManager.java b/Tethering/common/TetheringLib/src/android/net/TetheringManager.java index cd914d35c54581f7728fe258b16d8d97fd313080..7b769d49fe7fa65e8fe8968e473dcd280e444ef6 100644 --- a/Tethering/common/TetheringLib/src/android/net/TetheringManager.java +++ b/Tethering/common/TetheringLib/src/android/net/TetheringManager.java @@ -18,6 +18,7 @@ package android.net; import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; import android.Manifest; +import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -28,6 +29,8 @@ import android.content.Context; import android.os.Bundle; import android.os.ConditionVariable; import android.os.IBinder; +import android.os.Parcel; +import android.os.Parcelable; import android.os.RemoteException; import android.os.ResultReceiver; import android.util.ArrayMap; @@ -59,6 +62,14 @@ import java.util.function.Supplier; */ @SystemApi public class TetheringManager { + // TODO : remove this class when udc-mainline-prod is abandoned and android.net.flags.Flags is + // available here + /** @hide */ + public static class Flags { + static final String TETHERING_REQUEST_WITH_SOFT_AP_CONFIG = + "com.android.net.flags.tethering_request_with_soft_ap_config"; + } + private static final String TAG = TetheringManager.class.getSimpleName(); private static final int DEFAULT_TIMEOUT_MS = 60_000; private static final long CONNECTOR_POLL_INTERVAL_MILLIS = 200L; @@ -673,14 +684,44 @@ public class TetheringManager { /** * Use with {@link #startTethering} to specify additional parameters when starting tethering. */ - public static class TetheringRequest { + public static final class TetheringRequest implements Parcelable { /** A configuration set for TetheringRequest. */ private final TetheringRequestParcel mRequestParcel; - private TetheringRequest(final TetheringRequestParcel request) { + private TetheringRequest(@NonNull final TetheringRequestParcel request) { mRequestParcel = request; } + private TetheringRequest(@NonNull Parcel in) { + mRequestParcel = in.readParcelable(TetheringRequestParcel.class.getClassLoader()); + } + + @FlaggedApi(Flags.TETHERING_REQUEST_WITH_SOFT_AP_CONFIG) + @NonNull + public static final Creator<TetheringRequest> CREATOR = new Creator<>() { + @Override + public TetheringRequest createFromParcel(@NonNull Parcel in) { + return new TetheringRequest(in); + } + + @Override + public TetheringRequest[] newArray(int size) { + return new TetheringRequest[size]; + } + }; + + @FlaggedApi(Flags.TETHERING_REQUEST_WITH_SOFT_AP_CONFIG) + @Override + public int describeContents() { + return 0; + } + + @FlaggedApi(Flags.TETHERING_REQUEST_WITH_SOFT_AP_CONFIG) + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeParcelable(mRequestParcel, flags); + } + /** Builder used to create TetheringRequest. */ public static class Builder { private final TetheringRequestParcel mBuilderParcel; diff --git a/common/flags.aconfig b/common/flags.aconfig index 010fafcfc85a2d079056b517c908d13d4463752f..965354d8b3ed30610d6d5483164760974493ae61 100644 --- a/common/flags.aconfig +++ b/common/flags.aconfig @@ -46,3 +46,9 @@ flag { bug: "308011229" } +flag { + name: "tethering_request_with_soft_ap_config" + namespace: "android_core_networking" + description: "The flag controls the access for the parcelable TetheringRequest with getSoftApConfiguration/setSoftApConfiguration API" + bug: "216524590" +} diff --git a/framework/aidl-export/android/net/TetheringManager.aidl b/framework/aidl-export/android/net/TetheringManager.aidl new file mode 100644 index 0000000000000000000000000000000000000000..1235722402614089bc9e74d85a47ba85d6d1ebbf --- /dev/null +++ b/framework/aidl-export/android/net/TetheringManager.aidl @@ -0,0 +1,20 @@ +/** + * + * Copyright (C) 2024 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; + +parcelable TetheringManager.TetheringRequest; diff --git a/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java b/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java index 274596f105279c7ce82faa7713616209d81c47fd..81608f73063e04b15100d0df5228065c564b6bf1 100644 --- a/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java +++ b/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java @@ -71,6 +71,8 @@ import android.telephony.TelephonyManager; import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; +import com.android.testutils.ParcelUtils; + import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -235,6 +237,26 @@ public class TetheringManagerTest { assertFalse(tr2.getShouldShowEntitlementUi()); } + @Test + public void testTetheringRequestParcelable() { + final LinkAddress localAddr = new LinkAddress("192.168.24.5/24"); + final LinkAddress clientAddr = new LinkAddress("192.168.24.100/24"); + final TetheringRequest unparceled = new TetheringRequest.Builder(TETHERING_USB) + .setStaticIpv4Addresses(localAddr, clientAddr) + .setExemptFromEntitlementCheck(true) + .setShouldShowEntitlementUi(false).build(); + final TetheringRequest parceled = ParcelUtils.parcelingRoundTrip(unparceled); + assertEquals(unparceled.getTetheringType(), parceled.getTetheringType()); + assertEquals(unparceled.getConnectivityScope(), parceled.getConnectivityScope()); + assertEquals(unparceled.getLocalIpv4Address(), parceled.getLocalIpv4Address()); + assertEquals(unparceled.getClientStaticIpv4Address(), + parceled.getClientStaticIpv4Address()); + assertEquals(unparceled.isExemptFromEntitlementCheck(), + parceled.isExemptFromEntitlementCheck()); + assertEquals(unparceled.getShouldShowEntitlementUi(), + parceled.getShouldShowEntitlementUi()); + } + @Test public void testRegisterTetheringEventCallback() throws Exception { final TestTetheringEventCallback tetherEventCallback =