/*
 * Copyright 2017 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.android.internal.telephony;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.hardware.radio.V1_0.RegState;
import android.hardware.radio.V1_4.DataRegStateResult.VopsInfo.hidl_discriminator;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.telephony.AccessNetworkConstants;
import android.telephony.AccessNetworkConstants.AccessNetworkType;
import android.telephony.CellIdentity;
import android.telephony.CellIdentityCdma;
import android.telephony.LteVopsSupportInfo;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.NetworkService;
import android.telephony.NetworkServiceCallback;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;

import com.android.telephony.Rlog;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Implementation of network services for Cellular. It's a service that handles network requests
 * for Cellular. It passes the requests to inner CellularNetworkServiceProvider which has a
 * handler thread for each slot.
 */
public class CellularNetworkService extends NetworkService {
    private static final boolean DBG = false;

    private static final String TAG = CellularNetworkService.class.getSimpleName();

    private static final int GET_CS_REGISTRATION_STATE_DONE = 1;
    private static final int GET_PS_REGISTRATION_STATE_DONE = 2;
    private static final int NETWORK_REGISTRATION_STATE_CHANGED = 3;

    // From 24.008 6.1.3.0 and 10.5.6.2 the maximum number of PDP Contexts is 16.
    private static final int MAX_DATA_CALLS = 16;

    private class CellularNetworkServiceProvider extends NetworkServiceProvider {

        private final Map<Message, NetworkServiceCallback> mCallbackMap = new HashMap<>();

        private final Handler mHandler;

        private final Phone mPhone;

        CellularNetworkServiceProvider(int slotId) {
            super(slotId);

            mPhone = PhoneFactory.getPhone(getSlotIndex());

            mHandler = new Handler(Looper.myLooper()) {
                @Override
                public void handleMessage(Message message) {
                    NetworkServiceCallback callback = mCallbackMap.remove(message);

                    AsyncResult ar;
                    switch (message.what) {
                        case GET_CS_REGISTRATION_STATE_DONE:
                        case GET_PS_REGISTRATION_STATE_DONE:
                            if (callback == null) return;
                            ar = (AsyncResult) message.obj;
                            int domain = (message.what == GET_CS_REGISTRATION_STATE_DONE)
                                    ? NetworkRegistrationInfo.DOMAIN_CS
                                    : NetworkRegistrationInfo.DOMAIN_PS;
                            NetworkRegistrationInfo netState =
                                    getRegistrationStateFromResult(ar.result, domain);

                            int resultCode;
                            if (ar.exception != null || netState == null) {
                                resultCode = NetworkServiceCallback.RESULT_ERROR_FAILED;
                            } else {
                                resultCode = NetworkServiceCallback.RESULT_SUCCESS;
                            }

                            try {
                                if (DBG) {
                                    log("Calling onRequestNetworkRegistrationInfoComplete."
                                            + "resultCode = " + resultCode
                                            + ", netState = " + netState);
                                }
                                callback.onRequestNetworkRegistrationInfoComplete(
                                         resultCode, netState);
                            } catch (Exception e) {
                                loge("Exception: " + e);
                            }
                            break;
                        case NETWORK_REGISTRATION_STATE_CHANGED:
                            notifyNetworkRegistrationInfoChanged();
                            break;
                        default:
                            return;
                    }
                }
            };

            mPhone.mCi.registerForNetworkStateChanged(
                    mHandler, NETWORK_REGISTRATION_STATE_CHANGED, null);
        }

