1 /*
2  * Copyright 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.telephony;
18 
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.annotation.SystemApi;
23 import android.annotation.TestApi;
24 import android.os.Parcel;
25 import android.os.Parcelable;
26 import android.telephony.AccessNetworkConstants.TransportType;
27 import android.telephony.Annotation.NetworkType;
28 import android.text.TextUtils;
29 
30 import java.lang.annotation.Retention;
31 import java.lang.annotation.RetentionPolicy;
32 import java.util.ArrayList;
33 import java.util.Collections;
34 import java.util.List;
35 import java.util.Objects;
36 import java.util.stream.Collectors;
37 
38 /**
39  * Description of a mobile network registration info
40  */
41 public final class NetworkRegistrationInfo implements Parcelable {
42     /**
43      * Network domain
44      * @hide
45      */
46     @Retention(RetentionPolicy.SOURCE)
47     @IntDef(prefix = "DOMAIN_", value = {DOMAIN_UNKNOWN, DOMAIN_CS, DOMAIN_PS, DOMAIN_CS_PS})
48     public @interface Domain {}
49 
50     /** Unknown / Unspecified domain */
51     public static final int DOMAIN_UNKNOWN = 0;
52     /** Circuit switched domain */
53     public static final int DOMAIN_CS = android.hardware.radio.V1_5.Domain.CS;
54     /** Packet switched domain */
55     public static final int DOMAIN_PS = android.hardware.radio.V1_5.Domain.PS;
56     /** Applicable to both CS and PS Domain */
57     public static final int DOMAIN_CS_PS = DOMAIN_CS | DOMAIN_PS;
58 
59     /**
60      * Network registration state
61      * @hide
62      */
63     @Retention(RetentionPolicy.SOURCE)
64     @IntDef(prefix = "REGISTRATION_STATE_",
65             value = {REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING, REGISTRATION_STATE_HOME,
66                     REGISTRATION_STATE_NOT_REGISTERED_SEARCHING, REGISTRATION_STATE_DENIED,
67                     REGISTRATION_STATE_UNKNOWN, REGISTRATION_STATE_ROAMING})
68     public @interface RegistrationState {}
69 
70     /**
71      * Not registered. The device is not currently searching a new operator to register.
72      * @hide
73      */
74     @SystemApi @TestApi
75     public static final int REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING = 0;
76     /**
77      * Registered on home network.
78      * @hide
79      */
80     @SystemApi @TestApi
81     public static final int REGISTRATION_STATE_HOME = 1;
82     /**
83      * Not registered. The device is currently searching a new operator to register.
84      * @hide
85      */
86     @SystemApi @TestApi
87     public static final int REGISTRATION_STATE_NOT_REGISTERED_SEARCHING = 2;
88     /**
89      * Registration denied.
90      * @hide
91      */
92     @SystemApi @TestApi
93     public static final int REGISTRATION_STATE_DENIED = 3;
94     /**
95      * Registration state is unknown.
96      * @hide
97      */
98     @SystemApi @TestApi
99     public static final int REGISTRATION_STATE_UNKNOWN = 4;
100     /**
101      * Registered on roaming network.
102      * @hide
103      */
104     @SystemApi @TestApi
105     public static final int REGISTRATION_STATE_ROAMING = 5;
106 
107     /** @hide */
108     @Retention(RetentionPolicy.SOURCE)
109     @IntDef(prefix = "NR_STATE_",
110             value = {NR_STATE_NONE, NR_STATE_RESTRICTED, NR_STATE_NOT_RESTRICTED,
111                     NR_STATE_CONNECTED})
112     public @interface NRState {}
113 
114     /**
115      * The device isn't camped on an LTE cell or the LTE cell doesn't support E-UTRA-NR
116      * Dual Connectivity(EN-DC).
117      */
118     public static final int NR_STATE_NONE = 0;
119 
120     /**
121      * The device is camped on an LTE cell that supports E-UTRA-NR Dual Connectivity(EN-DC) but
122      * either the use of dual connectivity with NR(DCNR) is restricted or NR is not supported by
123      * the selected PLMN.
124      */
125     public static final int NR_STATE_RESTRICTED = 1;
126 
127     /**
128      * The device is camped on an LTE cell that supports E-UTRA-NR Dual Connectivity(EN-DC) and both
129      * the use of dual connectivity with NR(DCNR) is not restricted and NR is supported by the
130      * selected PLMN.
131      */
132     public static final int NR_STATE_NOT_RESTRICTED = 2;
133 
134     /**
135      * The device is camped on an LTE cell that supports E-UTRA-NR Dual Connectivity(EN-DC) and
136      * also connected to at least one 5G cell as a secondary serving cell.
137      */
138     public static final int NR_STATE_CONNECTED = 3;
139 
140     /**
141      * Supported service type
142      * @hide
143      */
144     @Retention(RetentionPolicy.SOURCE)
145     @IntDef(prefix = "SERVICE_TYPE_",
146             value = {SERVICE_TYPE_UNKNOWN, SERVICE_TYPE_VOICE, SERVICE_TYPE_DATA, SERVICE_TYPE_SMS,
147                     SERVICE_TYPE_VIDEO, SERVICE_TYPE_EMERGENCY})
148     public @interface ServiceType {}
149 
150     /**
151      * Unknown service
152      */
153     public static final int SERVICE_TYPE_UNKNOWN    = 0;
154 
155     /**
156      * Voice service
157      */
158     public static final int SERVICE_TYPE_VOICE      = 1;
159 
160     /**
161      * Data service
162      */
163     public static final int SERVICE_TYPE_DATA       = 2;
164 
165     /**
166      * SMS service
167      */
168     public static final int SERVICE_TYPE_SMS        = 3;
169 
170     /**
171      * Video service
172      */
173     public static final int SERVICE_TYPE_VIDEO      = 4;
174 
175     /**
176      * Emergency service
177      */
178     public static final int SERVICE_TYPE_EMERGENCY  = 5;
179 
180     @Domain
181     private final int mDomain;
182 
183     @TransportType
184     private final int mTransportType;
185 
186     @RegistrationState
187     private final int mRegistrationState;
188 
189     /**
190      * Save the {@link ServiceState.RoamingType roaming type}. it can be overridden roaming type
191      * from resource overlay or carrier config.
192      */
193     @ServiceState.RoamingType
194     private int mRoamingType;
195 
196     @NetworkType
197     private int mAccessNetworkTechnology;
198 
199     @NRState
200     private int mNrState;
201 
202     private final int mRejectCause;
203 
204     private final boolean mEmergencyOnly;
205 
206     @ServiceType
207     private final ArrayList<Integer> mAvailableServices;
208 
209     @Nullable
210     private CellIdentity mCellIdentity;
211 
212     @Nullable
213     private VoiceSpecificRegistrationInfo mVoiceSpecificInfo;
214 
215     @Nullable
216     private DataSpecificRegistrationInfo mDataSpecificInfo;
217 
218     @NonNull
219     private String mRplmn;
220 
221     /**
222      * @param domain Network domain. Must be a {@link Domain}. For transport type
223      * {@link AccessNetworkConstants#TRANSPORT_TYPE_WLAN}, this must set to {@link #DOMAIN_PS}.
224      * @param transportType Transport type.
225      * @param registrationState Network registration state. For transport type
226      * {@link AccessNetworkConstants#TRANSPORT_TYPE_WLAN}, only
227      * {@link #REGISTRATION_STATE_HOME} and {@link #REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING}
228      * are valid states.
229      * @param accessNetworkTechnology Access network technology.For transport type
230      * {@link AccessNetworkConstants#TRANSPORT_TYPE_WLAN}, set to
231      * {@link TelephonyManager#NETWORK_TYPE_IWLAN}.
232      * @param rejectCause Reason for denial if the registration state is
233      * {@link #REGISTRATION_STATE_DENIED}. Depending on {@code accessNetworkTechnology}, the values
234      * 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
235      * A.S0001 6.2.2.44 for CDMA. If the reject cause is not supported or unknown, set it to 0.
236      * // TODO: Add IWLAN reject cause reference
237      * @param emergencyOnly True if this registration is for emergency only.
238      * @param availableServices The list of the supported services.
239      * @param cellIdentity The identity representing a unique cell or wifi AP. Set to null if the
240      * information is not available.
241      * @param rplmn the registered plmn or the last plmn for attempted registration if reg failed.
242      */
NetworkRegistrationInfo(@omain int domain, @TransportType int transportType, @RegistrationState int registrationState, @NetworkType int accessNetworkTechnology, int rejectCause, boolean emergencyOnly, @Nullable @ServiceType List<Integer> availableServices, @Nullable CellIdentity cellIdentity, @Nullable String rplmn)243     private NetworkRegistrationInfo(@Domain int domain, @TransportType int transportType,
244                                    @RegistrationState int registrationState,
245                                    @NetworkType int accessNetworkTechnology, int rejectCause,
246                                    boolean emergencyOnly,
247                                    @Nullable @ServiceType List<Integer> availableServices,
248                                    @Nullable CellIdentity cellIdentity, @Nullable String rplmn) {
249         mDomain = domain;
250         mTransportType = transportType;
251         mRegistrationState = registrationState;
252         mRoamingType = (registrationState == REGISTRATION_STATE_ROAMING)
253                 ? ServiceState.ROAMING_TYPE_UNKNOWN : ServiceState.ROAMING_TYPE_NOT_ROAMING;
254         mAccessNetworkTechnology = accessNetworkTechnology;
255         mRejectCause = rejectCause;
256         mAvailableServices = (availableServices != null)
257                 ? new ArrayList<>(availableServices) : new ArrayList<>();
258         mCellIdentity = cellIdentity;
259         mEmergencyOnly = emergencyOnly;
260         mNrState = NR_STATE_NONE;
261         mRplmn = rplmn;
262     }
263 
264     /**
265      * Constructor for voice network registration info.
266      * @hide
267      */
NetworkRegistrationInfo(int domain, @TransportType int transportType, int registrationState, int accessNetworkTechnology, int rejectCause, boolean emergencyOnly, @Nullable List<Integer> availableServices, @Nullable CellIdentity cellIdentity, @Nullable String rplmn, boolean cssSupported, int roamingIndicator, int systemIsInPrl, int defaultRoamingIndicator)268     public NetworkRegistrationInfo(int domain, @TransportType int transportType,
269                                    int registrationState, int accessNetworkTechnology,
270                                    int rejectCause, boolean emergencyOnly,
271                                    @Nullable List<Integer> availableServices,
272                                    @Nullable CellIdentity cellIdentity, @Nullable String rplmn,
273                                    boolean cssSupported, int roamingIndicator, int systemIsInPrl,
274                                    int defaultRoamingIndicator) {
275         this(domain, transportType, registrationState, accessNetworkTechnology, rejectCause,
276                 emergencyOnly, availableServices, cellIdentity, rplmn);
277 
278         mVoiceSpecificInfo = new VoiceSpecificRegistrationInfo(cssSupported, roamingIndicator,
279                 systemIsInPrl, defaultRoamingIndicator);
280     }
281 
282     /**
283      * Constructor for data network registration info.
284      * @hide
285      */
NetworkRegistrationInfo(int domain, @TransportType int transportType, int registrationState, int accessNetworkTechnology, int rejectCause, boolean emergencyOnly, @Nullable List<Integer> availableServices, @Nullable CellIdentity cellIdentity, @Nullable String rplmn, int maxDataCalls, boolean isDcNrRestricted, boolean isNrAvailable, boolean isEndcAvailable, LteVopsSupportInfo lteVopsSupportInfo, boolean isUsingCarrierAggregation)286     public NetworkRegistrationInfo(int domain, @TransportType int transportType,
287                                    int registrationState, int accessNetworkTechnology,
288                                    int rejectCause, boolean emergencyOnly,
289                                    @Nullable List<Integer> availableServices,
290                                    @Nullable CellIdentity cellIdentity, @Nullable String rplmn,
291                                    int maxDataCalls, boolean isDcNrRestricted,
292                                    boolean isNrAvailable, boolean isEndcAvailable,
293                                    LteVopsSupportInfo lteVopsSupportInfo,
294                                    boolean isUsingCarrierAggregation) {
295         this(domain, transportType, registrationState, accessNetworkTechnology, rejectCause,
296                 emergencyOnly, availableServices, cellIdentity, rplmn);
297         mDataSpecificInfo = new DataSpecificRegistrationInfo(
298                 maxDataCalls, isDcNrRestricted, isNrAvailable, isEndcAvailable, lteVopsSupportInfo,
299                 isUsingCarrierAggregation);
300         updateNrState();
301     }
302 
NetworkRegistrationInfo(Parcel source)303     private NetworkRegistrationInfo(Parcel source) {
304         mDomain = source.readInt();
305         mTransportType = source.readInt();
306         mRegistrationState = source.readInt();
307         mRoamingType = source.readInt();
308         mAccessNetworkTechnology = source.readInt();
309         mRejectCause = source.readInt();
310         mEmergencyOnly = source.readBoolean();
311         mAvailableServices = new ArrayList<>();
312         source.readList(mAvailableServices, Integer.class.getClassLoader());
313         mCellIdentity = source.readParcelable(CellIdentity.class.getClassLoader());
314         mVoiceSpecificInfo = source.readParcelable(
315                 VoiceSpecificRegistrationInfo.class.getClassLoader());
316         mDataSpecificInfo = source.readParcelable(
317                 DataSpecificRegistrationInfo.class.getClassLoader());
318         mNrState = source.readInt();
319         mRplmn = source.readString();
320     }
321 
322     /**
323      * Constructor from another network registration info
324      *
325      * @param nri Another network registration info
326      * @hide
327      */
NetworkRegistrationInfo(NetworkRegistrationInfo nri)328     public NetworkRegistrationInfo(NetworkRegistrationInfo nri) {
329         mDomain = nri.mDomain;
330         mTransportType = nri.mTransportType;
331         mRegistrationState = nri.mRegistrationState;
332         mRoamingType = nri.mRoamingType;
333         mAccessNetworkTechnology = nri.mAccessNetworkTechnology;
334         mRejectCause = nri.mRejectCause;
335         mEmergencyOnly = nri.mEmergencyOnly;
336         mAvailableServices = new ArrayList<>(nri.mAvailableServices);
337         if (nri.mCellIdentity != null) {
338             Parcel p = Parcel.obtain();
339             nri.mCellIdentity.writeToParcel(p, 0);
340             p.setDataPosition(0);
341             // TODO: Instead of doing this, we should create a formal way for cloning cell identity.
342             // Cell identity is not an immutable object so we have to deep copy it.
343             mCellIdentity = CellIdentity.CREATOR.createFromParcel(p);
344         }
345 
346         if (nri.mVoiceSpecificInfo != null) {
347             mVoiceSpecificInfo = new VoiceSpecificRegistrationInfo(nri.mVoiceSpecificInfo);
348         }
349         if (nri.mDataSpecificInfo != null) {
350             mDataSpecificInfo = new DataSpecificRegistrationInfo(nri.mDataSpecificInfo);
351         }
352         mNrState = nri.mNrState;
353         mRplmn = nri.mRplmn;
354     }
355 
356     /**
357      * @return The transport type.
358      */
getTransportType()359     public @TransportType int getTransportType() { return mTransportType; }
360 
361     /**
362      * @return The network domain.
363      */
getDomain()364     public @Domain int getDomain() { return mDomain; }
365 
366     /**
367      * Get the 5G NR connection state.
368      *
369      * @return the 5G NR connection state.
370      * @hide
371      */
getNrState()372     public @NRState int getNrState() {
373         return mNrState;
374     }
375 
376     /** @hide */
setNrState(@RState int nrState)377     public void setNrState(@NRState int nrState) {
378         mNrState = nrState;
379     }
380 
381     /**
382      * @return The registration state.
383      *
384      * @hide
385      */
386     @SystemApi @TestApi
getRegistrationState()387     public @RegistrationState int getRegistrationState() {
388         return mRegistrationState;
389     }
390 
391     /**
392      * @return {@code true} if registered on roaming network, {@code false} otherwise.
393      */
isRegistered()394     public boolean isRegistered() {
395         return mRegistrationState == REGISTRATION_STATE_HOME
396                 || mRegistrationState == REGISTRATION_STATE_ROAMING;
397     }
398 
399     /**
400      * @return {@code true} if registered on roaming network, {@code false} otherwise.
401      */
isSearching()402     public boolean isSearching() {
403         return mRegistrationState == REGISTRATION_STATE_NOT_REGISTERED_SEARCHING;
404     }
405 
406     /**
407      * Get the PLMN-ID for this Network Registration, also known as the RPLMN.
408      *
409      * <p>If the device is registered, this will return the registered PLMN-ID. If registration
410      * has failed, then this will return the PLMN ID of the last attempted registration. If the
411      * device is not registered, or if is registered to a non-3GPP radio technology, then this
412      * will return null.
413      *
414      * <p>See 3GPP TS 23.122 for further information about the Registered PLMN.
415      *
416      * @return the registered PLMN-ID or null.
417      */
getRegisteredPlmn()418     @Nullable public String getRegisteredPlmn() {
419         return mRplmn;
420     }
421 
422     /**
423      * @return {@code true} if registered on roaming network, {@code false} otherwise.
424      */
isRoaming()425     public boolean isRoaming() {
426         return mRoamingType != ServiceState.ROAMING_TYPE_NOT_ROAMING;
427     }
428 
429     /**
430      * @hide
431      * @return {@code true} if in service.
432      */
isInService()433     public boolean isInService() {
434         return mRegistrationState == REGISTRATION_STATE_HOME
435                 || mRegistrationState == REGISTRATION_STATE_ROAMING;
436     }
437 
438     /**
439      * Set {@link ServiceState.RoamingType roaming type}. This could override
440      * roaming type based on resource overlay or carrier config.
441      * @hide
442      */
setRoamingType(@erviceState.RoamingType int roamingType)443     public void setRoamingType(@ServiceState.RoamingType int roamingType) {
444         mRoamingType = roamingType;
445     }
446 
447     /**
448      * @return the current network roaming type.
449      * @hide
450      */
451     @SystemApi @TestApi
getRoamingType()452     public @ServiceState.RoamingType int getRoamingType() {
453         return mRoamingType;
454     }
455 
456     /**
457      * @return Whether emergency is enabled.
458      * @hide
459      */
460     @SystemApi @TestApi
isEmergencyEnabled()461     public boolean isEmergencyEnabled() { return mEmergencyOnly; }
462 
463     /**
464      * @return List of available service types.
465      */
466     @NonNull
467     @ServiceType
getAvailableServices()468     public List<Integer> getAvailableServices() {
469         return Collections.unmodifiableList(mAvailableServices);
470     }
471 
472     /**
473      * @return The access network technology {@link NetworkType}.
474      */
getAccessNetworkTechnology()475     public @NetworkType int getAccessNetworkTechnology() {
476         return mAccessNetworkTechnology;
477     }
478 
479     /**
480      * override the access network technology {@link NetworkType} e.g, rat ratchet.
481      * @hide
482      */
setAccessNetworkTechnology(@etworkType int tech)483     public void setAccessNetworkTechnology(@NetworkType int tech) {
484         if (tech == TelephonyManager.NETWORK_TYPE_LTE_CA) {
485             // For old device backward compatibility support
486             tech = TelephonyManager.NETWORK_TYPE_LTE;
487             if (mDataSpecificInfo != null) {
488                 mDataSpecificInfo.setIsUsingCarrierAggregation(true);
489             }
490         }
491         mAccessNetworkTechnology = tech;
492     }
493 
494     /**
495      * @return Reason for denial if the registration state is {@link #REGISTRATION_STATE_DENIED}.
496      * Depending on {@code accessNetworkTechnology}, the values are defined in 3GPP TS 24.008
497      * 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
498      * @hide
499      */
500     @SystemApi @TestApi
getRejectCause()501     public int getRejectCause() {
502         return mRejectCause;
503     }
504 
505     /**
506      * @return The cell information.
507      */
508     @Nullable
getCellIdentity()509     public CellIdentity getCellIdentity() {
510         return mCellIdentity;
511     }
512 
513     /**
514      * @hide
515      */
516     @Nullable
getVoiceSpecificInfo()517     public VoiceSpecificRegistrationInfo getVoiceSpecificInfo() {
518         return mVoiceSpecificInfo;
519     }
520 
521     /**
522      * @return Data registration related info
523      * @hide
524      */
525     @Nullable
526     @SystemApi @TestApi
getDataSpecificInfo()527     public DataSpecificRegistrationInfo getDataSpecificInfo() {
528         return mDataSpecificInfo;
529     }
530 
531     @Override
describeContents()532     public int describeContents() {
533         return 0;
534     }
535 
536     /**
537      * Convert service type to string
538      *
539      * @hide
540      *
541      * @param serviceType The service type
542      * @return The service type in string format
543      */
serviceTypeToString(@erviceType int serviceType)544     public static String serviceTypeToString(@ServiceType int serviceType) {
545         switch (serviceType) {
546             case SERVICE_TYPE_VOICE: return "VOICE";
547             case SERVICE_TYPE_DATA: return "DATA";
548             case SERVICE_TYPE_SMS: return "SMS";
549             case SERVICE_TYPE_VIDEO: return "VIDEO";
550             case SERVICE_TYPE_EMERGENCY: return "EMERGENCY";
551         }
552         return "Unknown service type " + serviceType;
553     }
554 
555     /**
556      * Convert registration state to string
557      *
558      * @hide
559      *
560      * @param registrationState The registration state
561      * @return The reg state in string
562      */
registrationStateToString(@egistrationState int registrationState)563     public static String registrationStateToString(@RegistrationState int registrationState) {
564         switch (registrationState) {
565             case REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING: return "NOT_REG_OR_SEARCHING";
566             case REGISTRATION_STATE_HOME: return "HOME";
567             case REGISTRATION_STATE_NOT_REGISTERED_SEARCHING: return "NOT_REG_SEARCHING";
568             case REGISTRATION_STATE_DENIED: return "DENIED";
569             case REGISTRATION_STATE_UNKNOWN: return "UNKNOWN";
570             case REGISTRATION_STATE_ROAMING: return "ROAMING";
571         }
572         return "Unknown reg state " + registrationState;
573     }
574 
nrStateToString(@RState int nrState)575     private static String nrStateToString(@NRState int nrState) {
576         switch (nrState) {
577             case NR_STATE_RESTRICTED:
578                 return "RESTRICTED";
579             case NR_STATE_NOT_RESTRICTED:
580                 return "NOT_RESTRICTED";
581             case NR_STATE_CONNECTED:
582                 return "CONNECTED";
583             default:
584                 return "NONE";
585         }
586     }
587 
588     /** @hide */
domainToString(@omain int domain)589     static @NonNull String domainToString(@Domain int domain) {
590         switch (domain) {
591             case DOMAIN_CS: return "CS";
592             case DOMAIN_PS: return "PS";
593             case DOMAIN_CS_PS: return "CS_PS";
594             default: return "UNKNOWN";
595         }
596     }
597 
598     @NonNull
599     @Override
toString()600     public String toString() {
601         return new StringBuilder("NetworkRegistrationInfo{")
602                 .append(" domain=").append(domainToString(mDomain))
603                 .append(" transportType=").append(
604                         AccessNetworkConstants.transportTypeToString(mTransportType))
605                 .append(" registrationState=").append(registrationStateToString(mRegistrationState))
606                 .append(" roamingType=").append(ServiceState.roamingTypeToString(mRoamingType))
607                 .append(" accessNetworkTechnology=")
608                 .append(TelephonyManager.getNetworkTypeName(mAccessNetworkTechnology))
609                 .append(" rejectCause=").append(mRejectCause)
610                 .append(" emergencyEnabled=").append(mEmergencyOnly)
611                 .append(" availableServices=").append("[" + (mAvailableServices != null
612                         ? mAvailableServices.stream().map(type -> serviceTypeToString(type))
613                         .collect(Collectors.joining(",")) : null) + "]")
614                 .append(" cellIdentity=").append(mCellIdentity)
615                 .append(" voiceSpecificInfo=").append(mVoiceSpecificInfo)
616                 .append(" dataSpecificInfo=").append(mDataSpecificInfo)
617                 .append(" nrState=").append(nrStateToString(mNrState))
618                 .append(" rRplmn=").append(mRplmn)
619                 .append("}").toString();
620     }
621 
622     @Override
hashCode()623     public int hashCode() {
624         return Objects.hash(mDomain, mTransportType, mRegistrationState, mRoamingType,
625                 mAccessNetworkTechnology, mRejectCause, mEmergencyOnly, mAvailableServices,
626                 mCellIdentity, mVoiceSpecificInfo, mDataSpecificInfo, mNrState, mRplmn);
627     }
628 
629     @Override
equals(@ullable Object o)630     public boolean equals(@Nullable Object o) {
631         if (this == o) return true;
632 
633         if (!(o instanceof NetworkRegistrationInfo)) {
634             return false;
635         }
636 
637         NetworkRegistrationInfo other = (NetworkRegistrationInfo) o;
638         return mDomain == other.mDomain
639                 && mTransportType == other.mTransportType
640                 && mRegistrationState == other.mRegistrationState
641                 && mRoamingType == other.mRoamingType
642                 && mAccessNetworkTechnology == other.mAccessNetworkTechnology
643                 && mRejectCause == other.mRejectCause
644                 && mEmergencyOnly == other.mEmergencyOnly
645                 && mAvailableServices.equals(other.mAvailableServices)
646                 && Objects.equals(mCellIdentity, other.mCellIdentity)
647                 && Objects.equals(mVoiceSpecificInfo, other.mVoiceSpecificInfo)
648                 && Objects.equals(mDataSpecificInfo, other.mDataSpecificInfo)
649                 && TextUtils.equals(mRplmn, other.mRplmn)
650                 && mNrState == other.mNrState;
651     }
652 
653     /**
654      * @hide
655      */
656     @Override
657     @SystemApi @TestApi
writeToParcel(Parcel dest, int flags)658     public void writeToParcel(Parcel dest, int flags) {
659         dest.writeInt(mDomain);
660         dest.writeInt(mTransportType);
661         dest.writeInt(mRegistrationState);
662         dest.writeInt(mRoamingType);
663         dest.writeInt(mAccessNetworkTechnology);
664         dest.writeInt(mRejectCause);
665         dest.writeBoolean(mEmergencyOnly);
666         dest.writeList(mAvailableServices);
667         dest.writeParcelable(mCellIdentity, 0);
668         dest.writeParcelable(mVoiceSpecificInfo, 0);
669         dest.writeParcelable(mDataSpecificInfo, 0);
670         dest.writeInt(mNrState);
671         dest.writeString(mRplmn);
672     }
673 
674     /**
675      * Use the 5G NR Non-Standalone indicators from the network registration state to update the
676      * NR state. There are 3 indicators in the network registration state:
677      *
678      * 1. if E-UTRA-NR Dual Connectivity (EN-DC) is supported by the primary serving cell.
679      * 2. if NR is supported by the selected PLMN.
680      * 3. if the use of dual connectivity with NR is restricted.
681      *
682      * The network has 5G NR capability if E-UTRA-NR Dual Connectivity is supported by the primary
683      * serving cell.
684      *
685      * The use of NR 5G is not restricted If the network has 5G NR capability and both the use of
686      * DCNR is not restricted and NR is supported by the selected PLMN. Otherwise the use of 5G
687      * NR is restricted.
688      *
689      * @hide
690      */
updateNrState()691     public void updateNrState() {
692         mNrState = NR_STATE_NONE;
693         if (mDataSpecificInfo != null && mDataSpecificInfo.isEnDcAvailable) {
694             if (!mDataSpecificInfo.isDcNrRestricted && mDataSpecificInfo.isNrAvailable) {
695                 mNrState = NR_STATE_NOT_RESTRICTED;
696             } else {
697                 mNrState = NR_STATE_RESTRICTED;
698             }
699         }
700     }
701 
702     public static final @NonNull Parcelable.Creator<NetworkRegistrationInfo> CREATOR =
703             new Parcelable.Creator<NetworkRegistrationInfo>() {
704                 @Override
705                 public NetworkRegistrationInfo createFromParcel(Parcel source) {
706                     return new NetworkRegistrationInfo(source);
707                 }
708 
709                 @Override
710                 public NetworkRegistrationInfo[] newArray(int size) {
711                     return new NetworkRegistrationInfo[size];
712                 }
713             };
714 
715     /**
716      * @hide
717      */
sanitizeLocationInfo()718     public NetworkRegistrationInfo sanitizeLocationInfo() {
719         NetworkRegistrationInfo result = copy();
720         result.mCellIdentity = null;
721         return result;
722     }
723 
copy()724     private NetworkRegistrationInfo copy() {
725         Parcel p = Parcel.obtain();
726         this.writeToParcel(p, 0);
727         p.setDataPosition(0);
728         NetworkRegistrationInfo result = new NetworkRegistrationInfo(p);
729         p.recycle();
730         return result;
731     }
732 
733     /**
734      * Provides a convenient way to set the fields of a {@link NetworkRegistrationInfo} when
735      * creating a new instance.
736      *
737      * <p>The example below shows how you might create a new {@code NetworkRegistrationInfo}:
738      *
739      * <pre><code>
740      *
741      * NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
742      *     .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
743      *     .setRegistrationState(REGISTRATION_STATE_HOME)
744      *     .build();
745      * </code></pre>
746      * @hide
747      */
748     @SystemApi @TestApi
749     public static final class Builder {
750         @Domain
751         private int mDomain;
752 
753         @TransportType
754         private int mTransportType;
755 
756         @RegistrationState
757         private int mRegistrationState;
758 
759         @NetworkType
760         private int mAccessNetworkTechnology;
761 
762         private int mRejectCause;
763 
764         private boolean mEmergencyOnly;
765 
766         @ServiceType
767         private List<Integer> mAvailableServices;
768 
769         @Nullable
770         private CellIdentity mCellIdentity;
771 
772         @NonNull
773         private String mRplmn = "";
774 
775         /**
776          * Default constructor for Builder.
777          */
Builder()778         public Builder() {}
779 
780         /**
781          * Set the network domain.
782          *
783          * @param domain Network domain.
784          *
785          * @return The same instance of the builder.
786          */
setDomain(@omain int domain)787         public @NonNull Builder setDomain(@Domain int domain) {
788             mDomain = domain;
789             return this;
790         }
791 
792         /**
793          * Set the transport type.
794          *
795          * @param transportType Transport type.
796          *
797          * @return The same instance of the builder.
798          */
setTransportType(@ransportType int transportType)799         public @NonNull Builder setTransportType(@TransportType int transportType) {
800             mTransportType = transportType;
801             return this;
802         }
803 
804         /**
805          * Set the registration state.
806          *
807          * @param registrationState The registration state.
808          *
809          * @return The same instance of the builder.
810          */
setRegistrationState(@egistrationState int registrationState)811         public @NonNull Builder setRegistrationState(@RegistrationState int registrationState) {
812             mRegistrationState = registrationState;
813             return this;
814         }
815 
816         /**
817          * Set tne access network technology.
818          *
819          * @return The same instance of the builder.
820          *
821          * @param accessNetworkTechnology The access network technology
822          */
setAccessNetworkTechnology( @etworkType int accessNetworkTechnology)823         public @NonNull Builder setAccessNetworkTechnology(
824                 @NetworkType int accessNetworkTechnology) {
825             mAccessNetworkTechnology = accessNetworkTechnology;
826             return this;
827         }
828 
829         /**
830          * Set the network reject cause.
831          *
832          * @param rejectCause Reason for denial if the registration state is
833          * {@link #REGISTRATION_STATE_DENIED}.Depending on {@code accessNetworkTechnology}, the
834          * values are defined in 3GPP TS 24.008 10.5.3.6 for UMTS, 3GPP TS 24.301 9.9.3.9 for LTE,
835          * and 3GPP2 A.S0001 6.2.2.44 for CDMA. If the reject cause is not supported or unknown, set
836          * it to 0.
837          *
838          * @return The same instance of the builder.
839          */
setRejectCause(int rejectCause)840         public @NonNull Builder setRejectCause(int rejectCause) {
841             mRejectCause = rejectCause;
842             return this;
843         }
844 
845         /**
846          * Set emergency only.
847          *
848          * @param emergencyOnly True if this network registration is for emergency use only.
849          *
850          * @return The same instance of the builder.
851          * @hide
852          */
853         @SystemApi @TestApi
setEmergencyOnly(boolean emergencyOnly)854         public @NonNull Builder setEmergencyOnly(boolean emergencyOnly) {
855             mEmergencyOnly = emergencyOnly;
856             return this;
857         }
858 
859         /**
860          * Set the available services.
861          *
862          * @param availableServices Available services.
863          *
864          * @return The same instance of the builder.
865          * @hide
866          */
867         @SystemApi @TestApi
setAvailableServices( @onNull @erviceType List<Integer> availableServices)868         public @NonNull Builder setAvailableServices(
869                 @NonNull @ServiceType List<Integer> availableServices) {
870             mAvailableServices = availableServices;
871             return this;
872         }
873 
874         /**
875          * Set the cell identity.
876          *
877          * @param cellIdentity The cell identity.
878          *
879          * @return The same instance of the builder.
880          * @hide
881          */
882         @SystemApi @TestApi
setCellIdentity(@ullable CellIdentity cellIdentity)883         public @NonNull Builder setCellIdentity(@Nullable CellIdentity cellIdentity) {
884             mCellIdentity = cellIdentity;
885             return this;
886         }
887 
888         /**
889          * Set the registered PLMN.
890          *
891          * @param rplmn the registered plmn.
892          *
893          * @return The same instance of the builder.
894          */
setRegisteredPlmn(@ullable String rplmn)895         public @NonNull Builder setRegisteredPlmn(@Nullable String rplmn) {
896             mRplmn = rplmn;
897             return this;
898         }
899 
900         /**
901          * Build the NetworkRegistrationInfo.
902          * @return the NetworkRegistrationInfo object.
903          * @hide
904          */
905         @SystemApi @TestApi
build()906         public @NonNull NetworkRegistrationInfo build() {
907             return new NetworkRegistrationInfo(mDomain, mTransportType, mRegistrationState,
908                     mAccessNetworkTechnology, mRejectCause, mEmergencyOnly, mAvailableServices,
909                     mCellIdentity, mRplmn);
910         }
911     }
912 }
913