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.List; 32 import 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 */ 41 public 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 = 65 android.hardware.radio.V1_5.BarringInfo.ServiceType.CS_SERVICE; 66 /** Barring indicator for packet-switched service; applicable to UTRAN */ 67 public static final int BARRING_SERVICE_TYPE_PS_SERVICE = 68 android.hardware.radio.V1_5.BarringInfo.ServiceType.PS_SERVICE; 69 /** Barring indicator for circuit-switched voice service; applicable to UTRAN */ 70 public static final int BARRING_SERVICE_TYPE_CS_VOICE = 71 android.hardware.radio.V1_5.BarringInfo.ServiceType.CS_VOICE; 72 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 = 76 android.hardware.radio.V1_5.BarringInfo.ServiceType.MO_SIGNALLING; 77 /** Barring indicator for mobile-originated data traffic; applicable to EUTRAN and NGRAN */ 78 public static final int BARRING_SERVICE_TYPE_MO_DATA = 79 android.hardware.radio.V1_5.BarringInfo.ServiceType.MO_DATA; 80 /** Barring indicator for circuit-switched fallback for voice; applicable to EUTRAN and NGRAN */ 81 public static final int BARRING_SERVICE_TYPE_CS_FALLBACK = 82 android.hardware.radio.V1_5.BarringInfo.ServiceType.CS_FALLBACK; 83 /** Barring indicator for MMTEL (IMS) voice; applicable to EUTRAN and NGRAN */ 84 public static final int BARRING_SERVICE_TYPE_MMTEL_VOICE = 85 android.hardware.radio.V1_5.BarringInfo.ServiceType.MMTEL_VOICE; 86 /** Barring indicator for MMTEL (IMS) video; applicable to EUTRAN and NGRAN */ 87 public static final int BARRING_SERVICE_TYPE_MMTEL_VIDEO = 88 android.hardware.radio.V1_5.BarringInfo.ServiceType.MMTEL_VIDEO; 89 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 = 93 android.hardware.radio.V1_5.BarringInfo.ServiceType.EMERGENCY; 94 /** Barring indicator for SMS sending; applicable to UTRAN, EUTRAN, and NGRAN */ 95 public static final int BARRING_SERVICE_TYPE_SMS = 96 android.hardware.radio.V1_5.BarringInfo.ServiceType.SMS; 97 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, 110 BARRING_TYPE_CONDITIONAL, 111 BARRING_TYPE_UNKNOWN}) 112 public @interface BarringType {} 113 114 /** Barring is inactive */ 115 public static final int BARRING_TYPE_NONE = 116 android.hardware.radio.V1_5.BarringInfo.BarringType.NONE; 117 /** The service is barred */ 118 public static final int BARRING_TYPE_UNCONDITIONAL = 119 android.hardware.radio.V1_5.BarringInfo.BarringType.UNCONDITIONAL; 120 /** The service may be barred based on additional factors */ 121 public static final int BARRING_TYPE_CONDITIONAL = 122 android.hardware.radio.V1_5.BarringInfo.BarringType.CONDITIONAL; 123 124 /** 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 127 private final @BarringType int mBarringType; 128 129 private final boolean mIsConditionallyBarred; 130 private final int mConditionalBarringFactor; 131 private final int mConditionalBarringTimeSeconds; 132 133 /** @hide */ BarringServiceInfo(@arringType int type)134 public BarringServiceInfo(@BarringType int type) { 135 this(type, false, 0, 0); 136 } 137 138 /** @hide */ 139 @TestApi BarringServiceInfo(@arringType int barringType, boolean isConditionallyBarred, int conditionalBarringFactor, int conditionalBarringTimeSeconds)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 getBarringType()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 */ isConditionallyBarred()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 */ getConditionalBarringFactor()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") getConditionalBarringTimeSeconds()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 */ isBarred()183 public boolean isBarred() { 184 return mBarringType == BarringServiceInfo.BARRING_TYPE_UNCONDITIONAL 185 || (mBarringType == BarringServiceInfo.BARRING_TYPE_CONDITIONAL 186 && mIsConditionallyBarred); 187 } 188 189 @Override hashCode()190 public int hashCode() { 191 return Objects.hash(mBarringType, mIsConditionallyBarred, 192 mConditionalBarringFactor, mConditionalBarringTimeSeconds); 193 } 194 195 @Override equals(Object rhs)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 */ BarringServiceInfo(Parcel p)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 writeToParcel(@onNull Parcel dest, int flags)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 describeContents()237 public int describeContents() { 238 return 0; 239 } 240 } 241 242 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 248 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 BarringInfo()257 public BarringInfo() { 258 mBarringServiceInfos = new SparseArray<>(); 259 } 260 261 /** 262 * Constructor for new BarringInfo instances. 263 * 264 * @hide 265 */ 266 @TestApi BarringInfo(@ullable CellIdentity barringCellId, @NonNull SparseArray<BarringServiceInfo> barringServiceInfos)267 public BarringInfo(@Nullable CellIdentity barringCellId, 268 @NonNull SparseArray<BarringServiceInfo> barringServiceInfos) { 269 mCellIdentity = barringCellId; 270 mBarringServiceInfos = barringServiceInfos; 271 } 272 273 /** @hide */ create( @onNull android.hardware.radio.V1_5.CellIdentity halBarringCellId, @NonNull List<android.hardware.radio.V1_5.BarringInfo> halBarringInfos)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) { 281 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) { 286 // this is an error case where the barring info is conditional but the 287 // conditional barring fields weren't included 288 continue; 289 } 290 android.hardware.radio.V1_5.BarringInfo.BarringTypeSpecificInfo 291 .Conditional conditionalInfo = 292 halBarringInfo.barringTypeSpecificInfo.conditional(); 293 serviceInfos.put( 294 halBarringInfo.serviceType, new BarringServiceInfo( 295 halBarringInfo.barringType, // will always be CONDITIONAL here 296 conditionalInfo.isBarred, 297 conditionalInfo.factor, 298 conditionalInfo.timeSeconds)); 299 } else { 300 // Barring type is either NONE or UNCONDITIONAL 301 serviceInfos.put( 302 halBarringInfo.serviceType, new BarringServiceInfo( 303 halBarringInfo.barringType, false, 0, 0)); 304 } 305 } 306 return new BarringInfo(ci, serviceInfos); 307 } 308 309 /** 310 * Get the BarringServiceInfo for a specified service. 311 * 312 * @return a BarringServiceInfo struct describing the current barring status for a service 313 */ getBarringServiceInfo(@arringServiceType int service)314 public @NonNull BarringServiceInfo getBarringServiceInfo(@BarringServiceType int service) { 315 BarringServiceInfo bsi = mBarringServiceInfos.get(service); 316 // 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). 320 return (bsi != null) ? bsi : mBarringServiceInfos.size() > 0 321 ? BARRING_SERVICE_INFO_UNBARRED : BARRING_SERVICE_INFO_UNKNOWN; 322 } 323 324 /** @hide */ 325 @SystemApi createLocationInfoSanitizedCopy()326 public @NonNull BarringInfo createLocationInfoSanitizedCopy() { 327 // The only thing that would need sanitizing is the CellIdentity 328 if (mCellIdentity == null) return this; 329 330 return new BarringInfo(mCellIdentity.sanitizeLocationInfo(), mBarringServiceInfos); 331 } 332 333 /** @hide */ BarringInfo(Parcel p)334 public BarringInfo(Parcel p) { 335 mCellIdentity = p.readParcelable(CellIdentity.class.getClassLoader()); 336 mBarringServiceInfos = p.readSparseArray(BarringServiceInfo.class.getClassLoader()); 337 } 338 339 @Override writeToParcel(@onNull Parcel dest, int flags)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 describeContents()359 public int describeContents() { 360 return 0; 361 } 362 363 @Override hashCode()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 equals(Object rhs)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 toString()394 public String toString() { 395 return "BarringInfo {mCellIdentity=" + mCellIdentity 396 + ", mBarringServiceInfos=" + mBarringServiceInfos + "}"; 397 } 398 } 399