        private int getRegStateFromHalRegState(int halRegState) {
            switch (halRegState) {
                case RegState.NOT_REG_MT_NOT_SEARCHING_OP:
                case RegState.NOT_REG_MT_NOT_SEARCHING_OP_EM:
                    return NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING;
                case RegState.REG_HOME:
                    return NetworkRegistrationInfo.REGISTRATION_STATE_HOME;
                case RegState.NOT_REG_MT_SEARCHING_OP:
                case RegState.NOT_REG_MT_SEARCHING_OP_EM:
                    return NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_SEARCHING;
                case RegState.REG_DENIED:
                case RegState.REG_DENIED_EM:
                    return NetworkRegistrationInfo.REGISTRATION_STATE_DENIED;
                case RegState.UNKNOWN:
                case RegState.UNKNOWN_EM:
                    return NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN;
                case RegState.REG_ROAMING:
                    return NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING;
                default:
                    return NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING;
            }
        }

        private boolean isEmergencyOnly(int halRegState) {
            switch (halRegState) {
                case RegState.NOT_REG_MT_NOT_SEARCHING_OP_EM:
                case RegState.NOT_REG_MT_SEARCHING_OP_EM:
                case RegState.REG_DENIED_EM:
                case RegState.UNKNOWN_EM:
                    return true;
                case RegState.NOT_REG_MT_NOT_SEARCHING_OP:
                case RegState.REG_HOME:
                case RegState.NOT_REG_MT_SEARCHING_OP:
                case RegState.REG_DENIED:
                case RegState.UNKNOWN:
                case RegState.REG_ROAMING:
                default:
                    return false;
            }
        }

        private List<Integer> getAvailableServices(int regState, int domain,
                                                   boolean emergencyOnly) {
            List<Integer> availableServices = new ArrayList<>();

            // In emergency only states, only SERVICE_TYPE_EMERGENCY is available.
            // Otherwise, certain services are available only if it's registered on home or roaming
            // network.
            if (emergencyOnly) {
                availableServices.add(NetworkRegistrationInfo.SERVICE_TYPE_EMERGENCY);
            } else if (regState == NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING
                    || regState == NetworkRegistrationInfo.REGISTRATION_STATE_HOME) {
                if (domain == NetworkRegistrationInfo.DOMAIN_PS) {
                    availableServices.add(NetworkRegistrationInfo.SERVICE_TYPE_DATA);
                } else if (domain == NetworkRegistrationInfo.DOMAIN_CS) {
                    availableServices.add(NetworkRegistrationInfo.SERVICE_TYPE_VOICE);
                    availableServices.add(NetworkRegistrationInfo.SERVICE_TYPE_SMS);
                    availableServices.add(NetworkRegistrationInfo.SERVICE_TYPE_VIDEO);
                }
            }

            return availableServices;
        }

        private NetworkRegistrationInfo getRegistrationStateFromResult(Object result, int domain) {
            if (result == null) {
                return null;
            }

            // TODO: unify when voiceRegStateResult and DataRegStateResult are unified.
            if (domain == NetworkRegistrationInfo.DOMAIN_CS) {
                return createRegistrationStateFromVoiceRegState(result);
            } else if (domain == NetworkRegistrationInfo.DOMAIN_PS) {
                return createRegistrationStateFromDataRegState(result);
            } else {
                return null;
            }
        }

        private @NonNull String getPlmnFromCellIdentity(@Nullable final CellIdentity ci) {
            if (ci == null || ci instanceof CellIdentityCdma) return "";

            final String mcc = ci.getMccString();
            final String mnc = ci.getMncString();

            if (TextUtils.isEmpty(mcc) || TextUtils.isEmpty(mnc)) return "";

            return mcc + mnc;
        }

