Update shims for building an Ikev2VpnProfile from Builder

Add method to allow building an Ikev2VpnProfile from an
IkeTunnelConnectionParams and retrieve the IkeTunnelConnectionParams.
The methods take or return an object instead of
IkeTunnelConnectionParams since the IkeTunnelConnectionParams is
not available until API 31.

This commit also updates the implementation in shims to align the
way to create a Builder.

Bug: 226628416
Test: atest ctsNetTestCases
Test: atest CtsNetTestCasesLatestSdk in R/Q
Change-Id: I703666720b519644f51cf30c3f81edfcc122fd9d
diff --git a/Android.bp b/Android.bp
index 5340e98..ee104ff 100644
--- a/Android.bp
+++ b/Android.bp
@@ -183,6 +183,7 @@
         "framework-connectivity",
         "framework-connectivity-t.stubs.module_lib",
         "framework-tethering",
+        "android.net.ipsec.ike.stubs.module_lib",
     ],
     sdk_version: "module_current",
     visibility: ["//visibility:private"],
diff --git a/apishim/29/com/android/networkstack/apishim/api29/Ikev2VpnProfileBuilderShimImpl.java b/apishim/29/com/android/networkstack/apishim/api29/Ikev2VpnProfileBuilderShimImpl.java
index 754933a..ecf3f15 100644
--- a/apishim/29/com/android/networkstack/apishim/api29/Ikev2VpnProfileBuilderShimImpl.java
+++ b/apishim/29/com/android/networkstack/apishim/api29/Ikev2VpnProfileBuilderShimImpl.java
@@ -16,8 +16,11 @@
 
 package com.android.networkstack.apishim.api29;
 
+import android.os.Build;
+
+import androidx.annotation.RequiresApi;
+
 import com.android.networkstack.apishim.common.Ikev2VpnProfileBuilderShim;
-import com.android.networkstack.apishim.common.UnsupportedApiLevelException;
 
 /**
  * Implementation of Ikev2VpnProfileBuilderShim for API 29.
@@ -29,13 +32,6 @@
 // NOTE : the trick with the formal parameter only works because when this shim was introduced,
 // the stable API already contained the class that the caller needs to pass in; this won't
 // work for a class added in the latest API level.
+@RequiresApi(Build.VERSION_CODES.Q)
 public class Ikev2VpnProfileBuilderShimImpl<T> implements Ikev2VpnProfileBuilderShim<T> {
-    /**
-     * @see Ikev2VpnProfile.Builder#setRequiresInternetValidation(boolean)
-     */
-    @Override
-    public T setRequiresInternetValidation(T builder,
-            boolean requiresInternetValidation) throws UnsupportedApiLevelException {
-        throw new UnsupportedApiLevelException("Only supported from API level 33.");
-    }
 }
diff --git a/apishim/29/com/android/networkstack/apishim/api29/Ikev2VpnProfileShimImpl.java b/apishim/29/com/android/networkstack/apishim/api29/Ikev2VpnProfileShimImpl.java
index b3f5f43..0f8dae5 100644
--- a/apishim/29/com/android/networkstack/apishim/api29/Ikev2VpnProfileShimImpl.java
+++ b/apishim/29/com/android/networkstack/apishim/api29/Ikev2VpnProfileShimImpl.java
@@ -17,19 +17,10 @@
 package com.android.networkstack.apishim.api29;
 
 import com.android.networkstack.apishim.common.Ikev2VpnProfileShim;
-import com.android.networkstack.apishim.common.UnsupportedApiLevelException;
 
 /**
  * Implementation of Ikev2VpnProfileShim for API 29.
  * @param <T> type of profile, typically Ikev2VpnProfile
  */
 public class Ikev2VpnProfileShimImpl<T> implements Ikev2VpnProfileShim<T> {
-    /**
-     * @see Ikev2VpnProfile#isInternetValidationRequired(boolean)
-     */
-    @Override
-    public boolean isInternetValidationRequired(T profile)
-            throws UnsupportedApiLevelException {
-        throw new UnsupportedApiLevelException("Only supported from API level 33.");
-    }
 }
