• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.system.OsConstants.AF_INET;
22 import static android.system.OsConstants.AF_INET6;
23 
24 import android.content.Context;
25 import android.net.ConnectivityManager;
26 import android.net.InetAddresses;
27 import android.net.IpPrefix;
28 import android.net.IpSecManager;
29 import android.net.IpSecTransform;
30 import android.net.LinkAddress;
31 import android.net.Network;
32 import android.net.eap.EapAkaInfo;
33 import android.net.eap.EapInfo;
34 import android.net.eap.EapSessionConfig;
35 import android.net.ipsec.ike.ChildSaProposal;
36 import android.net.ipsec.ike.ChildSessionCallback;
37 import android.net.ipsec.ike.ChildSessionConfiguration;
38 import android.net.ipsec.ike.ChildSessionParams;
39 import android.net.ipsec.ike.IkeFqdnIdentification;
40 import android.net.ipsec.ike.IkeIdentification;
41 import android.net.ipsec.ike.IkeKeyIdIdentification;
42 import android.net.ipsec.ike.IkeRfc822AddrIdentification;
43 import android.net.ipsec.ike.IkeSaProposal;
44 import android.net.ipsec.ike.IkeSession;
45 import android.net.ipsec.ike.IkeSessionCallback;
46 import android.net.ipsec.ike.IkeSessionConfiguration;
47 import android.net.ipsec.ike.IkeSessionConnectionInfo;
48 import android.net.ipsec.ike.IkeSessionParams;
49 import android.net.ipsec.ike.IkeTrafficSelector;
50 import android.net.ipsec.ike.SaProposal;
51 import android.net.ipsec.ike.TunnelModeChildSessionParams;
52 import android.net.ipsec.ike.exceptions.IkeException;
53 import android.net.ipsec.ike.exceptions.IkeProtocolException;
54 import android.net.ipsec.ike.ike3gpp.Ike3gppBackoffTimer;
55 import android.net.ipsec.ike.ike3gpp.Ike3gppData;
56 import android.net.ipsec.ike.ike3gpp.Ike3gppExtension;
57 import android.net.ipsec.ike.ike3gpp.Ike3gppN1ModeInformation;
58 import android.net.ipsec.ike.ike3gpp.Ike3gppParams;
59 import android.os.Handler;
60 import android.os.HandlerThread;
61 import android.os.Looper;
62 import android.os.Message;
63 import android.support.annotation.NonNull;
64 import android.support.annotation.Nullable;
65 import android.telephony.CarrierConfigManager;
66 import android.telephony.SubscriptionManager;
67 import android.telephony.TelephonyManager;
68 import android.telephony.data.ApnSetting;
69 import android.telephony.data.NetworkSliceInfo;
70 import android.util.Log;
71 
72 import com.android.internal.annotations.VisibleForTesting;
73 
74 import com.google.android.iwlan.ErrorPolicyManager;
75 import com.google.android.iwlan.IwlanError;
76 import com.google.android.iwlan.IwlanHelper;
77 import com.google.android.iwlan.exceptions.IwlanSimNotReadyException;
78 
79 import java.io.FileDescriptor;
80 import java.io.IOException;
81 import java.io.PrintWriter;
82 import java.net.Inet4Address;
83 import java.net.Inet6Address;
84 import java.net.InetAddress;
85 import java.nio.charset.StandardCharsets;
86 import java.util.ArrayList;
87 import java.util.Arrays;
88 import java.util.Collections;
89 import java.util.HashSet;
90 import java.util.LinkedList;
91 import java.util.List;
92 import java.util.Map;
93 import java.util.Queue;
94 import java.util.Set;
95 import java.util.concurrent.ConcurrentHashMap;
96 import java.util.concurrent.Executor;
97 import java.util.concurrent.Executors;
98 import java.util.concurrent.TimeUnit;
99 
100 public class EpdgTunnelManager {
101 
102     private Context mContext;
103     private final int mSlotId;
104     private HandlerThread mHandlerThread;
105     private Handler mHandler;
106 
107     private static final int EVENT_TUNNEL_BRINGUP_REQUEST = 0;
108     private static final int EVENT_TUNNEL_BRINGDOWN_REQUEST = 1;
109     private static final int EVENT_CHILD_SESSION_OPENED = 2;
110     private static final int EVENT_CHILD_SESSION_CLOSED = 3;
111     private static final int EVENT_IKE_SESSION_CLOSED = 5;
112     private static final int EVENT_EPDG_ADDRESS_SELECTION_REQUEST_COMPLETE = 6;
113     private static final int EVENT_IPSEC_TRANSFORM_CREATED = 7;
114     private static final int EVENT_IPSEC_TRANSFORM_DELETED = 8;
115     private static final int EVENT_UPDATE_NETWORK = 9;
116     private static final int EVENT_IKE_SESSION_OPENED = 10;
117     private static final int EVENT_IKE_SESSION_CONNECTION_INFO_CHANGED = 11;
118     private static final int IKE_HARD_LIFETIME_SEC_MINIMUM = 300;
119     private static final int IKE_HARD_LIFETIME_SEC_MAXIMUM = 86400;
120     private static final int IKE_SOFT_LIFETIME_SEC_MINIMUM = 120;
121     private static final int CHILD_HARD_LIFETIME_SEC_MINIMUM = 300;
122     private static final int CHILD_HARD_LIFETIME_SEC_MAXIMUM = 14400;
123     private static final int CHILD_SOFT_LIFETIME_SEC_MINIMUM = 120;
124     private static final int LIFETIME_MARGIN_SEC_MINIMUM = (int) TimeUnit.MINUTES.toSeconds(1L);
125     private static final int IKE_RETRANS_TIMEOUT_MS_MIN = 500;
126 
127     private static final int IKE_RETRANS_TIMEOUT_MS_MAX = (int) TimeUnit.MINUTES.toMillis(30L);
128 
129     private static final int IKE_RETRANS_MAX_ATTEMPTS_MAX = 10;
130     private static final int IKE_DPD_DELAY_SEC_MIN = 20;
131     private static final int IKE_DPD_DELAY_SEC_MAX = 1800; // 30 minutes
132     private static final int NATT_KEEPALIVE_DELAY_SEC_MIN = 10;
133     private static final int NATT_KEEPALIVE_DELAY_SEC_MAX = 120;
134 
135     private static final int DEVICE_IMEI_LEN = 15;
136     private static final int DEVICE_IMEISV_SUFFIX_LEN = 2;
137 
138     private static final int TRAFFIC_SELECTOR_START_PORT = 0;
139     private static final int TRAFFIC_SELECTOR_END_PORT = 65535;
140     private static final String TRAFFIC_SELECTOR_IPV4_START_ADDR = "0.0.0.0";
141     private static final String TRAFFIC_SELECTOR_IPV4_END_ADDR = "255.255.255.255";
142     private static final String TRAFFIC_SELECTOR_IPV6_START_ADDR = "::";
143     private static final String TRAFFIC_SELECTOR_IPV6_END_ADDR =
144             "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
145 
146     private static Map<Integer, EpdgTunnelManager> mTunnelManagerInstances =
147             new ConcurrentHashMap<>();
148 
149     private Queue<TunnelRequestWrapper> mPendingBringUpRequests = new LinkedList<>();
150 
151     private EpdgInfo mValidEpdgInfo = new EpdgInfo();
152     private InetAddress mEpdgAddress;
153     private Network mNetwork;
154     private int mTransactionId = 0;
155     private int mProtoFilter = EpdgSelector.PROTO_FILTER_IPV4V6;
156     private boolean mIsEpdgAddressSelected;
157     private IkeSessionCreator mIkeSessionCreator;
158 
159     private Map<String, TunnelConfig> mApnNameToTunnelConfig = new ConcurrentHashMap<>();
160     private Map<String, Integer> mApnNameToCurrentToken = new ConcurrentHashMap<>();
161 
162     private final String TAG;
163 
164     private List<InetAddress> mLocalAddresses;
165 
166     @Nullable private byte[] mNextReauthId = null;
167     private long mEpdgServerSelectionDuration = 0;
168     private long mEpdgServerSelectionStartTime = 0;
169     private long mIkeTunnelEstablishmentDuration = 0;
170     private long mIkeTunnelEstablishmentStartTime = 0;
171 
172     private static final Set<Integer> VALID_DH_GROUPS;
173     private static final Set<Integer> VALID_KEY_LENGTHS;
174     private static final Set<Integer> VALID_PRF_ALGOS;
175     private static final Set<Integer> VALID_INTEGRITY_ALGOS;
176     private static final Set<Integer> VALID_ENCRYPTION_ALGOS;
177 
178     private static final String CONFIG_TYPE_DH_GROUP = "dh group";
179     private static final String CONFIG_TYPE_KEY_LEN = "alogrithm key length";
180     private static final String CONFIG_TYPE_PRF_ALGO = "prf algorithm";
181     private static final String CONFIG_TYPE_INTEGRITY_ALGO = "integrity algorithm";
182     private static final String CONFIG_TYPE_ENCRYPT_ALGO = "encryption algorithm";
183 
184     static {
185         VALID_DH_GROUPS =
186                 Collections.unmodifiableSet(
187                         new HashSet<>(
188                                 Arrays.asList(
189                                         SaProposal.DH_GROUP_1024_BIT_MODP,
190                                         SaProposal.DH_GROUP_1536_BIT_MODP,
191                                         SaProposal.DH_GROUP_2048_BIT_MODP)));
192         VALID_KEY_LENGTHS =
193                 Collections.unmodifiableSet(
194                         new HashSet<>(
195                                 Arrays.asList(
196                                         SaProposal.KEY_LEN_AES_128,
197                                         SaProposal.KEY_LEN_AES_192,
198                                         SaProposal.KEY_LEN_AES_256)));
199 
200         VALID_ENCRYPTION_ALGOS =
201                 Collections.unmodifiableSet(
202                         new HashSet<>(
203                                 Arrays.asList(
204                                         SaProposal.ENCRYPTION_ALGORITHM_AES_CBC,
205                                         SaProposal.ENCRYPTION_ALGORITHM_AES_CTR)));
206 
207         VALID_INTEGRITY_ALGOS =
208                 Collections.unmodifiableSet(
209                         new HashSet<>(
210                                 Arrays.asList(
211                                         SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96,
212                                         SaProposal.INTEGRITY_ALGORITHM_AES_XCBC_96,
213                                         SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_256_128,
214                                         SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_384_192,
215                                         SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_512_256)));
216 
217         VALID_PRF_ALGOS =
218                 Collections.unmodifiableSet(
219                         new HashSet<>(
220                                 Arrays.asList(
221                                         SaProposal.PSEUDORANDOM_FUNCTION_HMAC_SHA1,
222                                         SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC,
223                                         SaProposal.PSEUDORANDOM_FUNCTION_SHA2_256,
224                                         SaProposal.PSEUDORANDOM_FUNCTION_SHA2_384,
225                                         SaProposal.PSEUDORANDOM_FUNCTION_SHA2_512)));
226     }
227 
228     private final EpdgSelector.EpdgSelectorCallback mSelectorCallback =
229             new EpdgSelector.EpdgSelectorCallback() {
230                 @Override
231                 public void onServerListChanged(
232                         int transactionId, ArrayList<InetAddress> validIPList) {
233                     sendSelectionRequestComplete(
234                             validIPList, new IwlanError(IwlanError.NO_ERROR), transactionId);
235                 }
236 
237                 @Override
238                 public void onError(int transactionId, IwlanError epdgSelectorError) {
239                     sendSelectionRequestComplete(null, epdgSelectorError, transactionId);
240                 }
241             };
242 
243     @VisibleForTesting
244     class TunnelConfig {
245         @NonNull final TunnelCallback mTunnelCallback;
246         @NonNull final TunnelCallbackMetrics mTunnelCallbackMetrics;
247         // TODO: Change this to TunnelLinkProperties after removing autovalue
248         private List<InetAddress> mPcscfAddrList;
249         private List<InetAddress> mDnsAddrList;
250         private List<LinkAddress> mInternalAddrList;
251 
252         private InetAddress mSrcIpv6Address;
253         private int mSrcIpv6AddressPrefixLen;
254         private NetworkSliceInfo mSliceInfo;
255         private boolean mIsBackoffTimeValid = false;
256         private long mBackoffTime;
257 
getSliceInfo()258         public NetworkSliceInfo getSliceInfo() {
259             return mSliceInfo;
260         }
261 
setSliceInfo(NetworkSliceInfo si)262         public void setSliceInfo(NetworkSliceInfo si) {
263             mSliceInfo = si;
264         }
265 
isBackoffTimeValid()266         public boolean isBackoffTimeValid() {
267             return mIsBackoffTimeValid;
268         }
269 
getBackoffTime()270         public long getBackoffTime() {
271             return mBackoffTime;
272         }
273 
setBackoffTime(long backoffTime)274         public void setBackoffTime(long backoffTime) {
275             mIsBackoffTimeValid = true;
276             mBackoffTime = backoffTime;
277         }
278 
279         @NonNull final IkeSession mIkeSession;
280         IwlanError mError;
281         private IpSecManager.IpSecTunnelInterface mIface;
282 
TunnelConfig( IkeSession ikeSession, TunnelCallback tunnelCallback, TunnelCallbackMetrics tunnelCallbackMetrics, InetAddress srcIpv6Addr, int srcIpv6PrefixLength)283         public TunnelConfig(
284                 IkeSession ikeSession,
285                 TunnelCallback tunnelCallback,
286                 TunnelCallbackMetrics tunnelCallbackMetrics,
287                 InetAddress srcIpv6Addr,
288                 int srcIpv6PrefixLength) {
289             mTunnelCallback = tunnelCallback;
290             mTunnelCallbackMetrics = tunnelCallbackMetrics;
291             mIkeSession = ikeSession;
292             mError = new IwlanError(IwlanError.NO_ERROR);
293             mSrcIpv6Address = srcIpv6Addr;
294             mSrcIpv6AddressPrefixLen = srcIpv6PrefixLength;
295         }
296 
297         @NonNull
getTunnelCallback()298         TunnelCallback getTunnelCallback() {
299             return mTunnelCallback;
300         }
301 
302         @NonNull
getTunnelCallbackMetrics()303         TunnelCallbackMetrics getTunnelCallbackMetrics() {
304             return mTunnelCallbackMetrics;
305         }
306 
getPcscfAddrList()307         List<InetAddress> getPcscfAddrList() {
308             return mPcscfAddrList;
309         }
310 
setPcscfAddrList(List<InetAddress> pcscfAddrList)311         void setPcscfAddrList(List<InetAddress> pcscfAddrList) {
312             mPcscfAddrList = pcscfAddrList;
313         }
314 
getDnsAddrList()315         public List<InetAddress> getDnsAddrList() {
316             return mDnsAddrList;
317         }
318 
setDnsAddrList(List<InetAddress> dnsAddrList)319         public void setDnsAddrList(List<InetAddress> dnsAddrList) {
320             this.mDnsAddrList = dnsAddrList;
321         }
322 
getInternalAddrList()323         public List<LinkAddress> getInternalAddrList() {
324             return mInternalAddrList;
325         }
326 
isPrefixSameAsSrcIP(LinkAddress laddr)327         boolean isPrefixSameAsSrcIP(LinkAddress laddr) {
328             if (laddr.isIpv6() && (laddr.getPrefixLength() == mSrcIpv6AddressPrefixLen)) {
329                 IpPrefix assignedPrefix = new IpPrefix(laddr.getAddress(), laddr.getPrefixLength());
330                 IpPrefix srcPrefix = new IpPrefix(mSrcIpv6Address, mSrcIpv6AddressPrefixLen);
331                 if (assignedPrefix.equals(srcPrefix)) {
332                     return true;
333                 }
334             }
335             return false;
336         }
337 
setInternalAddrList(List<LinkAddress> internalAddrList)338         public void setInternalAddrList(List<LinkAddress> internalAddrList) {
339             mInternalAddrList = new ArrayList<LinkAddress>(internalAddrList);
340             if (getSrcIpv6Address() != null) {
341                 // check if we can reuse src ipv6 address (i.e if prefix is same)
342                 for (LinkAddress assignedAddr : internalAddrList) {
343                     if (isPrefixSameAsSrcIP(assignedAddr)) {
344                         // the assigned IPv6 address is same as pre-Handover IPv6
345                         // addr. Just reuse the pre-Handover Address so the IID is
346                         // preserved
347                         mInternalAddrList.remove(assignedAddr);
348 
349                         // add original address
350                         mInternalAddrList.add(
351                                 new LinkAddress(mSrcIpv6Address, mSrcIpv6AddressPrefixLen));
352 
353                         Log.d(
354                                 TAG,
355                                 "Network assigned IP replaced OLD:"
356                                         + internalAddrList
357                                         + " NEW:"
358                                         + mInternalAddrList);
359                         break;
360                     }
361                 }
362             }
363         }
364 
365         @NonNull
getIkeSession()366         public IkeSession getIkeSession() {
367             return mIkeSession;
368         }
369 
getError()370         public IwlanError getError() {
371             return mError;
372         }
373 
setError(IwlanError error)374         public void setError(IwlanError error) {
375             this.mError = error;
376         }
377 
getIface()378         public IpSecManager.IpSecTunnelInterface getIface() {
379             return mIface;
380         }
381 
setIface(IpSecManager.IpSecTunnelInterface iface)382         public void setIface(IpSecManager.IpSecTunnelInterface iface) {
383             mIface = iface;
384         }
385 
getSrcIpv6Address()386         public InetAddress getSrcIpv6Address() {
387             return mSrcIpv6Address;
388         }
389 
getSrcIpv6AddressPrefixLen()390         public int getSrcIpv6AddressPrefixLen() {
391             return mSrcIpv6AddressPrefixLen;
392         }
393 
addressListString(List<InetAddress> list)394         private String addressListString(List<InetAddress> list) {
395             StringBuilder sb = new StringBuilder();
396             sb.append("{ ");
397             for (InetAddress addr : list) {
398                 sb.append(addr);
399                 sb.append(", ");
400             }
401             sb.append(" }");
402             return sb.toString();
403         }
404 
hasTunnelOpened()405         public boolean hasTunnelOpened() {
406             return mInternalAddrList != null
407                     && !mInternalAddrList.isEmpty() /* The child session is opened */
408                     && mIface != null; /* The tunnel interface is bring up */
409         }
410 
411         @Override
toString()412         public String toString() {
413             StringBuilder sb = new StringBuilder();
414             sb.append("TunnelConfig { ");
415             /*if (mPcscfAddrList != null) {
416                 sb.append("mPcscfAddrList: " + addressListString(mPcscfAddrList));
417                 sb.append(", ");
418             }
419             if (mDnsAddrList != null) {
420                 sb.append("mDnsAddrList: " + addressListString(mDnsAddrList));
421                 sb.append(", ");
422             }
423             if (mInternalAddrList != null) {
424                 sb.append("mInternalAddrList: { ");
425                 for (LinkAddress addr : mInternalAddrList) {
426                     sb.append(addr + ", ");
427                 }
428                 sb.append(" }, ");
429             }
430 
431             if (mSrcIpv6Address != null) {
432                 sb.append("{mSrcIpv6Address: " + mSrcIpv6Address + "}, ");
433             } else {
434                 sb.append("{NULL mSrcIpv6Address}, ");
435             } */
436 
437             if (mSliceInfo != null) {
438                 sb.append("mSliceInfo: " + mSliceInfo + ", ");
439             }
440 
441             if (mIsBackoffTimeValid) {
442                 sb.append("mBackoffTime: " + mBackoffTime + ", ");
443             }
444             sb.append(" }");
445             return sb.toString();
446         }
447     }
448 
449     @VisibleForTesting
450     class TmIkeSessionCallback implements IkeSessionCallback {
451 
452         private final String mApnName;
453         private final int mToken;
454 
TmIkeSessionCallback(String apnName, int token)455         TmIkeSessionCallback(String apnName, int token) {
456             this.mApnName = apnName;
457             this.mToken = token;
458         }
459 
460         @Override
onOpened(IkeSessionConfiguration sessionConfiguration)461         public void onOpened(IkeSessionConfiguration sessionConfiguration) {
462             Log.d(TAG, "Ike session opened for apn: " + mApnName + " with token: " + mToken);
463             mHandler.sendMessage(
464                     mHandler.obtainMessage(
465                             EVENT_IKE_SESSION_OPENED,
466                             new IkeSessionOpenedData(mApnName, mToken, sessionConfiguration)));
467         }
468 
469         @Override
onClosed()470         public void onClosed() {
471             Log.d(TAG, "Ike session closed for apn: " + mApnName + " with token: " + mToken);
472             mHandler.sendMessage(
473                     mHandler.obtainMessage(
474                             EVENT_IKE_SESSION_CLOSED,
475                             new SessionClosedData(
476                                     mApnName, mToken, new IwlanError(IwlanError.NO_ERROR))));
477         }
478 
479         @Override
onClosedExceptionally(IkeException exception)480         public void onClosedExceptionally(IkeException exception) {
481             mNextReauthId = null;
482             onSessionClosedWithException(exception, mApnName, mToken, EVENT_IKE_SESSION_CLOSED);
483         }
484 
485         @Override
onError(IkeProtocolException exception)486         public void onError(IkeProtocolException exception) {
487             Log.d(TAG, "Ike session onError for apn: " + mApnName + " with token: " + mToken);
488 
489             mNextReauthId = null;
490 
491             Log.d(
492                     TAG,
493                     "ErrorType:"
494                             + exception.getErrorType()
495                             + " ErrorData:"
496                             + exception.getMessage());
497         }
498 
499         @Override
onIkeSessionConnectionInfoChanged( IkeSessionConnectionInfo ikeSessionConnectionInfo)500         public void onIkeSessionConnectionInfoChanged(
501                 IkeSessionConnectionInfo ikeSessionConnectionInfo) {
502             Network network = ikeSessionConnectionInfo.getNetwork();
503             Log.d(
504                     TAG,
505                     "Ike session connection info changed for apn: "
506                             + mApnName
507                             + " with token: "
508                             + mToken
509                             + " Network: "
510                             + network);
511             mHandler.sendMessage(
512                     mHandler.obtainMessage(
513                             EVENT_IKE_SESSION_CONNECTION_INFO_CHANGED,
514                             new IkeSessionConnectionInfoData(
515                                     mApnName, mToken, ikeSessionConnectionInfo)));
516         }
517     }
518 
519     @VisibleForTesting
520     class TmIke3gppCallback implements Ike3gppExtension.Ike3gppDataListener {
521         private final String mApnName;
522         private final int mToken;
523 
TmIke3gppCallback(String apnName, int token)524         private TmIke3gppCallback(String apnName, int token) {
525             mApnName = apnName;
526             mToken = token;
527         }
528 
529         @Override
onIke3gppDataReceived(List<Ike3gppData> payloads)530         public void onIke3gppDataReceived(List<Ike3gppData> payloads) {
531             if (isObsoleteToken(mApnName, mToken)) {
532                 Log.d(TAG, "onIke3gppDataReceived for obsolete token " + mToken);
533                 return;
534             }
535 
536             if (payloads != null && !payloads.isEmpty()) {
537                 TunnelConfig tunnelConfig = mApnNameToTunnelConfig.get(mApnName);
538                 for (Ike3gppData payload : payloads) {
539                     if (payload.getDataType() == DATA_TYPE_NOTIFY_N1_MODE_INFORMATION) {
540                         Log.d(TAG, "Got payload DATA_TYPE_NOTIFY_N1_MODE_INFORMATION");
541                         NetworkSliceInfo si =
542                                 NetworkSliceSelectionAssistanceInformation.getSliceInfo(
543                                         ((Ike3gppN1ModeInformation) payload).getSnssai());
544                         if (si != null) {
545                             tunnelConfig.setSliceInfo(si);
546                             Log.d(TAG, "SliceInfo: " + si);
547                         }
548                     } else if (payload.getDataType() == DATA_TYPE_NOTIFY_BACKOFF_TIMER) {
549                         Log.d(TAG, "Got payload DATA_TYPE_NOTIFY_BACKOFF_TIMER");
550                         long backoffTime =
551                                 decodeBackoffTime(
552                                         ((Ike3gppBackoffTimer) payload).getBackoffTimer());
553                         if (backoffTime > 0) {
554                             tunnelConfig.setBackoffTime(backoffTime);
555                             Log.d(TAG, "Backoff Timer: " + backoffTime);
556                         }
557                     }
558                 }
559             } else {
560                 Log.e(TAG, "Null or empty payloads received:");
561             }
562         }
563     }
564 
565     @VisibleForTesting
566     class TmChildSessionCallback implements ChildSessionCallback {
567 
568         private final String mApnName;
569         private final int mToken;
570 
TmChildSessionCallback(String apnName, int token)571         TmChildSessionCallback(String apnName, int token) {
572             this.mApnName = apnName;
573             this.mToken = token;
574         }
575 
576         @Override
onOpened(ChildSessionConfiguration sessionConfiguration)577         public void onOpened(ChildSessionConfiguration sessionConfiguration) {
578             Log.d(TAG, "onOpened child session for apn: " + mApnName + " with token: " + mToken);
579             mHandler.sendMessage(
580                     mHandler.obtainMessage(
581                             EVENT_CHILD_SESSION_OPENED,
582                             new TunnelOpenedData(
583                                     mApnName,
584                                     mToken,
585                                     sessionConfiguration.getInternalDnsServers(),
586                                     sessionConfiguration.getInternalAddresses())));
587         }
588 
589         @Override
onClosed()590         public void onClosed() {
591             Log.d(TAG, "onClosed child session for apn: " + mApnName + " with token: " + mToken);
592             mHandler.sendMessage(
593                     mHandler.obtainMessage(
594                             EVENT_CHILD_SESSION_CLOSED,
595                             new SessionClosedData(
596                                     mApnName, mToken, new IwlanError(IwlanError.NO_ERROR))));
597         }
598 
599         @Override
onClosedExceptionally(IkeException exception)600         public void onClosedExceptionally(IkeException exception) {
601             onSessionClosedWithException(exception, mApnName, mToken, EVENT_CHILD_SESSION_CLOSED);
602         }
603 
604         @Override
onIpSecTransformsMigrated( IpSecTransform inIpSecTransform, IpSecTransform outIpSecTransform)605         public void onIpSecTransformsMigrated(
606                 IpSecTransform inIpSecTransform, IpSecTransform outIpSecTransform) {
607             // migration is similar to addition
608             Log.d(TAG, "Transforms migrated for apn: " + mApnName + " with token: " + mToken);
609             mHandler.sendMessage(
610                     mHandler.obtainMessage(
611                             EVENT_IPSEC_TRANSFORM_CREATED,
612                             new IpsecTransformData(
613                                     inIpSecTransform,
614                                     IpSecManager.DIRECTION_IN,
615                                     mApnName,
616                                     mToken)));
617             mHandler.sendMessage(
618                     mHandler.obtainMessage(
619                             EVENT_IPSEC_TRANSFORM_CREATED,
620                             new IpsecTransformData(
621                                     outIpSecTransform,
622                                     IpSecManager.DIRECTION_OUT,
623                                     mApnName,
624                                     mToken)));
625         }
626 
627         @Override
onIpSecTransformCreated(IpSecTransform ipSecTransform, int direction)628         public void onIpSecTransformCreated(IpSecTransform ipSecTransform, int direction) {
629             Log.d(
630                     TAG,
631                     "Transform created, direction: "
632                             + direction
633                             + ", apn: "
634                             + mApnName
635                             + ", token: "
636                             + mToken);
637             mHandler.sendMessage(
638                     mHandler.obtainMessage(
639                             EVENT_IPSEC_TRANSFORM_CREATED,
640                             new IpsecTransformData(ipSecTransform, direction, mApnName, mToken)));
641         }
642 
643         @Override
onIpSecTransformDeleted(IpSecTransform ipSecTransform, int direction)644         public void onIpSecTransformDeleted(IpSecTransform ipSecTransform, int direction) {
645             Log.d(
646                     TAG,
647                     "Transform deleted, direction: "
648                             + direction
649                             + ", apn: "
650                             + mApnName
651                             + ", token: "
652                             + mToken);
653             mHandler.sendMessage(
654                     mHandler.obtainMessage(
655                             EVENT_IPSEC_TRANSFORM_DELETED,
656                             new IpsecTransformData(ipSecTransform, direction, mApnName, mToken)));
657         }
658     }
659 
EpdgTunnelManager(Context context, int slotId)660     private EpdgTunnelManager(Context context, int slotId) {
661         mContext = context;
662         mSlotId = slotId;
663         mIkeSessionCreator = new IkeSessionCreator();
664         TAG = EpdgTunnelManager.class.getSimpleName() + "[" + mSlotId + "]";
665         initHandler();
666     }
667 
668     @VisibleForTesting
initHandler()669     void initHandler() {
670         mHandler = new TmHandler(getLooper());
671     }
672 
673     @VisibleForTesting
getLooper()674     Looper getLooper() {
675         mHandlerThread = new HandlerThread("EpdgTunnelManagerThread");
676         mHandlerThread.start();
677         return mHandlerThread.getLooper();
678     }
679 
680     /**
681      * Gets a EpdgTunnelManager instance.
682      *
683      * @param context application context
684      * @param subId subscription ID for the tunnel
685      * @return tunnel manager instance corresponding to the sub id
686      */
getInstance(@onNull Context context, int subId)687     public static EpdgTunnelManager getInstance(@NonNull Context context, int subId) {
688         return mTunnelManagerInstances.computeIfAbsent(
689                 subId, k -> new EpdgTunnelManager(context, subId));
690     }
691 
692     @VisibleForTesting
resetAllInstances()693     public static void resetAllInstances() {
694         mTunnelManagerInstances.clear();
695     }
696 
697     public interface TunnelCallback {
698         /**
699          * Called when the tunnel is opened.
700          *
701          * @param apnName apn for which the tunnel was opened
702          * @param linkProperties link properties of the tunnel
703          */
onOpened(@onNull String apnName, @NonNull TunnelLinkProperties linkProperties)704         void onOpened(@NonNull String apnName, @NonNull TunnelLinkProperties linkProperties);
705         /**
706          * Called when the tunnel is closed OR if bringup fails
707          *
708          * @param apnName apn for which the tunnel was closed
709          * @param error IwlanError carrying details of the error
710          */
onClosed(@onNull String apnName, @NonNull IwlanError error)711         void onClosed(@NonNull String apnName, @NonNull IwlanError error);
712     }
713 
714     public interface TunnelCallbackMetrics {
715         /**
716          * Called for logging the tunnel is opened.
717          *
718          * @param apnName apn for which the tunnel was opened
719          * @param epdgServerAddress epdg server IP address for bringup the tunnel
720          * @param epdgServerSelectionDuration time for EpdgSelector doing FQDN
721          * @param ikeTunnelEstablishmentDuration time for IKE module processing tunnel
722          *     establishement
723          */
onOpened( @onNull String apnName, @Nullable String epdgServerAddress, @NonNull int epdgServerSelectionDuration, @NonNull int ikeTunnelEstablishmentDuration)724         void onOpened(
725                 @NonNull String apnName,
726                 @Nullable String epdgServerAddress,
727                 @NonNull int epdgServerSelectionDuration,
728                 @NonNull int ikeTunnelEstablishmentDuration);
729         /**
730          * Called for logging the tunnel is closed or bringup failed.
731          *
732          * @param apnName apn for which the tunnel was closed
733          * @param epdgServerAddress epdg server IP address for bringup the tunnel
734          * @param epdgServerSelectionDuration time for EpdgSelector doing FQDN
735          * @param ikeTunnelEstablishmentDuration time for IKE module processing tunnel
736          *     establishement
737          */
onClosed( @onNull String apnName, @Nullable String epdgServerAddress, @NonNull int epdgServerSelectionDuration, @NonNull int ikeTunnelEstablishmentDuration)738         void onClosed(
739                 @NonNull String apnName,
740                 @Nullable String epdgServerAddress,
741                 @NonNull int epdgServerSelectionDuration,
742                 @NonNull int ikeTunnelEstablishmentDuration);
743     }
744 
745     /**
746      * Close tunnel for an apn. Confirmation of closing will be delivered in TunnelCallback that was
747      * provided in {@link #bringUpTunnel}
748      *
749      * @param apnName apn name
750      * @param forceClose if true, results in local cleanup of tunnel
751      * @return true if params are valid and tunnel exists. False otherwise.
752      */
closeTunnel(@onNull String apnName, boolean forceClose)753     public boolean closeTunnel(@NonNull String apnName, boolean forceClose) {
754         mHandler.sendMessage(
755                 mHandler.obtainMessage(
756                         EVENT_TUNNEL_BRINGDOWN_REQUEST,
757                         forceClose ? 1 : 0,
758                         0 /*not used*/,
759                         apnName));
760         return true;
761     }
762 
763     /**
764      * Update the local Network. This will trigger a revaluation for every tunnel for which tunnel
765      * manager has state.
766      *
767      * <p>Tunnels in bringup state will be for closed since IKE currently keeps retrying.
768      *
769      * <p>For rest of the tunnels, update IKE session wth new network. This will either result in
770      * MOBIKE callflow or just a rekey over new Network
771      */
updateNetwork(@onNull Network network, String apnName)772     public void updateNetwork(@NonNull Network network, String apnName) {
773         UpdateNetworkWrapper updateNetworkWrapper = new UpdateNetworkWrapper(network, apnName);
774         mHandler.sendMessage(mHandler.obtainMessage(EVENT_UPDATE_NETWORK, updateNetworkWrapper));
775     }
776     /**
777      * Bring up epdg tunnel. Only one bring up request per apn is expected. All active tunnel
778      * requests and tunnels are expected to be on the same network.
779      *
780      * @param setupRequest {@link TunnelSetupRequest} tunnel configurations
781      * @param tunnelCallback {@link TunnelCallback} interface to notify clients about the tunnel
782      *     state
783      * @return true if params are valid and no existing tunnel. False otherwise.
784      */
bringUpTunnel( @onNull TunnelSetupRequest setupRequest, @NonNull TunnelCallback tunnelCallback, @NonNull TunnelCallbackMetrics tunnelCallbackMetrics)785     public boolean bringUpTunnel(
786             @NonNull TunnelSetupRequest setupRequest,
787             @NonNull TunnelCallback tunnelCallback,
788             @NonNull TunnelCallbackMetrics tunnelCallbackMetrics) {
789         String apnName = setupRequest.apnName();
790 
791         if (getTunnelSetupRequestApnName(setupRequest) == null) {
792             Log.e(TAG, "APN is null.");
793             return false;
794         }
795 
796         if (isTunnelConfigContainExistApn(apnName)) {
797             Log.e(TAG, "Tunnel exists for apn:" + apnName);
798             return false;
799         }
800 
801         if (!isValidApnProtocol(setupRequest.apnIpProtocol())) {
802             Log.e(TAG, "Invalid protocol for APN");
803             return false;
804         }
805 
806         int pduSessionId = setupRequest.pduSessionId();
807         if (pduSessionId < 0 || pduSessionId > 15) {
808             Log.e(TAG, "Invalid pduSessionId: " + pduSessionId);
809             return false;
810         }
811 
812         TunnelRequestWrapper tunnelRequestWrapper =
813                 new TunnelRequestWrapper(setupRequest, tunnelCallback, tunnelCallbackMetrics);
814 
815         mHandler.sendMessage(
816                 mHandler.obtainMessage(EVENT_TUNNEL_BRINGUP_REQUEST, tunnelRequestWrapper));
817 
818         return true;
819     }
820 
onBringUpTunnel( TunnelSetupRequest setupRequest, TunnelCallback tunnelCallback, TunnelCallbackMetrics tunnelCallbackMetrics)821     private void onBringUpTunnel(
822             TunnelSetupRequest setupRequest,
823             TunnelCallback tunnelCallback,
824             TunnelCallbackMetrics tunnelCallbackMetrics) {
825         String apnName = setupRequest.apnName();
826         IkeSessionParams ikeSessionParams = null;
827 
828         Log.d(
829                 TAG,
830                 "Bringing up tunnel for apn: "
831                         + apnName
832                         + "ePDG : "
833                         + mEpdgAddress.getHostAddress());
834 
835         final int token = incrementAndGetCurrentTokenForApn(apnName);
836 
837         try {
838             ikeSessionParams = buildIkeSessionParams(setupRequest, apnName, token);
839         } catch (IwlanSimNotReadyException e) {
840             IwlanError iwlanError = new IwlanError(IwlanError.SIM_NOT_READY_EXCEPTION);
841             reportIwlanError(apnName, iwlanError);
842             tunnelCallback.onClosed(apnName, iwlanError);
843             tunnelCallbackMetrics.onClosed(apnName, null, 0, 0);
844             return;
845         }
846 
847         mIkeTunnelEstablishmentStartTime = System.currentTimeMillis();
848         IkeSession ikeSession =
849                 getIkeSessionCreator()
850                         .createIkeSession(
851                                 mContext,
852                                 ikeSessionParams,
853                                 buildChildSessionParams(setupRequest),
854                                 Executors.newSingleThreadExecutor(),
855                                 getTmIkeSessionCallback(apnName, token),
856                                 new TmChildSessionCallback(apnName, token));
857 
858         boolean isSrcIpv6Present = setupRequest.srcIpv6Address().isPresent();
859         putApnNameToTunnelConfig(
860                 apnName,
861                 ikeSession,
862                 tunnelCallback,
863                 tunnelCallbackMetrics,
864                 isSrcIpv6Present ? setupRequest.srcIpv6Address().get() : null,
865                 setupRequest.srcIpv6AddressPrefixLength());
866     }
867 
868     /**
869      * Proxy to allow testing
870      *
871      * @hide
872      */
873     @VisibleForTesting
874     static class IkeSessionCreator {
875         /** Creates a IKE session */
createIkeSession( @onNull Context context, @NonNull IkeSessionParams ikeSessionParams, @NonNull ChildSessionParams firstChildSessionParams, @NonNull Executor userCbExecutor, @NonNull IkeSessionCallback ikeSessionCallback, @NonNull ChildSessionCallback firstChildSessionCallback)876         public IkeSession createIkeSession(
877                 @NonNull Context context,
878                 @NonNull IkeSessionParams ikeSessionParams,
879                 @NonNull ChildSessionParams firstChildSessionParams,
880                 @NonNull Executor userCbExecutor,
881                 @NonNull IkeSessionCallback ikeSessionCallback,
882                 @NonNull ChildSessionCallback firstChildSessionCallback) {
883             return new IkeSession(
884                     context,
885                     ikeSessionParams,
886                     firstChildSessionParams,
887                     userCbExecutor,
888                     ikeSessionCallback,
889                     firstChildSessionCallback);
890         }
891     }
892 
buildChildSessionParams(TunnelSetupRequest setupRequest)893     private ChildSessionParams buildChildSessionParams(TunnelSetupRequest setupRequest) {
894         int proto = setupRequest.apnIpProtocol();
895         int hardTimeSeconds =
896                 (int) getConfig(CarrierConfigManager.Iwlan.KEY_CHILD_SA_REKEY_HARD_TIMER_SEC_INT);
897         int softTimeSeconds =
898                 (int) getConfig(CarrierConfigManager.Iwlan.KEY_CHILD_SA_REKEY_SOFT_TIMER_SEC_INT);
899         if (!isValidChildSessionLifetime(hardTimeSeconds, softTimeSeconds)) {
900             if (hardTimeSeconds > CHILD_HARD_LIFETIME_SEC_MAXIMUM
901                     && softTimeSeconds > CHILD_SOFT_LIFETIME_SEC_MINIMUM) {
902                 hardTimeSeconds = CHILD_HARD_LIFETIME_SEC_MAXIMUM;
903                 softTimeSeconds = CHILD_HARD_LIFETIME_SEC_MAXIMUM - LIFETIME_MARGIN_SEC_MINIMUM;
904             } else {
905                 hardTimeSeconds =
906                         (int)
907                                 IwlanHelper.getDefaultConfig(
908                                         CarrierConfigManager.Iwlan
909                                                 .KEY_CHILD_SA_REKEY_HARD_TIMER_SEC_INT);
910                 softTimeSeconds =
911                         (int)
912                                 IwlanHelper.getDefaultConfig(
913                                         CarrierConfigManager.Iwlan
914                                                 .KEY_CHILD_SA_REKEY_SOFT_TIMER_SEC_INT);
915             }
916             Log.d(
917                     TAG,
918                     "Invalid child session lifetime values, set hard: "
919                             + hardTimeSeconds
920                             + ", soft: "
921                             + softTimeSeconds);
922         }
923 
924         TunnelModeChildSessionParams.Builder childSessionParamsBuilder =
925                 new TunnelModeChildSessionParams.Builder()
926                         .setLifetimeSeconds(hardTimeSeconds, softTimeSeconds);
927 
928         childSessionParamsBuilder.addSaProposal(buildChildSaProposal());
929 
930         boolean handoverIPv4Present = setupRequest.srcIpv4Address().isPresent();
931         boolean handoverIPv6Present = setupRequest.srcIpv6Address().isPresent();
932         if (handoverIPv4Present || handoverIPv6Present) {
933             if (handoverIPv4Present) {
934                 childSessionParamsBuilder.addInternalAddressRequest(
935                         (Inet4Address) setupRequest.srcIpv4Address().get());
936                 childSessionParamsBuilder.addInternalDnsServerRequest(AF_INET);
937                 childSessionParamsBuilder.addInboundTrafficSelectors(
938                         getDefaultTrafficSelectorIpv4());
939                 childSessionParamsBuilder.addOutboundTrafficSelectors(
940                         getDefaultTrafficSelectorIpv4());
941             }
942             if (handoverIPv6Present) {
943                 childSessionParamsBuilder.addInternalAddressRequest(
944                         (Inet6Address) setupRequest.srcIpv6Address().get(),
945                         setupRequest.srcIpv6AddressPrefixLength());
946                 childSessionParamsBuilder.addInternalDnsServerRequest(AF_INET6);
947                 childSessionParamsBuilder.addInboundTrafficSelectors(
948                         getDefaultTrafficSelectorIpv6());
949                 childSessionParamsBuilder.addOutboundTrafficSelectors(
950                         getDefaultTrafficSelectorIpv6());
951             }
952         } else {
953             // non-handover case
954             if (proto == ApnSetting.PROTOCOL_IP || proto == ApnSetting.PROTOCOL_IPV4V6) {
955                 childSessionParamsBuilder.addInternalAddressRequest(AF_INET);
956                 childSessionParamsBuilder.addInternalDnsServerRequest(AF_INET);
957                 childSessionParamsBuilder.addInboundTrafficSelectors(
958                         getDefaultTrafficSelectorIpv4());
959                 childSessionParamsBuilder.addOutboundTrafficSelectors(
960                         getDefaultTrafficSelectorIpv4());
961             }
962             if (proto == ApnSetting.PROTOCOL_IPV6 || proto == ApnSetting.PROTOCOL_IPV4V6) {
963                 childSessionParamsBuilder.addInternalAddressRequest(AF_INET6);
964                 childSessionParamsBuilder.addInternalDnsServerRequest(AF_INET6);
965                 childSessionParamsBuilder.addInboundTrafficSelectors(
966                         getDefaultTrafficSelectorIpv6());
967                 childSessionParamsBuilder.addOutboundTrafficSelectors(
968                         getDefaultTrafficSelectorIpv6());
969             }
970         }
971 
972         return childSessionParamsBuilder.build();
973     }
974 
getDefaultTrafficSelectorIpv4()975     private static IkeTrafficSelector getDefaultTrafficSelectorIpv4() {
976         return new IkeTrafficSelector(
977                 TRAFFIC_SELECTOR_START_PORT,
978                 TRAFFIC_SELECTOR_END_PORT,
979                 InetAddresses.parseNumericAddress(TRAFFIC_SELECTOR_IPV4_START_ADDR),
980                 InetAddresses.parseNumericAddress(TRAFFIC_SELECTOR_IPV4_END_ADDR));
981     }
982 
getDefaultTrafficSelectorIpv6()983     private static IkeTrafficSelector getDefaultTrafficSelectorIpv6() {
984         return new IkeTrafficSelector(
985                 TRAFFIC_SELECTOR_START_PORT,
986                 TRAFFIC_SELECTOR_END_PORT,
987                 InetAddresses.parseNumericAddress(TRAFFIC_SELECTOR_IPV6_START_ADDR),
988                 InetAddresses.parseNumericAddress(TRAFFIC_SELECTOR_IPV6_END_ADDR));
989     }
990 
numPdnTunnels()991     private int numPdnTunnels() {
992         return mApnNameToTunnelConfig.size();
993     }
994 
995     // Returns the IMEISV or device IMEI, in that order of priority.
getMobileDeviceIdentity()996     private @Nullable String getMobileDeviceIdentity() {
997         TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class);
998         telephonyManager =
999                 telephonyManager.createForSubscriptionId(IwlanHelper.getSubId(mContext, mSlotId));
1000         if (telephonyManager == null) {
1001             return null;
1002         }
1003         // Queries the 15-digit device IMEI.
1004         String imei = telephonyManager.getImei();
1005         if (imei == null || imei.length() != DEVICE_IMEI_LEN) {
1006             Log.i(TAG, "Unable to query valid Mobile Device Identity (IMEI)!");
1007             return null;
1008         }
1009         String imeisv_suffix = telephonyManager.getDeviceSoftwareVersion();
1010         if (imeisv_suffix == null || imeisv_suffix.length() != DEVICE_IMEISV_SUFFIX_LEN) {
1011             // Unable to retrieve 2-digit suffix for IMEISV, so returns device IMEI.
1012             return imei;
1013         }
1014         // Splices the first 14 digit of device IMEI with 2-digit SV suffix to form IMEISV.
1015         return imei.substring(0, imei.length() - 1) + imeisv_suffix;
1016     }
1017 
buildIkeSessionParams( TunnelSetupRequest setupRequest, String apnName, int token)1018     private IkeSessionParams buildIkeSessionParams(
1019             TunnelSetupRequest setupRequest, String apnName, int token)
1020             throws IwlanSimNotReadyException {
1021         int hardTimeSeconds =
1022                 (int) getConfig(CarrierConfigManager.Iwlan.KEY_IKE_REKEY_HARD_TIMER_SEC_INT);
1023         int softTimeSeconds =
1024                 (int) getConfig(CarrierConfigManager.Iwlan.KEY_IKE_REKEY_SOFT_TIMER_SEC_INT);
1025         if (!isValidIkeSessionLifetime(hardTimeSeconds, softTimeSeconds)) {
1026             if (hardTimeSeconds > IKE_HARD_LIFETIME_SEC_MAXIMUM
1027                     && softTimeSeconds > IKE_SOFT_LIFETIME_SEC_MINIMUM) {
1028                 hardTimeSeconds = IKE_HARD_LIFETIME_SEC_MAXIMUM;
1029                 softTimeSeconds = IKE_HARD_LIFETIME_SEC_MAXIMUM - LIFETIME_MARGIN_SEC_MINIMUM;
1030             } else {
1031                 hardTimeSeconds =
1032                         (int)
1033                                 IwlanHelper.getDefaultConfig(
1034                                         CarrierConfigManager.Iwlan
1035                                                 .KEY_IKE_REKEY_HARD_TIMER_SEC_INT);
1036                 softTimeSeconds =
1037                         (int)
1038                                 IwlanHelper.getDefaultConfig(
1039                                         CarrierConfigManager.Iwlan
1040                                                 .KEY_IKE_REKEY_SOFT_TIMER_SEC_INT);
1041             }
1042             Log.d(
1043                     TAG,
1044                     "Invalid ike session lifetime values, set hard: "
1045                             + hardTimeSeconds
1046                             + ", soft: "
1047                             + softTimeSeconds);
1048         }
1049 
1050         IkeSessionParams.Builder builder =
1051                 new IkeSessionParams.Builder(mContext)
1052                         // permanently hardcode DSCP to 46 (Expedited Forwarding class)
1053                         // See https://www.iana.org/assignments/dscp-registry/dscp-registry.xhtml
1054                         // This will make WiFi prioritize IKE signallig under WMM AC_VO
1055                         .setDscp(46)
1056                         .setServerHostname(mEpdgAddress.getHostAddress())
1057                         .setLocalIdentification(getLocalIdentification())
1058                         .setRemoteIdentification(getId(setupRequest.apnName(), false))
1059                         .setAuthEap(null, getEapConfig())
1060                         .addSaProposal(buildIkeSaProposal())
1061                         .setNetwork(mNetwork)
1062                         .addIkeOption(IkeSessionParams.IKE_OPTION_ACCEPT_ANY_REMOTE_ID)
1063                         .addIkeOption(IkeSessionParams.IKE_OPTION_MOBIKE)
1064                         .addIkeOption(IkeSessionParams.IKE_OPTION_REKEY_MOBILITY)
1065                         .setLifetimeSeconds(hardTimeSeconds, softTimeSeconds)
1066                         .setRetransmissionTimeoutsMillis(getRetransmissionTimeoutsFromConfig())
1067                         .setDpdDelaySeconds(getDpdDelayFromConfig());
1068 
1069         if (numPdnTunnels() == 0) {
1070             builder.addIkeOption(IkeSessionParams.IKE_OPTION_INITIAL_CONTACT);
1071             Log.d(TAG, "IKE_OPTION_INITIAL_CONTACT");
1072         }
1073 
1074         if ((int) getConfig(CarrierConfigManager.Iwlan.KEY_EPDG_AUTHENTICATION_METHOD_INT)
1075                 == CarrierConfigManager.Iwlan.AUTHENTICATION_METHOD_EAP_ONLY) {
1076             builder.addIkeOption(IkeSessionParams.IKE_OPTION_EAP_ONLY_AUTH);
1077         }
1078 
1079         if (setupRequest.requestPcscf()) {
1080             int proto = setupRequest.apnIpProtocol();
1081             if (proto == ApnSetting.PROTOCOL_IP || proto == ApnSetting.PROTOCOL_IPV4V6) {
1082                 builder.addPcscfServerRequest(AF_INET);
1083             }
1084             if (proto == ApnSetting.PROTOCOL_IPV6 || proto == ApnSetting.PROTOCOL_IPV4V6) {
1085                 builder.addPcscfServerRequest(AF_INET6);
1086             }
1087         }
1088 
1089         Ike3gppParams.Builder builder3gppParams = null;
1090 
1091         // TODO(b/239753287): Telus carrier requests DEVICE_IDENTITY, but errors out when parsing
1092         //  the response. Temporarily disabled.
1093         if (false) {
1094             String imei = getMobileDeviceIdentity();
1095             if (imei != null) {
1096                 if (builder3gppParams == null) {
1097                     builder3gppParams = new Ike3gppParams.Builder();
1098                 }
1099                 Log.d(TAG, "DEVICE_IDENTITY set in Ike3gppParams");
1100                 builder3gppParams.setMobileDeviceIdentity(imei);
1101             }
1102         }
1103 
1104         if (isN1ModeSupported()) {
1105             if (setupRequest.pduSessionId() != 0) {
1106                 // Configures the PduSession ID in N1_MODE_CAPABILITY payload
1107                 // to notify the server that UE supports N1_MODE
1108                 if (builder3gppParams == null) {
1109                     builder3gppParams = new Ike3gppParams.Builder();
1110                 }
1111                 builder3gppParams.setPduSessionId((byte) setupRequest.pduSessionId());
1112             }
1113         }
1114 
1115         if (builder3gppParams != null) {
1116             Ike3gppExtension extension =
1117                     new Ike3gppExtension(
1118                             builder3gppParams.build(), new TmIke3gppCallback(apnName, token));
1119             builder.setIke3gppExtension(extension);
1120         }
1121 
1122         int nattKeepAliveTimer =
1123                 (int) getConfig(CarrierConfigManager.Iwlan.KEY_NATT_KEEP_ALIVE_TIMER_SEC_INT);
1124         if (nattKeepAliveTimer < NATT_KEEPALIVE_DELAY_SEC_MIN
1125                 || nattKeepAliveTimer > NATT_KEEPALIVE_DELAY_SEC_MAX) {
1126             Log.d(TAG, "Falling back to default natt keep alive timer");
1127             nattKeepAliveTimer =
1128                     (int)
1129                             IwlanHelper.getDefaultConfig(
1130                                     CarrierConfigManager.Iwlan.KEY_NATT_KEEP_ALIVE_TIMER_SEC_INT);
1131         }
1132         builder.setNattKeepAliveDelaySeconds(nattKeepAliveTimer);
1133 
1134         return builder.build();
1135     }
1136 
isValidChildSessionLifetime(int hardLifetimeSeconds, int softLifetimeSeconds)1137     private boolean isValidChildSessionLifetime(int hardLifetimeSeconds, int softLifetimeSeconds) {
1138         if (hardLifetimeSeconds < CHILD_HARD_LIFETIME_SEC_MINIMUM
1139                 || hardLifetimeSeconds > CHILD_HARD_LIFETIME_SEC_MAXIMUM
1140                 || softLifetimeSeconds < CHILD_SOFT_LIFETIME_SEC_MINIMUM
1141                 || hardLifetimeSeconds - softLifetimeSeconds < LIFETIME_MARGIN_SEC_MINIMUM) {
1142             return false;
1143         }
1144         return true;
1145     }
1146 
isValidIkeSessionLifetime(int hardLifetimeSeconds, int softLifetimeSeconds)1147     private boolean isValidIkeSessionLifetime(int hardLifetimeSeconds, int softLifetimeSeconds) {
1148         if (hardLifetimeSeconds < IKE_HARD_LIFETIME_SEC_MINIMUM
1149                 || hardLifetimeSeconds > IKE_HARD_LIFETIME_SEC_MAXIMUM
1150                 || softLifetimeSeconds < IKE_SOFT_LIFETIME_SEC_MINIMUM
1151                 || hardLifetimeSeconds - softLifetimeSeconds < LIFETIME_MARGIN_SEC_MINIMUM) {
1152             return false;
1153         }
1154         return true;
1155     }
1156 
getConfig(String configKey)1157     private <T> T getConfig(String configKey) {
1158         return IwlanHelper.getConfig(configKey, mContext, mSlotId);
1159     }
1160 
buildIkeSaProposal()1161     private IkeSaProposal buildIkeSaProposal() {
1162         IkeSaProposal.Builder saProposalBuilder = new IkeSaProposal.Builder();
1163 
1164         int[] dhGroups = getConfig(CarrierConfigManager.Iwlan.KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY);
1165         for (int dhGroup : dhGroups) {
1166             if (validateConfig(dhGroup, VALID_DH_GROUPS, CONFIG_TYPE_DH_GROUP)) {
1167                 saProposalBuilder.addDhGroup(dhGroup);
1168             }
1169         }
1170 
1171         int[] encryptionAlgos =
1172                 getConfig(
1173                         CarrierConfigManager.Iwlan
1174                                 .KEY_SUPPORTED_IKE_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY);
1175         for (int encryptionAlgo : encryptionAlgos) {
1176             validateConfig(encryptionAlgo, VALID_ENCRYPTION_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO);
1177 
1178             if (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_CBC) {
1179                 int[] aesCbcKeyLens =
1180                         getConfig(
1181                                 CarrierConfigManager.Iwlan
1182                                         .KEY_IKE_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY);
1183                 for (int aesCbcKeyLen : aesCbcKeyLens) {
1184                     if (validateConfig(aesCbcKeyLen, VALID_KEY_LENGTHS, CONFIG_TYPE_KEY_LEN)) {
1185                         saProposalBuilder.addEncryptionAlgorithm(encryptionAlgo, aesCbcKeyLen);
1186                     }
1187                 }
1188             }
1189 
1190             if (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_CTR) {
1191                 int[] aesCtrKeyLens =
1192                         getConfig(
1193                                 CarrierConfigManager.Iwlan
1194                                         .KEY_IKE_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY);
1195                 for (int aesCtrKeyLen : aesCtrKeyLens) {
1196                     if (validateConfig(aesCtrKeyLen, VALID_KEY_LENGTHS, CONFIG_TYPE_KEY_LEN)) {
1197                         saProposalBuilder.addEncryptionAlgorithm(encryptionAlgo, aesCtrKeyLen);
1198                     }
1199                 }
1200             }
1201         }
1202 
1203         int[] integrityAlgos =
1204                 getConfig(CarrierConfigManager.Iwlan.KEY_SUPPORTED_INTEGRITY_ALGORITHMS_INT_ARRAY);
1205         for (int integrityAlgo : integrityAlgos) {
1206             if (validateConfig(integrityAlgo, VALID_INTEGRITY_ALGOS, CONFIG_TYPE_INTEGRITY_ALGO)) {
1207                 saProposalBuilder.addIntegrityAlgorithm(integrityAlgo);
1208             }
1209         }
1210 
1211         int[] prfAlgos =
1212                 getConfig(CarrierConfigManager.Iwlan.KEY_SUPPORTED_PRF_ALGORITHMS_INT_ARRAY);
1213         for (int prfAlgo : prfAlgos) {
1214             if (validateConfig(prfAlgo, VALID_PRF_ALGOS, CONFIG_TYPE_PRF_ALGO)) {
1215                 saProposalBuilder.addPseudorandomFunction(prfAlgo);
1216             }
1217         }
1218 
1219         return saProposalBuilder.build();
1220     }
1221 
validateConfig(int config, Set<Integer> validConfigValues, String configType)1222     private boolean validateConfig(int config, Set<Integer> validConfigValues, String configType) {
1223         if (validConfigValues.contains(config)) {
1224             return true;
1225         }
1226 
1227         Log.e(TAG, "Invalid config value for " + configType + ":" + config);
1228         return false;
1229     }
1230 
buildChildSaProposal()1231     private ChildSaProposal buildChildSaProposal() {
1232         ChildSaProposal.Builder saProposalBuilder = new ChildSaProposal.Builder();
1233 
1234         // IKE library doesn't add KE payload if dh groups are not set in child session params.
1235         // Use the same groups as that of IKE session.
1236         if (getConfig(CarrierConfigManager.Iwlan.KEY_ADD_KE_TO_CHILD_SESSION_REKEY_BOOL)) {
1237             int[] dhGroups =
1238                     getConfig(CarrierConfigManager.Iwlan.KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY);
1239             for (int dhGroup : dhGroups) {
1240                 if (validateConfig(dhGroup, VALID_DH_GROUPS, CONFIG_TYPE_DH_GROUP)) {
1241                     saProposalBuilder.addDhGroup(dhGroup);
1242                 }
1243             }
1244         }
1245 
1246         int[] encryptionAlgos =
1247                 getConfig(
1248                         CarrierConfigManager.Iwlan
1249                                 .KEY_SUPPORTED_CHILD_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY);
1250         for (int encryptionAlgo : encryptionAlgos) {
1251             if (validateConfig(encryptionAlgo, VALID_ENCRYPTION_ALGOS, CONFIG_TYPE_ENCRYPT_ALGO)) {
1252                 if (ChildSaProposal.getSupportedEncryptionAlgorithms().contains(encryptionAlgo)) {
1253                     if (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_CBC) {
1254                         int[] aesCbcKeyLens =
1255                                 getConfig(
1256                                         CarrierConfigManager.Iwlan
1257                                                 .KEY_CHILD_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY);
1258                         for (int aesCbcKeyLen : aesCbcKeyLens) {
1259                             if (validateConfig(
1260                                     aesCbcKeyLen, VALID_KEY_LENGTHS, CONFIG_TYPE_KEY_LEN)) {
1261                                 saProposalBuilder.addEncryptionAlgorithm(
1262                                         encryptionAlgo, aesCbcKeyLen);
1263                             }
1264                         }
1265                     }
1266 
1267                     if (encryptionAlgo == SaProposal.ENCRYPTION_ALGORITHM_AES_CTR) {
1268                         int[] aesCtrKeyLens =
1269                                 getConfig(
1270                                         CarrierConfigManager.Iwlan
1271                                                 .KEY_CHILD_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY);
1272                         for (int aesCtrKeyLen : aesCtrKeyLens) {
1273                             if (validateConfig(
1274                                     aesCtrKeyLen, VALID_KEY_LENGTHS, CONFIG_TYPE_KEY_LEN)) {
1275                                 saProposalBuilder.addEncryptionAlgorithm(
1276                                         encryptionAlgo, aesCtrKeyLen);
1277                             }
1278                         }
1279                     }
1280                 } else {
1281                     Log.w(TAG, "Device does not support encryption alog:  " + encryptionAlgo);
1282                 }
1283             }
1284         }
1285 
1286         int[] integrityAlgos =
1287                 getConfig(CarrierConfigManager.Iwlan.KEY_SUPPORTED_INTEGRITY_ALGORITHMS_INT_ARRAY);
1288         for (int integrityAlgo : integrityAlgos) {
1289             if (validateConfig(integrityAlgo, VALID_INTEGRITY_ALGOS, CONFIG_TYPE_INTEGRITY_ALGO)) {
1290                 if (ChildSaProposal.getSupportedIntegrityAlgorithms().contains(integrityAlgo)) {
1291                     saProposalBuilder.addIntegrityAlgorithm(integrityAlgo);
1292                 } else {
1293                     Log.w(TAG, "Device does not support integrity alog:  " + integrityAlgo);
1294                 }
1295             }
1296         }
1297 
1298         return saProposalBuilder.build();
1299     }
1300 
getLocalIdentification()1301     private IkeIdentification getLocalIdentification() throws IwlanSimNotReadyException {
1302         String nai;
1303 
1304         nai = IwlanHelper.getNai(mContext, mSlotId, mNextReauthId);
1305 
1306         if (nai == null) {
1307             throw new IwlanSimNotReadyException("Nai is null.");
1308         }
1309 
1310         Log.d(TAG, "getLocalIdentification: Nai: " + nai);
1311         return getId(nai, true);
1312     }
1313 
getId(String id, boolean isLocal)1314     private IkeIdentification getId(String id, boolean isLocal) {
1315         String idTypeConfig =
1316                 isLocal
1317                         ? CarrierConfigManager.Iwlan.KEY_IKE_LOCAL_ID_TYPE_INT
1318                         : CarrierConfigManager.Iwlan.KEY_IKE_REMOTE_ID_TYPE_INT;
1319         int idType = getConfig(idTypeConfig);
1320         switch (idType) {
1321             case CarrierConfigManager.Iwlan.ID_TYPE_FQDN:
1322                 return new IkeFqdnIdentification(id);
1323             case CarrierConfigManager.Iwlan.ID_TYPE_KEY_ID:
1324                 return new IkeKeyIdIdentification(id.getBytes(StandardCharsets.US_ASCII));
1325             case CarrierConfigManager.Iwlan.ID_TYPE_RFC822_ADDR:
1326                 return new IkeRfc822AddrIdentification(id);
1327             default:
1328                 throw new IllegalArgumentException("Invalid local Identity type: " + idType);
1329         }
1330     }
1331 
getEapConfig()1332     private EapSessionConfig getEapConfig() throws IwlanSimNotReadyException {
1333         int subId = IwlanHelper.getSubId(mContext, mSlotId);
1334         String nai = IwlanHelper.getNai(mContext, mSlotId, null);
1335 
1336         if (nai == null) {
1337             throw new IwlanSimNotReadyException("Nai is null.");
1338         }
1339 
1340         EapSessionConfig.EapAkaOption option = null;
1341         if (mNextReauthId != null) {
1342             option = new EapSessionConfig.EapAkaOption.Builder().setReauthId(mNextReauthId).build();
1343         }
1344 
1345         Log.d(TAG, "getEapConfig: Nai: " + nai);
1346         return new EapSessionConfig.Builder()
1347                 .setEapAkaConfig(subId, TelephonyManager.APPTYPE_USIM, option)
1348                 .setEapIdentity(nai.getBytes(StandardCharsets.US_ASCII))
1349                 .build();
1350     }
1351 
onSessionClosedWithException( IkeException exception, String apnName, int token, int sessionType)1352     private void onSessionClosedWithException(
1353             IkeException exception, String apnName, int token, int sessionType) {
1354         IwlanError error = new IwlanError(exception);
1355         Log.e(
1356                 TAG,
1357                 "Closing tunnel with exception for apn: "
1358                         + apnName
1359                         + " with token: "
1360                         + token
1361                         + " sessionType:"
1362                         + sessionType
1363                         + " error: "
1364                         + error);
1365         exception.printStackTrace();
1366 
1367         mHandler.sendMessage(
1368                 mHandler.obtainMessage(sessionType, new SessionClosedData(apnName, token, error)));
1369     }
1370 
1371     private final class TmHandler extends Handler {
1372         private final String TAG = TmHandler.class.getSimpleName();
1373 
1374         @Override
handleMessage(Message msg)1375         public void handleMessage(Message msg) {
1376             Log.d(TAG, "msg.what = " + eventToString(msg.what));
1377 
1378             String apnName;
1379             TunnelConfig tunnelConfig;
1380 
1381             switch (msg.what) {
1382                 case EVENT_CHILD_SESSION_OPENED:
1383                 case EVENT_IKE_SESSION_CLOSED:
1384                 case EVENT_IPSEC_TRANSFORM_CREATED:
1385                 case EVENT_IPSEC_TRANSFORM_DELETED:
1386                 case EVENT_CHILD_SESSION_CLOSED:
1387                 case EVENT_IKE_SESSION_OPENED:
1388                 case EVENT_IKE_SESSION_CONNECTION_INFO_CHANGED:
1389                     IkeEventData ikeEventData = (IkeEventData) msg.obj;
1390                     if (isObsoleteToken(ikeEventData.mApnName, ikeEventData.mToken)) {
1391                         Log.d(
1392                                 TAG,
1393                                 eventToString(msg.what)
1394                                         + " for obsolete token "
1395                                         + ikeEventData.mToken);
1396                         return;
1397                     }
1398             }
1399 
1400             switch (msg.what) {
1401                 case EVENT_TUNNEL_BRINGUP_REQUEST:
1402                     TunnelRequestWrapper tunnelRequestWrapper = (TunnelRequestWrapper) msg.obj;
1403                     TunnelSetupRequest setupRequest = tunnelRequestWrapper.getSetupRequest();
1404 
1405                     if (IwlanHelper.getSubId(mContext, mSlotId)
1406                             == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1407                         Log.e(TAG, "SIM isn't ready");
1408                         IwlanError iwlanError = new IwlanError(IwlanError.SIM_NOT_READY_EXCEPTION);
1409                         reportIwlanError(setupRequest.apnName(), iwlanError);
1410                         tunnelRequestWrapper
1411                                 .getTunnelCallback()
1412                                 .onClosed(setupRequest.apnName(), iwlanError);
1413                         tunnelRequestWrapper
1414                                 .getTunnelCallbackMetrics()
1415                                 .onClosed(setupRequest.apnName(), null, 0, 0);
1416                         return;
1417                     }
1418 
1419                     if (!canBringUpTunnel(setupRequest.apnName())) {
1420                         Log.d(TAG, "Cannot bring up tunnel as retry time has not passed");
1421                         tunnelRequestWrapper
1422                                 .getTunnelCallback()
1423                                 .onClosed(
1424                                         setupRequest.apnName(),
1425                                         getLastError(setupRequest.apnName()));
1426                         tunnelRequestWrapper
1427                                 .getTunnelCallbackMetrics()
1428                                 .onClosed(setupRequest.apnName(), null, 0, 0);
1429                         return;
1430                     }
1431 
1432                     // No tunnel bring up in progress and the epdg address is null
1433                     if (!mIsEpdgAddressSelected
1434                             && mApnNameToTunnelConfig.size() == 0
1435                             && mPendingBringUpRequests.isEmpty()) {
1436                         mNetwork = setupRequest.network();
1437                         mPendingBringUpRequests.add(tunnelRequestWrapper);
1438                         selectEpdgAddress(setupRequest);
1439                         break;
1440                     }
1441 
1442                     // Service the request immediately when epdg address is available
1443                     if (mIsEpdgAddressSelected) {
1444                         onBringUpTunnel(
1445                                 setupRequest,
1446                                 tunnelRequestWrapper.getTunnelCallback(),
1447                                 tunnelRequestWrapper.getTunnelCallbackMetrics());
1448                     } else {
1449                         mPendingBringUpRequests.add(tunnelRequestWrapper);
1450                     }
1451                     break;
1452 
1453                 case EVENT_EPDG_ADDRESS_SELECTION_REQUEST_COMPLETE:
1454                     EpdgSelectorResult selectorResult = (EpdgSelectorResult) msg.obj;
1455                     printRequestQueue("EVENT_EPDG_ADDRESS_SELECTION_REQUEST_COMPLETE");
1456 
1457                     if (selectorResult.getTransactionId() != mTransactionId) {
1458                         Log.e(TAG, "Mismatched transactionId");
1459                         break;
1460                     }
1461 
1462                     if (mPendingBringUpRequests.isEmpty()) {
1463                         Log.d(TAG, "Empty request queue");
1464                         break;
1465                     }
1466 
1467                     if (selectorResult.getEpdgError().getErrorType() == IwlanError.NO_ERROR
1468                             && selectorResult.getValidIpList() != null) {
1469                         tunnelRequestWrapper = mPendingBringUpRequests.poll();
1470                         validateAndSetEpdgAddress(selectorResult.getValidIpList());
1471                         onBringUpTunnel(
1472                                 tunnelRequestWrapper.getSetupRequest(),
1473                                 tunnelRequestWrapper.getTunnelCallback(),
1474                                 tunnelRequestWrapper.getTunnelCallbackMetrics());
1475                     } else {
1476                         IwlanError error =
1477                                 (selectorResult.getEpdgError().getErrorType()
1478                                                 == IwlanError.NO_ERROR)
1479                                         ? new IwlanError(
1480                                                 IwlanError.EPDG_SELECTOR_SERVER_SELECTION_FAILED)
1481                                         : selectorResult.getEpdgError();
1482                         failAllPendingRequests(error);
1483                     }
1484                     break;
1485 
1486                 case EVENT_CHILD_SESSION_OPENED:
1487                     TunnelOpenedData tunnelOpenedData = (TunnelOpenedData) msg.obj;
1488                     apnName = tunnelOpenedData.mApnName;
1489                     tunnelConfig = mApnNameToTunnelConfig.get(apnName);
1490 
1491                     tunnelConfig.setDnsAddrList(tunnelOpenedData.mInternalDnsServers);
1492                     tunnelConfig.setInternalAddrList(tunnelOpenedData.mInternalAddresses);
1493 
1494                     IpSecManager.IpSecTunnelInterface tunnelInterface = tunnelConfig.getIface();
1495 
1496                     for (LinkAddress address : tunnelConfig.getInternalAddrList()) {
1497                         try {
1498                             tunnelInterface.addAddress(
1499                                     address.getAddress(), address.getPrefixLength());
1500                         } catch (IOException e) {
1501                             Log.e(TAG, "Adding internal addresses to interface failed.");
1502                         }
1503                     }
1504 
1505                     TunnelLinkProperties linkProperties =
1506                             TunnelLinkProperties.builder()
1507                                     .setInternalAddresses(tunnelConfig.getInternalAddrList())
1508                                     .setDnsAddresses(tunnelConfig.getDnsAddrList())
1509                                     .setPcscfAddresses(tunnelConfig.getPcscfAddrList())
1510                                     .setIfaceName(tunnelConfig.getIface().getInterfaceName())
1511                                     .setSliceInfo(tunnelConfig.getSliceInfo())
1512                                     .build();
1513                     tunnelConfig.getTunnelCallback().onOpened(apnName, linkProperties);
1514 
1515                     mIkeTunnelEstablishmentDuration =
1516                             System.currentTimeMillis() - mIkeTunnelEstablishmentStartTime;
1517                     mIkeTunnelEstablishmentStartTime = 0;
1518                     tunnelConfig
1519                             .getTunnelCallbackMetrics()
1520                             .onOpened(
1521                                     apnName,
1522                                     mEpdgAddress.getHostAddress(),
1523                                     (int) mEpdgServerSelectionDuration,
1524                                     (int) mIkeTunnelEstablishmentDuration);
1525 
1526                     reportIwlanError(apnName, new IwlanError(IwlanError.NO_ERROR));
1527 
1528                     setIsEpdgAddressSelected(true);
1529                     mValidEpdgInfo.resetIndex();
1530                     printRequestQueue("EVENT_CHILD_SESSION_OPENED");
1531                     serviceAllPendingRequests();
1532                     break;
1533 
1534                 case EVENT_IKE_SESSION_CLOSED:
1535                     printRequestQueue("EVENT_IKE_SESSION_CLOSED");
1536                     SessionClosedData sessionClosedData = (SessionClosedData) msg.obj;
1537                     apnName = sessionClosedData.mApnName;
1538 
1539                     tunnelConfig = mApnNameToTunnelConfig.get(apnName);
1540                     if (tunnelConfig == null) {
1541                         Log.e(TAG, "No callback found for apn: " + apnName);
1542                         return;
1543                     }
1544 
1545                     // If IKE session closed exceptionally, we retrieve IwlanError directly from the
1546                     // exception; otherwise, it is still possible that we triggered an IKE session
1547                     // close due to an error (eg. IwlanError.TUNNEL_TRANSFORM_FAILED), or because
1548                     // the Child session closed exceptionally; in which case, we attempt to retrieve
1549                     // the stored error (if any) from TunnelConfig.
1550                     IwlanError iwlanError;
1551                     if (sessionClosedData.mIwlanError.getErrorType() != IwlanError.NO_ERROR) {
1552                         iwlanError = sessionClosedData.mIwlanError;
1553                     } else {
1554                         // If IKE session setup failed without error cause, Iwlan reports
1555                         // NETWORK_FAILURE instead of NO_ERROR
1556                         if (!tunnelConfig.hasTunnelOpened()) {
1557                             iwlanError = new IwlanError(IwlanError.NETWORK_FAILURE);
1558                         } else {
1559                             iwlanError = tunnelConfig.getError();
1560                         }
1561                     }
1562 
1563                     IpSecManager.IpSecTunnelInterface iface = tunnelConfig.getIface();
1564                     if (iface != null) {
1565                         iface.close();
1566                     }
1567 
1568                     if (!tunnelConfig.hasTunnelOpened()) {
1569                         if (tunnelConfig.isBackoffTimeValid()) {
1570                             reportIwlanError(apnName, iwlanError, tunnelConfig.getBackoffTime());
1571                         } else {
1572                             reportIwlanError(apnName, iwlanError);
1573                         }
1574                     }
1575 
1576                     Log.d(TAG, "Tunnel Closed: " + iwlanError);
1577                     tunnelConfig.getTunnelCallback().onClosed(apnName, iwlanError);
1578 
1579                     if (!mIsEpdgAddressSelected) {
1580                         failAllPendingRequests(iwlanError);
1581                         tunnelConfig.getTunnelCallbackMetrics().onClosed(apnName, null, 0, 0);
1582                     } else {
1583                         mIkeTunnelEstablishmentDuration =
1584                                 mIkeTunnelEstablishmentStartTime > 0
1585                                         ? System.currentTimeMillis()
1586                                                 - mIkeTunnelEstablishmentStartTime
1587                                         : 0;
1588                         mIkeTunnelEstablishmentStartTime = 0;
1589 
1590                         tunnelConfig
1591                                 .getTunnelCallbackMetrics()
1592                                 .onClosed(
1593                                         apnName,
1594                                         mEpdgAddress.getHostAddress(),
1595                                         (int) mEpdgServerSelectionDuration,
1596                                         (int) mIkeTunnelEstablishmentDuration);
1597                     }
1598 
1599                     mApnNameToTunnelConfig.remove(apnName);
1600                     if (mApnNameToTunnelConfig.size() == 0 && mPendingBringUpRequests.isEmpty()) {
1601                         resetTunnelManagerState();
1602                     }
1603                     break;
1604 
1605                 case EVENT_UPDATE_NETWORK:
1606                     UpdateNetworkWrapper updatedNetwork = (UpdateNetworkWrapper) msg.obj;
1607                     apnName = updatedNetwork.getApnName();
1608                     Network network = updatedNetwork.getNetwork();
1609                     tunnelConfig = mApnNameToTunnelConfig.get(apnName);
1610 
1611                     // Update the global cache if they aren't equal
1612                     if (mNetwork == null || !mNetwork.equals(network)) {
1613                         Log.d(TAG, "Updating mNetwork to " + network);
1614                         mNetwork = network;
1615                     }
1616 
1617                     if (tunnelConfig == null) {
1618                         Log.d(TAG, "Update Network request: No tunnel exists for apn: " + apnName);
1619                     } else {
1620                         Log.d(TAG, "Updating Network for apn: " + apnName + " Network: " + network);
1621                         tunnelConfig.getIkeSession().setNetwork(network);
1622                     }
1623                     break;
1624 
1625                 case EVENT_TUNNEL_BRINGDOWN_REQUEST:
1626                     apnName = (String) msg.obj;
1627                     int forceClose = msg.arg1;
1628                     tunnelConfig = mApnNameToTunnelConfig.get(apnName);
1629                     if (tunnelConfig == null) {
1630                         Log.d(
1631                                 TAG,
1632                                 "Bringdown request: No tunnel exists for apn: "
1633                                         + apnName
1634                                         + "forced: "
1635                                         + forceClose);
1636                     } else {
1637                         if (forceClose == 1) {
1638                             tunnelConfig.getIkeSession().kill();
1639                         } else {
1640                             tunnelConfig.getIkeSession().close();
1641                         }
1642                     }
1643                     int numClosed = closePendingRequestsForApn(apnName);
1644                     if (numClosed > 0) {
1645                         Log.d(TAG, "Closed " + numClosed + " pending requests for apn: " + apnName);
1646                     }
1647                     break;
1648 
1649                 case EVENT_IPSEC_TRANSFORM_CREATED:
1650                     IpsecTransformData transformData = (IpsecTransformData) msg.obj;
1651                     apnName = transformData.getApnName();
1652                     IpSecManager ipSecManager = mContext.getSystemService(IpSecManager.class);
1653                     tunnelConfig = mApnNameToTunnelConfig.get(apnName);
1654 
1655                     if (tunnelConfig.getIface() == null) {
1656                         if (mLocalAddresses == null
1657                                 || mLocalAddresses.size() == 0
1658                                 || ipSecManager == null) {
1659                             Log.e(TAG, "No local addresses found.");
1660                             closeIkeSession(
1661                                     apnName, new IwlanError(IwlanError.TUNNEL_TRANSFORM_FAILED));
1662                             return;
1663                         }
1664 
1665                         try {
1666                             if (mEpdgAddress instanceof Inet4Address
1667                                     && mProtoFilter == EpdgSelector.PROTO_FILTER_IPV6) {
1668                                 mLocalAddresses =
1669                                         IwlanHelper.getStackedAddressesForNetwork(
1670                                                 mNetwork, mContext);
1671                             }
1672                             InetAddress localAddress =
1673                                     (mEpdgAddress instanceof Inet4Address)
1674                                             ? IwlanHelper.getIpv4Address(mLocalAddresses)
1675                                             : IwlanHelper.getIpv6Address(mLocalAddresses);
1676                             Log.d(TAG, "Local address = " + localAddress);
1677                             tunnelConfig.setIface(
1678                                     ipSecManager.createIpSecTunnelInterface(
1679                                             localAddress, mEpdgAddress, mNetwork));
1680                         } catch (IpSecManager.ResourceUnavailableException | IOException e) {
1681                             Log.e(TAG, "Failed to create tunnel interface. " + e);
1682                             closeIkeSession(
1683                                     apnName, new IwlanError(IwlanError.TUNNEL_TRANSFORM_FAILED));
1684                             return;
1685                         }
1686                     }
1687 
1688                     try {
1689                         ipSecManager.applyTunnelModeTransform(
1690                                 tunnelConfig.getIface(),
1691                                 transformData.getDirection(),
1692                                 transformData.getTransform());
1693                     } catch (IOException | IllegalArgumentException e) {
1694                         // If the IKE session was closed before the transform could be applied, the
1695                         // IpSecService will throw an IAE on processing the IpSecTunnelInterface id.
1696                         Log.e(TAG, "Failed to apply tunnel transform." + e);
1697                         closeIkeSession(
1698                                 apnName, new IwlanError(IwlanError.TUNNEL_TRANSFORM_FAILED));
1699                     }
1700                     break;
1701 
1702                 case EVENT_IPSEC_TRANSFORM_DELETED:
1703                     transformData = (IpsecTransformData) msg.obj;
1704                     IpSecTransform transform = transformData.getTransform();
1705                     transform.close();
1706                     break;
1707 
1708                 case EVENT_CHILD_SESSION_CLOSED:
1709                     sessionClosedData = (SessionClosedData) msg.obj;
1710                     apnName = sessionClosedData.mApnName;
1711 
1712                     tunnelConfig = mApnNameToTunnelConfig.get(apnName);
1713                     if (tunnelConfig == null) {
1714                         Log.d(TAG, "No tunnel callback for apn: " + apnName);
1715                         return;
1716                     }
1717                     tunnelConfig.setError(sessionClosedData.mIwlanError);
1718                     tunnelConfig.getIkeSession().close();
1719                     break;
1720 
1721                 case EVENT_IKE_SESSION_OPENED:
1722                     IkeSessionOpenedData ikeSessionOpenedData = (IkeSessionOpenedData) msg.obj;
1723                     apnName = ikeSessionOpenedData.mApnName;
1724                     IkeSessionConfiguration sessionConfiguration =
1725                             ikeSessionOpenedData.mIkeSessionConfiguration;
1726 
1727                     tunnelConfig = mApnNameToTunnelConfig.get(apnName);
1728                     tunnelConfig.setPcscfAddrList(sessionConfiguration.getPcscfServers());
1729 
1730                     boolean enabledFastReauth =
1731                             (boolean)
1732                                     getConfig(
1733                                             CarrierConfigManager.Iwlan
1734                                                     .KEY_SUPPORTS_EAP_AKA_FAST_REAUTH_BOOL);
1735                     Log.d(
1736                             TAG,
1737                             "CarrierConfigManager.Iwlan.KEY_SUPPORTS_EAP_AKA_FAST_REAUTH_BOOL "
1738                                     + enabledFastReauth);
1739 
1740                     if (enabledFastReauth) {
1741                         EapInfo eapInfo = sessionConfiguration.getEapInfo();
1742                         if (eapInfo != null && eapInfo instanceof EapAkaInfo) {
1743                             mNextReauthId = ((EapAkaInfo) eapInfo).getReauthId();
1744                             Log.d(TAG, "Update ReauthId: " + Arrays.toString(mNextReauthId));
1745                         } else {
1746                             mNextReauthId = null;
1747                         }
1748                     }
1749                     break;
1750 
1751                 case EVENT_IKE_SESSION_CONNECTION_INFO_CHANGED:
1752                     IkeSessionConnectionInfoData ikeSessionConnectionInfoData =
1753                             (IkeSessionConnectionInfoData) msg.obj;
1754                     network = ikeSessionConnectionInfoData.mIkeSessionConnectionInfo.getNetwork();
1755                     apnName = ikeSessionConnectionInfoData.mApnName;
1756 
1757                     ConnectivityManager connectivityManager =
1758                             mContext.getSystemService(ConnectivityManager.class);
1759                     if (connectivityManager.getLinkProperties(network) == null) {
1760                         Log.e(TAG, "Network " + network + " has null LinkProperties!");
1761                         return;
1762                     }
1763 
1764                     tunnelConfig = mApnNameToTunnelConfig.get(apnName);
1765                     tunnelInterface = tunnelConfig.getIface();
1766                     try {
1767                         tunnelInterface.setUnderlyingNetwork(network);
1768                     } catch (IOException | IllegalArgumentException e) {
1769                         Log.e(
1770                                 TAG,
1771                                 "Failed to update underlying network for apn: "
1772                                         + apnName
1773                                         + " exception: "
1774                                         + e);
1775                     }
1776                     break;
1777 
1778                 default:
1779                     throw new IllegalStateException("Unexpected value: " + msg.what);
1780             }
1781         }
1782 
TmHandler(Looper looper)1783         TmHandler(Looper looper) {
1784             super(looper);
1785         }
1786     }
1787 
closeIkeSession(String apnName, IwlanError error)1788     private void closeIkeSession(String apnName, IwlanError error) {
1789         TunnelConfig tunnelConfig = mApnNameToTunnelConfig.get(apnName);
1790         tunnelConfig.setError(error);
1791         tunnelConfig.getIkeSession().close();
1792     }
1793 
selectEpdgAddress(TunnelSetupRequest setupRequest)1794     private void selectEpdgAddress(TunnelSetupRequest setupRequest) {
1795         mLocalAddresses = getAddressForNetwork(mNetwork, mContext);
1796         if (mLocalAddresses == null || mLocalAddresses.size() == 0) {
1797             Log.e(TAG, "No local addresses available.");
1798             failAllPendingRequests(
1799                     new IwlanError(IwlanError.EPDG_SELECTOR_SERVER_SELECTION_FAILED));
1800             return;
1801         }
1802 
1803         mProtoFilter = EpdgSelector.PROTO_FILTER_IPV4V6;
1804         if (!IwlanHelper.hasIpv6Address(mLocalAddresses)) {
1805             mProtoFilter = EpdgSelector.PROTO_FILTER_IPV4;
1806         }
1807         if (!IwlanHelper.hasIpv4Address(mLocalAddresses)) {
1808             mProtoFilter = EpdgSelector.PROTO_FILTER_IPV6;
1809         }
1810 
1811         mEpdgServerSelectionStartTime = System.currentTimeMillis();
1812         EpdgSelector epdgSelector = getEpdgSelector();
1813         IwlanError epdgError =
1814                 epdgSelector.getValidatedServerList(
1815                         ++mTransactionId,
1816                         mProtoFilter,
1817                         setupRequest.isRoaming(),
1818                         setupRequest.isEmergency(),
1819                         mNetwork,
1820                         mSelectorCallback);
1821 
1822         if (epdgError.getErrorType() != IwlanError.NO_ERROR) {
1823             Log.e(TAG, "Epdg address selection failed with error:" + epdgError);
1824             failAllPendingRequests(epdgError);
1825         }
1826     }
1827 
1828     @VisibleForTesting
getEpdgSelector()1829     EpdgSelector getEpdgSelector() {
1830         return EpdgSelector.getSelectorInstance(mContext, mSlotId);
1831     }
1832 
1833     @VisibleForTesting
closePendingRequestsForApn(String apnName)1834     int closePendingRequestsForApn(String apnName) {
1835         int numRequestsClosed = 0;
1836         int queueSize = mPendingBringUpRequests.size();
1837         if (queueSize == 0) {
1838             return numRequestsClosed;
1839         }
1840 
1841         for (int count = 0; count < queueSize; count++) {
1842             TunnelRequestWrapper requestWrapper = mPendingBringUpRequests.poll();
1843             if (requestWrapper.getSetupRequest().apnName() == apnName) {
1844                 requestWrapper
1845                         .getTunnelCallback()
1846                         .onClosed(apnName, new IwlanError(IwlanError.NO_ERROR));
1847 
1848                 requestWrapper
1849                         .getTunnelCallbackMetrics()
1850                         .onClosed(
1851                                 apnName,
1852                                 mEpdgAddress == null ? null : mEpdgAddress.getHostAddress(),
1853                                 0,
1854                                 0);
1855                 numRequestsClosed++;
1856             } else {
1857                 mPendingBringUpRequests.add(requestWrapper);
1858             }
1859         }
1860         return numRequestsClosed;
1861     }
1862 
1863     @VisibleForTesting
validateAndSetEpdgAddress(List<InetAddress> selectorResultList)1864     void validateAndSetEpdgAddress(List<InetAddress> selectorResultList) {
1865         List<InetAddress> addrList = mValidEpdgInfo.getAddrList();
1866         if (addrList == null || !addrList.equals(selectorResultList)) {
1867             Log.d(TAG, "Update ePDG address list.");
1868             mValidEpdgInfo.setAddrList(selectorResultList);
1869             addrList = mValidEpdgInfo.getAddrList();
1870         }
1871 
1872         int index = mValidEpdgInfo.getIndex();
1873         Log.d(
1874                 TAG,
1875                 "Valid ePDG Address List: "
1876                         + Arrays.toString(addrList.toArray())
1877                         + ", index = "
1878                         + index);
1879         mEpdgAddress = addrList.get(index);
1880         mValidEpdgInfo.incrementIndex();
1881     }
1882 
1883     @VisibleForTesting
resetTunnelManagerState()1884     void resetTunnelManagerState() {
1885         Log.d(TAG, "resetTunnelManagerState");
1886         mEpdgAddress = null;
1887         setIsEpdgAddressSelected(false);
1888         mNetwork = null;
1889         mPendingBringUpRequests = new LinkedList<>();
1890         mApnNameToTunnelConfig = new ConcurrentHashMap<>();
1891         mLocalAddresses = null;
1892     }
1893 
serviceAllPendingRequests()1894     private void serviceAllPendingRequests() {
1895         while (!mPendingBringUpRequests.isEmpty()) {
1896             Log.d(TAG, "serviceAllPendingRequests");
1897             TunnelRequestWrapper request = mPendingBringUpRequests.poll();
1898             onBringUpTunnel(
1899                     request.getSetupRequest(),
1900                     request.getTunnelCallback(),
1901                     request.getTunnelCallbackMetrics());
1902         }
1903     }
1904 
failAllPendingRequests(IwlanError error)1905     private void failAllPendingRequests(IwlanError error) {
1906         while (!mPendingBringUpRequests.isEmpty()) {
1907             Log.d(TAG, "failAllPendingRequests");
1908             TunnelRequestWrapper request = mPendingBringUpRequests.poll();
1909             TunnelSetupRequest setupRequest = request.getSetupRequest();
1910             reportIwlanError(setupRequest.apnName(), error);
1911             request.getTunnelCallback().onClosed(setupRequest.apnName(), error);
1912             request.getTunnelCallbackMetrics()
1913                     .onClosed(
1914                             setupRequest.apnName(),
1915                             mEpdgAddress == null ? null : mEpdgAddress.getHostAddress(),
1916                             0,
1917                             0);
1918         }
1919     }
1920 
1921     // Prints mPendingBringUpRequests
printRequestQueue(String info)1922     private void printRequestQueue(String info) {
1923         Log.d(TAG, info);
1924         Log.d(
1925                 TAG,
1926                 "mPendingBringUpRequests: " + Arrays.toString(mPendingBringUpRequests.toArray()));
1927     }
1928 
1929     // Update Network wrapper
1930     private static final class UpdateNetworkWrapper {
1931         private final Network mNetwork;
1932         private final String mApnName;
1933 
UpdateNetworkWrapper(Network network, String apnName)1934         private UpdateNetworkWrapper(Network network, String apnName) {
1935             mNetwork = network;
1936             mApnName = apnName;
1937         }
1938 
getApnName()1939         public String getApnName() {
1940             return mApnName;
1941         }
1942 
getNetwork()1943         public Network getNetwork() {
1944             return mNetwork;
1945         }
1946     }
1947     // Tunnel request + tunnel callback
1948     private static final class TunnelRequestWrapper {
1949         private final TunnelSetupRequest mSetupRequest;
1950 
1951         private final TunnelCallback mTunnelCallback;
1952         private final TunnelCallbackMetrics mTunnelCallbackMetrics;
1953 
TunnelRequestWrapper( TunnelSetupRequest setupRequest, TunnelCallback tunnelCallback, TunnelCallbackMetrics tunnelCallbackMetrics)1954         private TunnelRequestWrapper(
1955                 TunnelSetupRequest setupRequest,
1956                 TunnelCallback tunnelCallback,
1957                 TunnelCallbackMetrics tunnelCallbackMetrics) {
1958             mTunnelCallback = tunnelCallback;
1959             mSetupRequest = setupRequest;
1960             mTunnelCallbackMetrics = tunnelCallbackMetrics;
1961         }
1962 
getSetupRequest()1963         public TunnelSetupRequest getSetupRequest() {
1964             return mSetupRequest;
1965         }
1966 
getTunnelCallback()1967         public TunnelCallback getTunnelCallback() {
1968             return mTunnelCallback;
1969         }
1970 
getTunnelCallbackMetrics()1971         public TunnelCallbackMetrics getTunnelCallbackMetrics() {
1972             return mTunnelCallbackMetrics;
1973         }
1974     }
1975 
1976     private static final class EpdgSelectorResult {
1977         private final List<InetAddress> mValidIpList;
1978 
getValidIpList()1979         public List<InetAddress> getValidIpList() {
1980             return mValidIpList;
1981         }
1982 
getEpdgError()1983         public IwlanError getEpdgError() {
1984             return mEpdgError;
1985         }
1986 
getTransactionId()1987         public int getTransactionId() {
1988             return mTransactionId;
1989         }
1990 
1991         private final IwlanError mEpdgError;
1992         private final int mTransactionId;
1993 
EpdgSelectorResult( List<InetAddress> validIpList, IwlanError epdgError, int transactionId)1994         private EpdgSelectorResult(
1995                 List<InetAddress> validIpList, IwlanError epdgError, int transactionId) {
1996             mValidIpList = validIpList;
1997             mEpdgError = epdgError;
1998             mTransactionId = transactionId;
1999         }
2000     }
2001 
2002     // Data received from IkeSessionStateMachine on successful EVENT_CHILD_SESSION_OPENED.
2003     private static final class TunnelOpenedData extends IkeEventData {
2004         final List<InetAddress> mInternalDnsServers;
2005         final List<LinkAddress> mInternalAddresses;
2006 
TunnelOpenedData( String apnName, int token, List<InetAddress> internalDnsServers, List<LinkAddress> internalAddresses)2007         private TunnelOpenedData(
2008                 String apnName,
2009                 int token,
2010                 List<InetAddress> internalDnsServers,
2011                 List<LinkAddress> internalAddresses) {
2012             super(apnName, token);
2013             mInternalDnsServers = internalDnsServers;
2014             mInternalAddresses = internalAddresses;
2015         }
2016     }
2017 
2018     // Data received from IkeSessionStateMachine on successful EVENT_IKE_SESSION_OPENED.
2019     private static final class IkeSessionOpenedData extends IkeEventData {
2020         final IkeSessionConfiguration mIkeSessionConfiguration;
2021 
IkeSessionOpenedData( String apnName, int token, IkeSessionConfiguration ikeSessionConfiguration)2022         private IkeSessionOpenedData(
2023                 String apnName, int token, IkeSessionConfiguration ikeSessionConfiguration) {
2024             super(apnName, token);
2025             mIkeSessionConfiguration = ikeSessionConfiguration;
2026         }
2027     }
2028 
2029     private static final class IkeSessionConnectionInfoData extends IkeEventData {
2030         final IkeSessionConnectionInfo mIkeSessionConnectionInfo;
2031 
IkeSessionConnectionInfoData( String apnName, int token, IkeSessionConnectionInfo ikeSessionConnectionInfo)2032         private IkeSessionConnectionInfoData(
2033                 String apnName, int token, IkeSessionConnectionInfo ikeSessionConnectionInfo) {
2034             super(apnName, token);
2035             mIkeSessionConnectionInfo = ikeSessionConnectionInfo;
2036         }
2037     }
2038 
2039     // Data received from IkeSessionStateMachine if either IKE session or Child session have been
2040     // closed, normally or exceptionally.
2041     private static final class SessionClosedData extends IkeEventData {
2042         final IwlanError mIwlanError;
2043 
SessionClosedData(String apnName, int token, IwlanError iwlanError)2044         private SessionClosedData(String apnName, int token, IwlanError iwlanError) {
2045             super(apnName, token);
2046             mIwlanError = iwlanError;
2047         }
2048     }
2049 
releaseInstance()2050     public void releaseInstance() {
2051         mHandlerThread.quit();
2052         mTunnelManagerInstances.remove(mSlotId);
2053     }
2054 
2055     private static final class IpsecTransformData extends IkeEventData {
2056         private final IpSecTransform mTransform;
2057         private final int mDirection;
2058 
IpsecTransformData( IpSecTransform transform, int direction, String apnName, int token)2059         private IpsecTransformData(
2060                 IpSecTransform transform, int direction, String apnName, int token) {
2061             super(apnName, token);
2062             mTransform = transform;
2063             mDirection = direction;
2064         }
2065 
getTransform()2066         public IpSecTransform getTransform() {
2067             return mTransform;
2068         }
2069 
getDirection()2070         public int getDirection() {
2071             return mDirection;
2072         }
2073 
getApnName()2074         public String getApnName() {
2075             return super.mApnName;
2076         }
2077     }
2078 
2079     private abstract static class IkeEventData {
2080         final String mApnName;
2081         final int mToken;
2082 
IkeEventData(String apnName, int token)2083         private IkeEventData(String apnName, int token) {
2084             mApnName = apnName;
2085             mToken = token;
2086         }
2087     }
2088 
2089     private static final class EpdgInfo {
2090         private List<InetAddress> mAddrList;
2091         private int mIndex;
2092 
EpdgInfo()2093         private EpdgInfo() {
2094             mAddrList = null;
2095             mIndex = 0;
2096         }
2097 
getAddrList()2098         public List<InetAddress> getAddrList() {
2099             return mAddrList;
2100         }
2101 
setAddrList(@onNull List<InetAddress> AddrList)2102         public void setAddrList(@NonNull List<InetAddress> AddrList) {
2103             mAddrList = AddrList;
2104             resetIndex();
2105         }
2106 
getIndex()2107         public int getIndex() {
2108             return mIndex;
2109         }
2110 
incrementIndex()2111         public void incrementIndex() {
2112             if (getIndex() >= getAddrList().size() - 1) {
2113                 resetIndex();
2114             } else {
2115                 mIndex++;
2116             }
2117         }
2118 
resetIndex()2119         public void resetIndex() {
2120             mIndex = 0;
2121         }
2122     }
2123 
getRetransmissionTimeoutsFromConfig()2124     private int[] getRetransmissionTimeoutsFromConfig() {
2125         int[] timeList =
2126                 (int[]) getConfig(CarrierConfigManager.Iwlan.KEY_RETRANSMIT_TIMER_MSEC_INT_ARRAY);
2127         boolean isValid = true;
2128         if (timeList == null
2129                 || timeList.length == 0
2130                 || timeList.length > IKE_RETRANS_MAX_ATTEMPTS_MAX) {
2131             isValid = false;
2132         }
2133         for (int time : timeList) {
2134             if (time < IKE_RETRANS_TIMEOUT_MS_MIN || time > IKE_RETRANS_TIMEOUT_MS_MAX) {
2135                 isValid = false;
2136                 break;
2137             }
2138         }
2139         if (!isValid) {
2140             timeList =
2141                     (int[])
2142                             IwlanHelper.getDefaultConfig(
2143                                     CarrierConfigManager.Iwlan.KEY_RETRANSMIT_TIMER_MSEC_INT_ARRAY);
2144         }
2145         Log.d(TAG, "getRetransmissionTimeoutsFromConfig: " + Arrays.toString(timeList));
2146         return timeList;
2147     }
2148 
getDpdDelayFromConfig()2149     private int getDpdDelayFromConfig() {
2150         int dpdDelay = (int) getConfig(CarrierConfigManager.Iwlan.KEY_DPD_TIMER_SEC_INT);
2151         if (dpdDelay < IKE_DPD_DELAY_SEC_MIN || dpdDelay > IKE_DPD_DELAY_SEC_MAX) {
2152             dpdDelay =
2153                     (int)
2154                             IwlanHelper.getDefaultConfig(
2155                                     CarrierConfigManager.Iwlan.KEY_DPD_TIMER_SEC_INT);
2156         }
2157         return dpdDelay;
2158     }
2159 
2160     /**
2161      * Decodes backoff time as per TS 124 008 10.5.7.4a Bits 5 to 1 represent the binary coded timer
2162      * value
2163      *
2164      * <p>Bits 6 to 8 defines the timer value unit for the GPRS timer as follows: Bits 8 7 6 0 0 0
2165      * value is incremented in multiples of 10 minutes 0 0 1 value is incremented in multiples of 1
2166      * hour 0 1 0 value is incremented in multiples of 10 hours 0 1 1 value is incremented in
2167      * multiples of 2 seconds 1 0 0 value is incremented in multiples of 30 seconds 1 0 1 value is
2168      * incremented in multiples of 1 minute 1 1 0 value is incremented in multiples of 1 hour 1 1 1
2169      * value indicates that the timer is deactivated.
2170      *
2171      * @param backoffTimerByte Byte value obtained from ike
2172      * @return long time value in seconds. -1 if the timer needs to be deactivated.
2173      */
decodeBackoffTime(byte backoffTimeByte)2174     private static long decodeBackoffTime(byte backoffTimeByte) {
2175         final int BACKOFF_TIME_VALUE_MASK = 0x1F;
2176         final int BACKOFF_TIMER_UNIT_MASK = 0xE0;
2177         final Long[] BACKOFF_TIMER_UNIT_INCREMENT_SECS = {
2178             10L * 60L, // 10 mins
2179             1L * 60L * 60L, // 1 hour
2180             10L * 60L * 60L, // 10 hours
2181             2L, // 2 seconds
2182             30L, // 30 seconds
2183             1L * 60L, // 1 minute
2184             1L * 60L * 60L, // 1 hour
2185         };
2186 
2187         long time = backoffTimeByte & BACKOFF_TIME_VALUE_MASK;
2188         int timerUnit = (backoffTimeByte & BACKOFF_TIMER_UNIT_MASK) >> 5;
2189         if (timerUnit >= BACKOFF_TIMER_UNIT_INCREMENT_SECS.length) {
2190             return -1;
2191         }
2192         time *= BACKOFF_TIMER_UNIT_INCREMENT_SECS[timerUnit];
2193         return time;
2194     }
2195 
2196     @VisibleForTesting
getTunnelSetupRequestApnName(TunnelSetupRequest setupRequest)2197     String getTunnelSetupRequestApnName(TunnelSetupRequest setupRequest) {
2198         String apnName = setupRequest.apnName();
2199         return apnName;
2200     }
2201 
2202     @VisibleForTesting
putApnNameToTunnelConfig( String apnName, IkeSession ikeSession, TunnelCallback tunnelCallback, TunnelCallbackMetrics tunnelCallbackMetrics, InetAddress srcIpv6Addr, int srcIPv6AddrPrefixLen)2203     void putApnNameToTunnelConfig(
2204             String apnName,
2205             IkeSession ikeSession,
2206             TunnelCallback tunnelCallback,
2207             TunnelCallbackMetrics tunnelCallbackMetrics,
2208             InetAddress srcIpv6Addr,
2209             int srcIPv6AddrPrefixLen) {
2210         mApnNameToTunnelConfig.put(
2211                 apnName,
2212                 new TunnelConfig(
2213                         ikeSession,
2214                         tunnelCallback,
2215                         tunnelCallbackMetrics,
2216                         srcIpv6Addr,
2217                         srcIPv6AddrPrefixLen));
2218         Log.d(TAG, "Added apn: " + apnName + " to TunnelConfig");
2219     }
2220 
2221     @VisibleForTesting
incrementAndGetCurrentTokenForApn(String apnName)2222     int incrementAndGetCurrentTokenForApn(String apnName) {
2223         final int currentToken =
2224                 mApnNameToCurrentToken.compute(
2225                         apnName, (apn, token) -> token == null ? 0 : token + 1);
2226         Log.d(TAG, "Added token: " + currentToken + " for apn: " + apnName);
2227         return currentToken;
2228     }
2229 
2230     @VisibleForTesting
isN1ModeSupported()2231     boolean isN1ModeSupported() {
2232         int[] nrCarrierCaps =
2233                 getConfig(CarrierConfigManager.KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY);
2234         Log.d(TAG, "KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY : " + Arrays.toString(nrCarrierCaps));
2235         if (Arrays.stream(nrCarrierCaps)
2236                 .anyMatch(cap -> cap == CarrierConfigManager.CARRIER_NR_AVAILABILITY_SA)) {
2237             return true;
2238         } else return false;
2239     }
2240 
2241     @VisibleForTesting
isTunnelConfigContainExistApn(String apnName)2242     boolean isTunnelConfigContainExistApn(String apnName) {
2243         boolean ret = mApnNameToTunnelConfig.containsKey(apnName);
2244         return ret;
2245     }
2246 
2247     @VisibleForTesting
getAddressForNetwork(Network network, Context context)2248     List<InetAddress> getAddressForNetwork(Network network, Context context) {
2249         List<InetAddress> ret = IwlanHelper.getAddressesForNetwork(network, context);
2250         return ret;
2251     }
2252 
2253     @VisibleForTesting
getSelectorCallback()2254     EpdgSelector.EpdgSelectorCallback getSelectorCallback() {
2255         return mSelectorCallback;
2256     }
2257 
2258     @VisibleForTesting
getIkeSessionCreator()2259     IkeSessionCreator getIkeSessionCreator() {
2260         return mIkeSessionCreator;
2261     }
2262 
2263     @VisibleForTesting
sendSelectionRequestComplete( ArrayList<InetAddress> validIPList, IwlanError result, int transactionId)2264     void sendSelectionRequestComplete(
2265             ArrayList<InetAddress> validIPList, IwlanError result, int transactionId) {
2266         mEpdgServerSelectionDuration = System.currentTimeMillis() - mEpdgServerSelectionStartTime;
2267         mEpdgServerSelectionStartTime = 0;
2268         EpdgSelectorResult epdgSelectorResult =
2269                 new EpdgSelectorResult(validIPList, result, transactionId);
2270         mHandler.sendMessage(
2271                 mHandler.obtainMessage(
2272                         EVENT_EPDG_ADDRESS_SELECTION_REQUEST_COMPLETE, epdgSelectorResult));
2273     }
2274 
isValidApnProtocol(int proto)2275     static boolean isValidApnProtocol(int proto) {
2276         return (proto == ApnSetting.PROTOCOL_IP
2277                 || proto == ApnSetting.PROTOCOL_IPV4V6
2278                 || proto == ApnSetting.PROTOCOL_IPV6);
2279     }
2280 
isObsoleteToken(String apnName, int token)2281     boolean isObsoleteToken(String apnName, int token) {
2282         if (!mApnNameToCurrentToken.containsKey(apnName)) {
2283             return true;
2284         }
2285         return token != mApnNameToCurrentToken.get(apnName);
2286     }
2287 
eventToString(int event)2288     private static String eventToString(int event) {
2289         switch (event) {
2290             case EVENT_TUNNEL_BRINGUP_REQUEST:
2291                 return "EVENT_TUNNEL_BRINGUP_REQUEST";
2292             case EVENT_TUNNEL_BRINGDOWN_REQUEST:
2293                 return "EVENT_TUNNEL_BRINGDOWN_REQUEST";
2294             case EVENT_CHILD_SESSION_OPENED:
2295                 return "EVENT_CHILD_SESSION_OPENED";
2296             case EVENT_CHILD_SESSION_CLOSED:
2297                 return "EVENT_CHILD_SESSION_CLOSED";
2298             case EVENT_IKE_SESSION_CLOSED:
2299                 return "EVENT_IKE_SESSION_CLOSED";
2300             case EVENT_EPDG_ADDRESS_SELECTION_REQUEST_COMPLETE:
2301                 return "EVENT_EPDG_ADDRESS_SELECTION_REQUEST_COMPLETE";
2302             case EVENT_IPSEC_TRANSFORM_CREATED:
2303                 return "EVENT_IPSEC_TRANSFORM_CREATED";
2304             case EVENT_IPSEC_TRANSFORM_DELETED:
2305                 return "EVENT_IPSEC_TRANSFORM_DELETED";
2306             case EVENT_UPDATE_NETWORK:
2307                 return "EVENT_UPDATE_NETWORK";
2308             case EVENT_IKE_SESSION_OPENED:
2309                 return "EVENT_IKE_SESSION_OPENED";
2310             case EVENT_IKE_SESSION_CONNECTION_INFO_CHANGED:
2311                 return "EVENT_IKE_SESSION_CONNECTION_INFO_CHANGED";
2312             default:
2313                 return "Unknown(" + event + ")";
2314         }
2315     }
2316 
2317     @VisibleForTesting
getTmIkeSessionCallback(String apnName, int token)2318     TmIkeSessionCallback getTmIkeSessionCallback(String apnName, int token) {
2319         return new TmIkeSessionCallback(apnName, token);
2320     }
2321 
2322     @VisibleForTesting
setIsEpdgAddressSelected(boolean value)2323     void setIsEpdgAddressSelected(boolean value) {
2324         mIsEpdgAddressSelected = value;
2325     }
2326 
2327     @VisibleForTesting
getTunnelConfigForApn(String apnName)2328     TunnelConfig getTunnelConfigForApn(String apnName) {
2329         return mApnNameToTunnelConfig.get(apnName);
2330     }
2331 
2332     @VisibleForTesting
getCurrentTokenForApn(String apnName)2333     int getCurrentTokenForApn(String apnName) {
2334         if (!mApnNameToCurrentToken.containsKey(apnName)) {
2335             throw new IllegalArgumentException("There is no token for apn: " + apnName);
2336         }
2337         return mApnNameToCurrentToken.get(apnName);
2338     }
2339 
2340     @VisibleForTesting
reportIwlanError(String apnName, IwlanError error)2341     long reportIwlanError(String apnName, IwlanError error) {
2342         return ErrorPolicyManager.getInstance(mContext, mSlotId).reportIwlanError(apnName, error);
2343     }
2344 
2345     @VisibleForTesting
reportIwlanError(String apnName, IwlanError error, long backOffTime)2346     long reportIwlanError(String apnName, IwlanError error, long backOffTime) {
2347         return ErrorPolicyManager.getInstance(mContext, mSlotId)
2348                 .reportIwlanError(apnName, error, backOffTime);
2349     }
2350 
2351     @VisibleForTesting
getLastError(String apnName)2352     IwlanError getLastError(String apnName) {
2353         return ErrorPolicyManager.getInstance(mContext, mSlotId).getLastError(apnName);
2354     }
2355 
2356     @VisibleForTesting
canBringUpTunnel(String apnName)2357     boolean canBringUpTunnel(String apnName) {
2358         return ErrorPolicyManager.getInstance(mContext, mSlotId).canBringUpTunnel(apnName);
2359     }
2360 
2361     @VisibleForTesting
setEpdgAddress(InetAddress inetAddress)2362     void setEpdgAddress(InetAddress inetAddress) {
2363         mEpdgAddress = inetAddress;
2364     }
2365 
dump(FileDescriptor fd, PrintWriter pw, String[] args)2366     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2367         pw.println("---- EpdgTunnelManager ----");
2368         pw.println("mIsEpdgAddressSelected: " + mIsEpdgAddressSelected);
2369         if (mEpdgAddress != null) {
2370             pw.println("mEpdgAddress: " + mEpdgAddress);
2371         }
2372         pw.println("mApnNameToTunnelConfig:\n");
2373         for (Map.Entry<String, TunnelConfig> entry : mApnNameToTunnelConfig.entrySet()) {
2374             pw.println("APN: " + entry.getKey());
2375             pw.println("TunnelConfig: " + entry.getValue());
2376             pw.println();
2377         }
2378         pw.println("---------------------------");
2379     }
2380 }
2381