        private NetworkRegistrationInfo createRegistrationStateFromVoiceRegState(Object result) {
            final int transportType = AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
            final int domain = NetworkRegistrationInfo.DOMAIN_CS;

            // 1.5 at the top so that we can do an "early exit" from the method
            if (result instanceof android.hardware.radio.V1_5.RegStateResult) {
                return getNetworkRegistrationInfo(
                        domain,
                        transportType,
                        (android.hardware.radio.V1_5.RegStateResult) result);
            } else if (result instanceof android.hardware.radio.V1_0.VoiceRegStateResult) {
                android.hardware.radio.V1_0.VoiceRegStateResult voiceRegState =
                        (android.hardware.radio.V1_0.VoiceRegStateResult) result;
                int regState = getRegStateFromHalRegState(voiceRegState.regState);
                int networkType = ServiceState.rilRadioTechnologyToNetworkType(voiceRegState.rat);
                if (networkType == TelephonyManager.NETWORK_TYPE_LTE_CA) {
                    networkType = TelephonyManager.NETWORK_TYPE_LTE;
                }
                int reasonForDenial = voiceRegState.reasonForDenial;
                boolean emergencyOnly = isEmergencyOnly(voiceRegState.regState);
                boolean cssSupported = voiceRegState.cssSupported;
                int roamingIndicator = voiceRegState.roamingIndicator;
                int systemIsInPrl = voiceRegState.systemIsInPrl;
                int defaultRoamingIndicator = voiceRegState.defaultRoamingIndicator;
                List<Integer> availableServices = getAvailableServices(
                        regState, domain, emergencyOnly);
                CellIdentity cellIdentity = CellIdentity.create(voiceRegState.cellIdentity);
                final String rplmn = getPlmnFromCellIdentity(cellIdentity);

                return new NetworkRegistrationInfo(domain, transportType, regState,
                        networkType, reasonForDenial, emergencyOnly, availableServices,
                        cellIdentity, rplmn, cssSupported, roamingIndicator, systemIsInPrl,
                        defaultRoamingIndicator);
            } else if (result instanceof android.hardware.radio.V1_2.VoiceRegStateResult) {
                android.hardware.radio.V1_2.VoiceRegStateResult voiceRegState =
                        (android.hardware.radio.V1_2.VoiceRegStateResult) result;
                int regState = getRegStateFromHalRegState(voiceRegState.regState);
                int networkType = ServiceState.rilRadioTechnologyToNetworkType(voiceRegState.rat);
                if (networkType == TelephonyManager.NETWORK_TYPE_LTE_CA) {
                    networkType = TelephonyManager.NETWORK_TYPE_LTE;
                }
                int reasonForDenial = voiceRegState.reasonForDenial;
                boolean emergencyOnly = isEmergencyOnly(voiceRegState.regState);
                boolean cssSupported = voiceRegState.cssSupported;
                int roamingIndicator = voiceRegState.roamingIndicator;
                int systemIsInPrl = voiceRegState.systemIsInPrl;
                int defaultRoamingIndicator = voiceRegState.defaultRoamingIndicator;
                List<Integer> availableServices = getAvailableServices(
                        regState, domain, emergencyOnly);
                CellIdentity cellIdentity = CellIdentity.create(voiceRegState.cellIdentity);
                final String rplmn = getPlmnFromCellIdentity(cellIdentity);

                return new NetworkRegistrationInfo(domain, transportType, regState,
                        networkType, reasonForDenial, emergencyOnly, availableServices,
                        cellIdentity, rplmn, cssSupported, roamingIndicator, systemIsInPrl,
                        defaultRoamingIndicator);
            }

            return null;
        }