diff --git a/apishim/30/com/android/networkstack/apishim/api30/Ikev2VpnProfileBuilderShimImpl.java b/apishim/30/com/android/networkstack/apishim/api30/Ikev2VpnProfileBuilderShimImpl.java
index a8310ce..7c126a3 100644
--- a/apishim/30/com/android/networkstack/apishim/api30/Ikev2VpnProfileBuilderShimImpl.java
+++ b/apishim/30/com/android/networkstack/apishim/api30/Ikev2VpnProfileBuilderShimImpl.java
@@ -17,21 +17,105 @@
 package com.android.networkstack.apishim.api30;
 
 import android.net.Ikev2VpnProfile;
+import android.net.ProxyInfo;
+import android.os.Build;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 
 import com.android.networkstack.apishim.common.Ikev2VpnProfileBuilderShim;
+import com.android.networkstack.apishim.common.Ikev2VpnProfileShim;
+import com.android.networkstack.apishim.common.UnsupportedApiLevelException;
+
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+import java.util.List;
 
 /**
  * Implementation of Ikev2VpnProfileBuilderShim for API 30.
  */
 // TODO : when API29 is no longer supported, remove the type argument
+@RequiresApi(Build.VERSION_CODES.R)
 public class Ikev2VpnProfileBuilderShimImpl
         extends com.android.networkstack.apishim.api29.Ikev2VpnProfileBuilderShimImpl<
