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

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.AccessNetworkConstants.TransportType;
import android.telephony.TelephonyManager.NetworkType;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * Description of a mobile network registration info
 * @hide
 */
@SystemApi
@TestApi
public final class NetworkRegistrationInfo implements Parcelable {
    /**
     * Network domain
     * @hide
     */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = "DOMAIN_", value = {DOMAIN_CS, DOMAIN_PS})
    public @interface Domain {}

    /** Circuit switching domain */
    public static final int DOMAIN_CS = 1;
    /** Packet switching domain */
    public static final int DOMAIN_PS = 2;

    /**
     * Network registration state
     * @hide
     */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = "REGISTRATION_STATE_",
            value = {REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING, REGISTRATION_STATE_HOME,
                    REGISTRATION_STATE_NOT_REGISTERED_SEARCHING, REGISTRATION_STATE_DENIED,
                    REGISTRATION_STATE_UNKNOWN, REGISTRATION_STATE_ROAMING})
    public @interface RegistrationState {}

    /** Not registered. The device is not currently searching a new operator to register. */
    public static final int REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING = 0;
    /** Registered on home network. */
    public static final int REGISTRATION_STATE_HOME = 1;
    /** Not registered. The device is currently searching a new operator to register. */
    public static final int REGISTRATION_STATE_NOT_REGISTERED_SEARCHING = 2;
    /** Registration denied. */
    public static final int REGISTRATION_STATE_DENIED = 3;
    /** Registration state is unknown. */
    public static final int REGISTRATION_STATE_UNKNOWN = 4;
    /** Registered on roaming network. */
    public static final int REGISTRATION_STATE_ROAMING = 5;

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = "NR_STATE_",
            value = {NR_STATE_NONE, NR_STATE_RESTRICTED, NR_STATE_NOT_RESTRICTED,
                    NR_STATE_CONNECTED})
    public @interface NRState {}

    /**
     * The device isn't camped on an LTE cell or the LTE cell doesn't support E-UTRA-NR
     * Dual Connectivity(EN-DC).
     * @hide
     */
    public static final int NR_STATE_NONE = -1;

    /**
     * The device is camped on an LTE cell that supports E-UTRA-NR Dual Connectivity(EN-DC) but
     * either the use of dual connectivity with NR(DCNR) is restricted or NR is not supported by
     * the selected PLMN.
     * @hide
     */
    public static final int NR_STATE_RESTRICTED = 1;

    /**
     * The device is camped on an LTE cell that supports E-UTRA-NR Dual Connectivity(EN-DC) and both
     * the use of dual connectivity with NR(DCNR) is not restricted and NR is supported by the
     * selected PLMN.
     * @hide
     */
    public static final int NR_STATE_NOT_RESTRICTED = 2;

    /**
     * The device is camped on an LTE cell that supports E-UTRA-NR Dual Connectivity(EN-DC) and
     * also connected to at least one 5G cell as a secondary serving cell.
     * @hide
     */
    public static final int NR_STATE_CONNECTED = 3;

    /**
     * Supported service type
     * @hide
     */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = "SERVICE_TYPE_",
            value = {SERVICE_TYPE_UNKNOWN, SERVICE_TYPE_VOICE, SERVICE_TYPE_DATA, SERVICE_TYPE_SMS,
                    SERVICE_TYPE_VIDEO, SERVICE_TYPE_EMERGENCY})
    public @interface ServiceType {}

    /** Unkown service */
    public static final int SERVICE_TYPE_UNKNOWN    = 0;

    /** Voice service */
    public static final int SERVICE_TYPE_VOICE      = 1;

    /** Data service */
    public static final int SERVICE_TYPE_DATA       = 2;

    /** SMS service */
    public static final int SERVICE_TYPE_SMS        = 3;

    /** Video service */
    public static final int SERVICE_TYPE_VIDEO      = 4;

    /** Emergency service */
    public static final int SERVICE_TYPE_EMERGENCY  = 5;

    @Domain
    private final int mDomain;

    @TransportType
    private final int mTransportType;

    @RegistrationState
    private final int mRegistrationState;

    /**
     * Save the {@link ServiceState.RoamingType roaming type}. it can be overridden roaming type
     * from resource overlay or carrier config.
     */
    @ServiceState.RoamingType
    private int mRoamingType;

    @NetworkType
    private int mAccessNetworkTechnology;

    @NRState
    private int mNrState;

    private final int mRejectCause;

    private final boolean mEmergencyOnly;

    @ServiceType
    private final ArrayList<Integer> mAvailableServices;

    @Nullable
    private CellIdentity mCellIdentity;

    @Nullable
    private VoiceSpecificRegistrationInfo mVoiceSpecificInfo;

    @Nullable
    private DataSpecificRegistrationInfo mDataSpecificInfo;

    /**
     * @param domain Network domain. Must be a {@link Domain}. For transport type
     * {@link AccessNetworkConstants#TRANSPORT_TYPE_WLAN}, this must set to {@link #DOMAIN_PS}.
     * @param transportType Transport type.
     * @param registrationState Network registration state. For transport type
     * {@link AccessNetworkConstants#TRANSPORT_TYPE_WLAN}, only
     * {@link #REGISTRATION_STATE_HOME} and {@link #REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING}
     * are valid states.
     * @param accessNetworkTechnology Access network technology.For transport type
     * {@link AccessNetworkConstants#TRANSPORT_TYPE_WLAN}, set to
     * {@link TelephonyManager#NETWORK_TYPE_IWLAN}.
     * @param rejectCause Reason for denial if the registration state is
     * {@link #REGISTRATION_STATE_DENIED}. Depending on {@code accessNetworkTechnology}, the values
     * are defined in 3GPP TS 24.008 10.5.3.6 for UMTS, 3GPP TS 24.301 9.9.3.9 for LTE, and 3GPP2
     * A.S0001 6.2.2.44 for CDMA. If the reject cause is not supported or unknown, set it to 0.
     * // TODO: Add IWLAN reject cause reference
     * @param emergencyOnly True if this registration is for emergency only.
     * @param availableServices The list of the supported services.
     * @param cellIdentity The identity representing a unique cell or wifi AP. Set to null if the
     * information is not available.
     */
    private NetworkRegistrationInfo(@Domain int domain, @TransportType int transportType,
                                   @RegistrationState int registrationState,
                                   @NetworkType int accessNetworkTechnology, int rejectCause,
                                   boolean emergencyOnly,
                                   @Nullable @ServiceType List<Integer> availableServices,
                                   @Nullable CellIdentity cellIdentity) {
        mDomain = domain;
        mTransportType = transportType;
        mRegistrationState = registrationState;
        mRoamingType = (registrationState == REGISTRATION_STATE_ROAMING)
                ? ServiceState.ROAMING_TYPE_UNKNOWN : ServiceState.ROAMING_TYPE_NOT_ROAMING;
        mAccessNetworkTechnology = accessNetworkTechnology;
        mRejectCause = rejectCause;
        mAvailableServices = (availableServices != null)
                ? new ArrayList<>(availableServices) : new ArrayList<>();
        mCellIdentity = cellIdentity;
        mEmergencyOnly = emergencyOnly;
        mNrState = NR_STATE_NONE;
    }

    /**
     * Constructor for voice network registration info.
     * @hide
     */
    public NetworkRegistrationInfo(int domain, @TransportType int transportType,
                                   int registrationState, int accessNetworkTechnology,
                                   int rejectCause, boolean emergencyOnly,
                                   @Nullable List<Integer> availableServices,
                                   @Nullable CellIdentity cellIdentity, boolean cssSupported,
                                   int roamingIndicator, int systemIsInPrl,
                                   int defaultRoamingIndicator) {
        this(domain, transportType, registrationState, accessNetworkTechnology, rejectCause,
                emergencyOnly, availableServices, cellIdentity);

        mVoiceSpecificInfo = new VoiceSpecificRegistrationInfo(cssSupported, roamingIndicator,
                systemIsInPrl, defaultRoamingIndicator);
    }

    /**
     * Constructor for data network registration info.
     * @hide
     */
    public NetworkRegistrationInfo(int domain, @TransportType int transportType,
                                   int registrationState, int accessNetworkTechnology,
                                   int rejectCause, boolean emergencyOnly,
                                   @Nullable List<Integer> availableServices,
                                   @Nullable CellIdentity cellIdentity, int maxDataCalls,
                                   boolean isDcNrRestricted, boolean isNrAvailable,
                                   boolean isEndcAvailable,
                                   LteVopsSupportInfo lteVopsSupportInfo,
                                   boolean isUsingCarrierAggregation) {
        this(domain, transportType, registrationState, accessNetworkTechnology, rejectCause,
                emergencyOnly, availableServices, cellIdentity);
        mDataSpecificInfo = new DataSpecificRegistrationInfo(
                maxDataCalls, isDcNrRestricted, isNrAvailable, isEndcAvailable, lteVopsSupportInfo,
                isUsingCarrierAggregation);
        updateNrState(mDataSpecificInfo);
    }

    private NetworkRegistrationInfo(Parcel source) {
        mDomain = source.readInt();
        mTransportType = source.readInt();
        mRegistrationState = source.readInt();
        mRoamingType = source.readInt();
        mAccessNetworkTechnology = source.readInt();
        mRejectCause = source.readInt();
        mEmergencyOnly = source.readBoolean();
        mAvailableServices = new ArrayList<>();
        source.readList(mAvailableServices, Integer.class.getClassLoader());
        mCellIdentity = source.readParcelable(CellIdentity.class.getClassLoader());
        mVoiceSpecificInfo = source.readParcelable(
                VoiceSpecificRegistrationInfo.class.getClassLoader());
        mDataSpecificInfo = source.readParcelable(
                DataSpecificRegistrationInfo.class.getClassLoader());
        mNrState = source.readInt();
    }

    /**
     * Constructor from another network registration info
     *
     * @param nri Another network registration info
     * @hide
     */
    public NetworkRegistrationInfo(NetworkRegistrationInfo nri) {
        mDomain = nri.mDomain;
        mTransportType = nri.mTransportType;
        mRegistrationState = nri.mRegistrationState;
        mRoamingType = nri.mRoamingType;
        mAccessNetworkTechnology = nri.mAccessNetworkTechnology;
        mRejectCause = nri.mRejectCause;
        mEmergencyOnly = nri.mEmergencyOnly;
        mAvailableServices = new ArrayList<>(nri.mAvailableServices);
        if (nri.mCellIdentity != null) {
            Parcel p = Parcel.obtain();
            nri.mCellIdentity.writeToParcel(p, 0);
            p.setDataPosition(0);
            // TODO: Instead of doing this, we should create a formal way for cloning cell identity.
            // Cell identity is not an immutable object so we have to deep copy it.
            mCellIdentity = CellIdentity.CREATOR.createFromParcel(p);
        }

        if (nri.mVoiceSpecificInfo != null) {
            mVoiceSpecificInfo = new VoiceSpecificRegistrationInfo(nri.mVoiceSpecificInfo);
        }
        if (nri.mDataSpecificInfo != null) {
            mDataSpecificInfo = new DataSpecificRegistrationInfo(nri.mDataSpecificInfo);
        }
        mNrState = nri.mNrState;
    }

    /**
     * @return The transport type.
     */
    public @TransportType int getTransportType() { return mTransportType; }

    /**
     * @return The network domain.
     */
    public @Domain int getDomain() { return mDomain; }

    /**
     * @return the 5G NR connection state.
     * @hide
     */
    public @NRState int getNrState() {
        return mNrState;
    }

    /** @hide */
    public void setNrState(@NRState int nrState) {
        mNrState = nrState;
    }

    /**
     * @return The registration state.
     */
    public @RegistrationState int getRegistrationState() {
        return mRegistrationState;
    }

    /**
     * @return {@code true} if registered on roaming network, {@code false} otherwise.
     */
    public boolean isRoaming() {
        return mRoamingType != ServiceState.ROAMING_TYPE_NOT_ROAMING;
    }

    /**
     * @hide
     * @return {@code true} if in service.
     */
    public boolean isInService() {
        return mRegistrationState == REGISTRATION_STATE_HOME
                || mRegistrationState == REGISTRATION_STATE_ROAMING;
    }

    /**
     * Set {@link ServiceState.RoamingType roaming type}. This could override
     * roaming type based on resource overlay or carrier config.
     * @hide
     */
    public void setRoamingType(@ServiceState.RoamingType int roamingType) {
        mRoamingType = roamingType;
    }

    /**
     * @return the current network roaming type.
     */

    public @ServiceState.RoamingType int getRoamingType() {
        return mRoamingType;
    }

    /**
     * @return Whether emergency is enabled.
     */
    public boolean isEmergencyEnabled() { return mEmergencyOnly; }

    /**
     * @return List of available service types.
     */
    @NonNull
    @ServiceType
    public List<Integer> getAvailableServices() {
        return Collections.unmodifiableList(mAvailableServices);
    }

    /**
     * @return The access network technology {@link NetworkType}.
     */
    public @NetworkType int getAccessNetworkTechnology() {
        return mAccessNetworkTechnology;
    }

    /**
     * override the access network technology {@link NetworkType} e.g, rat ratchet.
     * @hide
     */
    public void setAccessNetworkTechnology(@NetworkType int tech) {
        if (tech == TelephonyManager.NETWORK_TYPE_LTE_CA) {
            // For old device backward compatibility support
            tech = TelephonyManager.NETWORK_TYPE_LTE;
            if (mDataSpecificInfo != null) {
                mDataSpecificInfo.setIsUsingCarrierAggregation(true);
            }
        }
        mAccessNetworkTechnology = tech;
    }

    /**
     * @return Reason for denial if the registration state is {@link #REGISTRATION_STATE_DENIED}.
     * Depending on {@code accessNetworkTechnology}, the values are defined in 3GPP TS 24.008
     * 10.5.3.6 for UMTS, 3GPP TS 24.301 9.9.3.9 for LTE, and 3GPP2 A.S0001 6.2.2.44 for CDMA
     */
    public int getRejectCause() {
        return mRejectCause;
    }

    /**
     * @return The cell information.
     */
    @Nullable
    public CellIdentity getCellIdentity() {
        return mCellIdentity;
    }

    /**
     * @hide
     */
    @Nullable
    public VoiceSpecificRegistrationInfo getVoiceSpecificInfo() {
        return mVoiceSpecificInfo;
    }

    /**
     * @return Data registration related info
     */
    @Nullable
    public DataSpecificRegistrationInfo getDataSpecificInfo() {
        return mDataSpecificInfo;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    /**
     * Convert service type to string
     *
     * @hide
     *
     * @param serviceType The service type
     * @return The service type in string format
     */
    public static String serviceTypeToString(@ServiceType int serviceType) {
        switch (serviceType) {
            case SERVICE_TYPE_VOICE: return "VOICE";
            case SERVICE_TYPE_DATA: return "DATA";
            case SERVICE_TYPE_SMS: return "SMS";
            case SERVICE_TYPE_VIDEO: return "VIDEO";
            case SERVICE_TYPE_EMERGENCY: return "EMERGENCY";
        }
        return "Unknown service type " + serviceType;
    }

    /**
     * Convert registration state to string
     *
     * @hide
     *
     * @param registrationState The registration state
     * @return The reg state in string
     */
    public static String registrationStateToString(@RegistrationState int registrationState) {
        switch (registrationState) {
            case REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING: return "NOT_REG_OR_SEARCHING";
            case REGISTRATION_STATE_HOME: return "HOME";
            case REGISTRATION_STATE_NOT_REGISTERED_SEARCHING: return "NOT_REG_SEARCHING";
            case REGISTRATION_STATE_DENIED: return "DENIED";
            case REGISTRATION_STATE_UNKNOWN: return "UNKNOWN";
            case REGISTRATION_STATE_ROAMING: return "ROAMING";
        }
        return "Unknown reg state " + registrationState;
    }

    private static String nrStateToString(@NRState int nrState) {
        switch (nrState) {
            case NR_STATE_RESTRICTED:
                return "RESTRICTED";
            case NR_STATE_NOT_RESTRICTED:
                return "NOT_RESTRICTED";
            case NR_STATE_CONNECTED:
                return "CONNECTED";
            default:
                return "NONE";
        }
    }

    @Override
    public String toString() {
        return new StringBuilder("NetworkRegistrationInfo{")
                .append(" domain=").append((mDomain == DOMAIN_CS) ? "CS" : "PS")
                .append(" transportType=").append(
                        AccessNetworkConstants.transportTypeToString(mTransportType))
                .append(" registrationState=").append(registrationStateToString(mRegistrationState))
                .append(" roamingType=").append(ServiceState.roamingTypeToString(mRoamingType))
                .append(" accessNetworkTechnology=")
                .append(TelephonyManager.getNetworkTypeName(mAccessNetworkTechnology))
                .append(" rejectCause=").append(mRejectCause)
                .append(" emergencyEnabled=").append(mEmergencyOnly)
                .append(" availableServices=").append("[" + (mAvailableServices != null
                        ? mAvailableServices.stream().map(type -> serviceTypeToString(type))
                        .collect(Collectors.joining(",")) : null) + "]")
                .append(" cellIdentity=").append(mCellIdentity)
                .append(" voiceSpecificInfo=").append(mVoiceSpecificInfo)
                .append(" dataSpecificInfo=").append(mDataSpecificInfo)
                .append(" nrState=").append(nrStateToString(mNrState))
                .append("}").toString();
    }

    @Override
    public int hashCode() {
        return Objects.hash(mDomain, mTransportType, mRegistrationState, mRoamingType,
                mAccessNetworkTechnology, mRejectCause, mEmergencyOnly, mAvailableServices,
                mCellIdentity, mVoiceSpecificInfo, mDataSpecificInfo, mNrState);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;

        if (!(o instanceof NetworkRegistrationInfo)) {
            return false;
        }

        NetworkRegistrationInfo other = (NetworkRegistrationInfo) o;
        return mDomain == other.mDomain
                && mTransportType == other.mTransportType
                && mRegistrationState == other.mRegistrationState
                && mRoamingType == other.mRoamingType
                && mAccessNetworkTechnology == other.mAccessNetworkTechnology
                && mRejectCause == other.mRejectCause
                && mEmergencyOnly == other.mEmergencyOnly
                && mAvailableServices.equals(other.mAvailableServices)
                && Objects.equals(mCellIdentity, other.mCellIdentity)
                && Objects.equals(mVoiceSpecificInfo, other.mVoiceSpecificInfo)
                && Objects.equals(mDataSpecificInfo, other.mDataSpecificInfo)
                && mNrState == other.mNrState;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mDomain);
        dest.writeInt(mTransportType);
        dest.writeInt(mRegistrationState);
        dest.writeInt(mRoamingType);
        dest.writeInt(mAccessNetworkTechnology);
        dest.writeInt(mRejectCause);
        dest.writeBoolean(mEmergencyOnly);
        dest.writeList(mAvailableServices);
        dest.writeParcelable(mCellIdentity, 0);
        dest.writeParcelable(mVoiceSpecificInfo, 0);
        dest.writeParcelable(mDataSpecificInfo, 0);
        dest.writeInt(mNrState);
    }

    /**
     * Use the 5G NR Non-Standalone indicators from the network registration state to update the
     * NR state. There are 3 indicators in the network registration state:
     *
     * 1. if E-UTRA-NR Dual Connectivity (EN-DC) is supported by the primary serving cell.
     * 2. if NR is supported by the selected PLMN.
     * 3. if the use of dual connectivity with NR is restricted.
     *
     * The network has 5G NR capability if E-UTRA-NR Dual Connectivity is supported by the primary
     * serving cell.
     *
     * The use of NR 5G is not restricted If the network has 5G NR capability and both the use of
     * DCNR is not restricted and NR is supported by the selected PLMN. Otherwise the use of 5G
     * NR is restricted.
     *
     * @param state data specific registration state contains the 5G NR indicators.
     */
    private void updateNrState(DataSpecificRegistrationInfo state) {
        mNrState = NR_STATE_NONE;
        if (state.isEnDcAvailable) {
            if (!state.isDcNrRestricted && state.isNrAvailable) {
                mNrState = NR_STATE_NOT_RESTRICTED;
            } else {
                mNrState = NR_STATE_RESTRICTED;
            }
        }
    }

    public static final @NonNull Parcelable.Creator<NetworkRegistrationInfo> CREATOR =
            new Parcelable.Creator<NetworkRegistrationInfo>() {
                @Override
                public NetworkRegistrationInfo createFromParcel(Parcel source) {
                    return new NetworkRegistrationInfo(source);
                }

                @Override
                public NetworkRegistrationInfo[] newArray(int size) {
                    return new NetworkRegistrationInfo[size];
                }
            };

    /**
     * @hide
     */
    public NetworkRegistrationInfo sanitizeLocationInfo() {
        NetworkRegistrationInfo result = copy();
        result.mCellIdentity = null;
        return result;
    }

    private NetworkRegistrationInfo copy() {
        Parcel p = Parcel.obtain();
        this.writeToParcel(p, 0);
        p.setDataPosition(0);
        NetworkRegistrationInfo result = new NetworkRegistrationInfo(p);
        p.recycle();
        return result;
    }

    /**
     * Provides a convenient way to set the fields of a {@link NetworkRegistrationInfo} when
     * creating a new instance.
     *
     * <p>The example below shows how you might create a new {@code NetworkRegistrationInfo}:
     *
     * <pre><code>
     *
     * NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
     *     .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
     *     .setRegistrationState(REGISTRATION_STATE_HOME)
     *     .build();
     * </code></pre>
     */
    public static final class Builder{
        @Domain
        private int mDomain;

        @TransportType
        private int mTransportType;

        @RegistrationState
        private int mRegistrationState;

        @NetworkType
        private int mAccessNetworkTechnology;

        private int mRejectCause;

        private boolean mEmergencyOnly;

        @ServiceType
        private List<Integer> mAvailableServices;

        @Nullable
        private CellIdentity mCellIdentity;

        /**
         * Default constructor for Builder.
         */
        public Builder() {}

        /**
         * Set the network domain.
         *
         * @param domain Network domain.
         *
         * @return The same instance of the builder.
         */
        public @NonNull Builder setDomain(@Domain int domain) {
            mDomain = domain;
            return this;
        }

        /**
         * Set the transport type.
         *
         * @param transportType Transport type.
         *
         * @return The same instance of the builder.
         */
        public @NonNull Builder setTransportType(@TransportType int transportType) {
            mTransportType = transportType;
            return this;
        }

        /**
         * Set the registration state.
         *
         * @param registrationState The registration state.
         *
         * @return The same instance of the builder.
         */
        public @NonNull Builder setRegistrationState(@RegistrationState int registrationState) {
            mRegistrationState = registrationState;
            return this;
        }

        /**
         * Set tne access network technology.
         *
         * @return The same instance of the builder.
         *
         * @param accessNetworkTechnology The access network technology
         */
        public @NonNull Builder setAccessNetworkTechnology(
                @NetworkType int accessNetworkTechnology) {
            mAccessNetworkTechnology = accessNetworkTechnology;
            return this;
        }

        /**
         * Set the network reject cause.
         *
         * @param rejectCause Reason for denial if the registration state is
         * {@link #REGISTRATION_STATE_DENIED}.Depending on {@code accessNetworkTechnology}, the
         * values are defined in 3GPP TS 24.008 10.5.3.6 for UMTS, 3GPP TS 24.301 9.9.3.9 for LTE,
         * and 3GPP2 A.S0001 6.2.2.44 for CDMA. If the reject cause is not supported or unknown, set
         * it to 0.
         *
         * @return The same instance of the builder.
         */
        public @NonNull Builder setRejectCause(int rejectCause) {
            mRejectCause = rejectCause;
            return this;
        }

        /**
         * Set emergency only.
         *
         * @param emergencyOnly True if this network registration is for emergency use only.
         *
         * @return The same instance of the builder.
         */
        public @NonNull Builder setEmergencyOnly(boolean emergencyOnly) {
            mEmergencyOnly = emergencyOnly;
            return this;
        }

        /**
         * Set the available services.
         *
         * @param availableServices Available services.
         *
         * @return The same instance of the builder.
         */
        public @NonNull Builder setAvailableServices(
                @NonNull @ServiceType List<Integer> availableServices) {
            mAvailableServices = availableServices;
            return this;
        }

        /**
         * Set the cell identity.
         *
         * @param cellIdentity The cell identity.
         *
         * @return The same instance of the builder.
         */
        public @NonNull Builder setCellIdentity(@Nullable CellIdentity cellIdentity) {
            mCellIdentity = cellIdentity;
            return this;
        }

        /**
         * Build the NetworkRegistrationInfo.
         *
         * @return the NetworkRegistrationInfo object.
         */
        public @NonNull NetworkRegistrationInfo build() {
            return new NetworkRegistrationInfo(mDomain, mTransportType, mRegistrationState,
                    mAccessNetworkTechnology, mRejectCause, mEmergencyOnly, mAvailableServices,
                    mCellIdentity);
        }
    }
}
