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