-                Ikev2VpnProfile.Builder
-        > {
+                Ikev2VpnProfile.Builder> {
+    protected Ikev2VpnProfile.Builder mBuilder;
+
+    protected Ikev2VpnProfileBuilderShimImpl(@Nullable String serverAddr,
+            @Nullable String identity, @Nullable Object params) {
+        if (serverAddr != null && identity != null) {
+            mBuilder = new Ikev2VpnProfile.Builder(serverAddr, identity);
+        }
+    }
     /**
      * Returns a new instance of this shim impl.
      */
-    public static Ikev2VpnProfileBuilderShim<Ikev2VpnProfile.Builder> newInstance() {
-        return new Ikev2VpnProfileBuilderShimImpl();
+    public static Ikev2VpnProfileBuilderShim<Ikev2VpnProfile.Builder> newInstance(
+            @Nullable String serverAddr, @Nullable String identity, @Nullable Object params) {
+        return new Ikev2VpnProfileBuilderShimImpl(serverAddr, identity, params);
+    }
+
+    @Override
+    public Ikev2VpnProfileBuilderShim<Ikev2VpnProfile.Builder> setAuthPsk(@NonNull byte[] psk) {
+        mBuilder.setAuthPsk(psk);
+        return this;
+    }
+
+    @Override
+    public Ikev2VpnProfileBuilderShim<Ikev2VpnProfile.Builder> setAuthUsernamePassword(
+            @NonNull String user, @NonNull String pass, @Nullable X509Certificate serverRootCa)
+            throws UnsupportedApiLevelException {
+        mBuilder.setAuthUsernamePassword(user, pass, serverRootCa);
+        return this;
+    }
+
+    @Override
+    public Ikev2VpnProfileBuilderShim<Ikev2VpnProfile.Builder> setAuthDigitalSignature(
+            @NonNull X509Certificate userCert, @NonNull PrivateKey key,
+            @Nullable X509Certificate serverRootCa) {
+        mBuilder.setAuthDigitalSignature(userCert, key, serverRootCa);
+        return this;
+    }
+
+    @Override
+    public Ikev2VpnProfileBuilderShim<Ikev2VpnProfile.Builder> setBypassable(boolean isBypassable) {
+        mBuilder.setBypassable(true);
+        return this;
+    }
+
+    @Override
+    public Ikev2VpnProfileBuilderShim<Ikev2VpnProfile.Builder> setProxy(@Nullable ProxyInfo proxy) {
+        mBuilder.setProxy(proxy);
+        return this;
+    }
+
+    @Override
+    public Ikev2VpnProfileBuilderShim<Ikev2VpnProfile.Builder> setMaxMtu(int mtu) {
+        mBuilder.setMaxMtu(mtu);
+        return this;
+    }
+
+    @Override
+    public Ikev2VpnProfileBuilderShim<Ikev2VpnProfile.Builder> setMetered(boolean isMetered) {
+        mBuilder.setMetered(isMetered);
+        return this;
+    }
+
+    @Override
+    public Ikev2VpnProfileBuilderShim<Ikev2VpnProfile.Builder> setAllowedAlgorithms(
+            @NonNull List<String> algorithmNames) {
+        mBuilder.setAllowedAlgorithms(algorithmNames);
+        return this;
+    }
+
+    @Override
+    public Ikev2VpnProfile.Builder getBuilder() {
+        return mBuilder;
+    }
+
+    @Override
+    public Ikev2VpnProfileShim build() {
+        return new Ikev2VpnProfileShimImpl(mBuilder.build());
     }
 }
diff --git a/apishim/30/com/android/networkstack/apishim/api30/Ikev2VpnProfileShimImpl.java b/apishim/30/com/android/networkstack/apishim/api30/Ikev2VpnProfileShimImpl.java
index cd7938f..71d68ab 100644
--- a/apishim/30/com/android/networkstack/apishim/api30/Ikev2VpnProfileShimImpl.java
+++ b/apishim/30/com/android/networkstack/apishim/api30/Ikev2VpnProfileShimImpl.java
@@ -18,18 +18,19 @@
 
 import android.net.Ikev2VpnProfile;
 
-import com.android.networkstack.apishim.common.Ikev2VpnProfileShim;
-
 /**
  * Implementation of Ikev2VpnProfileShim for API 30.
  */
 // TODO : when API29 is no longer supported, remove the type argument
 public class Ikev2VpnProfileShimImpl extends
         com.android.networkstack.apishim.api29.Ikev2VpnProfileShimImpl<Ikev2VpnProfile> {
-    /**
-     * Returns a new instance of this shim impl.
-     */
-    public static Ikev2VpnProfileShim<Ikev2VpnProfile> newInstance() {
-        return new Ikev2VpnProfileShimImpl();
+    protected Ikev2VpnProfile mProfile;
+
+    public Ikev2VpnProfileShimImpl(Ikev2VpnProfile profile) {
+        mProfile = profile;
+    }
+
+    public Ikev2VpnProfile getProfile() {
+        return mProfile;
     }
 }
diff --git a/apishim/31/com/android/networkstack/apishim/api31/Ikev2VpnProfileBuilderShimImpl.java b/apishim/31/com/android/networkstack/apishim/api31/Ikev2VpnProfileBuilderShimImpl.java
index d4f25d6..de60ff3 100644
--- a/apishim/31/com/android/networkstack/apishim/api31/Ikev2VpnProfileBuilderShimImpl.java
+++ b/apishim/31/com/android/networkstack/apishim/api31/Ikev2VpnProfileBuilderShimImpl.java
@@ -16,9 +16,19 @@
 
 package com.android.networkstack.apishim.api31;
 
+import android.os.Build;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
+
 /**
  * Implementation of Ikev2VpnProfileBuilderShim for API 31.
  */
+@RequiresApi(Build.VERSION_CODES.S)
 public class Ikev2VpnProfileBuilderShimImpl
         extends com.android.networkstack.apishim.api30.Ikev2VpnProfileBuilderShimImpl {
+    protected Ikev2VpnProfileBuilderShimImpl(@Nullable String serverAddr,
+            @Nullable String identity, @Nullable Object params) {
+        super(serverAddr, identity, params);
+    }
 }
diff --git a/apishim/31/com/android/networkstack/apishim/api31/Ikev2VpnProfileShimImpl.java b/apishim/31/com/android/networkstack/apishim/api31/Ikev2VpnProfileShimImpl.java
index e2d8b59..1a9e332 100644
--- a/apishim/31/com/android/networkstack/apishim/api31/Ikev2VpnProfileShimImpl.java
+++ b/apishim/31/com/android/networkstack/apishim/api31/Ikev2VpnProfileShimImpl.java
@@ -16,9 +16,14 @@
 
 package com.android.networkstack.apishim.api31;
 
+import android.net.Ikev2VpnProfile;
+
 /**
  * Implementation of Ikev2VpnProfileShim for API 31.
  */
 public class Ikev2VpnProfileShimImpl extends
         com.android.networkstack.apishim.api30.Ikev2VpnProfileShimImpl {
+    public Ikev2VpnProfileShimImpl(Ikev2VpnProfile profile) {
+        super(profile);
+    }
 }
diff --git a/apishim/33/com/android/networkstack/apishim/Ikev2VpnProfileBuilderShimImpl.java b/apishim/33/com/android/networkstack/apishim/Ikev2VpnProfileBuilderShimImpl.java
index d3315a2..634b6b5 100644
--- a/apishim/33/com/android/networkstack/apishim/Ikev2VpnProfileBuilderShimImpl.java
+++ b/apishim/33/com/android/networkstack/apishim/Ikev2VpnProfileBuilderShimImpl.java
@@ -17,9 +17,10 @@
 package com.android.networkstack.apishim;
 
 import android.net.Ikev2VpnProfile;
+import android.net.ipsec.ike.IkeTunnelConnectionParams;
 import android.os.Build;
 
-import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
 
 import com.android.modules.utils.build.SdkLevel;
@@ -31,16 +32,36 @@
 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
 public class Ikev2VpnProfileBuilderShimImpl
         extends com.android.networkstack.apishim.api31.Ikev2VpnProfileBuilderShimImpl {
+    private Ikev2VpnProfileBuilderShimImpl(@Nullable String serverAddr,
+            @Nullable String identity, @Nullable Object params) {
+        super(serverAddr, identity, params);
+
+        if (serverAddr == null && identity == null && params == null) {
+            throw new IllegalArgumentException(
+                    "serverAddr, identity and params should not be all null");
+        }
+        // Support building the Builder with an IkeTunnelConnectionParams from API 33.
+        if (params != null) {
+            if (!(params instanceof IkeTunnelConnectionParams)) {
+                throw new IllegalArgumentException("params should be an IkeTunnelConnectionParams");
+            }
+            mBuilder = new Ikev2VpnProfile.Builder((IkeTunnelConnectionParams) params);
+        } else {
+            mBuilder = new Ikev2VpnProfile.Builder(serverAddr, identity);
+        }
+    }
+
     /**
      * Returns a new instance of this shim impl.
      */
     @RequiresApi(Build.VERSION_CODES.R)
-    public static Ikev2VpnProfileBuilderShim<Ikev2VpnProfile.Builder> newInstance() {
+    public static Ikev2VpnProfileBuilderShim<Ikev2VpnProfile.Builder> newInstance(
+            @Nullable String serverAddr, @Nullable String identity, @Nullable Object params) {
         if (SdkLevel.isAtLeastT()) {
-            return new Ikev2VpnProfileBuilderShimImpl();
+            return new Ikev2VpnProfileBuilderShimImpl(serverAddr, identity, params);
         } else {
             return com.android.networkstack.apishim.api31.Ikev2VpnProfileBuilderShimImpl
-                    .newInstance();
+                    .newInstance(serverAddr, identity, params);
         }
     }
 
@@ -48,9 +69,19 @@
      * @see Ikev2VpnProfile.Builder#setRequiresInternetValidation(boolean)
      */
     @Override
-    public Ikev2VpnProfile.Builder setRequiresInternetValidation(
-            @NonNull final Ikev2VpnProfile.Builder builder, boolean requiresInternetValidation) {
-        builder.setRequiresInternetValidation(requiresInternetValidation);
-        return builder;
+    public Ikev2VpnProfileBuilderShim<Ikev2VpnProfile.Builder> setRequiresInternetValidation(
+            boolean requiresInternetValidation) {
+        mBuilder.setRequiresInternetValidation(requiresInternetValidation);
+        return this;
+    }
+
+    /**
+     * @see Ikev2VpnProfile.Builder#setLocalRoutesExcluded(boolean)
+     */
+    @Override
+    public Ikev2VpnProfileBuilderShim<Ikev2VpnProfile.Builder> setLocalRoutesExcluded(
+            boolean excludeLocalRoutes) {
+        mBuilder.setLocalRoutesExcluded(excludeLocalRoutes);
+        return this;
     }
 }
diff --git a/apishim/33/com/android/networkstack/apishim/Ikev2VpnProfileShimImpl.java b/apishim/33/com/android/networkstack/apishim/Ikev2VpnProfileShimImpl.java
index ccaf497..c3e35d3 100644
--- a/apishim/33/com/android/networkstack/apishim/Ikev2VpnProfileShimImpl.java
+++ b/apishim/33/com/android/networkstack/apishim/Ikev2VpnProfileShimImpl.java
@@ -19,35 +19,31 @@
 import android.net.Ikev2VpnProfile;
 import android.os.Build;
 
-import androidx.annotation.NonNull;
 import androidx.annotation.RequiresApi;
 
-import com.android.modules.utils.build.SdkLevel;
-import com.android.networkstack.apishim.common.Ikev2VpnProfileShim;
-
 /**
  * A shim for Ikev2VpnProfile
  */
 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
 public class Ikev2VpnProfileShimImpl
         extends com.android.networkstack.apishim.api31.Ikev2VpnProfileShimImpl {
-    /**
-     * Returns a new instance of this shim impl.
-     */
-    @RequiresApi(Build.VERSION_CODES.R)
-    public static Ikev2VpnProfileShim<Ikev2VpnProfile> newInstance() {
-        if (SdkLevel.isAtLeastT()) {
-            return new Ikev2VpnProfileShimImpl();
-        } else {
-            return com.android.networkstack.apishim.api31.Ikev2VpnProfileShimImpl.newInstance();
-        }
+    public Ikev2VpnProfileShimImpl(Ikev2VpnProfile profile) {
+       super(profile);
     }
 
     /**
      * @see Ikev2VpnProfile#isInternetValidationRequired()
      */
     @Override
-    public boolean isInternetValidationRequired(@NonNull final Ikev2VpnProfile profile) {
-        return profile.isInternetValidationRequired();
+    public boolean isInternetValidationRequired() {
+        return mProfile.isInternetValidationRequired();
+    }
+
+    /**
+     * @see Ikev2VpnProfile#getIkeTunnelConnectionParams()
+     */
+    @Override
+    public Object getIkeTunnelConnectionParams() {
+        return mProfile.getIkeTunnelConnectionParams();
     }
 }
diff --git a/apishim/common/com/android/networkstack/apishim/common/Ikev2VpnProfileBuilderShim.java b/apishim/common/com/android/networkstack/apishim/common/Ikev2VpnProfileBuilderShim.java
index b2483e3..0ad989e 100644
--- a/apishim/common/com/android/networkstack/apishim/common/Ikev2VpnProfileBuilderShim.java
+++ b/apishim/common/com/android/networkstack/apishim/common/Ikev2VpnProfileBuilderShim.java
@@ -16,6 +16,16 @@
 
 package com.android.networkstack.apishim.common;
 
+import android.net.ProxyInfo;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+import java.util.List;
+
+
 /**
  * A shim for Ikev2VpnProfile.Builder.
  *
@@ -28,6 +38,96 @@
     /**
      * @see Ikev2VpnProfile.Builder#setRequiresInternetValidation(boolean)
      */
-    T setRequiresInternetValidation(T builder, boolean requiresInternetValidation)
-            throws UnsupportedApiLevelException;
+    default Ikev2VpnProfileBuilderShim<T> setRequiresInternetValidation(
+            boolean requiresInternetValidation) throws UnsupportedApiLevelException {
+        throw new UnsupportedApiLevelException("Only supported from API 33");
+    }
+
+    /**
+     * @see Ikev2VpnProfile.Builder#setAuthPsk(byte[])
+     */
+    default Ikev2VpnProfileBuilderShim<T> setAuthPsk(@NonNull byte[] psk)
+            throws UnsupportedApiLevelException {
+        throw new UnsupportedApiLevelException("Only supported from API 30");
+    }
+
+    /**
+     * @see Ikev2VpnProfile.Builder#setAuthUsernamePassword(String, String, X509Certificate)
+     */
+    default Ikev2VpnProfileBuilderShim<T> setAuthUsernamePassword(@NonNull String user,
+            @NonNull String pass, @Nullable X509Certificate serverRootCa)
+            throws UnsupportedApiLevelException {
+        throw new UnsupportedApiLevelException("Only supported from API 30");
+    }
+
+    /**
+     * @see Ikev2VpnProfile.Builder#setAuthDigitalSignature(X509Certificate, PrivateKey,
+     *      X509Certificate)
+     */
+    default Ikev2VpnProfileBuilderShim<T> setAuthDigitalSignature(@NonNull X509Certificate userCert,
+            @NonNull PrivateKey key, @Nullable X509Certificate serverRootCa)
+            throws UnsupportedApiLevelException {
+        throw new UnsupportedApiLevelException("Only supported from API 30");
+    }
+
+    /**
+     * @see Ikev2VpnProfile.Builder#setBypassable(boolean)
+     */
+    default Ikev2VpnProfileBuilderShim<T> setBypassable(boolean isBypassable)
+            throws UnsupportedApiLevelException {
+        throw new UnsupportedApiLevelException("Only supported from API 30");
+    }
+
+    /**
+     * @see Ikev2VpnProfile.Builder#setProxy(ProxyInfo)
+     */
+    default Ikev2VpnProfileBuilderShim<T> setProxy(@Nullable ProxyInfo proxy)
+            throws UnsupportedApiLevelException {
+        throw new UnsupportedApiLevelException("Only supported from API 30");
+    }
+
+    /**
+     * @see Ikev2VpnProfile.Builder#setMaxMtu(int)
+     */
+    default Ikev2VpnProfileBuilderShim<T> setMaxMtu(int mtu) throws UnsupportedApiLevelException {
+        throw new UnsupportedApiLevelException("Only supported from API 30");
+    }
+
+    /**
+     * @see Ikev2VpnProfile.Builder#setMetered(boolean)
+     */
+    default Ikev2VpnProfileBuilderShim<T> setMetered(boolean isMetered)
+            throws UnsupportedApiLevelException {
+        throw new UnsupportedApiLevelException("Only supported from API 30");
+    }
+
+    /**
+     * @see Ikev2VpnProfile.Builder#setAllowedAlgorithms(List<String>)
+     */
+    default Ikev2VpnProfileBuilderShim<T> setAllowedAlgorithms(@NonNull List<String> algorithmNames)
+            throws UnsupportedApiLevelException {
+        throw new UnsupportedApiLevelException("Only supported from API 30");
+    }
+
+    /**
+     * @see Ikev2VpnProfile.Builder#setLocalRoutesExcluded(boolean)
+     */
+    default Ikev2VpnProfileBuilderShim<T> setLocalRoutesExcluded(boolean excludeLocalRoutes)
+            throws UnsupportedApiLevelException {
+        throw new UnsupportedApiLevelException("Only supported from API 33");
+    }
+
+    /**
+     * Get <T> type of builder, typically Ikev2VpnProfile.Builder
+     */
+    default T getBuilder() throws UnsupportedApiLevelException {
+        throw new UnsupportedApiLevelException("Only supported from API 30");
+    }
+
+    /**
+     * Build an Ikev2VpnProfileShim
+     */
+    default Ikev2VpnProfileShim build() throws UnsupportedApiLevelException {
+        throw new UnsupportedApiLevelException("Only supported from API 30");
+    }
 }
diff --git a/apishim/common/com/android/networkstack/apishim/common/Ikev2VpnProfileShim.java b/apishim/common/com/android/networkstack/apishim/common/Ikev2VpnProfileShim.java
index 4a79c43..a29c5bf 100644
--- a/apishim/common/com/android/networkstack/apishim/common/Ikev2VpnProfileShim.java
+++ b/apishim/common/com/android/networkstack/apishim/common/Ikev2VpnProfileShim.java
@@ -28,5 +28,21 @@
     /**
      * @see Ikev2VpnProfile#isInternetValidationRequired()
      */
-    boolean isInternetValidationRequired(T profile) throws UnsupportedApiLevelException;
+    default boolean isInternetValidationRequired() throws UnsupportedApiLevelException {
+        throw new UnsupportedApiLevelException("Only supported from API level 33.");
+    }
+
+    /**
+     * @see Ikev2VpnProfile#getIkeTunnelConnectionParams()
+     */
+    default Object getIkeTunnelConnectionParams() throws UnsupportedApiLevelException {
+        throw new UnsupportedApiLevelException("Only supported from API level 33.");
+    }
+
+    /**
+     * Return the <T> type of profile.
+     */
+    default T getProfile() throws UnsupportedApiLevelException {
+        throw new UnsupportedApiLevelException("Only supported from API level 30.");
+    }
 }