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
17package android.telephony;
18
19import android.annotation.IntDef;
20import android.annotation.Nullable;
21import android.os.Parcel;
22import android.os.Parcelable;
23
24import java.lang.annotation.Retention;
25import java.lang.annotation.RetentionPolicy;
26import java.util.Arrays;
27import java.util.Objects;
28
29/**
30 * Description of a mobile network registration state
31 * @hide
32 */
33public class NetworkRegistrationState implements Parcelable {
34    /**
35     * Network domain
36     * @hide
37     */
38    @Retention(RetentionPolicy.SOURCE)
39    @IntDef(prefix = "DOMAIN_", value = {DOMAIN_CS, DOMAIN_PS})
40    public @interface Domain {}
41
42    /** Circuit switching domain */
43    public static final int DOMAIN_CS = 1;
44    /** Packet switching domain */
45    public static final int DOMAIN_PS = 2;
46
47    /**
48     * Registration state
49     * @hide
50     */
51    @Retention(RetentionPolicy.SOURCE)
52    @IntDef(prefix = "REG_STATE_",
53            value = {REG_STATE_NOT_REG_NOT_SEARCHING, REG_STATE_HOME, REG_STATE_NOT_REG_SEARCHING,
54                    REG_STATE_DENIED, REG_STATE_UNKNOWN, REG_STATE_ROAMING})
55    public @interface RegState {}
56
57    /** Not registered. The device is not currently searching a new operator to register */
58    public static final int REG_STATE_NOT_REG_NOT_SEARCHING = 0;
59    /** Registered on home network */
60    public static final int REG_STATE_HOME = 1;
61    /** Not registered. The device is currently searching a new operator to register */
62    public static final int REG_STATE_NOT_REG_SEARCHING = 2;
63    /** Registration denied */
64    public static final int REG_STATE_DENIED = 3;
65    /** Registration state is unknown */
66    public static final int REG_STATE_UNKNOWN = 4;
67    /** Registered on roaming network */
68    public static final int REG_STATE_ROAMING = 5;
69
70    /**
71     * Supported service type
72     * @hide
73     */
74    @Retention(RetentionPolicy.SOURCE)
75    @IntDef(prefix = "SERVICE_TYPE_",
76            value = {SERVICE_TYPE_VOICE, SERVICE_TYPE_DATA, SERVICE_TYPE_SMS, SERVICE_TYPE_VIDEO,
77                    SERVICE_TYPE_EMERGENCY})
78    public @interface ServiceType {}
79
80    public static final int SERVICE_TYPE_VOICE = 1;
81    public static final int SERVICE_TYPE_DATA = 2;
82    public static final int SERVICE_TYPE_SMS = 3;
83    public static final int SERVICE_TYPE_VIDEO = 4;
84    public static final int SERVICE_TYPE_EMERGENCY = 5;
85
86    /** {@link AccessNetworkConstants.TransportType}*/
87    private final int mTransportType;
88
89    @Domain
90    private final int mDomain;
91
92    @RegState
93    private final int mRegState;
94
95    private final int mAccessNetworkTechnology;
96
97    private final int mReasonForDenial;
98
99    private final boolean mEmergencyOnly;
100
101    private final int[] mAvailableServices;
102
103    @Nullable
104    private final CellIdentity mCellIdentity;
105
106    @Nullable
107    private VoiceSpecificRegistrationStates mVoiceSpecificStates;
108
109    @Nullable
110    private DataSpecificRegistrationStates mDataSpecificStates;
111
112    /**
113     * @param transportType Transport type. Must be {@link AccessNetworkConstants.TransportType}
114     * @param domain Network domain. Must be DOMAIN_CS or DOMAIN_PS.
115     * @param regState Network registration state.
116     * @param accessNetworkTechnology See TelephonyManager NETWORK_TYPE_XXXX.
117     * @param reasonForDenial Reason for denial if the registration state is DENIED.
118     * @param availableServices The supported service.
119     * @param cellIdentity The identity representing a unique cell
120     */
121    public NetworkRegistrationState(int transportType, int domain, int regState,
122            int accessNetworkTechnology, int reasonForDenial, boolean emergencyOnly,
123            int[] availableServices, @Nullable CellIdentity cellIdentity) {
124        mTransportType = transportType;
125        mDomain = domain;
126        mRegState = regState;
127        mAccessNetworkTechnology = accessNetworkTechnology;
128        mReasonForDenial = reasonForDenial;
129        mAvailableServices = availableServices;
130        mCellIdentity = cellIdentity;
131        mEmergencyOnly = emergencyOnly;
132    }
133
134    /**
135     * Constructor for voice network registration states.
136     * @hide
137     */
138    public NetworkRegistrationState(int transportType, int domain, int regState,
139            int accessNetworkTechnology, int reasonForDenial, boolean emergencyOnly,
140            int[] availableServices, @Nullable CellIdentity cellIdentity, boolean cssSupported,
141            int roamingIndicator, int systemIsInPrl, int defaultRoamingIndicator) {
142        this(transportType, domain, regState, accessNetworkTechnology,
143                reasonForDenial, emergencyOnly, availableServices, cellIdentity);
144
145        mVoiceSpecificStates = new VoiceSpecificRegistrationStates(cssSupported, roamingIndicator,
146                systemIsInPrl, defaultRoamingIndicator);
147    }
148
149    /**
150     * Constructor for data network registration states.
151     * @hide
152     */
153    public NetworkRegistrationState(int transportType, int domain, int regState,
154            int accessNetworkTechnology, int reasonForDenial, boolean emergencyOnly,
155            int[] availableServices, @Nullable CellIdentity cellIdentity, int maxDataCalls) {
156        this(transportType, domain, regState, accessNetworkTechnology,
157                reasonForDenial, emergencyOnly, availableServices, cellIdentity);
158
159        mDataSpecificStates = new DataSpecificRegistrationStates(maxDataCalls);
160    }
161
162    protected NetworkRegistrationState(Parcel source) {
163        mTransportType = source.readInt();
164        mDomain = source.readInt();
165        mRegState = source.readInt();
166        mAccessNetworkTechnology = source.readInt();
167        mReasonForDenial = source.readInt();
168        mEmergencyOnly = source.readBoolean();
169        mAvailableServices = source.createIntArray();
170        mCellIdentity = source.readParcelable(CellIdentity.class.getClassLoader());
171        mVoiceSpecificStates = source.readParcelable(
172                VoiceSpecificRegistrationStates.class.getClassLoader());
173        mDataSpecificStates = source.readParcelable(
174                DataSpecificRegistrationStates.class.getClassLoader());
175    }
176
177    /**
178     * @return The transport type.
179     */
180    public int getTransportType() { return mTransportType; }
181
182    /**
183     * @return The network domain.
184     */
185    public @Domain int getDomain() { return mDomain; }
186
187    /**
188     * @return The registration state.
189     */
190    public @RegState int getRegState() {
191        return mRegState;
192    }
193
194    /**
195     * @return Whether emergency is enabled.
196     */
197    public boolean isEmergencyEnabled() { return mEmergencyOnly; }
198
199    /**
200     * @return List of available service types.
201     */
202    public int[] getAvailableServices() { return mAvailableServices; }
203
204    /**
205     * @return The access network technology. Must be one of TelephonyManager.NETWORK_TYPE_XXXX.
206     */
207    public int getAccessNetworkTechnology() {
208        return mAccessNetworkTechnology;
209    }
210
211    /**
212     * @return Reason for denial from network.
213     */
214    public int getReasonForDenial() {
215        return mReasonForDenial;
216    }
217
218    /**
219     * @return The cell information.
220     */
221    public CellIdentity getCellIdentity() {
222        return mCellIdentity;
223    }
224
225    /**
226     * @hide
227     */
228    @Nullable
229    public VoiceSpecificRegistrationStates getVoiceSpecificStates() {
230        return mVoiceSpecificStates;
231    }
232
233    /**
234     * @hide
235     */
236    @Nullable
237    public DataSpecificRegistrationStates getDataSpecificStates() {
238        return mDataSpecificStates;
239    }
240
241    @Override
242    public int describeContents() {
243        return 0;
244    }
245
246    private static String regStateToString(int regState) {
247        switch (regState) {
248            case REG_STATE_NOT_REG_NOT_SEARCHING: return "NOT_REG_NOT_SEARCHING";
249            case REG_STATE_HOME: return "HOME";
250            case REG_STATE_NOT_REG_SEARCHING: return "NOT_REG_SEARCHING";
251            case REG_STATE_DENIED: return "DENIED";
252            case REG_STATE_UNKNOWN: return "UNKNOWN";
253            case REG_STATE_ROAMING: return "ROAMING";
254        }
255        return "Unknown reg state " + regState;
256    }
257
258    @Override
259    public String toString() {
260        return new StringBuilder("NetworkRegistrationState{")
261                .append("transportType=").append(mTransportType)
262                .append(" domain=").append((mDomain == DOMAIN_CS) ? "CS" : "PS")
263                .append(" regState=").append(regStateToString(mRegState))
264                .append(" accessNetworkTechnology=")
265                .append(TelephonyManager.getNetworkTypeName(mAccessNetworkTechnology))
266                .append(" reasonForDenial=").append(mReasonForDenial)
267                .append(" emergencyEnabled=").append(mEmergencyOnly)
268                .append(" supportedServices=").append(mAvailableServices)
269                .append(" cellIdentity=").append(mCellIdentity)
270                .append(" voiceSpecificStates=").append(mVoiceSpecificStates)
271                .append(" dataSpecificStates=").append(mDataSpecificStates)
272                .append("}").toString();
273    }
274
275    @Override
276    public int hashCode() {
277        return Objects.hash(mTransportType, mDomain, mRegState, mAccessNetworkTechnology,
278                mReasonForDenial, mEmergencyOnly, mAvailableServices, mCellIdentity,
279                mVoiceSpecificStates, mDataSpecificStates);
280    }
281
282    @Override
283    public boolean equals(Object o) {
284        if (this == o) return true;
285
286        if (o == null || !(o instanceof NetworkRegistrationState)) {
287            return false;
288        }
289
290        NetworkRegistrationState other = (NetworkRegistrationState) o;
291        return mTransportType == other.mTransportType
292                && mDomain == other.mDomain
293                && mRegState == other.mRegState
294                && mAccessNetworkTechnology == other.mAccessNetworkTechnology
295                && mReasonForDenial == other.mReasonForDenial
296                && mEmergencyOnly == other.mEmergencyOnly
297                && (mAvailableServices == other.mAvailableServices
298                    || Arrays.equals(mAvailableServices, other.mAvailableServices))
299                && equals(mCellIdentity, other.mCellIdentity)
300                && equals(mVoiceSpecificStates, other.mVoiceSpecificStates)
301                && equals(mDataSpecificStates, other.mDataSpecificStates);
302    }
303
304    @Override
305    public void writeToParcel(Parcel dest, int flags) {
306        dest.writeInt(mTransportType);
307        dest.writeInt(mDomain);
308        dest.writeInt(mRegState);
309        dest.writeInt(mAccessNetworkTechnology);
310        dest.writeInt(mReasonForDenial);
311        dest.writeBoolean(mEmergencyOnly);
312        dest.writeIntArray(mAvailableServices);
313        dest.writeParcelable(mCellIdentity, 0);
314        dest.writeParcelable(mVoiceSpecificStates, 0);
315        dest.writeParcelable(mDataSpecificStates, 0);
316    }
317
318    public static final Parcelable.Creator<NetworkRegistrationState> CREATOR =
319            new Parcelable.Creator<NetworkRegistrationState>() {
320        @Override
321        public NetworkRegistrationState createFromParcel(Parcel source) {
322            return new NetworkRegistrationState(source);
323        }
324
325        @Override
326        public NetworkRegistrationState[] newArray(int size) {
327            return new NetworkRegistrationState[size];
328        }
329    };
330
331    private static boolean equals(Object o1, Object o2) {
332        if (o1 == o2) {
333            return true;
334        } else if (o1 == null) {
335            return false;
336        } else {
337            return o1.equals(o2);
338        }
339    }
340}
341