• 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 
22 import android.content.Context;
23 import android.content.Intent;
24 import android.net.ConnectivityManager;
25 import android.net.LinkAddress;
26 import android.net.LinkProperties;
27 import android.net.Network;
28 import android.net.NetworkCapabilities;
29 import android.net.wifi.WifiInfo;
30 import android.net.wifi.WifiManager;
31 import android.os.Handler;
32 import android.os.HandlerThread;
33 import android.os.IBinder;
34 import android.os.Looper;
35 import android.os.Message;
36 import android.support.annotation.IntRange;
37 import android.support.annotation.NonNull;
38 import android.support.annotation.Nullable;
39 import android.telephony.AccessNetworkConstants.AccessNetworkType;
40 import android.telephony.CarrierConfigManager;
41 import android.telephony.CellInfo;
42 import android.telephony.CellInfoGsm;
43 import android.telephony.CellInfoLte;
44 import android.telephony.CellInfoNr;
45 import android.telephony.CellInfoWcdma;
46 import android.telephony.DataFailCause;
47 import android.telephony.TelephonyManager;
48 import android.telephony.data.ApnSetting;
49 import android.telephony.data.DataCallResponse;
50 import android.telephony.data.DataProfile;
51 import android.telephony.data.DataService;
52 import android.telephony.data.DataServiceCallback;
53 import android.telephony.data.NetworkSliceInfo;
54 import android.telephony.data.TrafficDescriptor;
55 import android.util.Log;
56 
57 import com.android.internal.annotations.VisibleForTesting;
58 
59 import com.google.android.iwlan.epdg.EpdgSelector;
60 import com.google.android.iwlan.epdg.EpdgTunnelManager;
61 import com.google.android.iwlan.epdg.TunnelLinkProperties;
62 import com.google.android.iwlan.epdg.TunnelSetupRequest;
63 import com.google.android.iwlan.proto.MetricsAtom;
64 
65 import java.io.FileDescriptor;
66 import java.io.PrintWriter;
67 import java.net.Inet4Address;
68 import java.net.Inet6Address;
69 import java.net.InetAddress;
70 import java.net.UnknownHostException;
71 import java.util.ArrayList;
72 import java.util.Calendar;
73 import java.util.Date;
74 import java.util.HashMap;
75 import java.util.List;
76 import java.util.LongSummaryStatistics;
77 import java.util.Map;
78 import java.util.concurrent.ConcurrentHashMap;
79 
80 public class IwlanDataService extends DataService {
81 
82     private static final String TAG = IwlanDataService.class.getSimpleName();
83     private static Context mContext;
84     private IwlanNetworkMonitorCallback mNetworkMonitorCallback;
85     private static boolean sNetworkConnected = false;
86     private static Network sNetwork = null;
87     @VisibleForTesting Handler mIwlanDataServiceHandler;
88     private HandlerThread mIwlanDataServiceHandlerThread;
89     private static final Map<Integer, IwlanDataServiceProvider> sIwlanDataServiceProviders =
90             new ConcurrentHashMap<>();
91 
92     private static final int EVENT_BASE = IwlanEventListener.DATA_SERVICE_INTERNAL_EVENT_BASE;
93     private static final int EVENT_TUNNEL_OPENED = EVENT_BASE;
94     private static final int EVENT_TUNNEL_CLOSED = EVENT_BASE + 1;
95     private static final int EVENT_SETUP_DATA_CALL = EVENT_BASE + 2;
96     private static final int EVENT_DEACTIVATE_DATA_CALL = EVENT_BASE + 3;
97     private static final int EVENT_DATA_CALL_LIST_REQUEST = EVENT_BASE + 4;
98     private static final int EVENT_FORCE_CLOSE_TUNNEL = EVENT_BASE + 5;
99     private static final int EVENT_ADD_DATA_SERVICE_PROVIDER = EVENT_BASE + 6;
100     private static final int EVENT_REMOVE_DATA_SERVICE_PROVIDER = EVENT_BASE + 7;
101     private static final int EVENT_TUNNEL_OPENED_METRICS = EVENT_BASE + 8;
102     private static final int EVENT_TUNNEL_CLOSED_METRICS = EVENT_BASE + 9;
103 
104     @VisibleForTesting
105     enum Transport {
106         UNSPECIFIED_NETWORK,
107         MOBILE,
108         WIFI;
109     }
110 
111     private static Transport sDefaultDataTransport = Transport.UNSPECIFIED_NETWORK;
112 
113     enum LinkProtocolType {
114         UNKNOWN,
115         IPV4,
116         IPV6,
117         IPV4V6;
118     }
119 
120     private static LinkProtocolType sLinkProtocolType = LinkProtocolType.UNKNOWN;
121 
122     // TODO: see if network monitor callback impl can be shared between dataservice and
123     // networkservice
124     // This callback runs in the same thread as IwlanDataServiceHandler
125     static class IwlanNetworkMonitorCallback extends ConnectivityManager.NetworkCallback {
126 
127         /** Called when the framework connects and has declared a new network ready for use. */
128         @Override
onAvailable(Network network)129         public void onAvailable(Network network) {
130             Log.d(TAG, "onAvailable: " + network);
131         }
132 
133         /**
134          * Called when the network is about to be lost, typically because there are no outstanding
135          * requests left for it. This may be paired with a {@link NetworkCallback#onAvailable} call
136          * with the new replacement network for graceful handover. This method is not guaranteed to
137          * be called before {@link NetworkCallback#onLost} is called, for example in case a network
138          * is suddenly disconnected.
139          */
140         @Override
onLosing(Network network, int maxMsToLive)141         public void onLosing(Network network, int maxMsToLive) {
142             Log.d(TAG, "onLosing: maxMsToLive: " + maxMsToLive + " network: " + network);
143         }
144 
145         /**
146          * Called when a network disconnects or otherwise no longer satisfies this request or
147          * callback.
148          */
149         @Override
onLost(Network network)150         public void onLost(Network network) {
151             Log.d(TAG, "onLost: " + network);
152             IwlanDataService.setNetworkConnected(false, network, Transport.UNSPECIFIED_NETWORK);
153         }
154 
155         /** Called when the network corresponding to this request changes {@link LinkProperties}. */
156         @Override
onLinkPropertiesChanged(Network network, LinkProperties linkProperties)157         public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) {
158             Log.d(TAG, "onLinkPropertiesChanged: " + linkProperties);
159             if (isLinkProtocolTypeChanged(linkProperties)) {
160                 for (IwlanDataServiceProvider dp : sIwlanDataServiceProviders.values()) {
161                     dp.dnsPrefetchCheck();
162                 }
163             }
164         }
165 
166         /** Called when access to the specified network is blocked or unblocked. */
167         @Override
onBlockedStatusChanged(Network network, boolean blocked)168         public void onBlockedStatusChanged(Network network, boolean blocked) {
169             // TODO: check if we need to handle this
170             Log.d(TAG, "onBlockedStatusChanged: " + network + " BLOCKED:" + blocked);
171         }
172 
173         @Override
onCapabilitiesChanged( Network network, NetworkCapabilities networkCapabilities)174         public void onCapabilitiesChanged(
175                 Network network, NetworkCapabilities networkCapabilities) {
176             // onCapabilitiesChanged is guaranteed to be called immediately after onAvailable per
177             // API
178             Log.d(TAG, "onCapabilitiesChanged: " + network + " " + networkCapabilities);
179             if (networkCapabilities != null) {
180                 if (networkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
181                     Log.d(TAG, "Network " + network + " connected using transport MOBILE");
182                     IwlanDataService.setNetworkConnected(true, network, Transport.MOBILE);
183                 } else if (networkCapabilities.hasTransport(TRANSPORT_WIFI)) {
184                     Log.d(TAG, "Network " + network + " connected using transport WIFI");
185                     IwlanDataService.setNetworkConnected(true, network, Transport.WIFI);
186                 } else {
187                     Log.w(TAG, "Network does not have cellular or wifi capability");
188                 }
189             }
190         }
191     }
192 
193     @VisibleForTesting
194     class IwlanDataServiceProvider extends DataService.DataServiceProvider {
195 
196         private static final int CALLBACK_TYPE_SETUP_DATACALL_COMPLETE = 1;
197         private static final int CALLBACK_TYPE_DEACTIVATE_DATACALL_COMPLETE = 2;
198         private static final int CALLBACK_TYPE_GET_DATACALL_LIST_COMPLETE = 3;
199         private final String SUB_TAG;
200         private final IwlanDataService mIwlanDataService;
201         private final IwlanTunnelCallback mIwlanTunnelCallback;
202         private final IwlanTunnelCallbackMetrics mIwlanTunnelCallbackMetrics;
203         private boolean mWfcEnabled = false;
204         private boolean mCarrierConfigReady = false;
205         private EpdgSelector mEpdgSelector;
206         private IwlanDataTunnelStats mTunnelStats;
207         private CellInfo mCellInfo = null;
208         private long mProcessingStartTime = 0;
209 
210         // apn to TunnelState
211         // Access should be serialized inside IwlanDataServiceHandler
212         private Map<String, TunnelState> mTunnelStateForApn = new ConcurrentHashMap<>();
213         private Map<String, MetricsAtom> mMetricsAtomForApn = new ConcurrentHashMap<>();
214 
215         // Holds the state of a tunnel (for an APN)
216         @VisibleForTesting
217         class TunnelState {
218 
219             // this should be ideally be based on path MTU discovery. 1280 is the minimum packet
220             // size ipv6 routers have to handle so setting it to 1280 is the safest approach.
221             // ideally it should be 1280 - tunnelling overhead ?
222             private static final int LINK_MTU =
223                     1280; // TODO: need to substract tunnelling overhead?
224             private static final int LINK_MTU_CST = 1200; // Reserve 80 bytes for VCN.
225             static final int TUNNEL_DOWN = 1;
226             static final int TUNNEL_IN_BRINGUP = 2;
227             static final int TUNNEL_UP = 3;
228             static final int TUNNEL_IN_BRINGDOWN = 4;
229             static final int TUNNEL_IN_FORCE_CLEAN_WAS_IN_BRINGUP = 5;
230             private DataServiceCallback dataServiceCallback;
231             private int mState;
232             private int mPduSessionId;
233             private TunnelLinkProperties mTunnelLinkProperties;
234             private boolean mIsHandover;
235             private Date mBringUpStateTime = null;
236             private Date mUpStateTime = null;
237 
getPduSessionId()238             public int getPduSessionId() {
239                 return mPduSessionId;
240             }
241 
setPduSessionId(int mPduSessionId)242             public void setPduSessionId(int mPduSessionId) {
243                 this.mPduSessionId = mPduSessionId;
244             }
245 
getProtocolType()246             public int getProtocolType() {
247                 return mProtocolType;
248             }
249 
getLinkMtu()250             public int getLinkMtu() {
251                 if ((sDefaultDataTransport == Transport.MOBILE) && sNetworkConnected) {
252                     return LINK_MTU_CST;
253                 } else {
254                     return LINK_MTU; // TODO: need to substract tunnelling overhead
255                 }
256             }
257 
setProtocolType(int protocolType)258             public void setProtocolType(int protocolType) {
259                 mProtocolType = protocolType;
260             }
261 
262             private int mProtocolType; // from DataProfile
263 
getTunnelLinkProperties()264             public TunnelLinkProperties getTunnelLinkProperties() {
265                 return mTunnelLinkProperties;
266             }
267 
setTunnelLinkProperties(TunnelLinkProperties tunnelLinkProperties)268             public void setTunnelLinkProperties(TunnelLinkProperties tunnelLinkProperties) {
269                 mTunnelLinkProperties = tunnelLinkProperties;
270             }
271 
getDataServiceCallback()272             public DataServiceCallback getDataServiceCallback() {
273                 return dataServiceCallback;
274             }
275 
setDataServiceCallback(DataServiceCallback dataServiceCallback)276             public void setDataServiceCallback(DataServiceCallback dataServiceCallback) {
277                 this.dataServiceCallback = dataServiceCallback;
278             }
279 
TunnelState(DataServiceCallback callback)280             public TunnelState(DataServiceCallback callback) {
281                 dataServiceCallback = callback;
282                 mState = TUNNEL_DOWN;
283             }
284 
getState()285             public int getState() {
286                 return mState;
287             }
288 
289             /**
290              * @param state (TunnelState.TUNNEL_DOWN|TUNNEL_UP|TUNNEL_DOWN)
291              */
setState(int state)292             public void setState(int state) {
293                 mState = state;
294                 if (mState == TunnelState.TUNNEL_IN_BRINGUP) {
295                     mBringUpStateTime = Calendar.getInstance().getTime();
296                 }
297                 if (mState == TunnelState.TUNNEL_UP) {
298                     mUpStateTime = Calendar.getInstance().getTime();
299                 }
300             }
301 
setIsHandover(boolean isHandover)302             public void setIsHandover(boolean isHandover) {
303                 mIsHandover = isHandover;
304             }
305 
getIsHandover()306             public boolean getIsHandover() {
307                 return mIsHandover;
308             }
309 
getBringUpStateTime()310             public Date getBringUpStateTime() {
311                 return mBringUpStateTime;
312             }
313 
getUpStateTime()314             public Date getUpStateTime() {
315                 return mUpStateTime;
316             }
317 
318             @Override
toString()319             public String toString() {
320                 StringBuilder sb = new StringBuilder();
321                 String tunnelState = "UNKNOWN";
322                 switch (mState) {
323                     case TUNNEL_DOWN:
324                         tunnelState = "DOWN";
325                         break;
326                     case TUNNEL_IN_BRINGUP:
327                         tunnelState = "IN BRINGUP";
328                         break;
329                     case TUNNEL_UP:
330                         tunnelState = "UP";
331                         break;
332                     case TUNNEL_IN_BRINGDOWN:
333                         tunnelState = "IN BRINGDOWN";
334                         break;
335                     case TUNNEL_IN_FORCE_CLEAN_WAS_IN_BRINGUP:
336                         tunnelState = "IN FORCE CLEAN WAS IN BRINGUP";
337                         break;
338                 }
339                 sb.append("\tCurrent State of this tunnel: " + mState + " " + tunnelState);
340                 sb.append("\n\tTunnel state is in Handover: " + mIsHandover);
341                 if (mBringUpStateTime != null) {
342                     sb.append("\n\tTunnel bring up initiated at: " + mBringUpStateTime);
343                 } else {
344                     sb.append("\n\tPotential leak. Null mBringUpStateTime");
345                 }
346                 if (mUpStateTime != null) {
347                     sb.append("\n\tTunnel is up at: " + mUpStateTime);
348                 }
349                 if (mUpStateTime != null && mBringUpStateTime != null) {
350                     long tunnelUpTime = mUpStateTime.getTime() - mBringUpStateTime.getTime();
351                     sb.append("\n\tTime taken for the tunnel to come up in ms: " + tunnelUpTime);
352                 }
353                 return sb.toString();
354             }
355         }
356 
357         @VisibleForTesting
358         class IwlanTunnelCallback implements EpdgTunnelManager.TunnelCallback {
359 
360             DataServiceProvider mDataServiceProvider;
361 
IwlanTunnelCallback(DataServiceProvider dsp)362             public IwlanTunnelCallback(DataServiceProvider dsp) {
363                 mDataServiceProvider = dsp;
364             }
365 
366             // TODO: full implementation
367 
onOpened(String apnName, TunnelLinkProperties linkProperties)368             public void onOpened(String apnName, TunnelLinkProperties linkProperties) {
369                 Log.d(
370                         SUB_TAG,
371                         "Tunnel opened!. APN: " + apnName + "linkproperties: " + linkProperties);
372                 mIwlanDataServiceHandler.sendMessage(
373                         mIwlanDataServiceHandler.obtainMessage(
374                                 EVENT_TUNNEL_OPENED,
375                                 new TunnelOpenedData(
376                                         apnName, linkProperties, IwlanDataServiceProvider.this)));
377             }
378 
onClosed(String apnName, IwlanError error)379             public void onClosed(String apnName, IwlanError error) {
380                 Log.d(SUB_TAG, "Tunnel closed!. APN: " + apnName + " Error: " + error);
381                 // this is called, when a tunnel that is up, is closed.
382                 // the expectation is error==NO_ERROR for user initiated/normal close.
383                 mIwlanDataServiceHandler.sendMessage(
384                         mIwlanDataServiceHandler.obtainMessage(
385                                 EVENT_TUNNEL_CLOSED,
386                                 new TunnelClosedData(
387                                         apnName, error, IwlanDataServiceProvider.this)));
388             }
389         }
390 
391         @VisibleForTesting
392         class IwlanTunnelCallbackMetrics implements EpdgTunnelManager.TunnelCallbackMetrics {
393 
394             DataServiceProvider mDataServiceProvider;
395 
IwlanTunnelCallbackMetrics(DataServiceProvider dsp)396             public IwlanTunnelCallbackMetrics(DataServiceProvider dsp) {
397                 mDataServiceProvider = dsp;
398             }
399 
onOpened( String apnName, String epdgServerAddress, int epdgServerSelectionDuration, int ikeTunnelEstablishmentDuration)400             public void onOpened(
401                     String apnName,
402                     String epdgServerAddress,
403                     int epdgServerSelectionDuration,
404                     int ikeTunnelEstablishmentDuration) {
405                 mIwlanDataServiceHandler.sendMessage(
406                         mIwlanDataServiceHandler.obtainMessage(
407                                 EVENT_TUNNEL_OPENED_METRICS,
408                                 new TunnelOpenedMetricsData(
409                                         apnName,
410                                         epdgServerAddress,
411                                         System.currentTimeMillis() - mProcessingStartTime,
412                                         epdgServerSelectionDuration,
413                                         ikeTunnelEstablishmentDuration,
414                                         IwlanDataServiceProvider.this)));
415             }
416 
onClosed( String apnName, String epdgServerAddress, int epdgServerSelectionDuration, int ikeTunnelEstablishmentDuration)417             public void onClosed(
418                     String apnName,
419                     String epdgServerAddress,
420                     int epdgServerSelectionDuration,
421                     int ikeTunnelEstablishmentDuration) {
422                 mIwlanDataServiceHandler.sendMessage(
423                         mIwlanDataServiceHandler.obtainMessage(
424                                 EVENT_TUNNEL_CLOSED_METRICS,
425                                 new TunnelClosedMetricsData(
426                                         apnName,
427                                         epdgServerAddress,
428                                         mProcessingStartTime > 0
429                                                 ? System.currentTimeMillis() - mProcessingStartTime
430                                                 : 0,
431                                         epdgServerSelectionDuration,
432                                         ikeTunnelEstablishmentDuration,
433                                         IwlanDataServiceProvider.this)));
434             }
435         }
436 
437         /** Holds all tunnel related time and count statistics for this IwlanDataServiceProvider */
438         @VisibleForTesting
439         class IwlanDataTunnelStats {
440 
441             // represents the start time from when the following events are recorded
442             private Date mStartTime;
443 
444             // Stats for TunnelSetup Success time (BRING_UP -> UP state)
445             @VisibleForTesting
446             Map<String, LongSummaryStatistics> mTunnelSetupSuccessStats =
447                     new HashMap<String, LongSummaryStatistics>();
448             // Count for Tunnel Setup failures onClosed when in BRING_UP
449             @VisibleForTesting
450             Map<String, Long> mTunnelSetupFailureCounts = new HashMap<String, Long>();
451 
452             // Count for unsol tunnel down onClosed when in UP without deactivate
453             @VisibleForTesting
454             Map<String, Long> mUnsolTunnelDownCounts = new HashMap<String, Long>();
455 
456             // Stats for how long the tunnel is in up state onClosed when in UP
457             @VisibleForTesting
458             Map<String, LongSummaryStatistics> mTunnelUpStats =
459                     new HashMap<String, LongSummaryStatistics>();
460 
461             private long statCount;
462             private final long COUNT_MAX = 1000;
463             private final int APN_COUNT_MAX = 10;
464 
IwlanDataTunnelStats()465             public IwlanDataTunnelStats() {
466                 mStartTime = Calendar.getInstance().getTime();
467                 statCount = 0L;
468             }
469 
reportTunnelSetupSuccess(String apn, TunnelState tunnelState)470             public void reportTunnelSetupSuccess(String apn, TunnelState tunnelState) {
471                 if (statCount > COUNT_MAX || maxApnReached()) {
472                     reset();
473                 }
474                 statCount++;
475 
476                 Date bringUpTime = tunnelState.getBringUpStateTime();
477                 Date upTime = tunnelState.getUpStateTime();
478 
479                 if (bringUpTime != null && upTime != null) {
480                     long tunnelUpTime = upTime.getTime() - bringUpTime.getTime();
481                     if (!mTunnelSetupSuccessStats.containsKey(apn)) {
482                         mTunnelSetupSuccessStats.put(apn, new LongSummaryStatistics());
483                     }
484                     LongSummaryStatistics stats = mTunnelSetupSuccessStats.get(apn);
485                     stats.accept(tunnelUpTime);
486                     mTunnelSetupSuccessStats.put(apn, stats);
487                 }
488             }
489 
reportTunnelDown(String apn, TunnelState tunnelState)490             public void reportTunnelDown(String apn, TunnelState tunnelState) {
491                 if (statCount > COUNT_MAX || maxApnReached()) {
492                     reset();
493                 }
494                 statCount++;
495 
496                 // Setup fail
497                 if (tunnelState.getState() == TunnelState.TUNNEL_IN_BRINGUP) {
498                     if (!mTunnelSetupFailureCounts.containsKey(apn)) {
499                         mTunnelSetupFailureCounts.put(apn, 0L);
500                     }
501                     long count = mTunnelSetupFailureCounts.get(apn);
502                     mTunnelSetupFailureCounts.put(apn, ++count);
503                     return;
504                 }
505 
506                 // Unsolicited tunnel down as tunnel has to be in BRINGDOWN if
507                 // there is a deactivate call associated with this.
508                 if (tunnelState.getState() == TunnelState.TUNNEL_UP) {
509                     if (!mUnsolTunnelDownCounts.containsKey(apn)) {
510                         mUnsolTunnelDownCounts.put(apn, 0L);
511                     }
512                     long count = mUnsolTunnelDownCounts.get(apn);
513                     mUnsolTunnelDownCounts.put(apn, ++count);
514                 }
515                 Date currentTime = Calendar.getInstance().getTime();
516                 Date upTime = tunnelState.getUpStateTime();
517                 if (upTime != null) {
518                     if (!mTunnelUpStats.containsKey(apn)) {
519                         mTunnelUpStats.put(apn, new LongSummaryStatistics());
520                     }
521                     LongSummaryStatistics stats = mTunnelUpStats.get(apn);
522                     stats.accept(currentTime.getTime() - upTime.getTime());
523                     mTunnelUpStats.put(apn, stats);
524                 }
525             }
526 
maxApnReached()527             boolean maxApnReached() {
528                 if (mTunnelSetupSuccessStats.size() >= APN_COUNT_MAX
529                         || mTunnelSetupFailureCounts.size() >= APN_COUNT_MAX
530                         || mUnsolTunnelDownCounts.size() >= APN_COUNT_MAX
531                         || mTunnelUpStats.size() >= APN_COUNT_MAX) {
532                     return true;
533                 }
534                 return false;
535             }
536 
537             @Override
toString()538             public String toString() {
539                 StringBuilder sb = new StringBuilder();
540                 sb.append("IwlanDataTunnelStats:");
541                 sb.append("\n\tmStartTime: " + mStartTime);
542                 sb.append("\n\ttunnelSetupSuccessStats:");
543                 for (Map.Entry<String, LongSummaryStatistics> entry :
544                         mTunnelSetupSuccessStats.entrySet()) {
545                     sb.append("\n\t  Apn: " + entry.getKey());
546                     sb.append("\n\t  " + entry.getValue());
547                 }
548                 sb.append("\n\ttunnelUpStats:");
549                 for (Map.Entry<String, LongSummaryStatistics> entry : mTunnelUpStats.entrySet()) {
550                     sb.append("\n\t  Apn: " + entry.getKey());
551                     sb.append("\n\t  " + entry.getValue());
552                 }
553 
554                 sb.append("\n\ttunnelSetupFailureCounts: ");
555                 for (Map.Entry<String, Long> entry : mTunnelSetupFailureCounts.entrySet()) {
556                     sb.append("\n\t  Apn: " + entry.getKey());
557                     sb.append("\n\t  counts: " + entry.getValue());
558                 }
559                 sb.append("\n\tunsolTunnelDownCounts: ");
560                 for (Map.Entry<String, Long> entry : mTunnelSetupFailureCounts.entrySet()) {
561                     sb.append("\n\t  Apn: " + entry.getKey());
562                     sb.append("\n\t  counts: " + entry.getValue());
563                 }
564                 sb.append("\n\tendTime: " + Calendar.getInstance().getTime());
565                 return sb.toString();
566             }
567 
reset()568             private void reset() {
569                 mStartTime = Calendar.getInstance().getTime();
570                 mTunnelSetupSuccessStats = new HashMap<String, LongSummaryStatistics>();
571                 mTunnelUpStats = new HashMap<String, LongSummaryStatistics>();
572                 mTunnelSetupFailureCounts = new HashMap<String, Long>();
573                 mUnsolTunnelDownCounts = new HashMap<String, Long>();
574                 statCount = 0L;
575             }
576         }
577 
578         /**
579          * Constructor
580          *
581          * @param slotIndex SIM slot index the data service provider associated with.
582          */
IwlanDataServiceProvider(int slotIndex, IwlanDataService iwlanDataService)583         public IwlanDataServiceProvider(int slotIndex, IwlanDataService iwlanDataService) {
584             super(slotIndex);
585             SUB_TAG = TAG + "[" + slotIndex + "]";
586 
587             // TODO:
588             // get reference carrier config for this sub
589             // get reference to resolver
590             mIwlanDataService = iwlanDataService;
591             mIwlanTunnelCallback = new IwlanTunnelCallback(this);
592             mIwlanTunnelCallbackMetrics = new IwlanTunnelCallbackMetrics(this);
593             mEpdgSelector = EpdgSelector.getSelectorInstance(mContext, slotIndex);
594             mTunnelStats = new IwlanDataTunnelStats();
595 
596             // Register IwlanEventListener
597             List<Integer> events = new ArrayList<Integer>();
598             events.add(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT);
599             events.add(IwlanEventListener.CARRIER_CONFIG_UNKNOWN_CARRIER_EVENT);
600             events.add(IwlanEventListener.WIFI_CALLING_ENABLE_EVENT);
601             events.add(IwlanEventListener.WIFI_CALLING_DISABLE_EVENT);
602             events.add(IwlanEventListener.CELLINFO_CHANGED_EVENT);
603             IwlanEventListener.getInstance(mContext, slotIndex)
604                     .addEventListener(events, mIwlanDataServiceHandler);
605         }
606 
607         @VisibleForTesting
getTunnelManager()608         EpdgTunnelManager getTunnelManager() {
609             return EpdgTunnelManager.getInstance(mContext, getSlotIndex());
610         }
611 
612         // creates a DataCallResponse for an apn irrespective of state
apnTunnelStateToDataCallResponse(String apn)613         private DataCallResponse apnTunnelStateToDataCallResponse(String apn) {
614             TunnelState tunnelState = mTunnelStateForApn.get(apn);
615             if (tunnelState == null) {
616                 return null;
617             }
618 
619             DataCallResponse.Builder responseBuilder = new DataCallResponse.Builder();
620             responseBuilder
621                     .setId(apn.hashCode())
622                     .setProtocolType(tunnelState.getProtocolType())
623                     .setCause(DataFailCause.NONE);
624 
625             responseBuilder.setLinkStatus(DataCallResponse.LINK_STATUS_INACTIVE);
626             int state = tunnelState.getState();
627 
628             if (state == TunnelState.TUNNEL_UP) {
629                 responseBuilder.setLinkStatus(DataCallResponse.LINK_STATUS_ACTIVE);
630             }
631 
632             TunnelLinkProperties tunnelLinkProperties = tunnelState.getTunnelLinkProperties();
633             if (tunnelLinkProperties == null) {
634                 Log.d(TAG, "PDN with empty linkproperties. TunnelState : " + state);
635                 return responseBuilder.build();
636             }
637 
638             // fill wildcard address for gatewayList (used by DataConnection to add routes)
639             List<InetAddress> gatewayList = new ArrayList<>();
640             List<LinkAddress> linkAddrList = tunnelLinkProperties.internalAddresses();
641             if (linkAddrList.stream().anyMatch(t -> t.isIpv4())) {
642                 try {
643                     gatewayList.add(Inet4Address.getByName("0.0.0.0"));
644                 } catch (UnknownHostException e) {
645                     // should never happen for static string 0.0.0.0
646                 }
647             }
648             if (linkAddrList.stream().anyMatch(t -> t.isIpv6())) {
649                 try {
650                     gatewayList.add(Inet6Address.getByName("::"));
651                 } catch (UnknownHostException e) {
652                     // should never happen for static string ::
653                 }
654             }
655 
656             if (tunnelLinkProperties.sliceInfo().isPresent()) {
657                 responseBuilder.setSliceInfo(tunnelLinkProperties.sliceInfo().get());
658             }
659 
660             return responseBuilder
661                     .setAddresses(linkAddrList)
662                     .setDnsAddresses(tunnelLinkProperties.dnsAddresses())
663                     .setPcscfAddresses(tunnelLinkProperties.pcscfAddresses())
664                     .setInterfaceName(tunnelLinkProperties.ifaceName())
665                     .setGatewayAddresses(gatewayList)
666                     .setMtu(tunnelState.getLinkMtu())
667                     .setMtuV4(tunnelState.getLinkMtu())
668                     .setMtuV6(tunnelState.getLinkMtu())
669                     .setPduSessionId(tunnelState.getPduSessionId())
670                     .build(); // underlying n/w is same
671         }
672 
getCallList()673         private List<DataCallResponse> getCallList() {
674             List<DataCallResponse> dcList = new ArrayList<>();
675             for (String key : mTunnelStateForApn.keySet()) {
676                 DataCallResponse dcRsp = apnTunnelStateToDataCallResponse(key);
677                 if (dcRsp != null) {
678                     Log.d(SUB_TAG, "Apn: " + key + "Link state: " + dcRsp.getLinkStatus());
679                     dcList.add(dcRsp);
680                 }
681             }
682             return dcList;
683         }
684 
deliverCallback( int callbackType, int result, DataServiceCallback callback, DataCallResponse rsp)685         private void deliverCallback(
686                 int callbackType, int result, DataServiceCallback callback, DataCallResponse rsp) {
687             if (callback == null) {
688                 Log.d(SUB_TAG, "deliverCallback: callback is null.  callbackType:" + callbackType);
689                 return;
690             }
691             Log.d(
692                     SUB_TAG,
693                     "Delivering callbackType:"
694                             + callbackType
695                             + " result:"
696                             + result
697                             + " rsp:"
698                             + rsp);
699             switch (callbackType) {
700                 case CALLBACK_TYPE_DEACTIVATE_DATACALL_COMPLETE:
701                     callback.onDeactivateDataCallComplete(result);
702                     // always update current datacalllist
703                     notifyDataCallListChanged(getCallList());
704                     break;
705 
706                 case CALLBACK_TYPE_SETUP_DATACALL_COMPLETE:
707                     if (result == DataServiceCallback.RESULT_SUCCESS && rsp == null) {
708                         Log.d(SUB_TAG, "Warning: null rsp for success case");
709                     }
710                     callback.onSetupDataCallComplete(result, rsp);
711                     // always update current datacalllist
712                     notifyDataCallListChanged(getCallList());
713                     break;
714 
715                 case CALLBACK_TYPE_GET_DATACALL_LIST_COMPLETE:
716                     callback.onRequestDataCallListComplete(result, getCallList());
717                     // TODO: add code for the rest of the cases
718             }
719         }
720 
721         /**
722          * Setup a data connection.
723          *
724          * @param accessNetworkType Access network type that the data call will be established on.
725          *     Must be one of {@link android.telephony.AccessNetworkConstants.AccessNetworkType}.
726          * @param dataProfile Data profile used for data call setup. See {@link DataProfile}
727          * @param isRoaming True if the device is data roaming.
728          * @param allowRoaming True if data roaming is allowed by the user.
729          * @param reason The reason for data setup. Must be {@link #REQUEST_REASON_NORMAL} or {@link
730          *     #REQUEST_REASON_HANDOVER}.
731          * @param linkProperties If {@code reason} is {@link #REQUEST_REASON_HANDOVER}, this is the
732          *     link properties of the existing data connection, otherwise null.
733          * @param pduSessionId The pdu session id to be used for this data call. The standard range
734          *     of values are 1-15 while 0 means no pdu session id was attached to this call.
735          *     Reference: 3GPP TS 24.007 section 11.2.3.1b.
736          * @param sliceInfo The slice info related to this data call.
737          * @param trafficDescriptor TrafficDescriptor for which data connection needs to be
738          *     established. It is used for URSP traffic matching as described in 3GPP TS 24.526
739          *     Section 4.2.2. It includes an optional DNN which, if present, must be used for
740          *     traffic matching; it does not specify the end point to be used for the data call.
741          * @param matchAllRuleAllowed Indicates if using default match-all URSP rule for this
742          *     request is allowed. If false, this request must not use the match-all URSP rule and
743          *     if a non-match-all rule is not found (or if URSP rules are not available) then {@link
744          *     DataCallResponse#getCause()} is {@link
745          *     android.telephony.DataFailCause#MATCH_ALL_RULE_NOT_ALLOWED}. This is needed as some
746          *     requests need to have a hard failure if the intention cannot be met, for example, a
747          *     zero-rating slice.
748          * @param callback The result callback for this request.
749          */
750         @Override
setupDataCall( int accessNetworkType, @NonNull DataProfile dataProfile, boolean isRoaming, boolean allowRoaming, int reason, @Nullable LinkProperties linkProperties, @IntRange(from = 0, to = 15) int pduSessionId, @Nullable NetworkSliceInfo sliceInfo, @Nullable TrafficDescriptor trafficDescriptor, boolean matchAllRuleAllowed, @NonNull DataServiceCallback callback)751         public void setupDataCall(
752                 int accessNetworkType,
753                 @NonNull DataProfile dataProfile,
754                 boolean isRoaming,
755                 boolean allowRoaming,
756                 int reason,
757                 @Nullable LinkProperties linkProperties,
758                 @IntRange(from = 0, to = 15) int pduSessionId,
759                 @Nullable NetworkSliceInfo sliceInfo,
760                 @Nullable TrafficDescriptor trafficDescriptor,
761                 boolean matchAllRuleAllowed,
762                 @NonNull DataServiceCallback callback) {
763 
764             mProcessingStartTime = System.currentTimeMillis();
765             Log.d(
766                     SUB_TAG,
767                     "Setup data call with network: "
768                             + accessNetworkType
769                             + ", DataProfile: "
770                             + dataProfile
771                             + ", isRoaming:"
772                             + isRoaming
773                             + ", allowRoaming: "
774                             + allowRoaming
775                             + ", reason: "
776                             + reason
777                             + ", linkProperties: "
778                             + linkProperties
779                             + ", pduSessionId: "
780                             + pduSessionId);
781 
782             SetupDataCallData setupDataCallData =
783                     new SetupDataCallData(
784                             accessNetworkType,
785                             dataProfile,
786                             isRoaming,
787                             allowRoaming,
788                             reason,
789                             linkProperties,
790                             pduSessionId,
791                             sliceInfo,
792                             trafficDescriptor,
793                             matchAllRuleAllowed,
794                             callback,
795                             this);
796 
797             int networkTransport = -1;
798             if (sDefaultDataTransport == Transport.MOBILE) {
799                 networkTransport = TRANSPORT_CELLULAR;
800             } else if (sDefaultDataTransport == Transport.MOBILE) {
801                 networkTransport = TRANSPORT_WIFI;
802             }
803 
804             if (dataProfile != null) {
805                 this.setMetricsAtom(
806                         // ApnName
807                         dataProfile.getApn(),
808                         // ApnType
809                         dataProfile.getSupportedApnTypesBitmask(),
810                         // IsHandover
811                         (reason == DataService.REQUEST_REASON_HANDOVER),
812                         // Source Rat
813                         getCurrentCellularRat(),
814                         // IsRoaming
815                         isRoaming,
816                         // Is Network Connected
817                         sNetworkConnected,
818                         // Transport Type
819                         networkTransport);
820             }
821 
822             mIwlanDataServiceHandler.sendMessage(
823                     mIwlanDataServiceHandler.obtainMessage(
824                             EVENT_SETUP_DATA_CALL, setupDataCallData));
825         }
826 
827         /**
828          * Deactivate a data connection. The data service provider must implement this method to
829          * support data connection tear down. When completed or error, the service must invoke the
830          * provided callback to notify the platform.
831          *
832          * @param cid Call id returned in the callback of {@link
833          *     DataServiceProvider#setupDataCall(int, DataProfile, boolean, boolean, int,
834          *     LinkProperties, DataServiceCallback)}.
835          * @param reason The reason for data deactivation. Must be {@link #REQUEST_REASON_NORMAL},
836          *     {@link #REQUEST_REASON_SHUTDOWN} or {@link #REQUEST_REASON_HANDOVER}.
837          * @param callback The result callback for this request. Null if the client does not care
838          */
839         @Override
deactivateDataCall(int cid, int reason, DataServiceCallback callback)840         public void deactivateDataCall(int cid, int reason, DataServiceCallback callback) {
841             Log.d(
842                     SUB_TAG,
843                     "Deactivate data call "
844                             + " reason: "
845                             + reason
846                             + " cid: "
847                             + cid
848                             + "callback: "
849                             + callback);
850 
851             DeactivateDataCallData deactivateDataCallData =
852                     new DeactivateDataCallData(cid, reason, callback, this);
853 
854             mIwlanDataServiceHandler.sendMessage(
855                     mIwlanDataServiceHandler.obtainMessage(
856                             EVENT_DEACTIVATE_DATA_CALL, deactivateDataCallData));
857         }
858 
forceCloseTunnelsInDeactivatingState()859         public void forceCloseTunnelsInDeactivatingState() {
860             for (Map.Entry<String, TunnelState> entry : mTunnelStateForApn.entrySet()) {
861                 TunnelState tunnelState = entry.getValue();
862                 if (tunnelState.getState() == TunnelState.TUNNEL_IN_BRINGDOWN) {
863                     getTunnelManager().closeTunnel(entry.getKey(), true);
864                 }
865             }
866         }
867 
forceCloseTunnels()868         void forceCloseTunnels() {
869             for (Map.Entry<String, TunnelState> entry : mTunnelStateForApn.entrySet()) {
870                 getTunnelManager().closeTunnel(entry.getKey(), true);
871             }
872         }
873 
874         /**
875          * Get the active data call list.
876          *
877          * @param callback The result callback for this request.
878          */
879         @Override
requestDataCallList(DataServiceCallback callback)880         public void requestDataCallList(DataServiceCallback callback) {
881             mIwlanDataServiceHandler.sendMessage(
882                     mIwlanDataServiceHandler.obtainMessage(
883                             EVENT_DATA_CALL_LIST_REQUEST,
884                             new DataCallRequestData(callback, IwlanDataServiceProvider.this)));
885         }
886 
887         @VisibleForTesting
setTunnelState( DataProfile dataProfile, DataServiceCallback callback, int tunnelStatus, TunnelLinkProperties linkProperties, boolean isHandover, int pduSessionId)888         void setTunnelState(
889                 DataProfile dataProfile,
890                 DataServiceCallback callback,
891                 int tunnelStatus,
892                 TunnelLinkProperties linkProperties,
893                 boolean isHandover,
894                 int pduSessionId) {
895             TunnelState tunnelState = new TunnelState(callback);
896             tunnelState.setState(tunnelStatus);
897             tunnelState.setProtocolType(dataProfile.getProtocolType());
898             tunnelState.setTunnelLinkProperties(linkProperties);
899             tunnelState.setIsHandover(isHandover);
900             tunnelState.setPduSessionId(pduSessionId);
901             mTunnelStateForApn.put(dataProfile.getApn(), tunnelState);
902         }
903 
904         @VisibleForTesting
setMetricsAtom( String apnName, int apntype, boolean isHandover, int sourceRat, boolean isRoaming, boolean isNetworkConnected, int transportType)905         void setMetricsAtom(
906                 String apnName,
907                 int apntype,
908                 boolean isHandover,
909                 int sourceRat,
910                 boolean isRoaming,
911                 boolean isNetworkConnected,
912                 int transportType) {
913             MetricsAtom metricsAtom = new MetricsAtom();
914             metricsAtom.setApnType(apntype);
915             metricsAtom.setIsHandover(isHandover);
916             metricsAtom.setSourceRat(sourceRat);
917             metricsAtom.setIsCellularRoaming(isRoaming);
918             metricsAtom.setIsNetworkConnected(isNetworkConnected);
919             metricsAtom.setTransportType(transportType);
920             mMetricsAtomForApn.put(apnName, metricsAtom);
921         }
922 
923         @VisibleForTesting
924         @Nullable
getMetricsAtomByApn(String apnName)925         public MetricsAtom getMetricsAtomByApn(String apnName) {
926             return mMetricsAtomForApn.get(apnName);
927         }
928 
929         @VisibleForTesting
getIwlanTunnelCallback()930         public IwlanTunnelCallback getIwlanTunnelCallback() {
931             return mIwlanTunnelCallback;
932         }
933 
934         @VisibleForTesting
getIwlanTunnelCallbackMetrics()935         public IwlanTunnelCallbackMetrics getIwlanTunnelCallbackMetrics() {
936             return mIwlanTunnelCallbackMetrics;
937         }
938 
939         @VisibleForTesting
getTunnelStats()940         IwlanDataTunnelStats getTunnelStats() {
941             return mTunnelStats;
942         }
943 
updateNetwork(Network network)944         private void updateNetwork(Network network) {
945             if (network != null) {
946                 for (Map.Entry<String, TunnelState> entry : mTunnelStateForApn.entrySet()) {
947                     TunnelState tunnelState = entry.getValue();
948                     if (tunnelState.getState() == TunnelState.TUNNEL_IN_BRINGUP) {
949                         // force close tunnels in bringup since IKE lib only supports
950                         // updating network for tunnels that are already up.
951                         // This may not result in actual closing of Ike Session since
952                         // epdg selection may not be complete yet.
953                         tunnelState.setState(TunnelState.TUNNEL_IN_FORCE_CLEAN_WAS_IN_BRINGUP);
954                         getTunnelManager().closeTunnel(entry.getKey(), true);
955                     } else {
956                         if (mIwlanDataService.isNetworkConnected(
957                                 IwlanHelper.isDefaultDataSlot(mContext, getSlotIndex()),
958                                 IwlanHelper.isCrossSimCallingEnabled(mContext, getSlotIndex()))) {
959                             getTunnelManager().updateNetwork(network, entry.getKey());
960                         }
961                     }
962                 }
963             }
964         }
965 
isRegisteredCellInfoChanged(List<CellInfo> cellInfoList)966         private boolean isRegisteredCellInfoChanged(List<CellInfo> cellInfoList) {
967             for (CellInfo cellInfo : cellInfoList) {
968                 if (!cellInfo.isRegistered()) {
969                     continue;
970                 }
971 
972                 if (mCellInfo == null || mCellInfo != cellInfo) {
973                     mCellInfo = cellInfo;
974                     Log.d(TAG, " Update cached cellinfo");
975                     return true;
976                 }
977             }
978             return false;
979         }
980 
dnsPrefetchCheck()981         private void dnsPrefetchCheck() {
982             boolean networkConnected =
983                     mIwlanDataService.isNetworkConnected(
984                             IwlanHelper.isDefaultDataSlot(mContext, getSlotIndex()),
985                             IwlanHelper.isCrossSimCallingEnabled(mContext, getSlotIndex()));
986             /* Check if we need to do prefecting */
987             if (networkConnected == true
988                     && mCarrierConfigReady == true
989                     && mWfcEnabled == true
990                     && mTunnelStateForApn.isEmpty()) {
991 
992                 // Get roaming status
993                 TelephonyManager telephonyManager =
994                         mContext.getSystemService(TelephonyManager.class);
995                 telephonyManager =
996                         telephonyManager.createForSubscriptionId(
997                                 IwlanHelper.getSubId(mContext, getSlotIndex()));
998                 boolean isRoaming = telephonyManager.isNetworkRoaming();
999                 Log.d(TAG, "Trigger EPDG prefetch. Roaming=" + isRoaming);
1000 
1001                 prefetchEpdgServerList(mIwlanDataService.sNetwork, isRoaming);
1002             }
1003         }
1004 
prefetchEpdgServerList(Network network, boolean isRoaming)1005         private void prefetchEpdgServerList(Network network, boolean isRoaming) {
1006             mEpdgSelector.getValidatedServerList(
1007                     0, EpdgSelector.PROTO_FILTER_IPV4V6, isRoaming, false, network, null);
1008             mEpdgSelector.getValidatedServerList(
1009                     0, EpdgSelector.PROTO_FILTER_IPV4V6, isRoaming, true, network, null);
1010         }
1011 
getCurrentCellularRat()1012         private int getCurrentCellularRat() {
1013             TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class);
1014             telephonyManager =
1015                     telephonyManager.createForSubscriptionId(
1016                             IwlanHelper.getSubId(mContext, getSlotIndex()));
1017             List<CellInfo> cellInfoList = telephonyManager.getAllCellInfo();
1018             if (cellInfoList == null) {
1019                 Log.e(TAG, "cellInfoList is NULL");
1020                 return 0;
1021             }
1022 
1023             for (CellInfo cellInfo : cellInfoList) {
1024                 if (!cellInfo.isRegistered()) {
1025                     continue;
1026                 }
1027                 if (cellInfo instanceof CellInfoGsm) {
1028                     return TelephonyManager.NETWORK_TYPE_GSM;
1029                 } else if (cellInfo instanceof CellInfoWcdma) {
1030                     return TelephonyManager.NETWORK_TYPE_UMTS;
1031                 } else if (cellInfo instanceof CellInfoLte) {
1032                     return TelephonyManager.NETWORK_TYPE_LTE;
1033                 } else if (cellInfo instanceof CellInfoNr) {
1034                     return TelephonyManager.NETWORK_TYPE_NR;
1035                 }
1036             }
1037             return TelephonyManager.NETWORK_TYPE_UNKNOWN;
1038         }
1039 
1040         /**
1041          * Called when the instance of data service is destroyed (e.g. got unbind or binder died) or
1042          * when the data service provider is removed.
1043          */
1044         @Override
close()1045         public void close() {
1046             // TODO: call epdgtunnelmanager.releaseInstance or equivalent
1047             mIwlanDataService.removeDataServiceProvider(this);
1048             IwlanEventListener.getInstance(mContext, getSlotIndex())
1049                     .removeEventListener(mIwlanDataServiceHandler);
1050         }
1051 
dump(FileDescriptor fd, PrintWriter pw, String[] args)1052         public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1053             pw.println("---- IwlanDataServiceProvider[" + getSlotIndex() + "] ----");
1054             boolean isDDS = IwlanHelper.isDefaultDataSlot(mContext, getSlotIndex());
1055             boolean isCSTEnabled = IwlanHelper.isCrossSimCallingEnabled(mContext, getSlotIndex());
1056             pw.println("isDefaultDataSub: " + isDDS + " isCrossSimEnabled: " + isCSTEnabled);
1057             pw.println(
1058                     "isNetworkConnected: "
1059                             + isNetworkConnected(isDDS, isCSTEnabled)
1060                             + " Wfc enabled: "
1061                             + mWfcEnabled);
1062             for (Map.Entry<String, TunnelState> entry : mTunnelStateForApn.entrySet()) {
1063                 pw.println("Tunnel state for APN: " + entry.getKey());
1064                 pw.println(entry.getValue());
1065             }
1066             pw.println(mTunnelStats);
1067             EpdgTunnelManager.getInstance(mContext, getSlotIndex()).dump(fd, pw, args);
1068             ErrorPolicyManager.getInstance(mContext, getSlotIndex()).dump(fd, pw, args);
1069             pw.println("-------------------------------------");
1070         }
1071     }
1072 
1073     private final class IwlanDataServiceHandler extends Handler {
1074         private final String TAG = IwlanDataServiceHandler.class.getSimpleName();
1075 
1076         @Override
handleMessage(Message msg)1077         public void handleMessage(Message msg) {
1078             Log.d(TAG, "msg.what = " + eventToString(msg.what));
1079 
1080             String apnName;
1081             IwlanDataServiceProvider iwlanDataServiceProvider;
1082             IwlanDataServiceProvider.TunnelState tunnelState;
1083             DataServiceCallback callback;
1084             int reason;
1085             int retryTimeMillis;
1086             int errorCause;
1087             MetricsAtom metricsAtom;
1088 
1089             switch (msg.what) {
1090                 case EVENT_TUNNEL_OPENED:
1091                     TunnelOpenedData tunnelOpenedData = (TunnelOpenedData) msg.obj;
1092                     iwlanDataServiceProvider = tunnelOpenedData.mIwlanDataServiceProvider;
1093                     apnName = tunnelOpenedData.mApnName;
1094                     TunnelLinkProperties tunnelLinkProperties =
1095                             tunnelOpenedData.mTunnelLinkProperties;
1096 
1097                     tunnelState = iwlanDataServiceProvider.mTunnelStateForApn.get(apnName);
1098                     // tunnelstate should not be null, design violation.
1099                     // if its null, we should crash and debug.
1100                     tunnelState.setTunnelLinkProperties(tunnelLinkProperties);
1101                     tunnelState.setState(IwlanDataServiceProvider.TunnelState.TUNNEL_UP);
1102                     iwlanDataServiceProvider.mTunnelStats.reportTunnelSetupSuccess(
1103                             apnName, tunnelState);
1104 
1105                     // Record setup result for the Metrics
1106                     metricsAtom = iwlanDataServiceProvider.mMetricsAtomForApn.get(apnName);
1107                     metricsAtom.setSetupRequestResult(DataServiceCallback.RESULT_SUCCESS);
1108                     metricsAtom.setIwlanError(IwlanError.NO_ERROR);
1109                     metricsAtom.setDataCallFailCause(DataFailCause.NONE);
1110                     metricsAtom.setTunnelState(tunnelState.getState());
1111                     metricsAtom.setHandoverFailureMode(-1);
1112                     metricsAtom.setRetryDurationMillis(0);
1113                     metricsAtom.setMessageId(IwlanStatsLog.IWLAN_SETUP_DATA_CALL_RESULT_REPORTED);
1114 
1115                     iwlanDataServiceProvider.deliverCallback(
1116                             IwlanDataServiceProvider.CALLBACK_TYPE_SETUP_DATACALL_COMPLETE,
1117                             DataServiceCallback.RESULT_SUCCESS,
1118                             tunnelState.getDataServiceCallback(),
1119                             iwlanDataServiceProvider.apnTunnelStateToDataCallResponse(apnName));
1120                     break;
1121 
1122                 case EVENT_TUNNEL_CLOSED:
1123                     TunnelClosedData tunnelClosedData = (TunnelClosedData) msg.obj;
1124                     iwlanDataServiceProvider = tunnelClosedData.mIwlanDataServiceProvider;
1125                     apnName = tunnelClosedData.mApnName;
1126                     IwlanError iwlanError = tunnelClosedData.mIwlanError;
1127 
1128                     tunnelState = iwlanDataServiceProvider.mTunnelStateForApn.get(apnName);
1129                     iwlanDataServiceProvider.mTunnelStats.reportTunnelDown(apnName, tunnelState);
1130                     iwlanDataServiceProvider.mTunnelStateForApn.remove(apnName);
1131                     metricsAtom = iwlanDataServiceProvider.mMetricsAtomForApn.get(apnName);
1132 
1133                     if (tunnelState.getState()
1134                                     == IwlanDataServiceProvider.TunnelState.TUNNEL_IN_BRINGUP
1135                             || tunnelState.getState()
1136                                     == IwlanDataServiceProvider.TunnelState
1137                                             .TUNNEL_IN_FORCE_CLEAN_WAS_IN_BRINGUP) {
1138                         DataCallResponse.Builder respBuilder = new DataCallResponse.Builder();
1139                         respBuilder
1140                                 .setId(apnName.hashCode())
1141                                 .setProtocolType(tunnelState.getProtocolType());
1142 
1143                         if (tunnelState.getIsHandover()) {
1144                             respBuilder.setHandoverFailureMode(
1145                                     DataCallResponse
1146                                             .HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_HANDOVER);
1147                             metricsAtom.setHandoverFailureMode(
1148                                     DataCallResponse
1149                                             .HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_HANDOVER);
1150                         } else {
1151                             respBuilder.setHandoverFailureMode(
1152                                     DataCallResponse
1153                                             .HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_SETUP_NORMAL);
1154                             metricsAtom.setHandoverFailureMode(
1155                                     DataCallResponse
1156                                             .HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_SETUP_NORMAL);
1157                         }
1158 
1159                         if (tunnelState.getState()
1160                                 == IwlanDataServiceProvider.TunnelState.TUNNEL_IN_BRINGUP) {
1161                             errorCause =
1162                                     ErrorPolicyManager.getInstance(
1163                                                     mContext,
1164                                                     iwlanDataServiceProvider.getSlotIndex())
1165                                             .getDataFailCause(apnName);
1166                             respBuilder.setCause(errorCause);
1167                             metricsAtom.setDataCallFailCause(errorCause);
1168 
1169                             retryTimeMillis =
1170                                     (int)
1171                                             ErrorPolicyManager.getInstance(
1172                                                             mContext,
1173                                                             iwlanDataServiceProvider.getSlotIndex())
1174                                                     .getCurrentRetryTimeMs(apnName);
1175                             respBuilder.setRetryDurationMillis(retryTimeMillis);
1176                             metricsAtom.setRetryDurationMillis(retryTimeMillis);
1177 
1178                         } else if (tunnelState.getState()
1179                                 == IwlanDataServiceProvider.TunnelState
1180                                         .TUNNEL_IN_FORCE_CLEAN_WAS_IN_BRINGUP) {
1181                             respBuilder.setCause(DataFailCause.IWLAN_NETWORK_FAILURE);
1182                             metricsAtom.setDataCallFailCause(DataFailCause.IWLAN_NETWORK_FAILURE);
1183                             respBuilder.setRetryDurationMillis(5000);
1184                             metricsAtom.setRetryDurationMillis(5000);
1185                         }
1186 
1187                         // Record setup result for the Metrics
1188                         metricsAtom.setSetupRequestResult(DataServiceCallback.RESULT_SUCCESS);
1189                         metricsAtom.setIwlanError(iwlanError.getErrorType());
1190 
1191                         metricsAtom.setIwlanErrorWrappedClassnameAndStack(iwlanError);
1192 
1193                         metricsAtom.setTunnelState(tunnelState.getState());
1194                         metricsAtom.setMessageId(
1195                                 IwlanStatsLog.IWLAN_SETUP_DATA_CALL_RESULT_REPORTED);
1196 
1197                         iwlanDataServiceProvider.deliverCallback(
1198                                 IwlanDataServiceProvider.CALLBACK_TYPE_SETUP_DATACALL_COMPLETE,
1199                                 DataServiceCallback.RESULT_SUCCESS,
1200                                 tunnelState.getDataServiceCallback(),
1201                                 respBuilder.build());
1202                         return;
1203                     }
1204 
1205                     // iwlan service triggered teardown
1206                     if (tunnelState.getState()
1207                             == IwlanDataServiceProvider.TunnelState.TUNNEL_IN_BRINGDOWN) {
1208 
1209                         // IO exception happens when IKE library fails to retransmit requests.
1210                         // This can happen for multiple reasons:
1211                         // 1. Network disconnection due to wifi off.
1212                         // 2. Epdg server does not respond.
1213                         // 3. Socket send/receive fails.
1214                         // Ignore this during tunnel bring down.
1215                         if (iwlanError.getErrorType() != IwlanError.NO_ERROR
1216                                 && iwlanError.getErrorType()
1217                                         != IwlanError.IKE_INTERNAL_IO_EXCEPTION) {
1218                             Log.e(TAG, "Unexpected error during tunnel bring down: " + iwlanError);
1219                         }
1220 
1221                         iwlanDataServiceProvider.deliverCallback(
1222                                 IwlanDataServiceProvider.CALLBACK_TYPE_DEACTIVATE_DATACALL_COMPLETE,
1223                                 DataServiceCallback.RESULT_SUCCESS,
1224                                 tunnelState.getDataServiceCallback(),
1225                                 null);
1226 
1227                         return;
1228                     }
1229 
1230                     // just update list of data calls. No way to send error up
1231                     iwlanDataServiceProvider.notifyDataCallListChanged(
1232                             iwlanDataServiceProvider.getCallList());
1233 
1234                     // Report IwlanPdnDisconnectedReason due to the disconnection is neither for
1235                     // SETUP_DATA_CALL nor DEACTIVATE_DATA_CALL request.
1236                     metricsAtom.setDataCallFailCause(
1237                             ErrorPolicyManager.getInstance(
1238                                             mContext, iwlanDataServiceProvider.getSlotIndex())
1239                                     .getDataFailCause(apnName));
1240 
1241                     WifiManager wifiManager = mContext.getSystemService(WifiManager.class);
1242                     if (wifiManager == null) {
1243                         Log.e(TAG, "Could not find wifiManager");
1244                         return;
1245                     }
1246 
1247                     WifiInfo wifiInfo = wifiManager.getConnectionInfo();
1248                     if (wifiInfo == null) {
1249                         Log.e(TAG, "wifiInfo is null");
1250                         return;
1251                     }
1252 
1253                     metricsAtom.setWifiSignalValue(wifiInfo.getRssi());
1254                     metricsAtom.setMessageId(IwlanStatsLog.IWLAN_PDN_DISCONNECTED_REASON_REPORTED);
1255                     break;
1256 
1257                 case IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT:
1258                     iwlanDataServiceProvider =
1259                             (IwlanDataServiceProvider) getDataServiceProvider(msg.arg1);
1260 
1261                     iwlanDataServiceProvider.mCarrierConfigReady = true;
1262                     iwlanDataServiceProvider.dnsPrefetchCheck();
1263                     break;
1264 
1265                 case IwlanEventListener.CARRIER_CONFIG_UNKNOWN_CARRIER_EVENT:
1266                     iwlanDataServiceProvider =
1267                             (IwlanDataServiceProvider) getDataServiceProvider(msg.arg1);
1268 
1269                     iwlanDataServiceProvider.mCarrierConfigReady = false;
1270                     break;
1271 
1272                 case IwlanEventListener.WIFI_CALLING_ENABLE_EVENT:
1273                     iwlanDataServiceProvider =
1274                             (IwlanDataServiceProvider) getDataServiceProvider(msg.arg1);
1275 
1276                     iwlanDataServiceProvider.mWfcEnabled = true;
1277                     iwlanDataServiceProvider.dnsPrefetchCheck();
1278                     break;
1279 
1280                 case IwlanEventListener.WIFI_CALLING_DISABLE_EVENT:
1281                     iwlanDataServiceProvider =
1282                             (IwlanDataServiceProvider) getDataServiceProvider(msg.arg1);
1283 
1284                     iwlanDataServiceProvider.mWfcEnabled = false;
1285                     break;
1286 
1287                 case IwlanEventListener.CELLINFO_CHANGED_EVENT:
1288                     List<CellInfo> cellInfolist = (List<CellInfo>) msg.obj;
1289                     iwlanDataServiceProvider =
1290                             (IwlanDataServiceProvider) getDataServiceProvider(msg.arg1);
1291 
1292                     if (cellInfolist != null
1293                             && iwlanDataServiceProvider.isRegisteredCellInfoChanged(cellInfolist)) {
1294                         int[] addrResolutionMethods =
1295                                 IwlanHelper.getConfig(
1296                                         CarrierConfigManager.Iwlan
1297                                                 .KEY_EPDG_ADDRESS_PRIORITY_INT_ARRAY,
1298                                         mContext,
1299                                         iwlanDataServiceProvider.getSlotIndex());
1300                         for (int addrResolutionMethod : addrResolutionMethods) {
1301                             if (addrResolutionMethod
1302                                     == CarrierConfigManager.Iwlan.EPDG_ADDRESS_CELLULAR_LOC) {
1303                                 iwlanDataServiceProvider.dnsPrefetchCheck();
1304                             }
1305                         }
1306                     }
1307                     break;
1308 
1309                 case EVENT_SETUP_DATA_CALL:
1310                     SetupDataCallData setupDataCallData = (SetupDataCallData) msg.obj;
1311                     int accessNetworkType = setupDataCallData.mAccessNetworkType;
1312                     @NonNull DataProfile dataProfile = setupDataCallData.mDataProfile;
1313                     boolean isRoaming = setupDataCallData.mIsRoaming;
1314                     reason = setupDataCallData.mReason;
1315                     LinkProperties linkProperties = setupDataCallData.mLinkProperties;
1316                     @IntRange(from = 0, to = 15)
1317                     int pduSessionId = setupDataCallData.mPduSessionId;
1318                     callback = setupDataCallData.mCallback;
1319                     iwlanDataServiceProvider = setupDataCallData.mIwlanDataServiceProvider;
1320 
1321                     if ((accessNetworkType != AccessNetworkType.IWLAN)
1322                             || (dataProfile == null)
1323                             || (linkProperties == null
1324                                     && reason == DataService.REQUEST_REASON_HANDOVER)) {
1325 
1326                         iwlanDataServiceProvider.deliverCallback(
1327                                 IwlanDataServiceProvider.CALLBACK_TYPE_SETUP_DATACALL_COMPLETE,
1328                                 DataServiceCallback.RESULT_ERROR_INVALID_ARG,
1329                                 callback,
1330                                 null);
1331                         return;
1332                     }
1333 
1334                     boolean isDDS =
1335                             IwlanHelper.isDefaultDataSlot(
1336                                     mContext, iwlanDataServiceProvider.getSlotIndex());
1337                     boolean isCSTEnabled =
1338                             IwlanHelper.isCrossSimCallingEnabled(
1339                                     mContext, iwlanDataServiceProvider.getSlotIndex());
1340                     boolean networkConnected = isNetworkConnected(isDDS, isCSTEnabled);
1341                     Log.d(
1342                             TAG,
1343                             "isDds: "
1344                                     + isDDS
1345                                     + ", isCstEnabled: "
1346                                     + isCSTEnabled
1347                                     + ", transport: "
1348                                     + sDefaultDataTransport);
1349 
1350                     if (networkConnected == false) {
1351                         iwlanDataServiceProvider.deliverCallback(
1352                                 IwlanDataServiceProvider.CALLBACK_TYPE_SETUP_DATACALL_COMPLETE,
1353                                 5 /* DataServiceCallback.RESULT_ERROR_TEMPORARILY_UNAVAILABLE
1354                                    */,
1355                                 callback,
1356                                 null);
1357                         return;
1358                     }
1359 
1360                     tunnelState =
1361                             iwlanDataServiceProvider.mTunnelStateForApn.get(dataProfile.getApn());
1362 
1363                     // Return the existing PDN if the pduSessionId is the same and the tunnel
1364                     // state is
1365                     // TUNNEL_UP.
1366                     if (tunnelState != null) {
1367                         if (tunnelState.getPduSessionId() == pduSessionId
1368                                 && tunnelState.getState()
1369                                         == IwlanDataServiceProvider.TunnelState.TUNNEL_UP) {
1370                             Log.w(
1371                                     TAG,
1372                                     "The tunnel for " + dataProfile.getApn() + " already exists.");
1373                             iwlanDataServiceProvider.deliverCallback(
1374                                     IwlanDataServiceProvider.CALLBACK_TYPE_SETUP_DATACALL_COMPLETE,
1375                                     DataServiceCallback.RESULT_SUCCESS,
1376                                     callback,
1377                                     iwlanDataServiceProvider.apnTunnelStateToDataCallResponse(
1378                                             dataProfile.getApn()));
1379                             return;
1380                         } else {
1381                             Log.e(
1382                                     TAG,
1383                                     "Force close the existing PDN. pduSessionId = "
1384                                             + tunnelState.getPduSessionId()
1385                                             + " Tunnel State = "
1386                                             + tunnelState.getState());
1387                             iwlanDataServiceProvider
1388                                     .getTunnelManager()
1389                                     .closeTunnel(dataProfile.getApn(), true /* forceClose */);
1390                             iwlanDataServiceProvider.deliverCallback(
1391                                     IwlanDataServiceProvider.CALLBACK_TYPE_SETUP_DATACALL_COMPLETE,
1392                                     5 /* DataServiceCallback
1393                                       .RESULT_ERROR_TEMPORARILY_UNAVAILABLE */,
1394                                     callback,
1395                                     null);
1396                             return;
1397                         }
1398                     }
1399 
1400                     TunnelSetupRequest.Builder tunnelReqBuilder =
1401                             TunnelSetupRequest.builder()
1402                                     .setApnName(dataProfile.getApn())
1403                                     .setNetwork(sNetwork)
1404                                     .setIsRoaming(isRoaming)
1405                                     .setPduSessionId(pduSessionId)
1406                                     .setApnIpProtocol(
1407                                             isRoaming
1408                                                     ? dataProfile.getRoamingProtocolType()
1409                                                     : dataProfile.getProtocolType());
1410 
1411                     if (reason == DataService.REQUEST_REASON_HANDOVER) {
1412                         // for now assume that, at max,  only one address of eachtype (v4/v6).
1413                         // TODO: Check if multiple ips can be sent in ike tunnel setup
1414                         for (LinkAddress lAddr : linkProperties.getLinkAddresses()) {
1415                             if (lAddr.isIpv4()) {
1416                                 tunnelReqBuilder.setSrcIpv4Address(lAddr.getAddress());
1417                             } else if (lAddr.isIpv6()) {
1418                                 tunnelReqBuilder.setSrcIpv6Address(lAddr.getAddress());
1419                                 tunnelReqBuilder.setSrcIpv6AddressPrefixLength(
1420                                         lAddr.getPrefixLength());
1421                             }
1422                         }
1423                     }
1424 
1425                     int apnTypeBitmask = dataProfile.getSupportedApnTypesBitmask();
1426                     boolean isIMS = (apnTypeBitmask & ApnSetting.TYPE_IMS) == ApnSetting.TYPE_IMS;
1427                     boolean isEmergency =
1428                             (apnTypeBitmask & ApnSetting.TYPE_EMERGENCY)
1429                                     == ApnSetting.TYPE_EMERGENCY;
1430                     tunnelReqBuilder.setRequestPcscf(isIMS || isEmergency);
1431                     tunnelReqBuilder.setIsEmergency(isEmergency);
1432 
1433                     iwlanDataServiceProvider.setTunnelState(
1434                             dataProfile,
1435                             callback,
1436                             IwlanDataServiceProvider.TunnelState.TUNNEL_IN_BRINGUP,
1437                             null,
1438                             (reason == DataService.REQUEST_REASON_HANDOVER),
1439                             pduSessionId);
1440 
1441                     boolean result =
1442                             iwlanDataServiceProvider
1443                                     .getTunnelManager()
1444                                     .bringUpTunnel(
1445                                             tunnelReqBuilder.build(),
1446                                             iwlanDataServiceProvider.getIwlanTunnelCallback(),
1447                                             iwlanDataServiceProvider
1448                                                     .getIwlanTunnelCallbackMetrics());
1449                     Log.d(TAG, "bringup Tunnel with result:" + result);
1450                     if (!result) {
1451                         iwlanDataServiceProvider.deliverCallback(
1452                                 IwlanDataServiceProvider.CALLBACK_TYPE_SETUP_DATACALL_COMPLETE,
1453                                 DataServiceCallback.RESULT_ERROR_INVALID_ARG,
1454                                 callback,
1455                                 null);
1456                         return;
1457                     }
1458                     break;
1459 
1460                 case EVENT_DEACTIVATE_DATA_CALL:
1461                     DeactivateDataCallData deactivateDataCallData =
1462                             (DeactivateDataCallData) msg.obj;
1463                     int cid = deactivateDataCallData.mCid;
1464                     reason = deactivateDataCallData.mReason;
1465                     callback = deactivateDataCallData.mCallback;
1466                     iwlanDataServiceProvider = deactivateDataCallData.mIwlanDataServiceProvider;
1467 
1468                     for (String tunnelApnName :
1469                             iwlanDataServiceProvider.mTunnelStateForApn.keySet()) {
1470                         if (tunnelApnName.hashCode() == cid) {
1471                             /*
1472                             No need to check state since dataconnection in framework serializes
1473                             setup and deactivate calls using callId/cid.
1474                             */
1475                             iwlanDataServiceProvider
1476                                     .mTunnelStateForApn
1477                                     .get(tunnelApnName)
1478                                     .setState(
1479                                             IwlanDataServiceProvider.TunnelState
1480                                                     .TUNNEL_IN_BRINGDOWN);
1481                             iwlanDataServiceProvider
1482                                     .mTunnelStateForApn
1483                                     .get(tunnelApnName)
1484                                     .setDataServiceCallback(callback);
1485                             boolean isConnected =
1486                                     isNetworkConnected(
1487                                             IwlanHelper.isDefaultDataSlot(
1488                                                     mContext,
1489                                                     iwlanDataServiceProvider.getSlotIndex()),
1490                                             IwlanHelper.isCrossSimCallingEnabled(
1491                                                     mContext,
1492                                                     iwlanDataServiceProvider.getSlotIndex()));
1493                             iwlanDataServiceProvider
1494                                     .getTunnelManager()
1495                                     .closeTunnel(tunnelApnName, !isConnected);
1496                             return;
1497                         }
1498                     }
1499 
1500                     iwlanDataServiceProvider.deliverCallback(
1501                             IwlanDataServiceProvider.CALLBACK_TYPE_DEACTIVATE_DATACALL_COMPLETE,
1502                             DataServiceCallback.RESULT_ERROR_INVALID_ARG,
1503                             callback,
1504                             null);
1505                     break;
1506 
1507                 case EVENT_DATA_CALL_LIST_REQUEST:
1508                     DataCallRequestData dataCallRequestData = (DataCallRequestData) msg.obj;
1509                     callback = dataCallRequestData.mCallback;
1510                     iwlanDataServiceProvider = dataCallRequestData.mIwlanDataServiceProvider;
1511 
1512                     iwlanDataServiceProvider.deliverCallback(
1513                             IwlanDataServiceProvider.CALLBACK_TYPE_GET_DATACALL_LIST_COMPLETE,
1514                             DataServiceCallback.RESULT_SUCCESS,
1515                             callback,
1516                             null);
1517                     break;
1518 
1519                 case EVENT_FORCE_CLOSE_TUNNEL:
1520                     for (IwlanDataServiceProvider dp : sIwlanDataServiceProviders.values()) {
1521                         dp.forceCloseTunnels();
1522                     }
1523                     break;
1524 
1525                 case EVENT_ADD_DATA_SERVICE_PROVIDER:
1526                     iwlanDataServiceProvider = (IwlanDataServiceProvider) msg.obj;
1527                     addIwlanDataServiceProvider(iwlanDataServiceProvider);
1528                     break;
1529 
1530                 case EVENT_REMOVE_DATA_SERVICE_PROVIDER:
1531                     iwlanDataServiceProvider = (IwlanDataServiceProvider) msg.obj;
1532 
1533                     IwlanDataServiceProvider dsp =
1534                             sIwlanDataServiceProviders.remove(
1535                                     iwlanDataServiceProvider.getSlotIndex());
1536                     if (dsp == null) {
1537                         Log.w(
1538                                 TAG,
1539                                 "No DataServiceProvider exists for slot "
1540                                         + iwlanDataServiceProvider.getSlotIndex());
1541                     }
1542 
1543                     if (sIwlanDataServiceProviders.isEmpty()) {
1544                         deinitNetworkCallback();
1545                     }
1546                     break;
1547 
1548                 case EVENT_TUNNEL_OPENED_METRICS:
1549                     TunnelOpenedMetricsData tunnelOpenedMetricsData =
1550                             (TunnelOpenedMetricsData) msg.obj;
1551                     iwlanDataServiceProvider = tunnelOpenedMetricsData.mIwlanDataServiceProvider;
1552                     apnName = tunnelOpenedMetricsData.mApnName;
1553 
1554                     metricsAtom = iwlanDataServiceProvider.mMetricsAtomForApn.get(apnName);
1555                     metricsAtom.setEpdgServerAddress(tunnelOpenedMetricsData.mEpdgServerAddress);
1556                     metricsAtom.setProcessingDurationMillis(
1557                             tunnelOpenedMetricsData.mProcessingDuration);
1558                     metricsAtom.setEpdgServerSelectionDurationMillis(
1559                             tunnelOpenedMetricsData.mEpdgServerSelectionDuration);
1560                     metricsAtom.setIkeTunnelEstablishmentDurationMillis(
1561                             tunnelOpenedMetricsData.mIkeTunnelEstablishmentDuration);
1562 
1563                     metricsAtom.sendMetricsData();
1564                     break;
1565 
1566                 case EVENT_TUNNEL_CLOSED_METRICS:
1567                     TunnelClosedMetricsData tunnelClosedMetricsData =
1568                             (TunnelClosedMetricsData) msg.obj;
1569                     iwlanDataServiceProvider = tunnelClosedMetricsData.mIwlanDataServiceProvider;
1570                     apnName = tunnelClosedMetricsData.mApnName;
1571 
1572                     metricsAtom = iwlanDataServiceProvider.mMetricsAtomForApn.get(apnName);
1573                     metricsAtom.setEpdgServerAddress(tunnelClosedMetricsData.mEpdgServerAddress);
1574                     metricsAtom.setProcessingDurationMillis(
1575                             tunnelClosedMetricsData.mProcessingDuration);
1576                     metricsAtom.setEpdgServerSelectionDurationMillis(
1577                             tunnelClosedMetricsData.mEpdgServerSelectionDuration);
1578                     metricsAtom.setIkeTunnelEstablishmentDurationMillis(
1579                             tunnelClosedMetricsData.mIkeTunnelEstablishmentDuration);
1580 
1581                     metricsAtom.sendMetricsData();
1582                     iwlanDataServiceProvider.mMetricsAtomForApn.remove(apnName);
1583                     break;
1584 
1585                 default:
1586                     throw new IllegalStateException("Unexpected value: " + msg.what);
1587             }
1588         }
1589 
IwlanDataServiceHandler(Looper looper)1590         IwlanDataServiceHandler(Looper looper) {
1591             super(looper);
1592         }
1593     }
1594 
1595     private static final class TunnelOpenedData {
1596         final String mApnName;
1597         final TunnelLinkProperties mTunnelLinkProperties;
1598         final IwlanDataServiceProvider mIwlanDataServiceProvider;
1599 
TunnelOpenedData( String apnName, TunnelLinkProperties tunnelLinkProperties, IwlanDataServiceProvider dsp)1600         private TunnelOpenedData(
1601                 String apnName,
1602                 TunnelLinkProperties tunnelLinkProperties,
1603                 IwlanDataServiceProvider dsp) {
1604             mApnName = apnName;
1605             mTunnelLinkProperties = tunnelLinkProperties;
1606             mIwlanDataServiceProvider = dsp;
1607         }
1608     }
1609 
1610     private static final class TunnelClosedData {
1611         final String mApnName;
1612         final IwlanError mIwlanError;
1613         final IwlanDataServiceProvider mIwlanDataServiceProvider;
1614 
TunnelClosedData( String apnName, IwlanError iwlanError, IwlanDataServiceProvider dsp)1615         private TunnelClosedData(
1616                 String apnName, IwlanError iwlanError, IwlanDataServiceProvider dsp) {
1617             mApnName = apnName;
1618             mIwlanError = iwlanError;
1619             mIwlanDataServiceProvider = dsp;
1620         }
1621     }
1622 
1623     private static final class TunnelOpenedMetricsData {
1624         final String mApnName;
1625         final IwlanDataServiceProvider mIwlanDataServiceProvider;
1626         final String mEpdgServerAddress;
1627         final int mProcessingDuration;
1628         final int mEpdgServerSelectionDuration;
1629         final int mIkeTunnelEstablishmentDuration;
1630 
TunnelOpenedMetricsData( String apnName, String epdgServerAddress, long processingDuration, int epdgServerSelectionDuration, int ikeTunnelEstablishmentDuration, IwlanDataServiceProvider dsp)1631         private TunnelOpenedMetricsData(
1632                 String apnName,
1633                 String epdgServerAddress,
1634                 long processingDuration,
1635                 int epdgServerSelectionDuration,
1636                 int ikeTunnelEstablishmentDuration,
1637                 IwlanDataServiceProvider dsp) {
1638             mApnName = apnName;
1639             mIwlanDataServiceProvider = dsp;
1640             mEpdgServerAddress = epdgServerAddress;
1641             mProcessingDuration = (int) processingDuration;
1642             mEpdgServerSelectionDuration = epdgServerSelectionDuration;
1643             mIkeTunnelEstablishmentDuration = ikeTunnelEstablishmentDuration;
1644         }
1645     }
1646 
1647     private static final class TunnelClosedMetricsData {
1648         final String mApnName;
1649         final IwlanDataServiceProvider mIwlanDataServiceProvider;
1650         final String mEpdgServerAddress;
1651         final int mProcessingDuration;
1652         final int mEpdgServerSelectionDuration;
1653         final int mIkeTunnelEstablishmentDuration;
1654 
TunnelClosedMetricsData( String apnName, String epdgServerAddress, long processingDuration, int epdgServerSelectionDuration, int ikeTunnelEstablishmentDuration, IwlanDataServiceProvider dsp)1655         private TunnelClosedMetricsData(
1656                 String apnName,
1657                 String epdgServerAddress,
1658                 long processingDuration,
1659                 int epdgServerSelectionDuration,
1660                 int ikeTunnelEstablishmentDuration,
1661                 IwlanDataServiceProvider dsp) {
1662             mApnName = apnName;
1663             mIwlanDataServiceProvider = dsp;
1664             mEpdgServerAddress = epdgServerAddress;
1665             mProcessingDuration = (int) processingDuration;
1666             mEpdgServerSelectionDuration = epdgServerSelectionDuration;
1667             mIkeTunnelEstablishmentDuration = ikeTunnelEstablishmentDuration;
1668         }
1669     }
1670 
1671     private static final class SetupDataCallData {
1672         final int mAccessNetworkType;
1673         @NonNull final DataProfile mDataProfile;
1674         final boolean mIsRoaming;
1675         final boolean mAllowRoaming;
1676         final int mReason;
1677         @Nullable final LinkProperties mLinkProperties;
1678 
1679         @IntRange(from = 0, to = 15)
1680         final int mPduSessionId;
1681 
1682         @Nullable final NetworkSliceInfo mSliceInfo;
1683         @Nullable final TrafficDescriptor mTrafficDescriptor;
1684         final boolean mMatchAllRuleAllowed;
1685         @NonNull final DataServiceCallback mCallback;
1686         final IwlanDataServiceProvider mIwlanDataServiceProvider;
1687 
SetupDataCallData( int accessNetworkType, DataProfile dataProfile, boolean isRoaming, boolean allowRoaming, int reason, LinkProperties linkProperties, int pduSessionId, NetworkSliceInfo sliceInfo, TrafficDescriptor trafficDescriptor, boolean matchAllRuleAllowed, DataServiceCallback callback, IwlanDataServiceProvider dsp)1688         private SetupDataCallData(
1689                 int accessNetworkType,
1690                 DataProfile dataProfile,
1691                 boolean isRoaming,
1692                 boolean allowRoaming,
1693                 int reason,
1694                 LinkProperties linkProperties,
1695                 int pduSessionId,
1696                 NetworkSliceInfo sliceInfo,
1697                 TrafficDescriptor trafficDescriptor,
1698                 boolean matchAllRuleAllowed,
1699                 DataServiceCallback callback,
1700                 IwlanDataServiceProvider dsp) {
1701             mAccessNetworkType = accessNetworkType;
1702             mDataProfile = dataProfile;
1703             mIsRoaming = isRoaming;
1704             mAllowRoaming = allowRoaming;
1705             mReason = reason;
1706             mLinkProperties = linkProperties;
1707             mPduSessionId = pduSessionId;
1708             mSliceInfo = sliceInfo;
1709             mTrafficDescriptor = trafficDescriptor;
1710             mMatchAllRuleAllowed = matchAllRuleAllowed;
1711             mCallback = callback;
1712             mIwlanDataServiceProvider = dsp;
1713         }
1714     }
1715 
1716     private static final class DeactivateDataCallData {
1717         final int mCid;
1718         final int mReason;
1719         final DataServiceCallback mCallback;
1720         final IwlanDataServiceProvider mIwlanDataServiceProvider;
1721 
DeactivateDataCallData( int cid, int reason, DataServiceCallback callback, IwlanDataServiceProvider dsp)1722         private DeactivateDataCallData(
1723                 int cid, int reason, DataServiceCallback callback, IwlanDataServiceProvider dsp) {
1724             mCid = cid;
1725             mReason = reason;
1726             mCallback = callback;
1727             mIwlanDataServiceProvider = dsp;
1728         }
1729     }
1730 
1731     private static final class DataCallRequestData {
1732         final DataServiceCallback mCallback;
1733         final IwlanDataServiceProvider mIwlanDataServiceProvider;
1734 
DataCallRequestData(DataServiceCallback callback, IwlanDataServiceProvider dsp)1735         private DataCallRequestData(DataServiceCallback callback, IwlanDataServiceProvider dsp) {
1736             mCallback = callback;
1737             mIwlanDataServiceProvider = dsp;
1738         }
1739     }
1740 
1741     @VisibleForTesting
isNetworkConnected(boolean isDds, boolean isCstEnabled)1742     static boolean isNetworkConnected(boolean isDds, boolean isCstEnabled) {
1743         if (!isDds && isCstEnabled) {
1744             // Only Non-DDS sub with CST enabled, can use any transport.
1745             return sNetworkConnected;
1746         } else {
1747             // For all other cases, only wifi transport can be used.
1748             return ((sDefaultDataTransport == Transport.WIFI) && sNetworkConnected);
1749         }
1750     }
1751 
1752     @VisibleForTesting
1753     /* Note: this api should have valid transport if networkConnected==true */
setNetworkConnected( boolean networkConnected, Network network, Transport transport)1754     static void setNetworkConnected(
1755             boolean networkConnected, Network network, Transport transport) {
1756 
1757         boolean hasNetworkChanged = false;
1758         boolean hasTransportChanged = false;
1759         boolean hasNetworkConnectedChanged = false;
1760 
1761         if (sNetworkConnected == networkConnected
1762                 && network.equals(sNetwork)
1763                 && sDefaultDataTransport == transport) {
1764             // Nothing changed
1765             return;
1766         }
1767 
1768         // safety check
1769         if (networkConnected && transport == Transport.UNSPECIFIED_NETWORK) {
1770             Log.e(TAG, "setNetworkConnected: Network connected but transport unspecified");
1771             return;
1772         }
1773 
1774         if (!network.equals(sNetwork)) {
1775             Log.e(TAG, "setNetworkConnected NW changed from: " + sNetwork + " TO: " + network);
1776             hasNetworkChanged = true;
1777         }
1778 
1779         if (transport != sDefaultDataTransport) {
1780             Log.d(
1781                     TAG,
1782                     "Transport was changed from "
1783                             + sDefaultDataTransport.name()
1784                             + " to "
1785                             + transport.name());
1786             hasTransportChanged = true;
1787         }
1788 
1789         if (sNetworkConnected != networkConnected) {
1790             Log.d(
1791                     TAG,
1792                     "Network connected state change from "
1793                             + sNetworkConnected
1794                             + " to "
1795                             + networkConnected);
1796             hasNetworkConnectedChanged = true;
1797         }
1798 
1799         sNetworkConnected = networkConnected;
1800         sDefaultDataTransport = transport;
1801         sNetwork = network;
1802         if (!networkConnected) {
1803             // reset link protocol type
1804             sLinkProtocolType = LinkProtocolType.UNKNOWN;
1805         }
1806 
1807         if (networkConnected) {
1808             if (hasTransportChanged) {
1809                 // Perform forceClose for tunnels in bringdown.
1810                 // let framework handle explicit teardown
1811                 for (IwlanDataServiceProvider dp : sIwlanDataServiceProviders.values()) {
1812                     dp.forceCloseTunnelsInDeactivatingState();
1813                 }
1814             }
1815 
1816             if (transport == Transport.WIFI && hasNetworkConnectedChanged) {
1817                 IwlanEventListener.onWifiConnected(mContext);
1818             }
1819             // only prefetch dns and updateNetwork if Network has changed
1820             if (hasNetworkChanged) {
1821                 for (IwlanDataServiceProvider dp : sIwlanDataServiceProviders.values()) {
1822                     dp.dnsPrefetchCheck();
1823                     dp.updateNetwork(sNetwork);
1824                 }
1825                 IwlanHelper.updateCountryCodeWhenNetworkConnected();
1826             }
1827         } else {
1828             for (IwlanDataServiceProvider dp : sIwlanDataServiceProviders.values()) {
1829                 // once network is disconnected, even NAT KA offload fails
1830                 // But we should still let framework do an explicit teardown
1831                 // so as to not affect an ongoing handover
1832                 // only force close tunnels in bring down state
1833                 dp.forceCloseTunnelsInDeactivatingState();
1834             }
1835         }
1836     }
1837 
isLinkProtocolTypeChanged(LinkProperties linkProperties)1838     static boolean isLinkProtocolTypeChanged(LinkProperties linkProperties) {
1839         boolean hasIPV4 = false;
1840         boolean hasIPV6 = false;
1841 
1842         LinkProtocolType linkProtocolType = null;
1843         if (linkProperties != null) {
1844             for (LinkAddress linkAddress : linkProperties.getLinkAddresses()) {
1845                 InetAddress inetaddr = linkAddress.getAddress();
1846                 // skip linklocal and loopback addresses
1847                 if (!inetaddr.isLoopbackAddress() && !inetaddr.isLinkLocalAddress()) {
1848                     if (inetaddr instanceof Inet4Address) {
1849                         hasIPV4 = true;
1850                     } else if (inetaddr instanceof Inet6Address) {
1851                         hasIPV6 = true;
1852                     }
1853                 }
1854             }
1855 
1856             if (hasIPV4 && hasIPV6) {
1857                 linkProtocolType = LinkProtocolType.IPV4V6;
1858             } else if (hasIPV4) {
1859                 linkProtocolType = LinkProtocolType.IPV4;
1860             } else if (hasIPV6) {
1861                 linkProtocolType = LinkProtocolType.IPV6;
1862             }
1863 
1864             if (sLinkProtocolType != linkProtocolType) {
1865                 Log.d(
1866                         TAG,
1867                         "LinkProtocolType was changed from "
1868                                 + sLinkProtocolType
1869                                 + " to "
1870                                 + linkProtocolType);
1871                 sLinkProtocolType = linkProtocolType;
1872                 return true;
1873             }
1874             return false;
1875         }
1876         Log.w(TAG, "linkProperties is NULL.");
1877         return false;
1878     }
1879 
1880     /**
1881      * Get the DataServiceProvider associated with the slotId
1882      *
1883      * @param slotId slot index
1884      * @return DataService.DataServiceProvider associated with the slot
1885      */
getDataServiceProvider(int slotId)1886     public static DataService.DataServiceProvider getDataServiceProvider(int slotId) {
1887         return sIwlanDataServiceProviders.get(slotId);
1888     }
1889 
getContext()1890     public static Context getContext() {
1891         return mContext;
1892     }
1893 
1894     @Override
onCreateDataServiceProvider(int slotIndex)1895     public DataServiceProvider onCreateDataServiceProvider(int slotIndex) {
1896         // TODO: validity check on slot index
1897         Log.d(TAG, "Creating provider for " + slotIndex);
1898 
1899         if (mIwlanDataServiceHandler == null) {
1900             initHandler();
1901         }
1902 
1903         if (mNetworkMonitorCallback == null) {
1904             // start monitoring network and register for default network callback
1905             ConnectivityManager connectivityManager =
1906                     mContext.getSystemService(ConnectivityManager.class);
1907             mNetworkMonitorCallback = new IwlanNetworkMonitorCallback();
1908             connectivityManager.registerSystemDefaultNetworkCallback(
1909                     mNetworkMonitorCallback, mIwlanDataServiceHandler);
1910             Log.d(TAG, "Registered with Connectivity Service");
1911         }
1912 
1913         IwlanDataServiceProvider dp = new IwlanDataServiceProvider(slotIndex, this);
1914 
1915         mIwlanDataServiceHandler.sendMessage(
1916                 mIwlanDataServiceHandler.obtainMessage(EVENT_ADD_DATA_SERVICE_PROVIDER, dp));
1917         return dp;
1918     }
1919 
removeDataServiceProvider(IwlanDataServiceProvider dp)1920     public void removeDataServiceProvider(IwlanDataServiceProvider dp) {
1921         mIwlanDataServiceHandler.sendMessage(
1922                 mIwlanDataServiceHandler.obtainMessage(EVENT_REMOVE_DATA_SERVICE_PROVIDER, dp));
1923     }
1924 
1925     @VisibleForTesting
addIwlanDataServiceProvider(IwlanDataServiceProvider dp)1926     void addIwlanDataServiceProvider(IwlanDataServiceProvider dp) {
1927         int slotIndex = dp.getSlotIndex();
1928         if (sIwlanDataServiceProviders.containsKey(slotIndex)) {
1929             throw new IllegalStateException(
1930                     "DataServiceProvider already exists for slot " + slotIndex);
1931         }
1932         sIwlanDataServiceProviders.put(slotIndex, dp);
1933     }
1934 
deinitNetworkCallback()1935     void deinitNetworkCallback() {
1936         // deinit network related stuff
1937         ConnectivityManager connectivityManager =
1938                 mContext.getSystemService(ConnectivityManager.class);
1939         connectivityManager.unregisterNetworkCallback(mNetworkMonitorCallback);
1940         mNetworkMonitorCallback = null;
1941     }
1942 
1943     @VisibleForTesting
setAppContext(Context appContext)1944     void setAppContext(Context appContext) {
1945         mContext = appContext;
1946     }
1947 
1948     @VisibleForTesting
getNetworkMonitorCallback()1949     IwlanNetworkMonitorCallback getNetworkMonitorCallback() {
1950         return mNetworkMonitorCallback;
1951     }
1952 
1953     @VisibleForTesting
initHandler()1954     void initHandler() {
1955         mIwlanDataServiceHandler = new IwlanDataServiceHandler(getLooper());
1956     }
1957 
1958     @VisibleForTesting
getLooper()1959     Looper getLooper() {
1960         mIwlanDataServiceHandlerThread = new HandlerThread("IwlanDataServiceThread");
1961         mIwlanDataServiceHandlerThread.start();
1962         return mIwlanDataServiceHandlerThread.getLooper();
1963     }
1964 
eventToString(int event)1965     private static String eventToString(int event) {
1966         switch (event) {
1967             case EVENT_TUNNEL_OPENED:
1968                 return "EVENT_TUNNEL_OPENED";
1969             case EVENT_TUNNEL_CLOSED:
1970                 return "EVENT_TUNNEL_CLOSED";
1971             case EVENT_SETUP_DATA_CALL:
1972                 return "EVENT_SETUP_DATA_CALL";
1973             case EVENT_DEACTIVATE_DATA_CALL:
1974                 return "EVENT_DEACTIVATE_DATA_CALL";
1975             case EVENT_DATA_CALL_LIST_REQUEST:
1976                 return "EVENT_DATA_CALL_LIST_REQUEST";
1977             case EVENT_FORCE_CLOSE_TUNNEL:
1978                 return "EVENT_FORCE_CLOSE_TUNNEL";
1979             case EVENT_ADD_DATA_SERVICE_PROVIDER:
1980                 return "EVENT_ADD_DATA_SERVICE_PROVIDER";
1981             case EVENT_REMOVE_DATA_SERVICE_PROVIDER:
1982                 return "EVENT_REMOVE_DATA_SERVICE_PROVIDER";
1983             case IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT:
1984                 return "CARRIER_CONFIG_CHANGED_EVENT";
1985             case IwlanEventListener.CARRIER_CONFIG_UNKNOWN_CARRIER_EVENT:
1986                 return "CARRIER_CONFIG_UNKNOWN_CARRIER_EVENT";
1987             case IwlanEventListener.WIFI_CALLING_ENABLE_EVENT:
1988                 return "WIFI_CALLING_ENABLE_EVENT";
1989             case IwlanEventListener.WIFI_CALLING_DISABLE_EVENT:
1990                 return "WIFI_CALLING_DISABLE_EVENT";
1991             case IwlanEventListener.CELLINFO_CHANGED_EVENT:
1992                 return "CELLINFO_CHANGED_EVENT";
1993             case EVENT_TUNNEL_OPENED_METRICS:
1994                 return "EVENT_TUNNEL_OPENED_METRICS";
1995             case EVENT_TUNNEL_CLOSED_METRICS:
1996                 return "EVENT_TUNNEL_CLOSED_METRICS";
1997             default:
1998                 return "Unknown(" + event + ")";
1999         }
2000     }
2001 
2002     @Override
onCreate()2003     public void onCreate() {
2004         setAppContext(getApplicationContext());
2005         IwlanBroadcastReceiver.startListening(mContext);
2006         IwlanHelper.startCountryDetector(mContext);
2007     }
2008 
2009     @Override
onDestroy()2010     public void onDestroy() {
2011         IwlanBroadcastReceiver.stopListening(mContext);
2012     }
2013 
2014     @Override
onBind(Intent intent)2015     public IBinder onBind(Intent intent) {
2016         Log.d(TAG, "Iwlanservice onBind");
2017         return super.onBind(intent);
2018     }
2019 
2020     @Override
onUnbind(Intent intent)2021     public boolean onUnbind(Intent intent) {
2022         Log.d(TAG, "IwlanService onUnbind");
2023         mIwlanDataServiceHandler.sendMessage(
2024                 mIwlanDataServiceHandler.obtainMessage(EVENT_FORCE_CLOSE_TUNNEL));
2025         return super.onUnbind(intent);
2026     }
2027 
2028     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)2029     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2030         String transport = "UNSPECIFIED";
2031         if (sDefaultDataTransport == Transport.MOBILE) {
2032             transport = "CELLULAR";
2033         } else if (sDefaultDataTransport == Transport.WIFI) {
2034             transport = "WIFI";
2035         }
2036         pw.println("Default transport: " + transport);
2037         for (IwlanDataServiceProvider provider : sIwlanDataServiceProviders.values()) {
2038             pw.println();
2039             provider.dump(fd, pw, args);
2040             pw.println();
2041             pw.println();
2042         }
2043     }
2044 }
2045