1 /*
2  * Copyright (C) 2022 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.ims.feature;
18 
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 import android.util.SparseArray;
24 
25 import java.lang.annotation.Retention;
26 import java.lang.annotation.RetentionPolicy;
27 
28 /**
29  * Provides details on why transmitting IMS traffic failed.
30  *
31  * @hide
32  */
33 public final class ConnectionFailureInfo implements Parcelable {
34 
35     /** @hide */
36     @Retention(RetentionPolicy.SOURCE)
37     @IntDef(
38         prefix = "REASON_",
39         value = {
40             REASON_NONE,
41             REASON_ACCESS_DENIED,
42             REASON_NAS_FAILURE,
43             REASON_RACH_FAILURE,
44             REASON_RLC_FAILURE,
45             REASON_RRC_REJECT,
46             REASON_RRC_TIMEOUT,
47             REASON_NO_SERVICE,
48             REASON_PDN_NOT_AVAILABLE,
49             REASON_RF_BUSY,
50             REASON_UNSPECIFIED
51         })
52     public @interface FailureReason {}
53 
54     /** Default value */
55     public static final int REASON_NONE = 0;
56     /** Access class check failed */
57     public static final int REASON_ACCESS_DENIED = 1;
58     /** 3GPP Non-access stratum failure */
59     public static final int REASON_NAS_FAILURE = 2;
60     /** Random access failure */
61     public static final int REASON_RACH_FAILURE = 3;
62     /** Radio link failure */
63     public static final int REASON_RLC_FAILURE = 4;
64     /** Radio connection establishment rejected by network */
65     public static final int REASON_RRC_REJECT = 5;
66     /** Radio connection establishment timed out */
67     public static final int REASON_RRC_TIMEOUT = 6;
68     /** Device currently not in service */
69     public static final int REASON_NO_SERVICE = 7;
70     /** The PDN is no more active */
71     public static final int REASON_PDN_NOT_AVAILABLE = 8;
72     /** Radio resource is busy with another subscription */
73     public static final int REASON_RF_BUSY = 9;
74     /** Unspecified reason */
75     public static final int REASON_UNSPECIFIED = 0xFFFF;
76 
77     private static final SparseArray<String> sReasonMap;
78     static {
79         sReasonMap = new SparseArray<>();
sReasonMap.set(REASON_NONE, "NONE")80         sReasonMap.set(REASON_NONE, "NONE");
sReasonMap.set(REASON_ACCESS_DENIED, "ACCESS_DENIED")81         sReasonMap.set(REASON_ACCESS_DENIED, "ACCESS_DENIED");
sReasonMap.set(REASON_NAS_FAILURE, "NAS_FAILURE")82         sReasonMap.set(REASON_NAS_FAILURE, "NAS_FAILURE");
sReasonMap.set(REASON_RACH_FAILURE, "RACH_FAILURE")83         sReasonMap.set(REASON_RACH_FAILURE, "RACH_FAILURE");
sReasonMap.set(REASON_RLC_FAILURE, "RLC_FAILURE")84         sReasonMap.set(REASON_RLC_FAILURE, "RLC_FAILURE");
sReasonMap.set(REASON_RRC_REJECT, "RRC_REJECT")85         sReasonMap.set(REASON_RRC_REJECT, "RRC_REJECT");
sReasonMap.set(REASON_RRC_TIMEOUT, "RRC_TIMEOUT")86         sReasonMap.set(REASON_RRC_TIMEOUT, "RRC_TIMEOUT");
sReasonMap.set(REASON_NO_SERVICE, "NO_SERVICE")87         sReasonMap.set(REASON_NO_SERVICE, "NO_SERVICE");
sReasonMap.set(REASON_PDN_NOT_AVAILABLE, "PDN_NOT_AVAILABLE")88         sReasonMap.set(REASON_PDN_NOT_AVAILABLE, "PDN_NOT_AVAILABLE");
sReasonMap.set(REASON_RF_BUSY, "RF_BUSY")89         sReasonMap.set(REASON_RF_BUSY, "RF_BUSY");
sReasonMap.set(REASON_UNSPECIFIED, "UNSPECIFIED")90         sReasonMap.set(REASON_UNSPECIFIED, "UNSPECIFIED");
91     }
92 
93     /** The reason of failure */
94     private final @FailureReason int mReason;
95 
96     /**
97      * Failure cause code from network or modem specific to the failure
98      *
99      * Reference: 3GPP TS 24.401 Annex A (Cause values for EPS mobility management)
100      * Reference: 3GPP TS 24.501 Annex A (Cause values for 5GS mobility management)
101      */
102     private final int mCauseCode;
103 
104     /** Retry wait time provided by network in milliseconds */
105     private final int mWaitTimeMillis;
106 
ConnectionFailureInfo(Parcel in)107     private ConnectionFailureInfo(Parcel in) {
108         mReason = in.readInt();
109         mCauseCode = in.readInt();
110         mWaitTimeMillis = in.readInt();
111     }
112 
113     /**
114      * Constructor.
115      *
116      * @param reason The reason of failure.
117      * @param causeCode Failure cause code from network or modem specific to the failure.
118      *        See 3GPP TS 24.401 Annex A (Cause values for EPS mobility management) and
119      *        3GPP TS 24.501 Annex A (Cause values for 5GS mobility management).
120      * @param waitTimeMillis Retry wait time provided by network in milliseconds.
121      * @hide
122      */
ConnectionFailureInfo(@ailureReason int reason, int causeCode, int waitTimeMillis)123     public ConnectionFailureInfo(@FailureReason int reason, int causeCode, int waitTimeMillis) {
124         mReason = reason;
125         mCauseCode = causeCode;
126         mWaitTimeMillis = waitTimeMillis;
127     }
128 
129     /**
130      * @return the reason for the failure.
131      */
getReason()132     public @FailureReason int getReason() {
133         return mReason;
134     }
135 
136     /**
137      * @return the cause code from the network or modem specific to the failure.
138      */
getCauseCode()139     public int getCauseCode() {
140         return mCauseCode;
141     }
142 
143     /**
144      * @return the retry wait time provided by the network in milliseconds.
145      */
getWaitTimeMillis()146     public int getWaitTimeMillis() {
147         return mWaitTimeMillis;
148     }
149 
150     /**
151      * @return the string format of {@link ConnectionFailureInfo}
152      */
153     @NonNull
154     @Override
toString()155     public String toString() {
156         String reason = sReasonMap.get(mReason, "UNKNOWN");
157         return "ConnectionFailureInfo :: {" + mReason + " : " + reason + ", "
158                 + mCauseCode + ", " + mWaitTimeMillis + "}";
159     }
160 
161     @Override
describeContents()162     public int describeContents() {
163         return 0;
164     }
165 
166     @Override
writeToParcel(@onNull Parcel out, int flags)167     public void writeToParcel(@NonNull Parcel out, int flags) {
168         out.writeInt(mReason);
169         out.writeInt(mCauseCode);
170         out.writeInt(mWaitTimeMillis);
171     }
172 
173     public static final @NonNull Creator<ConnectionFailureInfo> CREATOR =
174             new Creator<ConnectionFailureInfo>() {
175         @Override
176         public ConnectionFailureInfo createFromParcel(Parcel in) {
177             return new ConnectionFailureInfo(in);
178         }
179 
180         @Override
181         public ConnectionFailureInfo[] newArray(int size) {
182             return new ConnectionFailureInfo[size];
183         }
184     };
185 }
186