1 /*
2  * Copyright 2019 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.SuppressLint;
23 import android.annotation.SystemApi;
24 import android.annotation.TestApi;
25 import android.os.Parcel;
26 import android.os.Parcelable;
27 import android.util.SparseArray;
28 
29 import java.lang.annotation.Retention;
30 import java.lang.annotation.RetentionPolicy;
31 import java.util.Objects;
32 
33 /**
34  * Provides the barring configuration for a particular service type.
35  *
36  * Provides indication about the barring of a particular service for use. Certain barring types
37  * are only valid for certain technology families. Any service that does not have a barring
38  * configuration is unbarred by default.
39  */
40 public final class BarringInfo implements Parcelable {
41 
42     /**
43      * Barring Service Type
44      *
45      * @hide
46      */
47     @Retention(RetentionPolicy.SOURCE)
48     @IntDef(prefix = "BARRING_SERVICE_TYPE_", value = {
49             BARRING_SERVICE_TYPE_CS_SERVICE,
50             BARRING_SERVICE_TYPE_PS_SERVICE,
51             BARRING_SERVICE_TYPE_CS_VOICE,
52             BARRING_SERVICE_TYPE_MO_SIGNALLING,
53             BARRING_SERVICE_TYPE_MO_DATA,
54             BARRING_SERVICE_TYPE_CS_FALLBACK,
55             BARRING_SERVICE_TYPE_MMTEL_VOICE,
56             BARRING_SERVICE_TYPE_MMTEL_VIDEO,
57             BARRING_SERVICE_TYPE_EMERGENCY,
58             BARRING_SERVICE_TYPE_SMS})
59     public @interface BarringServiceType {}
60 
61     /* Applicabe to UTRAN */
62     /** Barring indicator for circuit-switched service; applicable to UTRAN */
63     public static final int BARRING_SERVICE_TYPE_CS_SERVICE =
64             android.hardware.radio.V1_5.BarringInfo.ServiceType.CS_SERVICE;
65     /** Barring indicator for packet-switched service; applicable to UTRAN */
66     public static final int BARRING_SERVICE_TYPE_PS_SERVICE =
67             android.hardware.radio.V1_5.BarringInfo.ServiceType.PS_SERVICE;
68     /** Barring indicator for circuit-switched voice service; applicable to UTRAN */
69     public static final int BARRING_SERVICE_TYPE_CS_VOICE =
70             android.hardware.radio.V1_5.BarringInfo.ServiceType.CS_VOICE;
71 
72     /* Applicable to EUTRAN, NGRAN */
73     /** Barring indicator for mobile-originated signalling; applicable to EUTRAN and NGRAN */
74     public static final int BARRING_SERVICE_TYPE_MO_SIGNALLING =
75             android.hardware.radio.V1_5.BarringInfo.ServiceType.MO_SIGNALLING;
76     /** Barring indicator for mobile-originated data traffic; applicable to EUTRAN and NGRAN */
77     public static final int BARRING_SERVICE_TYPE_MO_DATA =
78             android.hardware.radio.V1_5.BarringInfo.ServiceType.MO_DATA;
79     /** Barring indicator for circuit-switched fallback for voice; applicable to EUTRAN and NGRAN */
80     public static final int BARRING_SERVICE_TYPE_CS_FALLBACK =
81             android.hardware.radio.V1_5.BarringInfo.ServiceType.CS_FALLBACK;
82     /** Barring indicator for MMTEL (IMS) voice; applicable to EUTRAN and NGRAN */
83     public static final int BARRING_SERVICE_TYPE_MMTEL_VOICE =
84             android.hardware.radio.V1_5.BarringInfo.ServiceType.MMTEL_VOICE;
85     /** Barring indicator for MMTEL (IMS) video; applicable to EUTRAN and NGRAN */
86     public static final int BARRING_SERVICE_TYPE_MMTEL_VIDEO =
87             android.hardware.radio.V1_5.BarringInfo.ServiceType.MMTEL_VIDEO;
88 
89     /* Applicable to UTRAN, EUTRAN, NGRAN */
90     /** Barring indicator for emergency services; applicable to UTRAN, EUTRAN, and NGRAN */
91     public static final int BARRING_SERVICE_TYPE_EMERGENCY =
92             android.hardware.radio.V1_5.BarringInfo.ServiceType.EMERGENCY;
93     /** Barring indicator for SMS sending; applicable to UTRAN, EUTRAN, and NGRAN */
94     public static final int BARRING_SERVICE_TYPE_SMS =
95             android.hardware.radio.V1_5.BarringInfo.ServiceType.SMS;
96 
97     //TODO: add barring constants for Operator-Specific barring codes
98 
99     /** Describe the current barring configuration of a cell */
100     public static final class BarringServiceInfo implements Parcelable {
101         /**
102          * Barring Type
103          * @hide
104          */
105         @Retention(RetentionPolicy.SOURCE)
106         @IntDef(prefix = "BARRING_TYPE_", value =
107                     {BARRING_TYPE_NONE,
108                     BARRING_TYPE_UNCONDITIONAL,
109                     BARRING_TYPE_CONDITIONAL,
110                     BARRING_TYPE_UNKNOWN})
111         public @interface BarringType {}
112 
113         /** Barring is inactive */
114         public static final int BARRING_TYPE_NONE =
115                 android.hardware.radio.V1_5.BarringInfo.BarringType.NONE;
116         /** The service is barred */
117         public static final int BARRING_TYPE_UNCONDITIONAL =
118                 android.hardware.radio.V1_5.BarringInfo.BarringType.UNCONDITIONAL;
119         /** The service may be barred based on additional factors */
120         public static final int BARRING_TYPE_CONDITIONAL =
121                 android.hardware.radio.V1_5.BarringInfo.BarringType.CONDITIONAL;
122 
123         /** If a modem does not report barring info, then the barring type will be UNKNOWN */
124         public static final int BARRING_TYPE_UNKNOWN = -1;
125 
126         private final @BarringType int mBarringType;
127 
128         private final boolean mIsConditionallyBarred;
129         private final int mConditionalBarringFactor;
130         private final int mConditionalBarringTimeSeconds;
131 
132         /** @hide */
BarringServiceInfo(@arringType int type)133         public BarringServiceInfo(@BarringType int type) {
134             this(type, false, 0, 0);
135         }
136 
137         /** @hide */
138         @TestApi
BarringServiceInfo(@arringType int barringType, boolean isConditionallyBarred, int conditionalBarringFactor, int conditionalBarringTimeSeconds)139         public BarringServiceInfo(@BarringType int barringType, boolean isConditionallyBarred,
140                 int conditionalBarringFactor, int conditionalBarringTimeSeconds) {
141             mBarringType = barringType;
142             mIsConditionallyBarred = isConditionallyBarred;
143             mConditionalBarringFactor = conditionalBarringFactor;
144             mConditionalBarringTimeSeconds = conditionalBarringTimeSeconds;
145         }
146 
getBarringType()147         public @BarringType int getBarringType() {
148             return mBarringType;
149         }
150 
151         /**
152          * @return true if the conditional barring parameters have resulted in the service being
153          *         barred; false if the service has either not been evaluated for conditional
154          *         barring or has been evaluated and isn't barred.
155          */
isConditionallyBarred()156         public boolean isConditionallyBarred() {
157             return mIsConditionallyBarred;
158         }
159 
160         /**
161          * @return the conditional barring factor as a percentage 0-100, which is the probability of
162          *         a random device being barred for the service type.
163          */
getConditionalBarringFactor()164         public int getConditionalBarringFactor() {
165             return mConditionalBarringFactor;
166         }
167 
168         /**
169          * @return the conditional barring time seconds, which is the interval between successive
170          *         evaluations for conditional barring based on the barring factor.
171          */
172         @SuppressLint("MethodNameUnits")
getConditionalBarringTimeSeconds()173         public int getConditionalBarringTimeSeconds() {
174             return mConditionalBarringTimeSeconds;
175         }
176 
177         /**
178          * Return whether a service is currently barred based on the BarringInfo
179          *
180          * @return true if the service is currently being barred, otherwise false
181          */
isBarred()182         public boolean isBarred() {
183             return mBarringType == BarringServiceInfo.BARRING_TYPE_UNCONDITIONAL
184                     || (mBarringType == BarringServiceInfo.BARRING_TYPE_CONDITIONAL
185                             && mIsConditionallyBarred);
186         }
187 
188         @Override
hashCode()189         public int hashCode() {
190             return Objects.hash(mBarringType, mIsConditionallyBarred,
191                     mConditionalBarringFactor, mConditionalBarringTimeSeconds);
192         }
193 
194         @Override
equals(Object rhs)195         public boolean equals(Object rhs) {
196             if (!(rhs instanceof BarringServiceInfo)) return false;
197 
198             BarringServiceInfo other = (BarringServiceInfo) rhs;
199             return mBarringType == other.mBarringType
200                     && mIsConditionallyBarred == other.mIsConditionallyBarred
201                     && mConditionalBarringFactor == other.mConditionalBarringFactor
202                     && mConditionalBarringTimeSeconds == other.mConditionalBarringTimeSeconds;
203         }
204 
205         /** @hide */
BarringServiceInfo(Parcel p)206         public BarringServiceInfo(Parcel p) {
207             mBarringType = p.readInt();
208             mIsConditionallyBarred = p.readBoolean();
209             mConditionalBarringFactor = p.readInt();
210             mConditionalBarringTimeSeconds = p.readInt();
211         }
212 
213         @Override
writeToParcel(@onNull Parcel dest, int flags)214         public void writeToParcel(@NonNull Parcel dest, int flags) {
215             dest.writeInt(mBarringType);
216             dest.writeBoolean(mIsConditionallyBarred);
217             dest.writeInt(mConditionalBarringFactor);
218             dest.writeInt(mConditionalBarringTimeSeconds);
219         }
220 
221         /* @inheritDoc */
222         public static final @NonNull Parcelable.Creator<BarringServiceInfo> CREATOR =
223                 new Parcelable.Creator<BarringServiceInfo>() {
224                     @Override
225                     public BarringServiceInfo createFromParcel(Parcel source) {
226                         return new BarringServiceInfo(source);
227                     }
228 
229                     @Override
230                     public BarringServiceInfo[] newArray(int size) {
231                         return new BarringServiceInfo[size];
232                     }
233                 };
234 
235         @Override
describeContents()236         public int describeContents() {
237             return 0;
238         }
239     }
240 
241     private static final BarringServiceInfo BARRING_SERVICE_INFO_UNKNOWN =
242             new BarringServiceInfo(BarringServiceInfo.BARRING_TYPE_UNKNOWN);
243 
244     private static final BarringServiceInfo BARRING_SERVICE_INFO_UNBARRED =
245             new BarringServiceInfo(BarringServiceInfo.BARRING_TYPE_NONE);
246 
247     private CellIdentity mCellIdentity;
248 
249     // A SparseArray potentially mapping each BarringService type to a BarringServiceInfo config
250     // that describes the current barring status of that particular service.
251     private SparseArray<BarringServiceInfo> mBarringServiceInfos;
252 
253     /** @hide */
254     @SystemApi
BarringInfo()255     public BarringInfo() {
256         mBarringServiceInfos = new SparseArray<>();
257     }
258 
259     /**
260      * Constructor for new BarringInfo instances.
261      *
262      * @hide
263      */
264     @TestApi
BarringInfo(@ullable CellIdentity barringCellId, @NonNull SparseArray<BarringServiceInfo> barringServiceInfos)265     public BarringInfo(@Nullable CellIdentity barringCellId,
266             @NonNull SparseArray<BarringServiceInfo> barringServiceInfos) {
267         mCellIdentity = barringCellId;
268         mBarringServiceInfos = barringServiceInfos;
269     }
270 
271     /**
272      * Get the BarringServiceInfo for a specified service.
273      *
274      * @return a BarringServiceInfo struct describing the current barring status for a service
275      */
getBarringServiceInfo(@arringServiceType int service)276     public @NonNull BarringServiceInfo getBarringServiceInfo(@BarringServiceType int service) {
277         BarringServiceInfo bsi = mBarringServiceInfos.get(service);
278         // If barring is reported but not for a particular service, then we report the barring
279         // type as UNKNOWN; if the modem reports barring info but doesn't report for a particular
280         // service then we can safely assume that the service isn't barred (for instance because
281         // that particular service isn't applicable to the current RAN).
282         return (bsi != null) ? bsi : mBarringServiceInfos.size() > 0
283                 ? BARRING_SERVICE_INFO_UNBARRED : BARRING_SERVICE_INFO_UNKNOWN;
284     }
285 
286     /** @hide */
287     @SystemApi
createLocationInfoSanitizedCopy()288     public @NonNull BarringInfo createLocationInfoSanitizedCopy() {
289         // The only thing that would need sanitizing is the CellIdentity
290         if (mCellIdentity == null) return this;
291 
292         return new BarringInfo(mCellIdentity.sanitizeLocationInfo(), mBarringServiceInfos);
293     }
294 
295     /** @hide */
BarringInfo(Parcel p)296     public BarringInfo(Parcel p) {
297         mCellIdentity = p.readParcelable(CellIdentity.class.getClassLoader(), android.telephony.CellIdentity.class);
298         mBarringServiceInfos = p.readSparseArray(BarringServiceInfo.class.getClassLoader(), android.telephony.BarringInfo.BarringServiceInfo.class);
299     }
300 
301     @Override
writeToParcel(@onNull Parcel dest, int flags)302     public void writeToParcel(@NonNull Parcel dest, int flags) {
303         dest.writeParcelable(mCellIdentity, flags);
304         dest.writeSparseArray(mBarringServiceInfos);
305     }
306 
307     public static final @NonNull Parcelable.Creator<BarringInfo> CREATOR =
308             new Parcelable.Creator<BarringInfo>() {
309                 @Override
310                 public BarringInfo createFromParcel(Parcel source) {
311                     return new BarringInfo(source);
312                 }
313 
314                 @Override
315                 public BarringInfo[] newArray(int size) {
316                     return new BarringInfo[size];
317                 }
318             };
319 
320     @Override
describeContents()321     public int describeContents() {
322         return 0;
323     }
324 
325     @Override
hashCode()326     public int hashCode() {
327         int hash = mCellIdentity != null ? mCellIdentity.hashCode() : 7;
328         for (int i = 0; i < mBarringServiceInfos.size(); i++) {
329             hash = hash + 15 * mBarringServiceInfos.keyAt(i);
330             hash = hash + 31 * mBarringServiceInfos.valueAt(i).hashCode();
331         }
332         return hash;
333     }
334 
335     @Override
equals(Object rhs)336     public boolean equals(Object rhs) {
337         if (!(rhs instanceof BarringInfo)) return false;
338 
339         BarringInfo bi = (BarringInfo) rhs;
340 
341         if (hashCode() != bi.hashCode()) return false;
342 
343         if (mBarringServiceInfos.size() != bi.mBarringServiceInfos.size()) return false;
344 
345         for (int i = 0; i < mBarringServiceInfos.size(); i++) {
346             if (mBarringServiceInfos.keyAt(i) != bi.mBarringServiceInfos.keyAt(i)) return false;
347             if (!Objects.equals(mBarringServiceInfos.valueAt(i),
348                         bi.mBarringServiceInfos.valueAt(i))) {
349                 return false;
350             }
351         }
352         return true;
353     }
354 
355     @Override
toString()356     public String toString() {
357         return "BarringInfo {mCellIdentity=" + mCellIdentity
358                + ", mBarringServiceInfos=" + mBarringServiceInfos + "}";
359     }
360 }
361