/*
 * Copyright 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.android.iwlan;

import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;

import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.telephony.AccessNetworkConstants.AccessNetworkType;
import android.telephony.CarrierConfigManager;
import android.telephony.CellInfo;
import android.telephony.DataFailCause;
import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
import android.telephony.data.DataCallResponse;
import android.telephony.data.DataProfile;
import android.telephony.data.DataService;
import android.telephony.data.DataServiceCallback;
import android.telephony.data.NetworkSliceInfo;
import android.telephony.data.TrafficDescriptor;
import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;

import com.google.android.iwlan.epdg.EpdgSelector;
import com.google.android.iwlan.epdg.EpdgTunnelManager;
import com.google.android.iwlan.epdg.TunnelLinkProperties;
import com.google.android.iwlan.epdg.TunnelSetupRequest;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.LongSummaryStatistics;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class IwlanDataService extends DataService {

    private static final String TAG = IwlanDataService.class.getSimpleName();
    private static Context mContext;
    private IwlanNetworkMonitorCallback mNetworkMonitorCallback;
    private static boolean sNetworkConnected = false;
    private static Network sNetwork = null;
    @VisibleForTesting Handler mIwlanDataServiceHandler;
    private HandlerThread mIwlanDataServiceHandlerThread;
    private static final Map<Integer, IwlanDataServiceProvider> sIwlanDataServiceProviders =
            new ConcurrentHashMap<>();

    private static final int EVENT_BASE = IwlanEventListener.DATA_SERVICE_INTERNAL_EVENT_BASE;
    private static final int EVENT_TUNNEL_OPENED = EVENT_BASE;
    private static final int EVENT_TUNNEL_CLOSED = EVENT_BASE + 1;
    private static final int EVENT_SETUP_DATA_CALL = EVENT_BASE + 2;
    private static final int EVENT_DEACTIVATE_DATA_CALL = EVENT_BASE + 3;
    private static final int EVENT_DATA_CALL_LIST_REQUEST = EVENT_BASE + 4;
    private static final int EVENT_FORCE_CLOSE_TUNNEL = EVENT_BASE + 5;
    private static final int EVENT_ADD_DATA_SERVICE_PROVIDER = EVENT_BASE + 6;
    private static final int EVENT_REMOVE_DATA_SERVICE_PROVIDER = EVENT_BASE + 7;

    @VisibleForTesting
    enum Transport {
        UNSPECIFIED_NETWORK,
        MOBILE,
        WIFI;
    }

    private static Transport sDefaultDataTransport = Transport.UNSPECIFIED_NETWORK;

    enum LinkProtocolType {
        UNKNOWN,
        IPV4,
        IPV6,
        IPV4V6;
    }

    private static LinkProtocolType sLinkProtocolType = LinkProtocolType.UNKNOWN;

    // TODO: see if network monitor callback impl can be shared between dataservice and
    // networkservice
    // This callback runs in the same thread as IwlanDataServiceHandler
    static class IwlanNetworkMonitorCallback extends ConnectivityManager.NetworkCallback {

        /** Called when the framework connects and has declared a new network ready for use. */
        @Override
        public void onAvailable(Network network) {
            Log.d(TAG, "onAvailable: " + network);
        }

        /**
         * Called when the network is about to be lost, typically because there are no outstanding
         * requests left for it. This may be paired with a {@link NetworkCallback#onAvailable} call
         * with the new replacement network for graceful handover. This method is not guaranteed to
         * be called before {@link NetworkCallback#onLost} is called, for example in case a network
         * is suddenly disconnected.
         */
        @Override
        public void onLosing(Network network, int maxMsToLive) {
            Log.d(TAG, "onLosing: maxMsToLive: " + maxMsToLive + " network: " + network);
        }

        /**
         * Called when a network disconnects or otherwise no longer satisfies this request or
         * callback.
         */
        @Override
        public void onLost(Network network) {
            Log.d(TAG, "onLost: " + network);
            IwlanDataService.setNetworkConnected(false, network, Transport.UNSPECIFIED_NETWORK);
        }

        /** Called when the network corresponding to this request changes {@link LinkProperties}. */
        @Override
        public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) {
            Log.d(TAG, "onLinkPropertiesChanged: " + linkProperties);
            if (isLinkProtocolTypeChanged(linkProperties)) {
                for (IwlanDataServiceProvider dp : sIwlanDataServiceProviders.values()) {
                    dp.dnsPrefetchCheck();
                }
            }
        }

        /** Called when access to the specified network is blocked or unblocked. */
        @Override
        public void onBlockedStatusChanged(Network network, boolean blocked) {
            // TODO: check if we need to handle this
            Log.d(TAG, "onBlockedStatusChanged: " + network + " BLOCKED:" + blocked);
        }

        @Override
        public void onCapabilitiesChanged(
                Network network, NetworkCapabilities networkCapabilities) {
            // onCapabilitiesChanged is guaranteed to be called immediately after onAvailable per
            // API
            Log.d(TAG, "onCapabilitiesChanged: " + network + " " + networkCapabilities);
            if (networkCapabilities != null) {
                if (networkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
                    Log.d(TAG, "Network " + network + " connected using transport MOBILE");
                    IwlanDataService.setNetworkConnected(true, network, Transport.MOBILE);
                } else if (networkCapabilities.hasTransport(TRANSPORT_WIFI)) {
                    Log.d(TAG, "Network " + network + " connected using transport WIFI");
                    IwlanDataService.setNetworkConnected(true, network, Transport.WIFI);
                } else {
                    Log.w(TAG, "Network does not have cellular or wifi capability");
                }
            }
        }
    }

    @VisibleForTesting
    class IwlanDataServiceProvider extends DataService.DataServiceProvider {

        private static final int CALLBACK_TYPE_SETUP_DATACALL_COMPLETE = 1;
        private static final int CALLBACK_TYPE_DEACTIVATE_DATACALL_COMPLETE = 2;
        private static final int CALLBACK_TYPE_GET_DATACALL_LIST_COMPLETE = 3;
        private final String SUB_TAG;
        private final IwlanDataService mIwlanDataService;
        private final IwlanTunnelCallback mIwlanTunnelCallback;
        private boolean mWfcEnabled = false;
        private boolean mCarrierConfigReady = false;
        private EpdgSelector mEpdgSelector;
        private IwlanDataTunnelStats mTunnelStats;
        private CellInfo mCellInfo = null;

        // apn to TunnelState
        // Access should be serialized inside IwlanDataServiceHandler
        private Map<String, TunnelState> mTunnelStateForApn = new ConcurrentHashMap<>();

        // Holds the state of a tunnel (for an APN)
        @VisibleForTesting
        class TunnelState {

            // this should be ideally be based on path MTU discovery. 1280 is the minimum packet
            // size ipv6 routers have to handle so setting it to 1280 is the safest approach.
            // ideally it should be 1280 - tunnelling overhead ?
            private static final int LINK_MTU =
                    1280; // TODO: need to substract tunnelling overhead?
            static final int TUNNEL_DOWN = 1;
            static final int TUNNEL_IN_BRINGUP = 2;
            static final int TUNNEL_UP = 3;
            static final int TUNNEL_IN_BRINGDOWN = 4;
            static final int TUNNEL_IN_FORCE_CLEAN_WAS_IN_BRINGUP = 5;
            private DataServiceCallback dataServiceCallback;
            private int mState;
            private int mPduSessionId;
            private TunnelLinkProperties mTunnelLinkProperties;
            private boolean mIsHandover;
            private Date mBringUpStateTime = null;
            private Date mUpStateTime = null;

            public int getPduSessionId() {
                return mPduSessionId;
            }

            public void setPduSessionId(int mPduSessionId) {
                this.mPduSessionId = mPduSessionId;
            }

            public int getProtocolType() {
                return mProtocolType;
            }

            public int getLinkMtu() {
                return LINK_MTU; // TODO: need to substract tunnelling overhead
            }

            public void setProtocolType(int protocolType) {
                mProtocolType = protocolType;
            }

            private int mProtocolType; // from DataProfile

            public TunnelLinkProperties getTunnelLinkProperties() {
                return mTunnelLinkProperties;
            }

            public void setTunnelLinkProperties(TunnelLinkProperties tunnelLinkProperties) {
                mTunnelLinkProperties = tunnelLinkProperties;
            }

            public DataServiceCallback getDataServiceCallback() {
                return dataServiceCallback;
            }

            public void setDataServiceCallback(DataServiceCallback dataServiceCallback) {
                this.dataServiceCallback = dataServiceCallback;
            }

            public TunnelState(DataServiceCallback callback) {
                dataServiceCallback = callback;
                mState = TUNNEL_DOWN;
            }

            public int getState() {
                return mState;
            }

            /**
             * @param state (TunnelState.TUNNEL_DOWN|TUNNEL_UP|TUNNEL_DOWN)
             */
            public void setState(int state) {
                mState = state;
                if (mState == TunnelState.TUNNEL_IN_BRINGUP) {
                    mBringUpStateTime = Calendar.getInstance().getTime();
                }
                if (mState == TunnelState.TUNNEL_UP) {
                    mUpStateTime = Calendar.getInstance().getTime();
                }
            }

            public void setIsHandover(boolean isHandover) {
                mIsHandover = isHandover;
            }

            public boolean getIsHandover() {
                return mIsHandover;
            }

            public Date getBringUpStateTime() {
                return mBringUpStateTime;
            }

            public Date getUpStateTime() {
                return mUpStateTime;
            }

            @Override
            public String toString() {
                StringBuilder sb = new StringBuilder();
                String tunnelState = "UNKNOWN";
                switch (mState) {
                    case TUNNEL_DOWN:
                        tunnelState = "DOWN";
                        break;
                    case TUNNEL_IN_BRINGUP:
                        tunnelState = "IN BRINGUP";
                        break;
                    case TUNNEL_UP:
                        tunnelState = "UP";
                        break;
                    case TUNNEL_IN_BRINGDOWN:
                        tunnelState = "IN BRINGDOWN";
                        break;
                    case TUNNEL_IN_FORCE_CLEAN_WAS_IN_BRINGUP:
                        tunnelState = "IN FORCE CLEAN WAS IN BRINGUP";
                        break;
                }
                sb.append("\tCurrent State of this tunnel: " + mState + " " + tunnelState);
                sb.append("\n\tTunnel state is in Handover: " + mIsHandover);
                if (mBringUpStateTime != null) {
                    sb.append("\n\tTunnel bring up initiated at: " + mBringUpStateTime);
                } else {
                    sb.append("\n\tPotential leak. Null mBringUpStateTime");
                }
                if (mUpStateTime != null) {
                    sb.append("\n\tTunnel is up at: " + mUpStateTime);
                }
                if (mUpStateTime != null && mBringUpStateTime != null) {
                    long tunnelUpTime = mUpStateTime.getTime() - mBringUpStateTime.getTime();
                    sb.append("\n\tTime taken for the tunnel to come up in ms: " + tunnelUpTime);
                }
                return sb.toString();
            }
        }

        @VisibleForTesting
        class IwlanTunnelCallback implements EpdgTunnelManager.TunnelCallback {

            DataServiceProvider mDataServiceProvider;

            public IwlanTunnelCallback(DataServiceProvider dsp) {
                mDataServiceProvider = dsp;
            }

            // TODO: full implementation

            public void onOpened(String apnName, TunnelLinkProperties linkProperties) {
                Log.d(
                        SUB_TAG,
                        "Tunnel opened!. APN: " + apnName + "linkproperties: " + linkProperties);
                mIwlanDataServiceHandler.sendMessage(
                        mIwlanDataServiceHandler.obtainMessage(
                                EVENT_TUNNEL_OPENED,
                                new TunnelOpenedData(
                                        apnName, linkProperties, IwlanDataServiceProvider.this)));
            }

            public void onClosed(String apnName, IwlanError error) {
                Log.d(SUB_TAG, "Tunnel closed!. APN: " + apnName + " Error: " + error);
                // this is called, when a tunnel that is up, is closed.
                // the expectation is error==NO_ERROR for user initiated/normal close.
                mIwlanDataServiceHandler.sendMessage(
                        mIwlanDataServiceHandler.obtainMessage(
                                EVENT_TUNNEL_CLOSED,
                                new TunnelClosedData(
                                        apnName, error, IwlanDataServiceProvider.this)));
            }
        }

        /** Holds all tunnel related time and count statistics for this IwlanDataServiceProvider */
        @VisibleForTesting
        class IwlanDataTunnelStats {

            // represents the start time from when the following events are recorded
            private Date mStartTime;

            // Stats for TunnelSetup Success time (BRING_UP -> UP state)
            @VisibleForTesting
            Map<String, LongSummaryStatistics> mTunnelSetupSuccessStats =
                    new HashMap<String, LongSummaryStatistics>();
            // Count for Tunnel Setup failures onClosed when in BRING_UP
            @VisibleForTesting
            Map<String, Long> mTunnelSetupFailureCounts = new HashMap<String, Long>();

            // Count for unsol tunnel down onClosed when in UP without deactivate
            @VisibleForTesting
            Map<String, Long> mUnsolTunnelDownCounts = new HashMap<String, Long>();

            // Stats for how long the tunnel is in up state onClosed when in UP
            @VisibleForTesting
            Map<String, LongSummaryStatistics> mTunnelUpStats =
                    new HashMap<String, LongSummaryStatistics>();

            private long statCount;
            private final long COUNT_MAX = 1000;
            private final int APN_COUNT_MAX = 10;

            public IwlanDataTunnelStats() {
                mStartTime = Calendar.getInstance().getTime();
                statCount = 0L;
            }

            public void reportTunnelSetupSuccess(String apn, TunnelState tunnelState) {
                if (statCount > COUNT_MAX || maxApnReached()) {
                    reset();
                }
                statCount++;

                Date bringUpTime = tunnelState.getBringUpStateTime();
                Date upTime = tunnelState.getUpStateTime();

                if (bringUpTime != null && upTime != null) {
                    long tunnelUpTime = upTime.getTime() - bringUpTime.getTime();
                    if (!mTunnelSetupSuccessStats.containsKey(apn)) {
                        mTunnelSetupSuccessStats.put(apn, new LongSummaryStatistics());
                    }
                    LongSummaryStatistics stats = mTunnelSetupSuccessStats.get(apn);
                    stats.accept(tunnelUpTime);
                    mTunnelSetupSuccessStats.put(apn, stats);
                }
            }

            public void reportTunnelDown(String apn, TunnelState tunnelState) {
                if (statCount > COUNT_MAX || maxApnReached()) {
                    reset();
                }
                statCount++;

                // Setup fail
                if (tunnelState.getState() == TunnelState.TUNNEL_IN_BRINGUP) {
                    if (!mTunnelSetupFailureCounts.containsKey(apn)) {
                        mTunnelSetupFailureCounts.put(apn, 0L);
                    }
                    long count = mTunnelSetupFailureCounts.get(apn);
                    mTunnelSetupFailureCounts.put(apn, ++count);
                    return;
                }

                // Unsolicited tunnel down as tunnel has to be in BRINGDOWN if
                // there is a deactivate call associated with this.
                if (tunnelState.getState() == TunnelState.TUNNEL_UP) {
                    if (!mUnsolTunnelDownCounts.containsKey(apn)) {
                        mUnsolTunnelDownCounts.put(apn, 0L);
                    }
                    long count = mUnsolTunnelDownCounts.get(apn);
                    mUnsolTunnelDownCounts.put(apn, ++count);
                }
                Date currentTime = Calendar.getInstance().getTime();
                Date upTime = tunnelState.getUpStateTime();
                if (upTime != null) {
                    if (!mTunnelUpStats.containsKey(apn)) {
                        mTunnelUpStats.put(apn, new LongSummaryStatistics());
                    }
                    LongSummaryStatistics stats = mTunnelUpStats.get(apn);
                    stats.accept(currentTime.getTime() - upTime.getTime());
                    mTunnelUpStats.put(apn, stats);
                }
            }

            boolean maxApnReached() {
                if (mTunnelSetupSuccessStats.size() >= APN_COUNT_MAX
                        || mTunnelSetupFailureCounts.size() >= APN_COUNT_MAX
                        || mUnsolTunnelDownCounts.size() >= APN_COUNT_MAX
                        || mTunnelUpStats.size() >= APN_COUNT_MAX) {
                    return true;
                }
                return false;
            }

            @Override
            public String toString() {
                StringBuilder sb = new StringBuilder();
                sb.append("IwlanDataTunnelStats:");
                sb.append("\n\tmStartTime: " + mStartTime);
                sb.append("\n\ttunnelSetupSuccessStats:");
                for (Map.Entry<String, LongSummaryStatistics> entry :
                        mTunnelSetupSuccessStats.entrySet()) {
                    sb.append("\n\t  Apn: " + entry.getKey());
                    sb.append("\n\t  " + entry.getValue());
                }
                sb.append("\n\ttunnelUpStats:");
                for (Map.Entry<String, LongSummaryStatistics> entry : mTunnelUpStats.entrySet()) {
                    sb.append("\n\t  Apn: " + entry.getKey());
                    sb.append("\n\t  " + entry.getValue());
                }

                sb.append("\n\ttunnelSetupFailureCounts: ");
                for (Map.Entry<String, Long> entry : mTunnelSetupFailureCounts.entrySet()) {
                    sb.append("\n\t  Apn: " + entry.getKey());
                    sb.append("\n\t  counts: " + entry.getValue());
                }
                sb.append("\n\tunsolTunnelDownCounts: ");
                for (Map.Entry<String, Long> entry : mTunnelSetupFailureCounts.entrySet()) {
                    sb.append("\n\t  Apn: " + entry.getKey());
                    sb.append("\n\t  counts: " + entry.getValue());
                }
                sb.append("\n\tendTime: " + Calendar.getInstance().getTime());
                return sb.toString();
            }

            private void reset() {
                mStartTime = Calendar.getInstance().getTime();
                mTunnelSetupSuccessStats = new HashMap<String, LongSummaryStatistics>();
                mTunnelUpStats = new HashMap<String, LongSummaryStatistics>();
                mTunnelSetupFailureCounts = new HashMap<String, Long>();
                mUnsolTunnelDownCounts = new HashMap<String, Long>();
                statCount = 0L;
            }
        }

        /**
         * Constructor
         *
         * @param slotIndex SIM slot index the data service provider associated with.
         */
        public IwlanDataServiceProvider(int slotIndex, IwlanDataService iwlanDataService) {
            super(slotIndex);
            SUB_TAG = TAG + "[" + slotIndex + "]";

            // TODO:
            // get reference carrier config for this sub
            // get reference to resolver
            mIwlanDataService = iwlanDataService;
            mIwlanTunnelCallback = new IwlanTunnelCallback(this);
            mEpdgSelector = EpdgSelector.getSelectorInstance(mContext, slotIndex);
            mTunnelStats = new IwlanDataTunnelStats();

            // Register IwlanEventListener
            List<Integer> events = new ArrayList<Integer>();
            events.add(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT);
            events.add(IwlanEventListener.CARRIER_CONFIG_UNKNOWN_CARRIER_EVENT);
            events.add(IwlanEventListener.WIFI_CALLING_ENABLE_EVENT);
            events.add(IwlanEventListener.WIFI_CALLING_DISABLE_EVENT);
            events.add(IwlanEventListener.CELLINFO_CHANGED_EVENT);
            IwlanEventListener.getInstance(mContext, slotIndex)
                    .addEventListener(events, mIwlanDataServiceHandler);
        }

        @VisibleForTesting
        EpdgTunnelManager getTunnelManager() {
            return EpdgTunnelManager.getInstance(mContext, getSlotIndex());
        }

        // creates a DataCallResponse for an apn irrespective of state
        private DataCallResponse apnTunnelStateToDataCallResponse(String apn) {
            TunnelState tunnelState = mTunnelStateForApn.get(apn);
            if (tunnelState == null) {
                return null;
            }

            DataCallResponse.Builder responseBuilder = new DataCallResponse.Builder();
            responseBuilder
                    .setId(apn.hashCode())
                    .setProtocolType(tunnelState.getProtocolType())
                    .setCause(DataFailCause.NONE);

            if (tunnelState.getState() != TunnelState.TUNNEL_UP) {
                // no need to fill additional params
                return responseBuilder.setLinkStatus(DataCallResponse.LINK_STATUS_INACTIVE).build();
            }

            // fill wildcard address for gatewayList (used by DataConnection to add routes)
            List<InetAddress> gatewayList = new ArrayList<>();
            List<LinkAddress> linkAddrList =
                    tunnelState.getTunnelLinkProperties().internalAddresses();
            if (linkAddrList.stream().anyMatch(t -> t.isIpv4())) {
                try {
                    gatewayList.add(Inet4Address.getByName("0.0.0.0"));
                } catch (UnknownHostException e) {
                    // should never happen for static string 0.0.0.0
                }
            }
            if (linkAddrList.stream().anyMatch(t -> t.isIpv6())) {
                try {
                    gatewayList.add(Inet6Address.getByName("::"));
                } catch (UnknownHostException e) {
                    // should never happen for static string ::
                }
            }

            if (tunnelState.getTunnelLinkProperties().sliceInfo().isPresent()) {
                responseBuilder.setSliceInfo(
                        tunnelState.getTunnelLinkProperties().sliceInfo().get());
            }

            return responseBuilder
                    .setAddresses(linkAddrList)
                    .setDnsAddresses(tunnelState.getTunnelLinkProperties().dnsAddresses())
                    .setPcscfAddresses(tunnelState.getTunnelLinkProperties().pcscfAddresses())
                    .setInterfaceName(tunnelState.getTunnelLinkProperties().ifaceName())
                    .setGatewayAddresses(gatewayList)
                    .setLinkStatus(DataCallResponse.LINK_STATUS_ACTIVE)
                    .setMtu(tunnelState.getLinkMtu())
                    .setMtuV4(tunnelState.getLinkMtu())
                    .setMtuV6(tunnelState.getLinkMtu())
                    .setPduSessionId(tunnelState.getPduSessionId())
                    .build(); // underlying n/w is same
        }

        private List<DataCallResponse> getCallList() {
            List<DataCallResponse> dcList = new ArrayList<>();
            for (String key : mTunnelStateForApn.keySet()) {
                DataCallResponse dcRsp = apnTunnelStateToDataCallResponse(key);
                if (dcRsp != null) {
                    Log.d(SUB_TAG, "Apn: " + key + "Link state: " + dcRsp.getLinkStatus());
                    dcList.add(dcRsp);
                }
            }
            return dcList;
        }

        private void deliverCallback(
                int callbackType, int result, DataServiceCallback callback, DataCallResponse rsp) {
            if (callback == null) {
                Log.d(SUB_TAG, "deliverCallback: callback is null.  callbackType:" + callbackType);
                return;
            }
            Log.d(
                    SUB_TAG,
                    "Delivering callbackType:"
                            + callbackType
                            + " result:"
                            + result
                            + " rsp:"
                            + rsp);
            switch (callbackType) {
                case CALLBACK_TYPE_DEACTIVATE_DATACALL_COMPLETE:
                    callback.onDeactivateDataCallComplete(result);
                    // always update current datacalllist
                    notifyDataCallListChanged(getCallList());
                    break;

                case CALLBACK_TYPE_SETUP_DATACALL_COMPLETE:
                    if (result == DataServiceCallback.RESULT_SUCCESS && rsp == null) {
                        Log.d(SUB_TAG, "Warning: null rsp for success case");
                    }
                    callback.onSetupDataCallComplete(result, rsp);
                    // always update current datacalllist
                    notifyDataCallListChanged(getCallList());
                    break;

                case CALLBACK_TYPE_GET_DATACALL_LIST_COMPLETE:
                    callback.onRequestDataCallListComplete(result, getCallList());
                    // TODO: add code for the rest of the cases
            }
        }

        /**
         * Setup a data connection.
         *
         * @param accessNetworkType Access network type that the data call will be established on.
         *     Must be one of {@link android.telephony.AccessNetworkConstants.AccessNetworkType}.
         * @param dataProfile Data profile used for data call setup. See {@link DataProfile}
         * @param isRoaming True if the device is data roaming.
         * @param allowRoaming True if data roaming is allowed by the user.
         * @param reason The reason for data setup. Must be {@link #REQUEST_REASON_NORMAL} or {@link
         *     #REQUEST_REASON_HANDOVER}.
         * @param linkProperties If {@code reason} is {@link #REQUEST_REASON_HANDOVER}, this is the
         *     link properties of the existing data connection, otherwise null.
         * @param pduSessionId The pdu session id to be used for this data call. The standard range
         *     of values are 1-15 while 0 means no pdu session id was attached to this call.
         *     Reference: 3GPP TS 24.007 section 11.2.3.1b.
         * @param sliceInfo The slice info related to this data call.
         * @param trafficDescriptor TrafficDescriptor for which data connection needs to be
         *     established. It is used for URSP traffic matching as described in 3GPP TS 24.526
         *     Section 4.2.2. It includes an optional DNN which, if present, must be used for
         *     traffic matching; it does not specify the end point to be used for the data call.
         * @param matchAllRuleAllowed Indicates if using default match-all URSP rule for this
         *     request is allowed. If false, this request must not use the match-all URSP rule and
         *     if a non-match-all rule is not found (or if URSP rules are not available) then {@link
         *     DataCallResponse#getCause()} is {@link
         *     android.telephony.DataFailCause#MATCH_ALL_RULE_NOT_ALLOWED}. This is needed as some
         *     requests need to have a hard failure if the intention cannot be met, for example, a
         *     zero-rating slice.
         * @param callback The result callback for this request.
         */
        @Override
        public void 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) {

            Log.d(
                    SUB_TAG,
                    "Setup data call with network: "
                            + accessNetworkType
                            + ", DataProfile: "
                            + dataProfile
                            + ", isRoaming:"
                            + isRoaming
                            + ", allowRoaming: "
                            + allowRoaming
                            + ", reason: "
                            + reason
                            + ", linkProperties: "
                            + linkProperties
                            + ", pduSessionId: "
                            + pduSessionId);

            SetupDataCallData setupDataCallData =
                    new SetupDataCallData(
                            accessNetworkType,
                            dataProfile,
                            isRoaming,
                            allowRoaming,
                            reason,
                            linkProperties,
                            pduSessionId,
                            sliceInfo,
                            trafficDescriptor,
                            matchAllRuleAllowed,
                            callback,
                            this);

            mIwlanDataServiceHandler.sendMessage(
                    mIwlanDataServiceHandler.obtainMessage(
                            EVENT_SETUP_DATA_CALL, setupDataCallData));
        }

        /**
         * Deactivate a data connection. The data service provider must implement this method to
         * support data connection tear down. When completed or error, the service must invoke the
         * provided callback to notify the platform.
         *
         * @param cid Call id returned in the callback of {@link
         *     DataServiceProvider#setupDataCall(int, DataProfile, boolean, boolean, int,
         *     LinkProperties, DataServiceCallback)}.
         * @param reason The reason for data deactivation. Must be {@link #REQUEST_REASON_NORMAL},
         *     {@link #REQUEST_REASON_SHUTDOWN} or {@link #REQUEST_REASON_HANDOVER}.
         * @param callback The result callback for this request. Null if the client does not care
         */
        @Override
        public void deactivateDataCall(int cid, int reason, DataServiceCallback callback) {
            Log.d(
                    SUB_TAG,
                    "Deactivate data call "
                            + " reason: "
                            + reason
                            + " cid: "
                            + cid
                            + "callback: "
                            + callback);

            DeactivateDataCallData deactivateDataCallData =
                    new DeactivateDataCallData(cid, reason, callback, this);

            mIwlanDataServiceHandler.sendMessage(
                    mIwlanDataServiceHandler.obtainMessage(
                            EVENT_DEACTIVATE_DATA_CALL, deactivateDataCallData));
        }

        public void forceCloseTunnelsInDeactivatingState() {
            for (Map.Entry<String, TunnelState> entry : mTunnelStateForApn.entrySet()) {
                TunnelState tunnelState = entry.getValue();
                if (tunnelState.getState() == TunnelState.TUNNEL_IN_BRINGDOWN) {
                    getTunnelManager().closeTunnel(entry.getKey(), true);
                }
            }
        }

        void forceCloseTunnels() {
            for (Map.Entry<String, TunnelState> entry : mTunnelStateForApn.entrySet()) {
                getTunnelManager().closeTunnel(entry.getKey(), true);
            }
        }

        /**
         * Get the active data call list.
         *
         * @param callback The result callback for this request.
         */
        @Override
        public void requestDataCallList(DataServiceCallback callback) {
            mIwlanDataServiceHandler.sendMessage(
                    mIwlanDataServiceHandler.obtainMessage(
                            EVENT_DATA_CALL_LIST_REQUEST,
                            new DataCallRequestData(callback, IwlanDataServiceProvider.this)));
        }

        @VisibleForTesting
        void setTunnelState(
                DataProfile dataProfile,
                DataServiceCallback callback,
                int tunnelStatus,
                TunnelLinkProperties linkProperties,
                boolean isHandover,
                int pduSessionId) {
            TunnelState tunnelState = new TunnelState(callback);
            tunnelState.setState(tunnelStatus);
            tunnelState.setProtocolType(dataProfile.getProtocolType());
            tunnelState.setTunnelLinkProperties(linkProperties);
            tunnelState.setIsHandover(isHandover);
            tunnelState.setPduSessionId(pduSessionId);
            mTunnelStateForApn.put(dataProfile.getApn(), tunnelState);
        }

        @VisibleForTesting
        public IwlanTunnelCallback getIwlanTunnelCallback() {
            return mIwlanTunnelCallback;
        }

        @VisibleForTesting
        IwlanDataTunnelStats getTunnelStats() {
            return mTunnelStats;
        }

        private void updateNetwork(Network network) {
            if (network != null) {
                for (Map.Entry<String, TunnelState> entry : mTunnelStateForApn.entrySet()) {
                    TunnelState tunnelState = entry.getValue();
                    if (tunnelState.getState() == TunnelState.TUNNEL_IN_BRINGUP) {
                        // force close tunnels in bringup since IKE lib only supports
                        // updating network for tunnels that are already up.
                        // This may not result in actual closing of Ike Session since
                        // epdg selection may not be complete yet.
                        tunnelState.setState(TunnelState.TUNNEL_IN_FORCE_CLEAN_WAS_IN_BRINGUP);
                        getTunnelManager().closeTunnel(entry.getKey(), true);
                    } else {
                        if (mIwlanDataService.isNetworkConnected(
                                IwlanHelper.isDefaultDataSlot(mContext, getSlotIndex()),
                                IwlanHelper.isCrossSimCallingEnabled(mContext, getSlotIndex()))) {
                            getTunnelManager().updateNetwork(network, entry.getKey());
                        }
                    }
                }
            }
        }

        private boolean isRegisteredCellInfoChanged(List<CellInfo> cellInfoList) {
            for (CellInfo cellInfo : cellInfoList) {
                if (!cellInfo.isRegistered()) {
                    continue;
                }

                if (mCellInfo == null || mCellInfo != cellInfo) {
                    mCellInfo = cellInfo;
                    Log.d(TAG, " Update cached cellinfo");
                    return true;
                }
            }
            return false;
        }

        private void dnsPrefetchCheck() {
            boolean networkConnected =
                    mIwlanDataService.isNetworkConnected(
                            IwlanHelper.isDefaultDataSlot(mContext, getSlotIndex()),
                            IwlanHelper.isCrossSimCallingEnabled(mContext, getSlotIndex()));
            /* Check if we need to do prefecting */
            if (networkConnected == true
                    && mCarrierConfigReady == true
                    && mWfcEnabled == true
                    && mTunnelStateForApn.isEmpty()) {

                // Get roaming status
                TelephonyManager telephonyManager =
                        mContext.getSystemService(TelephonyManager.class);
                telephonyManager =
                        telephonyManager.createForSubscriptionId(
                                IwlanHelper.getSubId(mContext, getSlotIndex()));
                boolean isRoaming = telephonyManager.isNetworkRoaming();
                Log.d(TAG, "Trigger EPDG prefetch. Roaming=" + isRoaming);

                prefetchEpdgServerList(mIwlanDataService.sNetwork, isRoaming);
            }
        }

        private void prefetchEpdgServerList(Network network, boolean isRoaming) {
            mEpdgSelector.getValidatedServerList(
                    0, EpdgSelector.PROTO_FILTER_IPV4V6, isRoaming, false, network, null);
            mEpdgSelector.getValidatedServerList(
                    0, EpdgSelector.PROTO_FILTER_IPV4V6, isRoaming, true, network, null);
        }

        /**
         * Called when the instance of data service is destroyed (e.g. got unbind or binder died) or
         * when the data service provider is removed.
         */
        @Override
        public void close() {
            // TODO: call epdgtunnelmanager.releaseInstance or equivalent
            mIwlanDataService.removeDataServiceProvider(this);
            IwlanEventListener.getInstance(mContext, getSlotIndex())
                    .removeEventListener(mIwlanDataServiceHandler);
        }

        public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
            pw.println("---- IwlanDataServiceProvider[" + getSlotIndex() + "] ----");
            boolean isDDS = IwlanHelper.isDefaultDataSlot(mContext, getSlotIndex());
            boolean isCSTEnabled = IwlanHelper.isCrossSimCallingEnabled(mContext, getSlotIndex());
            pw.println("isDefaultDataSub: " + isDDS + " isCrossSimEnabled: " + isCSTEnabled);
            pw.println(
                    "isNetworkConnected: "
                            + isNetworkConnected(isDDS, isCSTEnabled)
                            + " Wfc enabled: "
                            + mWfcEnabled);
            for (Map.Entry<String, TunnelState> entry : mTunnelStateForApn.entrySet()) {
                pw.println("Tunnel state for APN: " + entry.getKey());
                pw.println(entry.getValue());
            }
            pw.println(mTunnelStats);
            EpdgTunnelManager.getInstance(mContext, getSlotIndex()).dump(fd, pw, args);
            ErrorPolicyManager.getInstance(mContext, getSlotIndex()).dump(fd, pw, args);
            pw.println("-------------------------------------");
        }
    }

    private final class IwlanDataServiceHandler extends Handler {
        private final String TAG = IwlanDataServiceHandler.class.getSimpleName();

        @Override
        public void handleMessage(Message msg) {
            Log.d(TAG, "msg.what = " + eventToString(msg.what));

            String apnName;
            IwlanDataServiceProvider iwlanDataServiceProvider;
            IwlanDataServiceProvider.TunnelState tunnelState;
            DataServiceCallback callback;
            int reason;

            switch (msg.what) {
                case EVENT_TUNNEL_OPENED:
                    TunnelOpenedData tunnelOpenedData = (TunnelOpenedData) msg.obj;
                    iwlanDataServiceProvider = tunnelOpenedData.mIwlanDataServiceProvider;
                    apnName = tunnelOpenedData.mApnName;
                    TunnelLinkProperties tunnelLinkProperties =
                            tunnelOpenedData.mTunnelLinkProperties;

                    tunnelState = iwlanDataServiceProvider.mTunnelStateForApn.get(apnName);
                    // tunnelstate should not be null, design violation.
                    // if its null, we should crash and debug.
                    tunnelState.setTunnelLinkProperties(tunnelLinkProperties);
                    tunnelState.setState(IwlanDataServiceProvider.TunnelState.TUNNEL_UP);
                    iwlanDataServiceProvider.mTunnelStats.reportTunnelSetupSuccess(
                            apnName, tunnelState);

                    iwlanDataServiceProvider.deliverCallback(
                            IwlanDataServiceProvider.CALLBACK_TYPE_SETUP_DATACALL_COMPLETE,
                            DataServiceCallback.RESULT_SUCCESS,
                            tunnelState.getDataServiceCallback(),
                            iwlanDataServiceProvider.apnTunnelStateToDataCallResponse(apnName));
                    break;

                case EVENT_TUNNEL_CLOSED:
                    TunnelClosedData tunnelClosedData = (TunnelClosedData) msg.obj;
                    iwlanDataServiceProvider = tunnelClosedData.mIwlanDataServiceProvider;
                    apnName = tunnelClosedData.mApnName;
                    IwlanError iwlanError = tunnelClosedData.mIwlanError;

                    tunnelState = iwlanDataServiceProvider.mTunnelStateForApn.get(apnName);
                    iwlanDataServiceProvider.mTunnelStats.reportTunnelDown(apnName, tunnelState);
                    iwlanDataServiceProvider.mTunnelStateForApn.remove(apnName);

                    if (tunnelState.getState()
                                    == IwlanDataServiceProvider.TunnelState.TUNNEL_IN_BRINGUP
                            || tunnelState.getState()
                                    == IwlanDataServiceProvider.TunnelState
                                            .TUNNEL_IN_FORCE_CLEAN_WAS_IN_BRINGUP) {
                        DataCallResponse.Builder respBuilder = new DataCallResponse.Builder();
                        respBuilder
                                .setId(apnName.hashCode())
                                .setProtocolType(tunnelState.getProtocolType());

                        if (tunnelState.getIsHandover()) {
                            respBuilder.setHandoverFailureMode(
                                    DataCallResponse
                                            .HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_HANDOVER);
                        } else {
                            respBuilder.setHandoverFailureMode(
                                    DataCallResponse
                                            .HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_SETUP_NORMAL);
                        }

                        if (tunnelState.getState()
                                == IwlanDataServiceProvider.TunnelState.TUNNEL_IN_BRINGUP) {
                            respBuilder.setCause(
                                    ErrorPolicyManager.getInstance(
                                                    mContext,
                                                    iwlanDataServiceProvider.getSlotIndex())
                                            .getDataFailCause(apnName));
                            respBuilder.setRetryDurationMillis(
                                    ErrorPolicyManager.getInstance(
                                                    mContext,
                                                    iwlanDataServiceProvider.getSlotIndex())
                                            .getCurrentRetryTimeMs(apnName));
                        } else if (tunnelState.getState()
                                == IwlanDataServiceProvider.TunnelState
                                        .TUNNEL_IN_FORCE_CLEAN_WAS_IN_BRINGUP) {
                            respBuilder.setCause(DataFailCause.IWLAN_NETWORK_FAILURE);
                            respBuilder.setRetryDurationMillis(5000);
                        }

                        iwlanDataServiceProvider.deliverCallback(
                                IwlanDataServiceProvider.CALLBACK_TYPE_SETUP_DATACALL_COMPLETE,
                                DataServiceCallback.RESULT_SUCCESS,
                                tunnelState.getDataServiceCallback(),
                                respBuilder.build());
                        return;
                    }

                    // iwlan service triggered teardown
                    if (tunnelState.getState()
                            == IwlanDataServiceProvider.TunnelState.TUNNEL_IN_BRINGDOWN) {

                        // IO exception happens when IKE library fails to retransmit requests.
                        // This can happen for multiple reasons:
                        // 1. Network disconnection due to wifi off.
                        // 2. Epdg server does not respond.
                        // 3. Socket send/receive fails.
                        // Ignore this during tunnel bring down.
                        if (iwlanError.getErrorType() != IwlanError.NO_ERROR
                                && iwlanError.getErrorType()
                                        != IwlanError.IKE_INTERNAL_IO_EXCEPTION) {
                            Log.e(TAG, "Unexpected error during tunnel bring down: " + iwlanError);
                        }

                        iwlanDataServiceProvider.deliverCallback(
                                IwlanDataServiceProvider.CALLBACK_TYPE_DEACTIVATE_DATACALL_COMPLETE,
                                DataServiceCallback.RESULT_SUCCESS,
                                tunnelState.getDataServiceCallback(),
                                null);

                        return;
                    }

                    // just update list of data calls. No way to send error up
                    iwlanDataServiceProvider.notifyDataCallListChanged(
                            iwlanDataServiceProvider.getCallList());
                    break;

                case IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT:
                    iwlanDataServiceProvider =
                            (IwlanDataServiceProvider) getDataServiceProvider(msg.arg1);

                    iwlanDataServiceProvider.mCarrierConfigReady = true;
                    iwlanDataServiceProvider.dnsPrefetchCheck();
                    break;

                case IwlanEventListener.CARRIER_CONFIG_UNKNOWN_CARRIER_EVENT:
                    iwlanDataServiceProvider =
                            (IwlanDataServiceProvider) getDataServiceProvider(msg.arg1);

                    iwlanDataServiceProvider.mCarrierConfigReady = false;
                    break;

                case IwlanEventListener.WIFI_CALLING_ENABLE_EVENT:
                    iwlanDataServiceProvider =
                            (IwlanDataServiceProvider) getDataServiceProvider(msg.arg1);

                    iwlanDataServiceProvider.mWfcEnabled = true;
                    iwlanDataServiceProvider.dnsPrefetchCheck();
                    break;

                case IwlanEventListener.WIFI_CALLING_DISABLE_EVENT:
                    iwlanDataServiceProvider =
                            (IwlanDataServiceProvider) getDataServiceProvider(msg.arg1);

                    iwlanDataServiceProvider.mWfcEnabled = false;
                    break;

                case IwlanEventListener.CELLINFO_CHANGED_EVENT:
                    List<CellInfo> cellInfolist = (List<CellInfo>) msg.obj;
                    iwlanDataServiceProvider =
                            (IwlanDataServiceProvider) getDataServiceProvider(msg.arg1);

                    if (cellInfolist != null
                            && iwlanDataServiceProvider.isRegisteredCellInfoChanged(cellInfolist)) {
                        int[] addrResolutionMethods =
                                IwlanHelper.getConfig(
                                        CarrierConfigManager.Iwlan
                                                .KEY_EPDG_ADDRESS_PRIORITY_INT_ARRAY,
                                        mContext,
                                        iwlanDataServiceProvider.getSlotIndex());
                        for (int addrResolutionMethod : addrResolutionMethods) {
                            if (addrResolutionMethod
                                    == CarrierConfigManager.Iwlan.EPDG_ADDRESS_CELLULAR_LOC) {
                                iwlanDataServiceProvider.dnsPrefetchCheck();
                            }
                        }
                    }
                    break;

                case EVENT_SETUP_DATA_CALL:
                    SetupDataCallData setupDataCallData = (SetupDataCallData) msg.obj;
                    int accessNetworkType = setupDataCallData.mAccessNetworkType;
                    @NonNull DataProfile dataProfile = setupDataCallData.mDataProfile;
                    boolean isRoaming = setupDataCallData.mIsRoaming;
                    reason = setupDataCallData.mReason;
                    LinkProperties linkProperties = setupDataCallData.mLinkProperties;
                    @IntRange(from = 0, to = 15)
                    int pduSessionId = setupDataCallData.mPduSessionId;
                    callback = setupDataCallData.mCallback;
                    iwlanDataServiceProvider = setupDataCallData.mIwlanDataServiceProvider;

                    if ((accessNetworkType != AccessNetworkType.IWLAN)
                            || (dataProfile == null)
                            || (linkProperties == null
                                    && reason == DataService.REQUEST_REASON_HANDOVER)) {

                        iwlanDataServiceProvider.deliverCallback(
                                IwlanDataServiceProvider.CALLBACK_TYPE_SETUP_DATACALL_COMPLETE,
                                DataServiceCallback.RESULT_ERROR_INVALID_ARG,
                                callback,
                                null);
                        return;
                    }

                    boolean isDDS =
                            IwlanHelper.isDefaultDataSlot(
                                    mContext, iwlanDataServiceProvider.getSlotIndex());
                    boolean isCSTEnabled =
                            IwlanHelper.isCrossSimCallingEnabled(
                                    mContext, iwlanDataServiceProvider.getSlotIndex());
                    boolean networkConnected = isNetworkConnected(isDDS, isCSTEnabled);
                    Log.d(
                            TAG,
                            "isDds: "
                                    + isDDS
                                    + ", isCstEnabled: "
                                    + isCSTEnabled
                                    + ", transport: "
                                    + sDefaultDataTransport);

                    if (networkConnected == false) {
                        iwlanDataServiceProvider.deliverCallback(
                                IwlanDataServiceProvider.CALLBACK_TYPE_SETUP_DATACALL_COMPLETE,
                                5 /* DataServiceCallback.RESULT_ERROR_TEMPORARILY_UNAVAILABLE
                                   */,
                                callback,
                                null);
                        return;
                    }

                    tunnelState =
                            iwlanDataServiceProvider.mTunnelStateForApn.get(dataProfile.getApn());

                    // Return the existing PDN if the pduSessionId is the same and the tunnel
                    // state is
                    // TUNNEL_UP.
                    if (tunnelState != null) {
                        if (tunnelState.getPduSessionId() == pduSessionId
                                && tunnelState.getState()
                                        == IwlanDataServiceProvider.TunnelState.TUNNEL_UP) {
                            Log.w(
                                    TAG,
                                    "The tunnel for " + dataProfile.getApn() + " already exists.");
                            iwlanDataServiceProvider.deliverCallback(
                                    IwlanDataServiceProvider.CALLBACK_TYPE_SETUP_DATACALL_COMPLETE,
                                    DataServiceCallback.RESULT_SUCCESS,
                                    callback,
                                    iwlanDataServiceProvider.apnTunnelStateToDataCallResponse(
                                            dataProfile.getApn()));
                            return;
                        } else {
                            Log.e(
                                    TAG,
                                    "Force close the existing PDN. pduSessionId = "
                                            + tunnelState.getPduSessionId()
                                            + " Tunnel State = "
                                            + tunnelState.getState());
                            iwlanDataServiceProvider
                                    .getTunnelManager()
                                    .closeTunnel(dataProfile.getApn(), true /* forceClose */);
                            iwlanDataServiceProvider.deliverCallback(
                                    IwlanDataServiceProvider.CALLBACK_TYPE_SETUP_DATACALL_COMPLETE,
                                    5 /* DataServiceCallback
                                      .RESULT_ERROR_TEMPORARILY_UNAVAILABLE */,
                                    callback,
                                    null);
                            return;
                        }
                    }

                    TunnelSetupRequest.Builder tunnelReqBuilder =
                            TunnelSetupRequest.builder()
                                    .setApnName(dataProfile.getApn())
                                    .setNetwork(sNetwork)
                                    .setIsRoaming(isRoaming)
                                    .setPduSessionId(pduSessionId)
                                    .setApnIpProtocol(
                                            isRoaming
                                                    ? dataProfile.getRoamingProtocolType()
                                                    : dataProfile.getProtocolType());

                    if (reason == DataService.REQUEST_REASON_HANDOVER) {
                        // for now assume that, at max,  only one address of eachtype (v4/v6).
                        // TODO: Check if multiple ips can be sent in ike tunnel setup
                        for (LinkAddress lAddr : linkProperties.getLinkAddresses()) {
                            if (lAddr.isIpv4()) {
                                tunnelReqBuilder.setSrcIpv4Address(lAddr.getAddress());
                            } else if (lAddr.isIpv6()) {
                                tunnelReqBuilder.setSrcIpv6Address(lAddr.getAddress());
                                tunnelReqBuilder.setSrcIpv6AddressPrefixLength(
                                        lAddr.getPrefixLength());
                            }
                        }
                    }

                    int apnTypeBitmask = dataProfile.getSupportedApnTypesBitmask();
                    boolean isIMS = (apnTypeBitmask & ApnSetting.TYPE_IMS) == ApnSetting.TYPE_IMS;
                    boolean isEmergency =
                            (apnTypeBitmask & ApnSetting.TYPE_EMERGENCY)
                                    == ApnSetting.TYPE_EMERGENCY;
                    tunnelReqBuilder.setRequestPcscf(isIMS || isEmergency);
                    tunnelReqBuilder.setIsEmergency(isEmergency);

                    iwlanDataServiceProvider.setTunnelState(
                            dataProfile,
                            callback,
                            IwlanDataServiceProvider.TunnelState.TUNNEL_IN_BRINGUP,
                            null,
                            (reason == DataService.REQUEST_REASON_HANDOVER),
                            pduSessionId);

                    boolean result =
                            iwlanDataServiceProvider
                                    .getTunnelManager()
                                    .bringUpTunnel(
                                            tunnelReqBuilder.build(),
                                            iwlanDataServiceProvider.getIwlanTunnelCallback());
                    Log.d(TAG, "bringup Tunnel with result:" + result);
                    if (!result) {
                        iwlanDataServiceProvider.deliverCallback(
                                IwlanDataServiceProvider.CALLBACK_TYPE_SETUP_DATACALL_COMPLETE,
                                DataServiceCallback.RESULT_ERROR_INVALID_ARG,
                                callback,
                                null);
                        return;
                    }
                    break;

                case EVENT_DEACTIVATE_DATA_CALL:
                    DeactivateDataCallData deactivateDataCallData =
                            (DeactivateDataCallData) msg.obj;
                    iwlanDataServiceProvider = deactivateDataCallData.mIwlanDataServiceProvider;
                    callback = deactivateDataCallData.mCallback;
                    reason = deactivateDataCallData.mReason;

                    int cid = deactivateDataCallData.mCid;
                    int slotIndex = iwlanDataServiceProvider.getSlotIndex();
                    boolean isNetworkLost =
                            !isNetworkConnected(
                                    IwlanHelper.isDefaultDataSlot(mContext, slotIndex),
                                    IwlanHelper.isCrossSimCallingEnabled(mContext, slotIndex));
                    boolean isHandOutSuccessful = (reason == REQUEST_REASON_HANDOVER);

                    for (String apn : iwlanDataServiceProvider.mTunnelStateForApn.keySet()) {
                        if (apn.hashCode() == cid) {
                            // No need to check state since dataconnection in framework serializes
                            // setup and deactivate calls using callId/cid.
                            iwlanDataServiceProvider
                                    .mTunnelStateForApn
                                    .get(apn)
                                    .setState(
                                            IwlanDataServiceProvider.TunnelState
                                                    .TUNNEL_IN_BRINGDOWN);
                            iwlanDataServiceProvider
                                    .mTunnelStateForApn
                                    .get(apn)
                                    .setDataServiceCallback(callback);

                            // According to the handover procedure in 3GPP specifications (TS 23.402
                            // clause 8.6.1 for S1; TS 23.502 clause 4.11.4.1 for N1), if the PDN is
                            // handed out to another RAT, the IKE tunnel over ePDG SHOULD be
                            // released by the network.  Thus, UE just released the tunnel locally.
                            iwlanDataServiceProvider
                                    .getTunnelManager()
                                    .closeTunnel(
                                            apn,
                                            isNetworkLost || isHandOutSuccessful /* forceClose */);
                            return;
                        }
                    }

                    iwlanDataServiceProvider.deliverCallback(
                            IwlanDataServiceProvider.CALLBACK_TYPE_DEACTIVATE_DATACALL_COMPLETE,
                            DataServiceCallback.RESULT_ERROR_INVALID_ARG,
                            callback,
                            null);
                    break;

                case EVENT_DATA_CALL_LIST_REQUEST:
                    DataCallRequestData dataCallRequestData = (DataCallRequestData) msg.obj;
                    callback = dataCallRequestData.mCallback;
                    iwlanDataServiceProvider = dataCallRequestData.mIwlanDataServiceProvider;

                    iwlanDataServiceProvider.deliverCallback(
                            IwlanDataServiceProvider.CALLBACK_TYPE_GET_DATACALL_LIST_COMPLETE,
                            DataServiceCallback.RESULT_SUCCESS,
                            callback,
                            null);
                    break;

                case EVENT_FORCE_CLOSE_TUNNEL:
                    for (IwlanDataServiceProvider dp : sIwlanDataServiceProviders.values()) {
                        dp.forceCloseTunnels();
                    }
                    break;

                case EVENT_ADD_DATA_SERVICE_PROVIDER:
                    iwlanDataServiceProvider = (IwlanDataServiceProvider) msg.obj;
                    addIwlanDataServiceProvider(iwlanDataServiceProvider);
                    break;

                case EVENT_REMOVE_DATA_SERVICE_PROVIDER:
                    iwlanDataServiceProvider = (IwlanDataServiceProvider) msg.obj;

                    IwlanDataServiceProvider dsp =
                            sIwlanDataServiceProviders.remove(
                                    iwlanDataServiceProvider.getSlotIndex());
                    if (dsp == null) {
                        Log.w(
                                TAG,
                                "No DataServiceProvider exists for slot "
                                        + iwlanDataServiceProvider.getSlotIndex());
                    }

                    if (sIwlanDataServiceProviders.isEmpty()) {
                        deinitNetworkCallback();
                    }
                    break;

                default:
                    throw new IllegalStateException("Unexpected value: " + msg.what);
            }
        }

        IwlanDataServiceHandler(Looper looper) {
            super(looper);
        }
    }

    private static final class TunnelOpenedData {
        final String mApnName;
        final TunnelLinkProperties mTunnelLinkProperties;
        final IwlanDataServiceProvider mIwlanDataServiceProvider;

        private TunnelOpenedData(
                String apnName,
                TunnelLinkProperties tunnelLinkProperties,
                IwlanDataServiceProvider dsp) {
            mApnName = apnName;
            mTunnelLinkProperties = tunnelLinkProperties;
            mIwlanDataServiceProvider = dsp;
        }
    }

    private static final class TunnelClosedData {
        final String mApnName;
        final IwlanError mIwlanError;
        final IwlanDataServiceProvider mIwlanDataServiceProvider;

        private TunnelClosedData(
                String apnName, IwlanError iwlanError, IwlanDataServiceProvider dsp) {
            mApnName = apnName;
            mIwlanError = iwlanError;
            mIwlanDataServiceProvider = dsp;
        }
    }

    private static final class SetupDataCallData {
        final int mAccessNetworkType;
        @NonNull final DataProfile mDataProfile;
        final boolean mIsRoaming;
        final boolean mAllowRoaming;
        final int mReason;
        @Nullable final LinkProperties mLinkProperties;

        @IntRange(from = 0, to = 15)
        final int mPduSessionId;

        @Nullable final NetworkSliceInfo mSliceInfo;
        @Nullable final TrafficDescriptor mTrafficDescriptor;
        final boolean mMatchAllRuleAllowed;
        @NonNull final DataServiceCallback mCallback;
        final IwlanDataServiceProvider mIwlanDataServiceProvider;

        private 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) {
            mAccessNetworkType = accessNetworkType;
            mDataProfile = dataProfile;
            mIsRoaming = isRoaming;
            mAllowRoaming = allowRoaming;
            mReason = reason;
            mLinkProperties = linkProperties;
            mPduSessionId = pduSessionId;
            mSliceInfo = sliceInfo;
            mTrafficDescriptor = trafficDescriptor;
            mMatchAllRuleAllowed = matchAllRuleAllowed;
            mCallback = callback;
            mIwlanDataServiceProvider = dsp;
        }
    }

    private static final class DeactivateDataCallData {
        final int mCid;
        final int mReason;
        final DataServiceCallback mCallback;
        final IwlanDataServiceProvider mIwlanDataServiceProvider;

        private DeactivateDataCallData(
                int cid, int reason, DataServiceCallback callback, IwlanDataServiceProvider dsp) {
            mCid = cid;
            mReason = reason;
            mCallback = callback;
            mIwlanDataServiceProvider = dsp;
        }
    }

    private static final class DataCallRequestData {
        final DataServiceCallback mCallback;
        final IwlanDataServiceProvider mIwlanDataServiceProvider;

        private DataCallRequestData(DataServiceCallback callback, IwlanDataServiceProvider dsp) {
            mCallback = callback;
            mIwlanDataServiceProvider = dsp;
        }
    }

    @VisibleForTesting
    static boolean isNetworkConnected(boolean isDds, boolean isCstEnabled) {
        if (!isDds && isCstEnabled) {
            // Only Non-DDS sub with CST enabled, can use any transport.
            return sNetworkConnected;
        } else {
            // For all other cases, only wifi transport can be used.
            return ((sDefaultDataTransport == Transport.WIFI) && sNetworkConnected);
        }
    }

    @VisibleForTesting
    /* Note: this api should have valid transport if networkConnected==true */
    static void setNetworkConnected(
            boolean networkConnected, Network network, Transport transport) {

        boolean hasNetworkChanged = false;
        boolean hasTransportChanged = false;
        boolean hasNetworkConnectedChanged = false;

        if (sNetworkConnected == networkConnected
                && network.equals(sNetwork)
                && sDefaultDataTransport == transport) {
            // Nothing changed
            return;
        }

        // safety check
        if (networkConnected && transport == Transport.UNSPECIFIED_NETWORK) {
            Log.e(TAG, "setNetworkConnected: Network connected but transport unspecified");
            return;
        }

        if (!network.equals(sNetwork)) {
            Log.e(TAG, "setNetworkConnected NW changed from: " + sNetwork + " TO: " + network);
            hasNetworkChanged = true;
        }

        if (transport != sDefaultDataTransport) {
            Log.d(
                    TAG,
                    "Transport was changed from "
                            + sDefaultDataTransport.name()
                            + " to "
                            + transport.name());
            hasTransportChanged = true;
        }

        if (sNetworkConnected != networkConnected) {
            Log.d(
                    TAG,
                    "Network connected state change from "
                            + sNetworkConnected
                            + " to "
                            + networkConnected);
            hasNetworkConnectedChanged = true;
        }

        sNetworkConnected = networkConnected;
        sDefaultDataTransport = transport;
        sNetwork = network;
        if (!networkConnected) {
            // reset link protocol type
            sLinkProtocolType = LinkProtocolType.UNKNOWN;
        }

        if (networkConnected) {
            if (hasTransportChanged) {
                // Perform forceClose for tunnels in bringdown.
                // let framework handle explicit teardown
                for (IwlanDataServiceProvider dp : sIwlanDataServiceProviders.values()) {
                    dp.forceCloseTunnelsInDeactivatingState();
                }
            }

            if (transport == Transport.WIFI && hasNetworkConnectedChanged) {
                IwlanEventListener.onWifiConnected(mContext);
            }
            // only prefetch dns and updateNetwork if Network has changed
            if (hasNetworkChanged) {
                for (IwlanDataServiceProvider dp : sIwlanDataServiceProviders.values()) {
                    dp.dnsPrefetchCheck();
                    dp.updateNetwork(sNetwork);
                }
                IwlanHelper.updateCountryCodeWhenNetworkConnected();
            }
        } else {
            for (IwlanDataServiceProvider dp : sIwlanDataServiceProviders.values()) {
                // once network is disconnected, even NAT KA offload fails
                // But we should still let framework do an explicit teardown
                // so as to not affect an ongoing handover
                // only force close tunnels in bring down state
                dp.forceCloseTunnelsInDeactivatingState();
            }
        }
    }

    static boolean isLinkProtocolTypeChanged(LinkProperties linkProperties) {
        boolean hasIPV4 = false;
        boolean hasIPV6 = false;

        LinkProtocolType linkProtocolType = null;
        if (linkProperties != null) {
            for (LinkAddress linkAddress : linkProperties.getLinkAddresses()) {
                InetAddress inetaddr = linkAddress.getAddress();
                // skip linklocal and loopback addresses
                if (!inetaddr.isLoopbackAddress() && !inetaddr.isLinkLocalAddress()) {
                    if (inetaddr instanceof Inet4Address) {
                        hasIPV4 = true;
                    } else if (inetaddr instanceof Inet6Address) {
                        hasIPV6 = true;
                    }
                }
            }

            if (hasIPV4 && hasIPV6) {
                linkProtocolType = LinkProtocolType.IPV4V6;
            } else if (hasIPV4) {
                linkProtocolType = LinkProtocolType.IPV4;
            } else if (hasIPV6) {
                linkProtocolType = LinkProtocolType.IPV6;
            }

            if (sLinkProtocolType != linkProtocolType) {
                Log.d(
                        TAG,
                        "LinkProtocolType was changed from "
                                + sLinkProtocolType
                                + " to "
                                + linkProtocolType);
                sLinkProtocolType = linkProtocolType;
                return true;
            }
            return false;
        }
        Log.w(TAG, "linkProperties is NULL.");
        return false;
    }

    /**
     * Get the DataServiceProvider associated with the slotId
     *
     * @param slotId slot index
     * @return DataService.DataServiceProvider associated with the slot
     */
    public static DataService.DataServiceProvider getDataServiceProvider(int slotId) {
        return sIwlanDataServiceProviders.get(slotId);
    }

    public static Context getContext() {
        return mContext;
    }

    @Override
    public DataServiceProvider onCreateDataServiceProvider(int slotIndex) {
        // TODO: validity check on slot index
        Log.d(TAG, "Creating provider for " + slotIndex);

        if (mIwlanDataServiceHandler == null) {
            initHandler();
        }

        if (mNetworkMonitorCallback == null) {
            // start monitoring network and register for default network callback
            ConnectivityManager connectivityManager =
                    mContext.getSystemService(ConnectivityManager.class);
            mNetworkMonitorCallback = new IwlanNetworkMonitorCallback();
            connectivityManager.registerSystemDefaultNetworkCallback(
                    mNetworkMonitorCallback, mIwlanDataServiceHandler);
            Log.d(TAG, "Registered with Connectivity Service");
        }

        IwlanDataServiceProvider dp = new IwlanDataServiceProvider(slotIndex, this);

        mIwlanDataServiceHandler.sendMessage(
                mIwlanDataServiceHandler.obtainMessage(EVENT_ADD_DATA_SERVICE_PROVIDER, dp));
        return dp;
    }

    public void removeDataServiceProvider(IwlanDataServiceProvider dp) {
        mIwlanDataServiceHandler.sendMessage(
                mIwlanDataServiceHandler.obtainMessage(EVENT_REMOVE_DATA_SERVICE_PROVIDER, dp));
    }

    @VisibleForTesting
    void addIwlanDataServiceProvider(IwlanDataServiceProvider dp) {
        int slotIndex = dp.getSlotIndex();
        if (sIwlanDataServiceProviders.containsKey(slotIndex)) {
            throw new IllegalStateException(
                    "DataServiceProvider already exists for slot " + slotIndex);
        }
        sIwlanDataServiceProviders.put(slotIndex, dp);
    }

    void deinitNetworkCallback() {
        // deinit network related stuff
        ConnectivityManager connectivityManager =
                mContext.getSystemService(ConnectivityManager.class);
        connectivityManager.unregisterNetworkCallback(mNetworkMonitorCallback);
        mNetworkMonitorCallback = null;
        if (mIwlanDataServiceHandlerThread != null) {
            mIwlanDataServiceHandlerThread.quit();
            mIwlanDataServiceHandlerThread = null;
        }
        mIwlanDataServiceHandler = null;
    }

    @VisibleForTesting
    void setAppContext(Context appContext) {
        mContext = appContext;
    }

    @VisibleForTesting
    IwlanNetworkMonitorCallback getNetworkMonitorCallback() {
        return mNetworkMonitorCallback;
    }

    @VisibleForTesting
    void initHandler() {
        mIwlanDataServiceHandler = new IwlanDataServiceHandler(getLooper());
    }

    @VisibleForTesting
    Looper getLooper() {
        mIwlanDataServiceHandlerThread = new HandlerThread("IwlanDataServiceThread");
        mIwlanDataServiceHandlerThread.start();
        return mIwlanDataServiceHandlerThread.getLooper();
    }

    private static String eventToString(int event) {
        switch (event) {
            case EVENT_TUNNEL_OPENED:
                return "EVENT_TUNNEL_OPENED";
            case EVENT_TUNNEL_CLOSED:
                return "EVENT_TUNNEL_CLOSED";
            case EVENT_SETUP_DATA_CALL:
                return "EVENT_SETUP_DATA_CALL";
            case EVENT_DEACTIVATE_DATA_CALL:
                return "EVENT_DEACTIVATE_DATA_CALL";
            case EVENT_DATA_CALL_LIST_REQUEST:
                return "EVENT_DATA_CALL_LIST_REQUEST";
            case EVENT_FORCE_CLOSE_TUNNEL:
                return "EVENT_FORCE_CLOSE_TUNNEL";
            case EVENT_ADD_DATA_SERVICE_PROVIDER:
                return "EVENT_ADD_DATA_SERVICE_PROVIDER";
            case EVENT_REMOVE_DATA_SERVICE_PROVIDER:
                return "EVENT_REMOVE_DATA_SERVICE_PROVIDER";
            case IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT:
                return "CARRIER_CONFIG_CHANGED_EVENT";
            case IwlanEventListener.CARRIER_CONFIG_UNKNOWN_CARRIER_EVENT:
                return "CARRIER_CONFIG_UNKNOWN_CARRIER_EVENT";
            case IwlanEventListener.WIFI_CALLING_ENABLE_EVENT:
                return "WIFI_CALLING_ENABLE_EVENT";
            case IwlanEventListener.WIFI_CALLING_DISABLE_EVENT:
                return "WIFI_CALLING_DISABLE_EVENT";
            case IwlanEventListener.CELLINFO_CHANGED_EVENT:
                return "CELLINFO_CHANGED_EVENT";
            default:
                return "Unknown(" + event + ")";
        }
    }

    @Override
    public void onCreate() {
        setAppContext(getApplicationContext());
        IwlanBroadcastReceiver.startListening(mContext);
        IwlanHelper.startCountryDetector(mContext);
    }

    @Override
    public void onDestroy() {
        IwlanBroadcastReceiver.stopListening(mContext);
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "Iwlanservice onBind");
        return super.onBind(intent);
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.d(TAG, "IwlanService onUnbind");
        mIwlanDataServiceHandler.sendMessage(
                mIwlanDataServiceHandler.obtainMessage(EVENT_FORCE_CLOSE_TUNNEL));
        return super.onUnbind(intent);
    }

    @Override
    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        String transport = "UNSPECIFIED";
        if (sDefaultDataTransport == Transport.MOBILE) {
            transport = "CELLULAR";
        } else if (sDefaultDataTransport == Transport.WIFI) {
            transport = "WIFI";
        }
        pw.println("Default transport: " + transport);
        for (IwlanDataServiceProvider provider : sIwlanDataServiceProviders.values()) {
            pw.println();
            provider.dump(fd, pw, args);
            pw.println();
            pw.println();
        }
    }
}