        private NetworkRegistrationInfo createRegistrationStateFromDataRegState(Object result) {
            final int domain = NetworkRegistrationInfo.DOMAIN_PS;
            final int transportType = AccessNetworkConstants.TRANSPORT_TYPE_WWAN;

            int regState = NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN;
            int networkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
            int reasonForDenial = 0;
            boolean isUsingCarrierAggregation = false;
            boolean emergencyOnly = false;
            int maxDataCalls = 0;
            CellIdentity cellIdentity;
            boolean isEndcAvailable = false;
            boolean isNrAvailable = false;
            boolean isDcNrRestricted = false;

            LteVopsSupportInfo lteVopsSupportInfo =
                    new LteVopsSupportInfo(LteVopsSupportInfo.LTE_STATUS_NOT_AVAILABLE,
                            LteVopsSupportInfo.LTE_STATUS_NOT_AVAILABLE);

            // 1.5 at the top so that we can do an "early exit" from the method
            if (result instanceof android.hardware.radio.V1_5.RegStateResult) {
                return getNetworkRegistrationInfo(
                        domain,
                        transportType,
                        (android.hardware.radio.V1_5.RegStateResult) result);
            } else if (result instanceof android.hardware.radio.V1_0.DataRegStateResult) {
                android.hardware.radio.V1_0.DataRegStateResult dataRegState =
                        (android.hardware.radio.V1_0.DataRegStateResult) result;
                regState = getRegStateFromHalRegState(dataRegState.regState);
                networkType = ServiceState.rilRadioTechnologyToNetworkType(dataRegState.rat);
                reasonForDenial = dataRegState.reasonDataDenied;
                emergencyOnly = isEmergencyOnly(dataRegState.regState);
                maxDataCalls = dataRegState.maxDataCalls;
                cellIdentity = CellIdentity.create(dataRegState.cellIdentity);
            } else if (result instanceof android.hardware.radio.V1_2.DataRegStateResult) {
                android.hardware.radio.V1_2.DataRegStateResult dataRegState =
                        (android.hardware.radio.V1_2.DataRegStateResult) result;
                regState = getRegStateFromHalRegState(dataRegState.regState);
                networkType = ServiceState.rilRadioTechnologyToNetworkType(dataRegState.rat);
                reasonForDenial = dataRegState.reasonDataDenied;
                emergencyOnly = isEmergencyOnly(dataRegState.regState);
                maxDataCalls = dataRegState.maxDataCalls;
                cellIdentity = CellIdentity.create(dataRegState.cellIdentity);
            } else if (result instanceof android.hardware.radio.V1_4.DataRegStateResult) {
                android.hardware.radio.V1_4.DataRegStateResult dataRegState =
                        (android.hardware.radio.V1_4.DataRegStateResult) result;
                regState = getRegStateFromHalRegState(dataRegState.base.regState);
                networkType = ServiceState.rilRadioTechnologyToNetworkType(dataRegState.base.rat);

                reasonForDenial = dataRegState.base.reasonDataDenied;
                emergencyOnly = isEmergencyOnly(dataRegState.base.regState);
                maxDataCalls = dataRegState.base.maxDataCalls;
                cellIdentity = CellIdentity.create(dataRegState.base.cellIdentity);
                android.hardware.radio.V1_4.NrIndicators nrIndicators = dataRegState.nrIndicators;

                // Check for lteVopsInfo only if its initialized and RAT is EUTRAN
                if (dataRegState.vopsInfo.getDiscriminator() == hidl_discriminator.lteVopsInfo
                        && ServiceState.rilRadioTechnologyToAccessNetworkType(dataRegState.base.rat)
                            == AccessNetworkType.EUTRAN) {
                    android.hardware.radio.V1_4.LteVopsInfo vopsSupport =
                            dataRegState.vopsInfo.lteVopsInfo();
                    lteVopsSupportInfo = convertHalLteVopsSupportInfo(vopsSupport.isVopsSupported,
                        vopsSupport.isEmcBearerSupported);
                } else {
                    lteVopsSupportInfo =
                        new LteVopsSupportInfo(LteVopsSupportInfo.LTE_STATUS_NOT_AVAILABLE,
                        LteVopsSupportInfo.LTE_STATUS_NOT_AVAILABLE);
                }

                isEndcAvailable = nrIndicators.isEndcAvailable;
                isNrAvailable = nrIndicators.isNrAvailable;
                isDcNrRestricted = nrIndicators.isDcNrRestricted;
            } else {
                loge("Unknown type of DataRegStateResult " + result);
                return null;
            }

            String rplmn = getPlmnFromCellIdentity(cellIdentity);
            List<Integer> availableServices = getAvailableServices(
                    regState, domain, emergencyOnly);

            if (networkType == TelephonyManager.NETWORK_TYPE_LTE_CA) {
                isUsingCarrierAggregation = true;
                networkType = TelephonyManager.NETWORK_TYPE_LTE;
            }

            return new NetworkRegistrationInfo(domain, transportType, regState, networkType,
                    reasonForDenial, emergencyOnly, availableServices, cellIdentity, rplmn,
                    maxDataCalls, isDcNrRestricted, isNrAvailable, isEndcAvailable,
                    lteVopsSupportInfo, isUsingCarrierAggregation);
        }

