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;
18 
19 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
20 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
21 import static android.net.ipsec.ike.ike3gpp.Ike3gppParams.PDU_SESSION_ID_UNSET;
22 import static android.telephony.PreciseDataConnectionState.NetworkValidationStatus;
23 
24 import static com.google.android.iwlan.epdg.EpdgTunnelManager.BRINGDOWN_REASON_DEACTIVATE_DATA_CALL;
25 import static com.google.android.iwlan.epdg.EpdgTunnelManager.BRINGDOWN_REASON_IN_DEACTIVATING_STATE;
26 import static com.google.android.iwlan.epdg.EpdgTunnelManager.BRINGDOWN_REASON_NETWORK_UPDATE_WHEN_TUNNEL_IN_BRINGUP;
27 import static com.google.android.iwlan.epdg.EpdgTunnelManager.BRINGDOWN_REASON_SERVICE_OUT_OF_SYNC;
28 
29 import android.content.Context;
30 import android.content.Intent;
31 import android.net.ConnectivityManager;
32 import android.net.LinkAddress;
33 import android.net.LinkProperties;
34 import android.net.Network;
35 import android.net.NetworkCapabilities;
36 import android.net.NetworkSpecifier;
37 import android.net.TelephonyNetworkSpecifier;
38 import android.net.TransportInfo;
39 import android.net.vcn.VcnTransportInfo;
40 import android.net.wifi.WifiInfo;
41 import android.net.wifi.WifiManager;
42 import android.os.Handler;
43 import android.os.HandlerThread;
44 import android.os.IBinder;
45 import android.os.Looper;
46 import android.os.Message;
47 import android.support.annotation.IntRange;
48 import android.support.annotation.NonNull;
49 import android.support.annotation.Nullable;
50 import android.telephony.AccessNetworkConstants.AccessNetworkType;
51 import android.telephony.CarrierConfigManager;
52 import android.telephony.CellInfo;
53 import android.telephony.CellInfoGsm;
54 import android.telephony.CellInfoLte;
55 import android.telephony.CellInfoNr;
56 import android.telephony.CellInfoWcdma;
57 import android.telephony.DataFailCause;
58 import android.telephony.PreciseDataConnectionState;
59 import android.telephony.TelephonyManager;
60 import android.telephony.data.ApnSetting;
61 import android.telephony.data.DataCallResponse;
62 import android.telephony.data.DataProfile;
63 import android.telephony.data.DataService;
64 import android.telephony.data.DataServiceCallback;
65 import android.telephony.data.NetworkSliceInfo;
66 import android.telephony.data.TrafficDescriptor;
67 import android.util.Log;
68 
69 import com.android.internal.annotations.VisibleForTesting;
70 
71 import com.google.android.iwlan.TunnelMetricsInterface.OnClosedMetrics;
72 import com.google.android.iwlan.TunnelMetricsInterface.OnOpenedMetrics;
73 import com.google.android.iwlan.epdg.EpdgSelector;
74 import com.google.android.iwlan.epdg.EpdgTunnelManager;
75 import com.google.android.iwlan.epdg.TunnelLinkProperties;
76 import com.google.android.iwlan.epdg.TunnelSetupRequest;
77 import com.google.android.iwlan.flags.FeatureFlags;
78 import com.google.android.iwlan.flags.FeatureFlagsImpl;
79 import com.google.android.iwlan.proto.MetricsAtom;
80 
81 import java.io.FileDescriptor;
82 import java.io.PrintWriter;
83 import java.net.Inet4Address;
84 import java.net.Inet6Address;
85 import java.net.InetAddress;
86 import java.net.UnknownHostException;
87 import java.util.ArrayList;
88 import java.util.Arrays;
89 import java.util.Calendar;
90 import java.util.Date;
91 import java.util.HashMap;
92 import java.util.List;
93 import java.util.LongSummaryStatistics;
94 import java.util.Map;
95 import java.util.Objects;
96 import java.util.concurrent.ConcurrentHashMap;
97 import java.util.concurrent.Executor;
98 import java.util.function.Consumer;
99 
100 public class IwlanDataService extends DataService {
101 
102     private final FeatureFlags mFeatureFlags;
103     private static final String TAG = IwlanDataService.class.getSimpleName();
104 
105     private static final String CONTEXT_ATTRIBUTION_TAG = "IWLAN";
106     private static Context mContext;
107     private IwlanNetworkMonitorCallback mNetworkMonitorCallback;
108     private static boolean sNetworkConnected = false;
109     private static Network sNetwork = null;
110     private static LinkProperties sLinkProperties = null;
111     private static NetworkCapabilities sNetworkCapabilities;
112     @VisibleForTesting Handler mIwlanDataServiceHandler;
113     private HandlerThread mIwlanDataServiceHandlerThread;
114     private static final Map<Integer, IwlanDataServiceProvider> sIwlanDataServiceProviders =
115             new ConcurrentHashMap<>();
116     private static final int INVALID_SUB_ID = -1;
117 
118     // The current subscription with the active internet PDN. Need not be the default data sub.
119     // If internet is over WiFi, this value will be INVALID_SUB_ID.
120     private static int mConnectedDataSub = INVALID_SUB_ID;
121 
122     private static final int EVENT_BASE = IwlanEventListener.DATA_SERVICE_INTERNAL_EVENT_BASE;
123     private static final int EVENT_TUNNEL_OPENED = EVENT_BASE;
124     private static final int EVENT_TUNNEL_CLOSED = EVENT_BASE + 1;
125     private static final int EVENT_SETUP_DATA_CALL = EVENT_BASE + 2;
126     private static final int EVENT_DEACTIVATE_DATA_CALL = EVENT_BASE + 3;
127     private static final int EVENT_DATA_CALL_LIST_REQUEST = EVENT_BASE + 4;
128     private static final int EVENT_FORCE_CLOSE_TUNNEL = EVENT_BASE + 5;
129     private static final int EVENT_ADD_DATA_SERVICE_PROVIDER = EVENT_BASE + 6;
130     private static final int EVENT_REMOVE_DATA_SERVICE_PROVIDER = EVENT_BASE + 7;
131     private static final int EVENT_TUNNEL_OPENED_METRICS = EVENT_BASE + 8;
132     private static final int EVENT_TUNNEL_CLOSED_METRICS = EVENT_BASE + 9;
133     private static final int EVENT_DEACTIVATE_DATA_CALL_WITH_DELAY = EVENT_BASE + 10;
134     private static final int EVENT_ON_LIVENESS_STATUS_CHANGED = EVENT_BASE + 11;
135     private static final int EVENT_REQUEST_NETWORK_VALIDATION = EVENT_BASE + 12;
136 
137     @VisibleForTesting
138     enum Transport {
139         UNSPECIFIED_NETWORK,
140         MOBILE,
141         WIFI
142     }
143 
144     private static Transport sDefaultDataTransport = Transport.UNSPECIFIED_NETWORK;
145 
146     private boolean mIs5GEnabledOnUi;
147 
IwlanDataService()148     public IwlanDataService() {
149         mFeatureFlags = new FeatureFlagsImpl();
150     }
151 
152     @VisibleForTesting
IwlanDataService(FeatureFlags featureFlags)153     IwlanDataService(FeatureFlags featureFlags) {
154         mFeatureFlags = featureFlags;
155     }
156 
157     // TODO: see if network monitor callback impl can be shared between dataservice and
158     // networkservice
159     // This callback runs in the same thread as IwlanDataServiceHandler
160     static class IwlanNetworkMonitorCallback extends ConnectivityManager.NetworkCallback {
IwlanNetworkMonitorCallback()161         IwlanNetworkMonitorCallback() {
162             super(ConnectivityManager.NetworkCallback.FLAG_INCLUDE_LOCATION_INFO);
163         }
164 
165         /** Called when the framework connects and has declared a new network ready for use. */
166         @Override
onAvailable(@onNull Network network)167         public void onAvailable(@NonNull Network network) {
168             Log.d(TAG, "onAvailable: " + network);
169         }
170 
171         /**
172          * Called when the network is about to be lost, typically because there are no outstanding
173          * requests left for it. This may be paired with a {@link NetworkCallback#onAvailable} call
174          * with the new replacement network for graceful handover. This method is not guaranteed to
175          * be called before {@link NetworkCallback#onLost} is called, for example in case a network
176          * is suddenly disconnected.
177          */
178         @Override
onLosing(@onNull Network network, int maxMsToLive)179         public void onLosing(@NonNull Network network, int maxMsToLive) {
180             Log.d(TAG, "onLosing: maxMsToLive: " + maxMsToLive + " network: " + network);
181         }
182 
183         /**
184          * Called when a network disconnects or otherwise no longer satisfies this request or
185          * callback.
186          */
187         @Override
onLost(@onNull Network network)188         public void onLost(@NonNull Network network) {
189             Log.d(TAG, "onLost: " + network);
190             IwlanDataService.setConnectedDataSub(INVALID_SUB_ID);
191             IwlanDataService.setNetworkConnected(false, network, Transport.UNSPECIFIED_NETWORK);
192         }
193 
194         /** Called when the network corresponding to this request changes {@link LinkProperties}. */
195         @Override
onLinkPropertiesChanged( @onNull Network network, @NonNull LinkProperties linkProperties)196         public void onLinkPropertiesChanged(
197                 @NonNull Network network, @NonNull LinkProperties linkProperties) {
198             Log.d(TAG, "onLinkPropertiesChanged: " + linkProperties);
199 
200             if (!network.equals(sNetwork)) {
201                 Log.d(TAG, "Ignore LinkProperties changes for unused Network.");
202                 return;
203             }
204 
205             if (!linkProperties.equals(sLinkProperties)) {
206                 for (IwlanDataServiceProvider dp : sIwlanDataServiceProviders.values()) {
207                     dp.dnsPrefetchCheck();
208                     sLinkProperties = linkProperties;
209                     dp.updateNetwork(network, linkProperties);
210                 }
211             }
212         }
213 
214         /** Called when access to the specified network is blocked or unblocked. */
215         @Override
onBlockedStatusChanged(@onNull Network network, boolean blocked)216         public void onBlockedStatusChanged(@NonNull Network network, boolean blocked) {
217             // TODO: check if we need to handle this
218             Log.d(TAG, "onBlockedStatusChanged: " + network + " BLOCKED:" + blocked);
219         }
220 
221         @Override
onCapabilitiesChanged( @onNull Network network, @NonNull NetworkCapabilities networkCapabilities)222         public void onCapabilitiesChanged(
223                 @NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) {
224             // onCapabilitiesChanged is guaranteed to be called immediately after onAvailable per
225             // API
226             Log.d(TAG, "onCapabilitiesChanged: " + network + " " + networkCapabilities);
227             if (networkCapabilities != null) {
228                 if (networkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
229                     Log.d(TAG, "Network " + network + " connected using transport MOBILE");
230                     IwlanDataService.setConnectedDataSub(getConnectedDataSub(networkCapabilities));
231                     IwlanDataService.setNetworkConnected(true, network, Transport.MOBILE);
232                 } else if (networkCapabilities.hasTransport(TRANSPORT_WIFI)) {
233                     Log.d(TAG, "Network " + network + " connected using transport WIFI");
234                     IwlanDataService.setConnectedDataSub(INVALID_SUB_ID);
235                     IwlanDataService.setNetworkCapabilities(networkCapabilities);
236                     IwlanDataService.setNetworkConnected(true, network, Transport.WIFI);
237                 } else {
238                     Log.w(TAG, "Network does not have cellular or wifi capability");
239                 }
240             }
241         }
242     }
243 
244     @VisibleForTesting
245     class IwlanDataServiceProvider extends DataService.DataServiceProvider {
246         private static final int CALLBACK_TYPE_SETUP_DATACALL_COMPLETE = 1;
247         private static final int CALLBACK_TYPE_DEACTIVATE_DATACALL_COMPLETE = 2;
248         private static final int CALLBACK_TYPE_GET_DATACALL_LIST_COMPLETE = 3;
249 
250         private final String SUB_TAG;
251         private final IwlanDataService mIwlanDataService;
252         private final IwlanTunnelCallback mIwlanTunnelCallback;
253         private final IwlanTunnelMetricsImpl mIwlanTunnelMetrics;
254         private boolean mWfcEnabled = false;
255         private boolean mCarrierConfigReady = false;
256         private final EpdgSelector mEpdgSelector;
257         private final IwlanDataTunnelStats mTunnelStats;
258         private CellInfo mCellInfo = null;
259         private int mCallState = TelephonyManager.CALL_STATE_IDLE;
260         private long mProcessingStartTime = 0;
261 
262         // apn to TunnelState
263         // Access should be serialized inside IwlanDataServiceHandler
264         private final Map<String, TunnelState> mTunnelStateForApn = new ConcurrentHashMap<>();
265         private final Map<String, MetricsAtom> mMetricsAtomForApn = new ConcurrentHashMap<>();
266         private Calendar mCalendar;
267 
268         // Holds the state of a tunnel (for an APN)
269         @VisibleForTesting
270         class TunnelState {
271 
272             // this should be ideally be based on path MTU discovery. 1280 is the minimum packet
273             // size ipv6 routers have to handle so setting it to 1280 is the safest approach.
274             // ideally it should be 1280 - tunnelling overhead ?
275             private static final int LINK_MTU = 1280; // TODO: need to subtract tunnelling overhead?
276             private static final int LINK_MTU_CST = 1200; // Reserve 80 bytes for VCN.
277             static final int TUNNEL_DOWN = 1;
278             static final int TUNNEL_IN_BRINGUP = 2;
279             static final int TUNNEL_UP = 3;
280             static final int TUNNEL_IN_BRINGDOWN = 4;
281             static final int TUNNEL_IN_FORCE_CLEAN_WAS_IN_BRINGUP = 5;
282             private DataServiceCallback dataServiceCallback;
283             private int mState;
284             private int mPduSessionId;
285             private TunnelLinkProperties mTunnelLinkProperties;
286             private boolean mIsHandover;
287             private Date mBringUpStateTime = null;
288             private Date mUpStateTime = null;
289             private boolean mIsImsOrEmergency;
290             private DeactivateDataCallData mPendingDeactivateDataCallData;
291             private boolean mIsDataCallWithN1;
292             private int mNetworkValidationStatus =
293                     PreciseDataConnectionState.NETWORK_VALIDATION_SUCCESS;
294             private int mApnTypeBitmask;
295 
getIsDataCallWithN1()296             public boolean getIsDataCallWithN1() {
297                 return mIsDataCallWithN1;
298             }
299 
setIsDataCallWithN1(boolean mIsDataCallWithN1)300             public void setIsDataCallWithN1(boolean mIsDataCallWithN1) {
301                 this.mIsDataCallWithN1 = mIsDataCallWithN1;
302             }
303 
getPduSessionId()304             public int getPduSessionId() {
305                 return mPduSessionId;
306             }
307 
setPduSessionId(int mPduSessionId)308             public void setPduSessionId(int mPduSessionId) {
309                 this.mPduSessionId = mPduSessionId;
310             }
311 
getLinkMtu()312             public int getLinkMtu() {
313                 if ((sDefaultDataTransport == Transport.MOBILE) && sNetworkConnected) {
314                     return LINK_MTU_CST;
315                 } else {
316                     return LINK_MTU; // TODO: need to subtract tunnelling overhead
317                 }
318             }
319 
getRequestedProtocolType()320             public @ApnSetting.ProtocolType int getRequestedProtocolType() {
321                 return mProtocolType;
322             }
323 
setProtocolType(int protocolType)324             public void setProtocolType(int protocolType) {
325                 mProtocolType = protocolType;
326             }
327 
328             private int mProtocolType; // from DataProfile
329 
getTunnelLinkProperties()330             public TunnelLinkProperties getTunnelLinkProperties() {
331                 return mTunnelLinkProperties;
332             }
333 
setTunnelLinkProperties(TunnelLinkProperties tunnelLinkProperties)334             public void setTunnelLinkProperties(TunnelLinkProperties tunnelLinkProperties) {
335                 mTunnelLinkProperties = tunnelLinkProperties;
336             }
337 
getDataServiceCallback()338             public DataServiceCallback getDataServiceCallback() {
339                 return dataServiceCallback;
340             }
341 
setDataServiceCallback(DataServiceCallback dataServiceCallback)342             public void setDataServiceCallback(DataServiceCallback dataServiceCallback) {
343                 this.dataServiceCallback = dataServiceCallback;
344             }
345 
TunnelState(DataServiceCallback callback)346             public TunnelState(DataServiceCallback callback) {
347                 dataServiceCallback = callback;
348                 mState = TUNNEL_DOWN;
349             }
350 
getState()351             public int getState() {
352                 return mState;
353             }
354 
getPendingDeactivateDataCallData()355             public DeactivateDataCallData getPendingDeactivateDataCallData() {
356                 return mPendingDeactivateDataCallData;
357             }
358 
hasPendingDeactivateDataCallData()359             public boolean hasPendingDeactivateDataCallData() {
360                 return mPendingDeactivateDataCallData != null;
361             }
362 
363             /**
364              * @param state (TunnelState.TUNNEL_DOWN|TUNNEL_UP|TUNNEL_DOWN)
365              */
setState(int state)366             public void setState(int state) {
367                 mState = state;
368                 if (mState == TunnelState.TUNNEL_IN_BRINGUP) {
369                     mBringUpStateTime = mCalendar.getTime();
370                 }
371                 if (mState == TunnelState.TUNNEL_UP) {
372                     mUpStateTime = mCalendar.getTime();
373                 }
374             }
375 
setIsHandover(boolean isHandover)376             public void setIsHandover(boolean isHandover) {
377                 mIsHandover = isHandover;
378             }
379 
getIsHandover()380             public boolean getIsHandover() {
381                 return mIsHandover;
382             }
383 
getBringUpStateTime()384             public Date getBringUpStateTime() {
385                 return mBringUpStateTime;
386             }
387 
getUpStateTime()388             public Date getUpStateTime() {
389                 return mUpStateTime;
390             }
391 
getCurrentTime()392             public Date getCurrentTime() {
393                 return mCalendar.getTime();
394             }
395 
getIsImsOrEmergency()396             public boolean getIsImsOrEmergency() {
397                 return mIsImsOrEmergency;
398             }
399 
setIsImsOrEmergency(boolean isImsOrEmergency)400             public void setIsImsOrEmergency(boolean isImsOrEmergency) {
401                 mIsImsOrEmergency = isImsOrEmergency;
402             }
403 
setPendingDeactivateDataCallData( DeactivateDataCallData deactivateDataCallData)404             public void setPendingDeactivateDataCallData(
405                     DeactivateDataCallData deactivateDataCallData) {
406                 mPendingDeactivateDataCallData = deactivateDataCallData;
407             }
408 
setNetworkValidationStatus(int networkValidationStatus)409             public void setNetworkValidationStatus(int networkValidationStatus) {
410                 mNetworkValidationStatus = networkValidationStatus;
411             }
412 
getNetworkValidationStatus()413             public int getNetworkValidationStatus() {
414                 return mNetworkValidationStatus;
415             }
416 
setApnTypeBitmask(int apnTypeBitmask)417             public void setApnTypeBitmask(int apnTypeBitmask) {
418                 mApnTypeBitmask = apnTypeBitmask;
419             }
420 
hasApnType(int apnType)421             public boolean hasApnType(int apnType) {
422                 return (mApnTypeBitmask & apnType) != 0;
423             }
424 
425             @Override
toString()426             public String toString() {
427                 StringBuilder sb = new StringBuilder();
428                 String tunnelState = "UNKNOWN";
429                 switch (mState) {
430                     case TUNNEL_DOWN:
431                         tunnelState = "DOWN";
432                         break;
433                     case TUNNEL_IN_BRINGUP:
434                         tunnelState = "IN BRINGUP";
435                         break;
436                     case TUNNEL_UP:
437                         tunnelState = "UP";
438                         break;
439                     case TUNNEL_IN_BRINGDOWN:
440                         tunnelState = "IN BRINGDOWN";
441                         break;
442                     case TUNNEL_IN_FORCE_CLEAN_WAS_IN_BRINGUP:
443                         tunnelState = "IN FORCE CLEAN WAS IN BRINGUP";
444                         break;
445                 }
446                 sb.append("\tCurrent State of this tunnel: ")
447                         .append(mState)
448                         .append(" ")
449                         .append(tunnelState);
450                 sb.append("\n\tTunnel state is in Handover: ").append(mIsHandover);
451                 if (mBringUpStateTime != null) {
452                     sb.append("\n\tTunnel bring up initiated at: ").append(mBringUpStateTime);
453                 } else {
454                     sb.append("\n\tPotential leak. Null mBringUpStateTime");
455                 }
456                 if (mUpStateTime != null) {
457                     sb.append("\n\tTunnel is up at: ").append(mUpStateTime);
458                 }
459                 if (mUpStateTime != null && mBringUpStateTime != null) {
460                     long tunnelUpTime = mUpStateTime.getTime() - mBringUpStateTime.getTime();
461                     sb.append("\n\tTime taken for the tunnel to come up in ms: ")
462                             .append(tunnelUpTime);
463                 }
464                 sb.append("\n\tCurrent network validation status: ")
465                         .append(mNetworkValidationStatus);
466                 return sb.toString();
467             }
468         }
469 
470         @VisibleForTesting
471         class IwlanTunnelCallback implements EpdgTunnelManager.TunnelCallback {
472 
473             IwlanDataServiceProvider mIwlanDataServiceProvider;
474 
IwlanTunnelCallback(IwlanDataServiceProvider dsp)475             public IwlanTunnelCallback(IwlanDataServiceProvider dsp) {
476                 mIwlanDataServiceProvider = dsp;
477             }
478 
479             // TODO: full implementation
480 
onOpened(String apnName, TunnelLinkProperties linkProperties)481             public void onOpened(String apnName, TunnelLinkProperties linkProperties) {
482                 Log.d(
483                         SUB_TAG,
484                         "Tunnel opened! APN: " + apnName + ", linkProperties: " + linkProperties);
485                 getIwlanDataServiceHandler()
486                         .sendMessage(
487                                 getIwlanDataServiceHandler()
488                                         .obtainMessage(
489                                                 EVENT_TUNNEL_OPENED,
490                                                 new TunnelOpenedData(
491                                                         apnName,
492                                                         linkProperties,
493                                                         mIwlanDataServiceProvider)));
494             }
495 
onClosed(String apnName, IwlanError error)496             public void onClosed(String apnName, IwlanError error) {
497                 Log.d(SUB_TAG, "Tunnel closed! APN: " + apnName + ", Error: " + error);
498                 // this is called, when a tunnel that is up, is closed.
499                 // the expectation is error==NO_ERROR for user initiated/normal close.
500                 getIwlanDataServiceHandler()
501                         .sendMessage(
502                                 getIwlanDataServiceHandler()
503                                         .obtainMessage(
504                                                 EVENT_TUNNEL_CLOSED,
505                                                 new TunnelClosedData(
506                                                         apnName,
507                                                         error,
508                                                         mIwlanDataServiceProvider)));
509             }
510 
onNetworkValidationStatusChanged( String apnName, @NetworkValidationStatus int status)511             public void onNetworkValidationStatusChanged(
512                     String apnName, @NetworkValidationStatus int status) {
513                 Log.d(
514                         SUB_TAG,
515                         "Liveness status changed. APN: "
516                                 + apnName
517                                 + ", status: "
518                                 + PreciseDataConnectionState.networkValidationStatusToString(
519                                         status));
520                 getIwlanDataServiceHandler()
521                         .obtainMessage(
522                                 EVENT_ON_LIVENESS_STATUS_CHANGED,
523                                 new TunnelValidationStatusData(
524                                         apnName, status, mIwlanDataServiceProvider))
525                         .sendToTarget();
526             }
527         }
528 
529         /** Holds all tunnel related time and count statistics for this IwlanDataServiceProvider */
530         @VisibleForTesting
531         class IwlanDataTunnelStats {
532 
533             // represents the start time from when the following events are recorded
534             private Date mStartTime;
535 
536             // Stats for TunnelSetup Success time (BRING_UP -> UP state)
537             @VisibleForTesting
538             Map<String, LongSummaryStatistics> mTunnelSetupSuccessStats =
539                     new HashMap<String, LongSummaryStatistics>();
540 
541             // Count for Tunnel Setup failures onClosed when in BRING_UP
542             @VisibleForTesting
543             Map<String, Long> mTunnelSetupFailureCounts = new HashMap<String, Long>();
544 
545             // Count for unsol tunnel down onClosed when in UP without deactivate
546             @VisibleForTesting
547             Map<String, Long> mUnsolTunnelDownCounts = new HashMap<String, Long>();
548 
549             // Stats for how long the tunnel is in up state onClosed when in UP
550             @VisibleForTesting
551             Map<String, LongSummaryStatistics> mTunnelUpStats =
552                     new HashMap<String, LongSummaryStatistics>();
553 
554             private long statCount;
555             private final long COUNT_MAX = 1000;
556 
IwlanDataTunnelStats()557             public IwlanDataTunnelStats() {
558                 mStartTime = mCalendar.getTime();
559                 statCount = 0L;
560             }
561 
reportTunnelSetupSuccess(String apn, TunnelState tunnelState)562             public void reportTunnelSetupSuccess(String apn, TunnelState tunnelState) {
563                 if (statCount > COUNT_MAX || maxApnReached()) {
564                     reset();
565                 }
566                 statCount++;
567 
568                 Date bringUpTime = tunnelState.getBringUpStateTime();
569                 Date upTime = tunnelState.getUpStateTime();
570 
571                 if (bringUpTime != null && upTime != null) {
572                     long tunnelUpTime = upTime.getTime() - bringUpTime.getTime();
573                     if (!mTunnelSetupSuccessStats.containsKey(apn)) {
574                         mTunnelSetupSuccessStats.put(apn, new LongSummaryStatistics());
575                     }
576                     LongSummaryStatistics stats = mTunnelSetupSuccessStats.get(apn);
577                     stats.accept(tunnelUpTime);
578                     mTunnelSetupSuccessStats.put(apn, stats);
579                 }
580             }
581 
reportTunnelDown(String apn, TunnelState tunnelState)582             public void reportTunnelDown(String apn, TunnelState tunnelState) {
583                 if (statCount > COUNT_MAX || maxApnReached()) {
584                     reset();
585                 }
586                 statCount++;
587 
588                 // Setup fail
589                 if (tunnelState.getState() == TunnelState.TUNNEL_IN_BRINGUP) {
590                     if (!mTunnelSetupFailureCounts.containsKey(apn)) {
591                         mTunnelSetupFailureCounts.put(apn, 0L);
592                     }
593                     long count = mTunnelSetupFailureCounts.get(apn);
594                     mTunnelSetupFailureCounts.put(apn, ++count);
595                     return;
596                 }
597 
598                 // Unsolicited tunnel down as tunnel has to be in BRINGDOWN if
599                 // there is a deactivateDataCall() associated with this.
600                 if (tunnelState.getState() == TunnelState.TUNNEL_UP) {
601                     if (!mUnsolTunnelDownCounts.containsKey(apn)) {
602                         mUnsolTunnelDownCounts.put(apn, 0L);
603                     }
604                     long count = mUnsolTunnelDownCounts.get(apn);
605                     mUnsolTunnelDownCounts.put(apn, ++count);
606                 }
607                 Date currentTime = tunnelState.getCurrentTime();
608                 Date upTime = tunnelState.getUpStateTime();
609                 if (upTime != null) {
610                     if (!mTunnelUpStats.containsKey(apn)) {
611                         mTunnelUpStats.put(apn, new LongSummaryStatistics());
612                     }
613                     LongSummaryStatistics stats = mTunnelUpStats.get(apn);
614                     stats.accept(currentTime.getTime() - upTime.getTime());
615                     mTunnelUpStats.put(apn, stats);
616                 }
617             }
618 
maxApnReached()619             boolean maxApnReached() {
620                 int APN_COUNT_MAX = 10;
621                 return mTunnelSetupSuccessStats.size() >= APN_COUNT_MAX
622                         || mTunnelSetupFailureCounts.size() >= APN_COUNT_MAX
623                         || mUnsolTunnelDownCounts.size() >= APN_COUNT_MAX
624                         || mTunnelUpStats.size() >= APN_COUNT_MAX;
625             }
626 
627             @Override
toString()628             public String toString() {
629                 StringBuilder sb = new StringBuilder();
630                 sb.append("IwlanDataTunnelStats:");
631                 sb.append("\n\tmStartTime: ").append(mStartTime);
632                 sb.append("\n\ttunnelSetupSuccessStats:");
633                 for (Map.Entry<String, LongSummaryStatistics> entry :
634                         mTunnelSetupSuccessStats.entrySet()) {
635                     sb.append("\n\t  Apn: ").append(entry.getKey());
636                     sb.append("\n\t  ").append(entry.getValue());
637                 }
638                 sb.append("\n\ttunnelUpStats:");
639                 for (Map.Entry<String, LongSummaryStatistics> entry : mTunnelUpStats.entrySet()) {
640                     sb.append("\n\t  Apn: ").append(entry.getKey());
641                     sb.append("\n\t  ").append(entry.getValue());
642                 }
643 
644                 sb.append("\n\ttunnelSetupFailureCounts: ");
645                 for (Map.Entry<String, Long> entry : mTunnelSetupFailureCounts.entrySet()) {
646                     sb.append("\n\t  Apn: ").append(entry.getKey());
647                     sb.append("\n\t  counts: ").append(entry.getValue());
648                 }
649                 sb.append("\n\tunsolTunnelDownCounts: ");
650                 for (Map.Entry<String, Long> entry : mTunnelSetupFailureCounts.entrySet()) {
651                     sb.append("\n\t  Apn: ").append(entry.getKey());
652                     sb.append("\n\t  counts: ").append(entry.getValue());
653                 }
654                 sb.append("\n\tendTime: ").append(mCalendar.getTime());
655                 return sb.toString();
656             }
657 
reset()658             private void reset() {
659                 mStartTime = mCalendar.getTime();
660                 mTunnelSetupSuccessStats = new HashMap<String, LongSummaryStatistics>();
661                 mTunnelUpStats = new HashMap<String, LongSummaryStatistics>();
662                 mTunnelSetupFailureCounts = new HashMap<String, Long>();
663                 mUnsolTunnelDownCounts = new HashMap<String, Long>();
664                 statCount = 0L;
665             }
666         }
667 
668         /**
669          * Constructor
670          *
671          * @param slotIndex SIM slot index the data service provider associated with.
672          */
IwlanDataServiceProvider(int slotIndex, IwlanDataService iwlanDataService)673         public IwlanDataServiceProvider(int slotIndex, IwlanDataService iwlanDataService) {
674             super(slotIndex);
675             SUB_TAG = TAG + "[" + slotIndex + "]";
676 
677             // TODO:
678             // get reference carrier config for this sub
679             // get reference to resolver
680             mIwlanDataService = iwlanDataService;
681             mIwlanTunnelCallback = new IwlanTunnelCallback(this);
682             mIwlanTunnelMetrics = new IwlanTunnelMetricsImpl(this, getIwlanDataServiceHandler());
683             mEpdgSelector = EpdgSelector.getSelectorInstance(mContext, slotIndex);
684             mCalendar = Calendar.getInstance();
685             mTunnelStats = new IwlanDataTunnelStats();
686 
687             // Register IwlanEventListener
688             List<Integer> events = new ArrayList<Integer>();
689             events.add(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT);
690             events.add(IwlanEventListener.CARRIER_CONFIG_UNKNOWN_CARRIER_EVENT);
691             events.add(IwlanEventListener.WIFI_CALLING_ENABLE_EVENT);
692             events.add(IwlanEventListener.WIFI_CALLING_DISABLE_EVENT);
693             events.add(IwlanEventListener.CROSS_SIM_CALLING_ENABLE_EVENT);
694             events.add(IwlanEventListener.CELLINFO_CHANGED_EVENT);
695             events.add(IwlanEventListener.CALL_STATE_CHANGED_EVENT);
696             events.add(IwlanEventListener.PREFERRED_NETWORK_TYPE_CHANGED_EVENT);
697             IwlanEventListener.getInstance(mContext, slotIndex)
698                     .addEventListener(events, getIwlanDataServiceHandler());
699         }
700 
getTunnelManager()701         private EpdgTunnelManager getTunnelManager() {
702             return EpdgTunnelManager.getInstance(mContext, getSlotIndex());
703         }
704 
705         // creates a DataCallResponse for an apn irrespective of state
apnTunnelStateToDataCallResponse(String apn)706         private DataCallResponse apnTunnelStateToDataCallResponse(String apn) {
707             TunnelState tunnelState = mTunnelStateForApn.get(apn);
708             if (tunnelState == null) {
709                 return null;
710             }
711 
712             DataCallResponse.Builder responseBuilder = new DataCallResponse.Builder();
713             int state = tunnelState.getState();
714             TunnelLinkProperties tunnelLinkProperties = tunnelState.getTunnelLinkProperties();
715             if (tunnelLinkProperties == null) {
716                 Log.d(TAG, "PDN with empty linkProperties. TunnelState : " + state);
717                 return responseBuilder.build();
718             }
719             responseBuilder
720                     .setId(apn.hashCode())
721                     .setProtocolType(tunnelLinkProperties.getProtocolType())
722                     .setCause(DataFailCause.NONE)
723                     .setLinkStatus(
724                             state == TunnelState.TUNNEL_UP
725                                     ? DataCallResponse.LINK_STATUS_ACTIVE
726                                     : DataCallResponse.LINK_STATUS_INACTIVE);
727 
728             // fill wildcard address for gatewayList (used by DataConnection to add routes)
729             List<InetAddress> gatewayList = new ArrayList<>();
730             List<LinkAddress> linkAddrList = tunnelLinkProperties.internalAddresses();
731             if (linkAddrList.stream().anyMatch(LinkAddress::isIpv4)) {
732                 try {
733                     gatewayList.add(Inet4Address.getByName("0.0.0.0"));
734                 } catch (UnknownHostException e) {
735                     // should never happen for static string 0.0.0.0
736                 }
737             }
738             if (linkAddrList.stream().anyMatch(LinkAddress::isIpv6)) {
739                 try {
740                     gatewayList.add(Inet6Address.getByName("::"));
741                 } catch (UnknownHostException e) {
742                     // should never happen for static string ::
743                 }
744             }
745 
746             if (tunnelLinkProperties.sliceInfo().isPresent()) {
747                 responseBuilder.setSliceInfo(tunnelLinkProperties.sliceInfo().get());
748             }
749 
750             return responseBuilder
751                     .setAddresses(linkAddrList)
752                     .setDnsAddresses(tunnelLinkProperties.dnsAddresses())
753                     .setPcscfAddresses(tunnelLinkProperties.pcscfAddresses())
754                     .setInterfaceName(tunnelLinkProperties.ifaceName())
755                     .setGatewayAddresses(gatewayList)
756                     .setMtuV4(tunnelState.getLinkMtu())
757                     .setMtuV6(tunnelState.getLinkMtu())
758                     .setPduSessionId(tunnelState.getPduSessionId())
759                     .setNetworkValidationStatus(tunnelState.getNetworkValidationStatus())
760                     .build(); // underlying n/w is same
761         }
762 
getCallList()763         private List<DataCallResponse> getCallList() {
764             List<DataCallResponse> dcList = new ArrayList<>();
765             for (String key : mTunnelStateForApn.keySet()) {
766                 DataCallResponse dcRsp = apnTunnelStateToDataCallResponse(key);
767                 if (dcRsp != null) {
768                     Log.d(SUB_TAG, "Apn: " + key + "Link state: " + dcRsp.getLinkStatus());
769                     dcList.add(dcRsp);
770                 }
771             }
772             return dcList;
773         }
774 
deliverCallback( int callbackType, int result, DataServiceCallback callback, DataCallResponse rsp)775         private void deliverCallback(
776                 int callbackType, int result, DataServiceCallback callback, DataCallResponse rsp) {
777             if (callback == null) {
778                 Log.d(SUB_TAG, "deliverCallback: callback is null.  callbackType:" + callbackType);
779                 return;
780             }
781             Log.d(
782                     SUB_TAG,
783                     "Delivering callbackType:"
784                             + callbackType
785                             + " result:"
786                             + result
787                             + " rsp:"
788                             + rsp);
789             switch (callbackType) {
790                 case CALLBACK_TYPE_DEACTIVATE_DATACALL_COMPLETE:
791                     callback.onDeactivateDataCallComplete(result);
792                     // always update current datacalllist
793                     notifyDataCallListChanged(getCallList());
794                     break;
795 
796                 case CALLBACK_TYPE_SETUP_DATACALL_COMPLETE:
797                     if (result == DataServiceCallback.RESULT_SUCCESS && rsp == null) {
798                         Log.d(SUB_TAG, "Warning: null rsp for success case");
799                     }
800                     callback.onSetupDataCallComplete(result, rsp);
801                     // always update current datacalllist
802                     notifyDataCallListChanged(getCallList());
803                     break;
804 
805                 case CALLBACK_TYPE_GET_DATACALL_LIST_COMPLETE:
806                     callback.onRequestDataCallListComplete(result, getCallList());
807                     // TODO: add code for the rest of the cases
808             }
809         }
810 
811         /**
812          * Setup a data connection.
813          *
814          * @param accessNetworkType Access network type that the data call will be established on.
815          *     Must be one of {@link android.telephony.AccessNetworkConstants.AccessNetworkType}.
816          * @param dataProfile Data profile used for data call setup. See {@link DataProfile}
817          * @param isRoaming True if the device is data roaming.
818          * @param allowRoaming True if data roaming is allowed by the user.
819          * @param reason The reason for data setup. Must be {@link #REQUEST_REASON_NORMAL} or {@link
820          *     #REQUEST_REASON_HANDOVER}.
821          * @param linkProperties If {@code reason} is {@link #REQUEST_REASON_HANDOVER}, this is the
822          *     link properties of the existing data connection, otherwise null.
823          * @param pduSessionId The pdu session id to be used for this data call. The standard range
824          *     of values are 1-15 while 0 means no pdu session id was attached to this call.
825          *     Reference: 3GPP TS 24.007 section 11.2.3.1b.
826          * @param sliceInfo The slice info related to this data call.
827          * @param trafficDescriptor TrafficDescriptor for which data connection needs to be
828          *     established. It is used for URSP traffic matching as described in 3GPP TS 24.526
829          *     Section 4.2.2. It includes an optional DNN which, if present, must be used for
830          *     traffic matching; it does not specify the end point to be used for the data call.
831          * @param matchAllRuleAllowed Indicates if using default match-all URSP rule for this
832          *     request is allowed. If false, this request must not use the match-all URSP rule and
833          *     if a non-match-all rule is not found (or if URSP rules are not available) then {@link
834          *     DataCallResponse#getCause()} is {@link
835          *     android.telephony.DataFailCause#MATCH_ALL_RULE_NOT_ALLOWED}. This is needed as some
836          *     requests need to have a hard failure if the intention cannot be met, for example, a
837          *     zero-rating slice.
838          * @param callback The result callback for this request.
839          */
840         @Override
setupDataCall( int accessNetworkType, @NonNull DataProfile dataProfile, boolean isRoaming, boolean allowRoaming, @SetupDataReason int reason, @Nullable LinkProperties linkProperties, @IntRange(from = 0, to = 15) int pduSessionId, @Nullable NetworkSliceInfo sliceInfo, @Nullable TrafficDescriptor trafficDescriptor, boolean matchAllRuleAllowed, @NonNull DataServiceCallback callback)841         public void setupDataCall(
842                 int accessNetworkType,
843                 @NonNull DataProfile dataProfile,
844                 boolean isRoaming,
845                 boolean allowRoaming,
846                 @SetupDataReason int reason,
847                 @Nullable LinkProperties linkProperties,
848                 @IntRange(from = 0, to = 15) int pduSessionId,
849                 @Nullable NetworkSliceInfo sliceInfo,
850                 @Nullable TrafficDescriptor trafficDescriptor,
851                 boolean matchAllRuleAllowed,
852                 @NonNull DataServiceCallback callback) {
853 
854             mProcessingStartTime = System.currentTimeMillis();
855             Log.d(
856                     SUB_TAG,
857                     "Setup data call with network: "
858                             + accessNetworkType
859                             + ", reason: "
860                             + requestReasonToString(reason)
861                             + ", pduSessionId: "
862                             + pduSessionId
863                             + ", DataProfile: "
864                             + dataProfile
865                             + ", isRoaming:"
866                             + isRoaming
867                             + ", allowRoaming: "
868                             + allowRoaming
869                             + ", linkProperties: "
870                             + linkProperties);
871 
872             SetupDataCallData setupDataCallData =
873                     new SetupDataCallData(
874                             accessNetworkType,
875                             dataProfile,
876                             isRoaming,
877                             allowRoaming,
878                             reason,
879                             linkProperties,
880                             pduSessionId,
881                             sliceInfo,
882                             trafficDescriptor,
883                             matchAllRuleAllowed,
884                             callback,
885                             this);
886 
887             int networkTransport = -1;
888             if (sDefaultDataTransport == Transport.MOBILE) {
889                 networkTransport = TRANSPORT_CELLULAR;
890             } else if (sDefaultDataTransport == Transport.WIFI) {
891                 networkTransport = TRANSPORT_WIFI;
892             }
893 
894             if (dataProfile != null) {
895                 ApnSetting apnSetting = dataProfile.getApnSetting();
896                 this.setMetricsAtom(
897                         // ApnName
898                         apnSetting != null ? apnSetting.getApnName() : "",
899                         // ApnType
900                         apnSetting != null ? apnSetting.getApnTypeBitmask() : ApnSetting.TYPE_NONE,
901                         // IsHandover
902                         (reason == DataService.REQUEST_REASON_HANDOVER),
903                         // Source Rat
904                         getCurrentCellularRat(),
905                         // IsRoaming
906                         isRoaming,
907                         // Is Network Connected
908                         sNetworkConnected,
909                         // Transport Type
910                         networkTransport);
911             }
912 
913             getIwlanDataServiceHandler()
914                     .sendMessage(
915                             getIwlanDataServiceHandler()
916                                     .obtainMessage(EVENT_SETUP_DATA_CALL, setupDataCallData));
917         }
918 
919         /**
920          * Deactivate a data connection. The data service provider must implement this method to
921          * support data connection tear down. When completed or error, the service must invoke the
922          * provided callback to notify the platform.
923          *
924          * <p>Note: For handovers, in compliance with 3GPP specs (TS 23.402 clause 8.6.1, TS 23.502
925          * clause 4.11.4.1), a {@link KEY_HANDOVER_TO_WWAN_RELEASE_DELAY_SECOND_INT} delay is
926          * implemented to allow the network to release the IKE tunnel. If the network fails to
927          * release it within this timeframe, the UE will take over the release process.
928          *
929          * @param cid Call id returned in the callback of {@link
930          *     DataServiceProvider#setupDataCall(int, DataProfile, boolean, boolean, int,
931          *     LinkProperties, DataServiceCallback)}.
932          * @param reason The reason for data deactivation. Must be {@link #REQUEST_REASON_NORMAL},
933          *     {@link #REQUEST_REASON_SHUTDOWN} or {@link #REQUEST_REASON_HANDOVER}.
934          * @param callback The result callback for this request. Null if the client does not care
935          */
936         @Override
deactivateDataCall( int cid, @DeactivateDataReason int reason, DataServiceCallback callback)937         public void deactivateDataCall(
938                 int cid, @DeactivateDataReason int reason, DataServiceCallback callback) {
939             Log.d(
940                     SUB_TAG,
941                     "Deactivate data call with reason: "
942                             + requestReasonToString(reason)
943                             + ", cid: "
944                             + cid
945                             + ", callback: "
946                             + callback);
947 
948             boolean isRequestForHandoverToWWAN = (reason == REQUEST_REASON_HANDOVER);
949 
950             int delayTimeSeconds = 0;
951             if (isRequestForHandoverToWWAN) {
952                 delayTimeSeconds =
953                         IwlanCarrierConfig.getConfigInt(
954                                 mContext,
955                                 getSlotIndex(),
956                                 IwlanCarrierConfig.KEY_HANDOVER_TO_WWAN_RELEASE_DELAY_SECOND_INT);
957             }
958 
959             int event =
960                     (delayTimeSeconds > 0)
961                             ? EVENT_DEACTIVATE_DATA_CALL_WITH_DELAY
962                             : EVENT_DEACTIVATE_DATA_CALL;
963 
964             DeactivateDataCallData deactivateDataCallData =
965                     new DeactivateDataCallData(cid, reason, callback, this, delayTimeSeconds);
966 
967             getIwlanDataServiceHandler()
968                     .obtainMessage(event, deactivateDataCallData)
969                     .sendToTarget();
970         }
971 
972         /**
973          * Requests validation check to see if the network is working properly for a given data
974          * call.
975          *
976          * <p>This request is completed immediately after submitting the request to the data service
977          * provider and receiving {@link DataServiceCallback.ResultCode}, and progress status or
978          * validation results are notified through {@link
979          * DataCallResponse#getNetworkValidationStatus}.
980          *
981          * <p>If the network validation request is submitted successfully, {@link
982          * DataServiceCallback#RESULT_SUCCESS} is passed to {@code resultCodeCallback}. If the
983          * network validation feature is not supported by the data service provider itself, {@link
984          * DataServiceCallback#RESULT_ERROR_UNSUPPORTED} is passed to {@code resultCodeCallback}.
985          * See {@link DataServiceCallback.ResultCode} for the type of response that indicates
986          * whether the request was successfully submitted or had an error.
987          *
988          * <p>In response to this network validation request, providers can validate the data call
989          * in their own way. For example, in IWLAN, the DPD (Dead Peer Detection) can be used as a
990          * tool to check whether a data call is alive.
991          *
992          * @param cid The identifier of the data call which is provided in {@link DataCallResponse}
993          * @param executor The callback executor for the response.
994          * @param resultCodeCallback Listener for the {@link DataServiceCallback.ResultCode} that
995          *     request validation to the DataService and checks if the request has been submitted.
996          */
997         @Override
requestNetworkValidation( int cid, Executor executor, Consumer<Integer> resultCodeCallback)998         public void requestNetworkValidation(
999                 int cid, Executor executor, Consumer<Integer> resultCodeCallback) {
1000             Objects.requireNonNull(executor, "executor cannot be null");
1001             Objects.requireNonNull(resultCodeCallback, "resultCodeCallback cannot be null");
1002             Log.d(TAG, "request Network Validation: " + cid);
1003 
1004             getIwlanDataServiceHandler()
1005                     .obtainMessage(
1006                             EVENT_REQUEST_NETWORK_VALIDATION,
1007                             new NetworkValidationInfo(cid, executor, resultCodeCallback, this))
1008                     .sendToTarget();
1009         }
1010 
forceCloseTunnelsInDeactivatingState()1011         public void forceCloseTunnelsInDeactivatingState() {
1012             for (Map.Entry<String, TunnelState> entry : mTunnelStateForApn.entrySet()) {
1013                 TunnelState tunnelState = entry.getValue();
1014                 if (tunnelState.getState() == TunnelState.TUNNEL_IN_BRINGDOWN) {
1015                     getTunnelManager()
1016                             .closeTunnel(
1017                                     entry.getKey(),
1018                                     true /* forceClose */,
1019                                     getIwlanTunnelCallback(),
1020                                     getIwlanTunnelMetrics(),
1021                                     BRINGDOWN_REASON_IN_DEACTIVATING_STATE);
1022                 }
1023             }
1024         }
1025 
1026         /**
1027          * Closes all tunnels forcefully for a specified reason.
1028          *
1029          * @param reason The reason for closing the tunnel. Must be {@link
1030          *     EpdgTunnelManager.TunnelBringDownReason}.
1031          */
forceCloseTunnels(@pdgTunnelManager.TunnelBringDownReason int reason)1032         void forceCloseTunnels(@EpdgTunnelManager.TunnelBringDownReason int reason) {
1033             for (Map.Entry<String, TunnelState> entry : mTunnelStateForApn.entrySet()) {
1034                 getTunnelManager()
1035                         .closeTunnel(
1036                                 entry.getKey(),
1037                                 true /* forceClose */,
1038                                 getIwlanTunnelCallback(),
1039                                 getIwlanTunnelMetrics(),
1040                                 reason);
1041             }
1042         }
1043 
1044         /**
1045          * Get the active data call list.
1046          *
1047          * @param callback The result callback for this request.
1048          */
1049         @Override
requestDataCallList(DataServiceCallback callback)1050         public void requestDataCallList(DataServiceCallback callback) {
1051             getIwlanDataServiceHandler()
1052                     .sendMessage(
1053                             getIwlanDataServiceHandler()
1054                                     .obtainMessage(
1055                                             EVENT_DATA_CALL_LIST_REQUEST,
1056                                             new DataCallRequestData(
1057                                                     callback, IwlanDataServiceProvider.this)));
1058         }
1059 
1060         @VisibleForTesting
setTunnelState( DataProfile dataProfile, DataServiceCallback callback, int tunnelStatus, TunnelLinkProperties linkProperties, boolean isHandover, int pduSessionId, boolean isImsOrEmergency, boolean isDataCallSetupWithN1)1061         protected void setTunnelState(
1062                 DataProfile dataProfile,
1063                 DataServiceCallback callback,
1064                 int tunnelStatus,
1065                 TunnelLinkProperties linkProperties,
1066                 boolean isHandover,
1067                 int pduSessionId,
1068                 boolean isImsOrEmergency,
1069                 boolean isDataCallSetupWithN1) {
1070             TunnelState tunnelState = new TunnelState(callback);
1071             tunnelState.setState(tunnelStatus);
1072             tunnelState.setProtocolType(dataProfile.getApnSetting().getProtocol());
1073             tunnelState.setTunnelLinkProperties(linkProperties);
1074             tunnelState.setIsHandover(isHandover);
1075             tunnelState.setPduSessionId(pduSessionId);
1076             tunnelState.setIsImsOrEmergency(isImsOrEmergency);
1077             tunnelState.setIsDataCallWithN1(isDataCallSetupWithN1);
1078             mTunnelStateForApn.put(dataProfile.getApnSetting().getApnName(), tunnelState);
1079             tunnelState.setApnTypeBitmask(dataProfile.getApnSetting().getApnTypeBitmask());
1080         }
1081 
1082         @VisibleForTesting
setMetricsAtom( String apnName, int apnType, boolean isHandover, int sourceRat, boolean isRoaming, boolean isNetworkConnected, int transportType)1083         void setMetricsAtom(
1084                 String apnName,
1085                 int apnType,
1086                 boolean isHandover,
1087                 int sourceRat,
1088                 boolean isRoaming,
1089                 boolean isNetworkConnected,
1090                 int transportType) {
1091             MetricsAtom metricsAtom = new MetricsAtom();
1092             metricsAtom.setApnType(apnType);
1093             metricsAtom.setIsHandover(isHandover);
1094             metricsAtom.setSourceRat(sourceRat);
1095             metricsAtom.setIsCellularRoaming(isRoaming);
1096             metricsAtom.setIsNetworkConnected(isNetworkConnected);
1097             metricsAtom.setTransportType(transportType);
1098             mMetricsAtomForApn.put(apnName, metricsAtom);
1099         }
1100 
1101         @VisibleForTesting
1102         @Nullable
getMetricsAtomByApn(String apnName)1103         public MetricsAtom getMetricsAtomByApn(String apnName) {
1104             return mMetricsAtomForApn.get(apnName);
1105         }
1106 
1107         @VisibleForTesting
getIwlanTunnelCallback()1108         public IwlanTunnelCallback getIwlanTunnelCallback() {
1109             return mIwlanTunnelCallback;
1110         }
1111 
1112         @VisibleForTesting
getIwlanTunnelMetrics()1113         public IwlanTunnelMetricsImpl getIwlanTunnelMetrics() {
1114             return mIwlanTunnelMetrics;
1115         }
1116 
1117         @VisibleForTesting
getTunnelStats()1118         IwlanDataTunnelStats getTunnelStats() {
1119             return mTunnelStats;
1120         }
1121 
updateNetwork( @ullable Network network, @Nullable LinkProperties linkProperties)1122         private void updateNetwork(
1123                 @Nullable Network network, @Nullable LinkProperties linkProperties) {
1124             if (isNetworkConnected(
1125                     isActiveDataOnOtherSub(getSlotIndex()),
1126                     IwlanHelper.isCrossSimCallingEnabled(mContext, getSlotIndex()))) {
1127                 getTunnelManager().updateNetwork(network, linkProperties);
1128             }
1129 
1130             if (Objects.equals(network, sNetwork)) {
1131                 return;
1132             }
1133             for (Map.Entry<String, TunnelState> entry : mTunnelStateForApn.entrySet()) {
1134                 TunnelState tunnelState = entry.getValue();
1135                 if (tunnelState.getState() == TunnelState.TUNNEL_IN_BRINGUP) {
1136                     // force close tunnels in bringup since IKE lib only supports
1137                     // updating network for tunnels that are already up.
1138                     // This may not result in actual closing of Ike Session since
1139                     // epdg selection may not be complete yet.
1140                     tunnelState.setState(TunnelState.TUNNEL_IN_FORCE_CLEAN_WAS_IN_BRINGUP);
1141                     getTunnelManager()
1142                             .closeTunnel(
1143                                     entry.getKey(),
1144                                     true /* forceClose */,
1145                                     getIwlanTunnelCallback(),
1146                                     getIwlanTunnelMetrics(),
1147                                     BRINGDOWN_REASON_NETWORK_UPDATE_WHEN_TUNNEL_IN_BRINGUP);
1148                 }
1149             }
1150         }
1151 
isRegisteredCellInfoChanged(List<CellInfo> cellInfoList)1152         private boolean isRegisteredCellInfoChanged(List<CellInfo> cellInfoList) {
1153             for (CellInfo cellInfo : cellInfoList) {
1154                 if (!cellInfo.isRegistered()) {
1155                     continue;
1156                 }
1157 
1158                 if (mCellInfo == null || mCellInfo != cellInfo) {
1159                     mCellInfo = cellInfo;
1160                     Log.d(TAG, " Update cached cellinfo");
1161                     return true;
1162                 }
1163             }
1164             return false;
1165         }
1166 
dnsPrefetchCheck()1167         private void dnsPrefetchCheck() {
1168             boolean networkConnected =
1169                     isNetworkConnected(
1170                             isActiveDataOnOtherSub(getSlotIndex()),
1171                             IwlanHelper.isCrossSimCallingEnabled(mContext, getSlotIndex()));
1172             /* Check if we need to do prefecting */
1173             if (networkConnected
1174                     && mCarrierConfigReady
1175                     && mWfcEnabled
1176                     && mTunnelStateForApn.isEmpty()) {
1177 
1178                 // Get roaming status
1179                 TelephonyManager telephonyManager =
1180                         mContext.getSystemService(TelephonyManager.class);
1181                 telephonyManager =
1182                         telephonyManager.createForSubscriptionId(
1183                                 IwlanHelper.getSubId(mContext, getSlotIndex()));
1184                 boolean isRoaming = telephonyManager.isNetworkRoaming();
1185                 Log.d(TAG, "Trigger EPDG prefetch. Roaming=" + isRoaming);
1186 
1187                 prefetchEpdgServerList(sNetwork, isRoaming);
1188             }
1189         }
1190 
prefetchEpdgServerList(Network network, boolean isRoaming)1191         private void prefetchEpdgServerList(Network network, boolean isRoaming) {
1192             mEpdgSelector.getValidatedServerList(
1193                     0,
1194                     EpdgSelector.PROTO_FILTER_IPV4V6,
1195                     EpdgSelector.SYSTEM_PREFERRED,
1196                     isRoaming,
1197                     false,
1198                     network,
1199                     null);
1200             mEpdgSelector.getValidatedServerList(
1201                     0,
1202                     EpdgSelector.PROTO_FILTER_IPV4V6,
1203                     EpdgSelector.SYSTEM_PREFERRED,
1204                     isRoaming,
1205                     true,
1206                     network,
1207                     null);
1208         }
1209 
getCurrentCellularRat()1210         private int getCurrentCellularRat() {
1211             TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class);
1212             telephonyManager =
1213                     telephonyManager.createForSubscriptionId(
1214                             IwlanHelper.getSubId(mContext, getSlotIndex()));
1215             List<CellInfo> cellInfoList = telephonyManager.getAllCellInfo();
1216             if (cellInfoList == null) {
1217                 Log.e(TAG, "cellInfoList is NULL");
1218                 return 0;
1219             }
1220 
1221             for (CellInfo cellInfo : cellInfoList) {
1222                 if (!cellInfo.isRegistered()) {
1223                     continue;
1224                 }
1225                 if (cellInfo instanceof CellInfoGsm) {
1226                     return TelephonyManager.NETWORK_TYPE_GSM;
1227                 } else if (cellInfo instanceof CellInfoWcdma) {
1228                     return TelephonyManager.NETWORK_TYPE_UMTS;
1229                 } else if (cellInfo instanceof CellInfoLte) {
1230                     return TelephonyManager.NETWORK_TYPE_LTE;
1231                 } else if (cellInfo instanceof CellInfoNr) {
1232                     return TelephonyManager.NETWORK_TYPE_NR;
1233                 }
1234             }
1235             return TelephonyManager.NETWORK_TYPE_UNKNOWN;
1236         }
1237 
1238         /* Determines if this subscription is in an active call */
isOnCall()1239         private boolean isOnCall() {
1240             return mCallState != TelephonyManager.CALL_STATE_IDLE;
1241         }
1242 
1243         /**
1244          * IMS and Emergency are not allowed to retry with initial attach during call to keep call
1245          * continuity. Other APNs like XCAP and MMS are allowed to retry with initial attach
1246          * regardless of the call state.
1247          */
shouldRetryWithInitialAttachForHandoverRequest( String apn, TunnelState tunnelState)1248         private boolean shouldRetryWithInitialAttachForHandoverRequest(
1249                 String apn, TunnelState tunnelState) {
1250             boolean isOnImsOrEmergencyCall = tunnelState.getIsImsOrEmergency() && isOnCall();
1251             return tunnelState.getIsHandover()
1252                     && !isOnImsOrEmergencyCall
1253                     && ErrorPolicyManager.getInstance(mContext, getSlotIndex())
1254                             .shouldRetryWithInitialAttach(apn);
1255         }
1256 
1257         /**
1258          * Called when the instance of data service is destroyed (e.g. got unbind or binder died) or
1259          * when the data service provider is removed.
1260          */
1261         @Override
close()1262         public void close() {
1263             // TODO: call epdgtunnelmanager.releaseInstance or equivalent
1264             mIwlanDataService.removeDataServiceProvider(this);
1265             IwlanEventListener iwlanEventListener =
1266                     IwlanEventListener.getInstance(mContext, getSlotIndex());
1267             iwlanEventListener.removeEventListener(getIwlanDataServiceHandler());
1268             iwlanEventListener.unregisterContentObserver();
1269         }
1270 
dump(FileDescriptor fd, PrintWriter pw, String[] args)1271         public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1272             pw.println("---- IwlanDataServiceProvider[" + getSlotIndex() + "] ----");
1273             boolean isDDS = IwlanHelper.isDefaultDataSlot(mContext, getSlotIndex());
1274             boolean isCSTEnabled = IwlanHelper.isCrossSimCallingEnabled(mContext, getSlotIndex());
1275             pw.println(
1276                     "isDefaultDataSlot: "
1277                             + isDDS
1278                             + "subID: "
1279                             + IwlanHelper.getSubId(mContext, getSlotIndex())
1280                             + " mConnectedDataSub: "
1281                             + mConnectedDataSub
1282                             + " isCrossSimEnabled: "
1283                             + isCSTEnabled);
1284             pw.println(
1285                     "isNetworkConnected: "
1286                             + isNetworkConnected(
1287                                     isActiveDataOnOtherSub(getSlotIndex()), isCSTEnabled)
1288                             + " Wfc enabled: "
1289                             + mWfcEnabled);
1290             for (Map.Entry<String, TunnelState> entry : mTunnelStateForApn.entrySet()) {
1291                 pw.println("Tunnel state for APN: " + entry.getKey());
1292                 pw.println(entry.getValue());
1293             }
1294             pw.println(mTunnelStats);
1295             EpdgTunnelManager.getInstance(mContext, getSlotIndex()).dump(pw);
1296             ErrorPolicyManager.getInstance(mContext, getSlotIndex()).dump(pw);
1297             pw.println("-------------------------------------");
1298         }
1299 
1300         @VisibleForTesting
setCalendar(Calendar c)1301         public void setCalendar(Calendar c) {
1302             mCalendar = c;
1303         }
1304 
isPdnReestablishNeededOnIdleN1Update()1305         private boolean isPdnReestablishNeededOnIdleN1Update() {
1306             return isN1ModeSupported() && (needIncludeN1ModeCapability() != mIs5GEnabledOnUi);
1307         }
1308 
disconnectPdnForN1ModeUpdate()1309         private void disconnectPdnForN1ModeUpdate() {
1310             if (hasActiveOrInitiatingDataCall()) {
1311                 Log.d(TAG, "Disconnect PDNs for N1 mode update");
1312                 forceCloseTunnels(
1313                         mIs5GEnabledOnUi
1314                                 ? EpdgTunnelManager.BRINGDOWN_REASON_ENABLE_N1_MODE
1315                                 : EpdgTunnelManager.BRINGDOWN_REASON_DISABLE_N1_MODE);
1316             }
1317         }
1318 
hasActiveOrInitiatingDataCall()1319         private boolean hasActiveOrInitiatingDataCall() {
1320             return mTunnelStateForApn.values().stream()
1321                     .anyMatch(
1322                             tunnelState ->
1323                                     tunnelState.getState() == TunnelState.TUNNEL_UP
1324                                             || tunnelState.getState()
1325                                                     == TunnelState.TUNNEL_IN_BRINGUP);
1326         }
1327 
1328         // TODO(b/309867756): Include N1_MODE_CAPABILITY inclusion status in metrics.
needIncludeN1ModeCapability()1329         private boolean needIncludeN1ModeCapability() {
1330             if (!IwlanCarrierConfig.getConfigBoolean(
1331                     mContext,
1332                     getSlotIndex(),
1333                     IwlanCarrierConfig.KEY_UPDATE_N1_MODE_ON_UI_CHANGE_BOOL)) {
1334                 return isN1ModeSupported();
1335             }
1336             if (!isN1ModeSupported()) {
1337                 return false;
1338             }
1339             // Maintain uniform N1_MODE_CAPABILITY Notify inclusion for all PDNs.
1340             // Initiate PDN with current N1 inclusion in tunnel_up or tunnel_in_bringup states;
1341             // otherwise, use UI settings.
1342             return hasActiveOrInitiatingDataCall() ? isDataCallSetupWithN1() : mIs5GEnabledOnUi;
1343         }
1344 
isDataCallSetupWithN1()1345         private boolean isDataCallSetupWithN1() {
1346             return mTunnelStateForApn.values().stream().anyMatch(TunnelState::getIsDataCallWithN1);
1347         }
1348 
isN1ModeSupported()1349         protected boolean isN1ModeSupported() {
1350             int[] nrAvailabilities =
1351                     IwlanCarrierConfig.getConfigIntArray(
1352                             mContext,
1353                             getSlotIndex(),
1354                             CarrierConfigManager.KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY);
1355             Log.d(
1356                     TAG,
1357                     "KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY : "
1358                             + Arrays.toString(nrAvailabilities));
1359             return Arrays.stream(nrAvailabilities)
1360                     .anyMatch(k -> k == CarrierConfigManager.CARRIER_NR_AVAILABILITY_SA);
1361         }
1362     }
1363 
1364     private final class IwlanDataServiceHandler extends Handler {
1365         private final String TAG = IwlanDataServiceHandler.class.getSimpleName();
1366 
1367         @Override
handleMessage(Message msg)1368         public void handleMessage(Message msg) {
1369             Log.d(TAG, "msg.what = " + eventToString(msg.what));
1370 
1371             String apnName;
1372             IwlanDataServiceProvider iwlanDataServiceProvider;
1373             IwlanDataServiceProvider.TunnelState tunnelState;
1374             DataServiceCallback callback;
1375             int reason;
1376             int slotId;
1377             int retryTimeMillis;
1378             int errorCause;
1379             MetricsAtom metricsAtom;
1380 
1381             switch (msg.what) {
1382                 case EVENT_TUNNEL_OPENED:
1383                     TunnelOpenedData tunnelOpenedData = (TunnelOpenedData) msg.obj;
1384                     iwlanDataServiceProvider = tunnelOpenedData.mIwlanDataServiceProvider;
1385                     apnName = tunnelOpenedData.mApnName;
1386                     TunnelLinkProperties tunnelLinkProperties =
1387                             tunnelOpenedData.mTunnelLinkProperties;
1388 
1389                     tunnelState = iwlanDataServiceProvider.mTunnelStateForApn.get(apnName);
1390                     // tunnelstate should not be null, design violation.
1391                     // if its null, we should crash and debug.
1392                     tunnelState.setTunnelLinkProperties(tunnelLinkProperties);
1393                     tunnelState.setState(IwlanDataServiceProvider.TunnelState.TUNNEL_UP);
1394                     iwlanDataServiceProvider.mTunnelStats.reportTunnelSetupSuccess(
1395                             apnName, tunnelState);
1396 
1397                     iwlanDataServiceProvider.deliverCallback(
1398                             IwlanDataServiceProvider.CALLBACK_TYPE_SETUP_DATACALL_COMPLETE,
1399                             DataServiceCallback.RESULT_SUCCESS,
1400                             tunnelState.getDataServiceCallback(),
1401                             iwlanDataServiceProvider.apnTunnelStateToDataCallResponse(apnName));
1402                     break;
1403 
1404                 case EVENT_TUNNEL_CLOSED:
1405                     TunnelClosedData tunnelClosedData = (TunnelClosedData) msg.obj;
1406                     iwlanDataServiceProvider = tunnelClosedData.mIwlanDataServiceProvider;
1407                     apnName = tunnelClosedData.mApnName;
1408                     IwlanError iwlanError = tunnelClosedData.mIwlanError;
1409 
1410                     tunnelState = iwlanDataServiceProvider.mTunnelStateForApn.get(apnName);
1411 
1412                     if (tunnelState == null) {
1413                         // On a successful handover to EUTRAN, the NW may initiate an IKE DEL before
1414                         // the UE initiates a deactivateDataCall(). There may be a race condition
1415                         // where the deactivateDataCall() arrives immediately before
1416                         // IwlanDataService receives EVENT_TUNNEL_CLOSED (and clears TunnelState).
1417                         // Even though there is no tunnel, EpdgTunnelManager will still process the
1418                         // bringdown request and send back an onClosed() to ensure state coherence.
1419                         if (iwlanError.getErrorType() != IwlanError.TUNNEL_NOT_FOUND) {
1420                             Log.w(
1421                                     TAG,
1422                                     "Tunnel state does not exist! Unexpected IwlanError: "
1423                                             + iwlanError);
1424                         }
1425                         break;
1426                     }
1427 
1428                     if (tunnelState.hasPendingDeactivateDataCallData()) {
1429                         // Iwlan delays handling EVENT_DEACTIVATE_DATA_CALL to give the network time
1430                         // to release the PDN.  This allows for immediate response to Telephony if
1431                         // the network releases the PDN before timeout. Otherwise, Telephony's PDN
1432                         // state waits for Iwlan, blocking further actions on this PDN.
1433                         cancelPendingDeactivationIfExists(
1434                                 tunnelState.getPendingDeactivateDataCallData());
1435                     }
1436 
1437                     iwlanDataServiceProvider.mTunnelStats.reportTunnelDown(apnName, tunnelState);
1438                     iwlanDataServiceProvider.mTunnelStateForApn.remove(apnName);
1439                     metricsAtom = iwlanDataServiceProvider.mMetricsAtomForApn.get(apnName);
1440 
1441                     if (tunnelState.getState()
1442                                     == IwlanDataServiceProvider.TunnelState.TUNNEL_IN_BRINGUP
1443                             || tunnelState.getState()
1444                                     == IwlanDataServiceProvider.TunnelState
1445                                             .TUNNEL_IN_FORCE_CLEAN_WAS_IN_BRINGUP) {
1446                         DataCallResponse.Builder respBuilder = new DataCallResponse.Builder();
1447                         respBuilder
1448                                 .setId(apnName.hashCode())
1449                                 .setProtocolType(tunnelState.getRequestedProtocolType());
1450 
1451                         if (iwlanDataServiceProvider.shouldRetryWithInitialAttachForHandoverRequest(
1452                                 apnName, tunnelState)) {
1453                             respBuilder.setHandoverFailureMode(
1454                                     DataCallResponse
1455                                             .HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_SETUP_NORMAL);
1456                             metricsAtom.setHandoverFailureMode(
1457                                     DataCallResponse
1458                                             .HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_SETUP_NORMAL);
1459                         } else if (tunnelState.getIsHandover()) {
1460                             respBuilder.setHandoverFailureMode(
1461                                     DataCallResponse
1462                                             .HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_HANDOVER);
1463                             metricsAtom.setHandoverFailureMode(
1464                                     DataCallResponse
1465                                             .HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_HANDOVER);
1466                         }
1467 
1468                         errorCause =
1469                                 ErrorPolicyManager.getInstance(
1470                                                 mContext, iwlanDataServiceProvider.getSlotIndex())
1471                                         .getDataFailCause(apnName);
1472                         if (errorCause != DataFailCause.NONE) {
1473                             respBuilder.setCause(errorCause);
1474                             metricsAtom.setDataCallFailCause(errorCause);
1475 
1476                             retryTimeMillis =
1477                                     (int)
1478                                             ErrorPolicyManager.getInstance(
1479                                                             mContext,
1480                                                             iwlanDataServiceProvider.getSlotIndex())
1481                                                     .getRemainingRetryTimeMs(apnName);
1482                             // TODO(b/343962773): Need to refactor into ErrorPolicyManager
1483                             if (!tunnelState.getIsHandover()
1484                                     && tunnelState.hasApnType(ApnSetting.TYPE_EMERGENCY)) {
1485                                 retryTimeMillis = DataCallResponse.RETRY_DURATION_UNDEFINED;
1486                             }
1487                             respBuilder.setRetryDurationMillis(retryTimeMillis);
1488                             metricsAtom.setRetryDurationMillis(retryTimeMillis);
1489                         } else {
1490                             // TODO(b/265215349): Use a different DataFailCause for scenario where
1491                             // tunnel in bringup is closed or force-closed without error.
1492                             respBuilder.setCause(DataFailCause.IWLAN_NETWORK_FAILURE);
1493                             metricsAtom.setDataCallFailCause(DataFailCause.IWLAN_NETWORK_FAILURE);
1494                             respBuilder.setRetryDurationMillis(5000);
1495                             metricsAtom.setRetryDurationMillis(5000);
1496                         }
1497 
1498                         // Record setup result for the Metrics
1499                         metricsAtom.setSetupRequestResult(DataServiceCallback.RESULT_SUCCESS);
1500                         metricsAtom.setIwlanError(iwlanError.getErrorType());
1501                         metricsAtom.setIwlanErrorWrappedClassnameAndStack(iwlanError);
1502                         metricsAtom.setMessageId(
1503                                 IwlanStatsLog.IWLAN_SETUP_DATA_CALL_RESULT_REPORTED);
1504                         metricsAtom.setErrorCountOfSameCause(
1505                                 ErrorPolicyManager.getInstance(
1506                                                 mContext, iwlanDataServiceProvider.getSlotIndex())
1507                                         .getLastErrorCountOfSameCause(apnName));
1508 
1509                         iwlanDataServiceProvider.deliverCallback(
1510                                 IwlanDataServiceProvider.CALLBACK_TYPE_SETUP_DATACALL_COMPLETE,
1511                                 DataServiceCallback.RESULT_SUCCESS,
1512                                 tunnelState.getDataServiceCallback(),
1513                                 respBuilder.build());
1514                         return;
1515                     }
1516 
1517                     // iwlan service triggered teardown
1518                     if (tunnelState.getState()
1519                             == IwlanDataServiceProvider.TunnelState.TUNNEL_IN_BRINGDOWN) {
1520 
1521                         // IO exception happens when IKE library fails to retransmit requests.
1522                         // This can happen for multiple reasons:
1523                         // 1. Network disconnection due to wifi off.
1524                         // 2. Epdg server does not respond.
1525                         // 3. Socket send/receive fails.
1526                         // Ignore this during tunnel bring down.
1527                         if (iwlanError.getErrorType() != IwlanError.NO_ERROR
1528                                 && iwlanError.getErrorType()
1529                                         != IwlanError.IKE_INTERNAL_IO_EXCEPTION) {
1530                             Log.e(TAG, "Unexpected error during tunnel bring down: " + iwlanError);
1531                         }
1532 
1533                         iwlanDataServiceProvider.deliverCallback(
1534                                 IwlanDataServiceProvider.CALLBACK_TYPE_DEACTIVATE_DATACALL_COMPLETE,
1535                                 DataServiceCallback.RESULT_SUCCESS,
1536                                 tunnelState.getDataServiceCallback(),
1537                                 null);
1538 
1539                         return;
1540                     }
1541 
1542                     // just update list of data calls. No way to send error up
1543                     iwlanDataServiceProvider.notifyDataCallListChanged(
1544                             iwlanDataServiceProvider.getCallList());
1545 
1546                     // Report IwlanPdnDisconnectedReason due to the disconnection is neither for
1547                     // SETUP_DATA_CALL nor DEACTIVATE_DATA_CALL request.
1548                     metricsAtom.setDataCallFailCause(
1549                             ErrorPolicyManager.getInstance(
1550                                             mContext, iwlanDataServiceProvider.getSlotIndex())
1551                                     .getDataFailCause(apnName));
1552 
1553                     WifiManager wifiManager = mContext.getSystemService(WifiManager.class);
1554                     if (wifiManager == null) {
1555                         Log.e(TAG, "Could not find wifiManager");
1556                         return;
1557                     }
1558 
1559                     WifiInfo wifiInfo = getWifiInfo(sNetworkCapabilities);
1560                     if (wifiInfo == null) {
1561                         Log.e(TAG, "wifiInfo is null");
1562                         return;
1563                     }
1564 
1565                     metricsAtom.setWifiSignalValue(wifiInfo.getRssi());
1566                     metricsAtom.setMessageId(IwlanStatsLog.IWLAN_PDN_DISCONNECTED_REASON_REPORTED);
1567                     break;
1568 
1569                 case IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT:
1570                     iwlanDataServiceProvider =
1571                             (IwlanDataServiceProvider) getDataServiceProvider(msg.arg1);
1572 
1573                     iwlanDataServiceProvider.mCarrierConfigReady = true;
1574                     iwlanDataServiceProvider.dnsPrefetchCheck();
1575                     break;
1576 
1577                 case IwlanEventListener.CARRIER_CONFIG_UNKNOWN_CARRIER_EVENT:
1578                     iwlanDataServiceProvider =
1579                             (IwlanDataServiceProvider) getDataServiceProvider(msg.arg1);
1580 
1581                     iwlanDataServiceProvider.mCarrierConfigReady = false;
1582                     break;
1583 
1584                 case IwlanEventListener.WIFI_CALLING_ENABLE_EVENT:
1585                     iwlanDataServiceProvider =
1586                             (IwlanDataServiceProvider) getDataServiceProvider(msg.arg1);
1587 
1588                     iwlanDataServiceProvider.mWfcEnabled = true;
1589                     iwlanDataServiceProvider.dnsPrefetchCheck();
1590                     break;
1591 
1592                 case IwlanEventListener.WIFI_CALLING_DISABLE_EVENT:
1593                     iwlanDataServiceProvider =
1594                             (IwlanDataServiceProvider) getDataServiceProvider(msg.arg1);
1595 
1596                     iwlanDataServiceProvider.mWfcEnabled = false;
1597                     break;
1598 
1599                 case IwlanEventListener.CROSS_SIM_CALLING_ENABLE_EVENT:
1600                     iwlanDataServiceProvider =
1601                             (IwlanDataServiceProvider) getDataServiceProvider(msg.arg1);
1602                     iwlanDataServiceProvider.updateNetwork(sNetwork, sLinkProperties);
1603                     break;
1604 
1605                 case IwlanEventListener.CELLINFO_CHANGED_EVENT:
1606                     List<CellInfo> cellInfolist = (List<CellInfo>) msg.obj;
1607                     iwlanDataServiceProvider =
1608                             (IwlanDataServiceProvider) getDataServiceProvider(msg.arg1);
1609 
1610                     if (cellInfolist != null
1611                             && iwlanDataServiceProvider.isRegisteredCellInfoChanged(cellInfolist)) {
1612                         int[] addrResolutionMethods =
1613                                 IwlanCarrierConfig.getConfigIntArray(
1614                                         mContext,
1615                                         iwlanDataServiceProvider.getSlotIndex(),
1616                                         CarrierConfigManager.Iwlan
1617                                                 .KEY_EPDG_ADDRESS_PRIORITY_INT_ARRAY);
1618                         for (int addrResolutionMethod : addrResolutionMethods) {
1619                             if (addrResolutionMethod
1620                                     == CarrierConfigManager.Iwlan.EPDG_ADDRESS_CELLULAR_LOC) {
1621                                 iwlanDataServiceProvider.dnsPrefetchCheck();
1622                             }
1623                         }
1624                     }
1625                     break;
1626 
1627                 case IwlanEventListener.CALL_STATE_CHANGED_EVENT:
1628                     iwlanDataServiceProvider =
1629                             (IwlanDataServiceProvider) getDataServiceProvider(msg.arg1);
1630 
1631                     int previousCallState = iwlanDataServiceProvider.mCallState;
1632                     int currentCallState = iwlanDataServiceProvider.mCallState = msg.arg2;
1633 
1634                     if (!IwlanCarrierConfig.getConfigBoolean(
1635                             mContext,
1636                             iwlanDataServiceProvider.getSlotIndex(),
1637                             IwlanCarrierConfig.KEY_UPDATE_N1_MODE_ON_UI_CHANGE_BOOL)) {
1638                         break;
1639                     }
1640 
1641                     // Disconnect PDN if call ends and re-establishment needed.
1642                     if (previousCallState != currentCallState
1643                             && currentCallState == TelephonyManager.CALL_STATE_IDLE
1644                             && iwlanDataServiceProvider.isPdnReestablishNeededOnIdleN1Update()) {
1645                         iwlanDataServiceProvider.disconnectPdnForN1ModeUpdate();
1646                     }
1647                     break;
1648 
1649                 case IwlanEventListener.PREFERRED_NETWORK_TYPE_CHANGED_EVENT:
1650                     iwlanDataServiceProvider =
1651                             (IwlanDataServiceProvider) getDataServiceProvider(msg.arg1);
1652                     if (!IwlanCarrierConfig.getConfigBoolean(
1653                             mContext,
1654                             iwlanDataServiceProvider.getSlotIndex(),
1655                             IwlanCarrierConfig.KEY_UPDATE_N1_MODE_ON_UI_CHANGE_BOOL)) {
1656                         break;
1657                     }
1658                     long allowedNetworkType = (long) msg.obj;
1659                     onPreferredNetworkTypeChanged(iwlanDataServiceProvider, allowedNetworkType);
1660                     break;
1661 
1662                 case EVENT_SETUP_DATA_CALL:
1663                     SetupDataCallData setupDataCallData = (SetupDataCallData) msg.obj;
1664                     int accessNetworkType = setupDataCallData.mAccessNetworkType;
1665                     @NonNull DataProfile dataProfile = setupDataCallData.mDataProfile;
1666                     boolean isRoaming = setupDataCallData.mIsRoaming;
1667                     reason = setupDataCallData.mReason;
1668                     LinkProperties linkProperties = setupDataCallData.mLinkProperties;
1669                     @IntRange(from = 0, to = 15)
1670                     int pduSessionId = setupDataCallData.mPduSessionId;
1671                     callback = setupDataCallData.mCallback;
1672                     iwlanDataServiceProvider = setupDataCallData.mIwlanDataServiceProvider;
1673 
1674                     if ((accessNetworkType != AccessNetworkType.IWLAN)
1675                             || (dataProfile == null)
1676                             || (dataProfile.getApnSetting() == null)
1677                             || (linkProperties == null
1678                                     && reason == DataService.REQUEST_REASON_HANDOVER)) {
1679 
1680                         iwlanDataServiceProvider.deliverCallback(
1681                                 IwlanDataServiceProvider.CALLBACK_TYPE_SETUP_DATACALL_COMPLETE,
1682                                 DataServiceCallback.RESULT_ERROR_INVALID_ARG,
1683                                 callback,
1684                                 null);
1685                         return;
1686                     }
1687 
1688                     slotId = iwlanDataServiceProvider.getSlotIndex();
1689                     boolean isCSTEnabled = IwlanHelper.isCrossSimCallingEnabled(mContext, slotId);
1690                     boolean networkConnected =
1691                             isNetworkConnected(isActiveDataOnOtherSub(slotId), isCSTEnabled);
1692                     Log.d(
1693                             TAG + "[" + slotId + "]",
1694                             "isDds: "
1695                                     + IwlanHelper.isDefaultDataSlot(mContext, slotId)
1696                                     + ", isActiveDataOnOtherSub: "
1697                                     + isActiveDataOnOtherSub(slotId)
1698                                     + ", isCstEnabled: "
1699                                     + isCSTEnabled
1700                                     + ", transport: "
1701                                     + sDefaultDataTransport);
1702 
1703                     if (!networkConnected) {
1704                         iwlanDataServiceProvider.deliverCallback(
1705                                 IwlanDataServiceProvider.CALLBACK_TYPE_SETUP_DATACALL_COMPLETE,
1706                                 5 /* DataServiceCallback.RESULT_ERROR_TEMPORARILY_UNAVAILABLE
1707                                    */,
1708                                 callback,
1709                                 null);
1710                         return;
1711                     }
1712 
1713                     // Update Network & LinkProperties to EpdgTunnelManager
1714                     iwlanDataServiceProvider
1715                             .getTunnelManager()
1716                             .updateNetwork(sNetwork, sLinkProperties);
1717                     Log.d(TAG, "Update Network for SetupDataCall request");
1718 
1719                     tunnelState =
1720                             iwlanDataServiceProvider.mTunnelStateForApn.get(
1721                                     dataProfile.getApnSetting().getApnName());
1722 
1723                     // Return the existing PDN if the pduSessionId is the same and the tunnel
1724                     // state is TUNNEL_UP.
1725                     if (tunnelState != null) {
1726                         if (tunnelState.getPduSessionId() == pduSessionId
1727                                 && tunnelState.getState()
1728                                         == IwlanDataServiceProvider.TunnelState.TUNNEL_UP) {
1729                             Log.w(
1730                                     TAG + "[" + slotId + "]",
1731                                     "The tunnel for "
1732                                             + dataProfile.getApnSetting().getApnName()
1733                                             + " already exists.");
1734                             iwlanDataServiceProvider.deliverCallback(
1735                                     IwlanDataServiceProvider.CALLBACK_TYPE_SETUP_DATACALL_COMPLETE,
1736                                     DataServiceCallback.RESULT_SUCCESS,
1737                                     callback,
1738                                     iwlanDataServiceProvider.apnTunnelStateToDataCallResponse(
1739                                             dataProfile.getApnSetting().getApnName()));
1740                         } else {
1741                             Log.e(
1742                                     TAG + "[" + slotId + "]",
1743                                     "Force close the existing PDN. pduSessionId = "
1744                                             + tunnelState.getPduSessionId()
1745                                             + " Tunnel State = "
1746                                             + tunnelState.getState());
1747                             iwlanDataServiceProvider
1748                                     .getTunnelManager()
1749                                     .closeTunnel(
1750                                             dataProfile.getApnSetting().getApnName(),
1751                                             true /* forceClose */,
1752                                             iwlanDataServiceProvider.getIwlanTunnelCallback(),
1753                                             iwlanDataServiceProvider.getIwlanTunnelMetrics(),
1754                                             BRINGDOWN_REASON_SERVICE_OUT_OF_SYNC);
1755                             iwlanDataServiceProvider.deliverCallback(
1756                                     IwlanDataServiceProvider.CALLBACK_TYPE_SETUP_DATACALL_COMPLETE,
1757                                     5 /* DataServiceCallback
1758                                       .RESULT_ERROR_TEMPORARILY_UNAVAILABLE */,
1759                                     callback,
1760                                     null);
1761                         }
1762                         return;
1763                     }
1764 
1765                     int apnTypeBitmask = dataProfile.getApnSetting().getApnTypeBitmask();
1766                     boolean isIms = hasApnTypes(apnTypeBitmask, ApnSetting.TYPE_IMS);
1767                     boolean isEmergency = hasApnTypes(apnTypeBitmask, ApnSetting.TYPE_EMERGENCY);
1768 
1769                     boolean isDataCallSetupWithN1 =
1770                             iwlanDataServiceProvider.needIncludeN1ModeCapability();
1771 
1772                     // Override N1_MODE_CAPABILITY exclusion only for Emergency PDN due to carrier
1773                     // network limitations
1774                     if (IwlanCarrierConfig.getConfigBoolean(
1775                                     mContext,
1776                                     slotId,
1777                                     IwlanCarrierConfig
1778                                             .KEY_N1_MODE_EXCLUSION_FOR_EMERGENCY_SESSION_BOOL)
1779                             && isEmergency) {
1780                         isDataCallSetupWithN1 = false;
1781                     }
1782 
1783                     TunnelSetupRequest.Builder tunnelReqBuilder =
1784                             TunnelSetupRequest.builder()
1785                                     .setApnName(dataProfile.getApnSetting().getApnName())
1786                                     .setIsRoaming(isRoaming)
1787                                     .setPduSessionId(
1788                                             isDataCallSetupWithN1
1789                                                     ? pduSessionId
1790                                                     : PDU_SESSION_ID_UNSET)
1791                                     .setApnIpProtocol(
1792                                             isRoaming
1793                                                     ? dataProfile
1794                                                             .getApnSetting()
1795                                                             .getRoamingProtocol()
1796                                                     : dataProfile.getApnSetting().getProtocol())
1797                                     .setRequestPcscf(isIms || isEmergency)
1798                                     .setIsEmergency(isEmergency);
1799 
1800                     if (reason == DataService.REQUEST_REASON_HANDOVER) {
1801                         // for now assume that, at max,  only one address of each type (v4/v6).
1802                         // TODO: Check if multiple ips can be sent in ike tunnel setup
1803                         for (LinkAddress lAddr : linkProperties.getLinkAddresses()) {
1804                             if (lAddr.isIpv4()) {
1805                                 tunnelReqBuilder.setSrcIpv4Address(lAddr.getAddress());
1806                             } else if (lAddr.isIpv6()) {
1807                                 tunnelReqBuilder.setSrcIpv6Address(lAddr.getAddress());
1808                                 tunnelReqBuilder.setSrcIpv6AddressPrefixLength(
1809                                         lAddr.getPrefixLength());
1810                             }
1811                         }
1812                     }
1813 
1814                     iwlanDataServiceProvider.setTunnelState(
1815                             dataProfile,
1816                             callback,
1817                             IwlanDataServiceProvider.TunnelState.TUNNEL_IN_BRINGUP,
1818                             null,
1819                             (reason == DataService.REQUEST_REASON_HANDOVER),
1820                             pduSessionId,
1821                             isIms || isEmergency,
1822                             isDataCallSetupWithN1);
1823 
1824                     boolean result =
1825                             iwlanDataServiceProvider
1826                                     .getTunnelManager()
1827                                     .bringUpTunnel(
1828                                             tunnelReqBuilder.build(),
1829                                             iwlanDataServiceProvider.getIwlanTunnelCallback(),
1830                                             iwlanDataServiceProvider.getIwlanTunnelMetrics());
1831                     Log.d(TAG + "[" + slotId + "]", "bringup Tunnel with result:" + result);
1832                     if (!result) {
1833                         iwlanDataServiceProvider.deliverCallback(
1834                                 IwlanDataServiceProvider.CALLBACK_TYPE_SETUP_DATACALL_COMPLETE,
1835                                 DataServiceCallback.RESULT_ERROR_INVALID_ARG,
1836                                 callback,
1837                                 null);
1838                         return;
1839                     }
1840                     break;
1841 
1842                 case EVENT_DEACTIVATE_DATA_CALL:
1843                     handleDeactivateDataCall((DeactivateDataCallData) msg.obj);
1844                     break;
1845 
1846                 case EVENT_DEACTIVATE_DATA_CALL_WITH_DELAY:
1847                     handleDeactivateDataCallWithDelay((DeactivateDataCallData) msg.obj);
1848                     break;
1849 
1850                 case EVENT_DATA_CALL_LIST_REQUEST:
1851                     DataCallRequestData dataCallRequestData = (DataCallRequestData) msg.obj;
1852                     callback = dataCallRequestData.mCallback;
1853                     iwlanDataServiceProvider = dataCallRequestData.mIwlanDataServiceProvider;
1854 
1855                     iwlanDataServiceProvider.deliverCallback(
1856                             IwlanDataServiceProvider.CALLBACK_TYPE_GET_DATACALL_LIST_COMPLETE,
1857                             DataServiceCallback.RESULT_SUCCESS,
1858                             callback,
1859                             null);
1860                     break;
1861 
1862                 case EVENT_FORCE_CLOSE_TUNNEL:
1863                     for (IwlanDataServiceProvider dp : sIwlanDataServiceProviders.values()) {
1864                         dp.forceCloseTunnels(EpdgTunnelManager.BRINGDOWN_REASON_UNKNOWN);
1865                     }
1866                     break;
1867 
1868                 case EVENT_ADD_DATA_SERVICE_PROVIDER:
1869                     iwlanDataServiceProvider = (IwlanDataServiceProvider) msg.obj;
1870                     addIwlanDataServiceProvider(iwlanDataServiceProvider);
1871                     break;
1872 
1873                 case EVENT_REMOVE_DATA_SERVICE_PROVIDER:
1874                     iwlanDataServiceProvider = (IwlanDataServiceProvider) msg.obj;
1875 
1876                     slotId = iwlanDataServiceProvider.getSlotIndex();
1877                     IwlanDataServiceProvider dsp = sIwlanDataServiceProviders.remove(slotId);
1878                     if (dsp == null) {
1879                         Log.w(TAG + "[" + slotId + "]", "No DataServiceProvider exists for slot!");
1880                     }
1881 
1882                     if (sIwlanDataServiceProviders.isEmpty()) {
1883                         deinitNetworkCallback();
1884                     }
1885                     break;
1886 
1887                 case EVENT_TUNNEL_OPENED_METRICS:
1888                     OnOpenedMetrics openedMetricsData = (OnOpenedMetrics) msg.obj;
1889                     iwlanDataServiceProvider = openedMetricsData.getIwlanDataServiceProvider();
1890                     apnName = openedMetricsData.getApnName();
1891 
1892                     // Record setup result for the Metrics
1893                     metricsAtom = iwlanDataServiceProvider.mMetricsAtomForApn.get(apnName);
1894                     metricsAtom.setSetupRequestResult(DataServiceCallback.RESULT_SUCCESS);
1895                     metricsAtom.setIwlanError(IwlanError.NO_ERROR);
1896                     metricsAtom.setDataCallFailCause(DataFailCause.NONE);
1897                     metricsAtom.setHandoverFailureMode(-1);
1898                     metricsAtom.setRetryDurationMillis(0);
1899                     metricsAtom.setMessageId(IwlanStatsLog.IWLAN_SETUP_DATA_CALL_RESULT_REPORTED);
1900                     metricsAtom.setEpdgServerAddress(openedMetricsData.getEpdgServerAddress());
1901                     metricsAtom.setProcessingDurationMillis(
1902                             (int)
1903                                     (System.currentTimeMillis()
1904                                             - iwlanDataServiceProvider.mProcessingStartTime));
1905                     metricsAtom.setEpdgServerSelectionDurationMillis(
1906                             openedMetricsData.getEpdgServerSelectionDuration());
1907                     metricsAtom.setIkeTunnelEstablishmentDurationMillis(
1908                             openedMetricsData.getIkeTunnelEstablishmentDuration());
1909                     metricsAtom.setIsNetworkValidated(openedMetricsData.isNetworkValidated());
1910 
1911                     metricsAtom.sendMetricsData();
1912                     metricsAtom.setMessageId(MetricsAtom.INVALID_MESSAGE_ID);
1913                     break;
1914 
1915                 case EVENT_TUNNEL_CLOSED_METRICS:
1916                     OnClosedMetrics closedMetricsData = (OnClosedMetrics) msg.obj;
1917                     iwlanDataServiceProvider = closedMetricsData.getIwlanDataServiceProvider();
1918                     apnName = closedMetricsData.getApnName();
1919 
1920                     metricsAtom = iwlanDataServiceProvider.mMetricsAtomForApn.get(apnName);
1921                     if (metricsAtom == null) {
1922                         Log.w(TAG, "EVENT_TUNNEL_CLOSED_METRICS: MetricsAtom is null!");
1923                         break;
1924                     }
1925                     metricsAtom.setEpdgServerAddress(closedMetricsData.getEpdgServerAddress());
1926                     metricsAtom.setProcessingDurationMillis(
1927                             iwlanDataServiceProvider.mProcessingStartTime > 0
1928                                     ? (int)
1929                                             (System.currentTimeMillis()
1930                                                     - iwlanDataServiceProvider.mProcessingStartTime)
1931                                     : 0);
1932                     metricsAtom.setEpdgServerSelectionDurationMillis(
1933                             closedMetricsData.getEpdgServerSelectionDuration());
1934                     metricsAtom.setIkeTunnelEstablishmentDurationMillis(
1935                             closedMetricsData.getIkeTunnelEstablishmentDuration());
1936                     metricsAtom.setIsNetworkValidated(closedMetricsData.isNetworkValidated());
1937 
1938                     metricsAtom.sendMetricsData();
1939                     metricsAtom.setMessageId(MetricsAtom.INVALID_MESSAGE_ID);
1940                     iwlanDataServiceProvider.mMetricsAtomForApn.remove(apnName);
1941                     break;
1942 
1943                 case EVENT_ON_LIVENESS_STATUS_CHANGED:
1944                     handleLivenessStatusChange((TunnelValidationStatusData) msg.obj);
1945                     break;
1946 
1947                 case EVENT_REQUEST_NETWORK_VALIDATION:
1948                     handleNetworkValidationRequest((NetworkValidationInfo) msg.obj);
1949                     break;
1950 
1951                 default:
1952                     throw new IllegalStateException("Unexpected value: " + msg.what);
1953             }
1954         }
1955 
handleDeactivateDataCall(DeactivateDataCallData data)1956         public void handleDeactivateDataCall(DeactivateDataCallData data) {
1957             handleDeactivateDataCall(data, false);
1958         }
1959 
handleDeactivateDataCallWithDelay(DeactivateDataCallData data)1960         public void handleDeactivateDataCallWithDelay(DeactivateDataCallData data) {
1961             handleDeactivateDataCall(data, true);
1962         }
1963 
handleDeactivateDataCall(DeactivateDataCallData data, boolean isWithDelay)1964         public void handleDeactivateDataCall(DeactivateDataCallData data, boolean isWithDelay) {
1965             IwlanDataServiceProvider serviceProvider = data.mIwlanDataServiceProvider;
1966             String matchingApn = findMatchingApn(serviceProvider, data.mCid);
1967 
1968             if (matchingApn == null) {
1969                 deliverDeactivationError(serviceProvider, data.mCallback);
1970                 return;
1971             }
1972 
1973             if (isWithDelay) {
1974                 Log.d(TAG, "Delaying deactivation for APN: " + matchingApn);
1975                 scheduleDelayedDeactivateDataCall(serviceProvider, data, matchingApn);
1976                 return;
1977             }
1978             Log.d(TAG, "Processing deactivation for APN: " + matchingApn);
1979             processDeactivateDataCall(serviceProvider, data, matchingApn);
1980         }
1981 
handleNetworkValidationRequest(NetworkValidationInfo networkValidationInfo)1982         private void handleNetworkValidationRequest(NetworkValidationInfo networkValidationInfo) {
1983             IwlanDataServiceProvider iwlanDataServiceProvider =
1984                     networkValidationInfo.mIwlanDataServiceProvider;
1985             int cid = networkValidationInfo.mCid;
1986             Executor executor = networkValidationInfo.mExecutor;
1987             Consumer<Integer> resultCodeCallback = networkValidationInfo.mResultCodeCallback;
1988             IwlanDataServiceProvider.TunnelState tunnelState;
1989 
1990             String apnName = findMatchingApn(iwlanDataServiceProvider, cid);
1991             int resultCode;
1992             if (apnName == null) {
1993                 Log.w(TAG, "no matching APN name found for network validation.");
1994                 resultCode = DataServiceCallback.RESULT_ERROR_UNSUPPORTED;
1995             } else {
1996                 EpdgTunnelManager epdgTunnelManager = iwlanDataServiceProvider.getTunnelManager();
1997                 epdgTunnelManager.requestNetworkValidationForApn(apnName);
1998                 resultCode = DataServiceCallback.RESULT_SUCCESS;
1999                 tunnelState = iwlanDataServiceProvider.mTunnelStateForApn.get(apnName);
2000                 if (tunnelState == null) {
2001                     Log.w(TAG, "EVENT_REQUEST_NETWORK_VALIDATION: tunnel state is null.");
2002                 } else {
2003                     tunnelState.setNetworkValidationStatus(
2004                             PreciseDataConnectionState.NETWORK_VALIDATION_IN_PROGRESS);
2005                 }
2006             }
2007             executor.execute(() -> resultCodeCallback.accept(resultCode));
2008         }
2009 
handleLivenessStatusChange(TunnelValidationStatusData validationStatusData)2010         private void handleLivenessStatusChange(TunnelValidationStatusData validationStatusData) {
2011             IwlanDataServiceProvider iwlanDataServiceProvider =
2012                     validationStatusData.mIwlanDataServiceProvider;
2013             String apnName = validationStatusData.mApnName;
2014             IwlanDataServiceProvider.TunnelState tunnelState =
2015                     iwlanDataServiceProvider.mTunnelStateForApn.get(apnName);
2016             if (tunnelState == null) {
2017                 Log.w(TAG, "EVENT_ON_LIVENESS_STATUS_CHANGED: tunnel state is null.");
2018                 return;
2019             }
2020             tunnelState.setNetworkValidationStatus(validationStatusData.mStatus);
2021             iwlanDataServiceProvider.notifyDataCallListChanged(
2022                     iwlanDataServiceProvider.getCallList());
2023         }
2024 
findMatchingApn(IwlanDataServiceProvider serviceProvider, int cid)2025         private String findMatchingApn(IwlanDataServiceProvider serviceProvider, int cid) {
2026             return serviceProvider.mTunnelStateForApn.keySet().stream()
2027                     .filter(apn -> apn.hashCode() == cid)
2028                     .findFirst()
2029                     .orElse(null);
2030         }
2031 
deliverDeactivationError( IwlanDataServiceProvider serviceProvider, DataServiceCallback callback)2032         private void deliverDeactivationError(
2033                 IwlanDataServiceProvider serviceProvider, DataServiceCallback callback) {
2034             serviceProvider.deliverCallback(
2035                     IwlanDataServiceProvider.CALLBACK_TYPE_DEACTIVATE_DATACALL_COMPLETE,
2036                     DataServiceCallback.RESULT_ERROR_INVALID_ARG,
2037                     callback,
2038                     null);
2039         }
2040 
scheduleDelayedDeactivateDataCall( IwlanDataServiceProvider serviceProvider, DeactivateDataCallData data, String matchingApn)2041         private void scheduleDelayedDeactivateDataCall(
2042                 IwlanDataServiceProvider serviceProvider,
2043                 DeactivateDataCallData data,
2044                 String matchingApn) {
2045             IwlanDataServiceProvider.TunnelState tunnelState =
2046                     serviceProvider.mTunnelStateForApn.get(matchingApn);
2047             tunnelState.setPendingDeactivateDataCallData(data);
2048             tunnelState.setState(IwlanDataServiceProvider.TunnelState.TUNNEL_IN_BRINGDOWN);
2049             Handler handler = getIwlanDataServiceHandler();
2050             handler.sendMessageDelayed(
2051                     handler.obtainMessage(EVENT_DEACTIVATE_DATA_CALL, data),
2052                     data.mDelayTimeSeconds * 1000L);
2053         }
2054 
processDeactivateDataCall( IwlanDataServiceProvider serviceProvider, DeactivateDataCallData data, String matchingApn)2055         private void processDeactivateDataCall(
2056                 IwlanDataServiceProvider serviceProvider,
2057                 DeactivateDataCallData data,
2058                 String matchingApn) {
2059             int slotId = serviceProvider.getSlotIndex();
2060             boolean isNetworkLost =
2061                     !isNetworkConnected(
2062                             isActiveDataOnOtherSub(slotId),
2063                             IwlanHelper.isCrossSimCallingEnabled(mContext, slotId));
2064             boolean isHandoverSuccessful = (data.mReason == REQUEST_REASON_HANDOVER);
2065 
2066             IwlanDataServiceProvider.TunnelState tunnelState =
2067                     serviceProvider.mTunnelStateForApn.get(matchingApn);
2068             tunnelState.setState(IwlanDataServiceProvider.TunnelState.TUNNEL_IN_BRINGDOWN);
2069             tunnelState.setDataServiceCallback(data.mCallback);
2070 
2071             serviceProvider
2072                     .getTunnelManager()
2073                     .closeTunnel(
2074                             matchingApn,
2075                             isNetworkLost || isHandoverSuccessful, /* forceClose */
2076                             serviceProvider.getIwlanTunnelCallback(),
2077                             serviceProvider.getIwlanTunnelMetrics(),
2078                             BRINGDOWN_REASON_DEACTIVATE_DATA_CALL);
2079         }
2080 
cancelPendingDeactivationIfExists( DeactivateDataCallData deactivateDataCallData)2081         private void cancelPendingDeactivationIfExists(
2082                 DeactivateDataCallData deactivateDataCallData) {
2083             Handler handler = getIwlanDataServiceHandler();
2084             if (handler.hasMessages(EVENT_DEACTIVATE_DATA_CALL, deactivateDataCallData)) {
2085                 // Remove any existing deactivation messages and request a new one in the front
2086                 handler.removeMessages(EVENT_DEACTIVATE_DATA_CALL, deactivateDataCallData);
2087             }
2088         }
2089 
IwlanDataServiceHandler(Looper looper)2090         IwlanDataServiceHandler(Looper looper) {
2091             super(looper);
2092         }
2093     }
2094 
2095     private static final class TunnelOpenedData {
2096         final String mApnName;
2097         final TunnelLinkProperties mTunnelLinkProperties;
2098         final IwlanDataServiceProvider mIwlanDataServiceProvider;
2099 
TunnelOpenedData( String apnName, TunnelLinkProperties tunnelLinkProperties, IwlanDataServiceProvider dsp)2100         private TunnelOpenedData(
2101                 String apnName,
2102                 TunnelLinkProperties tunnelLinkProperties,
2103                 IwlanDataServiceProvider dsp) {
2104             mApnName = apnName;
2105             mTunnelLinkProperties = tunnelLinkProperties;
2106             mIwlanDataServiceProvider = dsp;
2107         }
2108     }
2109 
2110     private static final class TunnelClosedData {
2111         final String mApnName;
2112         final IwlanError mIwlanError;
2113         final IwlanDataServiceProvider mIwlanDataServiceProvider;
2114 
TunnelClosedData( String apnName, IwlanError iwlanError, IwlanDataServiceProvider dsp)2115         private TunnelClosedData(
2116                 String apnName, IwlanError iwlanError, IwlanDataServiceProvider dsp) {
2117             mApnName = apnName;
2118             mIwlanError = iwlanError;
2119             mIwlanDataServiceProvider = dsp;
2120         }
2121     }
2122 
2123     private static final class TunnelValidationStatusData {
2124         final String mApnName;
2125         final int mStatus;
2126         final IwlanDataServiceProvider mIwlanDataServiceProvider;
2127 
TunnelValidationStatusData( String apnName, int status, IwlanDataServiceProvider dsp)2128         private TunnelValidationStatusData(
2129                 String apnName, int status, IwlanDataServiceProvider dsp) {
2130             mApnName = apnName;
2131             mStatus = status;
2132             mIwlanDataServiceProvider = dsp;
2133         }
2134     }
2135 
2136     private static final class NetworkValidationInfo {
2137         final int mCid;
2138         final Executor mExecutor;
2139         final Consumer<Integer> mResultCodeCallback;
2140         final IwlanDataServiceProvider mIwlanDataServiceProvider;
2141 
NetworkValidationInfo( int cid, Executor executor, Consumer<Integer> r, IwlanDataServiceProvider dsp)2142         private NetworkValidationInfo(
2143                 int cid, Executor executor, Consumer<Integer> r, IwlanDataServiceProvider dsp) {
2144             mCid = cid;
2145             mExecutor = executor;
2146             mResultCodeCallback = r;
2147             mIwlanDataServiceProvider = dsp;
2148         }
2149     }
2150 
2151     private static final class SetupDataCallData {
2152         final int mAccessNetworkType;
2153         @NonNull final DataProfile mDataProfile;
2154         final boolean mIsRoaming;
2155         final boolean mAllowRoaming;
2156         final int mReason;
2157         @Nullable final LinkProperties mLinkProperties;
2158 
2159         @IntRange(from = 0, to = 15)
2160         final int mPduSessionId;
2161 
2162         @Nullable final NetworkSliceInfo mSliceInfo;
2163         @Nullable final TrafficDescriptor mTrafficDescriptor;
2164         final boolean mMatchAllRuleAllowed;
2165         @NonNull final DataServiceCallback mCallback;
2166         final IwlanDataServiceProvider mIwlanDataServiceProvider;
2167 
SetupDataCallData( int accessNetworkType, DataProfile dataProfile, boolean isRoaming, boolean allowRoaming, int reason, LinkProperties linkProperties, int pduSessionId, NetworkSliceInfo sliceInfo, TrafficDescriptor trafficDescriptor, boolean matchAllRuleAllowed, DataServiceCallback callback, IwlanDataServiceProvider dsp)2168         private SetupDataCallData(
2169                 int accessNetworkType,
2170                 DataProfile dataProfile,
2171                 boolean isRoaming,
2172                 boolean allowRoaming,
2173                 int reason,
2174                 LinkProperties linkProperties,
2175                 int pduSessionId,
2176                 NetworkSliceInfo sliceInfo,
2177                 TrafficDescriptor trafficDescriptor,
2178                 boolean matchAllRuleAllowed,
2179                 DataServiceCallback callback,
2180                 IwlanDataServiceProvider dsp) {
2181             mAccessNetworkType = accessNetworkType;
2182             mDataProfile = dataProfile;
2183             mIsRoaming = isRoaming;
2184             mAllowRoaming = allowRoaming;
2185             mReason = reason;
2186             mLinkProperties = linkProperties;
2187             mPduSessionId = pduSessionId;
2188             mSliceInfo = sliceInfo;
2189             mTrafficDescriptor = trafficDescriptor;
2190             mMatchAllRuleAllowed = matchAllRuleAllowed;
2191             mCallback = callback;
2192             mIwlanDataServiceProvider = dsp;
2193         }
2194     }
2195 
2196     private static final class DeactivateDataCallData {
2197         final int mCid;
2198         final int mReason;
2199         final DataServiceCallback mCallback;
2200         final IwlanDataServiceProvider mIwlanDataServiceProvider;
2201         final int mDelayTimeSeconds;
2202 
DeactivateDataCallData( int cid, int reason, DataServiceCallback callback, IwlanDataServiceProvider dsp, int delayTimeSeconds)2203         private DeactivateDataCallData(
2204                 int cid,
2205                 int reason,
2206                 DataServiceCallback callback,
2207                 IwlanDataServiceProvider dsp,
2208                 int delayTimeSeconds) {
2209             mCid = cid;
2210             mReason = reason;
2211             mCallback = callback;
2212             mIwlanDataServiceProvider = dsp;
2213             mDelayTimeSeconds = delayTimeSeconds;
2214         }
2215     }
2216 
2217     private static final class DataCallRequestData {
2218         final DataServiceCallback mCallback;
2219         final IwlanDataServiceProvider mIwlanDataServiceProvider;
2220 
DataCallRequestData(DataServiceCallback callback, IwlanDataServiceProvider dsp)2221         private DataCallRequestData(DataServiceCallback callback, IwlanDataServiceProvider dsp) {
2222             mCallback = callback;
2223             mIwlanDataServiceProvider = dsp;
2224         }
2225     }
2226 
getConnectedDataSub(NetworkCapabilities networkCapabilities)2227     static int getConnectedDataSub(NetworkCapabilities networkCapabilities) {
2228         int connectedDataSub = INVALID_SUB_ID;
2229         NetworkSpecifier specifier = networkCapabilities.getNetworkSpecifier();
2230         TransportInfo transportInfo = networkCapabilities.getTransportInfo();
2231 
2232         if (specifier instanceof TelephonyNetworkSpecifier) {
2233             connectedDataSub = ((TelephonyNetworkSpecifier) specifier).getSubscriptionId();
2234         } else if (transportInfo instanceof VcnTransportInfo) {
2235             connectedDataSub = ((VcnTransportInfo) transportInfo).getSubId();
2236         }
2237         return connectedDataSub;
2238     }
2239 
setConnectedDataSub(int subId)2240     static void setConnectedDataSub(int subId) {
2241         mConnectedDataSub = subId;
2242     }
2243 
2244     @VisibleForTesting
isActiveDataOnOtherSub(int slotId)2245     static boolean isActiveDataOnOtherSub(int slotId) {
2246         int subId = IwlanHelper.getSubId(mContext, slotId);
2247         return mConnectedDataSub != INVALID_SUB_ID && subId != mConnectedDataSub;
2248     }
2249 
2250     @VisibleForTesting
isNetworkConnected(boolean isActiveDataOnOtherSub, boolean isCstEnabled)2251     static boolean isNetworkConnected(boolean isActiveDataOnOtherSub, boolean isCstEnabled) {
2252         if (isActiveDataOnOtherSub && isCstEnabled) {
2253             // For cross-SIM IWLAN (Transport.MOBILE), an active data PDN must be maintained on the
2254             // other subscription.
2255             if (sNetworkConnected && (sDefaultDataTransport != Transport.MOBILE)) {
2256                 Log.e(TAG, "Internet is on other slot, but default transport is not MOBILE!");
2257             }
2258             return sNetworkConnected;
2259         } else {
2260             // For all other cases, only Transport.WIFI can be used.
2261             return ((sDefaultDataTransport == Transport.WIFI) && sNetworkConnected);
2262         }
2263     }
2264 
2265     /* Note: this api should have valid transport if networkConnected==true */
setNetworkConnected( boolean networkConnected, @NonNull Network network, Transport transport)2266     static void setNetworkConnected(
2267             boolean networkConnected, @NonNull Network network, Transport transport) {
2268 
2269         boolean hasNetworkChanged = false;
2270         boolean hasTransportChanged = false;
2271         boolean hasNetworkConnectedChanged = false;
2272 
2273         if (sNetworkConnected == networkConnected
2274                 && network.equals(sNetwork)
2275                 && sDefaultDataTransport == transport) {
2276             // Nothing changed
2277             return;
2278         }
2279 
2280         // safety check
2281         if (networkConnected && transport == Transport.UNSPECIFIED_NETWORK) {
2282             Log.e(TAG, "setNetworkConnected: Network connected but transport unspecified");
2283             return;
2284         }
2285 
2286         if (!network.equals(sNetwork)) {
2287             Log.e(TAG, "System default network changed from: " + sNetwork + " TO: " + network);
2288             hasNetworkChanged = true;
2289         }
2290 
2291         if (transport != sDefaultDataTransport) {
2292             Log.d(
2293                     TAG,
2294                     "Transport was changed from "
2295                             + sDefaultDataTransport.name()
2296                             + " to "
2297                             + transport.name());
2298             hasTransportChanged = true;
2299         }
2300 
2301         if (sNetworkConnected != networkConnected) {
2302             Log.d(
2303                     TAG,
2304                     "Network connected state change from "
2305                             + sNetworkConnected
2306                             + " to "
2307                             + networkConnected);
2308             hasNetworkConnectedChanged = true;
2309         }
2310 
2311         sDefaultDataTransport = transport;
2312         sNetworkConnected = networkConnected;
2313 
2314         if (networkConnected) {
2315             if (hasTransportChanged) {
2316                 // Perform forceClose for tunnels in bringdown.
2317                 // let framework handle explicit teardown
2318                 for (IwlanDataServiceProvider dp : sIwlanDataServiceProviders.values()) {
2319                     dp.forceCloseTunnelsInDeactivatingState();
2320                 }
2321             }
2322 
2323             if (transport == Transport.WIFI && hasNetworkConnectedChanged) {
2324                 IwlanEventListener.onWifiConnected(getWifiInfo(sNetworkCapabilities));
2325             }
2326             // only prefetch dns and updateNetwork if Network has changed
2327             if (hasNetworkChanged) {
2328                 ConnectivityManager connectivityManager =
2329                         mContext.getSystemService(ConnectivityManager.class);
2330                 LinkProperties linkProperties = connectivityManager.getLinkProperties(network);
2331                 sLinkProperties = linkProperties;
2332                 for (IwlanDataServiceProvider dp : sIwlanDataServiceProviders.values()) {
2333                     dp.dnsPrefetchCheck();
2334                     dp.updateNetwork(network, linkProperties);
2335                 }
2336                 IwlanHelper.updateCountryCodeWhenNetworkConnected();
2337             }
2338         } else {
2339             for (IwlanDataServiceProvider dp : sIwlanDataServiceProviders.values()) {
2340                 // once network is disconnected, even NAT KA offload fails
2341                 // But we should still let framework do an explicit teardown
2342                 // so as to not affect an ongoing handover
2343                 // only force close tunnels in bring down state
2344                 dp.forceCloseTunnelsInDeactivatingState();
2345             }
2346         }
2347         sNetwork = network;
2348     }
2349 
setNetworkCapabilities(NetworkCapabilities networkCapabilities)2350     private static void setNetworkCapabilities(NetworkCapabilities networkCapabilities) {
2351         sNetworkCapabilities = networkCapabilities;
2352     }
2353 
2354     /**
2355      * Get the DataServiceProvider associated with the slotId
2356      *
2357      * @param slotId slot index
2358      * @return DataService.DataServiceProvider associated with the slot
2359      */
getDataServiceProvider(int slotId)2360     public static DataService.DataServiceProvider getDataServiceProvider(int slotId) {
2361         return sIwlanDataServiceProviders.get(slotId);
2362     }
2363 
getContext()2364     public static Context getContext() {
2365         return mContext;
2366     }
2367 
2368     @Override
onCreateDataServiceProvider(int slotIndex)2369     public DataServiceProvider onCreateDataServiceProvider(int slotIndex) {
2370         // TODO: validity check on slot index
2371         Log.d(TAG, "Creating provider for " + slotIndex);
2372 
2373         if (mNetworkMonitorCallback == null) {
2374             // start monitoring network and register for default network callback
2375             ConnectivityManager connectivityManager =
2376                     mContext.getSystemService(ConnectivityManager.class);
2377             mNetworkMonitorCallback = new IwlanNetworkMonitorCallback();
2378             if (connectivityManager != null) {
2379                 connectivityManager.registerSystemDefaultNetworkCallback(
2380                         mNetworkMonitorCallback, getIwlanDataServiceHandler());
2381             }
2382             Log.d(TAG, "Registered with Connectivity Service");
2383         }
2384 
2385         IwlanDataServiceProvider dp = new IwlanDataServiceProvider(slotIndex, this);
2386 
2387         getIwlanDataServiceHandler()
2388                 .sendMessage(
2389                         getIwlanDataServiceHandler()
2390                                 .obtainMessage(EVENT_ADD_DATA_SERVICE_PROVIDER, dp));
2391         return dp;
2392     }
2393 
removeDataServiceProvider(IwlanDataServiceProvider dp)2394     public void removeDataServiceProvider(IwlanDataServiceProvider dp) {
2395         getIwlanDataServiceHandler()
2396                 .sendMessage(
2397                         getIwlanDataServiceHandler()
2398                                 .obtainMessage(EVENT_REMOVE_DATA_SERVICE_PROVIDER, dp));
2399     }
2400 
2401     @VisibleForTesting
addIwlanDataServiceProvider(IwlanDataServiceProvider dp)2402     void addIwlanDataServiceProvider(IwlanDataServiceProvider dp) {
2403         int slotIndex = dp.getSlotIndex();
2404         if (sIwlanDataServiceProviders.containsKey(slotIndex)) {
2405             throw new IllegalStateException(
2406                     "DataServiceProvider already exists for slot " + slotIndex);
2407         }
2408         sIwlanDataServiceProviders.put(slotIndex, dp);
2409     }
2410 
deinitNetworkCallback()2411     void deinitNetworkCallback() {
2412         // deinit network related stuff
2413         ConnectivityManager connectivityManager =
2414                 mContext.getSystemService(ConnectivityManager.class);
2415         if (connectivityManager != null) {
2416             connectivityManager.unregisterNetworkCallback(mNetworkMonitorCallback);
2417         }
2418         mNetworkMonitorCallback = null;
2419     }
2420 
hasApnTypes(int apnTypeBitmask, int expectedApn)2421     boolean hasApnTypes(int apnTypeBitmask, int expectedApn) {
2422         return (apnTypeBitmask & expectedApn) != 0;
2423     }
2424 
2425     @VisibleForTesting
setAppContext(Context appContext)2426     void setAppContext(Context appContext) {
2427         mContext = appContext;
2428     }
2429 
2430     @VisibleForTesting
2431     @NonNull
getIwlanDataServiceHandler()2432     Handler getIwlanDataServiceHandler() {
2433         if (mIwlanDataServiceHandler == null) {
2434             mIwlanDataServiceHandler = new IwlanDataServiceHandler(getLooper());
2435         }
2436         return mIwlanDataServiceHandler;
2437     }
2438 
2439     @VisibleForTesting
getLooper()2440     Looper getLooper() {
2441         mIwlanDataServiceHandlerThread = new HandlerThread("IwlanDataServiceThread");
2442         mIwlanDataServiceHandlerThread.start();
2443         return mIwlanDataServiceHandlerThread.getLooper();
2444     }
2445 
eventToString(int event)2446     private static String eventToString(int event) {
2447         switch (event) {
2448             case EVENT_TUNNEL_OPENED:
2449                 return "EVENT_TUNNEL_OPENED";
2450             case EVENT_TUNNEL_CLOSED:
2451                 return "EVENT_TUNNEL_CLOSED";
2452             case EVENT_SETUP_DATA_CALL:
2453                 return "EVENT_SETUP_DATA_CALL";
2454             case EVENT_DEACTIVATE_DATA_CALL:
2455                 return "EVENT_DEACTIVATE_DATA_CALL";
2456             case EVENT_DATA_CALL_LIST_REQUEST:
2457                 return "EVENT_DATA_CALL_LIST_REQUEST";
2458             case EVENT_FORCE_CLOSE_TUNNEL:
2459                 return "EVENT_FORCE_CLOSE_TUNNEL";
2460             case EVENT_ADD_DATA_SERVICE_PROVIDER:
2461                 return "EVENT_ADD_DATA_SERVICE_PROVIDER";
2462             case EVENT_REMOVE_DATA_SERVICE_PROVIDER:
2463                 return "EVENT_REMOVE_DATA_SERVICE_PROVIDER";
2464             case IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT:
2465                 return "CARRIER_CONFIG_CHANGED_EVENT";
2466             case IwlanEventListener.CARRIER_CONFIG_UNKNOWN_CARRIER_EVENT:
2467                 return "CARRIER_CONFIG_UNKNOWN_CARRIER_EVENT";
2468             case IwlanEventListener.WIFI_CALLING_ENABLE_EVENT:
2469                 return "WIFI_CALLING_ENABLE_EVENT";
2470             case IwlanEventListener.WIFI_CALLING_DISABLE_EVENT:
2471                 return "WIFI_CALLING_DISABLE_EVENT";
2472             case IwlanEventListener.CROSS_SIM_CALLING_ENABLE_EVENT:
2473                 return "CROSS_SIM_CALLING_ENABLE_EVENT";
2474             case IwlanEventListener.CELLINFO_CHANGED_EVENT:
2475                 return "CELLINFO_CHANGED_EVENT";
2476             case EVENT_TUNNEL_OPENED_METRICS:
2477                 return "EVENT_TUNNEL_OPENED_METRICS";
2478             case EVENT_TUNNEL_CLOSED_METRICS:
2479                 return "EVENT_TUNNEL_CLOSED_METRICS";
2480             case EVENT_DEACTIVATE_DATA_CALL_WITH_DELAY:
2481                 return "EVENT_DEACTIVATE_DATA_CALL_WITH_DELAY";
2482             case IwlanEventListener.CALL_STATE_CHANGED_EVENT:
2483                 return "CALL_STATE_CHANGED_EVENT";
2484             case IwlanEventListener.PREFERRED_NETWORK_TYPE_CHANGED_EVENT:
2485                 return "PREFERRED_NETWORK_TYPE_CHANGED_EVENT";
2486             case EVENT_ON_LIVENESS_STATUS_CHANGED:
2487                 return "EVENT_ON_LIVENESS_STATUS_CHANGED";
2488             case EVENT_REQUEST_NETWORK_VALIDATION:
2489                 return "EVENT_REQUEST_NETWORK_VALIDATION";
2490             default:
2491                 return "Unknown(" + event + ")";
2492         }
2493     }
2494 
initAllowedNetworkType()2495     private void initAllowedNetworkType() {
2496         TelephonyManager mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
2497         mIs5GEnabledOnUi =
2498                 ((mTelephonyManager.getAllowedNetworkTypesBitmask()
2499                                 & TelephonyManager.NETWORK_TYPE_BITMASK_NR)
2500                         != 0);
2501     }
2502 
onPreferredNetworkTypeChanged( IwlanDataServiceProvider iwlanDataServiceProvider, long allowedNetworkType)2503     private void onPreferredNetworkTypeChanged(
2504             IwlanDataServiceProvider iwlanDataServiceProvider, long allowedNetworkType) {
2505         boolean isCurrentUiEnable5G =
2506                 (allowedNetworkType & TelephonyManager.NETWORK_TYPE_BITMASK_NR) != 0;
2507         boolean isPreviousUiEnable5G = mIs5GEnabledOnUi;
2508         mIs5GEnabledOnUi = isCurrentUiEnable5G;
2509         if (!iwlanDataServiceProvider.isN1ModeSupported()) {
2510             return;
2511         }
2512         if (isPreviousUiEnable5G != isCurrentUiEnable5G) {
2513             if (!iwlanDataServiceProvider.isOnCall()) {
2514                 iwlanDataServiceProvider.disconnectPdnForN1ModeUpdate();
2515             }
2516         }
2517     }
2518 
2519     @Nullable
getWifiInfo(@ullable NetworkCapabilities networkCapabilities)2520     private static WifiInfo getWifiInfo(@Nullable NetworkCapabilities networkCapabilities) {
2521         if (networkCapabilities == null) {
2522             Log.d(TAG, "Cannot obtain wifi info, networkCapabilities is null");
2523             return null;
2524         }
2525         return networkCapabilities.getTransportInfo() instanceof WifiInfo wifiInfo
2526                 ? wifiInfo
2527                 : null;
2528     }
2529 
2530     @Override
onCreate()2531     public void onCreate() {
2532         Context context = getApplicationContext().createAttributionContext(CONTEXT_ATTRIBUTION_TAG);
2533         setAppContext(context);
2534         IwlanBroadcastReceiver.startListening(mContext);
2535         IwlanCarrierConfigChangeListener.startListening(mContext);
2536         IwlanHelper.startCountryDetector(mContext);
2537         initAllowedNetworkType();
2538     }
2539 
2540     @Override
onDestroy()2541     public void onDestroy() {
2542         IwlanCarrierConfigChangeListener.stopListening(mContext);
2543         IwlanBroadcastReceiver.stopListening(mContext);
2544     }
2545 
2546     @Override
onBind(Intent intent)2547     public IBinder onBind(Intent intent) {
2548         Log.d(TAG, "IwlanDataService onBind");
2549         return super.onBind(intent);
2550     }
2551 
2552     @Override
onUnbind(Intent intent)2553     public boolean onUnbind(Intent intent) {
2554         Log.d(TAG, "IwlanDataService onUnbind");
2555         getIwlanDataServiceHandler()
2556                 .sendMessage(getIwlanDataServiceHandler().obtainMessage(EVENT_FORCE_CLOSE_TUNNEL));
2557         return super.onUnbind(intent);
2558     }
2559 
requestReasonToString(int reason)2560     private String requestReasonToString(int reason) {
2561         switch (reason) {
2562             case DataService.REQUEST_REASON_UNKNOWN:
2563                 return "UNKNOWN";
2564             case DataService.REQUEST_REASON_NORMAL:
2565                 return "NORMAL";
2566             case DataService.REQUEST_REASON_SHUTDOWN:
2567                 return "SHUTDOWN";
2568             case DataService.REQUEST_REASON_HANDOVER:
2569                 return "HANDOVER";
2570             default:
2571                 return "UNKNOWN(" + reason + ")";
2572         }
2573     }
2574 
2575     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)2576     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2577         String transport = "UNSPECIFIED";
2578         if (sDefaultDataTransport == Transport.MOBILE) {
2579             transport = "CELLULAR";
2580         } else if (sDefaultDataTransport == Transport.WIFI) {
2581             transport = "WIFI";
2582         }
2583         pw.println("Default transport: " + transport);
2584         for (IwlanDataServiceProvider provider : sIwlanDataServiceProviders.values()) {
2585             pw.println();
2586             provider.dump(fd, pw, args);
2587             pw.println();
2588             pw.println();
2589         }
2590     }
2591 }
2592