From a940e426c141127aef52b23c76eecaff3986ce2a Mon Sep 17 00:00:00 2001 From: Quang Anh Luong Date: Fri, 2 Feb 2024 14:30:01 +0900 Subject: [PATCH] Add SoftApConfiguration to TetheringRequest Allow apps to specify the SoftApConfiguration to use for Tethering via TetheringRequest. API-Coverage-Bug: 361242098 Bug: 216524590 Test: atest TetheringManagerTest Change-Id: I956a2f9dc989e7b2d404b84957d859035e4cd6e8 --- Tethering/common/TetheringLib/Android.bp | 11 ++- .../TetheringLib/api/system-current.txt | 2 + .../src/android/net/TetheringManager.java | 48 +++++++++++-- .../android/net/TetheringRequestParcel.aidl | 2 + .../tethering/cts/TetheringManagerTest.java | 72 +++++++++++++++++-- 5 files changed, 124 insertions(+), 11 deletions(-) diff --git a/Tethering/common/TetheringLib/Android.bp b/Tethering/common/TetheringLib/Android.bp index 203d828853..6e00756656 100644 --- a/Tethering/common/TetheringLib/Android.bp +++ b/Tethering/common/TetheringLib/Android.bp @@ -49,7 +49,10 @@ java_sdk_library { "//packages/modules/NetworkStack/tests:__subpackages__", "//packages/modules/Wifi/service/tests/wifitests", ], - stub_only_libs: ["framework-connectivity.stubs.module_lib"], + stub_only_libs: [ + "framework-connectivity.stubs.module_lib", + "sdk_module-lib_current_framework-wifi", + ], jarjar_rules: ":framework-tethering-jarjar-rules", installable: true, @@ -97,13 +100,17 @@ java_defaults { srcs: [ ":framework-tethering-srcs", ], - libs: ["framework-connectivity.stubs.module_lib"], + libs: [ + "framework-connectivity.stubs.module_lib", + "sdk_module-lib_current_framework-wifi", + ], static_libs: [ "com.android.net.flags-aconfig-java", ], aidl: { include_dirs: [ "packages/modules/Connectivity/framework/aidl-export", + "packages/modules/Wifi/framework/aidl-export", ], }, apex_available: ["com.android.tethering"], diff --git a/Tethering/common/TetheringLib/api/system-current.txt b/Tethering/common/TetheringLib/api/system-current.txt index cccafd58d2..3efaac2089 100644 --- a/Tethering/common/TetheringLib/api/system-current.txt +++ b/Tethering/common/TetheringLib/api/system-current.txt @@ -102,6 +102,7 @@ package android.net { method public int getConnectivityScope(); method @Nullable public android.net.LinkAddress getLocalIpv4Address(); method public boolean getShouldShowEntitlementUi(); + method @FlaggedApi("com.android.net.flags.tethering_request_with_soft_ap_config") @Nullable public android.net.wifi.SoftApConfiguration getSoftApConfiguration(); 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); @@ -114,6 +115,7 @@ package android.net { method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setConnectivityScope(int); method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setExemptFromEntitlementCheck(boolean); method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setShouldShowEntitlementUi(boolean); + method @FlaggedApi("com.android.net.flags.tethering_request_with_soft_ap_config") @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setSoftApConfiguration(@Nullable android.net.wifi.SoftApConfiguration); method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setStaticIpv4Addresses(@NonNull android.net.LinkAddress, @NonNull android.net.LinkAddress); } diff --git a/Tethering/common/TetheringLib/src/android/net/TetheringManager.java b/Tethering/common/TetheringLib/src/android/net/TetheringManager.java index 1f6011aafd..5aca642906 100644 --- a/Tethering/common/TetheringLib/src/android/net/TetheringManager.java +++ b/Tethering/common/TetheringLib/src/android/net/TetheringManager.java @@ -26,6 +26,8 @@ import android.annotation.RequiresPermission; import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.content.Context; +import android.net.wifi.SoftApConfiguration; +import android.net.wifi.WifiManager; import android.os.Bundle; import android.os.ConditionVariable; import android.os.IBinder; @@ -744,6 +746,7 @@ public class TetheringManager { mBuilderParcel.exemptFromEntitlementCheck = false; mBuilderParcel.showProvisioningUi = true; mBuilderParcel.connectivityScope = getDefaultConnectivityScope(type); + mBuilderParcel.softApConfig = null; } /** @@ -803,6 +806,30 @@ public class TetheringManager { return this; } + /** + * Set the desired SoftApConfiguration for {@link #TETHERING_WIFI}. If this is null or + * not set, then the persistent tethering SoftApConfiguration from + * {@link WifiManager#getSoftApConfiguration()} will be used. + *

+ * If TETHERING_WIFI is already enabled and a new request is made with a different + * SoftApConfiguration, the request will be accepted if the device can support an + * additional tethering Wi-Fi AP interface. Otherwise, the request will be rejected. + * + * @param softApConfig SoftApConfiguration to use. + * @throws IllegalArgumentException if the tethering type isn't TETHERING_WIFI. + */ + @FlaggedApi(Flags.FLAG_TETHERING_REQUEST_WITH_SOFT_AP_CONFIG) + @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) + @NonNull + public Builder setSoftApConfiguration(@Nullable SoftApConfiguration softApConfig) { + if (mBuilderParcel.tetheringType != TETHERING_WIFI) { + throw new IllegalArgumentException( + "SoftApConfiguration can only be set for TETHERING_WIFI"); + } + mBuilderParcel.softApConfig = softApConfig; + return this; + } + /** Build {@link TetheringRequest} with the currently set configuration. */ @NonNull public TetheringRequest build() { @@ -883,6 +910,15 @@ public class TetheringManager { return type == TETHERING_USB || type == TETHERING_ETHERNET || type == TETHERING_NCM; } + /** + * Get the desired SoftApConfiguration of the request, if one was specified. + */ + @FlaggedApi(Flags.FLAG_TETHERING_REQUEST_WITH_SOFT_AP_CONFIG) + @Nullable + public SoftApConfiguration getSoftApConfiguration() { + return mRequestParcel.softApConfig; + } + /** * Get a TetheringRequestParcel from the configuration * @hide @@ -896,9 +932,10 @@ public class TetheringManager { return "TetheringRequest [ type= " + mRequestParcel.tetheringType + ", localIPv4Address= " + mRequestParcel.localIPv4Address + ", staticClientAddress= " + mRequestParcel.staticClientAddress - + ", exemptFromEntitlementCheck= " - + mRequestParcel.exemptFromEntitlementCheck + ", showProvisioningUi= " - + mRequestParcel.showProvisioningUi + " ]"; + + ", exemptFromEntitlementCheck= " + mRequestParcel.exemptFromEntitlementCheck + + ", showProvisioningUi= " + mRequestParcel.showProvisioningUi + + ", softApConfig= " + mRequestParcel.softApConfig + + " ]"; } @Override @@ -912,7 +949,8 @@ public class TetheringManager { && Objects.equals(parcel.staticClientAddress, otherParcel.staticClientAddress) && parcel.exemptFromEntitlementCheck == otherParcel.exemptFromEntitlementCheck && parcel.showProvisioningUi == otherParcel.showProvisioningUi - && parcel.connectivityScope == otherParcel.connectivityScope; + && parcel.connectivityScope == otherParcel.connectivityScope + && Objects.equals(parcel.softApConfig, otherParcel.softApConfig); } @Override @@ -920,7 +958,7 @@ public class TetheringManager { TetheringRequestParcel parcel = getParcel(); return Objects.hash(parcel.tetheringType, parcel.localIPv4Address, parcel.staticClientAddress, parcel.exemptFromEntitlementCheck, - parcel.showProvisioningUi, parcel.connectivityScope); + parcel.showProvisioningUi, parcel.connectivityScope, parcel.softApConfig); } } diff --git a/Tethering/common/TetheringLib/src/android/net/TetheringRequestParcel.aidl b/Tethering/common/TetheringLib/src/android/net/TetheringRequestParcel.aidl index f13c970d28..ea7a3537a0 100644 --- a/Tethering/common/TetheringLib/src/android/net/TetheringRequestParcel.aidl +++ b/Tethering/common/TetheringLib/src/android/net/TetheringRequestParcel.aidl @@ -17,6 +17,7 @@ package android.net; import android.net.LinkAddress; +import android.net.wifi.SoftApConfiguration; /** * Configuration details for requesting tethering. @@ -29,4 +30,5 @@ parcelable TetheringRequestParcel { boolean exemptFromEntitlementCheck; boolean showProvisioningUi; int connectivityScope; + SoftApConfiguration softApConfig; } diff --git a/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java b/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java index 8794847880..1454d9a119 100644 --- a/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java +++ b/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java @@ -22,6 +22,9 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN; import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET; +import static android.net.TetheringManager.TETHERING_BLUETOOTH; +import static android.net.TetheringManager.TETHERING_ETHERNET; +import static android.net.TetheringManager.TETHERING_NCM; import static android.net.TetheringManager.TETHERING_USB; import static android.net.TetheringManager.TETHERING_WIFI; import static android.net.TetheringManager.TETHERING_WIFI_P2P; @@ -34,6 +37,7 @@ import static com.android.testutils.TestPermissionUtil.runAsShell; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -60,7 +64,9 @@ import android.net.cts.util.CtsNetUtils.TestNetworkCallback; import android.net.cts.util.CtsTetheringUtils; import android.net.cts.util.CtsTetheringUtils.StartTetheringCallback; import android.net.cts.util.CtsTetheringUtils.TestTetheringEventCallback; +import android.net.wifi.SoftApConfiguration; import android.net.wifi.WifiManager; +import android.net.wifi.WifiSsid; import android.os.Bundle; import android.os.PersistableBundle; import android.os.ResultReceiver; @@ -71,6 +77,7 @@ import android.telephony.TelephonyManager; import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; +import com.android.modules.utils.build.SdkLevel; import com.android.testutils.ParcelUtils; import org.junit.After; @@ -78,6 +85,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -216,12 +224,26 @@ public class TetheringManagerTest { @Test public void testTetheringRequest() { - final TetheringRequest tr = new TetheringRequest.Builder(TETHERING_WIFI).build(); + SoftApConfiguration softApConfiguration; + if (SdkLevel.isAtLeastT()) { + softApConfiguration = new SoftApConfiguration.Builder() + .setWifiSsid(WifiSsid.fromBytes( + "This is an SSID!".getBytes(StandardCharsets.UTF_8))) + .build(); + } else { + softApConfiguration = new SoftApConfiguration.Builder() + .setSsid("This is an SSID!") + .build(); + } + final TetheringRequest tr = new TetheringRequest.Builder(TETHERING_WIFI) + .setSoftApConfiguration(softApConfiguration) + .build(); assertEquals(TETHERING_WIFI, tr.getTetheringType()); assertNull(tr.getLocalIpv4Address()); assertNull(tr.getClientStaticIpv4Address()); assertFalse(tr.isExemptFromEntitlementCheck()); assertTrue(tr.getShouldShowEntitlementUi()); + assertEquals(softApConfiguration, tr.getSoftApConfiguration()); final LinkAddress localAddr = new LinkAddress("192.168.24.5/24"); final LinkAddress clientAddr = new LinkAddress("192.168.24.100/24"); @@ -243,16 +265,58 @@ public class TetheringManagerTest { assertEquals(tr2, tr3); } + @Test + public void testTetheringRequestSetSoftApConfigurationFailsWhenNotWifi() { + final SoftApConfiguration softApConfiguration; + if (SdkLevel.isAtLeastT()) { + softApConfiguration = new SoftApConfiguration.Builder() + .setWifiSsid(WifiSsid.fromBytes( + "This is an SSID!".getBytes(StandardCharsets.UTF_8))) + .build(); + } else { + softApConfiguration = new SoftApConfiguration.Builder() + .setSsid("This is an SSID!") + .build(); + } + for (int type : List.of(TETHERING_USB, TETHERING_BLUETOOTH, TETHERING_WIFI_P2P, + TETHERING_NCM, TETHERING_ETHERNET)) { + try { + new TetheringRequest.Builder(type).setSoftApConfiguration(softApConfiguration); + fail("Was able to set SoftApConfiguration for tethering type " + type); + } catch (IllegalArgumentException e) { + // Success + } + } + } + @Test public void testTetheringRequestParcelable() { + final SoftApConfiguration softApConfiguration; + if (SdkLevel.isAtLeastT()) { + softApConfiguration = new SoftApConfiguration.Builder() + .setWifiSsid(WifiSsid.fromBytes( + "This is an SSID!".getBytes(StandardCharsets.UTF_8))) + .build(); + } else { + softApConfiguration = new SoftApConfiguration.Builder() + .setSsid("This is an SSID!") + .build(); + } 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) + final TetheringRequest withConfig = new TetheringRequest.Builder(TETHERING_WIFI) + .setSoftApConfiguration(softApConfiguration) .setStaticIpv4Addresses(localAddr, clientAddr) .setExemptFromEntitlementCheck(true) .setShouldShowEntitlementUi(false).build(); - final TetheringRequest parceled = ParcelUtils.parcelingRoundTrip(unparceled); - assertEquals(unparceled, parceled); + final TetheringRequest withoutConfig = new TetheringRequest.Builder(TETHERING_WIFI) + .setStaticIpv4Addresses(localAddr, clientAddr) + .setExemptFromEntitlementCheck(true) + .setShouldShowEntitlementUi(false).build(); + assertEquals(withConfig, ParcelUtils.parcelingRoundTrip(withConfig)); + assertEquals(withoutConfig, ParcelUtils.parcelingRoundTrip(withoutConfig)); + assertNotEquals(withConfig, ParcelUtils.parcelingRoundTrip(withoutConfig)); + assertNotEquals(withoutConfig, ParcelUtils.parcelingRoundTrip(withConfig)); } @Test