Merge 6c195cd0a4142fa24f949c5f720c47763040db12 on remote branch
Change-Id: I6192e02e3f9a10a36c8be9ad09f0b91118e385ce
diff --git a/Android.bp b/Android.bp
index ef7af7c..f9a785b 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,3 +1,7 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
android_app {
name: "Iwlan",
manifest: "AndroidManifest.xml",
@@ -16,6 +20,7 @@
"android.net.ipsec.ike.stubs.system",
"auto_value_annotations",
"framework-annotations-lib",
+ "framework-connectivity",
"framework-wifi"
],
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index f0cdd15..6a7a2d4 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -12,6 +12,7 @@
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
+ <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<protected-broadcast android:name="IkeAlarmReceiver.ACTION_DELETE_CHILD" />
<protected-broadcast android:name="IkeAlarmReceiver.ACTION_REKEY_CHILD" />
@@ -20,21 +21,21 @@
<protected-broadcast android:name="IkeAlarmReceiver.ACTION_DPD" />
<protected-broadcast android:name="IkeAlarmReceiver.ACTION_KEEPALIVE" />
- <application>
+ <application
+ android:directBootAware="true"
+ android:defaultToDeviceProtectedStorage="true">
<service android:name=".IwlanDataService"
+ android:exported="true"
android:permission="android.permission.BIND_TELEPHONY_DATA_SERVICE"
- android:enabled="true"
- android:directBootAware="true"
- android:exported="true" >
+ android:enabled="true" >
<intent-filter>
<action android:name="android.telephony.data.DataService" />
</intent-filter>
</service>
<service android:name=".IwlanNetworkService"
+ android:exported="true"
android:permission="android.permission.BIND_TELEPHONY_NETWORK_SERVICE"
- android:enabled="true"
- android:directBootAware="true"
- android:exported="true" >
+ android:enabled="true" >
<intent-filter>
<action android:name="android.telephony.NetworkService" />
</intent-filter>
@@ -44,7 +45,6 @@
<intent-filter>
<action android:name="android.telephony.action.CARRIER_CONFIG_CHANGED"/>
<action android:name="android.telephony.action.CARRIER_SIGNAL_PCO_VALUE"/>
- <action android:name="android.intent.action.AIRPLANE_MODE" />
</intent-filter>
</receiver>
<uses-library android:name="android.net.ipsec.ike" />
diff --git a/src/com/google/android/iwlan/ErrorPolicyManager.java b/src/com/google/android/iwlan/ErrorPolicyManager.java
index c7f9fd9..66f6459 100644
--- a/src/com/google/android/iwlan/ErrorPolicyManager.java
+++ b/src/com/google/android/iwlan/ErrorPolicyManager.java
@@ -295,8 +295,7 @@
int protocolErrorType = ((IkeProtocolException) exception).getErrorType();
switch (protocolErrorType) {
case IkeProtocolException.ERROR_TYPE_AUTHENTICATION_FAILED:
- // TODO: Change this as per b/175719031
- ret = DataFailCause.USER_AUTHENTICATION;
+ ret = DataFailCause.IWLAN_IKEV2_AUTH_FAILURE;
break;
case IKE_PROTOCOL_ERROR_PDN_CONNECTION_REJECTION:
ret = DataFailCause.IWLAN_PDN_CONNECTION_REJECTION;
@@ -486,13 +485,13 @@
for (int i = 0; i < apnArray.length(); i++) {
JSONObject apnDetails = apnArray.getJSONObject(i);
- String apnName = (String) apnDetails.get("ApnName");
+ String apnName = ((String) apnDetails.get("ApnName")).trim();
JSONArray errorTypeArray = (JSONArray) apnDetails.get("ErrorTypes");
for (int j = 0; j < errorTypeArray.length(); j++) {
JSONObject errorTypeObject = errorTypeArray.getJSONObject(j);
- String errorTypeStr = (String) errorTypeObject.get("ErrorType");
+ String errorTypeStr = ((String) errorTypeObject.get("ErrorType")).trim();
JSONArray errorDetailArray = (JSONArray) errorTypeObject.get("ErrorDetails");
int errorType = UNKNOWN_ERROR_TYPE;
@@ -519,7 +518,7 @@
throws JSONException, IllegalArgumentException {
List<Integer> ret = new ArrayList<>();
for (int i = 0; i < retryArray.length(); i++) {
- String retryTime = retryArray.getString(i);
+ String retryTime = retryArray.getString(i).trim();
// catch misplaced -1 retry times in the array.
// 1. if it is not placed at the last position in the array
@@ -554,7 +553,8 @@
throws JSONException, IllegalArgumentException {
List<Integer> ret = new ArrayList<>();
for (int i = 0; i < unthrottlingEvents.length(); i++) {
- int event = IwlanEventListener.getUnthrottlingEvent(unthrottlingEvents.getString(i));
+ int event =
+ IwlanEventListener.getUnthrottlingEvent(unthrottlingEvents.getString(i).trim());
if (event == IwlanEventListener.UNKNOWN_EVENT) {
throw new IllegalArgumentException(
"Unexpected unthrottlingEvent " + unthrottlingEvents.getString(i));
@@ -570,7 +570,7 @@
boolean isValidErrorDetail = true;
for (int i = 0; i < errorDetailArray.length(); i++) {
- String errorDetail = errorDetailArray.getString(i);
+ String errorDetail = errorDetailArray.getString(i).trim();
switch (errorType) {
case IKE_PROTOCOL_ERROR_TYPE:
isValidErrorDetail = verifyIkeProtocolErrorDetail(errorDetail);
diff --git a/src/com/google/android/iwlan/IwlanBroadcastReceiver.java b/src/com/google/android/iwlan/IwlanBroadcastReceiver.java
index 971f0d5..10b10e4 100644
--- a/src/com/google/android/iwlan/IwlanBroadcastReceiver.java
+++ b/src/com/google/android/iwlan/IwlanBroadcastReceiver.java
@@ -42,6 +42,7 @@
}
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
+ intentFilter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
context.registerReceiver(getInstance(), intentFilter);
mIsReceiverRegistered = true;
}
diff --git a/src/com/google/android/iwlan/IwlanDataService.java b/src/com/google/android/iwlan/IwlanDataService.java
index 2aa6654..0394a34 100644
--- a/src/com/google/android/iwlan/IwlanDataService.java
+++ b/src/com/google/android/iwlan/IwlanDataService.java
@@ -43,7 +43,8 @@
import android.telephony.data.DataProfile;
import android.telephony.data.DataService;
import android.telephony.data.DataServiceCallback;
-import android.telephony.data.SliceInfo;
+import android.telephony.data.NetworkSliceInfo;
+import android.telephony.data.TrafficDescriptor;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -133,11 +134,13 @@
Network network, NetworkCapabilities networkCapabilities) {
// onCapabilitiesChanged is guaranteed to be called immediately after onAvailable per
// API
- Log.d(TAG, "onCapabilitiesChanged: " + network);
+ Log.d(TAG, "onCapabilitiesChanged: " + network + " " + networkCapabilities);
if (networkCapabilities != null) {
if (networkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
+ Log.d(TAG, "Network " + network + " connected using transport MOBILE");
IwlanDataService.setNetworkConnected(true, network, Transport.MOBILE);
} else if (networkCapabilities.hasTransport(TRANSPORT_WIFI)) {
+ Log.d(TAG, "Network " + network + " connected using transport WIFI");
IwlanDataService.setNetworkConnected(true, network, Transport.WIFI);
} else {
Log.w(TAG, "Network does not have cellular or wifi capability");
@@ -455,6 +458,11 @@
}
}
+ if (tunnelState.getTunnelLinkProperties().sliceInfo().isPresent()) {
+ responseBuilder.setSliceInfo(
+ tunnelState.getTunnelLinkProperties().sliceInfo().get());
+ }
+
return responseBuilder
.setAddresses(linkAddrList)
.setDnsAddresses(tunnelState.getTunnelLinkProperties().dnsAddresses())
@@ -532,6 +540,17 @@
* of values are 1-15 while 0 means no pdu session id was attached to this call.
* Reference: 3GPP TS 24.007 section 11.2.3.1b.
* @param sliceInfo The slice info related to this data call.
+ * @param trafficDescriptor TrafficDescriptor for which data connection needs to be
+ * established. It is used for URSP traffic matching as described in 3GPP TS 24.526
+ * Section 4.2.2. It includes an optional DNN which, if present, must be used for
+ * traffic matching; it does not specify the end point to be used for the data call.
+ * @param matchAllRuleAllowed Indicates if using default match-all URSP rule for this
+ * request is allowed. If false, this request must not use the match-all URSP rule and
+ * if a non-match-all rule is not found (or if URSP rules are not available) then {@link
+ * DataCallResponse#getCause()} is {@link
+ * android.telephony.DataFailCause#MATCH_ALL_RULE_NOT_ALLOWED}. This is needed as some
+ * requests need to have a hard failure if the intention cannot be met, for example, a
+ * zero-rating slice.
* @param callback The result callback for this request.
*/
@Override
@@ -543,21 +562,27 @@
int reason,
@Nullable LinkProperties linkProperties,
@IntRange(from = 0, to = 15) int pduSessionId,
- @Nullable SliceInfo sliceInfo,
+ @Nullable NetworkSliceInfo sliceInfo,
+ @Nullable TrafficDescriptor trafficDescriptor,
+ boolean matchAllRuleAllowed,
@NonNull DataServiceCallback callback) {
Log.d(
SUB_TAG,
"Setup data call with network: "
+ accessNetworkType
- + " reason: "
+ + ", DataProfile: "
+ + dataProfile
+ + ", isRoaming:"
+ + isRoaming
+ + ", allowRoaming: "
+ + allowRoaming
+ + ", reason: "
+ reason
- + " pduSessionId: "
- + pduSessionId
- + " linkProperties: "
+ + ", linkProperties: "
+ linkProperties
- + "DataProfile: "
- + dataProfile);
+ + ", pduSessionId: "
+ + pduSessionId);
// Framework will never call bringup on the same APN back 2 back.
// but add a safety check
@@ -574,11 +599,20 @@
}
synchronized (mTunnelStateForApn) {
- if (isNetworkConnected(
- IwlanHelper.isDefaultDataSlot(mContext, getSlotIndex()),
- IwlanHelper.isCrossSimCallingEnabled(
- mContext, getSlotIndex()))
- == false
+ boolean isDDS = IwlanHelper.isDefaultDataSlot(mContext, getSlotIndex());
+ boolean isCSTEnabled =
+ IwlanHelper.isCrossSimCallingEnabled(mContext, getSlotIndex());
+ boolean networkConnected = isNetworkConnected(isDDS, isCSTEnabled);
+ Log.d(
+ SUB_TAG,
+ "isDds: "
+ + isDDS
+ + ", isCstEnabled: "
+ + isCSTEnabled
+ + ", transport: "
+ + sDefaultDataTransport);
+
+ if (networkConnected == false
|| mTunnelStateForApn.get(dataProfile.getApn()) != null) {
deliverCallback(
CALLBACK_TYPE_SETUP_DATACALL_COMPLETE,
@@ -674,14 +708,12 @@
*/
mTunnelStateForApn.get(apnName).setState(TunnelState.TUNNEL_IN_BRINGDOWN);
mTunnelStateForApn.get(apnName).setDataServiceCallback(callback);
- getTunnelManager()
- .closeTunnel(
- apnName,
- !isNetworkConnected(
- IwlanHelper.isDefaultDataSlot(
- mContext, getSlotIndex()),
- IwlanHelper.isCrossSimCallingEnabled(
- mContext, getSlotIndex())));
+ boolean isConnected =
+ isNetworkConnected(
+ IwlanHelper.isDefaultDataSlot(mContext, getSlotIndex()),
+ IwlanHelper.isCrossSimCallingEnabled(
+ mContext, getSlotIndex()));
+ getTunnelManager().closeTunnel(apnName, !isConnected);
return;
}
}
@@ -705,7 +737,7 @@
}
}
- private void forceCloseTunnels() {
+ void forceCloseTunnels() {
synchronized (mTunnelStateForApn) {
for (Map.Entry<String, TunnelState> entry : mTunnelStateForApn.entrySet()) {
getTunnelManager().closeTunnel(entry.getKey(), true);
@@ -758,7 +790,6 @@
&& mCarrierConfigReady == true
&& mWfcEnabled == true
&& mTunnelStateForApn.isEmpty()) {
- Log.d(TAG, "Trigger DNS prefetching");
// Get roaming status
TelephonyManager telephonyManager =
@@ -767,18 +798,9 @@
telephonyManager.createForSubscriptionId(
IwlanHelper.getSubId(mContext, getSlotIndex()));
boolean isRoaming = telephonyManager.isNetworkRoaming();
- Log.d(TAG, "is Roaming " + isRoaming);
+ Log.d(TAG, "Trigger EPDG prefetch. Roaming=" + isRoaming);
prefetchEpdgServerList(mIwlanDataService.sNetwork, isRoaming);
- } else {
- Log.d(
- TAG,
- "Network connected:"
- + networkConnected
- + " CarrierConfigReady:"
- + mCarrierConfigReady
- + " WfcEnabled:"
- + mWfcEnabled);
}
}
}
@@ -805,14 +827,6 @@
@VisibleForTesting
static boolean isNetworkConnected(boolean isDds, boolean isCstEnabled) {
- Log.d(
- TAG,
- "isDds: "
- + isDds
- + ", isCstEnabled: "
- + isCstEnabled
- + ", transport: "
- + sDefaultDataTransport);
if (!isDds && isCstEnabled) {
// Only Non-DDS sub with CST enabled, can use any transport.
return sNetworkConnected;
@@ -823,18 +837,17 @@
}
@VisibleForTesting
+ /* Note: this api should have valid transport if networkConnected==true */
static void setNetworkConnected(
boolean networkConnected, Network network, Transport transport) {
sNetworkConnected = networkConnected;
sNetwork = network;
-
if (networkConnected) {
if (transport == Transport.UNSPECIFIED_NETWORK) {
- // just return since we do not know the transport yet
+ Log.e(TAG, "setNetworkConnected: Network connected but transport unspecified");
return;
}
- if (sDefaultDataTransport != Transport.UNSPECIFIED_NETWORK
- && transport != sDefaultDataTransport) {
+ if (transport != sDefaultDataTransport) {
Log.d(
TAG,
"Transport was changed from "
@@ -851,7 +864,9 @@
if (!networkConnected) {
for (IwlanDataServiceProvider dp : sIwlanDataServiceProviderList) {
- dp.forceCloseTunnelsInDeactivatingState();
+ //once network is disconnect, even NAT KA offload fails
+ //so we should force close all tunnels
+ dp.forceCloseTunnels();
}
} else {
if (transport == Transport.WIFI) {
diff --git a/src/com/google/android/iwlan/IwlanHelper.java b/src/com/google/android/iwlan/IwlanHelper.java
index 73bde13..7988aca 100644
--- a/src/com/google/android/iwlan/IwlanHelper.java
+++ b/src/com/google/android/iwlan/IwlanHelper.java
@@ -21,8 +21,6 @@
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
-import android.net.wifi.WifiInfo;
-import android.net.wifi.WifiManager;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionInfo;
@@ -224,7 +222,7 @@
ImsMmTelManager imsMmTelManager = imsManager.getImsMmTelManager(subid);
if (imsMmTelManager != null) {
try {
- isCstEnabled = imsMmTelManager.isCrossSimCallingEnabledByUser();
+ isCstEnabled = imsMmTelManager.isCrossSimCallingEnabled();
} catch (Exception e) {
// Fail to query Cross-SIM calling setting, just return false to avoid an
// exception.
diff --git a/src/com/google/android/iwlan/epdg/EpdgSelector.java b/src/com/google/android/iwlan/epdg/EpdgSelector.java
index ede3ec8..f36f348 100644
--- a/src/com/google/android/iwlan/epdg/EpdgSelector.java
+++ b/src/com/google/android/iwlan/epdg/EpdgSelector.java
@@ -17,11 +17,9 @@
package com.google.android.iwlan.epdg;
import android.content.Context;
-import android.net.DnsResolver;
import android.net.Network;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
import android.telephony.CarrierConfigManager;
import android.telephony.CellIdentityGsm;
import android.telephony.CellIdentityLte;
@@ -46,7 +44,6 @@
import java.net.Inet6Address;
import java.net.InetAddress;
import java.util.*;
-import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
public class EpdgSelector {
@@ -144,50 +141,36 @@
// Get All IP for each domain name
Log.d(TAG, "Input domainName : " + domainName);
try {
- CompletableFuture<List<InetAddress>> result = new CompletableFuture();
- final DnsResolver.Callback<List<InetAddress>> cb =
- new DnsResolver.Callback<List<InetAddress>>() {
- @Override
- public void onAnswer(
- @NonNull final List<InetAddress> answer, final int rcode) {
- if (rcode == 0) {
- result.complete(answer);
- } else {
- Log.e(TAG, "DnsResover Response Code = " + rcode);
- }
- }
-
- @Override
- public void onError(@Nullable final DnsResolver.DnsException error) {
- Log.e(TAG, "Resolve DNS with error : " + error);
- result.completeExceptionally(error);
- }
- };
- DnsResolver.getInstance()
- .query(network, domainName, DnsResolver.FLAG_EMPTY, r -> r.run(), null, cb);
-
- // Filter the IP list by input ProtoFilter
- for (InetAddress ipAddress : result.get()) {
- switch (filter) {
- case PROTO_FILTER_IPV4:
- if (ipAddress instanceof Inet4Address) {
- validIpList.add(ipAddress);
- }
- break;
- case PROTO_FILTER_IPV6:
- if (ipAddress instanceof Inet6Address) {
- validIpList.add(ipAddress);
- }
- break;
- case PROTO_FILTER_IPV4V6:
- validIpList.add(ipAddress);
- break;
- default:
- Log.d(TAG, "Invalid ProtoFilter : " + filter);
- }
- }
+ ipList = network.getAllByName(domainName);
} catch (Exception e) {
- Log.e(TAG, "Exception when resolving domainName : " + domainName + ".", e);
+ Log.e(TAG, "Exception when querying IP address : " + e);
+ return;
+ }
+
+ if (ipList == null) {
+ Log.e(TAG, "Get empty IP address list");
+ return;
+ }
+
+ // Filter the IP list by input ProtoFilter
+ for (InetAddress ipAddress : ipList) {
+ switch (filter) {
+ case PROTO_FILTER_IPV4:
+ if (ipAddress instanceof Inet4Address) {
+ validIpList.add(ipAddress);
+ }
+ break;
+ case PROTO_FILTER_IPV6:
+ if (ipAddress instanceof Inet6Address) {
+ validIpList.add(ipAddress);
+ }
+ break;
+ case PROTO_FILTER_IPV4V6:
+ validIpList.add(ipAddress);
+ break;
+ default:
+ Log.d(TAG, "Invalid ProtoFilter : " + filter);
+ }
}
}
diff --git a/src/com/google/android/iwlan/epdg/EpdgTunnelManager.java b/src/com/google/android/iwlan/epdg/EpdgTunnelManager.java
index 3041faa..43c8bcf 100644
--- a/src/com/google/android/iwlan/epdg/EpdgTunnelManager.java
+++ b/src/com/google/android/iwlan/epdg/EpdgTunnelManager.java
@@ -23,6 +23,7 @@
import android.content.Context;
import android.net.InetAddresses;
+import android.net.IpPrefix;
import android.net.IpSecManager;
import android.net.IpSecTransform;
import android.net.LinkAddress;
@@ -42,6 +43,7 @@
import android.net.ipsec.ike.IkeSessionConfiguration;
import android.net.ipsec.ike.IkeSessionParams;
import android.net.ipsec.ike.IkeTrafficSelector;
+import android.net.ipsec.ike.SaProposal;
import android.net.ipsec.ike.TunnelModeChildSessionParams;
import android.net.ipsec.ike.exceptions.IkeException;
import android.net.ipsec.ike.exceptions.IkeProtocolException;
@@ -58,6 +60,7 @@
import android.telephony.CarrierConfigManager;
import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
+import android.telephony.data.NetworkSliceInfo;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -162,48 +165,43 @@
Collections.unmodifiableSet(
new HashSet<>(
Arrays.asList(
- CarrierConfigManager.Iwlan.DH_GROUP_1024_BIT_MODP,
- CarrierConfigManager.Iwlan.DH_GROUP_1536_BIT_MODP,
- CarrierConfigManager.Iwlan.DH_GROUP_2048_BIT_MODP)));
+ SaProposal.DH_GROUP_1024_BIT_MODP,
+ SaProposal.DH_GROUP_1536_BIT_MODP,
+ SaProposal.DH_GROUP_2048_BIT_MODP)));
VALID_KEY_LENGTHS =
Collections.unmodifiableSet(
new HashSet<>(
Arrays.asList(
- CarrierConfigManager.Iwlan.KEY_LEN_AES_128,
- CarrierConfigManager.Iwlan.KEY_LEN_AES_192,
- CarrierConfigManager.Iwlan.KEY_LEN_AES_256)));
+ SaProposal.KEY_LEN_AES_128,
+ SaProposal.KEY_LEN_AES_192,
+ SaProposal.KEY_LEN_AES_256)));
VALID_ENCRYPTION_ALGOS =
Collections.unmodifiableSet(
new HashSet<>(
Arrays.asList(
- CarrierConfigManager.Iwlan.ENCRYPTION_ALGORITHM_AES_CBC,
- CarrierConfigManager.Iwlan.ENCRYPTION_ALGORITHM_AES_CTR)));
+ SaProposal.ENCRYPTION_ALGORITHM_AES_CBC,
+ SaProposal.ENCRYPTION_ALGORITHM_AES_CTR)));
VALID_INTEGRITY_ALGOS =
Collections.unmodifiableSet(
new HashSet<>(
Arrays.asList(
- CarrierConfigManager.Iwlan.INTEGRITY_ALGORITHM_HMAC_SHA1_96,
- CarrierConfigManager.Iwlan.INTEGRITY_ALGORITHM_AES_XCBC_96,
- CarrierConfigManager.Iwlan
- .INTEGRITY_ALGORITHM_HMAC_SHA2_256_128,
- CarrierConfigManager.Iwlan
- .INTEGRITY_ALGORITHM_HMAC_SHA2_384_192,
- CarrierConfigManager.Iwlan
- .INTEGRITY_ALGORITHM_HMAC_SHA2_512_256)));
+ SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96,
+ SaProposal.INTEGRITY_ALGORITHM_AES_XCBC_96,
+ SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_256_128,
+ SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_384_192,
+ SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_512_256)));
VALID_PRF_ALGOS =
Collections.unmodifiableSet(
new HashSet<>(
Arrays.asList(
- CarrierConfigManager.Iwlan.PSEUDORANDOM_FUNCTION_HMAC_SHA1,
- CarrierConfigManager.Iwlan
- .PSEUDORANDOM_FUNCTION_AES128_XCBC,
- CarrierConfigManager.Iwlan.PSEUDORANDOM_FUNCTION_SHA2_256,
- CarrierConfigManager.Iwlan.PSEUDORANDOM_FUNCTION_SHA2_384,
- CarrierConfigManager.Iwlan
- .PSEUDORANDOM_FUNCTION_SHA2_512)));
+ SaProposal.PSEUDORANDOM_FUNCTION_HMAC_SHA1,
+ SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC,
+ SaProposal.PSEUDORANDOM_FUNCTION_SHA2_256,
+ SaProposal.PSEUDORANDOM_FUNCTION_SHA2_384,
+ SaProposal.PSEUDORANDOM_FUNCTION_SHA2_512)));
}
private final EpdgSelector.EpdgSelectorCallback mSelectorCallback =
@@ -219,22 +217,26 @@
}
};
- private static class TunnelConfig {
+ @VisibleForTesting
+ class TunnelConfig {
@NonNull final TunnelCallback mTunnelCallback;
// TODO: Change this to TunnelLinkProperties after removing autovalue
private List<InetAddress> mPcscfAddrList;
private List<InetAddress> mDnsAddrList;
private List<LinkAddress> mInternalAddrList;
- private byte[] mSnssai;
+
+ private InetAddress mSrcIpv6Address;
+ private int mSrcIpv6AddressPrefixLen;
+ private NetworkSliceInfo mSliceInfo;
private boolean mIsBackoffTimeValid = false;
private long mBackoffTime;
- public byte[] getSnssai() {
- return mSnssai;
+ public NetworkSliceInfo getSliceInfo() {
+ return mSliceInfo;
}
- public void setSnssai(byte[] snssai) {
- mSnssai = snssai;
+ public void setSliceInfo(NetworkSliceInfo si) {
+ mSliceInfo = si;
}
public boolean isBackoffTimeValid() {
@@ -254,10 +256,16 @@
IwlanError mError;
private IpSecManager.IpSecTunnelInterface mIface;
- public TunnelConfig(IkeSession ikeSession, TunnelCallback tunnelCallback) {
+ public TunnelConfig(
+ IkeSession ikeSession,
+ TunnelCallback tunnelCallback,
+ InetAddress srcIpv6Addr,
+ int srcIpv6PrefixLength) {
mTunnelCallback = tunnelCallback;
mIkeSession = ikeSession;
mError = new IwlanError(IwlanError.NO_ERROR);
+ mSrcIpv6Address = srcIpv6Addr;
+ mSrcIpv6AddressPrefixLen = srcIpv6PrefixLength;
}
@NonNull
@@ -285,8 +293,42 @@
return mInternalAddrList;
}
+ boolean isPrefixSameAsSrcIP(LinkAddress laddr) {
+ if (laddr.isIpv6() && (laddr.getPrefixLength() == mSrcIpv6AddressPrefixLen)) {
+ IpPrefix assignedPrefix = new IpPrefix(laddr.getAddress(), laddr.getPrefixLength());
+ IpPrefix srcPrefix = new IpPrefix(mSrcIpv6Address, mSrcIpv6AddressPrefixLen);
+ if (assignedPrefix.equals(srcPrefix)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
public void setInternalAddrList(List<LinkAddress> internalAddrList) {
- mInternalAddrList = internalAddrList;
+ mInternalAddrList = new ArrayList<LinkAddress>(internalAddrList);
+ if (getSrcIpv6Address() != null) {
+ // check if we can reuse src ipv6 address (i.e if prefix is same)
+ for (LinkAddress assignedAddr : internalAddrList) {
+ if (isPrefixSameAsSrcIP(assignedAddr)) {
+ // the assigned IPv6 address is same as pre-Handover IPv6
+ // addr. Just reuse the pre-Handover Address so the IID is
+ // preserved
+ mInternalAddrList.remove(assignedAddr);
+
+ // add original address
+ mInternalAddrList.add(
+ new LinkAddress(mSrcIpv6Address, mSrcIpv6AddressPrefixLen));
+
+ Log.d(
+ TAG,
+ "Network assigned IP replaced OLD:"
+ + internalAddrList
+ + " NEW:"
+ + mInternalAddrList);
+ break;
+ }
+ }
+ }
}
@NonNull
@@ -309,6 +351,14 @@
public void setIface(IpSecManager.IpSecTunnelInterface iface) {
mIface = iface;
}
+
+ public InetAddress getSrcIpv6Address() {
+ return mSrcIpv6Address;
+ }
+
+ public int getSrcIpv6AddressPrefixLen() {
+ return mSrcIpv6AddressPrefixLen;
+ }
}
@VisibleForTesting
@@ -365,13 +415,22 @@
TunnelConfig tunnelConfig = mApnNameToTunnelConfig.get(mApnName);
for (Ike3gppData payload : payloads) {
if (payload.getDataType() == DATA_TYPE_NOTIFY_N1_MODE_INFORMATION) {
- tunnelConfig.setSnssai(((Ike3gppN1ModeInformation) payload).getSnssai());
+ Log.d(TAG, "Got payload DATA_TYPE_NOTIFY_N1_MODE_INFORMATION");
+ NetworkSliceInfo si =
+ NetworkSliceSelectionAssistanceInformation.getSliceInfo(
+ ((Ike3gppN1ModeInformation) payload).getSnssai());
+ if (si != null) {
+ tunnelConfig.setSliceInfo(si);
+ Log.d(TAG, "SliceInfo: " + si);
+ }
} else if (payload.getDataType() == DATA_TYPE_NOTIFY_BACKOFF_TIMER) {
+ Log.d(TAG, "Got payload DATA_TYPE_NOTIFY_BACKOFF_TIMER");
long backoffTime =
decodeBackoffTime(
((Ike3gppBackoffTimer) payload).getBackoffTimer());
if (backoffTime > 0) {
tunnelConfig.setBackoffTime(backoffTime);
+ Log.d(TAG, "Backoff Timer: " + backoffTime);
}
}
}
@@ -398,7 +457,7 @@
IpSecManager.IpSecTunnelInterface tunnelInterface = tunnelConfig.getIface();
- for (LinkAddress address : sessionConfiguration.getInternalAddresses()) {
+ for (LinkAddress address : tunnelConfig.getInternalAddrList()) {
try {
tunnelInterface.addAddress(address.getAddress(), address.getPrefixLength());
} catch (IOException e) {
@@ -412,7 +471,7 @@
.setDnsAddresses(tunnelConfig.getDnsAddrList())
.setPcscfAddresses(tunnelConfig.getPcscfAddrList())
.setIfaceName(tunnelConfig.getIface().getInterfaceName())
- .setSNssai(tunnelConfig.getSnssai())
+ .setSliceInfo(tunnelConfig.getSliceInfo())
.build();
mHandler.dispatchMessage(
mHandler.obtainMessage(
@@ -586,7 +645,13 @@
getTmIkeSessionCallback(apnName),
new TmChildSessionCallBack(apnName));
- putApnNameToTunnelConfig(apnName, ikeSession, tunnelCallback);
+ boolean isSrcIpv6Present = setupRequest.srcIpv6Address().isPresent();
+ putApnNameToTunnelConfig(
+ apnName,
+ ikeSession,
+ tunnelCallback,
+ isSrcIpv6Present ? setupRequest.srcIpv6Address().get() : null,
+ setupRequest.srcIpv6AddressPrefixLength());
}
/**
@@ -733,6 +798,10 @@
IkeSessionParams.Builder builder =
new IkeSessionParams.Builder(mContext)
+ //permanently hardcode DSCP to 46 (Expedited Forwarding class)
+ //See https://www.iana.org/assignments/dscp-registry/dscp-registry.xhtml
+ //This will make WiFi prioritize IKE signallig under WMM AC_VO
+ .setDscp(46)
.setServerHostname(mEpdgAddress.getHostName())
.setLocalIdentification(getLocalIdentification())
.setRemoteIdentification(getId(setupRequest.apnName(), false))
@@ -825,7 +894,7 @@
for (int encryptionAlgo : encryptionAlgos) {
validateConfig(encryptionAlgo, VALID_ENCRYPTION_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO);
- if (encryptionAlgo == CarrierConfigManager.Iwlan.ENCRYPTION_ALGORITHM_AES_CBC) {
+ if (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_CBC) {
int[] aesCbcKeyLens =
getConfig(
CarrierConfigManager.Iwlan
@@ -837,7 +906,7 @@
}
}
- if (encryptionAlgo == CarrierConfigManager.Iwlan.ENCRYPTION_ALGORITHM_AES_CTR) {
+ if (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_CTR) {
int[] aesCtrKeyLens =
getConfig(
CarrierConfigManager.Iwlan
@@ -900,7 +969,7 @@
for (int encryptionAlgo : encryptionAlgos) {
if (validateConfig(encryptionAlgo, VALID_ENCRYPTION_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO)) {
if (ChildSaProposal.getSupportedEncryptionAlgorithms().contains(encryptionAlgo)) {
- if (encryptionAlgo == CarrierConfigManager.Iwlan.ENCRYPTION_ALGORITHM_AES_CBC) {
+ if (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_CBC) {
int[] aesCbcKeyLens =
getConfig(
CarrierConfigManager.Iwlan
@@ -914,7 +983,7 @@
}
}
- if (encryptionAlgo == CarrierConfigManager.Iwlan.ENCRYPTION_ALGORITHM_AES_CTR) {
+ if (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_CTR) {
int[] aesCtrKeyLens =
getConfig(
CarrierConfigManager.Iwlan
@@ -1026,7 +1095,7 @@
String message = error.getException().getCause().getMessage();
if (message != null
&& (message.equals("Retransmitting IKE INIT request failure")
- || message.equals("Retransmitting failure"))) {
+ || message.equals("Retransmitting failure"))) {
return true;
}
}
@@ -1543,8 +1612,14 @@
@VisibleForTesting
void putApnNameToTunnelConfig(
- String apnName, IkeSession ikeSession, TunnelCallback tunnelCallback) {
- mApnNameToTunnelConfig.put(apnName, new TunnelConfig(ikeSession, tunnelCallback));
+ String apnName,
+ IkeSession ikeSession,
+ TunnelCallback tunnelCallback,
+ InetAddress srcIpv6Addr,
+ int srcIPv6AddrPrefixLen) {
+ mApnNameToTunnelConfig.put(
+ apnName,
+ new TunnelConfig(ikeSession, tunnelCallback, srcIpv6Addr, srcIPv6AddrPrefixLen));
}
@VisibleForTesting
diff --git a/src/com/google/android/iwlan/epdg/NetworkSliceSelectionAssistanceInformation.java b/src/com/google/android/iwlan/epdg/NetworkSliceSelectionAssistanceInformation.java
new file mode 100644
index 0000000..669aa5d
--- /dev/null
+++ b/src/com/google/android/iwlan/epdg/NetworkSliceSelectionAssistanceInformation.java
@@ -0,0 +1,104 @@
+package com.google.android.iwlan.epdg;
+
+import android.support.annotation.NonNull;
+import android.telephony.data.NetworkSliceInfo;
+import android.util.Log;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class NetworkSliceSelectionAssistanceInformation {
+ private static final String TAG =
+ NetworkSliceSelectionAssistanceInformation.class.getSimpleName();
+ static final List<Integer> VALID_LENGTHS = Arrays.asList(1, 2, 4, 5, 8);
+
+ public static NetworkSliceInfo getSliceInfo(byte[] snssai) {
+ if (snssai == null) {
+ return null;
+ }
+ /**
+ * From 3GPP TS 24.501 Section 9.11.2.8, Content structure of the Value of S-NSSAI
+ *
+ * <p>Slice Service Type - 1 byte
+ * Slice Differentiator - 3 bytes
+ * Mapped HPLMN Slice Service Type - 1 byte
+ * Mapped HPLMN Slice Differentiator - 3 bytes
+ *
+ * <p>Depending on the value of the length field the following S-NSSAI contents are
+ * included:
+ * Bits 8 7 6 5 4 3 2 1
+ * 0 0 0 0 0 0 0 1 SST
+ * 0 0 0 0 0 0 1 0 SST and mapped HPLMN SST
+ * 0 0 0 0 0 1 0 0 SST and SD
+ * 0 0 0 0 0 1 0 1 SST, SD and mapped HPLMN SST
+ * 0 0 0 0 1 0 0 0 SST, SD, mapped HPLMN SST and mapped HPLMN SD
+ * All other values are reserved.
+ */
+ NetworkSliceInfo.Builder siBuilder = new NetworkSliceInfo.Builder();
+ int len = snssai.length;
+ // validity checks. See TS 24.501 Section 9.11.2.8
+ // length should be valid
+ if (!VALID_LENGTHS.contains(len)) {
+ Log.d(TAG, "Invalid S-NSSAI length : " + snssai.length);
+ return null;
+ }
+
+ switch (len) {
+ case 1: // get SST
+ siBuilder.setSliceServiceType(getSST(snssai, 0));
+ break;
+ case 2: // get SST and mapped SST
+ siBuilder.setSliceServiceType(getSST(snssai, 0));
+ siBuilder.setMappedHplmnSliceServiceType(getSST(snssai, 1));
+ break;
+ case 4: // get SST and SD
+ siBuilder.setSliceServiceType(getSST(snssai, 0));
+ siBuilder.setSliceDifferentiator(getSD(snssai, 1));
+ break;
+ case 5: // get SST, SD and mapped SST
+ siBuilder.setSliceServiceType(getSST(snssai, 0));
+ siBuilder.setSliceDifferentiator(getSD(snssai, 1));
+ siBuilder.setMappedHplmnSliceServiceType(getSST(snssai, 4));
+ break;
+ case 8: // get SST, SD, mapped SST, mapped SD
+ siBuilder.setSliceServiceType(getSST(snssai, 0));
+ siBuilder.setSliceDifferentiator(getSD(snssai, 1));
+ siBuilder.setMappedHplmnSliceServiceType(getSST(snssai, 4));
+ siBuilder.setMappedHplmnSliceDifferentiator(getSD(snssai, 5));
+ break;
+ }
+
+ return siBuilder.build();
+ }
+
+ private static int getSST(@NonNull byte[] snssai, int offset) {
+ if (offset < 0 || snssai.length < offset + 1) {
+ return NetworkSliceInfo.SLICE_SERVICE_TYPE_NONE;
+ }
+ /**
+ * From 3GPP TS 23.003: Values 0 to 127 belong to the standardized SST range and they are
+ * defined in 3GPP TS 23.501. Values 128 to 255 belong to the Operator-specific range
+ */
+ return Byte.toUnsignedInt(snssai[offset]);
+ }
+
+ private static int getSD(byte[] snssai, int offset) {
+ int sliceDescriptor = NetworkSliceInfo.SLICE_SERVICE_TYPE_NONE;
+ /*
+ * Slice Descriptor is 3 bytes long
+ * The SD field has a reserved value "no SD value associated with the SST"
+ * defined as hexadecimal FFFFFF
+ */
+ if (offset >= 0 && snssai.length >= offset + 3) {
+ int sd = 0;
+ sd =
+ (sd | snssai[offset + 2])
+ | ((sd | snssai[offset + 1]) << 8)
+ | ((sd | snssai[offset]) << 16);
+ if (sd != 0xFFFFFF) {
+ sliceDescriptor = sd;
+ }
+ }
+ return sliceDescriptor;
+ }
+}
diff --git a/src/com/google/android/iwlan/epdg/TunnelLinkProperties.java b/src/com/google/android/iwlan/epdg/TunnelLinkProperties.java
index 77f7295..864c282 100644
--- a/src/com/google/android/iwlan/epdg/TunnelLinkProperties.java
+++ b/src/com/google/android/iwlan/epdg/TunnelLinkProperties.java
@@ -17,6 +17,7 @@
package com.google.android.iwlan.epdg;
import android.net.LinkAddress;
+import android.telephony.data.NetworkSliceInfo;
import com.google.auto.value.AutoValue;
@@ -34,10 +35,10 @@
public abstract String ifaceName();
- public abstract Optional<byte[]> sNssai();
+ public abstract Optional<NetworkSliceInfo> sliceInfo();
static Builder builder() {
- return new AutoValue_TunnelLinkProperties.Builder().setSNssai(Optional.empty());
+ return new AutoValue_TunnelLinkProperties.Builder().setSliceInfo(Optional.empty());
}
@AutoValue.Builder
@@ -50,11 +51,11 @@
abstract Builder setIfaceName(String ifaceName);
- public Builder setSNssai(byte[] snssai) {
- return setSNssai(Optional.ofNullable(snssai));
+ public Builder setSliceInfo(NetworkSliceInfo si) {
+ return setSliceInfo(Optional.ofNullable(si));
}
- abstract Builder setSNssai(Optional<byte[]> snssai);
+ abstract Builder setSliceInfo(Optional<NetworkSliceInfo> si);
abstract TunnelLinkProperties build();
}
diff --git a/test/com/google/android/iwlan/ErrorPolicyManagerTest.java b/test/com/google/android/iwlan/ErrorPolicyManagerTest.java
index 44e50b0..320fbd0 100644
--- a/test/com/google/android/iwlan/ErrorPolicyManagerTest.java
+++ b/test/com/google/android/iwlan/ErrorPolicyManagerTest.java
@@ -562,7 +562,7 @@
assertEquals(5, time);
int failCause = mErrorPolicyManager.getDataFailCause(apn1);
- assertEquals(DataFailCause.USER_AUTHENTICATION, failCause);
+ assertEquals(DataFailCause.IWLAN_IKEV2_AUTH_FAILURE, failCause);
failCause = mErrorPolicyManager.getDataFailCause(apn2);
assertEquals(DataFailCause.IWLAN_PDN_CONNECTION_REJECTION, failCause);
diff --git a/test/com/google/android/iwlan/IwlanDataServiceTest.java b/test/com/google/android/iwlan/IwlanDataServiceTest.java
index 1320095..2c5de04 100644
--- a/test/com/google/android/iwlan/IwlanDataServiceTest.java
+++ b/test/com/google/android/iwlan/IwlanDataServiceTest.java
@@ -235,7 +235,7 @@
boolean ret = mIwlanDataService.isNetworkConnected(true, false);
assertFalse(ret);
- verify(mMockIwlanDataServiceProvider).forceCloseTunnelsInDeactivatingState();
+ verify(mMockIwlanDataServiceProvider).forceCloseTunnels();
mIwlanDataService.removeDataServiceProvider(mMockIwlanDataServiceProvider);
}
@@ -319,6 +319,8 @@
null, /* LinkProperties */
2, /* pdu session id */
null, /* sliceInfo */
+ null, /* trafficDescriptor */
+ true, /* matchAllRuleAllowed */
mMockDataServiceCallback);
verify(mMockDataServiceCallback, timeout(1000).times(1))
@@ -343,6 +345,8 @@
null, /* LinkProperties */
1, /* pdu session id */
null, /* sliceInfo */
+ null, /* trafficDescriptor */
+ true, /* matchAllRuleAllowed */
mMockDataServiceCallback);
verify(mMockDataServiceCallback, timeout(1000).times(1))
@@ -379,6 +383,8 @@
null, /* LinkProperties */
1, /* pduSessionId */
null, /* sliceInfo */
+ null, /* trafficDescriptor */
+ true, /* matchAllRuleAllowed */
mMockDataServiceCallback);
/* Check bringUpTunnel() is called. */
@@ -395,6 +401,49 @@
}
@Test
+ public void testSliceInfoInclusionInDataCallResponse() throws Exception {
+ DataProfile dp = buildDataProfile();
+
+ /* Wifi is connected */
+ mIwlanDataService.setNetworkConnected(true, mMockNetwork, IwlanDataService.Transport.WIFI);
+
+ doReturn(mMockEpdgTunnelManager).when(mSpyIwlanDataServiceProvider).getTunnelManager();
+
+ mSpyIwlanDataServiceProvider.setupDataCall(
+ AccessNetworkType.IWLAN, /* AccessNetworkType */
+ dp, /* dataProfile */
+ false, /* isRoaming */
+ true, /* allowRoaming */
+ DataService.REQUEST_REASON_NORMAL, /* DataService.REQUEST_REASON_NORMAL */
+ null, /* LinkProperties */
+ 1, /* pduSessionId */
+ null, /* sliceInfo */
+ null, /* trafficDescriptor */
+ true, /* matchAllRuleAllowed */
+ mMockDataServiceCallback);
+
+ /* Check bringUpTunnel() is called. */
+ verify(mMockEpdgTunnelManager, times(1))
+ .bringUpTunnel(any(TunnelSetupRequest.class), any(IwlanTunnelCallback.class));
+
+ /* Check callback result is RESULT_SUCCESS when onOpened() is called. */
+ TunnelLinkProperties tp = TunnelLinkPropertiesTest.createTestTunnelLinkProperties();
+
+ ArgumentCaptor<DataCallResponse> dataCallResponseCaptor =
+ ArgumentCaptor.forClass(DataCallResponse.class);
+
+ mSpyIwlanDataServiceProvider.getIwlanTunnelCallback().onOpened(TEST_APN_NAME, tp);
+ verify(mMockDataServiceCallback, times(1))
+ .onSetupDataCallComplete(
+ eq(DataServiceCallback.RESULT_SUCCESS), dataCallResponseCaptor.capture());
+
+ /* check that sliceinfo is filled up and matches */
+ DataCallResponse dataCallResponse = dataCallResponseCaptor.getValue();
+ assertNotNull(dataCallResponse.getSliceInfo());
+ assertEquals(dataCallResponse.getSliceInfo(), tp.sliceInfo().get());
+ }
+
+ @Test
public void testIwlanDeactivateDataCallWithCloseTunnel() {
DataProfile dp = buildDataProfile();
@@ -583,6 +632,8 @@
null, /* LinkProperties */
1, /* pdu session id */
null, /* sliceInfo */
+ null, /* trafficDescriptor */
+ true, /* matchAllRuleAllowed */
mMockDataServiceCallback);
verify(mMockDataServiceCallback, timeout(1000).times(1))
@@ -622,6 +673,8 @@
null, /* LinkProperties */
1, /* pduSessionId */
null, /* sliceInfo */
+ null, /* trafficDescriptor */
+ true, /* matchAllRuleAllowed */
mMockDataServiceCallback);
/* Check bringUpTunnel() is called. */
diff --git a/test/com/google/android/iwlan/epdg/EpdgSelectorTest.java b/test/com/google/android/iwlan/epdg/EpdgSelectorTest.java
index d7ffb0e..54c2fac 100644
--- a/test/com/google/android/iwlan/epdg/EpdgSelectorTest.java
+++ b/test/com/google/android/iwlan/epdg/EpdgSelectorTest.java
@@ -16,22 +16,11 @@
package com.google.android.iwlan.epdg;
-import static android.net.DnsResolver.TYPE_A;
-import static android.net.DnsResolver.TYPE_AAAA;
-
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
-
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
-import static java.util.stream.Collectors.toList;
-
import android.content.Context;
-import android.net.DnsResolver;
-import android.net.InetAddresses;
import android.net.Network;
-import android.os.Handler;
-import android.os.Looper;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import android.telephony.CellIdentityGsm;
@@ -50,22 +39,21 @@
import com.google.android.iwlan.IwlanError;
-import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.mockito.MockitoSession;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
import java.net.InetAddress;
-import java.net.UnknownHostException;
import java.util.*;
import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
+@RunWith(JUnit4.class)
public class EpdgSelectorTest {
private static final String TAG = "EpdgSelectorTest";
private EpdgSelector mEpdgSelector;
@@ -83,6 +71,8 @@
private byte[] pcoData = testPcoString.getBytes();
private List<String> ehplmnList = new ArrayList<String>();
+ @Rule public final MockitoRule mockito = MockitoJUnit.rule();
+
@Mock private Context mMockContext;
@Mock private Network mMockNetwork;
@Mock private SubscriptionManager mMockSubscriptionManager;
@@ -98,17 +88,11 @@
@Mock private CellIdentityLte mMockCellIdentityLte;
@Mock private CellInfoNr mMockCellInfoNr;
@Mock private CellIdentityNr mMockCellIdentityNr;
- @Mock private DnsResolver mMockDnsResolver;
private PersistableBundle mTestBundle;
- private FakeDns mFakeDns;
- MockitoSession mStaticMockSession;
@Before
public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
- mStaticMockSession = mockitoSession().mockStatic(DnsResolver.class).startMocking();
-
mEpdgSelector = new EpdgSelector(mMockContext, DEFAULT_SLOT_INDEX);
when(mMockContext.getSystemService(eq(SubscriptionManager.class)))
@@ -135,24 +119,14 @@
when(mMockContext.getSystemService(eq(CarrierConfigManager.class)))
.thenReturn(mMockCarrierConfigManager);
when(mMockCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(mTestBundle);
-
- lenient().when(DnsResolver.getInstance()).thenReturn(mMockDnsResolver);
-
- mFakeDns = new FakeDns();
- mFakeDns.startMocking();
- }
-
- @After
- public void cleanUp() throws Exception {
- mStaticMockSession.finishMocking();
- mFakeDns.clearAll();
}
@Test
public void testStaticMethodPass() throws Exception {
- // Set DnsResolver query mock
+ // Set Network.getAllByName mock
final String testStaticAddress = "epdg.epc.mnc088.mcc888.pub.3gppnetwork.org";
- mFakeDns.setAnswer(testStaticAddress, new String[] {TEST_IP_ADDRESS}, TYPE_A);
+ when(mMockNetwork.getAllByName(eq(testStaticAddress)))
+ .thenReturn(new InetAddress[] {InetAddress.getByName(TEST_IP_ADDRESS)});
// Set carrier config mock
mTestBundle.putIntArray(
@@ -184,17 +158,14 @@
public void testPlmnResolutionMethodWithNoPlmnInCarrierConfig() throws Exception {
// setUp() fills default values for mcc-mnc
String expectedFqdn1 = "epdg.epc.mnc120.mcc311.pub.3gppnetwork.org";
- String expectedFqdn2 = "epdg.epc.mnc120.mcc300.pub.3gppnetwork.org";
-
- mFakeDns.setAnswer(expectedFqdn1, new String[] {TEST_IP_ADDRESS_1}, TYPE_A);
- mFakeDns.setAnswer(expectedFqdn2, new String[] {TEST_IP_ADDRESS_2}, TYPE_A);
+ when(mMockNetwork.getAllByName(eq(expectedFqdn1)))
+ .thenReturn(new InetAddress[] {InetAddress.getByName(TEST_IP_ADDRESS_1)});
ArrayList<InetAddress> testInetAddresses =
getValidatedServerListWithDefaultParams(false /*isEmergency*/);
- assertEquals(testInetAddresses.size(), 2);
+ assertEquals(testInetAddresses.size(), 1);
assertTrue(testInetAddresses.contains(InetAddress.getByName(TEST_IP_ADDRESS_1)));
- assertTrue(testInetAddresses.contains(InetAddress.getByName(TEST_IP_ADDRESS_2)));
}
private void testPlmnResolutionMethod(boolean isEmergency) throws Exception {
@@ -218,13 +189,20 @@
CarrierConfigManager.Iwlan.KEY_MCC_MNCS_STRING_ARRAY,
new String[] {"310-480", "300-120", "311-120"});
- mFakeDns.setAnswer(expectedFqdn1, new String[] {TEST_IP_ADDRESS_1}, TYPE_A);
- mFakeDns.setAnswer(expectedFqdn2, new String[] {TEST_IP_ADDRESS_2}, TYPE_A);
- mFakeDns.setAnswer(expectedFqdn3, new String[] {TEST_IP_ADDRESS}, TYPE_A);
+ when(mMockNetwork.getAllByName(eq(expectedFqdn1)))
+ .thenReturn(new InetAddress[] {InetAddress.getByName(TEST_IP_ADDRESS_1)});
+ when(mMockNetwork.getAllByName(eq(expectedFqdn2)))
+ .thenReturn(new InetAddress[] {InetAddress.getByName(TEST_IP_ADDRESS_2)});
+ when(mMockNetwork.getAllByName(eq(expectedFqdn3)))
+ .thenReturn(new InetAddress[] {InetAddress.getByName(TEST_IP_ADDRESS)});
ArrayList<InetAddress> testInetAddresses =
getValidatedServerListWithDefaultParams(isEmergency);
+ verify(mMockNetwork).getAllByName(expectedFqdn1);
+ verify(mMockNetwork).getAllByName(expectedFqdn2);
+ verify(mMockNetwork).getAllByName(expectedFqdn3);
+
assertEquals(testInetAddresses.size(), 3);
assertEquals(testInetAddresses.get(0), InetAddress.getByName(TEST_IP_ADDRESS));
assertEquals(testInetAddresses.get(1), InetAddress.getByName(TEST_IP_ADDRESS_2));
@@ -238,10 +216,12 @@
final String addr2 = "epdg.epc.mnc120.mcc300.pub.3gppnetwork.org";
final String addr3 = "epdg.epc.mnc120.mcc311.pub.3gppnetwork.org";
final String testStaticAddress = addr1 + "," + addr2 + "," + addr3;
-
- mFakeDns.setAnswer(addr1, new String[] {TEST_IP_ADDRESS_1}, TYPE_A);
- mFakeDns.setAnswer(addr2, new String[] {TEST_IP_ADDRESS_2}, TYPE_A);
- mFakeDns.setAnswer(addr3, new String[] {TEST_IP_ADDRESS}, TYPE_A);
+ when(mMockNetwork.getAllByName(eq(addr1)))
+ .thenReturn(new InetAddress[] {InetAddress.getByName(TEST_IP_ADDRESS_1)});
+ when(mMockNetwork.getAllByName(eq(addr2)))
+ .thenReturn(new InetAddress[] {InetAddress.getByName(TEST_IP_ADDRESS_2)});
+ when(mMockNetwork.getAllByName(eq(addr3)))
+ .thenReturn(new InetAddress[] {InetAddress.getByName(TEST_IP_ADDRESS)});
// Set carrier config mock
mTestBundle.putIntArray(
@@ -350,7 +330,15 @@
int testLac = 65484;
int testTac = 65484;
int testNrTac = 16764074;
-
+ String fqdn1_emergency = "lacffcc.sos.epdg.epc.mnc120.mcc311.pub.3gppnetwork.org";
+ String fqdn1 = "lacffcc.epdg.epc.mnc120.mcc311.pub.3gppnetwork.org";
+ String fqdn2_emergency =
+ "tac-lbcc.tac-hbff.tac.sos.epdg.epc.mnc120.mcc311.pub.3gppnetwork.org";
+ String fqdn2 = "tac-lbcc.tac-hbff.tac.epdg.epc.mnc120.mcc311.pub.3gppnetwork.org";
+ String fqdn3_emergency =
+ "tac-lbaa.tac-mbcc.tac-hbff.5gstac.sos.epdg.epc.mnc120.mcc311.pub.3gppnetwork.org";
+ String fqdn3 =
+ "tac-lbaa.tac-mbcc.tac-hbff.5gstac.epdg.epc.mnc120.mcc311.pub.3gppnetwork.org";
List<CellInfo> fakeCellInfoArray = new ArrayList<CellInfo>();
mTestBundle.putIntArray(
@@ -388,164 +376,27 @@
when(mMockTelephonyManager.getAllCellInfo()).thenReturn(fakeCellInfoArray);
- setAnswerForCellularMethod(isEmergency, 311, 120);
- setAnswerForCellularMethod(isEmergency, 300, 120);
+ String expectedFqdn1 = (isEmergency) ? fqdn1_emergency : fqdn1;
+ String expectedFqdn2 = (isEmergency) ? fqdn2_emergency : fqdn2;
+ String expectedFqdn3 = (isEmergency) ? fqdn3_emergency : fqdn3;
+
+ when(mMockNetwork.getAllByName(eq(expectedFqdn1)))
+ .thenReturn(new InetAddress[] {InetAddress.getByName(TEST_IP_ADDRESS)});
+ when(mMockNetwork.getAllByName(eq(expectedFqdn2)))
+ .thenReturn(new InetAddress[] {InetAddress.getByName(TEST_IP_ADDRESS_1)});
+ when(mMockNetwork.getAllByName(eq(expectedFqdn3)))
+ .thenReturn(new InetAddress[] {InetAddress.getByName(TEST_IP_ADDRESS_2)});
ArrayList<InetAddress> testInetAddresses =
getValidatedServerListWithDefaultParams(isEmergency);
+ verify(mMockNetwork, times(2)).getAllByName(expectedFqdn1);
+ verify(mMockNetwork).getAllByName(expectedFqdn2);
+ verify(mMockNetwork).getAllByName(expectedFqdn3);
+
assertEquals(testInetAddresses.size(), 3);
assertEquals(testInetAddresses.get(0), InetAddress.getByName(TEST_IP_ADDRESS));
assertEquals(testInetAddresses.get(1), InetAddress.getByName(TEST_IP_ADDRESS_1));
assertEquals(testInetAddresses.get(2), InetAddress.getByName(TEST_IP_ADDRESS_2));
}
-
- private void setAnswerForCellularMethod(boolean isEmergency, int mcc, int mnc)
- throws Exception {
- String expectedFqdn1 =
- (isEmergency)
- ? "lacffcc.sos.epdg.epc.mnc" + mnc + ".mcc" + mcc + ".pub.3gppnetwork.org"
- : "lacffcc.epdg.epc.mnc" + mnc + ".mcc" + mcc + ".pub.3gppnetwork.org";
- String expectedFqdn2 =
- (isEmergency)
- ? "tac-lbcc.tac-hbff.tac.sos.epdg.epc.mnc"
- + mnc
- + ".mcc"
- + mcc
- + ".pub.3gppnetwork.org"
- : "tac-lbcc.tac-hbff.tac.epdg.epc.mnc"
- + mnc
- + ".mcc"
- + mcc
- + ".pub.3gppnetwork.org";
- String expectedFqdn3 =
- (isEmergency)
- ? "tac-lbaa.tac-mbcc.tac-hbff.5gstac.sos.epdg.epc.mnc"
- + mnc
- + ".mcc"
- + mcc
- + ".pub.3gppnetwork.org"
- : "tac-lbaa.tac-mbcc.tac-hbff.5gstac.epdg.epc.mnc"
- + mnc
- + ".mcc"
- + mcc
- + ".pub.3gppnetwork.org";
-
- mFakeDns.setAnswer(expectedFqdn1, new String[] {TEST_IP_ADDRESS}, TYPE_A);
- mFakeDns.setAnswer(expectedFqdn2, new String[] {TEST_IP_ADDRESS_1}, TYPE_A);
- mFakeDns.setAnswer(expectedFqdn3, new String[] {TEST_IP_ADDRESS_2}, TYPE_A);
- }
-
- /**
- * Fakes DNS responses.
- *
- * <p>Allows test methods to configure the IP addresses that will be resolved by
- * Network#getAllByName and by DnsResolver#query.
- */
- class FakeDns {
- /** Data class to record the Dns entry. */
- class DnsEntry {
- final String mHostname;
- final int mType;
- final List<InetAddress> mAddresses;
-
- DnsEntry(String host, int type, List<InetAddress> addr) {
- mHostname = host;
- mType = type;
- mAddresses = addr;
- }
- // Full match or partial match that target host contains the entry hostname to support
- // random private dns probe hostname.
- private boolean matches(String hostname, int type) {
- return hostname.endsWith(mHostname) && type == mType;
- }
- }
-
- private final ArrayList<DnsEntry> mAnswers = new ArrayList<DnsEntry>();
-
- /** Clears all DNS entries. */
- private synchronized void clearAll() {
- mAnswers.clear();
- }
-
- /** Returns the answer for a given name and type on the given mock network. */
- private synchronized List<InetAddress> getAnswer(Object mock, String hostname, int type) {
- return mAnswers.stream()
- .filter(e -> e.matches(hostname, type))
- .map(answer -> answer.mAddresses)
- .findFirst()
- .orElse(null);
- }
-
- /** Sets the answer for a given name and type. */
- private synchronized void setAnswer(String hostname, String[] answer, int type)
- throws UnknownHostException {
- DnsEntry record = new DnsEntry(hostname, type, generateAnswer(answer));
- // Remove the existing one.
- mAnswers.removeIf(entry -> entry.matches(hostname, type));
- // Add or replace a new record.
- mAnswers.add(record);
- }
-
- private List<InetAddress> generateAnswer(String[] answer) {
- if (answer == null) return new ArrayList<>();
- return Arrays.stream(answer)
- .map(addr -> InetAddresses.parseNumericAddress(addr))
- .collect(toList());
- }
-
- // Regardless of the type, depends on what the responses contained in the network.
- private List<InetAddress> queryAllTypes(Object mock, String hostname) {
- List<InetAddress> answer = new ArrayList<>();
- addAllIfNotNull(answer, getAnswer(mock, hostname, TYPE_A));
- addAllIfNotNull(answer, getAnswer(mock, hostname, TYPE_AAAA));
- return answer;
- }
-
- private void addAllIfNotNull(List<InetAddress> list, List<InetAddress> c) {
- if (c != null) {
- list.addAll(c);
- }
- }
-
- /** Starts mocking DNS queries. */
- private void startMocking() throws UnknownHostException {
- doAnswer(
- invocation -> {
- return mockQuery(
- invocation,
- 1 /* posHostname */,
- 3 /* posExecutor */,
- 5 /* posCallback */,
- -1 /* posType */);
- })
- .when(mMockDnsResolver)
- .query(any(), any(), anyInt(), any(), any(), any());
- }
-
- // Mocking queries on DnsResolver#query.
- private Answer mockQuery(
- InvocationOnMock invocation,
- int posHostname,
- int posExecutor,
- int posCallback,
- int posType) {
- String hostname = (String) invocation.getArgument(posHostname);
- Executor executor = (Executor) invocation.getArgument(posExecutor);
- DnsResolver.Callback<List<InetAddress>> callback = invocation.getArgument(posCallback);
- List<InetAddress> answer;
-
- answer = queryAllTypes(invocation.getMock(), hostname);
-
- if (answer != null && answer.size() > 0) {
- new Handler(Looper.getMainLooper())
- .post(
- () -> {
- executor.execute(() -> callback.onAnswer(answer, 0));
- });
- }
- // If no answers, do nothing. sendDnsProbeWithTimeout will time out and throw UHE.
- return null;
- }
- }
}
diff --git a/test/com/google/android/iwlan/epdg/EpdgTunnelManagerTest.java b/test/com/google/android/iwlan/epdg/EpdgTunnelManagerTest.java
index 79e3726..7c4d19a 100644
--- a/test/com/google/android/iwlan/epdg/EpdgTunnelManagerTest.java
+++ b/test/com/google/android/iwlan/epdg/EpdgTunnelManagerTest.java
@@ -29,12 +29,15 @@
import android.content.Context;
import android.net.InetAddresses;
+import android.net.LinkAddress;
import android.net.Network;
import android.net.ipsec.ike.ChildSessionCallback;
import android.net.ipsec.ike.ChildSessionParams;
+import android.net.ipsec.ike.IkeFqdnIdentification;
import android.net.ipsec.ike.IkeSession;
import android.net.ipsec.ike.IkeSessionCallback;
import android.net.ipsec.ike.IkeSessionParams;
+import android.net.ipsec.ike.TunnelModeChildSessionParams;
import android.net.ipsec.ike.exceptions.IkeException;
import android.net.ipsec.ike.exceptions.IkeInternalException;
import android.net.ipsec.ike.exceptions.InvalidIkeSpiException;
@@ -64,6 +67,8 @@
import org.mockito.junit.MockitoRule;
import java.io.IOException;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
@@ -208,7 +213,7 @@
TunnelSetupRequest TSR = getBasicTunnelSetupRequest(TEST_APN_NAME, ApnSetting.PROTOCOL_IP);
mEpdgTunnelManager.putApnNameToTunnelConfig(
- testApnName2, mMockIkeSession, mMockIwlanTunnelCallback);
+ testApnName2, mMockIkeSession, mMockIwlanTunnelCallback, null, 0);
doReturn(true).when(mEpdgTunnelManager).canBringUpTunnel(eq(TEST_APN_NAME));
boolean ret = mEpdgTunnelManager.bringUpTunnel(TSR, mMockIwlanTunnelCallback);
@@ -246,7 +251,7 @@
String testApnName = "www.xyz.com";
mEpdgTunnelManager.putApnNameToTunnelConfig(
- testApnName, mMockIkeSession, mMockIwlanTunnelCallback);
+ testApnName, mMockIkeSession, mMockIwlanTunnelCallback, null, 0);
boolean ret = mEpdgTunnelManager.closeTunnel(testApnName, true /*forceClose*/);
assertTrue(ret);
@@ -259,7 +264,7 @@
String testApnName = "www.xyz.com";
mEpdgTunnelManager.putApnNameToTunnelConfig(
- testApnName, mMockIkeSession, mMockIwlanTunnelCallback);
+ testApnName, mMockIkeSession, mMockIwlanTunnelCallback, null, 0);
boolean ret = mEpdgTunnelManager.closeTunnel(testApnName, false /*forceClose*/);
assertTrue(ret);
@@ -590,6 +595,20 @@
}
@Test
+ public void testIpv6PrefixMatching() throws Exception {
+ InetAddress a1 = InetAddress.getByName("2600:381:4872:5d1e:ac45:69c7:bab2:639b");
+ LinkAddress l1 = new LinkAddress(a1, 64);
+ InetAddress src = InetAddress.getByName("2600:381:4872:5d1e:0:10:3582:a501");
+ EpdgTunnelManager.TunnelConfig tf =
+ mEpdgTunnelManager.new TunnelConfig(null, null, src, 64);
+ assertTrue(tf.isPrefixSameAsSrcIP(l1));
+
+ // different prefix length
+ LinkAddress l2 = new LinkAddress(a1, 63);
+ assertFalse(tf.isPrefixSameAsSrcIP(l2));
+ }
+
+ @Test
public void testBackOffTimeCalculation() throws Exception {
// unit: 10 mins value: 2 expectedTime: 1200 (10 * 60 * 2)
verifyBackOffTimer("00000010", 1200);
@@ -768,7 +787,7 @@
doReturn(0L).when(mEpdgTunnelManager).reportIwlanError(eq(testApnName), eq(error));
mEpdgTunnelManager.putApnNameToTunnelConfig(
- testApnName, mMockIkeSession, mMockIwlanTunnelCallback);
+ testApnName, mMockIkeSession, mMockIwlanTunnelCallback, null, 0);
mEpdgTunnelManager.setIsEpdgAddressSelected(true);
@@ -818,7 +837,7 @@
doReturn(0L).when(mEpdgTunnelManager).reportIwlanError(eq(testApnName), eq(error));
mEpdgTunnelManager.putApnNameToTunnelConfig(
- testApnName, mMockIkeSession, mMockIwlanTunnelCallback);
+ testApnName, mMockIkeSession, mMockIwlanTunnelCallback, null, 0);
mEpdgTunnelManager.setIsEpdgAddressSelected(true);
@@ -1025,7 +1044,7 @@
doReturn(0L).when(mEpdgTunnelManager).reportIwlanError(eq(testApnName), eq(error));
mEpdgTunnelManager.putApnNameToTunnelConfig(
- testApnName, mMockIkeSession, mMockIwlanTunnelCallback);
+ testApnName, mMockIkeSession, mMockIwlanTunnelCallback, null, 0);
mEpdgTunnelManager.setIsEpdgAddressSelected(true);
@@ -1202,4 +1221,137 @@
IkeSessionParams ikeSessionParams = ikeSessionParamsCaptor.getValue();
assertEquals(ikeSessionParams.getNattKeepAliveDelaySeconds(), ikeDefaultNattTimerValue);
}
+
+ @Test
+ public void testTunnelSetupRequestParams() throws Exception {
+ String testApnName = "www.xyz.com";
+ Network testNetwork = new Network(123);
+ Inet6Address testAddressV6 = Inet6Address.getByAddress("25.25.25.25", new byte[16], 0);
+ Inet4Address testAddressV4 = (Inet4Address) Inet4Address.getByName("30.30.30.30");
+ int pduSessionId = 5;
+ boolean isRoaming = false;
+ boolean isEmergency = true;
+ boolean requestPcscf = true;
+ int ipv6AddressLen = 64;
+
+ TunnelSetupRequest tsr =
+ TunnelSetupRequest.builder()
+ .setApnName(testApnName)
+ .setNetwork(testNetwork)
+ .setApnIpProtocol(ApnSetting.PROTOCOL_IPV4V6)
+ .setSrcIpv6Address(testAddressV6)
+ .setSrcIpv6AddressPrefixLength(ipv6AddressLen)
+ .setSrcIpv4Address(testAddressV4)
+ .setPduSessionId(pduSessionId)
+ .setIsRoaming(isRoaming)
+ .setIsEmergency(isEmergency)
+ .setRequestPcscf(requestPcscf)
+ .build();
+
+ setupMockForGetConfig(null);
+ when(mMockEpdgSelector.getValidatedServerList(
+ anyInt(),
+ eq(isRoaming),
+ eq(isEmergency),
+ eq(testNetwork),
+ any(EpdgSelector.EpdgSelectorCallback.class)))
+ .thenReturn(new IwlanError(IwlanError.NO_ERROR));
+
+ doReturn(null)
+ .when(mMockIkeSessionCreator)
+ .createIkeSession(
+ eq(mMockContext),
+ any(IkeSessionParams.class),
+ any(ChildSessionParams.class),
+ any(Executor.class),
+ any(IkeSessionCallback.class),
+ any(ChildSessionCallback.class));
+ doReturn(true).when(mEpdgTunnelManager).canBringUpTunnel(eq(testApnName));
+
+ boolean ret = mEpdgTunnelManager.bringUpTunnel(tsr, mMockIwlanTunnelCallback);
+ assertTrue(ret);
+
+ // verify isRoaming, isEmergency and Network variables.
+ verify(mMockEpdgSelector)
+ .getValidatedServerList(
+ anyInt(), // only Ipv6 address is added
+ eq(isRoaming),
+ eq(isEmergency),
+ eq(testNetwork),
+ any(EpdgSelector.EpdgSelectorCallback.class));
+
+ ArrayList<InetAddress> ipList = new ArrayList<>();
+ ipList.add(InetAddress.getByName(TEST_IP_ADDRESS));
+ mEpdgTunnelManager.sendSelectionRequestComplete(
+ ipList, new IwlanError(IwlanError.NO_ERROR));
+
+ ArgumentCaptor<IkeSessionParams> ikeSessionParamsCaptor =
+ ArgumentCaptor.forClass(IkeSessionParams.class);
+ ArgumentCaptor<TunnelModeChildSessionParams> childSessionParamsCaptor =
+ ArgumentCaptor.forClass(TunnelModeChildSessionParams.class);
+
+ verify(mMockIkeSessionCreator)
+ .createIkeSession(
+ eq(mMockContext),
+ ikeSessionParamsCaptor.capture(),
+ childSessionParamsCaptor.capture(),
+ any(Executor.class),
+ any(IkeSessionCallback.class),
+ any(ChildSessionCallback.class));
+
+ IkeSessionParams ikeSessionParams = ikeSessionParamsCaptor.getValue();
+ TunnelModeChildSessionParams childSessionParams = childSessionParamsCaptor.getValue();
+
+ // apnName verification. By default remote identification is type fqdn
+ IkeFqdnIdentification ikeId =
+ (IkeFqdnIdentification) ikeSessionParams.getRemoteIdentification();
+ assertEquals(ikeId.fqdn, testApnName);
+
+ // verify Network
+ assertEquals(ikeSessionParams.getConfiguredNetwork(), testNetwork);
+
+ // verify requestPcscf (true) with Apn protocol IPV6
+ // it should add the pcscf config requests of type ConfigRequestIpv6PcscfServer and
+ // ConfigRequestIpv4PcscfServer
+ assertTrue(
+ ikeSessionParams.getConfigurationRequests().stream()
+ .anyMatch(c -> c instanceof IkeSessionParams.ConfigRequestIpv6PcscfServer));
+ assertTrue(
+ ikeSessionParams.getConfigurationRequests().stream()
+ .anyMatch(c -> c instanceof IkeSessionParams.ConfigRequestIpv4PcscfServer));
+
+ // verify pduSessionID
+ assertEquals(
+ ikeSessionParams.getIke3gppExtension().getIke3gppParams().getPduSessionId(),
+ pduSessionId);
+
+ // verify src ipv6 and src ipv4 address
+ List<TunnelModeChildSessionParams.TunnelModeChildConfigRequest> configRequests =
+ childSessionParams.getConfigurationRequests();
+ boolean ipv6ConfigRequestPresent = false;
+ boolean ipv4ConfigRequestPresent = true;
+ for (TunnelModeChildSessionParams.TunnelModeChildConfigRequest configRequest :
+ configRequests) {
+ if (configRequest instanceof TunnelModeChildSessionParams.ConfigRequestIpv6Address) {
+ ipv6ConfigRequestPresent = true;
+ assertEquals(
+ ((TunnelModeChildSessionParams.ConfigRequestIpv6Address) configRequest)
+ .getAddress(),
+ testAddressV6);
+ assertEquals(
+ ((TunnelModeChildSessionParams.ConfigRequestIpv6Address) configRequest)
+ .getPrefixLength(),
+ ipv6AddressLen);
+ }
+ if (configRequest instanceof TunnelModeChildSessionParams.ConfigRequestIpv4Address) {
+ ipv4ConfigRequestPresent = true;
+ assertEquals(
+ ((TunnelModeChildSessionParams.ConfigRequestIpv4Address) configRequest)
+ .getAddress(),
+ testAddressV4);
+ }
+ }
+ assertTrue(ipv6ConfigRequestPresent);
+ assertTrue(ipv4ConfigRequestPresent);
+ }
}
diff --git a/test/com/google/android/iwlan/epdg/NetworkSliceSelectionAssistanceInformationTest.java b/test/com/google/android/iwlan/epdg/NetworkSliceSelectionAssistanceInformationTest.java
new file mode 100644
index 0000000..4ebae32
--- /dev/null
+++ b/test/com/google/android/iwlan/epdg/NetworkSliceSelectionAssistanceInformationTest.java
@@ -0,0 +1,135 @@
+package com.google.android.iwlan.epdg;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+
+import android.telephony.data.NetworkSliceInfo;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.*;
+
+@RunWith(JUnit4.class)
+public class NetworkSliceSelectionAssistanceInformationTest {
+ private static final String TAG = "NssaiTest";
+
+ @Before
+ public void setUp() throws Exception {}
+
+ @After
+ public void cleanUp() throws Exception {}
+
+ @Test
+ public void testNullNssai() throws Exception {
+ NetworkSliceInfo si = NetworkSliceSelectionAssistanceInformation.getSliceInfo(null);
+ assertNull(si);
+ }
+
+ @Test
+ public void testNssaiWithInvalidLength() throws Exception {
+ // only these lengths are valid: 1, 2, 4, 5, 8
+
+ byte[] nssai0 = {}; // length 0
+ byte[] nssai3 = {1, 1, 1}; // length 3
+ byte[] nssai6 = {1, 1, 1, 2, 1, 1}; // length 6
+ byte[] nssai10 = {1, 1, 1, 2, 1, 1, 2, 1, 1, 1}; // length 10
+
+ NetworkSliceInfo si;
+
+ si = NetworkSliceSelectionAssistanceInformation.getSliceInfo(nssai0);
+ assertNull(si);
+
+ si = NetworkSliceSelectionAssistanceInformation.getSliceInfo(nssai3);
+ assertNull(si);
+
+ si = NetworkSliceSelectionAssistanceInformation.getSliceInfo(nssai6);
+ assertNull(si);
+
+ si = NetworkSliceSelectionAssistanceInformation.getSliceInfo(nssai10);
+ assertNull(si);
+ }
+
+ @Test
+ public void testNssaiWithSST() throws Exception {
+ byte[] nssai = {3}; // SST = 3
+ NetworkSliceInfo si;
+
+ si = NetworkSliceSelectionAssistanceInformation.getSliceInfo(nssai);
+
+ assertNotNull(si);
+ assertEquals(si.getSliceServiceType(), 3);
+ assertEquals(si.getMappedHplmnSliceServiceType(), NetworkSliceInfo.SLICE_SERVICE_TYPE_NONE);
+ assertEquals(si.getSliceDifferentiator(), NetworkSliceInfo.SLICE_DIFFERENTIATOR_NO_SLICE);
+ assertEquals(
+ si.getMappedHplmnSliceDifferentiator(),
+ NetworkSliceInfo.SLICE_DIFFERENTIATOR_NO_SLICE);
+ }
+
+ @Test
+ public void testNssaiWithSSTandMappedSST() throws Exception {
+ byte[] nssai = {3, 2}; // SST = 3, mapped SST=2
+ NetworkSliceInfo si;
+
+ si = NetworkSliceSelectionAssistanceInformation.getSliceInfo(nssai);
+
+ assertNotNull(si);
+ assertEquals(si.getSliceServiceType(), 3);
+ assertEquals(si.getMappedHplmnSliceServiceType(), 2);
+ assertEquals(si.getSliceDifferentiator(), NetworkSliceInfo.SLICE_DIFFERENTIATOR_NO_SLICE);
+ assertEquals(
+ si.getMappedHplmnSliceDifferentiator(),
+ NetworkSliceInfo.SLICE_DIFFERENTIATOR_NO_SLICE);
+ }
+
+ @Test
+ public void testNssaiWithSSTandSD() throws Exception {
+ byte[] nssai = {3, 0x0a, 0x0b, 0x0c}; // SST = 3, SD=0x0a0b0c
+ NetworkSliceInfo si;
+
+ si = NetworkSliceSelectionAssistanceInformation.getSliceInfo(nssai);
+
+ assertNotNull(si);
+ assertEquals(si.getSliceServiceType(), 3);
+ assertEquals(si.getMappedHplmnSliceServiceType(), NetworkSliceInfo.SLICE_SERVICE_TYPE_NONE);
+ assertEquals(si.getSliceDifferentiator(), 0x0a0b0c);
+ assertEquals(
+ si.getMappedHplmnSliceDifferentiator(),
+ NetworkSliceInfo.SLICE_DIFFERENTIATOR_NO_SLICE);
+ }
+
+ @Test
+ public void testNssaiWithSSTandSDandMappedSST() throws Exception {
+ byte[] nssai = {3, 0x0a, 0x0b, 0x0c, 3}; // SST = 3, SD=0x0a0b0c, Mapped SST=3
+ NetworkSliceInfo si;
+
+ si = NetworkSliceSelectionAssistanceInformation.getSliceInfo(nssai);
+
+ assertNotNull(si);
+ assertEquals(si.getSliceServiceType(), 3);
+ assertEquals(si.getMappedHplmnSliceServiceType(), 3);
+ assertEquals(si.getSliceDifferentiator(), 0x0a0b0c);
+ assertEquals(
+ si.getMappedHplmnSliceDifferentiator(),
+ NetworkSliceInfo.SLICE_DIFFERENTIATOR_NO_SLICE);
+ }
+
+ @Test
+ public void testNssaiWithSSTandSDandMappedSSTandMappedSD() throws Exception {
+ byte[] nssai = {
+ 3, 0x0a, 0x0b, 0x0c, 2, 0x0F, 0x0E, 0x0D
+ }; // SST = 3, SD=0x0a0b0c, Mapped SST=2, Mapped SD =0x0f0e0d
+ NetworkSliceInfo si;
+
+ si = NetworkSliceSelectionAssistanceInformation.getSliceInfo(nssai);
+
+ assertNotNull(si);
+ assertEquals(si.getSliceServiceType(), 3);
+ assertEquals(si.getMappedHplmnSliceServiceType(), 2);
+ assertEquals(si.getSliceDifferentiator(), 0x0a0b0c);
+ assertEquals(si.getMappedHplmnSliceDifferentiator(), 0x0f0e0d);
+ }
+}
diff --git a/test/com/google/android/iwlan/epdg/TunnelLinkPropertiesTest.java b/test/com/google/android/iwlan/epdg/TunnelLinkPropertiesTest.java
index b1e2505..4f8f8cc 100644
--- a/test/com/google/android/iwlan/epdg/TunnelLinkPropertiesTest.java
+++ b/test/com/google/android/iwlan/epdg/TunnelLinkPropertiesTest.java
@@ -17,6 +17,7 @@
package com.google.android.iwlan.epdg;
import android.net.LinkAddress;
+import android.telephony.data.NetworkSliceInfo;
import java.net.InetAddress;
import java.util.LinkedList;
@@ -28,7 +29,8 @@
private static final String DNS_ADDRESS = "8.8.8.8";
private static final String PSCF_ADDRESS = "10.159.204.230";
private static final String INTERFACE_NAME = "ipsec6";
- private static final byte[] SNSSAI = new byte[] {1, 2, 3};
+ private static final NetworkSliceInfo SLICE_INFO =
+ NetworkSliceSelectionAssistanceInformation.getSliceInfo(new byte[] {1});
public static TunnelLinkProperties createTestTunnelLinkProperties() throws Exception {
List<LinkAddress> mInternalAddressList = new LinkedList<>();
@@ -47,7 +49,7 @@
.setDnsAddresses(mDNSAddressList)
.setPcscfAddresses(mPCSFAddressList)
.setIfaceName(INTERFACE_NAME)
- .setSNssai(SNSSAI)
+ .setSliceInfo(SLICE_INFO)
.build();
}
}