        private @NonNull NetworkRegistrationInfo getNetworkRegistrationInfo(
                int domain, int transportType,
                android.hardware.radio.V1_5.RegStateResult regResult) {

            // Perform common conversions that aren't domain specific
            final int regState = getRegStateFromHalRegState(regResult.regState);
            final boolean isEmergencyOnly = isEmergencyOnly(regResult.regState);
            final List<Integer> availableServices = getAvailableServices(
                    regState, domain, isEmergencyOnly);
            final int rejectCause = regResult.reasonForDenial;
            final CellIdentity cellIdentity = CellIdentity.create(regResult.cellIdentity);
            final String rplmn = regResult.registeredPlmn;
            final int reasonForDenial = regResult.reasonForDenial;

            // Network Type fixup for carrier aggregation
            int networkType = ServiceState.rilRadioTechnologyToNetworkType(regResult.rat);
            // In earlier versions of the HAL, LTE_CA was allowed to indicate that the device
            // is on CA; however, that has been superseded by the PHYSICAL_CHANNEL_CONFIG signal.
            // Because some vendors provide both NETWORK_TYPE_LTE_CA *and* PHYSICAL_CHANNEL_CONFIG,
            // this tweak is left for compatibility; however, the network type is no longer allowed
            // to be used to declare that carrier aggregation is in effect, because the other
            // signal provides a much richer information set, and we want to mitigate confusion in
            // how CA information is being provided.
            if (networkType == TelephonyManager.NETWORK_TYPE_LTE_CA) {
                networkType = TelephonyManager.NETWORK_TYPE_LTE;
            }

            // Conditional parameters for specific RANs
            boolean cssSupported = false;
            int roamingIndicator = 0;
            int systemIsInPrl = 0;
            int defaultRoamingIndicator = 0;
            boolean isEndcAvailable = false;
            boolean isNrAvailable = false;
            boolean isDcNrRestricted = false;
            LteVopsSupportInfo vopsInfo = new LteVopsSupportInfo(
                    LteVopsSupportInfo.LTE_STATUS_NOT_AVAILABLE,
                    LteVopsSupportInfo.LTE_STATUS_NOT_AVAILABLE);

            switch (regResult.accessTechnologySpecificInfo.getDiscriminator()) {
                case android.hardware.radio.V1_5.RegStateResult
                        .AccessTechnologySpecificInfo.hidl_discriminator.cdmaInfo:
                    android.hardware.radio.V1_5.RegStateResult
                            .AccessTechnologySpecificInfo.Cdma2000RegistrationInfo cdmaInfo =
                                    regResult.accessTechnologySpecificInfo.cdmaInfo();
                    cssSupported = cdmaInfo.cssSupported;
                    roamingIndicator = cdmaInfo.roamingIndicator;
                    systemIsInPrl = cdmaInfo.systemIsInPrl;
                    defaultRoamingIndicator = cdmaInfo.defaultRoamingIndicator;
                    break;
                case android.hardware.radio.V1_5.RegStateResult
                        .AccessTechnologySpecificInfo.hidl_discriminator.eutranInfo:
                    android.hardware.radio.V1_5.RegStateResult
                            .AccessTechnologySpecificInfo.EutranRegistrationInfo eutranInfo =
                                    regResult.accessTechnologySpecificInfo.eutranInfo();

                    isDcNrRestricted = eutranInfo.nrIndicators.isDcNrRestricted;
                    isNrAvailable = eutranInfo.nrIndicators.isNrAvailable;
                    isEndcAvailable = eutranInfo.nrIndicators.isEndcAvailable;
                    vopsInfo = convertHalLteVopsSupportInfo(
                            eutranInfo.lteVopsInfo.isVopsSupported,
                            eutranInfo.lteVopsInfo.isEmcBearerSupported);
                    break;
                default:
                    log("No access tech specific info passes for RegStateResult");
                    break;
            }

            // build the result based on the domain for the request
            switch(domain) {
                case NetworkRegistrationInfo.DOMAIN_CS:
                    return new NetworkRegistrationInfo(domain, transportType, regState,
                            networkType, reasonForDenial, isEmergencyOnly, availableServices,
                            cellIdentity, rplmn, cssSupported, roamingIndicator, systemIsInPrl,
                            defaultRoamingIndicator);
                default:
                    loge("Unknown domain passed to CellularNetworkService= " + domain);
                    // fall through
                case NetworkRegistrationInfo.DOMAIN_PS:
                    return new NetworkRegistrationInfo(domain, transportType, regState, networkType,
                            reasonForDenial, isEmergencyOnly, availableServices, cellIdentity,
                            rplmn, MAX_DATA_CALLS, isDcNrRestricted, isNrAvailable, isEndcAvailable,
                            vopsInfo, false /* isUsingCarrierAggregation */);
            }
        }

