blob: 92423a2f2218ed68da497cb39d2688bec56ec58a [file] [log] [blame]
Nathan Haroldc564b1d2019-12-26 17:10:15 -08001/*
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
17package android.telephony;
18
19import android.annotation.IntDef;
20import android.annotation.NonNull;
21import android.annotation.Nullable;
22import android.annotation.SuppressLint;
23import android.annotation.SystemApi;
24import android.annotation.TestApi;
25import android.os.Parcel;
26import android.os.Parcelable;
27import android.util.SparseArray;
28
29import java.lang.annotation.Retention;
30import java.lang.annotation.RetentionPolicy;
31import java.util.List;
32import java.util.Objects;
33
34/**
35 * Provides the barring configuration for a particular service type.
36 *
37 * Provides indication about the barring of a particular service for use. Certain barring types
38 * are only valid for certain technology families. Any service that does not have a barring
39 * configuration is unbarred by default.
40 */
41public final class BarringInfo implements Parcelable {
42
43 /**
44 * Barring Service Type
45 *
46 * @hide
47 */
48 @Retention(RetentionPolicy.SOURCE)
49 @IntDef(prefix = "BARRING_SERVICE_TYPE_", value = {
50 BARRING_SERVICE_TYPE_CS_SERVICE,
51 BARRING_SERVICE_TYPE_PS_SERVICE,
52 BARRING_SERVICE_TYPE_CS_VOICE,
53 BARRING_SERVICE_TYPE_MO_SIGNALLING,
54 BARRING_SERVICE_TYPE_MO_DATA,
55 BARRING_SERVICE_TYPE_CS_FALLBACK,
56 BARRING_SERVICE_TYPE_MMTEL_VOICE,
57 BARRING_SERVICE_TYPE_MMTEL_VIDEO,
58 BARRING_SERVICE_TYPE_EMERGENCY,
59 BARRING_SERVICE_TYPE_SMS})
60 public @interface BarringServiceType {}
61
62 /* Applicabe to UTRAN */
63 /** Barring indicator for circuit-switched service; applicable to UTRAN */
64 public static final int BARRING_SERVICE_TYPE_CS_SERVICE =
Rambo Wang7ce04ea2020-01-29 16:20:53 -080065 android.hardware.radio.V1_5.BarringInfo.ServiceType.CS_SERVICE;
Nathan Haroldc564b1d2019-12-26 17:10:15 -080066 /** Barring indicator for packet-switched service; applicable to UTRAN */
67 public static final int BARRING_SERVICE_TYPE_PS_SERVICE =
Rambo Wang7ce04ea2020-01-29 16:20:53 -080068 android.hardware.radio.V1_5.BarringInfo.ServiceType.PS_SERVICE;
Nathan Haroldc564b1d2019-12-26 17:10:15 -080069 /** Barring indicator for circuit-switched voice service; applicable to UTRAN */
70 public static final int BARRING_SERVICE_TYPE_CS_VOICE =
Rambo Wang7ce04ea2020-01-29 16:20:53 -080071 android.hardware.radio.V1_5.BarringInfo.ServiceType.CS_VOICE;
Nathan Haroldc564b1d2019-12-26 17:10:15 -080072
73 /* Applicable to EUTRAN, NGRAN */
74 /** Barring indicator for mobile-originated signalling; applicable to EUTRAN and NGRAN */
75 public static final int BARRING_SERVICE_TYPE_MO_SIGNALLING =
Rambo Wang7ce04ea2020-01-29 16:20:53 -080076 android.hardware.radio.V1_5.BarringInfo.ServiceType.MO_SIGNALLING;
Nathan Haroldc564b1d2019-12-26 17:10:15 -080077 /** Barring indicator for mobile-originated data traffic; applicable to EUTRAN and NGRAN */
78 public static final int BARRING_SERVICE_TYPE_MO_DATA =
Rambo Wang7ce04ea2020-01-29 16:20:53 -080079 android.hardware.radio.V1_5.BarringInfo.ServiceType.MO_DATA;
Nathan Haroldc564b1d2019-12-26 17:10:15 -080080 /** Barring indicator for circuit-switched fallback for voice; applicable to EUTRAN and NGRAN */
81 public static final int BARRING_SERVICE_TYPE_CS_FALLBACK =
Rambo Wang7ce04ea2020-01-29 16:20:53 -080082 android.hardware.radio.V1_5.BarringInfo.ServiceType.CS_FALLBACK;
Nathan Haroldc564b1d2019-12-26 17:10:15 -080083 /** Barring indicator for MMTEL (IMS) voice; applicable to EUTRAN and NGRAN */
84 public static final int BARRING_SERVICE_TYPE_MMTEL_VOICE =
Rambo Wang7ce04ea2020-01-29 16:20:53 -080085 android.hardware.radio.V1_5.BarringInfo.ServiceType.MMTEL_VOICE;
Nathan Haroldc564b1d2019-12-26 17:10:15 -080086 /** Barring indicator for MMTEL (IMS) video; applicable to EUTRAN and NGRAN */
87 public static final int BARRING_SERVICE_TYPE_MMTEL_VIDEO =
Rambo Wang7ce04ea2020-01-29 16:20:53 -080088 android.hardware.radio.V1_5.BarringInfo.ServiceType.MMTEL_VIDEO;
Nathan Haroldc564b1d2019-12-26 17:10:15 -080089
90 /* Applicable to UTRAN, EUTRAN, NGRAN */
91 /** Barring indicator for emergency services; applicable to UTRAN, EUTRAN, and NGRAN */
92 public static final int BARRING_SERVICE_TYPE_EMERGENCY =
Rambo Wang7ce04ea2020-01-29 16:20:53 -080093 android.hardware.radio.V1_5.BarringInfo.ServiceType.EMERGENCY;
Nathan Haroldc564b1d2019-12-26 17:10:15 -080094 /** Barring indicator for SMS sending; applicable to UTRAN, EUTRAN, and NGRAN */
95 public static final int BARRING_SERVICE_TYPE_SMS =
Rambo Wang7ce04ea2020-01-29 16:20:53 -080096 android.hardware.radio.V1_5.BarringInfo.ServiceType.SMS;
Nathan Haroldc564b1d2019-12-26 17:10:15 -080097
98 //TODO: add barring constants for Operator-Specific barring codes
99
100 /** Describe the current barring configuration of a cell */
101 public static final class BarringServiceInfo implements Parcelable {
102 /**
103 * Barring Type
104 * @hide
105 */
106 @Retention(RetentionPolicy.SOURCE)
107 @IntDef(prefix = "BARRING_TYPE_", value =
108 {BARRING_TYPE_NONE,
109 BARRING_TYPE_UNCONDITIONAL,
Nathan Haroldd5b9cc72020-01-10 16:16:55 -0800110 BARRING_TYPE_CONDITIONAL,
111 BARRING_TYPE_UNKNOWN})
Nathan Haroldc564b1d2019-12-26 17:10:15 -0800112 public @interface BarringType {}
113
114 /** Barring is inactive */
Rambo Wang7ce04ea2020-01-29 16:20:53 -0800115 public static final int BARRING_TYPE_NONE =
116 android.hardware.radio.V1_5.BarringInfo.BarringType.NONE;
Nathan Haroldc564b1d2019-12-26 17:10:15 -0800117 /** The service is barred */
118 public static final int BARRING_TYPE_UNCONDITIONAL =
Rambo Wang7ce04ea2020-01-29 16:20:53 -0800119 android.hardware.radio.V1_5.BarringInfo.BarringType.UNCONDITIONAL;
Nathan Haroldc564b1d2019-12-26 17:10:15 -0800120 /** The service may be barred based on additional factors */
121 public static final int BARRING_TYPE_CONDITIONAL =
Rambo Wang7ce04ea2020-01-29 16:20:53 -0800122 android.hardware.radio.V1_5.BarringInfo.BarringType.CONDITIONAL;
Nathan Haroldc564b1d2019-12-26 17:10:15 -0800123
Nathan Haroldd5b9cc72020-01-10 16:16:55 -0800124 /** If a modem does not report barring info, then the barring type will be UNKNOWN */
125 public static final int BARRING_TYPE_UNKNOWN = -1;
126
Nathan Haroldc564b1d2019-12-26 17:10:15 -0800127 private final @BarringType int mBarringType;
128
129 private final boolean mIsConditionallyBarred;
130 private final int mConditionalBarringFactor;
131 private final int mConditionalBarringTimeSeconds;
132
133 /** @hide */
Nathan Haroldd5b9cc72020-01-10 16:16:55 -0800134 public BarringServiceInfo(@BarringType int type) {
135 this(type, false, 0, 0);
Nathan Haroldc564b1d2019-12-26 17:10:15 -0800136 }
137
138 /** @hide */
139 @TestApi
140 public BarringServiceInfo(@BarringType int barringType, boolean isConditionallyBarred,
141 int conditionalBarringFactor, int conditionalBarringTimeSeconds) {
142 mBarringType = barringType;
143 mIsConditionallyBarred = isConditionallyBarred;
144 mConditionalBarringFactor = conditionalBarringFactor;
145 mConditionalBarringTimeSeconds = conditionalBarringTimeSeconds;
146 }
147
148 public @BarringType int getBarringType() {
149 return mBarringType;
150 }
151
152 /**
153 * @return true if the conditional barring parameters have resulted in the service being
154 * barred; false if the service has either not been evaluated for conditional
155 * barring or has been evaluated and isn't barred.
156 */
157 public boolean isConditionallyBarred() {
158 return mIsConditionallyBarred;
159 }
160
161 /**
162 * @return the conditional barring factor as a percentage 0-100, which is the probability of
163 * a random device being barred for the service type.
164 */
165 public int getConditionalBarringFactor() {
166 return mConditionalBarringFactor;
167 }
168
169 /**
170 * @return the conditional barring time seconds, which is the interval between successive
171 * evaluations for conditional barring based on the barring factor.
172 */
173 @SuppressLint("MethodNameUnits")
174 public int getConditionalBarringTimeSeconds() {
175 return mConditionalBarringTimeSeconds;
176 }
177
178 /**
179 * Return whether a service is currently barred based on the BarringInfo
180 *
181 * @return true if the service is currently being barred, otherwise false
182 */
183 public boolean isBarred() {
184 return mBarringType == BarringServiceInfo.BARRING_TYPE_UNCONDITIONAL
185 || (mBarringType == BarringServiceInfo.BARRING_TYPE_CONDITIONAL
186 && mIsConditionallyBarred);
187 }
188
189 @Override
190 public int hashCode() {
191 return Objects.hash(mBarringType, mIsConditionallyBarred,
192 mConditionalBarringFactor, mConditionalBarringTimeSeconds);
193 }
194
195 @Override
196 public boolean equals(Object rhs) {
197 if (!(rhs instanceof BarringServiceInfo)) return false;
198
199 BarringServiceInfo other = (BarringServiceInfo) rhs;
200 return mBarringType == other.mBarringType
201 && mIsConditionallyBarred == other.mIsConditionallyBarred
202 && mConditionalBarringFactor == other.mConditionalBarringFactor
203 && mConditionalBarringTimeSeconds == other.mConditionalBarringTimeSeconds;
204 }
205
206 /** @hide */
207 public BarringServiceInfo(Parcel p) {
208 mBarringType = p.readInt();
209 mIsConditionallyBarred = p.readBoolean();
210 mConditionalBarringFactor = p.readInt();
211 mConditionalBarringTimeSeconds = p.readInt();
212 }
213
214 @Override
215 public void writeToParcel(@NonNull Parcel dest, int flags) {
216 dest.writeInt(mBarringType);
217 dest.writeBoolean(mIsConditionallyBarred);
218 dest.writeInt(mConditionalBarringFactor);
219 dest.writeInt(mConditionalBarringTimeSeconds);
220 }
221
222 /* @inheritDoc */
223 public static final @NonNull Parcelable.Creator<BarringServiceInfo> CREATOR =
224 new Parcelable.Creator<BarringServiceInfo>() {
225 @Override
226 public BarringServiceInfo createFromParcel(Parcel source) {
227 return new BarringServiceInfo(source);
228 }
229
230 @Override
231 public BarringServiceInfo[] newArray(int size) {
232 return new BarringServiceInfo[size];
233 }
234 };
235
236 @Override
237 public int describeContents() {
238 return 0;
239 }
240 }
241
Nathan Harold40cd94d2020-01-29 20:31:54 -0800242 private static final BarringServiceInfo BARRING_SERVICE_INFO_UNKNOWN =
243 new BarringServiceInfo(BarringServiceInfo.BARRING_TYPE_UNKNOWN);
244
245 private static final BarringServiceInfo BARRING_SERVICE_INFO_UNBARRED =
246 new BarringServiceInfo(BarringServiceInfo.BARRING_TYPE_NONE);
247
Nathan Haroldc564b1d2019-12-26 17:10:15 -0800248 private CellIdentity mCellIdentity;
249
250 // A SparseArray potentially mapping each BarringService type to a BarringServiceInfo config
251 // that describes the current barring status of that particular service.
252 private SparseArray<BarringServiceInfo> mBarringServiceInfos;
253
254 /** @hide */
255 @TestApi
256 @SystemApi
257 public BarringInfo() {
258 mBarringServiceInfos = new SparseArray<>();
259 }
260
261 /**
262 * Constructor for new BarringInfo instances.
263 *
264 * @hide
265 */
266 @TestApi
267 public BarringInfo(@Nullable CellIdentity barringCellId,
268 @NonNull SparseArray<BarringServiceInfo> barringServiceInfos) {
269 mCellIdentity = barringCellId;
270 mBarringServiceInfos = barringServiceInfos;
271 }
272
273 /** @hide */
274 public static BarringInfo create(
275 @NonNull android.hardware.radio.V1_5.CellIdentity halBarringCellId,
276 @NonNull List<android.hardware.radio.V1_5.BarringInfo> halBarringInfos) {
277 CellIdentity ci = CellIdentity.create(halBarringCellId);
278 SparseArray<BarringServiceInfo> serviceInfos = new SparseArray<>();
279
280 for (android.hardware.radio.V1_5.BarringInfo halBarringInfo : halBarringInfos) {
Rambo Wang7ce04ea2020-01-29 16:20:53 -0800281 if (halBarringInfo.barringType
282 == android.hardware.radio.V1_5.BarringInfo.BarringType.CONDITIONAL) {
283 if (halBarringInfo.barringTypeSpecificInfo.getDiscriminator()
284 != android.hardware.radio.V1_5.BarringInfo.BarringTypeSpecificInfo
285 .hidl_discriminator.conditional) {
Nathan Haroldc564b1d2019-12-26 17:10:15 -0800286 // this is an error case where the barring info is conditional but the
287 // conditional barring fields weren't included
288 continue;
289 }
Rambo Wang7ce04ea2020-01-29 16:20:53 -0800290 android.hardware.radio.V1_5.BarringInfo.BarringTypeSpecificInfo
291 .Conditional conditionalInfo =
292 halBarringInfo.barringTypeSpecificInfo.conditional();
Nathan Haroldc564b1d2019-12-26 17:10:15 -0800293 serviceInfos.put(
Rambo Wang7ce04ea2020-01-29 16:20:53 -0800294 halBarringInfo.serviceType, new BarringServiceInfo(
295 halBarringInfo.barringType, // will always be CONDITIONAL here
Nathan Haroldc564b1d2019-12-26 17:10:15 -0800296 conditionalInfo.isBarred,
Rambo Wang7ce04ea2020-01-29 16:20:53 -0800297 conditionalInfo.factor,
298 conditionalInfo.timeSeconds));
Nathan Haroldc564b1d2019-12-26 17:10:15 -0800299 } else {
300 // Barring type is either NONE or UNCONDITIONAL
301 serviceInfos.put(
Rambo Wang7ce04ea2020-01-29 16:20:53 -0800302 halBarringInfo.serviceType, new BarringServiceInfo(
303 halBarringInfo.barringType, false, 0, 0));
Nathan Haroldc564b1d2019-12-26 17:10:15 -0800304 }
305 }
306 return new BarringInfo(ci, serviceInfos);
307 }
308
309 /**
Nathan Haroldc564b1d2019-12-26 17:10:15 -0800310 * Get the BarringServiceInfo for a specified service.
311 *
312 * @return a BarringServiceInfo struct describing the current barring status for a service
313 */
314 public @NonNull BarringServiceInfo getBarringServiceInfo(@BarringServiceType int service) {
315 BarringServiceInfo bsi = mBarringServiceInfos.get(service);
Nathan Haroldd5b9cc72020-01-10 16:16:55 -0800316 // If barring is reported but not for a particular service, then we report the barring
317 // type as UNKNOWN; if the modem reports barring info but doesn't report for a particular
318 // service then we can safely assume that the service isn't barred (for instance because
319 // that particular service isn't applicable to the current RAN).
Nathan Harold40cd94d2020-01-29 20:31:54 -0800320 return (bsi != null) ? bsi : mBarringServiceInfos.size() > 0
321 ? BARRING_SERVICE_INFO_UNBARRED : BARRING_SERVICE_INFO_UNKNOWN;
Nathan Haroldc564b1d2019-12-26 17:10:15 -0800322 }
323
324 /** @hide */
325 @SystemApi
326 public @NonNull BarringInfo createLocationInfoSanitizedCopy() {
Nathan Harold5f8ab162020-01-31 15:47:35 -0800327 // The only thing that would need sanitizing is the CellIdentity
328 if (mCellIdentity == null) return this;
329
Nathan Haroldc564b1d2019-12-26 17:10:15 -0800330 return new BarringInfo(mCellIdentity.sanitizeLocationInfo(), mBarringServiceInfos);
331 }
332
333 /** @hide */
334 public BarringInfo(Parcel p) {
335 mCellIdentity = p.readParcelable(CellIdentity.class.getClassLoader());
336 mBarringServiceInfos = p.readSparseArray(BarringServiceInfo.class.getClassLoader());
337 }
338
339 @Override
340 public void writeToParcel(@NonNull Parcel dest, int flags) {
341 dest.writeParcelable(mCellIdentity, flags);
342 dest.writeSparseArray(mBarringServiceInfos);
343 }
344
345 public static final @NonNull Parcelable.Creator<BarringInfo> CREATOR =
346 new Parcelable.Creator<BarringInfo>() {
347 @Override
348 public BarringInfo createFromParcel(Parcel source) {
349 return new BarringInfo(source);
350 }
351
352 @Override
353 public BarringInfo[] newArray(int size) {
354 return new BarringInfo[size];
355 }
356 };
357
358 @Override
359 public int describeContents() {
360 return 0;
361 }
362
363 @Override
364 public int hashCode() {
365 int hash = mCellIdentity != null ? mCellIdentity.hashCode() : 7;
366 for (int i = 0; i < mBarringServiceInfos.size(); i++) {
367 hash = hash + 15 * mBarringServiceInfos.keyAt(i);
368 hash = hash + 31 * mBarringServiceInfos.valueAt(i).hashCode();
369 }
370 return hash;
371 }
372
373 @Override
374 public boolean equals(Object rhs) {
375 if (!(rhs instanceof BarringInfo)) return false;
376
377 BarringInfo bi = (BarringInfo) rhs;
378
379 if (hashCode() != bi.hashCode()) return false;
380
381 if (mBarringServiceInfos.size() != bi.mBarringServiceInfos.size()) return false;
382
383 for (int i = 0; i < mBarringServiceInfos.size(); i++) {
384 if (mBarringServiceInfos.keyAt(i) != bi.mBarringServiceInfos.keyAt(i)) return false;
385 if (!Objects.equals(mBarringServiceInfos.valueAt(i),
386 bi.mBarringServiceInfos.valueAt(i))) {
387 return false;
388 }
389 }
390 return true;
391 }
392
393 @Override
394 public String toString() {
395 return "BarringInfo {mCellIdentity=" + mCellIdentity
396 + ", mBarringServiceInfos=" + mBarringServiceInfos + "}";
397 }
398}