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