        private LteVopsSupportInfo convertHalLteVopsSupportInfo(
                boolean vopsSupport, boolean emcBearerSupport) {
            int vops = LteVopsSupportInfo.LTE_STATUS_NOT_SUPPORTED;
            int emergency = LteVopsSupportInfo.LTE_STATUS_NOT_SUPPORTED;

            if (vopsSupport) {
                vops = LteVopsSupportInfo.LTE_STATUS_SUPPORTED;
            }
            if (emcBearerSupport) {
                emergency = LteVopsSupportInfo.LTE_STATUS_SUPPORTED;
            }
            return new LteVopsSupportInfo(vops, emergency);
        }

        @Override
        public void requestNetworkRegistrationInfo(int domain, NetworkServiceCallback callback) {
            if (DBG) log("requestNetworkRegistrationInfo for domain " + domain);
            Message message = null;

            if (domain == NetworkRegistrationInfo.DOMAIN_CS) {
                message = Message.obtain(mHandler, GET_CS_REGISTRATION_STATE_DONE);
                mCallbackMap.put(message, callback);
                mPhone.mCi.getVoiceRegistrationState(message);
            } else if (domain == NetworkRegistrationInfo.DOMAIN_PS) {
                message = Message.obtain(mHandler, GET_PS_REGISTRATION_STATE_DONE);
                mCallbackMap.put(message, callback);
                mPhone.mCi.getDataRegistrationState(message);
            } else {
                loge("requestNetworkRegistrationInfo invalid domain " + domain);
                callback.onRequestNetworkRegistrationInfoComplete(
                        NetworkServiceCallback.RESULT_ERROR_INVALID_ARG, null);
            }
        }

        @Override
        public void close() {
            mCallbackMap.clear();
            mPhone.mCi.unregisterForNetworkStateChanged(mHandler);
        }
    }

    @Override
    public NetworkServiceProvider onCreateNetworkServiceProvider(int slotIndex) {
        if (DBG) log("Cellular network service created for slot " + slotIndex);
        if (!SubscriptionManager.isValidSlotIndex(slotIndex)) {
            loge("Tried to Cellular network service with invalid slotId " + slotIndex);
            return null;
        }
        return new CellularNetworkServiceProvider(slotIndex);
    }

    private void log(String s) {
        Rlog.d(TAG, s);
    }

    private void loge(String s) {
        Rlog.e(TAG, s);
    }
}
