1 /*
2  * Copyright 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.android.iwlan.epdg;
18 
19 import static android.net.ipsec.ike.ike3gpp.Ike3gppData.DATA_TYPE_NOTIFY_BACKOFF_TIMER;
20 import static android.net.ipsec.ike.ike3gpp.Ike3gppData.DATA_TYPE_NOTIFY_N1_MODE_INFORMATION;
21 import static android.net.ipsec.ike.ike3gpp.Ike3gppParams.PDU_SESSION_ID_UNSET;
22 import static android.system.OsConstants.AF_INET;
23 import static android.system.OsConstants.AF_INET6;
24 import static android.telephony.PreciseDataConnectionState.NetworkValidationStatus;
25 
26 import android.content.Context;
27 import android.net.ConnectivityManager;
28 import android.net.InetAddresses;
29 import android.net.IpPrefix;
30 import android.net.IpSecManager;
31 import android.net.IpSecTransform;
32 import android.net.LinkAddress;
33 import android.net.LinkProperties;
34 import android.net.Network;
35 import android.net.NetworkCapabilities;
36 import android.net.eap.EapAkaInfo;
37 import android.net.eap.EapInfo;
38 import android.net.eap.EapSessionConfig;
39 import android.net.ipsec.ike.ChildSaProposal;
40 import android.net.ipsec.ike.ChildSessionCallback;
41 import android.net.ipsec.ike.ChildSessionConfiguration;
42 import android.net.ipsec.ike.ChildSessionParams;
43 import android.net.ipsec.ike.IkeFqdnIdentification;
44 import android.net.ipsec.ike.IkeIdentification;
45 import android.net.ipsec.ike.IkeKeyIdIdentification;
46 import android.net.ipsec.ike.IkeRfc822AddrIdentification;
47 import android.net.ipsec.ike.IkeSaProposal;
48 import android.net.ipsec.ike.IkeSession;
49 import android.net.ipsec.ike.IkeSessionCallback;
50 import android.net.ipsec.ike.IkeSessionConfiguration;
51 import android.net.ipsec.ike.IkeSessionConnectionInfo;
52 import android.net.ipsec.ike.IkeSessionParams;
53 import android.net.ipsec.ike.IkeTrafficSelector;
54 import android.net.ipsec.ike.SaProposal;
55 import android.net.ipsec.ike.TunnelModeChildSessionParams;
56 import android.net.ipsec.ike.exceptions.IkeException;
57 import android.net.ipsec.ike.exceptions.IkeIOException;
58 import android.net.ipsec.ike.exceptions.IkeProtocolException;
59 import android.net.ipsec.ike.ike3gpp.Ike3gppBackoffTimer;
60 import android.net.ipsec.ike.ike3gpp.Ike3gppData;
61 import android.net.ipsec.ike.ike3gpp.Ike3gppExtension;
62 import android.net.ipsec.ike.ike3gpp.Ike3gppN1ModeInformation;
63 import android.net.ipsec.ike.ike3gpp.Ike3gppParams;
64 import android.os.Handler;
65 import android.os.HandlerThread;
66 import android.os.Looper;
67 import android.os.Message;
68 import android.support.annotation.IntDef;
69 import android.support.annotation.NonNull;
70 import android.support.annotation.Nullable;
71 import android.telephony.CarrierConfigManager;
72 import android.telephony.PreciseDataConnectionState;
73 import android.telephony.SubscriptionManager;
74 import android.telephony.TelephonyManager;
75 import android.telephony.data.ApnSetting;
76 import android.telephony.data.NetworkSliceInfo;
77 import android.util.Log;
78 
79 import com.android.internal.annotations.VisibleForTesting;
80 
81 import com.google.android.iwlan.ErrorPolicyManager;
82 import com.google.android.iwlan.IwlanCarrierConfig;
83 import com.google.android.iwlan.IwlanError;
84 import com.google.android.iwlan.IwlanHelper;
85 import com.google.android.iwlan.IwlanTunnelMetricsImpl;
86 import com.google.android.iwlan.TunnelMetricsInterface;
87 import com.google.android.iwlan.TunnelMetricsInterface.OnClosedMetrics;
88 import com.google.android.iwlan.TunnelMetricsInterface.OnOpenedMetrics;
89 import com.google.android.iwlan.exceptions.IwlanSimNotReadyException;
90 import com.google.android.iwlan.flags.FeatureFlags;
91 import com.google.android.iwlan.flags.FeatureFlagsImpl;
92 
93 import java.io.IOException;
94 import java.io.PrintWriter;
95 import java.net.Inet4Address;
96 import java.net.Inet6Address;
97 import java.net.InetAddress;
98 import java.nio.charset.StandardCharsets;
99 import java.util.ArrayDeque;
100 import java.util.ArrayList;
101 import java.util.Arrays;
102 import java.util.List;
103 import java.util.Map;
104 import java.util.Objects;
105 import java.util.Queue;
106 import java.util.Set;
107 import java.util.concurrent.ConcurrentHashMap;
108 import java.util.concurrent.Executor;
109 import java.util.concurrent.Executors;
110 import java.util.concurrent.TimeUnit;
111 
112 public class EpdgTunnelManager {
113     private final FeatureFlags mFeatureFlags;
114     private final Context mContext;
115     private final int mSlotId;
116     private Handler mHandler;
117 
118     private static final int EVENT_TUNNEL_BRINGUP_REQUEST = 0;
119     private static final int EVENT_TUNNEL_BRINGDOWN_REQUEST = 1;
120     private static final int EVENT_CHILD_SESSION_OPENED = 2;
121     private static final int EVENT_CHILD_SESSION_CLOSED = 3;
122     private static final int EVENT_IKE_SESSION_CLOSED = 5;
123     private static final int EVENT_EPDG_ADDRESS_SELECTION_REQUEST_COMPLETE = 6;
124     private static final int EVENT_IPSEC_TRANSFORM_CREATED = 7;
125     private static final int EVENT_IPSEC_TRANSFORM_DELETED = 8;
126     private static final int EVENT_UPDATE_NETWORK = 9;
127     private static final int EVENT_IKE_SESSION_OPENED = 10;
128     private static final int EVENT_IKE_SESSION_CONNECTION_INFO_CHANGED = 11;
129     private static final int EVENT_IKE_3GPP_DATA_RECEIVED = 12;
130     private static final int EVENT_IKE_LIVENESS_STATUS_CHANGED = 13;
131     private static final int EVENT_REQUEST_NETWORK_VALIDATION_CHECK = 14;
132     private static final int IKE_HARD_LIFETIME_SEC_MINIMUM = 300;
133     private static final int IKE_HARD_LIFETIME_SEC_MAXIMUM = 86400;
134     private static final int IKE_SOFT_LIFETIME_SEC_MINIMUM = 120;
135     private static final int CHILD_HARD_LIFETIME_SEC_MINIMUM = 300;
136     private static final int CHILD_HARD_LIFETIME_SEC_MAXIMUM = 14400;
137     private static final int CHILD_SOFT_LIFETIME_SEC_MINIMUM = 120;
138     private static final int LIFETIME_MARGIN_SEC_MINIMUM = (int) TimeUnit.MINUTES.toSeconds(1L);
139     private static final int IKE_RETRANS_TIMEOUT_MS_MIN = 500;
140 
141     private static final int IKE_RETRANS_TIMEOUT_MS_MAX = (int) TimeUnit.MINUTES.toMillis(30L);
142 
143     private static final int IKE_RETRANS_MAX_ATTEMPTS_MAX = 10;
144     private static final int IKE_DPD_DELAY_SEC_MIN = 20;
145     private static final int IKE_DPD_DELAY_SEC_MAX = 1800; // 30 minutes
146     private static final int NATT_KEEPALIVE_DELAY_SEC_MIN = 10;
147     private static final int NATT_KEEPALIVE_DELAY_SEC_MAX = 120;
148 
149     private static final int DEVICE_IMEI_LEN = 15;
150     private static final int DEVICE_IMEISV_SUFFIX_LEN = 2;
151 
152     private static final int TRAFFIC_SELECTOR_START_PORT = 0;
153     private static final int TRAFFIC_SELECTOR_END_PORT = 65535;
154     private static final String TRAFFIC_SELECTOR_IPV4_START_ADDR = "0.0.0.0";
155     private static final String TRAFFIC_SELECTOR_IPV4_END_ADDR = "255.255.255.255";
156     private static final String TRAFFIC_SELECTOR_IPV6_START_ADDR = "::";
157     private static final String TRAFFIC_SELECTOR_IPV6_END_ADDR =
158             "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
159 
160     // "192.0.2.0" is selected from RFC5737, "IPv4 Address Blocks Reserved for Documentation"
161     private static final InetAddress DUMMY_ADDR = InetAddresses.parseNumericAddress("192.0.2.0");
162 
163     private static final Map<Integer, EpdgTunnelManager> mTunnelManagerInstances =
164             new ConcurrentHashMap<>();
165 
166     private final Queue<TunnelRequestWrapper> mPendingBringUpRequests = new ArrayDeque<>();
167 
168     private final EpdgInfo mValidEpdgInfo = new EpdgInfo();
169 
170     // The most recently updated system default network as seen by IwlanDataService.
171     @Nullable private Network mDefaultNetwork;
172     // The latest Network provided to the IKE session. Only for debugging purposes.
173     @Nullable private Network mIkeSessionNetwork;
174 
175     private int mTransactionId = 0;
176     private boolean mHasConnectedToEpdg;
177     private final IkeSessionCreator mIkeSessionCreator;
178     private final IpSecManager mIpSecManager;
179 
180     private final Map<String, TunnelConfig> mApnNameToTunnelConfig = new ConcurrentHashMap<>();
181     private final Map<String, Integer> mApnNameToCurrentToken = new ConcurrentHashMap<>();
182 
183     private final String TAG;
184 
185     @Nullable private byte[] mNextReauthId = null;
186     private long mEpdgServerSelectionDuration = 0;
187     private long mEpdgServerSelectionStartTime = 0;
188     private long mIkeTunnelEstablishmentStartTime = 0;
189 
190     private static final Set<Integer> VALID_DH_GROUPS;
191     private static final Set<Integer> VALID_KEY_LENGTHS;
192     private static final Set<Integer> VALID_PRF_ALGOS;
193     private static final Set<Integer> VALID_INTEGRITY_ALGOS;
194     private static final Set<Integer> VALID_ENCRYPTION_ALGOS;
195     private static final Set<Integer> VALID_AEAD_ALGOS;
196 
197     private static final String CONFIG_TYPE_DH_GROUP = "dh group";
198     private static final String CONFIG_TYPE_KEY_LEN = "algorithm key length";
199     private static final String CONFIG_TYPE_PRF_ALGO = "prf algorithm";
200     private static final String CONFIG_TYPE_INTEGRITY_ALGO = "integrity algorithm";
201     private static final String CONFIG_TYPE_ENCRYPT_ALGO = "encryption algorithm";
202 
203     static {
204         VALID_DH_GROUPS =
205                 Set.of(
206                         SaProposal.DH_GROUP_1024_BIT_MODP,
207                         SaProposal.DH_GROUP_1536_BIT_MODP,
208                         SaProposal.DH_GROUP_2048_BIT_MODP,
209                         SaProposal.DH_GROUP_3072_BIT_MODP,
210                         SaProposal.DH_GROUP_4096_BIT_MODP);
211         VALID_KEY_LENGTHS =
212                 Set.of(
213                         SaProposal.KEY_LEN_AES_128,
214                         SaProposal.KEY_LEN_AES_192,
215                         SaProposal.KEY_LEN_AES_256);
216 
217         VALID_ENCRYPTION_ALGOS =
218                 Set.of(
219                         SaProposal.ENCRYPTION_ALGORITHM_AES_CBC,
220                         SaProposal.ENCRYPTION_ALGORITHM_AES_CTR);
221 
222         VALID_INTEGRITY_ALGOS =
223                 Set.of(
224                         SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96,
225                         SaProposal.INTEGRITY_ALGORITHM_AES_XCBC_96,
226                         SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_256_128,
227                         SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_384_192,
228                         SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_512_256);
229 
230         VALID_AEAD_ALGOS =
231                 Set.of(
232                         SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8,
233                         SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12,
234                         SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16);
235 
236         VALID_PRF_ALGOS =
237                 Set.of(
238                         SaProposal.PSEUDORANDOM_FUNCTION_HMAC_SHA1,
239                         SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC,
240                         SaProposal.PSEUDORANDOM_FUNCTION_SHA2_256,
241                         SaProposal.PSEUDORANDOM_FUNCTION_SHA2_384,
242                         SaProposal.PSEUDORANDOM_FUNCTION_SHA2_512);
243     }
244 
245     @VisibleForTesting protected EpdgMonitor mEpdgMonitor = new EpdgMonitor();
246 
247     public static final int BRINGDOWN_REASON_UNKNOWN = 0;
248     public static final int BRINGDOWN_REASON_DISABLE_N1_MODE = 1;
249     public static final int BRINGDOWN_REASON_ENABLE_N1_MODE = 2;
250     public static final int BRINGDOWN_REASON_SERVICE_OUT_OF_SYNC = 3;
251     public static final int BRINGDOWN_REASON_IN_DEACTIVATING_STATE = 4;
252     public static final int BRINGDOWN_REASON_NETWORK_UPDATE_WHEN_TUNNEL_IN_BRINGUP = 5;
253     public static final int BRINGDOWN_REASON_DEACTIVATE_DATA_CALL = 6;
254 
255     @IntDef({
256         BRINGDOWN_REASON_UNKNOWN,
257         BRINGDOWN_REASON_DISABLE_N1_MODE,
258         BRINGDOWN_REASON_ENABLE_N1_MODE,
259         BRINGDOWN_REASON_SERVICE_OUT_OF_SYNC,
260         BRINGDOWN_REASON_IN_DEACTIVATING_STATE,
261         BRINGDOWN_REASON_NETWORK_UPDATE_WHEN_TUNNEL_IN_BRINGUP,
262         BRINGDOWN_REASON_DEACTIVATE_DATA_CALL,
263     })
264     public @interface TunnelBringDownReason {}
265 
bringdownReasonToString(@unnelBringDownReason int reason)266     private static String bringdownReasonToString(@TunnelBringDownReason int reason) {
267         switch (reason) {
268             case BRINGDOWN_REASON_UNKNOWN:
269                 return "BRINGDOWN_REASON_UNKNOWN";
270             case BRINGDOWN_REASON_DISABLE_N1_MODE:
271                 return "BRINGDOWN_REASON_DISABLE_N1_MODE";
272             case BRINGDOWN_REASON_ENABLE_N1_MODE:
273                 return "BRINGDOWN_REASON_ENABLE_N1_MODE";
274             case BRINGDOWN_REASON_SERVICE_OUT_OF_SYNC:
275                 return "BRINGDOWN_REASON_SERVICE_OUT_OF_SYNC";
276             case BRINGDOWN_REASON_IN_DEACTIVATING_STATE:
277                 return "BRINGDOWN_REASON_IN_DEACTIVATING_STATE";
278             case BRINGDOWN_REASON_NETWORK_UPDATE_WHEN_TUNNEL_IN_BRINGUP:
279                 return "BRINGDOWN_REASON_NETWORK_UPDATE_WHEN_TUNNEL_IN_BRINGUP";
280             case BRINGDOWN_REASON_DEACTIVATE_DATA_CALL:
281                 return "BRINGDOWN_REASON_DEACTIVATE_DATA_CALL";
282             default:
283                 return "Unknown(" + reason + ")";
284         }
285     }
286 
287     private final EpdgSelector.EpdgSelectorCallback mSelectorCallback =
288             new EpdgSelector.EpdgSelectorCallback() {
289                 @Override
290                 public void onServerListChanged(int transactionId, List<InetAddress> validIPList) {
291                     sendSelectionRequestComplete(
292                             validIPList, new IwlanError(IwlanError.NO_ERROR), transactionId);
293                 }
294 
295                 @Override
296                 public void onError(int transactionId, IwlanError epdgSelectorError) {
297                     sendSelectionRequestComplete(null, epdgSelectorError, transactionId);
298                 }
299             };
300 
301     @VisibleForTesting
302     class TunnelConfig {
303         @NonNull final TunnelCallback mTunnelCallback;
304         @NonNull final TunnelMetricsInterface mTunnelMetrics;
305         // TODO: Change this to TunnelLinkProperties after removing autovalue
306         private List<InetAddress> mPcscfAddrList;
307         private List<InetAddress> mDnsAddrList;
308         private List<LinkAddress> mInternalAddrList;
309 
310         private final InetAddress mSrcIpv6Address;
311         private final int mSrcIpv6AddressPrefixLen;
312         private NetworkSliceInfo mSliceInfo;
313         private boolean mIsBackoffTimeValid = false;
314         private long mBackoffTime;
315 
316         @NonNull final IkeSession mIkeSession;
317 
318         IwlanError mError;
319         private final IpSecManager.IpSecTunnelInterface mIface;
320         private IkeSessionState mIkeSessionState;
321         private final boolean mIsEmergency;
322         private final InetAddress mEpdgAddress;
323 
TunnelConfig( IkeSession ikeSession, TunnelCallback tunnelCallback, TunnelMetricsInterface tunnelMetrics, IpSecManager.IpSecTunnelInterface iface, InetAddress srcIpv6Addr, int srcIpv6PrefixLength, boolean isEmergency, InetAddress epdgAddress)324         public TunnelConfig(
325                 IkeSession ikeSession,
326                 TunnelCallback tunnelCallback,
327                 TunnelMetricsInterface tunnelMetrics,
328                 IpSecManager.IpSecTunnelInterface iface,
329                 InetAddress srcIpv6Addr,
330                 int srcIpv6PrefixLength,
331                 boolean isEmergency,
332                 InetAddress epdgAddress) {
333             mTunnelCallback = tunnelCallback;
334             mTunnelMetrics = tunnelMetrics;
335             mIkeSession = ikeSession;
336             mError = new IwlanError(IwlanError.NO_ERROR);
337             mSrcIpv6Address = srcIpv6Addr;
338             mSrcIpv6AddressPrefixLen = srcIpv6PrefixLength;
339             mIface = iface;
340             setIkeSessionState(IkeSessionState.IKE_SESSION_INIT_IN_PROGRESS);
341             mIsEmergency = isEmergency;
342             mEpdgAddress = epdgAddress;
343         }
344 
getIkeSessionState()345         public IkeSessionState getIkeSessionState() {
346             return mIkeSessionState;
347         }
348 
setIkeSessionState(IkeSessionState ikeSessionState)349         public void setIkeSessionState(IkeSessionState ikeSessionState) {
350             mIkeSessionState = ikeSessionState;
351         }
352 
getSliceInfo()353         public NetworkSliceInfo getSliceInfo() {
354             return mSliceInfo;
355         }
356 
setSliceInfo(NetworkSliceInfo si)357         public void setSliceInfo(NetworkSliceInfo si) {
358             mSliceInfo = si;
359         }
360 
isBackoffTimeValid()361         public boolean isBackoffTimeValid() {
362             return mIsBackoffTimeValid;
363         }
364 
getBackoffTime()365         public long getBackoffTime() {
366             return mBackoffTime;
367         }
368 
setBackoffTime(long backoffTime)369         public void setBackoffTime(long backoffTime) {
370             mIsBackoffTimeValid = true;
371             mBackoffTime = backoffTime;
372         }
373 
374         @NonNull
getTunnelCallback()375         TunnelCallback getTunnelCallback() {
376             return mTunnelCallback;
377         }
378 
379         @NonNull
getTunnelMetrics()380         TunnelMetricsInterface getTunnelMetrics() {
381             return mTunnelMetrics;
382         }
383 
getPcscfAddrList()384         List<InetAddress> getPcscfAddrList() {
385             return mPcscfAddrList;
386         }
387 
setPcscfAddrList(List<InetAddress> pcscfAddrList)388         void setPcscfAddrList(List<InetAddress> pcscfAddrList) {
389             mPcscfAddrList = pcscfAddrList;
390         }
391 
getDnsAddrList()392         public List<InetAddress> getDnsAddrList() {
393             return mDnsAddrList;
394         }
395 
setDnsAddrList(List<InetAddress> dnsAddrList)396         public void setDnsAddrList(List<InetAddress> dnsAddrList) {
397             this.mDnsAddrList = dnsAddrList;
398         }
399 
getInternalAddrList()400         public List<LinkAddress> getInternalAddrList() {
401             return mInternalAddrList;
402         }
403 
isPrefixSameAsSrcIP(LinkAddress laddr)404         boolean isPrefixSameAsSrcIP(LinkAddress laddr) {
405             if (laddr.isIpv6() && (laddr.getPrefixLength() == mSrcIpv6AddressPrefixLen)) {
406                 IpPrefix assignedPrefix = new IpPrefix(laddr.getAddress(), laddr.getPrefixLength());
407                 IpPrefix srcPrefix = new IpPrefix(mSrcIpv6Address, mSrcIpv6AddressPrefixLen);
408                 return assignedPrefix.equals(srcPrefix);
409             }
410             return false;
411         }
412 
setInternalAddrList(List<LinkAddress> internalAddrList)413         public void setInternalAddrList(List<LinkAddress> internalAddrList) {
414             mInternalAddrList = new ArrayList<LinkAddress>(internalAddrList);
415             if (getSrcIpv6Address() != null) {
416                 // check if we can reuse src ipv6 address (i.e. if prefix is same)
417                 for (LinkAddress assignedAddr : internalAddrList) {
418                     if (isPrefixSameAsSrcIP(assignedAddr)) {
419                         // the assigned IPv6 address is same as pre-Handover IPv6
420                         // addr. Just reuse the pre-Handover Address so the IID is
421                         // preserved
422                         mInternalAddrList.remove(assignedAddr);
423 
424                         // add original address
425                         mInternalAddrList.add(
426                                 new LinkAddress(mSrcIpv6Address, mSrcIpv6AddressPrefixLen));
427 
428                         Log.d(
429                                 TAG,
430                                 "Network assigned IP replaced OLD:"
431                                         + internalAddrList
432                                         + " NEW:"
433                                         + mInternalAddrList);
434                         break;
435                     }
436                 }
437             }
438         }
439 
440         @NonNull
getIkeSession()441         public IkeSession getIkeSession() {
442             return mIkeSession;
443         }
444 
getError()445         public IwlanError getError() {
446             return mError;
447         }
448 
setError(IwlanError error)449         public void setError(IwlanError error) {
450             this.mError = error;
451         }
452 
getIface()453         public IpSecManager.IpSecTunnelInterface getIface() {
454             return mIface;
455         }
456 
getSrcIpv6Address()457         public InetAddress getSrcIpv6Address() {
458             return mSrcIpv6Address;
459         }
460 
isEmergency()461         public boolean isEmergency() {
462             return mIsEmergency;
463         }
464 
getEpdgAddress()465         public InetAddress getEpdgAddress() {
466             return mEpdgAddress;
467         }
468 
hasTunnelOpened()469         public boolean hasTunnelOpened() {
470             return mInternalAddrList != null
471                     && !mInternalAddrList.isEmpty() /* The child session is opened */
472                     && mIface != null; /* The tunnel interface is bring up */
473         }
474 
475         @Override
toString()476         public String toString() {
477             StringBuilder sb = new StringBuilder();
478             sb.append("TunnelConfig { ");
479 
480             if (mSliceInfo != null) {
481                 sb.append("mSliceInfo: ").append(mSliceInfo).append(", ");
482             }
483 
484             if (mIsBackoffTimeValid) {
485                 sb.append("mBackoffTime: ").append(mBackoffTime).append(", ");
486             }
487             sb.append(" }");
488             return sb.toString();
489         }
490     }
491 
492     @VisibleForTesting
493     class TmIkeSessionCallback implements IkeSessionCallback {
494 
495         private final String mApnName;
496         private final int mToken;
497 
TmIkeSessionCallback(String apnName, int token)498         TmIkeSessionCallback(String apnName, int token) {
499             this.mApnName = apnName;
500             this.mToken = token;
501         }
502 
503         @Override
onOpened(IkeSessionConfiguration sessionConfiguration)504         public void onOpened(IkeSessionConfiguration sessionConfiguration) {
505             Log.d(TAG, "Ike session opened for apn: " + mApnName + " with token: " + mToken);
506             mHandler.sendMessage(
507                     mHandler.obtainMessage(
508                             EVENT_IKE_SESSION_OPENED,
509                             new IkeSessionOpenedData(mApnName, mToken, sessionConfiguration)));
510         }
511 
512         @Override
onClosed()513         public void onClosed() {
514             Log.d(TAG, "Ike session closed for apn: " + mApnName + " with token: " + mToken);
515             mHandler.sendMessage(
516                     mHandler.obtainMessage(
517                             EVENT_IKE_SESSION_CLOSED,
518                             new SessionClosedData(mApnName, mToken, null /* ikeException */)));
519         }
520 
521         @Override
onClosedWithException(IkeException exception)522         public void onClosedWithException(IkeException exception) {
523             mNextReauthId = null;
524             onSessionClosedWithException(exception, mApnName, mToken, EVENT_IKE_SESSION_CLOSED);
525         }
526 
527         @Override
onError(IkeProtocolException exception)528         public void onError(IkeProtocolException exception) {
529             Log.d(TAG, "Ike session onError for apn: " + mApnName + " with token: " + mToken);
530 
531             mNextReauthId = null;
532 
533             Log.d(
534                     TAG,
535                     "ErrorType:"
536                             + exception.getErrorType()
537                             + " ErrorData:"
538                             + exception.getMessage());
539         }
540 
541         @Override
onIkeSessionConnectionInfoChanged( IkeSessionConnectionInfo ikeSessionConnectionInfo)542         public void onIkeSessionConnectionInfoChanged(
543                 IkeSessionConnectionInfo ikeSessionConnectionInfo) {
544             Network network = ikeSessionConnectionInfo.getNetwork();
545             Log.d(
546                     TAG,
547                     "Ike session connection info changed for apn: "
548                             + mApnName
549                             + " with token: "
550                             + mToken
551                             + " Network: "
552                             + network);
553             mHandler.sendMessage(
554                     mHandler.obtainMessage(
555                             EVENT_IKE_SESSION_CONNECTION_INFO_CHANGED,
556                             new IkeSessionConnectionInfoData(
557                                     mApnName, mToken, ikeSessionConnectionInfo)));
558         }
559 
560         @Override
onLivenessStatusChanged(int status)561         public void onLivenessStatusChanged(int status) {
562             Log.d(
563                     TAG,
564                     "Ike liveness status changed for apn: " + mApnName + " with status: " + status);
565             @NetworkValidationStatus int validationStatus;
566             switch (status) {
567                 case IkeSessionCallback.LIVENESS_STATUS_ON_DEMAND_STARTED:
568                 case IkeSessionCallback.LIVENESS_STATUS_BACKGROUND_STARTED:
569                 case IkeSessionCallback.LIVENESS_STATUS_ON_DEMAND_ONGOING:
570                 case IkeSessionCallback.LIVENESS_STATUS_BACKGROUND_ONGOING:
571                     validationStatus = PreciseDataConnectionState.NETWORK_VALIDATION_IN_PROGRESS;
572                     break;
573                 case IkeSessionCallback.LIVENESS_STATUS_SUCCESS:
574                     validationStatus = PreciseDataConnectionState.NETWORK_VALIDATION_SUCCESS;
575                     break;
576                 case IkeSessionCallback.LIVENESS_STATUS_FAILURE:
577                     validationStatus = PreciseDataConnectionState.NETWORK_VALIDATION_FAILURE;
578                     break;
579                 default:
580                     validationStatus = PreciseDataConnectionState.NETWORK_VALIDATION_SUCCESS;
581             }
582 
583             mHandler.obtainMessage(
584                             EVENT_IKE_LIVENESS_STATUS_CHANGED,
585                             new IkeSessionValidationStatusData(mApnName, mToken, validationStatus))
586                     .sendToTarget();
587         }
588     }
589 
590     @VisibleForTesting
591     class TmIke3gppCallback implements Ike3gppExtension.Ike3gppDataListener {
592         private final String mApnName;
593         private final int mToken;
594 
TmIke3gppCallback(String apnName, int token)595         private TmIke3gppCallback(String apnName, int token) {
596             mApnName = apnName;
597             mToken = token;
598         }
599 
600         @Override
onIke3gppDataReceived(List<Ike3gppData> payloads)601         public void onIke3gppDataReceived(List<Ike3gppData> payloads) {
602             mHandler.sendMessage(
603                     mHandler.obtainMessage(
604                             EVENT_IKE_3GPP_DATA_RECEIVED,
605                             new Ike3gppDataReceived(mApnName, mToken, payloads)));
606         }
607     }
608 
609     @VisibleForTesting
610     class TmChildSessionCallback implements ChildSessionCallback {
611 
612         private final String mApnName;
613         private final int mToken;
614 
TmChildSessionCallback(String apnName, int token)615         TmChildSessionCallback(String apnName, int token) {
616             this.mApnName = apnName;
617             this.mToken = token;
618         }
619 
620         @Override
onOpened(ChildSessionConfiguration sessionConfiguration)621         public void onOpened(ChildSessionConfiguration sessionConfiguration) {
622             Log.d(TAG, "onOpened child session for apn: " + mApnName + " with token: " + mToken);
623             mHandler.sendMessage(
624                     mHandler.obtainMessage(
625                             EVENT_CHILD_SESSION_OPENED,
626                             new TunnelOpenedData(
627                                     mApnName,
628                                     mToken,
629                                     sessionConfiguration.getInternalDnsServers(),
630                                     sessionConfiguration.getInternalAddresses())));
631         }
632 
633         @Override
onClosed()634         public void onClosed() {
635             Log.d(TAG, "onClosed child session for apn: " + mApnName + " with token: " + mToken);
636             mHandler.sendMessage(
637                     mHandler.obtainMessage(
638                             EVENT_CHILD_SESSION_CLOSED,
639                             new SessionClosedData(mApnName, mToken, null /* ikeException */)));
640         }
641 
642         @Override
onClosedWithException(IkeException exception)643         public void onClosedWithException(IkeException exception) {
644             onSessionClosedWithException(exception, mApnName, mToken, EVENT_CHILD_SESSION_CLOSED);
645         }
646 
647         @Override
onIpSecTransformsMigrated( IpSecTransform inIpSecTransform, IpSecTransform outIpSecTransform)648         public void onIpSecTransformsMigrated(
649                 IpSecTransform inIpSecTransform, IpSecTransform outIpSecTransform) {
650             // migration is similar to addition
651             Log.d(TAG, "Transforms migrated for apn: " + mApnName + " with token: " + mToken);
652             mHandler.sendMessage(
653                     mHandler.obtainMessage(
654                             EVENT_IPSEC_TRANSFORM_CREATED,
655                             new IpsecTransformData(
656                                     inIpSecTransform,
657                                     IpSecManager.DIRECTION_IN,
658                                     mApnName,
659                                     mToken)));
660             mHandler.sendMessage(
661                     mHandler.obtainMessage(
662                             EVENT_IPSEC_TRANSFORM_CREATED,
663                             new IpsecTransformData(
664                                     outIpSecTransform,
665                                     IpSecManager.DIRECTION_OUT,
666                                     mApnName,
667                                     mToken)));
668         }
669 
670         @Override
onIpSecTransformCreated(IpSecTransform ipSecTransform, int direction)671         public void onIpSecTransformCreated(IpSecTransform ipSecTransform, int direction) {
672             Log.d(
673                     TAG,
674                     "Transform created, direction: "
675                             + direction
676                             + ", apn: "
677                             + mApnName
678                             + ", token: "
679                             + mToken);
680             mHandler.sendMessage(
681                     mHandler.obtainMessage(
682                             EVENT_IPSEC_TRANSFORM_CREATED,
683                             new IpsecTransformData(ipSecTransform, direction, mApnName, mToken)));
684         }
685 
686         @Override
onIpSecTransformDeleted(IpSecTransform ipSecTransform, int direction)687         public void onIpSecTransformDeleted(IpSecTransform ipSecTransform, int direction) {
688             Log.d(
689                     TAG,
690                     "Transform deleted, direction: "
691                             + direction
692                             + ", apn: "
693                             + mApnName
694                             + ", token: "
695                             + mToken);
696             mHandler.sendMessage(
697                     mHandler.obtainMessage(
698                             EVENT_IPSEC_TRANSFORM_DELETED,
699                             new IpsecTransformData(ipSecTransform, direction, mApnName, mToken)));
700         }
701     }
702 
703     @VisibleForTesting
EpdgTunnelManager(Context context, int slotId, FeatureFlags featureFlags)704     EpdgTunnelManager(Context context, int slotId, FeatureFlags featureFlags) {
705         mContext = context;
706         mSlotId = slotId;
707         mFeatureFlags = featureFlags;
708         mIkeSessionCreator = new IkeSessionCreator();
709         mIpSecManager = mContext.getSystemService(IpSecManager.class);
710         TAG = EpdgTunnelManager.class.getSimpleName() + "[" + mSlotId + "]";
711         initHandler();
712     }
713 
714     @VisibleForTesting
initHandler()715     void initHandler() {
716         mHandler = new TmHandler(getLooper());
717     }
718 
719     @VisibleForTesting
getLooper()720     Looper getLooper() {
721         HandlerThread handlerThread = new HandlerThread("EpdgTunnelManagerThread");
722         handlerThread.start();
723         return handlerThread.getLooper();
724     }
725 
726     /**
727      * Gets a EpdgTunnelManager instance.
728      *
729      * @param context application context
730      * @param subId subscription ID for the tunnel
731      * @return tunnel manager instance corresponding to the sub id
732      */
getInstance(@onNull Context context, int subId)733     public static EpdgTunnelManager getInstance(@NonNull Context context, int subId) {
734         return mTunnelManagerInstances.computeIfAbsent(
735                 subId, k -> new EpdgTunnelManager(context, subId, new FeatureFlagsImpl()));
736     }
737 
738     @VisibleForTesting
resetAllInstances()739     public static void resetAllInstances() {
740         mTunnelManagerInstances.clear();
741     }
742 
743     public interface TunnelCallback {
744         /**
745          * Called when the tunnel is opened.
746          *
747          * @param apnName apn for which the tunnel was opened
748          * @param linkProperties link properties of the tunnel
749          */
onOpened(@onNull String apnName, @NonNull TunnelLinkProperties linkProperties)750         void onOpened(@NonNull String apnName, @NonNull TunnelLinkProperties linkProperties);
751 
752         /**
753          * Called when the tunnel is closed OR if bringup fails
754          *
755          * @param apnName apn for which the tunnel was closed
756          * @param error IwlanError carrying details of the error
757          */
onClosed(@onNull String apnName, @NonNull IwlanError error)758         void onClosed(@NonNull String apnName, @NonNull IwlanError error);
759 
760         /**
761          * Called when updates upon network validation status change.
762          *
763          * @param apnName APN affected.
764          * @param status The updated validation status of the network.
765          */
onNetworkValidationStatusChanged( @onNull String apnName, @NetworkValidationStatus int status)766         void onNetworkValidationStatusChanged(
767                 @NonNull String apnName, @NetworkValidationStatus int status);
768     }
769 
770     /**
771      * Close tunnel for an apn. Confirmation of closing will be delivered in TunnelCallback that was
772      * provided in {@link #bringUpTunnel}. If no tunnel was available, callback will be delivered
773      * using client-provided provided tunnelCallback and iwlanTunnelMetrics
774      *
775      * @param apnName APN name
776      * @param forceClose if {@code true}, triggers a local cleanup of the tunnel; if {@code false},
777      *     performs a normal closure procedure
778      * @param tunnelCallback The tunnelCallback for tunnel to be closed
779      * @param iwlanTunnelMetrics The metrics to be reported
780      * @param reason The reason for tunnel to be closed
781      */
closeTunnel( @onNull String apnName, boolean forceClose, @NonNull TunnelCallback tunnelCallback, @NonNull IwlanTunnelMetricsImpl iwlanTunnelMetrics, @TunnelBringDownReason int reason)782     public void closeTunnel(
783             @NonNull String apnName,
784             boolean forceClose,
785             @NonNull TunnelCallback tunnelCallback,
786             @NonNull IwlanTunnelMetricsImpl iwlanTunnelMetrics,
787             @TunnelBringDownReason int reason) {
788         mHandler.sendMessage(
789                 mHandler.obtainMessage(
790                         EVENT_TUNNEL_BRINGDOWN_REQUEST,
791                         new TunnelBringdownRequest(
792                                 apnName, forceClose, tunnelCallback, iwlanTunnelMetrics, reason)));
793     }
794 
795     /**
796      * Update the local Network. This will trigger a revaluation for every tunnel for which tunnel
797      * manager has state.
798      *
799      * @param network the network to be updated
800      * @param network the linkProperties to be updated
801      */
updateNetwork(Network network, LinkProperties linkProperties)802     public void updateNetwork(Network network, LinkProperties linkProperties) {
803         UpdateNetworkWrapper updateNetworkWrapper =
804                 new UpdateNetworkWrapper(network, linkProperties);
805         mHandler.sendMessage(mHandler.obtainMessage(EVENT_UPDATE_NETWORK, updateNetworkWrapper));
806     }
807 
808     /**
809      * Bring up epdg tunnel. Only one bring up request per apn is expected. All active tunnel
810      * requests and tunnels are expected to be on the same network.
811      *
812      * @param setupRequest {@link TunnelSetupRequest} tunnel configurations
813      * @param tunnelCallback {@link TunnelCallback} interface to notify clients about the tunnel
814      *     state
815      * @return true if params are valid and no existing tunnel. False otherwise.
816      */
bringUpTunnel( @onNull TunnelSetupRequest setupRequest, @NonNull TunnelCallback tunnelCallback, @NonNull TunnelMetricsInterface tunnelMetrics)817     public boolean bringUpTunnel(
818             @NonNull TunnelSetupRequest setupRequest,
819             @NonNull TunnelCallback tunnelCallback,
820             @NonNull TunnelMetricsInterface tunnelMetrics) {
821         String apnName = setupRequest.apnName();
822 
823         if (getTunnelSetupRequestApnName(setupRequest) == null) {
824             Log.e(TAG, "APN is null.");
825             return false;
826         }
827 
828         if (isTunnelConfigContainExistApn(apnName)) {
829             Log.e(TAG, "Tunnel exists for apn:" + apnName);
830             return false;
831         }
832 
833         if (!isValidApnProtocol(setupRequest.apnIpProtocol())) {
834             Log.e(TAG, "Invalid protocol for APN");
835             return false;
836         }
837 
838         int pduSessionId = setupRequest.pduSessionId();
839         if (pduSessionId < 0 || pduSessionId > 15) {
840             Log.e(TAG, "Invalid pduSessionId: " + pduSessionId);
841             return false;
842         }
843 
844         TunnelRequestWrapper tunnelRequestWrapper =
845                 new TunnelRequestWrapper(setupRequest, tunnelCallback, tunnelMetrics);
846 
847         mHandler.sendMessage(
848                 mHandler.obtainMessage(EVENT_TUNNEL_BRINGUP_REQUEST, tunnelRequestWrapper));
849 
850         return true;
851     }
852 
tryBuildIkeSessionParams( TunnelSetupRequest setupRequest, String apnName, int token, InetAddress epdgAddress)853     private IkeSessionParams tryBuildIkeSessionParams(
854             TunnelSetupRequest setupRequest, String apnName, int token, InetAddress epdgAddress) {
855         try {
856             return buildIkeSessionParams(setupRequest, apnName, token, epdgAddress);
857         } catch (IwlanSimNotReadyException e) {
858             return null;
859         }
860     }
861 
tryCreateIpSecTunnelInterface()862     private IpSecManager.IpSecTunnelInterface tryCreateIpSecTunnelInterface() {
863         try {
864             return mIpSecManager.createIpSecTunnelInterface(
865                     DUMMY_ADDR /* unused */, DUMMY_ADDR /* unused */, mDefaultNetwork);
866         } catch (IpSecManager.ResourceUnavailableException | IOException e) {
867             Log.e(TAG, "Failed to create tunnel interface. " + e);
868             return null;
869         }
870     }
871 
onBringUpTunnel( TunnelRequestWrapper tunnelRequestWrapper, InetAddress epdgAddress)872     private void onBringUpTunnel(
873             TunnelRequestWrapper tunnelRequestWrapper, InetAddress epdgAddress) {
874         TunnelSetupRequest setupRequest = tunnelRequestWrapper.getSetupRequest();
875         TunnelCallback tunnelCallback = tunnelRequestWrapper.getTunnelCallback();
876         TunnelMetricsInterface tunnelMetrics = tunnelRequestWrapper.getTunnelMetrics();
877         String apnName = setupRequest.apnName();
878         IkeSessionParams ikeSessionParams;
879         IpSecManager.IpSecTunnelInterface iface;
880 
881         Log.d(
882                 TAG,
883                 "Bringing up tunnel for apn: "
884                         + apnName
885                         + " ePDG: "
886                         + epdgAddress.getHostAddress());
887 
888         final int token = incrementAndGetCurrentTokenForApn(apnName);
889 
890         ikeSessionParams = tryBuildIkeSessionParams(setupRequest, apnName, token, epdgAddress);
891         if (Objects.isNull(ikeSessionParams)) {
892             IwlanError iwlanError = new IwlanError(IwlanError.SIM_NOT_READY_EXCEPTION);
893             reportIwlanError(apnName, iwlanError);
894             tunnelCallback.onClosed(apnName, iwlanError);
895             tunnelMetrics.onClosed(new OnClosedMetrics.Builder().setApnName(apnName).build());
896             return;
897         }
898 
899         iface = tryCreateIpSecTunnelInterface();
900         if (Objects.isNull(iface)) {
901             IwlanError iwlanError = new IwlanError(IwlanError.TUNNEL_TRANSFORM_FAILED);
902             reportIwlanError(apnName, iwlanError);
903             tunnelCallback.onClosed(apnName, iwlanError);
904             tunnelMetrics.onClosed(new OnClosedMetrics.Builder().setApnName(apnName).build());
905             return;
906         }
907 
908         mIkeTunnelEstablishmentStartTime = System.currentTimeMillis();
909         IkeSession ikeSession =
910                 getIkeSessionCreator()
911                         .createIkeSession(
912                                 mContext,
913                                 ikeSessionParams,
914                                 buildChildSessionParams(setupRequest),
915                                 Executors.newSingleThreadExecutor(),
916                                 getTmIkeSessionCallback(apnName, token),
917                                 new TmChildSessionCallback(apnName, token));
918 
919         boolean isSrcIpv6Present = setupRequest.srcIpv6Address().isPresent();
920         putApnNameToTunnelConfig(
921                 apnName,
922                 ikeSession,
923                 tunnelCallback,
924                 tunnelMetrics,
925                 iface,
926                 isSrcIpv6Present ? setupRequest.srcIpv6Address().get() : null,
927                 setupRequest.srcIpv6AddressPrefixLength(),
928                 setupRequest.isEmergency(),
929                 epdgAddress);
930     }
931 
932     /**
933      * Proxy to allow testing
934      *
935      * @hide
936      */
937     @VisibleForTesting
938     static class IkeSessionCreator {
939         /** Creates a IKE session */
createIkeSession( @onNull Context context, @NonNull IkeSessionParams ikeSessionParams, @NonNull ChildSessionParams firstChildSessionParams, @NonNull Executor userCbExecutor, @NonNull IkeSessionCallback ikeSessionCallback, @NonNull ChildSessionCallback firstChildSessionCallback)940         public IkeSession createIkeSession(
941                 @NonNull Context context,
942                 @NonNull IkeSessionParams ikeSessionParams,
943                 @NonNull ChildSessionParams firstChildSessionParams,
944                 @NonNull Executor userCbExecutor,
945                 @NonNull IkeSessionCallback ikeSessionCallback,
946                 @NonNull ChildSessionCallback firstChildSessionCallback) {
947             return new IkeSession(
948                     context,
949                     ikeSessionParams,
950                     firstChildSessionParams,
951                     userCbExecutor,
952                     ikeSessionCallback,
953                     firstChildSessionCallback);
954         }
955     }
956 
buildChildSessionParams(TunnelSetupRequest setupRequest)957     private ChildSessionParams buildChildSessionParams(TunnelSetupRequest setupRequest) {
958         int proto = setupRequest.apnIpProtocol();
959         int hardTimeSeconds =
960                 IwlanCarrierConfig.getConfigInt(
961                         mContext,
962                         mSlotId,
963                         CarrierConfigManager.Iwlan.KEY_CHILD_SA_REKEY_HARD_TIMER_SEC_INT);
964         int softTimeSeconds =
965                 IwlanCarrierConfig.getConfigInt(
966                         mContext,
967                         mSlotId,
968                         CarrierConfigManager.Iwlan.KEY_CHILD_SA_REKEY_SOFT_TIMER_SEC_INT);
969         if (!isValidChildSessionLifetime(hardTimeSeconds, softTimeSeconds)) {
970             if (hardTimeSeconds > CHILD_HARD_LIFETIME_SEC_MAXIMUM
971                     && softTimeSeconds > CHILD_SOFT_LIFETIME_SEC_MINIMUM) {
972                 hardTimeSeconds = CHILD_HARD_LIFETIME_SEC_MAXIMUM;
973                 softTimeSeconds = CHILD_HARD_LIFETIME_SEC_MAXIMUM - LIFETIME_MARGIN_SEC_MINIMUM;
974             } else {
975                 hardTimeSeconds =
976                         IwlanCarrierConfig.getDefaultConfigInt(
977                                 CarrierConfigManager.Iwlan.KEY_CHILD_SA_REKEY_HARD_TIMER_SEC_INT);
978                 softTimeSeconds =
979                         IwlanCarrierConfig.getDefaultConfigInt(
980                                 CarrierConfigManager.Iwlan.KEY_CHILD_SA_REKEY_SOFT_TIMER_SEC_INT);
981             }
982             Log.d(
983                     TAG,
984                     "Invalid child session lifetime values, set hard: "
985                             + hardTimeSeconds
986                             + ", soft: "
987                             + softTimeSeconds);
988         }
989 
990         TunnelModeChildSessionParams.Builder childSessionParamsBuilder =
991                 new TunnelModeChildSessionParams.Builder()
992                         .setLifetimeSeconds(hardTimeSeconds, softTimeSeconds);
993 
994         // Else block and it's related functionality can be removed once
995         // multipleSaProposals, highSecureTransformsPrioritized and aeadAlgosEnabled feature flags
996         // related functionality becomes stable and gets instruction to remove feature flags.
997         if (mFeatureFlags.multipleSaProposals()
998                 || mFeatureFlags.highSecureTransformsPrioritized()) {
999             EpdgChildSaProposal epdgChildSaProposal = createEpdgChildSaProposal();
1000 
1001             if (IwlanCarrierConfig.getConfigBoolean(
1002                     mContext,
1003                     mSlotId,
1004                     CarrierConfigManager.Iwlan.KEY_ADD_KE_TO_CHILD_SESSION_REKEY_BOOL)) {
1005                 epdgChildSaProposal.enableAddChildSessionRekeyKePayload();
1006             }
1007             // Adds single SA proposal, priority is for AEAD if configured else non-AEAD proposal.
1008             if (isChildSessionAeadAlgosAvailable()) {
1009                 childSessionParamsBuilder.addChildSaProposal(
1010                         epdgChildSaProposal.buildProposedChildSaAeadProposal());
1011             } else {
1012                 childSessionParamsBuilder.addChildSaProposal(
1013                         epdgChildSaProposal.buildProposedChildSaProposal());
1014             }
1015             // Adds multiple proposals. If AEAD proposal already added then adds
1016             // configured non-AEAD proposal followed by supported AEAD and non-AEAD proposals.
1017             if (IwlanCarrierConfig.getConfigBoolean(
1018                     mContext,
1019                     mSlotId,
1020                     CarrierConfigManager.Iwlan
1021                             .KEY_SUPPORTS_CHILD_SESSION_MULTIPLE_SA_PROPOSALS_BOOL)) {
1022                 if (isChildSessionAeadAlgosAvailable() && isChildSessionNonAeadAlgosAvailable()) {
1023                     childSessionParamsBuilder.addChildSaProposal(
1024                             epdgChildSaProposal.buildProposedChildSaProposal());
1025                 }
1026                 childSessionParamsBuilder.addChildSaProposal(
1027                         epdgChildSaProposal.buildSupportedChildSaAeadProposal());
1028                 childSessionParamsBuilder.addChildSaProposal(
1029                         epdgChildSaProposal.buildSupportedChildSaProposal());
1030             }
1031         } else {
1032             if (isChildSessionAeadAlgosAvailable()) {
1033                 childSessionParamsBuilder.addChildSaProposal(buildAeadChildSaProposal());
1034             } else {
1035                 childSessionParamsBuilder.addChildSaProposal(buildChildSaProposal());
1036             }
1037         }
1038 
1039         boolean handoverIPv4Present = setupRequest.srcIpv4Address().isPresent();
1040         boolean handoverIPv6Present = setupRequest.srcIpv6Address().isPresent();
1041         if (handoverIPv4Present || handoverIPv6Present) {
1042             if (handoverIPv4Present) {
1043                 childSessionParamsBuilder.addInternalAddressRequest(
1044                         (Inet4Address) setupRequest.srcIpv4Address().get());
1045                 childSessionParamsBuilder.addInternalDnsServerRequest(AF_INET);
1046                 childSessionParamsBuilder.addInboundTrafficSelectors(
1047                         getDefaultTrafficSelectorIpv4());
1048                 childSessionParamsBuilder.addOutboundTrafficSelectors(
1049                         getDefaultTrafficSelectorIpv4());
1050             }
1051             if (handoverIPv6Present) {
1052                 childSessionParamsBuilder.addInternalAddressRequest(
1053                         (Inet6Address) setupRequest.srcIpv6Address().get(),
1054                         setupRequest.srcIpv6AddressPrefixLength());
1055                 childSessionParamsBuilder.addInternalDnsServerRequest(AF_INET6);
1056                 childSessionParamsBuilder.addInboundTrafficSelectors(
1057                         getDefaultTrafficSelectorIpv6());
1058                 childSessionParamsBuilder.addOutboundTrafficSelectors(
1059                         getDefaultTrafficSelectorIpv6());
1060             }
1061         } else {
1062             // non-handover case
1063             if (proto == ApnSetting.PROTOCOL_IP || proto == ApnSetting.PROTOCOL_IPV4V6) {
1064                 childSessionParamsBuilder.addInternalAddressRequest(AF_INET);
1065                 childSessionParamsBuilder.addInternalDnsServerRequest(AF_INET);
1066                 childSessionParamsBuilder.addInboundTrafficSelectors(
1067                         getDefaultTrafficSelectorIpv4());
1068                 childSessionParamsBuilder.addOutboundTrafficSelectors(
1069                         getDefaultTrafficSelectorIpv4());
1070             }
1071             if (proto == ApnSetting.PROTOCOL_IPV6 || proto == ApnSetting.PROTOCOL_IPV4V6) {
1072                 childSessionParamsBuilder.addInternalAddressRequest(AF_INET6);
1073                 childSessionParamsBuilder.addInternalDnsServerRequest(AF_INET6);
1074                 childSessionParamsBuilder.addInboundTrafficSelectors(
1075                         getDefaultTrafficSelectorIpv6());
1076                 childSessionParamsBuilder.addOutboundTrafficSelectors(
1077                         getDefaultTrafficSelectorIpv6());
1078             }
1079         }
1080 
1081         return childSessionParamsBuilder.build();
1082     }
1083 
getDefaultTrafficSelectorIpv4()1084     private static IkeTrafficSelector getDefaultTrafficSelectorIpv4() {
1085         return new IkeTrafficSelector(
1086                 TRAFFIC_SELECTOR_START_PORT,
1087                 TRAFFIC_SELECTOR_END_PORT,
1088                 InetAddresses.parseNumericAddress(TRAFFIC_SELECTOR_IPV4_START_ADDR),
1089                 InetAddresses.parseNumericAddress(TRAFFIC_SELECTOR_IPV4_END_ADDR));
1090     }
1091 
getDefaultTrafficSelectorIpv6()1092     private static IkeTrafficSelector getDefaultTrafficSelectorIpv6() {
1093         return new IkeTrafficSelector(
1094                 TRAFFIC_SELECTOR_START_PORT,
1095                 TRAFFIC_SELECTOR_END_PORT,
1096                 InetAddresses.parseNumericAddress(TRAFFIC_SELECTOR_IPV6_START_ADDR),
1097                 InetAddresses.parseNumericAddress(TRAFFIC_SELECTOR_IPV6_END_ADDR));
1098     }
1099 
needIncludeInitialContact(InetAddress epdgAddress)1100     private boolean needIncludeInitialContact(InetAddress epdgAddress) {
1101         return !mEpdgMonitor.isConnectedEpdg(epdgAddress);
1102     }
1103 
1104     // Returns the IMEISV or device IMEI, in that order of priority.
getMobileDeviceIdentity()1105     private @Nullable String getMobileDeviceIdentity() {
1106         TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class);
1107         telephonyManager =
1108                 Objects.requireNonNull(telephonyManager)
1109                         .createForSubscriptionId(IwlanHelper.getSubId(mContext, mSlotId));
1110         if (telephonyManager == null) {
1111             return null;
1112         }
1113         // Queries the 15-digit device IMEI.
1114         String imei = telephonyManager.getImei();
1115         if (imei == null || imei.length() != DEVICE_IMEI_LEN) {
1116             Log.i(TAG, "Unable to query valid Mobile Device Identity (IMEI)!");
1117             return null;
1118         }
1119         String imeisv_suffix = telephonyManager.getDeviceSoftwareVersion();
1120         if (imeisv_suffix == null || imeisv_suffix.length() != DEVICE_IMEISV_SUFFIX_LEN) {
1121             // Unable to retrieve 2-digit suffix for IMEISV, so returns device IMEI.
1122             return imei;
1123         }
1124         // Splices the first 14 digit of device IMEI with 2-digit SV suffix to form IMEISV.
1125         return imei.substring(0, imei.length() - 1) + imeisv_suffix;
1126     }
1127 
buildIkeSessionParams( TunnelSetupRequest setupRequest, String apnName, int token, InetAddress epdgAddress)1128     private IkeSessionParams buildIkeSessionParams(
1129             TunnelSetupRequest setupRequest, String apnName, int token, InetAddress epdgAddress)
1130             throws IwlanSimNotReadyException {
1131         int hardTimeSeconds =
1132                 IwlanCarrierConfig.getConfigInt(
1133                         mContext,
1134                         mSlotId,
1135                         CarrierConfigManager.Iwlan.KEY_IKE_REKEY_HARD_TIMER_SEC_INT);
1136         int softTimeSeconds =
1137                 IwlanCarrierConfig.getConfigInt(
1138                         mContext,
1139                         mSlotId,
1140                         CarrierConfigManager.Iwlan.KEY_IKE_REKEY_SOFT_TIMER_SEC_INT);
1141         if (!isValidIkeSessionLifetime(hardTimeSeconds, softTimeSeconds)) {
1142             if (hardTimeSeconds > IKE_HARD_LIFETIME_SEC_MAXIMUM
1143                     && softTimeSeconds > IKE_SOFT_LIFETIME_SEC_MINIMUM) {
1144                 hardTimeSeconds = IKE_HARD_LIFETIME_SEC_MAXIMUM;
1145                 softTimeSeconds = IKE_HARD_LIFETIME_SEC_MAXIMUM - LIFETIME_MARGIN_SEC_MINIMUM;
1146             } else {
1147                 hardTimeSeconds =
1148                         IwlanCarrierConfig.getDefaultConfigInt(
1149                                 CarrierConfigManager.Iwlan.KEY_IKE_REKEY_HARD_TIMER_SEC_INT);
1150                 softTimeSeconds =
1151                         IwlanCarrierConfig.getDefaultConfigInt(
1152                                 CarrierConfigManager.Iwlan.KEY_IKE_REKEY_SOFT_TIMER_SEC_INT);
1153             }
1154             Log.d(
1155                     TAG,
1156                     "Invalid ike session lifetime values, set hard: "
1157                             + hardTimeSeconds
1158                             + ", soft: "
1159                             + softTimeSeconds);
1160         }
1161 
1162         IkeSessionParams.Builder builder =
1163                 new IkeSessionParams.Builder()
1164                         // permanently hardcode DSCP to 46 (Expedited Forwarding class)
1165                         // See https://www.iana.org/assignments/dscp-registry/dscp-registry.xhtml
1166                         // This will make WiFi prioritize IKE signallig under WMM AC_VO
1167                         .setDscp(46)
1168                         .setServerHostname(epdgAddress.getHostAddress())
1169                         .setLocalIdentification(getLocalIdentification())
1170                         .setRemoteIdentification(getId(setupRequest.apnName(), false))
1171                         .setAuthEap(null, getEapConfig())
1172                         .setNetwork(mDefaultNetwork)
1173                         .addIkeOption(IkeSessionParams.IKE_OPTION_ACCEPT_ANY_REMOTE_ID)
1174                         .addIkeOption(IkeSessionParams.IKE_OPTION_MOBIKE)
1175                         .addIkeOption(IkeSessionParams.IKE_OPTION_REKEY_MOBILITY)
1176                         .setLifetimeSeconds(hardTimeSeconds, softTimeSeconds)
1177                         .setRetransmissionTimeoutsMillis(getRetransmissionTimeoutsFromConfig())
1178                         .setDpdDelaySeconds(getDpdDelayFromConfig());
1179 
1180         // Else block and it's related functionality can be removed once
1181         // multipleSaProposals, highSecureTransformsPrioritized and aeadAlgosEnabled feature flags
1182         // related functionality becomes stable and gets instruction to remove feature flags.
1183         if (mFeatureFlags.multipleSaProposals()
1184                 || mFeatureFlags.highSecureTransformsPrioritized()) {
1185             EpdgIkeSaProposal epdgIkeSaProposal = createEpdgIkeSaProposal();
1186 
1187             // Adds single SA proposal, priority is for AEAD if configured else non-AEAD proposal.
1188             if (isIkeSessionAeadAlgosAvailable()) {
1189                 builder.addIkeSaProposal(epdgIkeSaProposal.buildProposedIkeSaAeadProposal());
1190             } else {
1191                 builder.addIkeSaProposal(epdgIkeSaProposal.buildProposedIkeSaProposal());
1192             }
1193             // Adds multiple proposals. If AEAD proposal already added then adds
1194             // configured non-AEAD proposal followed by supported AEAD and non-AEAD proposals.
1195             if (IwlanCarrierConfig.getConfigBoolean(
1196                     mContext,
1197                     mSlotId,
1198                     CarrierConfigManager.Iwlan
1199                             .KEY_SUPPORTS_IKE_SESSION_MULTIPLE_SA_PROPOSALS_BOOL)) {
1200                 if (isIkeSessionAeadAlgosAvailable() && isIkeSessionNonAeadAlgosAvailable()) {
1201                     builder.addIkeSaProposal(epdgIkeSaProposal.buildProposedIkeSaProposal());
1202                 }
1203                 builder.addIkeSaProposal(epdgIkeSaProposal.buildSupportedIkeSaAeadProposal());
1204                 builder.addIkeSaProposal(epdgIkeSaProposal.buildSupportedIkeSaProposal());
1205             }
1206         } else {
1207             if (isIkeSessionAeadAlgosAvailable()) {
1208                 builder.addIkeSaProposal(buildIkeSaAeadProposal());
1209             } else {
1210                 builder.addIkeSaProposal(buildIkeSaProposal());
1211             }
1212         }
1213 
1214         if (needIncludeInitialContact(epdgAddress)) {
1215             builder.addIkeOption(IkeSessionParams.IKE_OPTION_INITIAL_CONTACT);
1216             Log.d(TAG, "IKE_OPTION_INITIAL_CONTACT");
1217         }
1218 
1219         if (IwlanCarrierConfig.getConfigInt(
1220                         mContext,
1221                         mSlotId,
1222                         CarrierConfigManager.Iwlan.KEY_EPDG_AUTHENTICATION_METHOD_INT)
1223                 == CarrierConfigManager.Iwlan.AUTHENTICATION_METHOD_EAP_ONLY) {
1224             builder.addIkeOption(IkeSessionParams.IKE_OPTION_EAP_ONLY_AUTH);
1225         }
1226 
1227         if (setupRequest.requestPcscf()) {
1228             int proto = setupRequest.apnIpProtocol();
1229             if (proto == ApnSetting.PROTOCOL_IP || proto == ApnSetting.PROTOCOL_IPV4V6) {
1230                 builder.addPcscfServerRequest(AF_INET);
1231             }
1232             if (proto == ApnSetting.PROTOCOL_IPV6 || proto == ApnSetting.PROTOCOL_IPV4V6) {
1233                 builder.addPcscfServerRequest(AF_INET6);
1234             }
1235         }
1236 
1237         // If MOBIKE is configured, ePDGs may force IPv6 UDP encapsulation- as specified by
1238         // RFC 4555- which Android connectivity stack presently does not support.
1239         if (epdgAddress instanceof Inet6Address) {
1240             builder.removeIkeOption(IkeSessionParams.IKE_OPTION_MOBIKE);
1241         }
1242 
1243         builder.setIke3gppExtension(buildIke3gppExtension(setupRequest, apnName, token));
1244 
1245         int nattKeepAliveTimer =
1246                 IwlanCarrierConfig.getConfigInt(
1247                         mContext,
1248                         mSlotId,
1249                         CarrierConfigManager.Iwlan.KEY_NATT_KEEP_ALIVE_TIMER_SEC_INT);
1250         if (nattKeepAliveTimer < NATT_KEEPALIVE_DELAY_SEC_MIN
1251                 || nattKeepAliveTimer > NATT_KEEPALIVE_DELAY_SEC_MAX) {
1252             Log.d(TAG, "Falling back to default natt keep alive timer" + nattKeepAliveTimer);
1253             nattKeepAliveTimer =
1254                     IwlanCarrierConfig.getDefaultConfigInt(
1255                             CarrierConfigManager.Iwlan.KEY_NATT_KEEP_ALIVE_TIMER_SEC_INT);
1256         }
1257         builder.setNattKeepAliveDelaySeconds(nattKeepAliveTimer);
1258 
1259         return builder.build();
1260     }
1261 
buildIke3gppExtension( TunnelSetupRequest setupRequest, String apnName, int token)1262     private Ike3gppExtension buildIke3gppExtension(
1263             TunnelSetupRequest setupRequest, String apnName, int token) {
1264         Ike3gppParams.Builder builder3gppParams = new Ike3gppParams.Builder();
1265 
1266         if (IwlanCarrierConfig.getConfigBoolean(
1267                 mContext, mSlotId, IwlanCarrierConfig.KEY_IKE_DEVICE_IDENTITY_SUPPORTED_BOOL)) {
1268             String imei = getMobileDeviceIdentity();
1269             if (imei != null) {
1270                 Log.d(TAG, "DEVICE_IDENTITY set in Ike3gppParams");
1271                 builder3gppParams.setMobileDeviceIdentity(imei);
1272             }
1273         }
1274 
1275         if (setupRequest.pduSessionId() != PDU_SESSION_ID_UNSET) {
1276             // Includes N1_MODE_CAPABILITY NOTIFY payload in IKE_AUTH exchange when PDU session ID
1277             // is set; otherwise, do not include.
1278             builder3gppParams.setPduSessionId((byte) setupRequest.pduSessionId());
1279         }
1280 
1281         return new Ike3gppExtension(
1282                 builder3gppParams.build(), new TmIke3gppCallback(apnName, token));
1283     }
1284 
isChildSessionAeadAlgosAvailable()1285     private boolean isChildSessionAeadAlgosAvailable() {
1286         if (!mFeatureFlags.aeadAlgosEnabled()) {
1287             return false;
1288         }
1289 
1290         int[] encryptionAlgos =
1291                 IwlanCarrierConfig.getConfigIntArray(
1292                         mContext,
1293                         mSlotId,
1294                         CarrierConfigManager.Iwlan
1295                                 .KEY_SUPPORTED_CHILD_SESSION_AEAD_ALGORITHMS_INT_ARRAY);
1296         for (int encryptionAlgo : encryptionAlgos) {
1297             if (validateConfig(encryptionAlgo, VALID_AEAD_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO)) {
1298                 return true;
1299             }
1300         }
1301         return false;
1302     }
1303 
isChildSessionNonAeadAlgosAvailable()1304     private boolean isChildSessionNonAeadAlgosAvailable() {
1305         int[] encryptionAlgos =
1306                 IwlanCarrierConfig.getConfigIntArray(
1307                         mContext,
1308                         mSlotId,
1309                         CarrierConfigManager.Iwlan
1310                                 .KEY_SUPPORTED_CHILD_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY);
1311         for (int encryptionAlgo : encryptionAlgos) {
1312             if (validateConfig(encryptionAlgo, VALID_ENCRYPTION_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO)) {
1313                 return true;
1314             }
1315         }
1316         return false;
1317     }
1318 
isIkeSessionAeadAlgosAvailable()1319     private boolean isIkeSessionAeadAlgosAvailable() {
1320         if (!mFeatureFlags.aeadAlgosEnabled()) {
1321             return false;
1322         }
1323 
1324         int[] encryptionAlgos =
1325                 IwlanCarrierConfig.getConfigIntArray(
1326                         mContext,
1327                         mSlotId,
1328                         CarrierConfigManager.Iwlan
1329                                 .KEY_SUPPORTED_IKE_SESSION_AEAD_ALGORITHMS_INT_ARRAY);
1330         for (int encryptionAlgo : encryptionAlgos) {
1331             if (validateConfig(encryptionAlgo, VALID_AEAD_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO)) {
1332                 return true;
1333             }
1334         }
1335         return false;
1336     }
1337 
isIkeSessionNonAeadAlgosAvailable()1338     private boolean isIkeSessionNonAeadAlgosAvailable() {
1339         int[] encryptionAlgos =
1340                 IwlanCarrierConfig.getConfigIntArray(
1341                         mContext,
1342                         mSlotId,
1343                         CarrierConfigManager.Iwlan
1344                                 .KEY_SUPPORTED_IKE_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY);
1345         for (int encryptionAlgo : encryptionAlgos) {
1346             if (validateConfig(encryptionAlgo, VALID_ENCRYPTION_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO)) {
1347                 return true;
1348             }
1349         }
1350         return false;
1351     }
1352 
isValidChildSessionLifetime(int hardLifetimeSeconds, int softLifetimeSeconds)1353     private boolean isValidChildSessionLifetime(int hardLifetimeSeconds, int softLifetimeSeconds) {
1354         return hardLifetimeSeconds >= CHILD_HARD_LIFETIME_SEC_MINIMUM
1355                 && hardLifetimeSeconds <= CHILD_HARD_LIFETIME_SEC_MAXIMUM
1356                 && softLifetimeSeconds >= CHILD_SOFT_LIFETIME_SEC_MINIMUM
1357                 && hardLifetimeSeconds - softLifetimeSeconds >= LIFETIME_MARGIN_SEC_MINIMUM;
1358     }
1359 
isValidIkeSessionLifetime(int hardLifetimeSeconds, int softLifetimeSeconds)1360     private boolean isValidIkeSessionLifetime(int hardLifetimeSeconds, int softLifetimeSeconds) {
1361         return hardLifetimeSeconds >= IKE_HARD_LIFETIME_SEC_MINIMUM
1362                 && hardLifetimeSeconds <= IKE_HARD_LIFETIME_SEC_MAXIMUM
1363                 && softLifetimeSeconds >= IKE_SOFT_LIFETIME_SEC_MINIMUM
1364                 && hardLifetimeSeconds - softLifetimeSeconds >= LIFETIME_MARGIN_SEC_MINIMUM;
1365     }
1366 
createEpdgSaProposal(EpdgSaProposal epdgSaProposal, boolean isChildProposal)1367     private void createEpdgSaProposal(EpdgSaProposal epdgSaProposal, boolean isChildProposal) {
1368         epdgSaProposal.addProposedDhGroups(
1369                 IwlanCarrierConfig.getConfigIntArray(
1370                         mContext,
1371                         mSlotId,
1372                         CarrierConfigManager.Iwlan.KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY));
1373 
1374         int[] encryptionAlgos =
1375                 isChildProposal
1376                         ? IwlanCarrierConfig.getConfigIntArray(
1377                                 mContext,
1378                                 mSlotId,
1379                                 CarrierConfigManager.Iwlan
1380                                     .KEY_SUPPORTED_CHILD_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY)
1381                         : IwlanCarrierConfig.getConfigIntArray(
1382                                 mContext,
1383                                 mSlotId,
1384                                 CarrierConfigManager.Iwlan
1385                                     .KEY_SUPPORTED_IKE_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY);
1386 
1387         for (int encryptionAlgo : encryptionAlgos) {
1388             if (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_CBC) {
1389                 int[] aesCbcKeyLens =
1390                         isChildProposal
1391                                 ? IwlanCarrierConfig.getConfigIntArray(
1392                                         mContext,
1393                                         mSlotId,
1394                                         CarrierConfigManager.Iwlan
1395                                                 .KEY_CHILD_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY)
1396                                 : IwlanCarrierConfig.getConfigIntArray(
1397                                         mContext,
1398                                         mSlotId,
1399                                         CarrierConfigManager.Iwlan
1400                                                 .KEY_IKE_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY);
1401                 epdgSaProposal.addProposedEncryptionAlgorithm(encryptionAlgo, aesCbcKeyLens);
1402             }
1403 
1404             if (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_CTR) {
1405                 int[] aesCtrKeyLens =
1406                         isChildProposal
1407                                 ? IwlanCarrierConfig.getConfigIntArray(
1408                                         mContext,
1409                                         mSlotId,
1410                                         CarrierConfigManager.Iwlan
1411                                                 .KEY_CHILD_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY)
1412                                 : IwlanCarrierConfig.getConfigIntArray(
1413                                         mContext,
1414                                         mSlotId,
1415                                         CarrierConfigManager.Iwlan
1416                                                 .KEY_IKE_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY);
1417                 epdgSaProposal.addProposedEncryptionAlgorithm(encryptionAlgo, aesCtrKeyLens);
1418             }
1419         }
1420 
1421         if (encryptionAlgos.length > 0) {
1422             epdgSaProposal.addProposedIntegrityAlgorithm(
1423                     IwlanCarrierConfig.getConfigIntArray(
1424                             mContext,
1425                             mSlotId,
1426                             CarrierConfigManager.Iwlan
1427                                     .KEY_SUPPORTED_INTEGRITY_ALGORITHMS_INT_ARRAY));
1428         }
1429 
1430         int[] aeadAlgos =
1431                 isChildProposal
1432                         ? IwlanCarrierConfig.getConfigIntArray(
1433                                 mContext,
1434                                 mSlotId,
1435                                 CarrierConfigManager.Iwlan
1436                                         .KEY_SUPPORTED_CHILD_SESSION_AEAD_ALGORITHMS_INT_ARRAY)
1437                         : IwlanCarrierConfig.getConfigIntArray(
1438                                 mContext,
1439                                 mSlotId,
1440                                 CarrierConfigManager.Iwlan
1441                                         .KEY_SUPPORTED_IKE_SESSION_AEAD_ALGORITHMS_INT_ARRAY);
1442         for (int aeadAlgo : aeadAlgos) {
1443             if (!validateConfig(aeadAlgo, VALID_AEAD_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO)) {
1444                 continue;
1445             }
1446             if ((aeadAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8)
1447                     || (aeadAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12)
1448                     || (aeadAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16)) {
1449                 int[] aesGcmKeyLens =
1450                         isChildProposal
1451                                 ? IwlanCarrierConfig.getConfigIntArray(
1452                                         mContext,
1453                                         mSlotId,
1454                                         CarrierConfigManager.Iwlan
1455                                                 .KEY_CHILD_SESSION_AES_GCM_KEY_SIZE_INT_ARRAY)
1456                                 : IwlanCarrierConfig.getConfigIntArray(
1457                                         mContext,
1458                                         mSlotId,
1459                                         CarrierConfigManager.Iwlan
1460                                                 .KEY_IKE_SESSION_AES_GCM_KEY_SIZE_INT_ARRAY);
1461                 epdgSaProposal.addProposedAeadAlgorithm(aeadAlgo, aesGcmKeyLens);
1462             }
1463         }
1464 
1465         if (IwlanCarrierConfig.getConfigBoolean(
1466                 mContext, mSlotId, IwlanCarrierConfig.KEY_IKE_SA_TRANSFORMS_REORDER_BOOL)) {
1467             epdgSaProposal.enableReorderingSaferProposals();
1468         }
1469     }
1470 
createEpdgChildSaProposal()1471     private EpdgChildSaProposal createEpdgChildSaProposal() {
1472         EpdgChildSaProposal epdgChildSaProposal = new EpdgChildSaProposal();
1473         createEpdgSaProposal(epdgChildSaProposal, true);
1474         return epdgChildSaProposal;
1475     }
1476 
createEpdgIkeSaProposal()1477     private EpdgIkeSaProposal createEpdgIkeSaProposal() {
1478         EpdgIkeSaProposal epdgIkeSaProposal = new EpdgIkeSaProposal();
1479 
1480         createEpdgSaProposal(epdgIkeSaProposal, false);
1481 
1482         epdgIkeSaProposal.addProposedPrfAlgorithm(
1483                 IwlanCarrierConfig.getConfigIntArray(
1484                         mContext,
1485                         mSlotId,
1486                         CarrierConfigManager.Iwlan.KEY_SUPPORTED_PRF_ALGORITHMS_INT_ARRAY));
1487         return epdgIkeSaProposal;
1488     }
1489 
buildIkeSaProposal()1490     private IkeSaProposal buildIkeSaProposal() {
1491         IkeSaProposal.Builder saProposalBuilder = new IkeSaProposal.Builder();
1492 
1493         int[] dhGroups =
1494                 IwlanCarrierConfig.getConfigIntArray(
1495                         mContext,
1496                         mSlotId,
1497                         CarrierConfigManager.Iwlan.KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY);
1498         for (int dhGroup : dhGroups) {
1499             if (validateConfig(dhGroup, VALID_DH_GROUPS, CONFIG_TYPE_DH_GROUP)) {
1500                 saProposalBuilder.addDhGroup(dhGroup);
1501             }
1502         }
1503 
1504         int[] encryptionAlgos =
1505                 IwlanCarrierConfig.getConfigIntArray(
1506                         mContext,
1507                         mSlotId,
1508                         CarrierConfigManager.Iwlan
1509                                 .KEY_SUPPORTED_IKE_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY);
1510         for (int encryptionAlgo : encryptionAlgos) {
1511             validateConfig(encryptionAlgo, VALID_ENCRYPTION_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO);
1512 
1513             if (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_CBC) {
1514                 int[] aesCbcKeyLens =
1515                         IwlanCarrierConfig.getConfigIntArray(
1516                                 mContext,
1517                                 mSlotId,
1518                                 CarrierConfigManager.Iwlan
1519                                         .KEY_IKE_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY);
1520                 for (int aesCbcKeyLen : aesCbcKeyLens) {
1521                     if (validateConfig(aesCbcKeyLen, VALID_KEY_LENGTHS, CONFIG_TYPE_KEY_LEN)) {
1522                         saProposalBuilder.addEncryptionAlgorithm(encryptionAlgo, aesCbcKeyLen);
1523                     }
1524                 }
1525             }
1526 
1527             if (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_CTR) {
1528                 int[] aesCtrKeyLens =
1529                         IwlanCarrierConfig.getConfigIntArray(
1530                                 mContext,
1531                                 mSlotId,
1532                                 CarrierConfigManager.Iwlan
1533                                         .KEY_IKE_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY);
1534                 for (int aesCtrKeyLen : aesCtrKeyLens) {
1535                     if (validateConfig(aesCtrKeyLen, VALID_KEY_LENGTHS, CONFIG_TYPE_KEY_LEN)) {
1536                         saProposalBuilder.addEncryptionAlgorithm(encryptionAlgo, aesCtrKeyLen);
1537                     }
1538                 }
1539             }
1540         }
1541 
1542         int[] integrityAlgos =
1543                 IwlanCarrierConfig.getConfigIntArray(
1544                         mContext,
1545                         mSlotId,
1546                         CarrierConfigManager.Iwlan.KEY_SUPPORTED_INTEGRITY_ALGORITHMS_INT_ARRAY);
1547         for (int integrityAlgo : integrityAlgos) {
1548             if (validateConfig(integrityAlgo, VALID_INTEGRITY_ALGOS, CONFIG_TYPE_INTEGRITY_ALGO)) {
1549                 saProposalBuilder.addIntegrityAlgorithm(integrityAlgo);
1550             }
1551         }
1552 
1553         int[] prfAlgos =
1554                 IwlanCarrierConfig.getConfigIntArray(
1555                         mContext,
1556                         mSlotId,
1557                         CarrierConfigManager.Iwlan.KEY_SUPPORTED_PRF_ALGORITHMS_INT_ARRAY);
1558         for (int prfAlgo : prfAlgos) {
1559             if (validateConfig(prfAlgo, VALID_PRF_ALGOS, CONFIG_TYPE_PRF_ALGO)) {
1560                 saProposalBuilder.addPseudorandomFunction(prfAlgo);
1561             }
1562         }
1563 
1564         return saProposalBuilder.build();
1565     }
1566 
buildIkeSaAeadProposal()1567     private IkeSaProposal buildIkeSaAeadProposal() {
1568         IkeSaProposal.Builder saProposalBuilder = new IkeSaProposal.Builder();
1569 
1570         int[] dhGroups =
1571                 IwlanCarrierConfig.getConfigIntArray(
1572                         mContext,
1573                         mSlotId,
1574                         CarrierConfigManager.Iwlan.KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY);
1575         for (int dhGroup : dhGroups) {
1576             if (validateConfig(dhGroup, VALID_DH_GROUPS, CONFIG_TYPE_DH_GROUP)) {
1577                 saProposalBuilder.addDhGroup(dhGroup);
1578             }
1579         }
1580 
1581         int[] encryptionAlgos =
1582                 IwlanCarrierConfig.getConfigIntArray(
1583                         mContext,
1584                         mSlotId,
1585                         CarrierConfigManager.Iwlan
1586                                 .KEY_SUPPORTED_IKE_SESSION_AEAD_ALGORITHMS_INT_ARRAY);
1587         for (int encryptionAlgo : encryptionAlgos) {
1588             if (!validateConfig(encryptionAlgo, VALID_AEAD_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO)) {
1589                 continue;
1590             }
1591             if ((encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8)
1592                     || (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12)
1593                     || (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16)) {
1594                 int[] aesGcmKeyLens =
1595                         IwlanCarrierConfig.getConfigIntArray(
1596                                 mContext,
1597                                 mSlotId,
1598                                 CarrierConfigManager.Iwlan
1599                                         .KEY_IKE_SESSION_AES_GCM_KEY_SIZE_INT_ARRAY);
1600                 for (int aesGcmKeyLen : aesGcmKeyLens) {
1601                     if (validateConfig(aesGcmKeyLen, VALID_KEY_LENGTHS, CONFIG_TYPE_KEY_LEN)) {
1602                         saProposalBuilder.addEncryptionAlgorithm(encryptionAlgo, aesGcmKeyLen);
1603                     }
1604                 }
1605             }
1606         }
1607 
1608         int[] prfAlgos =
1609                 IwlanCarrierConfig.getConfigIntArray(
1610                         mContext,
1611                         mSlotId,
1612                         CarrierConfigManager.Iwlan.KEY_SUPPORTED_PRF_ALGORITHMS_INT_ARRAY);
1613         for (int prfAlgo : prfAlgos) {
1614             if (validateConfig(prfAlgo, VALID_PRF_ALGOS, CONFIG_TYPE_PRF_ALGO)) {
1615                 saProposalBuilder.addPseudorandomFunction(prfAlgo);
1616             }
1617         }
1618 
1619         return saProposalBuilder.build();
1620     }
1621 
validateConfig(int config, Set<Integer> validConfigValues, String configType)1622     private boolean validateConfig(int config, Set<Integer> validConfigValues, String configType) {
1623         if (validConfigValues.contains(config)) {
1624             return true;
1625         }
1626 
1627         Log.e(TAG, "Invalid config value for " + configType + ":" + config);
1628         return false;
1629     }
1630 
buildChildSaProposal()1631     private ChildSaProposal buildChildSaProposal() {
1632         ChildSaProposal.Builder saProposalBuilder = new ChildSaProposal.Builder();
1633 
1634         // IKE library doesn't add KE payload if dh groups are not set in child session params.
1635         // Use the same groups as that of IKE session.
1636         if (IwlanCarrierConfig.getConfigBoolean(
1637                 mContext,
1638                 mSlotId,
1639                 CarrierConfigManager.Iwlan.KEY_ADD_KE_TO_CHILD_SESSION_REKEY_BOOL)) {
1640             int[] dhGroups =
1641                     IwlanCarrierConfig.getConfigIntArray(
1642                             mContext,
1643                             mSlotId,
1644                             CarrierConfigManager.Iwlan.KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY);
1645             for (int dhGroup : dhGroups) {
1646                 if (validateConfig(dhGroup, VALID_DH_GROUPS, CONFIG_TYPE_DH_GROUP)) {
1647                     saProposalBuilder.addDhGroup(dhGroup);
1648                 }
1649             }
1650         }
1651 
1652         int[] encryptionAlgos =
1653                 IwlanCarrierConfig.getConfigIntArray(
1654                         mContext,
1655                         mSlotId,
1656                         CarrierConfigManager.Iwlan
1657                                 .KEY_SUPPORTED_CHILD_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY);
1658         for (int encryptionAlgo : encryptionAlgos) {
1659             if (validateConfig(encryptionAlgo, VALID_ENCRYPTION_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO)) {
1660                 if (ChildSaProposal.getSupportedEncryptionAlgorithms().contains(encryptionAlgo)) {
1661                     if (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_CBC) {
1662                         int[] aesCbcKeyLens =
1663                                 IwlanCarrierConfig.getConfigIntArray(
1664                                         mContext,
1665                                         mSlotId,
1666                                         CarrierConfigManager.Iwlan
1667                                                 .KEY_CHILD_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY);
1668                         for (int aesCbcKeyLen : aesCbcKeyLens) {
1669                             if (validateConfig(
1670                                     aesCbcKeyLen, VALID_KEY_LENGTHS, CONFIG_TYPE_KEY_LEN)) {
1671                                 saProposalBuilder.addEncryptionAlgorithm(
1672                                         encryptionAlgo, aesCbcKeyLen);
1673                             }
1674                         }
1675                     }
1676 
1677                     if (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_CTR) {
1678                         int[] aesCtrKeyLens =
1679                                 IwlanCarrierConfig.getConfigIntArray(
1680                                         mContext,
1681                                         mSlotId,
1682                                         CarrierConfigManager.Iwlan
1683                                                 .KEY_CHILD_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY);
1684                         for (int aesCtrKeyLen : aesCtrKeyLens) {
1685                             if (validateConfig(
1686                                     aesCtrKeyLen, VALID_KEY_LENGTHS, CONFIG_TYPE_KEY_LEN)) {
1687                                 saProposalBuilder.addEncryptionAlgorithm(
1688                                         encryptionAlgo, aesCtrKeyLen);
1689                             }
1690                         }
1691                     }
1692                 } else {
1693                     Log.w(TAG, "Device does not support encryption algo:  " + encryptionAlgo);
1694                 }
1695             }
1696         }
1697 
1698         int[] integrityAlgos =
1699                 IwlanCarrierConfig.getConfigIntArray(
1700                         mContext,
1701                         mSlotId,
1702                         CarrierConfigManager.Iwlan.KEY_SUPPORTED_INTEGRITY_ALGORITHMS_INT_ARRAY);
1703         for (int integrityAlgo : integrityAlgos) {
1704             if (validateConfig(integrityAlgo, VALID_INTEGRITY_ALGOS, CONFIG_TYPE_INTEGRITY_ALGO)) {
1705                 if (ChildSaProposal.getSupportedIntegrityAlgorithms().contains(integrityAlgo)) {
1706                     saProposalBuilder.addIntegrityAlgorithm(integrityAlgo);
1707                 } else {
1708                     Log.w(TAG, "Device does not support integrity algo:  " + integrityAlgo);
1709                 }
1710             }
1711         }
1712 
1713         return saProposalBuilder.build();
1714     }
1715 
buildAeadChildSaProposal()1716     private ChildSaProposal buildAeadChildSaProposal() {
1717         ChildSaProposal.Builder saProposalBuilder = new ChildSaProposal.Builder();
1718 
1719         int[] dhGroups =
1720                 IwlanCarrierConfig.getConfigIntArray(
1721                         mContext,
1722                         mSlotId,
1723                         CarrierConfigManager.Iwlan.KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY);
1724         for (int dhGroup : dhGroups) {
1725             if (validateConfig(dhGroup, VALID_DH_GROUPS, CONFIG_TYPE_DH_GROUP)) {
1726                 saProposalBuilder.addDhGroup(dhGroup);
1727             }
1728         }
1729 
1730         int[] encryptionAlgos =
1731                 IwlanCarrierConfig.getConfigIntArray(
1732                         mContext,
1733                         mSlotId,
1734                         CarrierConfigManager.Iwlan
1735                                 .KEY_SUPPORTED_CHILD_SESSION_AEAD_ALGORITHMS_INT_ARRAY);
1736         for (int encryptionAlgo : encryptionAlgos) {
1737             if (!validateConfig(encryptionAlgo, VALID_AEAD_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO)) {
1738                 continue;
1739             }
1740             if ((encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8)
1741                     || (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12)
1742                     || (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16)) {
1743                 int[] aesGcmKeyLens =
1744                         IwlanCarrierConfig.getConfigIntArray(
1745                                 mContext,
1746                                 mSlotId,
1747                                 CarrierConfigManager.Iwlan
1748                                         .KEY_CHILD_SESSION_AES_GCM_KEY_SIZE_INT_ARRAY);
1749                 for (int aesGcmKeyLen : aesGcmKeyLens) {
1750                     if (validateConfig(aesGcmKeyLen, VALID_KEY_LENGTHS, CONFIG_TYPE_KEY_LEN)) {
1751                         saProposalBuilder.addEncryptionAlgorithm(encryptionAlgo, aesGcmKeyLen);
1752                     }
1753                 }
1754             }
1755         }
1756 
1757         return saProposalBuilder.build();
1758     }
1759 
getLocalIdentification()1760     private IkeIdentification getLocalIdentification() throws IwlanSimNotReadyException {
1761         String nai;
1762 
1763         nai = IwlanHelper.getNai(mContext, mSlotId, mNextReauthId);
1764 
1765         if (nai == null) {
1766             throw new IwlanSimNotReadyException("Nai is null.");
1767         }
1768 
1769         Log.d(TAG, "getLocalIdentification: Nai: " + nai);
1770         return getId(nai, true);
1771     }
1772 
getId(String id, boolean isLocal)1773     private IkeIdentification getId(String id, boolean isLocal) {
1774         String idTypeConfig =
1775                 isLocal
1776                         ? CarrierConfigManager.Iwlan.KEY_IKE_LOCAL_ID_TYPE_INT
1777                         : CarrierConfigManager.Iwlan.KEY_IKE_REMOTE_ID_TYPE_INT;
1778         int idType = IwlanCarrierConfig.getConfigInt(mContext, mSlotId, idTypeConfig);
1779         switch (idType) {
1780             case CarrierConfigManager.Iwlan.ID_TYPE_FQDN:
1781                 return new IkeFqdnIdentification(id);
1782             case CarrierConfigManager.Iwlan.ID_TYPE_KEY_ID:
1783                 return new IkeKeyIdIdentification(id.getBytes(StandardCharsets.US_ASCII));
1784             case CarrierConfigManager.Iwlan.ID_TYPE_RFC822_ADDR:
1785                 return new IkeRfc822AddrIdentification(id);
1786             default:
1787                 throw new IllegalArgumentException("Invalid local Identity type: " + idType);
1788         }
1789     }
1790 
getEapConfig()1791     private EapSessionConfig getEapConfig() throws IwlanSimNotReadyException {
1792         int subId = IwlanHelper.getSubId(mContext, mSlotId);
1793         String nai = IwlanHelper.getNai(mContext, mSlotId, null);
1794 
1795         if (nai == null) {
1796             throw new IwlanSimNotReadyException("Nai is null.");
1797         }
1798 
1799         EapSessionConfig.EapAkaOption option = null;
1800         if (mNextReauthId != null) {
1801             option = new EapSessionConfig.EapAkaOption.Builder().setReauthId(mNextReauthId).build();
1802         }
1803 
1804         Log.d(TAG, "getEapConfig: Nai: " + nai);
1805         return new EapSessionConfig.Builder()
1806                 .setEapAkaConfig(subId, TelephonyManager.APPTYPE_USIM, option)
1807                 .setEapIdentity(nai.getBytes(StandardCharsets.US_ASCII))
1808                 .build();
1809     }
1810 
onSessionClosedWithException( IkeException exception, String apnName, int token, int sessionType)1811     private void onSessionClosedWithException(
1812             IkeException exception, String apnName, int token, int sessionType) {
1813         Log.e(
1814                 TAG,
1815                 "Closing tunnel with exception for apn: "
1816                         + apnName
1817                         + " with token: "
1818                         + token
1819                         + " sessionType:"
1820                         + sessionType);
1821         exception.printStackTrace();
1822 
1823         mHandler.sendMessage(
1824                 mHandler.obtainMessage(
1825                         sessionType, new SessionClosedData(apnName, token, exception)));
1826     }
1827 
isEpdgSelectionOrFirstTunnelBringUpInProgress()1828     private boolean isEpdgSelectionOrFirstTunnelBringUpInProgress() {
1829         // Tunnel config is created but not connected to an ePDG. i.e., The first bring-up request
1830         // in progress.
1831         // No bring-up request in progress but pending queue is not empty. i.e. ePDG selection in
1832         // progress
1833         return (!mHasConnectedToEpdg && !mApnNameToTunnelConfig.isEmpty())
1834                 || !mPendingBringUpRequests.isEmpty();
1835     }
1836 
getErrorFromIkeException( IkeException ikeException, IkeSessionState ikeSessionState)1837     private IwlanError getErrorFromIkeException(
1838             IkeException ikeException, IkeSessionState ikeSessionState) {
1839         IwlanError error;
1840         if (ikeException instanceof IkeIOException) {
1841             error = new IwlanError(ikeSessionState.getErrorType(), ikeException);
1842         } else {
1843             error = new IwlanError(ikeException);
1844         }
1845         Log.e(TAG, "Closing tunnel: error: " + error + " state: " + ikeSessionState);
1846         return error;
1847     }
1848 
1849     private final class TmHandler extends Handler {
1850 
1851         @Override
handleMessage(Message msg)1852         public void handleMessage(Message msg) {
1853             Log.d(TAG, "msg.what = " + eventToString(msg.what));
1854 
1855             String apnName;
1856             TunnelConfig tunnelConfig;
1857             OnClosedMetrics.Builder onClosedMetricsBuilder;
1858             TunnelRequestWrapper tunnelRequestWrapper;
1859             ConnectivityManager connectivityManager;
1860             NetworkCapabilities networkCapabilities;
1861             boolean isNetworkValidated;
1862             switch (msg.what) {
1863                 case EVENT_CHILD_SESSION_OPENED:
1864                 case EVENT_IKE_SESSION_CLOSED:
1865                 case EVENT_IPSEC_TRANSFORM_CREATED:
1866                 case EVENT_IPSEC_TRANSFORM_DELETED:
1867                 case EVENT_CHILD_SESSION_CLOSED:
1868                 case EVENT_IKE_SESSION_OPENED:
1869                 case EVENT_IKE_SESSION_CONNECTION_INFO_CHANGED:
1870                 case EVENT_IKE_3GPP_DATA_RECEIVED:
1871                 case EVENT_IKE_LIVENESS_STATUS_CHANGED:
1872                     IkeEventData ikeEventData = (IkeEventData) msg.obj;
1873                     if (isObsoleteToken(ikeEventData.mApnName, ikeEventData.mToken)) {
1874                         Log.d(
1875                                 TAG,
1876                                 eventToString(msg.what)
1877                                         + " for obsolete token "
1878                                         + ikeEventData.mToken);
1879                         return;
1880                     }
1881             }
1882 
1883             long mIkeTunnelEstablishmentDuration;
1884             switch (msg.what) {
1885                 case EVENT_TUNNEL_BRINGUP_REQUEST:
1886                     handleTunnelBringUpRequest((TunnelRequestWrapper) msg.obj);
1887                     break;
1888 
1889                 case EVENT_EPDG_ADDRESS_SELECTION_REQUEST_COMPLETE:
1890                     EpdgSelectorResult selectorResult = (EpdgSelectorResult) msg.obj;
1891                     printRequestQueue("EVENT_EPDG_ADDRESS_SELECTION_REQUEST_COMPLETE");
1892 
1893                     if (selectorResult.getTransactionId() != mTransactionId) {
1894                         Log.e(TAG, "Mismatched transactionId");
1895                         break;
1896                     }
1897 
1898                     if (mPendingBringUpRequests.isEmpty()) {
1899                         Log.d(TAG, "Empty request queue");
1900                         break;
1901                     }
1902 
1903                     if (selectorResult.getEpdgError().getErrorType() == IwlanError.NO_ERROR
1904                             && selectorResult.getValidIpList() != null) {
1905                         tunnelRequestWrapper = mPendingBringUpRequests.remove();
1906                         onBringUpTunnel(
1907                                 tunnelRequestWrapper,
1908                                 validateAndSetEpdgAddress(selectorResult.getValidIpList()));
1909                     } else {
1910                         IwlanError error =
1911                                 (selectorResult.getEpdgError().getErrorType()
1912                                                 == IwlanError.NO_ERROR)
1913                                         ? new IwlanError(
1914                                                 IwlanError.EPDG_SELECTOR_SERVER_SELECTION_FAILED)
1915                                         : selectorResult.getEpdgError();
1916                         failAllPendingRequests(error);
1917                     }
1918                     break;
1919 
1920                 case EVENT_CHILD_SESSION_OPENED:
1921                     TunnelOpenedData tunnelOpenedData = (TunnelOpenedData) msg.obj;
1922                     apnName = tunnelOpenedData.mApnName;
1923                     tunnelConfig = mApnNameToTunnelConfig.get(apnName);
1924 
1925                     tunnelConfig.setDnsAddrList(tunnelOpenedData.mInternalDnsServers);
1926                     tunnelConfig.setInternalAddrList(tunnelOpenedData.mInternalAddresses);
1927 
1928                     IpSecManager.IpSecTunnelInterface tunnelInterface = tunnelConfig.getIface();
1929 
1930                     for (LinkAddress address : tunnelConfig.getInternalAddrList()) {
1931                         try {
1932                             tunnelInterface.addAddress(
1933                                     address.getAddress(), address.getPrefixLength());
1934                         } catch (IOException e) {
1935                             Log.e(TAG, "Adding internal addresses to interface failed.");
1936                         }
1937                     }
1938 
1939                     TunnelLinkProperties linkProperties =
1940                             TunnelLinkProperties.builder()
1941                                     .setInternalAddresses(tunnelConfig.getInternalAddrList())
1942                                     .setDnsAddresses(tunnelConfig.getDnsAddrList())
1943                                     .setPcscfAddresses(tunnelConfig.getPcscfAddrList())
1944                                     .setIfaceName(tunnelConfig.getIface().getInterfaceName())
1945                                     .setSliceInfo(tunnelConfig.getSliceInfo())
1946                                     .build();
1947                     tunnelConfig.getTunnelCallback().onOpened(apnName, linkProperties);
1948 
1949                     reportIwlanError(apnName, new IwlanError(IwlanError.NO_ERROR));
1950                     getEpdgSelector().onEpdgConnectedSuccessfully();
1951 
1952                     mIkeTunnelEstablishmentDuration =
1953                             System.currentTimeMillis() - mIkeTunnelEstablishmentStartTime;
1954                     mIkeTunnelEstablishmentStartTime = 0;
1955                     connectivityManager = mContext.getSystemService(ConnectivityManager.class);
1956                     networkCapabilities =
1957                             connectivityManager.getNetworkCapabilities(mIkeSessionNetwork);
1958                     isNetworkValidated =
1959                             (networkCapabilities != null)
1960                                     && networkCapabilities.hasCapability(
1961                                             NetworkCapabilities.NET_CAPABILITY_VALIDATED);
1962                     tunnelConfig
1963                             .getTunnelMetrics()
1964                             .onOpened(
1965                                     new OnOpenedMetrics.Builder()
1966                                             .setApnName(apnName)
1967                                             .setEpdgServerAddress(tunnelConfig.getEpdgAddress())
1968                                             .setEpdgServerSelectionDuration(
1969                                                     (int) mEpdgServerSelectionDuration)
1970                                             .setIkeTunnelEstablishmentDuration(
1971                                                     (int) mIkeTunnelEstablishmentDuration)
1972                                             .setIsNetworkValidated(isNetworkValidated)
1973                                             .build());
1974 
1975                     mEpdgMonitor.onApnConnectToEpdg(apnName, tunnelConfig.getEpdgAddress());
1976                     onConnectedToEpdg(true);
1977                     mValidEpdgInfo.resetIndex();
1978                     printRequestQueue("EVENT_CHILD_SESSION_OPENED");
1979                     serviceAllPendingRequests();
1980                     tunnelConfig.setIkeSessionState(IkeSessionState.CHILD_SESSION_OPENED);
1981                     break;
1982 
1983                 case EVENT_IKE_SESSION_CLOSED:
1984                     printRequestQueue("EVENT_IKE_SESSION_CLOSED");
1985                     SessionClosedData sessionClosedData = (SessionClosedData) msg.obj;
1986                     apnName = sessionClosedData.mApnName;
1987 
1988                     tunnelConfig = mApnNameToTunnelConfig.get(apnName);
1989                     if (tunnelConfig == null) {
1990                         Log.e(TAG, "No callback found for apn: " + apnName);
1991                         return;
1992                     }
1993 
1994                     // If IKE session closed exceptionally, we retrieve IwlanError directly from the
1995                     // exception; otherwise, it is still possible that we triggered an IKE session
1996                     // close due to an error (e.g. IwlanError.TUNNEL_TRANSFORM_FAILED), or because
1997                     // the Child session closed exceptionally; in which case, we attempt to retrieve
1998                     // the stored error (if any) from TunnelConfig.
1999                     IwlanError iwlanError;
2000                     if (sessionClosedData.mIkeException != null) {
2001                         iwlanError =
2002                                 getErrorFromIkeException(
2003                                         sessionClosedData.mIkeException,
2004                                         tunnelConfig.getIkeSessionState());
2005                     } else {
2006                         // If IKE session opened, then closed before child session (and IWLAN
2007                         // tunnel) opened.
2008                         // Iwlan reports IKE_SESSION_CLOSED_BEFORE_CHILD_SESSION_OPENED
2009                         // instead of NO_ERROR
2010                         if (!tunnelConfig.hasTunnelOpened()) {
2011                             iwlanError = new IwlanError(
2012                                     IwlanError.IKE_SESSION_CLOSED_BEFORE_CHILD_SESSION_OPENED);
2013                         } else {
2014                             iwlanError = tunnelConfig.getError();
2015                         }
2016                     }
2017 
2018                     IpSecManager.IpSecTunnelInterface iface = tunnelConfig.getIface();
2019                     if (iface != null) {
2020                         iface.close();
2021                     }
2022 
2023                     if (!tunnelConfig.hasTunnelOpened()) {
2024                         if (tunnelConfig.isBackoffTimeValid()) {
2025                             reportIwlanError(apnName, iwlanError, tunnelConfig.getBackoffTime());
2026                         } else {
2027                             reportIwlanError(apnName, iwlanError);
2028                         }
2029                         mEpdgMonitor.onEpdgConnectionFailed(
2030                                 tunnelConfig.isEmergency(), tunnelConfig.getEpdgAddress());
2031                         getEpdgSelector().onEpdgConnectionFailed(tunnelConfig.getEpdgAddress());
2032                     }
2033 
2034                     Log.d(TAG, "Tunnel Closed: " + iwlanError);
2035                     tunnelConfig.setIkeSessionState(IkeSessionState.NO_IKE_SESSION);
2036                     tunnelConfig.getTunnelCallback().onClosed(apnName, iwlanError);
2037                     onClosedMetricsBuilder = new OnClosedMetrics.Builder().setApnName(apnName);
2038 
2039                     if (!mEpdgMonitor.hasEpdgConnected()) {
2040                         failAllPendingRequests(iwlanError);
2041                         tunnelConfig.getTunnelMetrics().onClosed(onClosedMetricsBuilder.build());
2042                     } else {
2043                         mIkeTunnelEstablishmentDuration =
2044                                 mIkeTunnelEstablishmentStartTime > 0
2045                                         ? System.currentTimeMillis()
2046                                                 - mIkeTunnelEstablishmentStartTime
2047                                         : 0;
2048                         mIkeTunnelEstablishmentStartTime = 0;
2049 
2050                         connectivityManager = mContext.getSystemService(ConnectivityManager.class);
2051                         networkCapabilities =
2052                                 connectivityManager.getNetworkCapabilities(mIkeSessionNetwork);
2053                         isNetworkValidated =
2054                                 (networkCapabilities != null)
2055                                         && networkCapabilities.hasCapability(
2056                                                 NetworkCapabilities.NET_CAPABILITY_VALIDATED);
2057                         onClosedMetricsBuilder
2058                                 .setEpdgServerAddress(tunnelConfig.getEpdgAddress())
2059                                 .setEpdgServerSelectionDuration((int) mEpdgServerSelectionDuration)
2060                                 .setIkeTunnelEstablishmentDuration(
2061                                         (int) mIkeTunnelEstablishmentDuration)
2062                                 .setIsNetworkValidated(isNetworkValidated);
2063                         tunnelConfig.getTunnelMetrics().onClosed(onClosedMetricsBuilder.build());
2064                     }
2065 
2066                     mApnNameToTunnelConfig.remove(apnName);
2067                     mEpdgMonitor.onApnDisconnectFromEpdg(apnName);
2068                     if (mApnNameToTunnelConfig.isEmpty() && mPendingBringUpRequests.isEmpty()) {
2069                         onConnectedToEpdg(false);
2070                     }
2071                     break;
2072 
2073                 case EVENT_UPDATE_NETWORK:
2074                     UpdateNetworkWrapper updatedNetwork = (UpdateNetworkWrapper) msg.obj;
2075                     mDefaultNetwork = updatedNetwork.getNetwork();
2076                     LinkProperties defaultLinkProperties = updatedNetwork.getLinkProperties();
2077                     String paraString = "Network: " + mDefaultNetwork;
2078 
2079                     if (mEpdgMonitor.hasEpdgConnected()) {
2080                         if (Objects.isNull(mDefaultNetwork)) {
2081                             Log.w(TAG, "The default network has been removed.");
2082                         } else if (Objects.isNull(defaultLinkProperties)) {
2083                             Log.w(
2084                                     TAG,
2085                                     "The default network's LinkProperties is not ready ."
2086                                             + paraString);
2087                         } else if (Objects.equals(mDefaultNetwork, mIkeSessionNetwork)) {
2088                             Log.w(
2089                                     TAG,
2090                                     "The default network has not changed from the IKE session"
2091                                             + " network. "
2092                                             + paraString);
2093                         } else {
2094                             for (var entry : mApnNameToTunnelConfig.entrySet()) {
2095                                 String apn = entry.getKey();
2096                                 TunnelConfig config = entry.getValue();
2097                                 if (!defaultLinkProperties.isReachable(config.getEpdgAddress())) {
2098                                     Log.w(
2099                                             TAG,
2100                                             "The default network link "
2101                                                     + defaultLinkProperties
2102                                                     + " doesn't have a route to the ePDG "
2103                                                     + config.getEpdgAddress()
2104                                                     + paraString);
2105                                 } else {
2106                                     Log.d(
2107                                             TAG,
2108                                             "The Underlying Network is updating for APN (+"
2109                                                     + apn
2110                                                     + "). "
2111                                                     + paraString);
2112                                     config.getIkeSession().setNetwork(mDefaultNetwork);
2113                                     config.setIkeSessionState(
2114                                             IkeSessionState.IKE_MOBILITY_IN_PROGRESS);
2115                                     mIkeSessionNetwork = mDefaultNetwork;
2116                                 }
2117                             }
2118                         }
2119                     }
2120                     break;
2121 
2122                 case EVENT_TUNNEL_BRINGDOWN_REQUEST:
2123                     TunnelBringdownRequest bringdownRequest = (TunnelBringdownRequest) msg.obj;
2124                     apnName = bringdownRequest.mApnName;
2125                     boolean forceClose = bringdownRequest.mForceClose;
2126                     int reason = bringdownRequest.mBringDownReason;
2127                     tunnelConfig = mApnNameToTunnelConfig.get(apnName);
2128                     if (tunnelConfig == null) {
2129                         Log.w(
2130                                 TAG,
2131                                 "Bringdown request: No tunnel exists for apn: "
2132                                         + apnName
2133                                         + ", forced: "
2134                                         + forceClose
2135                                         + ", bringdown reason: "
2136                                         + bringdownReasonToString(reason));
2137                     } else {
2138                         if (forceClose) {
2139                             tunnelConfig.getIkeSession().kill();
2140                         } else {
2141                             tunnelConfig.getIkeSession().close();
2142                         }
2143                     }
2144                     // TODO(b/309867892): Include tunnel bring down reason in metrics.
2145                     int numClosed = closePendingRequestsForApn(apnName);
2146                     if (numClosed > 0) {
2147                         Log.d(
2148                                 TAG,
2149                                 "Closed "
2150                                         + numClosed
2151                                         + " pending requests for apn: "
2152                                         + apnName
2153                                         + ", bringdown reason: "
2154                                         + bringdownReasonToString(reason));
2155                     }
2156                     if (tunnelConfig == null && numClosed == 0) {
2157                         // IwlanDataService expected to close a (pending or up) tunnel but was not
2158                         // found. Recovers state in IwlanDataService through TunnelCallback.
2159                         iwlanError = new IwlanError(IwlanError.TUNNEL_NOT_FOUND);
2160                         reportIwlanError(apnName, iwlanError);
2161                         bringdownRequest.mTunnelCallback.onClosed(apnName, iwlanError);
2162                         bringdownRequest.mIwlanTunnelMetrics.onClosed(
2163                                 new OnClosedMetrics.Builder().setApnName(apnName).build());
2164                     }
2165                     break;
2166 
2167                 case EVENT_IPSEC_TRANSFORM_CREATED:
2168                     IpsecTransformData transformData = (IpsecTransformData) msg.obj;
2169                     apnName = transformData.getApnName();
2170                     tunnelConfig = mApnNameToTunnelConfig.get(apnName);
2171 
2172                     try {
2173                         mIpSecManager.applyTunnelModeTransform(
2174                                 tunnelConfig.getIface(),
2175                                 transformData.getDirection(),
2176                                 transformData.getTransform());
2177                     } catch (IOException | IllegalArgumentException e) {
2178                         // If the IKE session was closed before the transform could be applied, the
2179                         // IpSecService will throw an IAE on processing the IpSecTunnelInterface id.
2180                         Log.e(TAG, "Failed to apply tunnel transform." + e);
2181                         closeIkeSession(
2182                                 apnName, new IwlanError(IwlanError.TUNNEL_TRANSFORM_FAILED));
2183                     }
2184                     if (tunnelConfig.getIkeSessionState()
2185                             == IkeSessionState.IKE_MOBILITY_IN_PROGRESS) {
2186                         tunnelConfig.setIkeSessionState(IkeSessionState.CHILD_SESSION_OPENED);
2187                     }
2188                     break;
2189 
2190                 case EVENT_IPSEC_TRANSFORM_DELETED:
2191                     transformData = (IpsecTransformData) msg.obj;
2192                     IpSecTransform transform = transformData.getTransform();
2193                     transform.close();
2194                     break;
2195 
2196                 case EVENT_CHILD_SESSION_CLOSED:
2197                     sessionClosedData = (SessionClosedData) msg.obj;
2198                     apnName = sessionClosedData.mApnName;
2199 
2200                     tunnelConfig = mApnNameToTunnelConfig.get(apnName);
2201                     if (tunnelConfig == null) {
2202                         Log.d(TAG, "No tunnel callback for apn: " + apnName);
2203                         return;
2204                     }
2205                     if (sessionClosedData.mIkeException != null) {
2206                         tunnelConfig.setError(
2207                                 getErrorFromIkeException(
2208                                         sessionClosedData.mIkeException,
2209                                         tunnelConfig.getIkeSessionState()));
2210                     }
2211                     tunnelConfig.getIkeSession().close();
2212                     break;
2213 
2214                 case EVENT_IKE_SESSION_OPENED:
2215                     IkeSessionOpenedData ikeSessionOpenedData = (IkeSessionOpenedData) msg.obj;
2216                     apnName = ikeSessionOpenedData.mApnName;
2217                     IkeSessionConfiguration sessionConfiguration =
2218                             ikeSessionOpenedData.mIkeSessionConfiguration;
2219 
2220                     tunnelConfig = mApnNameToTunnelConfig.get(apnName);
2221                     tunnelConfig.setPcscfAddrList(sessionConfiguration.getPcscfServers());
2222 
2223                     boolean enabledFastReauth =
2224                             IwlanCarrierConfig.getConfigBoolean(
2225                                     mContext,
2226                                     mSlotId,
2227                                     CarrierConfigManager.Iwlan
2228                                             .KEY_SUPPORTS_EAP_AKA_FAST_REAUTH_BOOL);
2229                     Log.d(
2230                             TAG,
2231                             "CarrierConfigManager.Iwlan.KEY_SUPPORTS_EAP_AKA_FAST_REAUTH_BOOL "
2232                                     + enabledFastReauth);
2233 
2234                     if (enabledFastReauth) {
2235                         EapInfo eapInfo = sessionConfiguration.getEapInfo();
2236                         if (eapInfo instanceof EapAkaInfo) {
2237                             mNextReauthId = ((EapAkaInfo) eapInfo).getReauthId();
2238                             Log.d(TAG, "Update ReauthId: " + Arrays.toString(mNextReauthId));
2239                         } else {
2240                             mNextReauthId = null;
2241                         }
2242                     }
2243                     break;
2244 
2245                 case EVENT_IKE_SESSION_CONNECTION_INFO_CHANGED:
2246                     IkeSessionConnectionInfoData ikeSessionConnectionInfoData =
2247                             (IkeSessionConnectionInfoData) msg.obj;
2248                     Network network =
2249                             ikeSessionConnectionInfoData.mIkeSessionConnectionInfo.getNetwork();
2250                     apnName = ikeSessionConnectionInfoData.mApnName;
2251 
2252                     connectivityManager = mContext.getSystemService(ConnectivityManager.class);
2253                     if (Objects.requireNonNull(connectivityManager).getLinkProperties(network)
2254                             == null) {
2255                         Log.e(TAG, "Network " + network + " has null LinkProperties!");
2256                         return;
2257                     }
2258 
2259                     tunnelConfig = mApnNameToTunnelConfig.get(apnName);
2260                     tunnelInterface = tunnelConfig.getIface();
2261                     try {
2262                         tunnelInterface.setUnderlyingNetwork(network);
2263                     } catch (IOException | IllegalArgumentException e) {
2264                         Log.e(
2265                                 TAG,
2266                                 "Failed to update underlying network for apn: "
2267                                         + apnName
2268                                         + " exception: "
2269                                         + e);
2270                     }
2271                     break;
2272 
2273                 case EVENT_IKE_3GPP_DATA_RECEIVED:
2274                     Ike3gppDataReceived ike3gppDataReceived = (Ike3gppDataReceived) msg.obj;
2275                     apnName = ike3gppDataReceived.mApnName;
2276                     List<Ike3gppData> ike3gppData = ike3gppDataReceived.mIke3gppData;
2277                     if (ike3gppData != null && !ike3gppData.isEmpty()) {
2278                         tunnelConfig = mApnNameToTunnelConfig.get(apnName);
2279                         for (Ike3gppData payload : ike3gppData) {
2280                             if (payload.getDataType() == DATA_TYPE_NOTIFY_N1_MODE_INFORMATION) {
2281                                 Log.d(TAG, "Got payload DATA_TYPE_NOTIFY_N1_MODE_INFORMATION");
2282                                 NetworkSliceInfo si =
2283                                         NetworkSliceSelectionAssistanceInformation.getSliceInfo(
2284                                                 ((Ike3gppN1ModeInformation) payload).getSnssai());
2285                                 if (si != null) {
2286                                     tunnelConfig.setSliceInfo(si);
2287                                     Log.d(TAG, "SliceInfo: " + si);
2288                                 }
2289                             } else if (payload.getDataType() == DATA_TYPE_NOTIFY_BACKOFF_TIMER) {
2290                                 Log.d(TAG, "Got payload DATA_TYPE_NOTIFY_BACKOFF_TIMER");
2291                                 long backoffTime =
2292                                         decodeBackoffTime(
2293                                                 ((Ike3gppBackoffTimer) payload).getBackoffTimer());
2294                                 if (backoffTime > 0) {
2295                                     tunnelConfig.setBackoffTime(backoffTime);
2296                                     Log.d(TAG, "Backoff Timer: " + backoffTime);
2297                                 }
2298                             }
2299                         }
2300                     } else {
2301                         Log.e(TAG, "Null or empty payloads received:");
2302                     }
2303                     break;
2304 
2305                 case EVENT_IKE_LIVENESS_STATUS_CHANGED:
2306                     IkeSessionValidationStatusData ikeLivenessData =
2307                             (IkeSessionValidationStatusData) msg.obj;
2308                     @NetworkValidationStatus int validationStatus = ikeLivenessData.mStatus;
2309                     apnName = ikeLivenessData.mApnName;
2310                     tunnelConfig = mApnNameToTunnelConfig.get(apnName);
2311                     if (tunnelConfig == null) {
2312                         Log.e(TAG, "No tunnel config found for apn: " + apnName);
2313                         return;
2314                     }
2315                     tunnelConfig
2316                             .getTunnelCallback()
2317                             .onNetworkValidationStatusChanged(apnName, validationStatus);
2318                     break;
2319 
2320                 case EVENT_REQUEST_NETWORK_VALIDATION_CHECK:
2321                     apnName = (String) msg.obj;
2322                     tunnelConfig = mApnNameToTunnelConfig.get(apnName);
2323                     if (tunnelConfig == null) {
2324                         Log.e(TAG, "No tunnel config found for apn: " + apnName);
2325                         return;
2326                     }
2327                     tunnelConfig.getIkeSession().requestLivenessCheck();
2328                     break;
2329 
2330                 default:
2331                     throw new IllegalStateException("Unexpected value: " + msg.what);
2332             }
2333         }
2334 
handleTunnelBringUpRequest(TunnelRequestWrapper tunnelRequestWrapper)2335         private void handleTunnelBringUpRequest(TunnelRequestWrapper tunnelRequestWrapper) {
2336             TunnelSetupRequest setupRequest = tunnelRequestWrapper.getSetupRequest();
2337             String apnName = setupRequest.apnName();
2338             OnClosedMetrics.Builder onClosedMetricsBuilder =
2339                     new OnClosedMetrics.Builder().setApnName(apnName);
2340 
2341             IwlanError bringUpError = canBringUpTunnel(apnName, setupRequest.isEmergency());
2342             if (Objects.nonNull(bringUpError)) {
2343                 tunnelRequestWrapper.getTunnelCallback().onClosed(apnName, bringUpError);
2344                 tunnelRequestWrapper.getTunnelMetrics().onClosed(onClosedMetricsBuilder.build());
2345                 return;
2346             }
2347             serviceTunnelBringUpRequest(tunnelRequestWrapper);
2348         }
2349 
serviceTunnelBringUpRequest(TunnelRequestWrapper tunnelRequestWrapper)2350         private void serviceTunnelBringUpRequest(TunnelRequestWrapper tunnelRequestWrapper) {
2351             if (mEpdgMonitor.hasEpdgConnected()) {
2352                 InetAddress epdgAddress = selectConnectedEpdgForTunnelBringUp(tunnelRequestWrapper);
2353                 if (epdgAddress != null) {
2354                     onBringUpTunnel(tunnelRequestWrapper, epdgAddress);
2355                     return;
2356                 }
2357             }
2358 
2359             if (!isEpdgSelectionOrFirstTunnelBringUpInProgress()) {
2360                 // No tunnel bring-up in progress Or emergency request has attempted ePDG for normal
2361                 // session but failed, select the ePDG address.
2362                 selectEpdgAddress(tunnelRequestWrapper.getSetupRequest());
2363             }
2364 
2365             // Another bring-up or ePDG selection is in progress, pending this request.
2366             mPendingBringUpRequests.add(tunnelRequestWrapper);
2367         }
2368 
selectConnectedEpdgForTunnelBringUp( TunnelRequestWrapper tunnelRequestWrapper)2369         private InetAddress selectConnectedEpdgForTunnelBringUp(
2370                 TunnelRequestWrapper tunnelRequestWrapper) {
2371             if (!mFeatureFlags.distinctEpdgSelectionForEmergencySessions()
2372                     || !IwlanCarrierConfig.getConfigBoolean(
2373                             mContext,
2374                             mSlotId,
2375                             IwlanCarrierConfig.KEY_DISTINCT_EPDG_FOR_EMERGENCY_ALLOWED_BOOL)) {
2376                 // Attempt on ePDG for normal session since feature not enabled
2377                 return mEpdgMonitor.getEpdgAddressForNormalSession();
2378             }
2379 
2380             if (!tunnelRequestWrapper.getSetupRequest().isEmergency()) {
2381                 if (mEpdgMonitor.hasSeparateEpdgConnectedForEmergencySession()) {
2382                     // Attempt on ePDG for emergency session
2383                     return mEpdgMonitor.getEpdgAddressForEmergencySession();
2384                 } else {
2385                     // Attempt on ePDG for normal session.
2386                     return mEpdgMonitor.getEpdgAddressForNormalSession();
2387                 }
2388             }
2389 
2390             if (!mEpdgMonitor.hasEmergencyPdnFailedWithConnectedEpdg()) {
2391                 // First emergnecy attempt on ePDG for normal session.
2392                 return mEpdgMonitor.getEpdgAddressForNormalSession();
2393             }
2394             return null; // no suitable ePDG address found. Select new ePDG address needed.
2395         }
2396 
TmHandler(Looper looper)2397         TmHandler(Looper looper) {
2398             super(looper);
2399         }
2400     }
2401 
closeIkeSession(String apnName, IwlanError error)2402     private void closeIkeSession(String apnName, IwlanError error) {
2403         TunnelConfig tunnelConfig = mApnNameToTunnelConfig.get(apnName);
2404         tunnelConfig.setError(error);
2405         tunnelConfig.getIkeSession().close();
2406     }
2407 
selectEpdgAddress(TunnelSetupRequest setupRequest)2408     private void selectEpdgAddress(TunnelSetupRequest setupRequest) {
2409         ++mTransactionId;
2410         mEpdgServerSelectionStartTime = System.currentTimeMillis();
2411 
2412         final int ipPreference =
2413                 IwlanCarrierConfig.getConfigInt(
2414                         mContext,
2415                         mSlotId,
2416                         CarrierConfigManager.Iwlan.KEY_EPDG_ADDRESS_IP_TYPE_PREFERENCE_INT);
2417 
2418         IpPreferenceConflict ipPreferenceConflict =
2419                 isIpPreferenceConflictsWithNetwork(ipPreference);
2420         if (ipPreferenceConflict.mIsConflict) {
2421             sendSelectionRequestComplete(
2422                     null, new IwlanError(ipPreferenceConflict.mErrorType), mTransactionId);
2423             return;
2424         }
2425 
2426         int protoFilter = EpdgSelector.PROTO_FILTER_IPV4V6;
2427         int epdgAddressOrder = EpdgSelector.SYSTEM_PREFERRED;
2428         switch (ipPreference) {
2429             case CarrierConfigManager.Iwlan.EPDG_ADDRESS_IPV4_PREFERRED:
2430                 epdgAddressOrder = EpdgSelector.IPV4_PREFERRED;
2431                 break;
2432             case CarrierConfigManager.Iwlan.EPDG_ADDRESS_IPV6_PREFERRED:
2433                 epdgAddressOrder = EpdgSelector.IPV6_PREFERRED;
2434                 break;
2435             case CarrierConfigManager.Iwlan.EPDG_ADDRESS_IPV4_ONLY:
2436                 protoFilter = EpdgSelector.PROTO_FILTER_IPV4;
2437                 break;
2438             case CarrierConfigManager.Iwlan.EPDG_ADDRESS_IPV6_ONLY:
2439                 protoFilter = EpdgSelector.PROTO_FILTER_IPV6;
2440                 break;
2441             case CarrierConfigManager.Iwlan.EPDG_ADDRESS_SYSTEM_PREFERRED:
2442                 break;
2443             default:
2444                 Log.w(TAG, "Invalid Ip preference : " + ipPreference);
2445         }
2446 
2447         EpdgSelector epdgSelector = getEpdgSelector();
2448         IwlanError epdgError =
2449                 epdgSelector.getValidatedServerList(
2450                         mTransactionId,
2451                         protoFilter,
2452                         epdgAddressOrder,
2453                         setupRequest.isRoaming(),
2454                         setupRequest.isEmergency(),
2455                         mDefaultNetwork,
2456                         mSelectorCallback);
2457 
2458         if (epdgError.getErrorType() != IwlanError.NO_ERROR) {
2459             Log.e(TAG, "Epdg address selection failed with error:" + epdgError);
2460             sendSelectionRequestComplete(null, epdgError, mTransactionId);
2461         }
2462     }
2463 
2464     @VisibleForTesting
getEpdgSelector()2465     EpdgSelector getEpdgSelector() {
2466         return EpdgSelector.getSelectorInstance(mContext, mSlotId);
2467     }
2468 
2469     @VisibleForTesting
closePendingRequestsForApn(String apnName)2470     int closePendingRequestsForApn(String apnName) {
2471         int numRequestsClosed = 0;
2472         int queueSize = mPendingBringUpRequests.size();
2473         if (queueSize == 0) {
2474             return numRequestsClosed;
2475         }
2476 
2477         for (int count = 0; count < queueSize; count++) {
2478             TunnelRequestWrapper requestWrapper = mPendingBringUpRequests.remove();
2479             if (requestWrapper.getSetupRequest().apnName().equals(apnName)) {
2480                 requestWrapper
2481                         .getTunnelCallback()
2482                         .onClosed(apnName, new IwlanError(IwlanError.NO_ERROR));
2483                 requestWrapper
2484                         .getTunnelMetrics()
2485                         .onClosed(
2486                                 new OnClosedMetrics.Builder()
2487                                         .setApnName(apnName)
2488                                         .setEpdgServerAddress(null)
2489                                         .build());
2490                 numRequestsClosed++;
2491             } else {
2492                 mPendingBringUpRequests.add(requestWrapper);
2493             }
2494         }
2495         return numRequestsClosed;
2496     }
2497 
validateAndSetEpdgAddressLegacy(List<InetAddress> selectorResultList)2498     InetAddress validateAndSetEpdgAddressLegacy(List<InetAddress> selectorResultList) {
2499         List<InetAddress> addrList = mValidEpdgInfo.getAddrList();
2500         if (addrList == null || !addrList.equals(selectorResultList)) {
2501             Log.d(TAG, "Update ePDG address list.");
2502             mValidEpdgInfo.setAddrList(selectorResultList);
2503             addrList = mValidEpdgInfo.getAddrList();
2504         }
2505 
2506         int index = mValidEpdgInfo.getIndex();
2507         Log.d(
2508                 TAG,
2509                 "Valid ePDG Address List: "
2510                         + Arrays.toString(addrList.toArray())
2511                         + ", index = "
2512                         + index);
2513         mValidEpdgInfo.incrementIndex();
2514         return addrList.get(index);
2515     }
2516 
2517     @VisibleForTesting
validateAndSetEpdgAddress(List<InetAddress> selectorResultList)2518     InetAddress validateAndSetEpdgAddress(List<InetAddress> selectorResultList) {
2519         if (!mFeatureFlags.epdgSelectionExcludeFailedIpAddress()) {
2520             return validateAndSetEpdgAddressLegacy(selectorResultList);
2521         }
2522 
2523         if (mEpdgMonitor.hasEmergencyPdnFailedWithConnectedEpdg()
2524                 && selectorResultList
2525                         .get(0)
2526                         .equals(mEpdgMonitor.getEpdgAddressForNormalSession())) {
2527             List<InetAddress> sublist = selectorResultList.subList(1, selectorResultList.size());
2528             Log.d(
2529                     TAG,
2530                     "Selected separate ePDG address for emergency session "
2531                             + sublist.get(0)
2532                             + " from available ePDG address list: "
2533                             + Arrays.toString(selectorResultList.toArray()));
2534             mValidEpdgInfo.setAddrList(sublist);
2535             return sublist.get(0);
2536         }
2537 
2538         Log.d(
2539                 TAG,
2540                 "Selected first ePDG address "
2541                         + selectorResultList.get(0)
2542                         + " from available ePDG address list: "
2543                         + Arrays.toString(selectorResultList.toArray()));
2544         mValidEpdgInfo.setAddrList(selectorResultList);
2545         return selectorResultList.get(0);
2546     }
2547 
serviceAllPendingRequests()2548     private void serviceAllPendingRequests() {
2549         while (!mPendingBringUpRequests.isEmpty()) {
2550             Log.d(TAG, "serviceAllPendingRequests");
2551             TunnelRequestWrapper requestWrapper = mPendingBringUpRequests.remove();
2552             onBringUpTunnel(requestWrapper, mEpdgMonitor.getEpdgAddressForNormalSession());
2553         }
2554     }
2555 
failAllPendingRequests(IwlanError error)2556     private void failAllPendingRequests(IwlanError error) {
2557         while (!mPendingBringUpRequests.isEmpty()) {
2558             Log.d(TAG, "failAllPendingRequests");
2559             TunnelRequestWrapper request = mPendingBringUpRequests.remove();
2560             TunnelSetupRequest setupRequest = request.getSetupRequest();
2561             String apnName = setupRequest.apnName();
2562             reportIwlanError(apnName, error);
2563             request.getTunnelCallback().onClosed(apnName, error);
2564             request.getTunnelMetrics()
2565                     .onClosed(
2566                             new OnClosedMetrics.Builder()
2567                                     .setApnName(apnName)
2568                                     .setEpdgServerAddress(null)
2569                                     .build());
2570         }
2571     }
2572 
2573     // Prints mPendingBringUpRequests
printRequestQueue(String info)2574     private void printRequestQueue(String info) {
2575         Log.d(TAG, info);
2576         Log.d(
2577                 TAG,
2578                 "mPendingBringUpRequests: " + Arrays.toString(mPendingBringUpRequests.toArray()));
2579     }
2580 
2581     // Update Network wrapper
2582     private static final class UpdateNetworkWrapper {
2583         private final Network mNetwork;
2584         private final LinkProperties mLinkProperties;
2585 
UpdateNetworkWrapper(Network network, LinkProperties linkProperties)2586         private UpdateNetworkWrapper(Network network, LinkProperties linkProperties) {
2587             mNetwork = network;
2588             mLinkProperties = linkProperties;
2589         }
2590 
getNetwork()2591         public Network getNetwork() {
2592             return mNetwork;
2593         }
2594 
getLinkProperties()2595         public LinkProperties getLinkProperties() {
2596             return mLinkProperties;
2597         }
2598     }
2599 
2600     // Tunnel request + tunnel callback
2601     private static final class TunnelRequestWrapper {
2602         private final TunnelSetupRequest mSetupRequest;
2603         private final TunnelCallback mTunnelCallback;
2604         private final TunnelMetricsInterface mTunnelMetrics;
2605 
TunnelRequestWrapper( TunnelSetupRequest setupRequest, TunnelCallback tunnelCallback, TunnelMetricsInterface tunnelMetrics)2606         private TunnelRequestWrapper(
2607                 TunnelSetupRequest setupRequest,
2608                 TunnelCallback tunnelCallback,
2609                 TunnelMetricsInterface tunnelMetrics) {
2610             mTunnelCallback = tunnelCallback;
2611             mSetupRequest = setupRequest;
2612             mTunnelMetrics = tunnelMetrics;
2613         }
2614 
getSetupRequest()2615         public TunnelSetupRequest getSetupRequest() {
2616             return mSetupRequest;
2617         }
2618 
getTunnelCallback()2619         public TunnelCallback getTunnelCallback() {
2620             return mTunnelCallback;
2621         }
2622 
getTunnelMetrics()2623         public TunnelMetricsInterface getTunnelMetrics() {
2624             return mTunnelMetrics;
2625         }
2626     }
2627 
2628     private static final class TunnelBringdownRequest {
2629         final String mApnName;
2630         final boolean mForceClose;
2631         final TunnelCallback mTunnelCallback;
2632         final IwlanTunnelMetricsImpl mIwlanTunnelMetrics;
2633         final int mBringDownReason;
2634 
TunnelBringdownRequest( String apnName, boolean forceClose, TunnelCallback tunnelCallback, IwlanTunnelMetricsImpl iwlanTunnelMetrics, @TunnelBringDownReason int reason)2635         private TunnelBringdownRequest(
2636                 String apnName,
2637                 boolean forceClose,
2638                 TunnelCallback tunnelCallback,
2639                 IwlanTunnelMetricsImpl iwlanTunnelMetrics,
2640                 @TunnelBringDownReason int reason) {
2641             mApnName = apnName;
2642             mForceClose = forceClose;
2643             mTunnelCallback = tunnelCallback;
2644             mIwlanTunnelMetrics = iwlanTunnelMetrics;
2645             mBringDownReason = reason;
2646         }
2647     }
2648 
2649     private static final class EpdgSelectorResult {
2650         private final List<InetAddress> mValidIpList;
2651 
getValidIpList()2652         public List<InetAddress> getValidIpList() {
2653             return mValidIpList;
2654         }
2655 
getEpdgError()2656         public IwlanError getEpdgError() {
2657             return mEpdgError;
2658         }
2659 
getTransactionId()2660         public int getTransactionId() {
2661             return mTransactionId;
2662         }
2663 
2664         private final IwlanError mEpdgError;
2665         private final int mTransactionId;
2666 
EpdgSelectorResult( List<InetAddress> validIpList, IwlanError epdgError, int transactionId)2667         private EpdgSelectorResult(
2668                 List<InetAddress> validIpList, IwlanError epdgError, int transactionId) {
2669             mValidIpList = validIpList;
2670             mEpdgError = epdgError;
2671             mTransactionId = transactionId;
2672         }
2673     }
2674 
2675     // Data received from IkeSessionStateMachine on successful EVENT_CHILD_SESSION_OPENED.
2676     private static final class TunnelOpenedData extends IkeEventData {
2677         final List<InetAddress> mInternalDnsServers;
2678         final List<LinkAddress> mInternalAddresses;
2679 
TunnelOpenedData( String apnName, int token, List<InetAddress> internalDnsServers, List<LinkAddress> internalAddresses)2680         private TunnelOpenedData(
2681                 String apnName,
2682                 int token,
2683                 List<InetAddress> internalDnsServers,
2684                 List<LinkAddress> internalAddresses) {
2685             super(apnName, token);
2686             mInternalDnsServers = internalDnsServers;
2687             mInternalAddresses = internalAddresses;
2688         }
2689     }
2690 
2691     // Data received from IkeSessionStateMachine on successful EVENT_IKE_SESSION_OPENED.
2692     private static final class IkeSessionOpenedData extends IkeEventData {
2693         final IkeSessionConfiguration mIkeSessionConfiguration;
2694 
IkeSessionOpenedData( String apnName, int token, IkeSessionConfiguration ikeSessionConfiguration)2695         private IkeSessionOpenedData(
2696                 String apnName, int token, IkeSessionConfiguration ikeSessionConfiguration) {
2697             super(apnName, token);
2698             mIkeSessionConfiguration = ikeSessionConfiguration;
2699         }
2700     }
2701 
2702     private static final class IkeSessionConnectionInfoData extends IkeEventData {
2703         final IkeSessionConnectionInfo mIkeSessionConnectionInfo;
2704 
IkeSessionConnectionInfoData( String apnName, int token, IkeSessionConnectionInfo ikeSessionConnectionInfo)2705         private IkeSessionConnectionInfoData(
2706                 String apnName, int token, IkeSessionConnectionInfo ikeSessionConnectionInfo) {
2707             super(apnName, token);
2708             mIkeSessionConnectionInfo = ikeSessionConnectionInfo;
2709         }
2710     }
2711 
2712     private static final class Ike3gppDataReceived extends IkeEventData {
2713         final List<Ike3gppData> mIke3gppData;
2714 
Ike3gppDataReceived(String apnName, int token, List<Ike3gppData> ike3gppData)2715         private Ike3gppDataReceived(String apnName, int token, List<Ike3gppData> ike3gppData) {
2716             super(apnName, token);
2717             mIke3gppData = ike3gppData;
2718         }
2719     }
2720 
2721     // Data received from IkeSessionStateMachine if either IKE session or Child session have been
2722     // closed, normally or exceptionally.
2723     private static final class SessionClosedData extends IkeEventData {
2724         final IkeException mIkeException;
2725 
SessionClosedData(String apnName, int token, IkeException ikeException)2726         private SessionClosedData(String apnName, int token, IkeException ikeException) {
2727             super(apnName, token);
2728             mIkeException = ikeException;
2729         }
2730     }
2731 
2732     private static final class IkeSessionValidationStatusData extends IkeEventData {
2733         @NetworkValidationStatus final int mStatus;
2734 
IkeSessionValidationStatusData(String apnName, int token, int status)2735         private IkeSessionValidationStatusData(String apnName, int token, int status) {
2736             super(apnName, token);
2737             mStatus = status;
2738         }
2739     }
2740 
2741     private static final class IpsecTransformData extends IkeEventData {
2742         private final IpSecTransform mTransform;
2743         private final int mDirection;
2744 
IpsecTransformData( IpSecTransform transform, int direction, String apnName, int token)2745         private IpsecTransformData(
2746                 IpSecTransform transform, int direction, String apnName, int token) {
2747             super(apnName, token);
2748             mTransform = transform;
2749             mDirection = direction;
2750         }
2751 
getTransform()2752         public IpSecTransform getTransform() {
2753             return mTransform;
2754         }
2755 
getDirection()2756         public int getDirection() {
2757             return mDirection;
2758         }
2759 
getApnName()2760         public String getApnName() {
2761             return super.mApnName;
2762         }
2763     }
2764 
2765     private abstract static class IkeEventData {
2766         final String mApnName;
2767         final int mToken;
2768 
IkeEventData(String apnName, int token)2769         private IkeEventData(String apnName, int token) {
2770             mApnName = apnName;
2771             mToken = token;
2772         }
2773     }
2774 
2775     private static final class EpdgInfo {
2776         private List<InetAddress> mAddrList;
2777         private int mIndex;
2778 
EpdgInfo()2779         private EpdgInfo() {
2780             mAddrList = null;
2781             mIndex = 0;
2782         }
2783 
getAddrList()2784         public List<InetAddress> getAddrList() {
2785             return mAddrList;
2786         }
2787 
setAddrList(@onNull List<InetAddress> AddrList)2788         public void setAddrList(@NonNull List<InetAddress> AddrList) {
2789             mAddrList = AddrList;
2790             resetIndex();
2791         }
2792 
getIndex()2793         public int getIndex() {
2794             return mIndex;
2795         }
2796 
incrementIndex()2797         public void incrementIndex() {
2798             if (getIndex() >= getAddrList().size() - 1) {
2799                 resetIndex();
2800             } else {
2801                 mIndex++;
2802             }
2803         }
2804 
resetIndex()2805         public void resetIndex() {
2806             mIndex = 0;
2807         }
2808     }
2809 
2810     private static class IpPreferenceConflict {
2811         final boolean mIsConflict;
2812         final int mErrorType;
2813 
IpPreferenceConflict(boolean isConflict, int errorType)2814         private IpPreferenceConflict(boolean isConflict, int errorType) {
2815             mIsConflict = isConflict;
2816             mErrorType = errorType;
2817         }
2818 
IpPreferenceConflict()2819         private IpPreferenceConflict() {
2820             mIsConflict = false;
2821             mErrorType = IwlanError.NO_ERROR;
2822         }
2823     }
2824 
getRetransmissionTimeoutsFromConfig()2825     private int[] getRetransmissionTimeoutsFromConfig() {
2826         int[] timeList =
2827                 IwlanCarrierConfig.getConfigIntArray(
2828                         mContext,
2829                         mSlotId,
2830                         CarrierConfigManager.Iwlan.KEY_RETRANSMIT_TIMER_MSEC_INT_ARRAY);
2831         boolean isValid =
2832                 timeList != null
2833                         && timeList.length != 0
2834                         && timeList.length <= IKE_RETRANS_MAX_ATTEMPTS_MAX;
2835         for (int time : Objects.requireNonNull(timeList)) {
2836             if (time < IKE_RETRANS_TIMEOUT_MS_MIN || time > IKE_RETRANS_TIMEOUT_MS_MAX) {
2837                 isValid = false;
2838                 break;
2839             }
2840         }
2841         if (!isValid) {
2842             timeList =
2843                     IwlanCarrierConfig.getDefaultConfigIntArray(
2844                             CarrierConfigManager.Iwlan.KEY_RETRANSMIT_TIMER_MSEC_INT_ARRAY);
2845         }
2846         Log.d(TAG, "getRetransmissionTimeoutsFromConfig: " + Arrays.toString(timeList));
2847         return timeList;
2848     }
2849 
getDpdDelayFromConfig()2850     private int getDpdDelayFromConfig() {
2851         int dpdDelay =
2852                 IwlanCarrierConfig.getConfigInt(
2853                         mContext, mSlotId, CarrierConfigManager.Iwlan.KEY_DPD_TIMER_SEC_INT);
2854         if (dpdDelay < IKE_DPD_DELAY_SEC_MIN || dpdDelay > IKE_DPD_DELAY_SEC_MAX) {
2855             dpdDelay =
2856                     IwlanCarrierConfig.getDefaultConfigInt(
2857                             CarrierConfigManager.Iwlan.KEY_DPD_TIMER_SEC_INT);
2858         }
2859         return dpdDelay;
2860     }
2861 
2862     /**
2863      * Decodes backoff time as per TS 124 008 10.5.7.4a Bits 5 to 1 represent the binary coded timer
2864      * value
2865      *
2866      * <p>Bits 6 to 8 defines the timer value unit for the GPRS timer as follows: Bits 8 7 6 0 0 0
2867      * value is incremented in multiples of 10 minutes 0 0 1 value is incremented in multiples of 1
2868      * hour 0 1 0 value is incremented in multiples of 10 hours 0 1 1 value is incremented in
2869      * multiples of 2 seconds 1 0 0 value is incremented in multiples of 30 seconds 1 0 1 value is
2870      * incremented in multiples of 1 minute 1 1 0 value is incremented in multiples of 1 hour 1 1 1
2871      * value indicates that the timer is deactivated.
2872      *
2873      * @param backoffTimeByte Byte value obtained from ike
2874      * @return long time value in seconds. -1 if the timer needs to be deactivated.
2875      */
decodeBackoffTime(byte backoffTimeByte)2876     private static long decodeBackoffTime(byte backoffTimeByte) {
2877         final int BACKOFF_TIME_VALUE_MASK = 0x1F;
2878         final int BACKOFF_TIMER_UNIT_MASK = 0xE0;
2879         final Long[] BACKOFF_TIMER_UNIT_INCREMENT_SECS = {
2880             10L * 60L, // 10 minutes
2881             60L * 60L, // 1 hour
2882             10L * 60L * 60L, // 10 hours
2883             2L, // 2 seconds
2884             30L, // 30 seconds
2885             60L, // 1 minute
2886             60L * 60L, // 1 hour
2887         };
2888 
2889         long time = backoffTimeByte & BACKOFF_TIME_VALUE_MASK;
2890         int timerUnit = (backoffTimeByte & BACKOFF_TIMER_UNIT_MASK) >> 5;
2891         if (timerUnit >= BACKOFF_TIMER_UNIT_INCREMENT_SECS.length) {
2892             return -1;
2893         }
2894         time *= BACKOFF_TIMER_UNIT_INCREMENT_SECS[timerUnit];
2895         return time;
2896     }
2897 
2898     @VisibleForTesting
getTunnelSetupRequestApnName(TunnelSetupRequest setupRequest)2899     String getTunnelSetupRequestApnName(TunnelSetupRequest setupRequest) {
2900         return setupRequest.apnName();
2901     }
2902 
2903     @VisibleForTesting
putApnNameToTunnelConfig( String apnName, IkeSession ikeSession, TunnelCallback tunnelCallback, TunnelMetricsInterface tunnelMetrics, IpSecManager.IpSecTunnelInterface iface, InetAddress srcIpv6Addr, int srcIPv6AddrPrefixLen, boolean isEmergency, InetAddress epdgAddress)2904     void putApnNameToTunnelConfig(
2905             String apnName,
2906             IkeSession ikeSession,
2907             TunnelCallback tunnelCallback,
2908             TunnelMetricsInterface tunnelMetrics,
2909             IpSecManager.IpSecTunnelInterface iface,
2910             InetAddress srcIpv6Addr,
2911             int srcIPv6AddrPrefixLen,
2912             boolean isEmergency,
2913             InetAddress epdgAddress) {
2914         mApnNameToTunnelConfig.put(
2915                 apnName,
2916                 new TunnelConfig(
2917                         ikeSession,
2918                         tunnelCallback,
2919                         tunnelMetrics,
2920                         iface,
2921                         srcIpv6Addr,
2922                         srcIPv6AddrPrefixLen,
2923                         isEmergency,
2924                         epdgAddress));
2925         Log.d(TAG, "Added APN: " + apnName + " to TunnelConfig");
2926     }
2927 
2928     @VisibleForTesting
incrementAndGetCurrentTokenForApn(String apnName)2929     int incrementAndGetCurrentTokenForApn(String apnName) {
2930         final int currentToken =
2931                 mApnNameToCurrentToken.compute(
2932                         apnName, (apn, token) -> token == null ? 0 : token + 1);
2933         Log.d(TAG, "Added token: " + currentToken + " for apn: " + apnName);
2934         return currentToken;
2935     }
2936 
2937     @VisibleForTesting
isTunnelConfigContainExistApn(String apnName)2938     boolean isTunnelConfigContainExistApn(String apnName) {
2939         return mApnNameToTunnelConfig.containsKey(apnName);
2940     }
2941 
2942     @VisibleForTesting
getAddressForNetwork(Network network)2943     List<InetAddress> getAddressForNetwork(Network network) {
2944         return IwlanHelper.getAllAddressesForNetwork(mContext, network);
2945     }
2946 
2947     @VisibleForTesting
getIkeSessionCreator()2948     IkeSessionCreator getIkeSessionCreator() {
2949         return mIkeSessionCreator;
2950     }
2951 
2952     @VisibleForTesting
sendSelectionRequestComplete( List<InetAddress> validIPList, IwlanError result, int transactionId)2953     void sendSelectionRequestComplete(
2954             List<InetAddress> validIPList, IwlanError result, int transactionId) {
2955         mEpdgServerSelectionDuration = System.currentTimeMillis() - mEpdgServerSelectionStartTime;
2956         mEpdgServerSelectionStartTime = 0;
2957         EpdgSelectorResult epdgSelectorResult =
2958                 new EpdgSelectorResult(validIPList, result, transactionId);
2959         mHandler.sendMessage(
2960                 mHandler.obtainMessage(
2961                         EVENT_EPDG_ADDRESS_SELECTION_REQUEST_COMPLETE, epdgSelectorResult));
2962     }
2963 
isValidApnProtocol(int proto)2964     static boolean isValidApnProtocol(int proto) {
2965         return (proto == ApnSetting.PROTOCOL_IP
2966                 || proto == ApnSetting.PROTOCOL_IPV4V6
2967                 || proto == ApnSetting.PROTOCOL_IPV6);
2968     }
2969 
isObsoleteToken(String apnName, int token)2970     boolean isObsoleteToken(String apnName, int token) {
2971         if (!mApnNameToCurrentToken.containsKey(apnName)) {
2972             return true;
2973         }
2974         return token != mApnNameToCurrentToken.get(apnName);
2975     }
2976 
eventToString(int event)2977     private static String eventToString(int event) {
2978         switch (event) {
2979             case EVENT_TUNNEL_BRINGUP_REQUEST:
2980                 return "EVENT_TUNNEL_BRINGUP_REQUEST";
2981             case EVENT_TUNNEL_BRINGDOWN_REQUEST:
2982                 return "EVENT_TUNNEL_BRINGDOWN_REQUEST";
2983             case EVENT_CHILD_SESSION_OPENED:
2984                 return "EVENT_CHILD_SESSION_OPENED";
2985             case EVENT_CHILD_SESSION_CLOSED:
2986                 return "EVENT_CHILD_SESSION_CLOSED";
2987             case EVENT_IKE_SESSION_CLOSED:
2988                 return "EVENT_IKE_SESSION_CLOSED";
2989             case EVENT_EPDG_ADDRESS_SELECTION_REQUEST_COMPLETE:
2990                 return "EVENT_EPDG_ADDRESS_SELECTION_REQUEST_COMPLETE";
2991             case EVENT_IPSEC_TRANSFORM_CREATED:
2992                 return "EVENT_IPSEC_TRANSFORM_CREATED";
2993             case EVENT_IPSEC_TRANSFORM_DELETED:
2994                 return "EVENT_IPSEC_TRANSFORM_DELETED";
2995             case EVENT_UPDATE_NETWORK:
2996                 return "EVENT_UPDATE_NETWORK";
2997             case EVENT_IKE_SESSION_OPENED:
2998                 return "EVENT_IKE_SESSION_OPENED";
2999             case EVENT_IKE_SESSION_CONNECTION_INFO_CHANGED:
3000                 return "EVENT_IKE_SESSION_CONNECTION_INFO_CHANGED";
3001             case EVENT_IKE_3GPP_DATA_RECEIVED:
3002                 return "EVENT_IKE_3GPP_DATA_RECEIVED";
3003             case EVENT_IKE_LIVENESS_STATUS_CHANGED:
3004                 return "EVENT_IKE_LIVENESS_STATUS_CHANGED";
3005             case EVENT_REQUEST_NETWORK_VALIDATION_CHECK:
3006                 return "EVENT_REQUEST_NETWORK_VALIDATION_CHECK";
3007             default:
3008                 return "Unknown(" + event + ")";
3009         }
3010     }
3011 
3012     @VisibleForTesting
getTmIkeSessionCallback(String apnName, int token)3013     TmIkeSessionCallback getTmIkeSessionCallback(String apnName, int token) {
3014         return new TmIkeSessionCallback(apnName, token);
3015     }
3016 
3017     @VisibleForTesting
onConnectedToEpdg(boolean hasConnected)3018     void onConnectedToEpdg(boolean hasConnected) {
3019         mHasConnectedToEpdg = hasConnected;
3020         if (mHasConnectedToEpdg) {
3021             mIkeSessionNetwork = mDefaultNetwork;
3022         } else {
3023             mIkeSessionNetwork = null;
3024         }
3025     }
3026 
3027     @VisibleForTesting
getTunnelConfigForApn(String apnName)3028     TunnelConfig getTunnelConfigForApn(String apnName) {
3029         return mApnNameToTunnelConfig.get(apnName);
3030     }
3031 
3032     @VisibleForTesting
getCurrentTokenForApn(String apnName)3033     int getCurrentTokenForApn(String apnName) {
3034         if (!mApnNameToCurrentToken.containsKey(apnName)) {
3035             throw new IllegalArgumentException("There is no token for apn: " + apnName);
3036         }
3037         return mApnNameToCurrentToken.get(apnName);
3038     }
3039 
3040     @VisibleForTesting
reportIwlanError(String apnName, IwlanError error)3041     long reportIwlanError(String apnName, IwlanError error) {
3042         return ErrorPolicyManager.getInstance(mContext, mSlotId).reportIwlanError(apnName, error);
3043     }
3044 
3045     @VisibleForTesting
reportIwlanError(String apnName, IwlanError error, long backOffTime)3046     long reportIwlanError(String apnName, IwlanError error, long backOffTime) {
3047         return ErrorPolicyManager.getInstance(mContext, mSlotId)
3048                 .reportIwlanError(apnName, error, backOffTime);
3049     }
3050 
3051     @VisibleForTesting
getLastError(String apnName)3052     IwlanError getLastError(String apnName) {
3053         return ErrorPolicyManager.getInstance(mContext, mSlotId).getLastError(apnName);
3054     }
3055 
3056     @VisibleForTesting
canBringUpTunnel(String apnName, boolean isEmergency)3057     IwlanError canBringUpTunnel(String apnName, boolean isEmergency) {
3058         IwlanError bringUpError = null;
3059         if (IwlanHelper.getSubId(mContext, mSlotId)
3060                 == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
3061             Log.e(TAG, "SIM isn't ready");
3062             bringUpError = new IwlanError(IwlanError.SIM_NOT_READY_EXCEPTION);
3063             reportIwlanError(apnName, bringUpError);
3064         } else if (Objects.isNull(mDefaultNetwork)) {
3065             Log.e(TAG, "The default network is not ready");
3066             bringUpError = new IwlanError(IwlanError.IKE_INTERNAL_IO_EXCEPTION);
3067             reportIwlanError(apnName, bringUpError);
3068         } else if (!isEmergency
3069                 && !ErrorPolicyManager.getInstance(mContext, mSlotId).canBringUpTunnel(apnName)) {
3070             // TODO(b/343962773): Need to refactor emergency condition into ErrorPolicyManager
3071             Log.d(TAG, "Cannot bring up tunnel as retry time has not passed");
3072             bringUpError = getLastError(apnName);
3073         }
3074         return bringUpError;
3075     }
3076 
3077     @VisibleForTesting
isIpPreferenceConflictsWithNetwork( @arrierConfigManager.Iwlan.EpdgAddressIpPreference int ipPreference)3078     IpPreferenceConflict isIpPreferenceConflictsWithNetwork(
3079             @CarrierConfigManager.Iwlan.EpdgAddressIpPreference int ipPreference) {
3080         List<InetAddress> localAddresses = getAddressForNetwork(mDefaultNetwork);
3081         if (localAddresses == null || localAddresses.size() == 0) {
3082             Log.e(TAG, "No local addresses available for Network " + mDefaultNetwork);
3083             return new IpPreferenceConflict(true, IwlanError.EPDG_SELECTOR_SERVER_SELECTION_FAILED);
3084         } else if (!IwlanHelper.hasIpv6Address(localAddresses)
3085                 && ipPreference == CarrierConfigManager.Iwlan.EPDG_ADDRESS_IPV6_ONLY) {
3086             Log.e(
3087                     TAG,
3088                     "ePDG IP preference: "
3089                             + ipPreference
3090                             + " conflicts with source IP type: "
3091                             + EpdgSelector.PROTO_FILTER_IPV4);
3092             return new IpPreferenceConflict(true, IwlanError.EPDG_ADDRESS_ONLY_IPV6_ALLOWED);
3093         } else if (!IwlanHelper.hasIpv4Address(localAddresses)
3094                 && ipPreference == CarrierConfigManager.Iwlan.EPDG_ADDRESS_IPV4_ONLY) {
3095             // b/209938719 allows Iwlan to support VoWiFi for IPv4 ePDG server while on IPv6 WiFi.
3096             // Iwlan will receive a IPv4 address which is embedded in stacked IPv6 address. By using
3097             // this IPv4 address, UE will connect to IPv4 ePDG server through XLAT. However, there
3098             // are issues on connecting ePDG server through XLAT. Will allow IPV4_ONLY on IPv6 WiFi
3099             // after the issues are resolved.
3100             Log.e(
3101                     TAG,
3102                     "ePDG IP preference: "
3103                             + ipPreference
3104                             + " conflicts with source IP type: "
3105                             + EpdgSelector.PROTO_FILTER_IPV6);
3106             return new IpPreferenceConflict(true, IwlanError.EPDG_ADDRESS_ONLY_IPV4_ALLOWED);
3107         }
3108         return new IpPreferenceConflict();
3109     }
3110 
3111     /**
3112      * Performs network validation check
3113      *
3114      * @param apnName APN for which to perform validation check
3115      */
requestNetworkValidationForApn(String apnName)3116     public void requestNetworkValidationForApn(String apnName) {
3117         mHandler.obtainMessage(EVENT_REQUEST_NETWORK_VALIDATION_CHECK, apnName).sendToTarget();
3118     }
3119 
3120     @VisibleForTesting
removeApnNameInTunnelConfig(String apnName)3121     protected void removeApnNameInTunnelConfig(String apnName) {
3122         mApnNameToTunnelConfig.remove(apnName);
3123     }
3124 
dump(PrintWriter pw)3125     public void dump(PrintWriter pw) {
3126         pw.println("---- EpdgTunnelManager ----");
3127         pw.println(
3128                 "Has ePDG connected for normal session: "
3129                         + mEpdgMonitor.hasEpdgConnectedForNormalSession());
3130         pw.println(
3131                 "Has Separate ePDG connected for emergency session: "
3132                         + mEpdgMonitor.hasSeparateEpdgConnectedForEmergencySession());
3133         pw.println("mIkeSessionNetwork: " + mIkeSessionNetwork);
3134         if (mEpdgMonitor.getEpdgAddressForNormalSession() != null) {
3135             pw.println(
3136                     "EpdgAddressForNormalSession: "
3137                             + mEpdgMonitor.getEpdgAddressForNormalSession());
3138         }
3139         if (mEpdgMonitor.getEpdgAddressForEmergencySession() != null) {
3140             pw.println(
3141                     "SeparateEpdgAddressForEmergencySession: "
3142                             + mEpdgMonitor.getEpdgAddressForEmergencySession());
3143         }
3144         pw.println("mApnNameToTunnelConfig:\n");
3145         for (Map.Entry<String, TunnelConfig> entry : mApnNameToTunnelConfig.entrySet()) {
3146             pw.println("APN: " + entry.getKey());
3147             pw.println("TunnelConfig: " + entry.getValue());
3148             pw.println();
3149         }
3150         pw.println("---------------------------");
3151     }
3152 }
3153