summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp1
-rw-r--r--OWNERS2
-rw-r--r--flags/Android.bp5
-rw-r--r--flags/main.aconfig19
-rw-r--r--src/com/google/android/iwlan/IwlanCarrierConfig.java93
-rw-r--r--src/com/google/android/iwlan/IwlanDataService.java50
-rw-r--r--src/com/google/android/iwlan/IwlanEventListener.java4
-rw-r--r--src/com/google/android/iwlan/epdg/EpdgChildSaProposal.java79
-rw-r--r--src/com/google/android/iwlan/epdg/EpdgIkeSaProposal.java117
-rw-r--r--src/com/google/android/iwlan/epdg/EpdgSaProposal.java329
-rw-r--r--src/com/google/android/iwlan/epdg/EpdgSelector.java7
-rw-r--r--src/com/google/android/iwlan/epdg/EpdgTunnelManager.java323
-rw-r--r--test/com/google/android/iwlan/IwlanDataServiceTest.java108
-rw-r--r--test/com/google/android/iwlan/IwlanEventListenerTest.java4
-rw-r--r--test/com/google/android/iwlan/epdg/EpdgTunnelManagerTest.java218
15 files changed, 1255 insertions, 104 deletions
diff --git a/Android.bp b/Android.bp
index 35a609a..3ac8129 100644
--- a/Android.bp
+++ b/Android.bp
@@ -30,6 +30,7 @@ android_app {
libs: [
"android.net.ipsec.ike.stubs.system",
+ "androidx.annotation_annotation",
"auto_value_annotations",
"framework-annotations-lib",
"framework-connectivity",
diff --git a/OWNERS b/OWNERS
index 54d6c0b..0d92786 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,5 +1,5 @@
-edensu@google.com
amreddy@google.com
radhikaagrawal@google.com
pochunlee@google.com
apsankar@google.com
+tairuw@google.com
diff --git a/flags/Android.bp b/flags/Android.bp
index 28aa750..f3e0c76 100644
--- a/flags/Android.bp
+++ b/flags/Android.bp
@@ -21,12 +21,13 @@ package {
aconfig_declarations {
name: "iwlan_telephony_flags",
package: "com.google.android.iwlan.flags",
+ container: "system",
srcs: [
- "main.aconfig",
+ "main.aconfig",
],
}
java_aconfig_library {
name: "iwlan_telephony_flags_lib",
- aconfig_declarations: "iwlan_telephony_flags"
+ aconfig_declarations: "iwlan_telephony_flags",
}
diff --git a/flags/main.aconfig b/flags/main.aconfig
index 9bc80a1..57b0527 100644
--- a/flags/main.aconfig
+++ b/flags/main.aconfig
@@ -1,4 +1,5 @@
package: "com.google.android.iwlan.flags"
+container: "system"
flag {
name: "prevent_epdg_selection_threads_exhausted"
@@ -7,6 +8,24 @@ flag {
bug: "278788983"
}
flag {
+ name: "aead_algos_enabled"
+ namespace: "iwlan_telephony"
+ description: "Add AES_GCM algorithm support in IWLAN."
+ bug: "306119890"
+}
+flag {
+ name: "multiple_sa_proposals"
+ namespace: "iwlan_telephony"
+ description: "Add multiple proposals of IKE SA and Child SA"
+ bug: "287296642"
+}
+flag {
+ name: "high_secure_transforms_prioritized"
+ namespace: "iwlan_telephony"
+ description: "Reorder IKE and Child SA security transforms with high secured as prioritized"
+ bug: "306323917"
+}
+flag {
name: "epdg_selection_exclude_failed_ip_address"
namespace: "iwlan_telephony"
description: "Exclude the failed ip address in epdg selection until tunnel establish successfully or all ip address candidates are failed"
diff --git a/src/com/google/android/iwlan/IwlanCarrierConfig.java b/src/com/google/android/iwlan/IwlanCarrierConfig.java
index bb3a20f..e68341a 100644
--- a/src/com/google/android/iwlan/IwlanCarrierConfig.java
+++ b/src/com/google/android/iwlan/IwlanCarrierConfig.java
@@ -21,6 +21,8 @@ import android.os.PersistableBundle;
import android.support.annotation.NonNull;
import android.telephony.CarrierConfigManager;
+import androidx.annotation.VisibleForTesting;
+
/** Class for handling IWLAN carrier configuration. */
public class IwlanCarrierConfig {
static final String PREFIX = "iwlan.";
@@ -42,6 +44,13 @@ public class IwlanCarrierConfig {
PREFIX + "n1_mode_exclusion_for_emergency_session";
/**
+ * Key to decide whether N1 mode shall be enabled or disabled depending on 5G enabling status
+ * via the UI/UX. See {@link #DEFAULT_UPDATE_N1_MODE_ON_UI_CHANGE_BOOL} for the default value.
+ */
+ public static final String KEY_UPDATE_N1_MODE_ON_UI_CHANGE_BOOL =
+ PREFIX + "update_n1_mode_on_ui_change_bool";
+
+ /**
* Default delay in seconds for releasing the IWLAN connection after a WWAN handover. This is
* the default value for {@link #KEY_HANDOVER_TO_WWAN_RELEASE_DELAY_SECOND_INT}.
*/
@@ -53,10 +62,18 @@ public class IwlanCarrierConfig {
*/
public static final boolean DEFAULT_N1_MODE_EXCLUSION_FOR_EMERGENCY_SESSION_BOOL = false;
- private static PersistableBundle mHiddenBundle = new PersistableBundle();
+ /**
+ * The default value for determining whether N1 mode shall be enabled or disabled depending on
+ * 5G enabling status via the UI/UX.
+ */
+ public static final boolean DEFAULT_UPDATE_N1_MODE_ON_UI_CHANGE_BOOL = true;
+
+ private static PersistableBundle sTestBundle = new PersistableBundle();
+
+ private static PersistableBundle sHiddenBundle = new PersistableBundle();
static {
- mHiddenBundle = createHiddenDefaultConfig();
+ sHiddenBundle = createHiddenDefaultConfig();
}
/**
@@ -72,6 +89,8 @@ public class IwlanCarrierConfig {
bundle.putBoolean(
KEY_N1_MODE_EXCLUSION_FOR_EMERGENCY_SESSION_BOOL,
DEFAULT_N1_MODE_EXCLUSION_FOR_EMERGENCY_SESSION_BOOL);
+ bundle.putBoolean(
+ KEY_UPDATE_N1_MODE_ON_UI_CHANGE_BOOL, DEFAULT_UPDATE_N1_MODE_ON_UI_CHANGE_BOOL);
return bundle;
}
@@ -88,13 +107,17 @@ public class IwlanCarrierConfig {
}
private static PersistableBundle getDefaultConfig(String key) {
+ if (sTestBundle.containsKey(key)) {
+ return sTestBundle;
+ }
+
PersistableBundle bundle = CarrierConfigManager.getDefaultConfig();
if (bundle.containsKey(key)) {
return bundle;
}
- if (mHiddenBundle.containsKey(key)) {
- return mHiddenBundle;
+ if (sHiddenBundle.containsKey(key)) {
+ return sHiddenBundle;
}
throw new IllegalArgumentException("Default config not found for key: " + key);
@@ -274,6 +297,7 @@ public class IwlanCarrierConfig {
public static boolean getDefaultConfigBoolean(String key) {
return getDefaultConfig(key).getBoolean(key);
}
+
/**
* Gets the default configuration int[] value for a given key.
*
@@ -295,6 +319,7 @@ public class IwlanCarrierConfig {
public static long[] getDefaultConfigLongArray(String key) {
return getDefaultConfig(key).getLongArray(key);
}
+
/**
* Gets the default configuration double[] value for a given key.
*
@@ -327,4 +352,64 @@ public class IwlanCarrierConfig {
public static boolean[] getDefaultConfigBooleanArray(String key) {
return getDefaultConfig(key).getBooleanArray(key);
}
+
+ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+ static void putTestConfigBundle(PersistableBundle bundle) {
+ sTestBundle.putAll(bundle);
+ }
+
+ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+ static void putTestConfigInt(@NonNull String key, int value) {
+ sTestBundle.putInt(key, value);
+ }
+
+ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+ static void putTestConfigLong(@NonNull String key, long value) {
+ sTestBundle.putLong(key, value);
+ }
+
+ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+ static void putTestConfigDouble(@NonNull String key, double value) {
+ sTestBundle.putDouble(key, value);
+ }
+
+ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+ static void putTestConfigBoolean(@NonNull String key, boolean value) {
+ sTestBundle.putBoolean(key, value);
+ }
+
+ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+ static void putTestConfigString(@NonNull String key, String value) {
+ sTestBundle.putString(key, value);
+ }
+
+ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+ static void putTestConfigIntArray(@NonNull String key, @NonNull int[] value) {
+ sTestBundle.putIntArray(key, value);
+ }
+
+ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+ static void putTestConfigLongArray(@NonNull String key, @NonNull long[] value) {
+ sTestBundle.putLongArray(key, value);
+ }
+
+ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+ static void putTestConfigDoubleArray(@NonNull String key, @NonNull double[] value) {
+ sTestBundle.putDoubleArray(key, value);
+ }
+
+ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+ static void putTestConfigBooleanArray(@NonNull String key, @NonNull boolean[] value) {
+ sTestBundle.putBooleanArray(key, value);
+ }
+
+ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+ static void putTestConfigStringArray(@NonNull String key, @NonNull String[] value) {
+ sTestBundle.putStringArray(key, value);
+ }
+
+ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+ static void resetTestConfig() {
+ sTestBundle.clear();
+ }
}
diff --git a/src/com/google/android/iwlan/IwlanDataService.java b/src/com/google/android/iwlan/IwlanDataService.java
index 2bf967a..7c680ea 100644
--- a/src/com/google/android/iwlan/IwlanDataService.java
+++ b/src/com/google/android/iwlan/IwlanDataService.java
@@ -20,6 +20,11 @@ import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.ipsec.ike.ike3gpp.Ike3gppParams.PDU_SESSION_ID_UNSET;
+import static com.google.android.iwlan.epdg.EpdgTunnelManager.BRINGDOWN_REASON_DEACTIVATE_DATA_CALL;
+import static com.google.android.iwlan.epdg.EpdgTunnelManager.BRINGDOWN_REASON_IN_DEACTIVATING_STATE;
+import static com.google.android.iwlan.epdg.EpdgTunnelManager.BRINGDOWN_REASON_NETWORK_UPDATE_WHEN_TUNNEL_IN_BRINGUP;
+import static com.google.android.iwlan.epdg.EpdgTunnelManager.BRINGDOWN_REASON_SERVICE_OUT_OF_SYNC;
+
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
@@ -923,7 +928,8 @@ public class IwlanDataService extends DataService {
entry.getKey(),
true /* forceClose */,
getIwlanTunnelCallback(),
- getIwlanTunnelMetrics());
+ getIwlanTunnelMetrics(),
+ BRINGDOWN_REASON_IN_DEACTIVATING_STATE);
}
}
}
@@ -1047,7 +1053,8 @@ public class IwlanDataService extends DataService {
entry.getKey(),
true /* forceClose */,
getIwlanTunnelCallback(),
- getIwlanTunnelMetrics());
+ getIwlanTunnelMetrics(),
+ BRINGDOWN_REASON_NETWORK_UPDATE_WHEN_TUNNEL_IN_BRINGUP);
}
}
}
@@ -1229,7 +1236,10 @@ public class IwlanDataService extends DataService {
// TODO(b/309867756): Include N1_MODE_CAPABILITY inclusion status in metrics.
private boolean needIncludeN1ModeCapability() {
- if (!mFeatureFlags.updateN1ModeOnUiChange()) {
+ if (!IwlanCarrierConfig.getConfigBoolean(
+ mContext,
+ getSlotIndex(),
+ IwlanCarrierConfig.KEY_UPDATE_N1_MODE_ON_UI_CHANGE_BOOL)) {
return isN1ModeSupported();
}
if (!isN1ModeSupported()) {
@@ -1247,10 +1257,10 @@ public class IwlanDataService extends DataService {
protected boolean isN1ModeSupported() {
int[] nrAvailabilities =
- IwlanHelper.getConfig(
- CarrierConfigManager.KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY,
+ IwlanCarrierConfig.getConfigIntArray(
mContext,
- getSlotIndex());
+ getSlotIndex(),
+ CarrierConfigManager.KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY);
Log.d(
TAG,
"KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY : "
@@ -1508,11 +1518,11 @@ public class IwlanDataService extends DataService {
if (cellInfolist != null
&& iwlanDataServiceProvider.isRegisteredCellInfoChanged(cellInfolist)) {
int[] addrResolutionMethods =
- IwlanHelper.getConfig(
- CarrierConfigManager.Iwlan
- .KEY_EPDG_ADDRESS_PRIORITY_INT_ARRAY,
+ IwlanCarrierConfig.getConfigIntArray(
mContext,
- iwlanDataServiceProvider.getSlotIndex());
+ iwlanDataServiceProvider.getSlotIndex(),
+ CarrierConfigManager.Iwlan
+ .KEY_EPDG_ADDRESS_PRIORITY_INT_ARRAY);
for (int addrResolutionMethod : addrResolutionMethods) {
if (addrResolutionMethod
== CarrierConfigManager.Iwlan.EPDG_ADDRESS_CELLULAR_LOC) {
@@ -1529,7 +1539,10 @@ public class IwlanDataService extends DataService {
int previousCallState = iwlanDataServiceProvider.mCallState;
int currentCallState = iwlanDataServiceProvider.mCallState = msg.arg2;
- if (!mFeatureFlags.updateN1ModeOnUiChange()) {
+ if (!IwlanCarrierConfig.getConfigBoolean(
+ mContext,
+ iwlanDataServiceProvider.getSlotIndex(),
+ IwlanCarrierConfig.KEY_UPDATE_N1_MODE_ON_UI_CHANGE_BOOL)) {
break;
}
@@ -1542,11 +1555,14 @@ public class IwlanDataService extends DataService {
break;
case IwlanEventListener.PREFERRED_NETWORK_TYPE_CHANGED_EVENT:
- if (!mFeatureFlags.updateN1ModeOnUiChange()) {
- break;
- }
iwlanDataServiceProvider =
(IwlanDataServiceProvider) getDataServiceProvider(msg.arg1);
+ if (!IwlanCarrierConfig.getConfigBoolean(
+ mContext,
+ iwlanDataServiceProvider.getSlotIndex(),
+ IwlanCarrierConfig.KEY_UPDATE_N1_MODE_ON_UI_CHANGE_BOOL)) {
+ break;
+ }
long allowedNetworkType = (long) msg.obj;
onPreferredNetworkTypeChanged(iwlanDataServiceProvider, allowedNetworkType);
break;
@@ -1642,7 +1658,8 @@ public class IwlanDataService extends DataService {
dataProfile.getApnSetting().getApnName(),
true /* forceClose */,
iwlanDataServiceProvider.getIwlanTunnelCallback(),
- iwlanDataServiceProvider.getIwlanTunnelMetrics());
+ iwlanDataServiceProvider.getIwlanTunnelMetrics(),
+ BRINGDOWN_REASON_SERVICE_OUT_OF_SYNC);
iwlanDataServiceProvider.deliverCallback(
IwlanDataServiceProvider.CALLBACK_TYPE_SETUP_DATACALL_COMPLETE,
5 /* DataServiceCallback
@@ -1913,7 +1930,8 @@ public class IwlanDataService extends DataService {
matchingApn,
isNetworkLost || isHandoverSuccessful, /* forceClose */
serviceProvider.getIwlanTunnelCallback(),
- serviceProvider.getIwlanTunnelMetrics());
+ serviceProvider.getIwlanTunnelMetrics(),
+ BRINGDOWN_REASON_DEACTIVATE_DATA_CALL);
}
private void resumePendingDeactivationIfExists(
diff --git a/src/com/google/android/iwlan/IwlanEventListener.java b/src/com/google/android/iwlan/IwlanEventListener.java
index 890afb4..427f4a7 100644
--- a/src/com/google/android/iwlan/IwlanEventListener.java
+++ b/src/com/google/android/iwlan/IwlanEventListener.java
@@ -187,10 +187,6 @@ public class IwlanEventListener {
public void onAllowedNetworkTypesChanged(
@TelephonyManager.AllowedNetworkTypesReason int reason,
@TelephonyManager.NetworkTypeBitMask long allowedNetworkType) {
- if (!mFeatureFlags.updateN1ModeOnUiChange()) {
- return;
- }
-
if (reason != TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER) {
return;
}
diff --git a/src/com/google/android/iwlan/epdg/EpdgChildSaProposal.java b/src/com/google/android/iwlan/epdg/EpdgChildSaProposal.java
new file mode 100644
index 0000000..d85e322
--- /dev/null
+++ b/src/com/google/android/iwlan/epdg/EpdgChildSaProposal.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2020 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.google.android.iwlan.epdg;
+
+import android.net.ipsec.ike.ChildSaProposal;
+import android.util.Pair;
+
+public class EpdgChildSaProposal extends EpdgSaProposal {
+ /**
+ * Builds {@link ChildSaProposal} of carrier proposed encryption algorithms (non-AEAD) cipher
+ * suit.
+ */
+ public ChildSaProposal buildProposedChildSaProposal() {
+ return buildProposal(false, true);
+ }
+
+ /** Builds {@link ChildSaProposal} of carrier proposed AEAD algorithms cipher suit. */
+ public ChildSaProposal buildProposedChildSaAeadProposal() {
+ return buildProposal(true, true);
+ }
+
+ /**
+ * Builds {@link ChildSaProposal} of Iwlan supported encryption algorithms (non-AEAD) cipher
+ * suit.
+ */
+ public ChildSaProposal buildSupportedChildSaProposal() {
+ return buildProposal(false, false);
+ }
+
+ /** Builds {@link ChildSaProposal} of Iwlan supported AEAD algorithms cipher suit. */
+ public ChildSaProposal buildSupportedChildSaAeadProposal() {
+ return buildProposal(true, false);
+ }
+
+ private ChildSaProposal buildProposal(boolean isAead, boolean isProposed) {
+ ChildSaProposal.Builder saProposalBuilder = new ChildSaProposal.Builder();
+
+ int[] dhGroups = getDhGroups();
+ for (int dhGroup : dhGroups) {
+ saProposalBuilder.addDhGroup(dhGroup);
+ }
+
+ Pair<Integer, Integer>[] encrAlgos;
+
+ if (isAead) {
+ encrAlgos = (isProposed) ? getAeadAlgos() : getSupportedAeadAlgos();
+ } else {
+ encrAlgos = (isProposed) ? getEncryptionAlgos() : getSupportedEncryptionAlgos();
+ }
+
+ for (Pair<Integer, Integer> encrAlgo : encrAlgos) {
+ saProposalBuilder.addEncryptionAlgorithm(encrAlgo.first, encrAlgo.second);
+ }
+
+ if (!isAead) {
+ int[] integrityAlgos =
+ (isProposed) ? getIntegrityAlgos() : getSupportedIntegrityAlgos();
+ for (int integrityAlgo : integrityAlgos) {
+ saProposalBuilder.addIntegrityAlgorithm(integrityAlgo);
+ }
+ }
+
+ return saProposalBuilder.build();
+ }
+}
diff --git a/src/com/google/android/iwlan/epdg/EpdgIkeSaProposal.java b/src/com/google/android/iwlan/epdg/EpdgIkeSaProposal.java
new file mode 100644
index 0000000..f4d6d56
--- /dev/null
+++ b/src/com/google/android/iwlan/epdg/EpdgIkeSaProposal.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2020 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.google.android.iwlan.epdg;
+
+import android.net.ipsec.ike.IkeSaProposal;
+import android.util.Pair;
+
+import java.util.LinkedHashSet;
+
+public class EpdgIkeSaProposal extends EpdgSaProposal {
+ protected final LinkedHashSet<Integer> mProposedPrfAlgos = new LinkedHashSet<>();
+
+ /**
+ * Add proposed PRF algorithms by the carrier.
+ *
+ * @param prfAlgos proposed PRF algorithms
+ */
+ public void addProposedPrfAlgorithm(int[] prfAlgos) {
+ for (int prfAlgo : prfAlgos) {
+ if (validateConfig(prfAlgo, VALID_PRF_ALGOS, CONFIG_TYPE_PRF_ALGO)) {
+ mProposedPrfAlgos.add(prfAlgo);
+ }
+ }
+ }
+
+ private int[] getPrfAlgos() {
+ if (isSaferProposalsPrioritized()) {
+ return mProposedPrfAlgos.stream()
+ .sorted(
+ (item1, item2) ->
+ compareTransformPriority(VALID_PRF_ALGOS, item1, item2))
+ .mapToInt(Integer::intValue)
+ .toArray();
+ }
+
+ return mProposedPrfAlgos.stream().mapToInt(Integer::intValue).toArray();
+ }
+
+ private int[] getSupportedPrfAlgos() {
+ return VALID_PRF_ALGOS.stream().mapToInt(Integer::intValue).toArray();
+ }
+
+ /**
+ * Builds {@link IkeSaProposal} of carrier proposed encryption algorithms (non-AEAD) cipher
+ * suit.
+ */
+ public IkeSaProposal buildProposedIkeSaProposal() {
+ return buildProposal(false, true);
+ }
+
+ /** Builds {@link IkeSaProposal} of carrier proposed AEAD algorithms cipher suit. */
+ public IkeSaProposal buildProposedIkeSaAeadProposal() {
+ return buildProposal(true, true);
+ }
+
+ /**
+ * Builds {@link IkeSaProposal} of Iwlan supported encryption algorithms (non-AEAD) cipher suit.
+ */
+ public IkeSaProposal buildSupportedIkeSaProposal() {
+ return buildProposal(false, false);
+ }
+
+ /** Builds {@link IkeSaProposal} of Iwlan supported AEAD algorithms cipher suit. */
+ public IkeSaProposal buildSupportedIkeSaAeadProposal() {
+ return buildProposal(true, false);
+ }
+
+ private IkeSaProposal buildProposal(boolean isAead, boolean isProposed) {
+ IkeSaProposal.Builder saProposalBuilder = new IkeSaProposal.Builder();
+
+ int[] dhGroups = isProposed ? getDhGroups() : getSupportedDhGroups();
+ for (int dhGroup : dhGroups) {
+ saProposalBuilder.addDhGroup(dhGroup);
+ }
+
+ Pair<Integer, Integer>[] encrAlgos;
+
+ if (isAead) {
+ encrAlgos = (isProposed) ? getAeadAlgos() : getSupportedAeadAlgos();
+ } else {
+ encrAlgos = (isProposed) ? getEncryptionAlgos() : getSupportedEncryptionAlgos();
+ }
+
+ for (Pair<Integer, Integer> encrAlgo : encrAlgos) {
+ saProposalBuilder.addEncryptionAlgorithm(encrAlgo.first, encrAlgo.second);
+ }
+
+ if (!isAead) {
+ int[] integrityAlgos =
+ (isProposed) ? getIntegrityAlgos() : getSupportedIntegrityAlgos();
+ for (int integrityAlgo : integrityAlgos) {
+ saProposalBuilder.addIntegrityAlgorithm(integrityAlgo);
+ }
+ }
+
+ int[] prfAlgos = (isProposed) ? getPrfAlgos() : getSupportedPrfAlgos();
+ for (int prfAlgo : prfAlgos) {
+ saProposalBuilder.addPseudorandomFunction(prfAlgo);
+ }
+
+ return saProposalBuilder.build();
+ }
+}
diff --git a/src/com/google/android/iwlan/epdg/EpdgSaProposal.java b/src/com/google/android/iwlan/epdg/EpdgSaProposal.java
new file mode 100644
index 0000000..871cc5c
--- /dev/null
+++ b/src/com/google/android/iwlan/epdg/EpdgSaProposal.java
@@ -0,0 +1,329 @@
+/*
+ * Copyright 2020 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.google.android.iwlan.epdg;
+
+import android.net.ipsec.ike.SaProposal;
+import android.util.Log;
+import android.util.Pair;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+abstract class EpdgSaProposal {
+ private static final String TAG = EpdgSaProposal.class.getSimpleName();
+ private static final Set<Integer> VALID_DH_GROUPS;
+ private static final Set<Integer> VALID_KEY_LENGTHS;
+ protected static final Set<Integer> VALID_PRF_ALGOS;
+ private static final Set<Integer> VALID_INTEGRITY_ALGOS;
+ private static final Set<Integer> VALID_ENCRYPTION_ALGOS;
+ private static final Set<Integer> VALID_AEAD_ALGOS;
+
+ private static final String CONFIG_TYPE_DH_GROUP = "dh group";
+ private static final String CONFIG_TYPE_KEY_LEN = "algorithm key length";
+ protected static final String CONFIG_TYPE_PRF_ALGO = "prf algorithm";
+ private static final String CONFIG_TYPE_INTEGRITY_ALGO = "integrity algorithm";
+ private static final String CONFIG_TYPE_ENCRYPT_ALGO = "encryption algorithm";
+ private static final String CONFIG_TYPE_AEAD_ALGO = "AEAD algorithm";
+
+ private boolean mSaferAlgosPrioritized = false;
+
+ /*
+ * Each transform below filled with high secured order and index of each value
+ * represents the priority.
+ * Safer transform has high priority and proposals will be orders based on
+ * the priority order.
+ * For example, DH Group 4096 has more priority compare to 3072, and 3072
+ * has more priority than 2048.
+ * With reference to 3GPP TS 33.210 and RFC 8221, high secured transforms
+ * are prioritized in IKE and CHILD SA proposals.
+ */
+ static {
+ VALID_DH_GROUPS =
+ Collections.unmodifiableSet(
+ new LinkedHashSet<Integer>(
+ List.of(
+ SaProposal.DH_GROUP_4096_BIT_MODP,
+ SaProposal.DH_GROUP_3072_BIT_MODP,
+ SaProposal.DH_GROUP_2048_BIT_MODP,
+ SaProposal.DH_GROUP_1536_BIT_MODP,
+ SaProposal.DH_GROUP_1024_BIT_MODP)));
+
+ VALID_KEY_LENGTHS =
+ Collections.unmodifiableSet(
+ new LinkedHashSet<Integer>(
+ List.of(
+ SaProposal.KEY_LEN_AES_256,
+ SaProposal.KEY_LEN_AES_192,
+ SaProposal.KEY_LEN_AES_128)));
+
+ VALID_ENCRYPTION_ALGOS =
+ Collections.unmodifiableSet(
+ new LinkedHashSet<Integer>(
+ List.of(
+ SaProposal.ENCRYPTION_ALGORITHM_AES_CBC,
+ SaProposal.ENCRYPTION_ALGORITHM_AES_CTR)));
+
+ VALID_INTEGRITY_ALGOS =
+ Collections.unmodifiableSet(
+ new LinkedHashSet<Integer>(
+ List.of(
+ SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_512_256,
+ SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_384_192,
+ SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_256_128,
+ SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96,
+ SaProposal.INTEGRITY_ALGORITHM_AES_XCBC_96)));
+
+ VALID_AEAD_ALGOS =
+ Collections.unmodifiableSet(
+ new LinkedHashSet<Integer>(
+ List.of(
+ SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16,
+ SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12,
+ SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8)));
+
+ VALID_PRF_ALGOS =
+ Collections.unmodifiableSet(
+ new LinkedHashSet<Integer>(
+ List.of(
+ SaProposal.PSEUDORANDOM_FUNCTION_SHA2_512,
+ SaProposal.PSEUDORANDOM_FUNCTION_SHA2_384,
+ SaProposal.PSEUDORANDOM_FUNCTION_SHA2_256,
+ SaProposal.PSEUDORANDOM_FUNCTION_HMAC_SHA1,
+ SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC)));
+ }
+
+ protected final LinkedHashSet<Integer> mProposedDhGroups = new LinkedHashSet<>();
+ protected final LinkedHashSet<Integer> mProposedIntegrityAlgos = new LinkedHashSet<>();
+ protected final LinkedHashSet<Pair<Integer, Integer>> mProposedEncryptAlgos =
+ new LinkedHashSet<>();
+ protected final LinkedHashSet<Pair<Integer, Integer>> mProposedAeadAlgos =
+ new LinkedHashSet<>();
+
+ /**
+ * Add proposed DH groups by the carrier.
+ *
+ * @param dhGroups proposed DH groups
+ */
+ public void addProposedDhGroups(int[] dhGroups) {
+ for (int dhGroup : dhGroups) {
+ if (validateConfig(dhGroup, VALID_DH_GROUPS, CONFIG_TYPE_DH_GROUP)) {
+ mProposedDhGroups.add(dhGroup);
+ }
+ }
+ }
+
+ /**
+ * Add proposed integrity algorithms by the carrier.
+ *
+ * @param integrityAlgos proposed integrity algorithms
+ */
+ public void addProposedIntegrityAlgorithm(int[] integrityAlgos) {
+ for (int integrityAlgo : integrityAlgos) {
+ if (validateConfig(integrityAlgo, VALID_INTEGRITY_ALGOS, CONFIG_TYPE_INTEGRITY_ALGO)) {
+ mProposedIntegrityAlgos.add(integrityAlgo);
+ }
+ }
+ }
+
+ /**
+ * Add proposed encryption algorithms and respective key lengths by the carrier.
+ *
+ * @param encryptionAlgo proposed encryption algorithm
+ * @param keyLens proposed key lengths for the encryption algorithm
+ */
+ public void addProposedEncryptionAlgorithm(int encryptionAlgo, int[] keyLens) {
+ if (validateConfig(encryptionAlgo, VALID_ENCRYPTION_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO)) {
+ for (int keyLen : keyLens) {
+ if (validateConfig(keyLen, VALID_KEY_LENGTHS, CONFIG_TYPE_KEY_LEN)) {
+ mProposedEncryptAlgos.add(new Pair<Integer, Integer>(encryptionAlgo, keyLen));
+ }
+ }
+ }
+ }
+
+ /**
+ * Add proposed AEAD algorithms and respective key lengths by the carrier.
+ *
+ * @param aeadAlgo proposed AEAD algorithm
+ * @param keyLens proposed key lengths for the encryption algorithm
+ */
+ public void addProposedAeadAlgorithm(int aeadAlgo, int[] keyLens) {
+ if (validateConfig(aeadAlgo, VALID_AEAD_ALGOS, CONFIG_TYPE_AEAD_ALGO)) {
+ for (int keyLen : keyLens) {
+ if (validateConfig(keyLen, VALID_KEY_LENGTHS, CONFIG_TYPE_KEY_LEN)) {
+ mProposedAeadAlgos.add(new Pair<Integer, Integer>(aeadAlgo, keyLen));
+ }
+ }
+ }
+ }
+
+ /** Enable to reorder proposals with safer ciphers prioritized. */
+ public void enableReorderingSaferProposals() {
+ mSaferAlgosPrioritized = true;
+ }
+
+ /**
+ * Disable to reorder proposals with safer ciphers prioritized.Follows default configured order.
+ */
+ public void disableReorderingSaferProposals() {
+ mSaferAlgosPrioritized = false;
+ }
+
+ protected boolean isSaferProposalsPrioritized() {
+ return mSaferAlgosPrioritized;
+ }
+
+ protected int getIndexOf(Set<Integer> set, int value) {
+ Iterator<Integer> itr = set.iterator();
+ int index = 0;
+
+ while (itr.hasNext()) {
+ if (itr.next().equals(value)) {
+ return index;
+ }
+ index++;
+ }
+
+ return -1;
+ }
+
+ /**
+ * Compares the priority of the transforms.
+ */
+ protected int compareTransformPriority(Set<Integer> transformGroup, int item1, int item2) {
+ return getIndexOf(transformGroup, item1) - getIndexOf(transformGroup, item2);
+ }
+
+ /**
+ * Compares the priority of the encryption/AEAD transforms.
+ * First value in pair is encryption/AEAD algorithm and
+ * second value in pair is key length of that algorithm.
+ * If Algorithms are same then compare the priotity of the key lengths else compare
+ * the priority of the algorithms.
+ */
+ protected int compareEncryptionTransformPriority(
+ Set<Integer> algos,
+ Set<Integer> keyLens,
+ Pair<Integer, Integer> item1,
+ Pair<Integer, Integer> item2) {
+ return item1.first.equals(item2.first)
+ ? getIndexOf(keyLens, item1.second) - getIndexOf(keyLens, item2.second)
+ : getIndexOf(algos, item1.first) - getIndexOf(algos, item2.first);
+ }
+
+ protected int[] getDhGroups() {
+ if (isSaferProposalsPrioritized()) {
+ return mProposedDhGroups.stream()
+ .sorted(
+ (item1, item2) ->
+ compareTransformPriority(VALID_DH_GROUPS, item1, item2))
+ .mapToInt(Integer::intValue)
+ .toArray();
+ }
+
+ return mProposedDhGroups.stream().mapToInt(Integer::intValue).toArray();
+ }
+
+ protected int[] getSupportedDhGroups() {
+ return VALID_DH_GROUPS.stream().mapToInt(Integer::intValue).toArray();
+ }
+
+ protected int[] getIntegrityAlgos() {
+ if (isSaferProposalsPrioritized()) {
+ return mProposedIntegrityAlgos.stream()
+ .sorted(
+ (item1, item2) ->
+ compareTransformPriority(VALID_INTEGRITY_ALGOS, item1, item2))
+ .mapToInt(Integer::intValue)
+ .toArray();
+ }
+
+ return mProposedIntegrityAlgos.stream().mapToInt(Integer::intValue).toArray();
+ }
+
+ protected int[] getSupportedIntegrityAlgos() {
+ return VALID_INTEGRITY_ALGOS.stream().mapToInt(Integer::intValue).toArray();
+ }
+
+ protected Pair<Integer, Integer>[] getEncryptionAlgos() {
+ if (isSaferProposalsPrioritized()) {
+ return mProposedEncryptAlgos.stream()
+ .sorted(
+ (item1, item2) ->
+ compareEncryptionTransformPriority(
+ VALID_ENCRYPTION_ALGOS,
+ VALID_KEY_LENGTHS,
+ item1,
+ item2))
+ .toArray(Pair[]::new);
+ }
+
+ return mProposedEncryptAlgos.toArray(new Pair[mProposedEncryptAlgos.size()]);
+ }
+
+ protected Pair<Integer, Integer>[] getSupportedEncryptionAlgos() {
+ Pair<Integer, Integer>[] encrAlgos =
+ new Pair[VALID_ENCRYPTION_ALGOS.size() * VALID_KEY_LENGTHS.size()];
+ int index = 0;
+ for (int algo : VALID_ENCRYPTION_ALGOS) {
+ for (int len : VALID_KEY_LENGTHS) {
+ encrAlgos[index++] = new Pair(algo, len);
+ }
+ }
+
+ return encrAlgos;
+ }
+
+ protected Pair<Integer, Integer>[] getAeadAlgos() {
+ if (isSaferProposalsPrioritized()) {
+ return mProposedAeadAlgos.stream()
+ .sorted(
+ (item1, item2) ->
+ compareEncryptionTransformPriority(
+ VALID_AEAD_ALGOS, VALID_KEY_LENGTHS, item1, item2))
+ .toArray(Pair[]::new);
+ }
+
+ return mProposedAeadAlgos.toArray(new Pair[mProposedAeadAlgos.size()]);
+ }
+
+ protected Pair<Integer, Integer>[] getSupportedAeadAlgos() {
+ Pair<Integer, Integer>[] aeadAlgos =
+ new Pair[VALID_AEAD_ALGOS.size() * VALID_KEY_LENGTHS.size()];
+ int index = 0;
+ for (int algo : VALID_AEAD_ALGOS) {
+ for (int len : VALID_KEY_LENGTHS) {
+ aeadAlgos[index++] = new Pair(algo, len);
+ }
+ }
+
+ return aeadAlgos;
+ }
+
+ protected static boolean validateConfig(
+ int config, Set<Integer> validConfigValues, String configType) {
+ if (validConfigValues.contains(config)) {
+ return true;
+ }
+
+ Log.e(TAG, "Invalid config value for " + configType + ":" + config);
+ return false;
+ }
+}
diff --git a/src/com/google/android/iwlan/epdg/EpdgSelector.java b/src/com/google/android/iwlan/epdg/EpdgSelector.java
index 3db6ac2..dc2c364 100644
--- a/src/com/google/android/iwlan/epdg/EpdgSelector.java
+++ b/src/com/google/android/iwlan/epdg/EpdgSelector.java
@@ -68,6 +68,7 @@ import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import java.util.regex.Pattern;
import java.util.stream.Collectors;
public class EpdgSelector {
@@ -101,6 +102,7 @@ public class EpdgSelector {
private static final int PCO_IPV6_LEN = 16; // 16 bytes for IPv6 address in PCO data.
private static final String NO_DOMAIN = "NO_DOMAIN";
+ private static final Pattern PLMN_PATTERN = Pattern.compile("\\d{5,6}");
BlockingQueue<Runnable> dnsResolutionQueue;
@@ -153,6 +155,9 @@ public class EpdgSelector {
mV4PcoData = new ArrayList<>();
mV6PcoData = new ArrayList<>();
+ mV4PcoData = new ArrayList<>();
+ mV6PcoData = new ArrayList<>();
+
mErrorPolicyManager = ErrorPolicyManager.getInstance(mContext, mSlotId);
mTemporaryExcludedAddresses = new HashSet<>();
@@ -1388,6 +1393,6 @@ public class EpdgSelector {
* @return True if the PLMN identifier is valid, false otherwise.
*/
private static boolean isValidPlmn(String plmn) {
- return plmn != null && plmn.matches("\\d{5,6}");
+ return plmn != null && PLMN_PATTERN.matcher(plmn).matches();
}
}
diff --git a/src/com/google/android/iwlan/epdg/EpdgTunnelManager.java b/src/com/google/android/iwlan/epdg/EpdgTunnelManager.java
index 47f3fa3..8b53ee1 100644
--- a/src/com/google/android/iwlan/epdg/EpdgTunnelManager.java
+++ b/src/com/google/android/iwlan/epdg/EpdgTunnelManager.java
@@ -76,6 +76,7 @@ import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.google.android.iwlan.ErrorPolicyManager;
+import com.google.android.iwlan.IwlanCarrierConfig;
import com.google.android.iwlan.IwlanError;
import com.google.android.iwlan.IwlanHelper;
import com.google.android.iwlan.IwlanTunnelMetricsImpl;
@@ -187,6 +188,7 @@ public class EpdgTunnelManager {
private static final Set<Integer> VALID_PRF_ALGOS;
private static final Set<Integer> VALID_INTEGRITY_ALGOS;
private static final Set<Integer> VALID_ENCRYPTION_ALGOS;
+ private static final Set<Integer> VALID_AEAD_ALGOS;
private static final String CONFIG_TYPE_DH_GROUP = "dh group";
private static final String CONFIG_TYPE_KEY_LEN = "algorithm key length";
@@ -221,6 +223,12 @@ public class EpdgTunnelManager {
SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_384_192,
SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_512_256);
+ VALID_AEAD_ALGOS =
+ Set.of(
+ SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8,
+ SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12,
+ SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16);
+
VALID_PRF_ALGOS =
Set.of(
SaProposal.PSEUDORANDOM_FUNCTION_HMAC_SHA1,
@@ -237,11 +245,19 @@ public class EpdgTunnelManager {
public static final int BRINGDOWN_REASON_UNKNOWN = 0;
public static final int BRINGDOWN_REASON_DISABLE_N1_MODE = 1;
public static final int BRINGDOWN_REASON_ENABLE_N1_MODE = 2;
+ public static final int BRINGDOWN_REASON_SERVICE_OUT_OF_SYNC = 3;
+ public static final int BRINGDOWN_REASON_IN_DEACTIVATING_STATE = 4;
+ public static final int BRINGDOWN_REASON_NETWORK_UPDATE_WHEN_TUNNEL_IN_BRINGUP = 5;
+ public static final int BRINGDOWN_REASON_DEACTIVATE_DATA_CALL = 6;
@IntDef({
BRINGDOWN_REASON_UNKNOWN,
BRINGDOWN_REASON_DISABLE_N1_MODE,
BRINGDOWN_REASON_ENABLE_N1_MODE,
+ BRINGDOWN_REASON_SERVICE_OUT_OF_SYNC,
+ BRINGDOWN_REASON_IN_DEACTIVATING_STATE,
+ BRINGDOWN_REASON_NETWORK_UPDATE_WHEN_TUNNEL_IN_BRINGUP,
+ BRINGDOWN_REASON_DEACTIVATE_DATA_CALL,
})
public @interface TunnelBringDownReason {}
@@ -253,6 +269,14 @@ public class EpdgTunnelManager {
return "BRINGDOWN_REASON_DISABLE_N1_MODE";
case BRINGDOWN_REASON_ENABLE_N1_MODE:
return "BRINGDOWN_REASON_ENABLE_N1_MODE";
+ case BRINGDOWN_REASON_SERVICE_OUT_OF_SYNC:
+ return "BRINGDOWN_REASON_SERVICE_OUT_OF_SYNC";
+ case BRINGDOWN_REASON_IN_DEACTIVATING_STATE:
+ return "BRINGDOWN_REASON_IN_DEACTIVATING_STATE";
+ case BRINGDOWN_REASON_NETWORK_UPDATE_WHEN_TUNNEL_IN_BRINGUP:
+ return "BRINGDOWN_REASON_NETWORK_UPDATE_WHEN_TUNNEL_IN_BRINGUP";
+ case BRINGDOWN_REASON_DEACTIVATE_DATA_CALL:
+ return "BRINGDOWN_REASON_DEACTIVATE_DATA_CALL";
default:
return "Unknown(" + reason + ")";
}
@@ -693,24 +717,6 @@ public class EpdgTunnelManager {
* provided in {@link #bringUpTunnel}. If no tunnel was available, callback will be delivered
* using client-provided provided tunnelCallback and iwlanTunnelMetrics
*
- * @param apnName apn name
- * @param forceClose if true, results in local cleanup of tunnel
- * @param tunnelCallback Used if no current or pending IWLAN tunnel exists
- * @param iwlanTunnelMetrics Used to report metrics if no current or pending IWLAN tunnel exists
- */
- // TODO(b/309866889): Clarify tunnel bring down reason for tunnel closure.
- public void closeTunnel(
- @NonNull String apnName,
- boolean forceClose,
- @NonNull TunnelCallback tunnelCallback,
- @NonNull IwlanTunnelMetricsImpl iwlanTunnelMetrics) {
- closeTunnel(
- apnName, forceClose, tunnelCallback, iwlanTunnelMetrics, BRINGDOWN_REASON_UNKNOWN);
- }
-
- /**
- * Closes tunnel for an apn with reason.
- *
* @param apnName APN name
* @param forceClose if {@code true}, triggers a local cleanup of the tunnel; if {@code false},
* performs a normal closure procedure
@@ -920,7 +926,35 @@ public class EpdgTunnelManager {
new TunnelModeChildSessionParams.Builder()
.setLifetimeSeconds(hardTimeSeconds, softTimeSeconds);
- childSessionParamsBuilder.addChildSaProposal(buildChildSaProposal());
+ if (mFeatureFlags.multipleSaProposals()
+ && IwlanCarrierConfig.getConfigBoolean(
+ mContext,
+ mSlotId,
+ CarrierConfigManager.Iwlan
+ .KEY_SUPPORTS_CHILD_SESSION_MULTIPLE_SA_PROPOSALS_BOOL)) {
+ EpdgChildSaProposal epdgChildSaProposal = createEpdgChildSaProposal();
+
+ if (mFeatureFlags.highSecureTransformsPrioritized()) {
+ epdgChildSaProposal.enableReorderingSaferProposals();
+ }
+
+ if (isChildSessionAeadAlgosAvailable()) {
+ childSessionParamsBuilder.addChildSaProposal(
+ epdgChildSaProposal.buildProposedChildSaAeadProposal());
+ }
+ childSessionParamsBuilder.addChildSaProposal(
+ epdgChildSaProposal.buildProposedChildSaProposal());
+ childSessionParamsBuilder.addChildSaProposal(
+ epdgChildSaProposal.buildSupportedChildSaAeadProposal());
+ childSessionParamsBuilder.addChildSaProposal(
+ epdgChildSaProposal.buildSupportedChildSaProposal());
+ } else {
+ if (mFeatureFlags.aeadAlgosEnabled() && isChildSessionAeadAlgosAvailable()) {
+ childSessionParamsBuilder.addChildSaProposal(buildAeadChildSaProposal());
+ } else {
+ childSessionParamsBuilder.addChildSaProposal(buildChildSaProposal());
+ }
+ }
boolean handoverIPv4Present = setupRequest.srcIpv4Address().isPresent();
boolean handoverIPv6Present = setupRequest.srcIpv6Address().isPresent();
@@ -1049,7 +1083,6 @@ public class EpdgTunnelManager {
.setLocalIdentification(getLocalIdentification())
.setRemoteIdentification(getId(setupRequest.apnName(), false))
.setAuthEap(null, getEapConfig())
- .addIkeSaProposal(buildIkeSaProposal())
.setNetwork(mDefaultNetwork)
.addIkeOption(IkeSessionParams.IKE_OPTION_ACCEPT_ANY_REMOTE_ID)
.addIkeOption(IkeSessionParams.IKE_OPTION_MOBIKE)
@@ -1058,6 +1091,32 @@ public class EpdgTunnelManager {
.setRetransmissionTimeoutsMillis(getRetransmissionTimeoutsFromConfig())
.setDpdDelaySeconds(getDpdDelayFromConfig());
+ if (mFeatureFlags.multipleSaProposals()
+ && IwlanCarrierConfig.getConfigBoolean(
+ mContext,
+ mSlotId,
+ CarrierConfigManager.Iwlan
+ .KEY_SUPPORTS_IKE_SESSION_MULTIPLE_SA_PROPOSALS_BOOL)) {
+ EpdgIkeSaProposal epdgIkeSaProposal = createEpdgIkeSaProposal();
+
+ if (mFeatureFlags.highSecureTransformsPrioritized()) {
+ epdgIkeSaProposal.enableReorderingSaferProposals();
+ }
+
+ if (isIkeSessionAeadAlgosAvailable()) {
+ builder.addIkeSaProposal(epdgIkeSaProposal.buildProposedIkeSaAeadProposal());
+ }
+ builder.addIkeSaProposal(epdgIkeSaProposal.buildProposedIkeSaProposal());
+ builder.addIkeSaProposal(epdgIkeSaProposal.buildSupportedIkeSaAeadProposal());
+ builder.addIkeSaProposal(epdgIkeSaProposal.buildSupportedIkeSaProposal());
+ } else {
+ if (mFeatureFlags.aeadAlgosEnabled() && isIkeSessionAeadAlgosAvailable()) {
+ builder.addIkeSaProposal(buildIkeSaAeadProposal());
+ } else {
+ builder.addIkeSaProposal(buildIkeSaProposal());
+ }
+ }
+
if (numPdnTunnels() == 0) {
builder.addIkeOption(IkeSessionParams.IKE_OPTION_INITIAL_CONTACT);
Log.d(TAG, "IKE_OPTION_INITIAL_CONTACT");
@@ -1122,6 +1181,32 @@ public class EpdgTunnelManager {
builder3gppParams.build(), new TmIke3gppCallback(apnName, token));
}
+ private boolean isChildSessionAeadAlgosAvailable() {
+ int[] encryptionAlgos =
+ getConfig(
+ CarrierConfigManager.Iwlan
+ .KEY_SUPPORTED_CHILD_SESSION_AEAD_ALGORITHMS_INT_ARRAY);
+ for (int encryptionAlgo : encryptionAlgos) {
+ if (validateConfig(encryptionAlgo, VALID_AEAD_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isIkeSessionAeadAlgosAvailable() {
+ int[] encryptionAlgos =
+ getConfig(
+ CarrierConfigManager.Iwlan
+ .KEY_SUPPORTED_IKE_SESSION_AEAD_ALGORITHMS_INT_ARRAY);
+ for (int encryptionAlgo : encryptionAlgos) {
+ if (validateConfig(encryptionAlgo, VALID_AEAD_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private boolean isValidChildSessionLifetime(int hardLifetimeSeconds, int softLifetimeSeconds) {
return hardLifetimeSeconds >= CHILD_HARD_LIFETIME_SEC_MINIMUM
&& hardLifetimeSeconds <= CHILD_HARD_LIFETIME_SEC_MAXIMUM
@@ -1140,6 +1225,124 @@ public class EpdgTunnelManager {
return IwlanHelper.getConfig(configKey, mContext, mSlotId);
}
+ private void createEpdgSaProposal(EpdgSaProposal epdgSaProposal, boolean isChildProposal) {
+ epdgSaProposal.addProposedDhGroups(
+ IwlanCarrierConfig.getConfigIntArray(
+ mContext,
+ mSlotId,
+ CarrierConfigManager.Iwlan.KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY));
+
+ int[] encryptionAlgos =
+ isChildProposal
+ ? IwlanCarrierConfig.getConfigIntArray(
+ mContext,
+ mSlotId,
+ CarrierConfigManager.Iwlan
+ .KEY_SUPPORTED_CHILD_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY)
+ : IwlanCarrierConfig.getConfigIntArray(
+ mContext,
+ mSlotId,
+ CarrierConfigManager.Iwlan
+ .KEY_SUPPORTED_IKE_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY);
+
+ for (int encryptionAlgo : encryptionAlgos) {
+ if (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_CBC) {
+ int[] aesCbcKeyLens =
+ isChildProposal
+ ? IwlanCarrierConfig.getConfigIntArray(
+ mContext,
+ mSlotId,
+ CarrierConfigManager.Iwlan
+ .KEY_CHILD_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY)
+ : IwlanCarrierConfig.getConfigIntArray(
+ mContext,
+ mSlotId,
+ CarrierConfigManager.Iwlan
+ .KEY_IKE_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY);
+ epdgSaProposal.addProposedEncryptionAlgorithm(encryptionAlgo, aesCbcKeyLens);
+ }
+
+ if (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_CTR) {
+ int[] aesCtrKeyLens =
+ isChildProposal
+ ? IwlanCarrierConfig.getConfigIntArray(
+ mContext,
+ mSlotId,
+ CarrierConfigManager.Iwlan
+ .KEY_CHILD_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY)
+ : IwlanCarrierConfig.getConfigIntArray(
+ mContext,
+ mSlotId,
+ CarrierConfigManager.Iwlan
+ .KEY_IKE_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY);
+ epdgSaProposal.addProposedEncryptionAlgorithm(encryptionAlgo, aesCtrKeyLens);
+ }
+ }
+
+ if (encryptionAlgos.length > 0) {
+ epdgSaProposal.addProposedIntegrityAlgorithm(
+ IwlanCarrierConfig.getConfigIntArray(
+ mContext,
+ mSlotId,
+ CarrierConfigManager.Iwlan
+ .KEY_SUPPORTED_INTEGRITY_ALGORITHMS_INT_ARRAY));
+ }
+
+ int[] aeadAlgos =
+ isChildProposal
+ ? IwlanCarrierConfig.getConfigIntArray(
+ mContext,
+ mSlotId,
+ CarrierConfigManager.Iwlan
+ .KEY_SUPPORTED_CHILD_SESSION_AEAD_ALGORITHMS_INT_ARRAY)
+ : IwlanCarrierConfig.getConfigIntArray(
+ mContext,
+ mSlotId,
+ CarrierConfigManager.Iwlan
+ .KEY_SUPPORTED_IKE_SESSION_AEAD_ALGORITHMS_INT_ARRAY);
+ for (int aeadAlgo : aeadAlgos) {
+ if (!validateConfig(aeadAlgo, VALID_AEAD_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO)) {
+ continue;
+ }
+ if ((aeadAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8)
+ || (aeadAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12)
+ || (aeadAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16)) {
+ int[] aesGcmKeyLens =
+ isChildProposal
+ ? IwlanCarrierConfig.getConfigIntArray(
+ mContext,
+ mSlotId,
+ CarrierConfigManager.Iwlan
+ .KEY_CHILD_SESSION_AES_GCM_KEY_SIZE_INT_ARRAY)
+ : IwlanCarrierConfig.getConfigIntArray(
+ mContext,
+ mSlotId,
+ CarrierConfigManager.Iwlan
+ .KEY_IKE_SESSION_AES_GCM_KEY_SIZE_INT_ARRAY);
+ epdgSaProposal.addProposedAeadAlgorithm(aeadAlgo, aesGcmKeyLens);
+ }
+ }
+ }
+
+ private EpdgChildSaProposal createEpdgChildSaProposal() {
+ EpdgChildSaProposal epdgChildSaProposal = new EpdgChildSaProposal();
+ createEpdgSaProposal(epdgChildSaProposal, true);
+ return epdgChildSaProposal;
+ }
+
+ private EpdgIkeSaProposal createEpdgIkeSaProposal() {
+ EpdgIkeSaProposal epdgIkeSaProposal = new EpdgIkeSaProposal();
+
+ createEpdgSaProposal(epdgIkeSaProposal, false);
+
+ epdgIkeSaProposal.addProposedPrfAlgorithm(
+ IwlanCarrierConfig.getConfigIntArray(
+ mContext,
+ mSlotId,
+ CarrierConfigManager.Iwlan.KEY_SUPPORTED_PRF_ALGORITHMS_INT_ARRAY));
+ return epdgIkeSaProposal;
+ }
+
private IkeSaProposal buildIkeSaProposal() {
IkeSaProposal.Builder saProposalBuilder = new IkeSaProposal.Builder();
@@ -1201,6 +1404,50 @@ public class EpdgTunnelManager {
return saProposalBuilder.build();
}
+ private IkeSaProposal buildIkeSaAeadProposal() {
+ IkeSaProposal.Builder saProposalBuilder = new IkeSaProposal.Builder();
+
+ int[] dhGroups = getConfig(CarrierConfigManager.Iwlan.KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY);
+ for (int dhGroup : dhGroups) {
+ if (validateConfig(dhGroup, VALID_DH_GROUPS, CONFIG_TYPE_DH_GROUP)) {
+ saProposalBuilder.addDhGroup(dhGroup);
+ }
+ }
+
+ int[] encryptionAlgos =
+ getConfig(
+ CarrierConfigManager.Iwlan
+ .KEY_SUPPORTED_IKE_SESSION_AEAD_ALGORITHMS_INT_ARRAY);
+ for (int encryptionAlgo : encryptionAlgos) {
+ if (!validateConfig(encryptionAlgo, VALID_AEAD_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO)) {
+ continue;
+ }
+ if ((encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8)
+ || (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12)
+ || (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16)) {
+ int[] aesGcmKeyLens =
+ getConfig(
+ CarrierConfigManager.Iwlan
+ .KEY_IKE_SESSION_AES_GCM_KEY_SIZE_INT_ARRAY);
+ for (int aesGcmKeyLen : aesGcmKeyLens) {
+ if (validateConfig(aesGcmKeyLen, VALID_KEY_LENGTHS, CONFIG_TYPE_KEY_LEN)) {
+ saProposalBuilder.addEncryptionAlgorithm(encryptionAlgo, aesGcmKeyLen);
+ }
+ }
+ }
+ }
+
+ int[] prfAlgos =
+ getConfig(CarrierConfigManager.Iwlan.KEY_SUPPORTED_PRF_ALGORITHMS_INT_ARRAY);
+ for (int prfAlgo : prfAlgos) {
+ if (validateConfig(prfAlgo, VALID_PRF_ALGOS, CONFIG_TYPE_PRF_ALGO)) {
+ saProposalBuilder.addPseudorandomFunction(prfAlgo);
+ }
+ }
+
+ return saProposalBuilder.build();
+ }
+
private boolean validateConfig(int config, Set<Integer> validConfigValues, String configType) {
if (validConfigValues.contains(config)) {
return true;
@@ -1280,6 +1527,42 @@ public class EpdgTunnelManager {
return saProposalBuilder.build();
}
+ private ChildSaProposal buildAeadChildSaProposal() {
+ ChildSaProposal.Builder saProposalBuilder = new ChildSaProposal.Builder();
+
+ int[] dhGroups = getConfig(CarrierConfigManager.Iwlan.KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY);
+ for (int dhGroup : dhGroups) {
+ if (validateConfig(dhGroup, VALID_DH_GROUPS, CONFIG_TYPE_DH_GROUP)) {
+ saProposalBuilder.addDhGroup(dhGroup);
+ }
+ }
+
+ int[] encryptionAlgos =
+ getConfig(
+ CarrierConfigManager.Iwlan
+ .KEY_SUPPORTED_CHILD_SESSION_AEAD_ALGORITHMS_INT_ARRAY);
+ for (int encryptionAlgo : encryptionAlgos) {
+ if (!validateConfig(encryptionAlgo, VALID_AEAD_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO)) {
+ continue;
+ }
+ if ((encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8)
+ || (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12)
+ || (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16)) {
+ int[] aesGcmKeyLens =
+ getConfig(
+ CarrierConfigManager.Iwlan
+ .KEY_CHILD_SESSION_AES_GCM_KEY_SIZE_INT_ARRAY);
+ for (int aesGcmKeyLen : aesGcmKeyLens) {
+ if (validateConfig(aesGcmKeyLen, VALID_KEY_LENGTHS, CONFIG_TYPE_KEY_LEN)) {
+ saProposalBuilder.addEncryptionAlgorithm(encryptionAlgo, aesGcmKeyLen);
+ }
+ }
+ }
+ }
+
+ return saProposalBuilder.build();
+ }
+
private IkeIdentification getLocalIdentification() throws IwlanSimNotReadyException {
String nai;
diff --git a/test/com/google/android/iwlan/IwlanDataServiceTest.java b/test/com/google/android/iwlan/IwlanDataServiceTest.java
index f5914d9..6168b82 100644
--- a/test/com/google/android/iwlan/IwlanDataServiceTest.java
+++ b/test/com/google/android/iwlan/IwlanDataServiceTest.java
@@ -27,6 +27,9 @@ import static android.telephony.TelephonyManager.NETWORK_TYPE_BITMASK_NR;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static com.google.android.iwlan.epdg.EpdgTunnelManager.BRINGDOWN_REASON_DEACTIVATE_DATA_CALL;
+import static com.google.android.iwlan.epdg.EpdgTunnelManager.BRINGDOWN_REASON_NETWORK_UPDATE_WHEN_TUNNEL_IN_BRINGUP;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
@@ -142,7 +145,6 @@ public class IwlanDataServiceTest {
@Mock private LinkAddress mMockIPv6LinkAddress;
@Mock private Inet4Address mMockInet4Address;
@Mock private Inet6Address mMockInet6Address;
- @Mock private CarrierConfigManager mMockCarrierConfigManager;
@Mock private FeatureFlags mFakeFeatureFlags;
MockitoSession mStaticMockSession;
@@ -213,7 +215,6 @@ public class IwlanDataServiceTest {
.mockStatic(ErrorPolicyManager.class)
.mockStatic(IwlanBroadcastReceiver.class)
.mockStatic(SubscriptionManager.class)
- .mockStatic(IwlanCarrierConfig.class)
.strictness(Strictness.LENIENT)
.startMocking();
@@ -262,8 +263,6 @@ public class IwlanDataServiceTest {
mIwlanDataService = spy(new IwlanDataService(mFakeFeatureFlags));
- when(mMockContext.getSystemService(eq(CarrierConfigManager.class)))
- .thenReturn(mMockCarrierConfigManager);
// Injects the test looper into the IwlanDataServiceHandler
doReturn(mTestLooper.getLooper()).when(mIwlanDataService).getLooper();
mIwlanDataService.setAppContext(mMockContext);
@@ -281,8 +280,9 @@ public class IwlanDataServiceTest {
when(mMockConnectivityManager.getLinkProperties(eq(mMockNetwork)))
.thenReturn(mLinkProperties);
-
when(mMockTunnelLinkProperties.ifaceName()).thenReturn("mockipsec0");
+
+ mockCarrierConfigForN1Mode(true);
}
private void moveTimeForwardAndDispatch(long milliSeconds) {
@@ -293,6 +293,7 @@ public class IwlanDataServiceTest {
@After
public void cleanUp() throws Exception {
mStaticMockSession.finishMocking();
+ IwlanCarrierConfig.resetTestConfig();
mSpyIwlanDataServiceProvider.close();
mTestLooper.dispatchAll();
if (mIwlanDataService != null) {
@@ -458,7 +459,8 @@ public class IwlanDataServiceTest {
networkCallback.onLinkPropertiesChanged(mMockNetwork, newLinkProperties);
verify(mMockEpdgTunnelManager, times(1))
.updateNetwork(eq(mMockNetwork), eq(newLinkProperties));
- verify(mMockEpdgTunnelManager, never()).closeTunnel(any(), anyBoolean(), any(), any());
+ verify(mMockEpdgTunnelManager, never())
+ .closeTunnel(any(), anyBoolean(), any(), any(), anyInt());
}
@Test
@@ -867,7 +869,8 @@ public class IwlanDataServiceTest {
eq(TEST_APN_NAME),
eq(false),
any(IwlanTunnelCallback.class),
- any(IwlanTunnelMetricsImpl.class));
+ any(IwlanTunnelMetricsImpl.class),
+ eq(BRINGDOWN_REASON_DEACTIVATE_DATA_CALL));
/* Check callback result is RESULT_SUCCESS when onClosed() is called. */
mSpyIwlanDataServiceProvider
@@ -907,7 +910,8 @@ public class IwlanDataServiceTest {
eq(TEST_APN_NAME),
eq(true) /* forceClose */,
any(IwlanTunnelCallback.class),
- any(IwlanTunnelMetricsImpl.class));
+ any(IwlanTunnelMetricsImpl.class),
+ eq(BRINGDOWN_REASON_DEACTIVATE_DATA_CALL));
/* Check callback result is RESULT_SUCCESS when onClosed() is called. */
mSpyIwlanDataServiceProvider
@@ -922,11 +926,8 @@ public class IwlanDataServiceTest {
public void testDeactivateDataCall_DelayedReleaseAfterHandover() {
DataProfile dp = buildImsDataProfile();
- when(IwlanCarrierConfig.getConfigInt(
- mMockContext,
- DEFAULT_SLOT_INDEX,
- IwlanCarrierConfig.KEY_HANDOVER_TO_WWAN_RELEASE_DELAY_SECOND_INT))
- .thenReturn(3);
+ IwlanCarrierConfig.putTestConfigInt(
+ IwlanCarrierConfig.KEY_HANDOVER_TO_WWAN_RELEASE_DELAY_SECOND_INT, 3);
onSystemDefaultNetworkConnected(TRANSPORT_WIFI);
mSpyIwlanDataServiceProvider.setTunnelState(
@@ -952,7 +953,8 @@ public class IwlanDataServiceTest {
eq(TEST_APN_NAME),
anyBoolean(),
any(IwlanTunnelCallback.class),
- any(IwlanTunnelMetricsImpl.class));
+ any(IwlanTunnelMetricsImpl.class),
+ eq(BRINGDOWN_REASON_DEACTIVATE_DATA_CALL));
moveTimeForwardAndDispatch(50);
/* Check closeTunnel() is called. */
@@ -961,7 +963,8 @@ public class IwlanDataServiceTest {
eq(TEST_APN_NAME),
eq(true) /* forceClose */,
any(IwlanTunnelCallback.class),
- any(IwlanTunnelMetricsImpl.class));
+ any(IwlanTunnelMetricsImpl.class),
+ eq(BRINGDOWN_REASON_DEACTIVATE_DATA_CALL));
/* Check callback result is RESULT_SUCCESS when onClosed() is called. */
mSpyIwlanDataServiceProvider
@@ -976,11 +979,8 @@ public class IwlanDataServiceTest {
public void testDeactivateDataCall_DelayedReleaseAfterHandover_NetworkReleaseBeforeDelay() {
DataProfile dp = buildImsDataProfile();
- when(IwlanCarrierConfig.getConfigInt(
- mMockContext,
- DEFAULT_SLOT_INDEX,
- IwlanCarrierConfig.KEY_HANDOVER_TO_WWAN_RELEASE_DELAY_SECOND_INT))
- .thenReturn(3);
+ IwlanCarrierConfig.putTestConfigInt(
+ IwlanCarrierConfig.KEY_HANDOVER_TO_WWAN_RELEASE_DELAY_SECOND_INT, 3);
when(ErrorPolicyManager.getInstance(eq(mMockContext), eq(DEFAULT_SLOT_INDEX)))
.thenReturn(mMockErrorPolicyManager);
when(mMockErrorPolicyManager.getDataFailCause(eq(TEST_APN_NAME)))
@@ -1020,7 +1020,8 @@ public class IwlanDataServiceTest {
eq(TEST_APN_NAME),
anyBoolean(),
any(IwlanTunnelCallback.class),
- any(IwlanTunnelMetricsImpl.class));
+ any(IwlanTunnelMetricsImpl.class),
+ anyInt());
/* Check callback result is RESULT_SUCCESS when onClosed() is called. */
mSpyIwlanDataServiceProvider
@@ -1037,7 +1038,8 @@ public class IwlanDataServiceTest {
eq(TEST_APN_NAME),
anyBoolean(),
any(IwlanTunnelCallback.class),
- any(IwlanTunnelMetricsImpl.class));
+ any(IwlanTunnelMetricsImpl.class),
+ anyInt());
// No additional callbacks are involved.
verify(mMockDataServiceCallback, times(1)).onDeactivateDataCallComplete(anyInt());
@@ -1993,7 +1995,8 @@ public class IwlanDataServiceTest {
eq(TEST_APN_NAME),
anyBoolean(),
any(IwlanTunnelCallback.class),
- any(IwlanTunnelMetricsImpl.class));
+ any(IwlanTunnelMetricsImpl.class),
+ eq(BRINGDOWN_REASON_DEACTIVATE_DATA_CALL));
advanceCalendarByTimeMs(deactivationTime, calendar);
@@ -2044,7 +2047,13 @@ public class IwlanDataServiceTest {
Network newNetwork2 = createMockNetwork(mLinkProperties);
onSystemDefaultNetworkConnected(
newNetwork2, mLinkProperties, TRANSPORT_WIFI, DEFAULT_SUB_INDEX);
- verify(mMockEpdgTunnelManager, times(1)).closeTunnel(any(), anyBoolean(), any(), any());
+ verify(mMockEpdgTunnelManager, times(1))
+ .closeTunnel(
+ any(),
+ anyBoolean(),
+ any(),
+ any(),
+ eq(BRINGDOWN_REASON_NETWORK_UPDATE_WHEN_TUNNEL_IN_BRINGUP));
}
public static TunnelLinkProperties createTunnelLinkProperties() throws Exception {
@@ -2072,15 +2081,6 @@ public class IwlanDataServiceTest {
.build();
}
- private void setupMockForGetConfig(PersistableBundle bundle) {
- if (bundle == null) {
- bundle = new PersistableBundle();
- }
- when(mMockContext.getSystemService(eq(CarrierConfigManager.class)))
- .thenReturn(mMockCarrierConfigManager);
- when(mMockCarrierConfigManager.getConfigForSubId(DEFAULT_SLOT_INDEX)).thenReturn(bundle);
- }
-
private void mockCarrierConfigForN1Mode(boolean supportN1Mode) {
PersistableBundle bundle = new PersistableBundle();
if (supportN1Mode) {
@@ -2095,7 +2095,7 @@ public class IwlanDataServiceTest {
CarrierConfigManager.KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY,
new int[] {CarrierConfigManager.CARRIER_NR_AVAILABILITY_NSA});
}
- setupMockForGetConfig(bundle);
+ IwlanCarrierConfig.putTestConfigBundle(bundle);
}
private void mockCallState(int callState) {
@@ -2132,7 +2132,7 @@ public class IwlanDataServiceTest {
CarrierConfigManager.CARRIER_NR_AVAILABILITY_NSA,
CarrierConfigManager.CARRIER_NR_AVAILABILITY_SA
});
- setupMockForGetConfig(bundle);
+ IwlanCarrierConfig.putTestConfigBundle(bundle);
assertTrue(mSpyIwlanDataServiceProvider.isN1ModeSupported());
bundle.putIntArray(
@@ -2140,14 +2140,15 @@ public class IwlanDataServiceTest {
new int[] {
CarrierConfigManager.CARRIER_NR_AVAILABILITY_NSA,
});
- setupMockForGetConfig(bundle);
+ IwlanCarrierConfig.putTestConfigBundle(bundle);
assertFalse(mSpyIwlanDataServiceProvider.isN1ModeSupported());
}
@Test
public void testMultipleAllowedNetworkTypeChangeInIdle_updateN1Mode() throws Exception {
- when(mFakeFeatureFlags.updateN1ModeOnUiChange()).thenReturn(true);
mockCarrierConfigForN1Mode(true);
+ IwlanCarrierConfig.putTestConfigBoolean(
+ IwlanCarrierConfig.KEY_UPDATE_N1_MODE_ON_UI_CHANGE_BOOL, true);
mockCallState(CALL_STATE_IDLE);
mockSetupDataCallWithPduSessionId(0);
updatePreferredNetworkType(NETWORK_TYPE_BITMASK_NR);
@@ -2175,8 +2176,10 @@ public class IwlanDataServiceTest {
@Test
public void testMultipleAllowedNetworkTypeChangeInCall_preferenceChanged_updateAfterCallEnds()
throws Exception {
- when(mFakeFeatureFlags.updateN1ModeOnUiChange()).thenReturn(true);
mockCarrierConfigForN1Mode(true);
+ IwlanCarrierConfig.putTestConfigBoolean(
+ IwlanCarrierConfig.KEY_UPDATE_N1_MODE_ON_UI_CHANGE_BOOL, true);
+
mockCallState(CALL_STATE_RINGING);
mockSetupDataCallWithPduSessionId(0);
updatePreferredNetworkType(NETWORK_TYPE_BITMASK_NR);
@@ -2208,8 +2211,10 @@ public class IwlanDataServiceTest {
@Test
public void testMultipleAllowedNetworkTypeChangeInCall_preferenceNotChanged_noUpdate()
throws Exception {
- when(mFakeFeatureFlags.updateN1ModeOnUiChange()).thenReturn(true);
mockCarrierConfigForN1Mode(true);
+ IwlanCarrierConfig.putTestConfigBoolean(
+ IwlanCarrierConfig.KEY_UPDATE_N1_MODE_ON_UI_CHANGE_BOOL, true);
+
mockCallState(CALL_STATE_RINGING);
mockSetupDataCallWithPduSessionId(0);
updatePreferredNetworkType(NETWORK_TYPE_BITMASK_NR);
@@ -2234,8 +2239,10 @@ public class IwlanDataServiceTest {
@Test
public void testOnAllowedNetworkTypeChange_flagDisabled_noTunnelClose() {
- when(mFakeFeatureFlags.updateN1ModeOnUiChange()).thenReturn(false);
mockCarrierConfigForN1Mode(true);
+ IwlanCarrierConfig.putTestConfigBoolean(
+ IwlanCarrierConfig.KEY_UPDATE_N1_MODE_ON_UI_CHANGE_BOOL, false);
+
mockCallState(CALL_STATE_IDLE);
mockSetupDataCallWithPduSessionId(0);
updatePreferredNetworkType(NETWORK_TYPE_BITMASK_NR);
@@ -2246,8 +2253,10 @@ public class IwlanDataServiceTest {
@Test
public void testOnAllowedNetworkTypeChange_n1ModeNotSupported_noTunnelClose() {
- when(mFakeFeatureFlags.updateN1ModeOnUiChange()).thenReturn(true);
mockCarrierConfigForN1Mode(false);
+ IwlanCarrierConfig.putTestConfigBoolean(
+ IwlanCarrierConfig.KEY_UPDATE_N1_MODE_ON_UI_CHANGE_BOOL, true);
+
mockCallState(CALL_STATE_IDLE);
mockSetupDataCallWithPduSessionId(0);
updatePreferredNetworkType(NETWORK_TYPE_BITMASK_NR);
@@ -2258,8 +2267,10 @@ public class IwlanDataServiceTest {
@Test
public void testN1ModeNotSupported_tunnelBringupWithNoN1ModeCapability() {
- when(mFakeFeatureFlags.updateN1ModeOnUiChange()).thenReturn(true);
mockCarrierConfigForN1Mode(false);
+ IwlanCarrierConfig.putTestConfigBoolean(
+ IwlanCarrierConfig.KEY_UPDATE_N1_MODE_ON_UI_CHANGE_BOOL, true);
+
mockSetupDataCallWithPduSessionId(1);
ArgumentCaptor<TunnelSetupRequest> tunnelSetupRequestCaptor =
@@ -2272,8 +2283,10 @@ public class IwlanDataServiceTest {
@Test
public void testNoN1ModeCapabilityInOngoingDataCall_newTunnelBringup_doNotIncludeN1() {
- when(mFakeFeatureFlags.updateN1ModeOnUiChange()).thenReturn(true);
mockCarrierConfigForN1Mode(true);
+ IwlanCarrierConfig.putTestConfigBoolean(
+ IwlanCarrierConfig.KEY_UPDATE_N1_MODE_ON_UI_CHANGE_BOOL, true);
+
mockSetupDataCallWithPduSessionId(0);
ArgumentCaptor<TunnelSetupRequest> tunnelSetupRequestCaptor =
@@ -2325,6 +2338,7 @@ public class IwlanDataServiceTest {
@Test
public void testN1ModeForEmergencySession() {
int pduSessionId = 5;
+ updatePreferredNetworkType(NETWORK_TYPE_BITMASK_NR);
DataProfile dp = buildDataProfile(ApnSetting.TYPE_EMERGENCY);
verifySetupDataCallRequestHandled(pduSessionId, dp);
@@ -2338,11 +2352,9 @@ public class IwlanDataServiceTest {
@Test
public void testN1ModeExclusionForEmergencySession() {
- when(IwlanCarrierConfig.getConfigBoolean(
- mMockContext,
- DEFAULT_SLOT_INDEX,
- IwlanCarrierConfig.KEY_N1_MODE_EXCLUSION_FOR_EMERGENCY_SESSION_BOOL))
- .thenReturn(true);
+ IwlanCarrierConfig.putTestConfigBoolean(
+ IwlanCarrierConfig.KEY_N1_MODE_EXCLUSION_FOR_EMERGENCY_SESSION_BOOL, true);
+ updatePreferredNetworkType(NETWORK_TYPE_BITMASK_NR);
DataProfile dp = buildDataProfile(ApnSetting.TYPE_EMERGENCY);
verifySetupDataCallRequestHandled(5 /* pduSessionId */, dp);
diff --git a/test/com/google/android/iwlan/IwlanEventListenerTest.java b/test/com/google/android/iwlan/IwlanEventListenerTest.java
index a922a10..5999872 100644
--- a/test/com/google/android/iwlan/IwlanEventListenerTest.java
+++ b/test/com/google/android/iwlan/IwlanEventListenerTest.java
@@ -368,8 +368,6 @@ public class IwlanEventListenerTest {
@SuppressLint("MissingPermission")
@Test
public void testDisable5gViaUi() throws Exception {
- when(mFakeFeatureFlags.updateN1ModeOnUiChange()).thenReturn(true);
-
when(mMockHandler.obtainMessage(
eq(IwlanEventListener.PREFERRED_NETWORK_TYPE_CHANGED_EVENT),
eq(DEFAULT_SLOT_INDEX),
@@ -393,8 +391,6 @@ public class IwlanEventListenerTest {
@SuppressLint("MissingPermission")
@Test
public void testEnable5gViaUi() throws Exception {
- when(mFakeFeatureFlags.updateN1ModeOnUiChange()).thenReturn(true);
-
when(mMockHandler.obtainMessage(
eq(IwlanEventListener.PREFERRED_NETWORK_TYPE_CHANGED_EVENT),
eq(DEFAULT_SLOT_INDEX),
diff --git a/test/com/google/android/iwlan/epdg/EpdgTunnelManagerTest.java b/test/com/google/android/iwlan/epdg/EpdgTunnelManagerTest.java
index b7004e7..05ab0bc 100644
--- a/test/com/google/android/iwlan/epdg/EpdgTunnelManagerTest.java
+++ b/test/com/google/android/iwlan/epdg/EpdgTunnelManagerTest.java
@@ -16,6 +16,8 @@
package com.google.android.iwlan.epdg;
+import static com.google.android.iwlan.epdg.EpdgTunnelManager.BRINGDOWN_REASON_UNKNOWN;
+
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -26,6 +28,7 @@ import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyLong;
+import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doReturn;
@@ -72,6 +75,7 @@ import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
+import android.util.Pair;
import com.google.android.iwlan.IwlanError;
import com.google.android.iwlan.IwlanTunnelMetricsImpl;
@@ -543,6 +547,207 @@ public class EpdgTunnelManagerTest {
}
@Test
+ public void testAeadSaProposals() throws Exception {
+ when(mFakeFeatureFlags.aeadAlgosEnabled()).thenReturn(true);
+ final String apnName = "ims";
+ int[] aeadAlgos = {
+ SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8,
+ SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12,
+ SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16,
+ };
+ int[] aeadAlgosKeyLens = {
+ SaProposal.KEY_LEN_AES_128, SaProposal.KEY_LEN_AES_192, SaProposal.KEY_LEN_AES_256,
+ };
+
+ PersistableBundle bundle = new PersistableBundle();
+ bundle.putIntArray(
+ CarrierConfigManager.Iwlan.KEY_SUPPORTED_IKE_SESSION_AEAD_ALGORITHMS_INT_ARRAY,
+ aeadAlgos);
+ bundle.putIntArray(
+ CarrierConfigManager.Iwlan.KEY_IKE_SESSION_AES_GCM_KEY_SIZE_INT_ARRAY,
+ aeadAlgosKeyLens);
+ bundle.putIntArray(
+ CarrierConfigManager.Iwlan.KEY_SUPPORTED_CHILD_SESSION_AEAD_ALGORITHMS_INT_ARRAY,
+ aeadAlgos);
+ bundle.putIntArray(
+ CarrierConfigManager.Iwlan.KEY_CHILD_SESSION_AES_GCM_KEY_SIZE_INT_ARRAY,
+ aeadAlgosKeyLens);
+
+ setupMockForGetConfig(bundle);
+
+ IkeSessionArgumentCaptors tunnelArgumentCaptors =
+ verifyBringUpTunnelWithDnsQuery(apnName, mMockDefaultNetwork);
+
+ IkeSessionParams ikeTunnelParams = tunnelArgumentCaptors.mIkeSessionParamsCaptor.getValue();
+
+ List<Pair<Integer, Integer>> ikeEncrAlgos =
+ ikeTunnelParams.getIkeSaProposals().get(0).getEncryptionAlgorithms();
+
+ assertTrue(ikeEncrAlgos.contains(new Pair(aeadAlgos[0], aeadAlgosKeyLens[0])));
+ assertEquals(
+ "IKE AEAD algorithms mismatch",
+ (long) aeadAlgos.length * aeadAlgosKeyLens.length,
+ (long) ikeEncrAlgos.size());
+
+ ChildSessionParams childTunnelParams =
+ tunnelArgumentCaptors.mChildSessionParamsCaptor.getValue();
+
+ List<Pair<Integer, Integer>> childEncrAlgos =
+ childTunnelParams.getChildSaProposals().get(0).getEncryptionAlgorithms();
+
+ assertTrue(childEncrAlgos.contains(new Pair(aeadAlgos[0], aeadAlgosKeyLens[0])));
+ assertEquals(
+ "Child AEAD algorithms mismatch",
+ (long) aeadAlgos.length * aeadAlgosKeyLens.length,
+ (long) childEncrAlgos.size());
+ }
+
+ @Test
+ public void testMultipleSaProposals() throws Exception {
+ when(mFakeFeatureFlags.multipleSaProposals()).thenReturn(true);
+ final String apnName = "ims";
+ PersistableBundle bundle = new PersistableBundle();
+
+ int[] aeadAlgos = {
+ SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12,
+ };
+ int[] aeadAlgosKeyLens = {
+ SaProposal.KEY_LEN_AES_192, SaProposal.KEY_LEN_AES_256,
+ };
+
+ bundle.putIntArray(
+ CarrierConfigManager.Iwlan.KEY_SUPPORTED_IKE_SESSION_AEAD_ALGORITHMS_INT_ARRAY,
+ aeadAlgos);
+ bundle.putIntArray(
+ CarrierConfigManager.Iwlan.KEY_IKE_SESSION_AES_GCM_KEY_SIZE_INT_ARRAY,
+ aeadAlgosKeyLens);
+ bundle.putIntArray(
+ CarrierConfigManager.Iwlan.KEY_SUPPORTED_CHILD_SESSION_AEAD_ALGORITHMS_INT_ARRAY,
+ aeadAlgos);
+ bundle.putIntArray(
+ CarrierConfigManager.Iwlan.KEY_CHILD_SESSION_AES_GCM_KEY_SIZE_INT_ARRAY,
+ aeadAlgosKeyLens);
+
+ bundle.putBoolean(
+ CarrierConfigManager.Iwlan.KEY_SUPPORTS_IKE_SESSION_MULTIPLE_SA_PROPOSALS_BOOL,
+ true);
+ bundle.putBoolean(
+ CarrierConfigManager.Iwlan.KEY_SUPPORTS_CHILD_SESSION_MULTIPLE_SA_PROPOSALS_BOOL,
+ true);
+
+ setupMockForGetConfig(bundle);
+
+ IkeSessionArgumentCaptors tunnelArgumentCaptors =
+ verifyBringUpTunnelWithDnsQuery(apnName, mMockDefaultNetwork);
+
+ IkeSessionParams ikeTunnelParams = tunnelArgumentCaptors.mIkeSessionParamsCaptor.getValue();
+
+ assertTrue(ikeTunnelParams.getIkeSaProposals().size() > 1);
+
+ List<Pair<Integer, Integer>> ikeAeadAlgos =
+ ikeTunnelParams.getIkeSaProposals().get(0).getEncryptionAlgorithms();
+ assertEquals(
+ "Reorder higher AEAD in IKE SA mismatch",
+ (long) SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12,
+ (long) ikeAeadAlgos.get(0).first);
+
+ ChildSessionParams childTunnelParams =
+ tunnelArgumentCaptors.mChildSessionParamsCaptor.getValue();
+
+ assertTrue(childTunnelParams.getChildSaProposals().size() > 1);
+
+ List<Pair<Integer, Integer>> childAeadAlgos =
+ childTunnelParams.getChildSaProposals().get(0).getEncryptionAlgorithms();
+ assertEquals(
+ "Reorder higher AEAD in Child SA mismatch",
+ (long) SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12,
+ (long) childAeadAlgos.get(0).first);
+ }
+
+ @Test
+ public void testSaProposalsReorder() throws Exception {
+ when(mFakeFeatureFlags.aeadAlgosEnabled()).thenReturn(true);
+ when(mFakeFeatureFlags.multipleSaProposals()).thenReturn(true);
+ when(mFakeFeatureFlags.highSecureTransformsPrioritized()).thenReturn(true);
+
+ final String apnName = "ims";
+ int[] aeadAlgos = {
+ SaProposal.ENCRYPTION_ALGORITHM_AES_CBC,
+ };
+ int[] aeadAlgosKeyLens = {
+ SaProposal.KEY_LEN_AES_128, SaProposal.KEY_LEN_AES_192, SaProposal.KEY_LEN_AES_256,
+ };
+
+ PersistableBundle bundle = new PersistableBundle();
+
+ bundle.putIntArray(
+ CarrierConfigManager.Iwlan
+ .KEY_SUPPORTED_IKE_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY,
+ aeadAlgos);
+ bundle.putIntArray(
+ CarrierConfigManager.Iwlan.KEY_IKE_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY,
+ aeadAlgosKeyLens);
+ bundle.putIntArray(
+ CarrierConfigManager.Iwlan
+ .KEY_SUPPORTED_CHILD_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY,
+ aeadAlgos);
+ bundle.putIntArray(
+ CarrierConfigManager.Iwlan.KEY_CHILD_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY,
+ aeadAlgosKeyLens);
+
+ bundle.putBoolean(
+ CarrierConfigManager.Iwlan.KEY_SUPPORTS_IKE_SESSION_MULTIPLE_SA_PROPOSALS_BOOL,
+ true);
+ bundle.putBoolean(
+ CarrierConfigManager.Iwlan.KEY_SUPPORTS_CHILD_SESSION_MULTIPLE_SA_PROPOSALS_BOOL,
+ true);
+
+ setupMockForGetConfig(bundle);
+
+ IkeSessionArgumentCaptors tunnelArgumentCaptors =
+ verifyBringUpTunnelWithDnsQuery(apnName, mMockDefaultNetwork);
+
+ IkeSessionParams ikeTunnelParams = tunnelArgumentCaptors.mIkeSessionParamsCaptor.getValue();
+
+ assertTrue(ikeTunnelParams.getIkeSaProposals().size() > 1);
+
+ List<Pair<Integer, Integer>> ikeEncrAlgos =
+ ikeTunnelParams.getIkeSaProposals().get(0).getEncryptionAlgorithms();
+
+ assertEquals(
+ "Reorder bigger key length in IKE SA mismatch",
+ (long) SaProposal.KEY_LEN_AES_256,
+ (long) ikeEncrAlgos.get(0).second);
+
+ List<Pair<Integer, Integer>> ikeAeadAlgos =
+ ikeTunnelParams.getIkeSaProposals().get(1).getEncryptionAlgorithms();
+ assertEquals(
+ "Reorder higher AEAD in IKE SA mismatch",
+ (long) SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16,
+ (long) ikeAeadAlgos.get(0).first);
+
+ ChildSessionParams childTunnelParams =
+ tunnelArgumentCaptors.mChildSessionParamsCaptor.getValue();
+
+ assertTrue(childTunnelParams.getChildSaProposals().size() > 1);
+
+ List<Pair<Integer, Integer>> childEncrAlgos =
+ childTunnelParams.getChildSaProposals().get(0).getEncryptionAlgorithms();
+
+ assertEquals(
+ "Reorder bigger key length in Child SA mismatch",
+ (long) SaProposal.KEY_LEN_AES_256,
+ (long) childEncrAlgos.get(0).second);
+
+ List<Pair<Integer, Integer>> childAeadAlgos =
+ childTunnelParams.getChildSaProposals().get(1).getEncryptionAlgorithms();
+ assertEquals(
+ "Reorder higher AEAD in Child SA mismatch",
+ (long) SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16,
+ (long) childAeadAlgos.get(0).first);
+ }
+
+ @Test
public void testCloseTunnelWithNoTunnelForApn() throws Exception {
String testApnName = "www.xyz.com";
doReturn(0L)
@@ -553,7 +758,8 @@ public class EpdgTunnelManagerTest {
testApnName,
false /*forceClose*/,
mMockIwlanTunnelCallback,
- mMockIwlanTunnelMetrics);
+ mMockIwlanTunnelMetrics,
+ BRINGDOWN_REASON_UNKNOWN);
mTestLooper.dispatchAll();
verify(mEpdgTunnelManager).closePendingRequestsForApn(eq(testApnName));
@@ -582,7 +788,8 @@ public class EpdgTunnelManagerTest {
testApnName,
true /*forceClose*/,
mMockIwlanTunnelCallback,
- mMockIwlanTunnelMetrics);
+ mMockIwlanTunnelMetrics,
+ BRINGDOWN_REASON_UNKNOWN);
mTestLooper.dispatchAll();
verify(mMockIkeSession).kill();
@@ -606,7 +813,8 @@ public class EpdgTunnelManagerTest {
testApnName,
false /*forceClose*/,
mMockIwlanTunnelCallback,
- mMockIwlanTunnelMetrics);
+ mMockIwlanTunnelMetrics,
+ BRINGDOWN_REASON_UNKNOWN);
mTestLooper.dispatchAll();
verify(mMockIkeSession).close();
@@ -1153,6 +1361,7 @@ public class EpdgTunnelManagerTest {
when(mMockTelephonyManager.createForSubscriptionId(DEFAULT_SUBID))
.thenReturn(mMockTelephonyManager);
when(mMockCarrierConfigManager.getConfigForSubId(DEFAULT_SLOT_INDEX)).thenReturn(bundle);
+ when(mMockCarrierConfigManager.getConfigForSubId(anyInt(), anyString())).thenReturn(bundle);
}
private void setVariable(Object target, String variableName, Object value) throws Exception {
@@ -2091,7 +2300,8 @@ public class EpdgTunnelManagerTest {
TEST_APN_NAME,
false /*forceClose*/,
mMockIwlanTunnelCallback,
- mMockIwlanTunnelMetrics);
+ mMockIwlanTunnelMetrics,
+ BRINGDOWN_REASON_UNKNOWN);
mTestLooper.dispatchAll();
verify(mMockIwlanTunnelCallback, times(1))