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 /* Applicable 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.network.BarringInfo.SERVICE_TYPE_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.network.BarringInfo.SERVICE_TYPE_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.network.BarringInfo.SERVICE_TYPE_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.network.BarringInfo.SERVICE_TYPE_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.network.BarringInfo.SERVICE_TYPE_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.network.BarringInfo.SERVICE_TYPE_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.network.BarringInfo.SERVICE_TYPE_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.network.BarringInfo.SERVICE_TYPE_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.network.BarringInfo.SERVICE_TYPE_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.network.BarringInfo.SERVICE_TYPE_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.network.BarringInfo.BARRING_TYPE_NONE; 116 /** The service is barred */ 117 public static final int BARRING_TYPE_UNCONDITIONAL = 118 android.hardware.radio.network.BarringInfo.BARRING_TYPE_UNCONDITIONAL; 119 /** The service may be barred based on additional factors */ 120 public static final int BARRING_TYPE_CONDITIONAL = 121 android.hardware.radio.network.BarringInfo.BARRING_TYPE_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 barringTypeToString(@arringType int barringType)205 private static String barringTypeToString(@BarringType int barringType) { 206 return switch (barringType) { 207 case BARRING_TYPE_NONE -> "NONE"; 208 case BARRING_TYPE_CONDITIONAL -> "CONDITIONAL"; 209 case BARRING_TYPE_UNCONDITIONAL -> "UNCONDITIONAL"; 210 case BARRING_TYPE_UNKNOWN -> "UNKNOWN"; 211 default -> "UNKNOWN(" + barringType + ")"; 212 }; 213 } 214 215 @Override toString()216 public String toString() { 217 return "BarringServiceInfo {mBarringType=" + barringTypeToString(mBarringType) 218 + ", mIsConditionallyBarred=" + mIsConditionallyBarred 219 + ", mConditionalBarringFactor=" + mConditionalBarringFactor 220 + ", mConditionalBarringTimeSeconds=" + mConditionalBarringTimeSeconds + "}"; 221 } 222 223 /** @hide */ BarringServiceInfo(Parcel p)224 public BarringServiceInfo(Parcel p) { 225 mBarringType = p.readInt(); 226 mIsConditionallyBarred = p.readBoolean(); 227 mConditionalBarringFactor = p.readInt(); 228 mConditionalBarringTimeSeconds = p.readInt(); 229 } 230 231 @Override writeToParcel(@onNull Parcel dest, int flags)232 public void writeToParcel(@NonNull Parcel dest, int flags) { 233 dest.writeInt(mBarringType); 234 dest.writeBoolean(mIsConditionallyBarred); 235 dest.writeInt(mConditionalBarringFactor); 236 dest.writeInt(mConditionalBarringTimeSeconds); 237 } 238 239 /* @inheritDoc */ 240 public static final @NonNull Parcelable.Creator<BarringServiceInfo> CREATOR = 241 new Parcelable.Creator<BarringServiceInfo>() { 242 @Override 243 public BarringServiceInfo createFromParcel(Parcel source) { 244 return new BarringServiceInfo(source); 245 } 246 247 @Override 248 public BarringServiceInfo[] newArray(int size) { 249 return new BarringServiceInfo[size]; 250 } 251 }; 252 253 @Override describeContents()254 public int describeContents() { 255 return 0; 256 } 257 } 258 259 private static final BarringServiceInfo BARRING_SERVICE_INFO_UNKNOWN = 260 new BarringServiceInfo(BarringServiceInfo.BARRING_TYPE_UNKNOWN); 261 262 private static final BarringServiceInfo BARRING_SERVICE_INFO_UNBARRED = 263 new BarringServiceInfo(BarringServiceInfo.BARRING_TYPE_NONE); 264 265 private CellIdentity mCellIdentity; 266 267 // A SparseArray potentially mapping each BarringService type to a BarringServiceInfo config 268 // that describes the current barring status of that particular service. 269 private SparseArray<BarringServiceInfo> mBarringServiceInfos; 270 271 /** @hide */ 272 @SystemApi BarringInfo()273 public BarringInfo() { 274 mBarringServiceInfos = new SparseArray<>(); 275 } 276 277 /** 278 * Constructor for new BarringInfo instances. 279 * 280 * @hide 281 */ 282 @TestApi BarringInfo(@ullable CellIdentity barringCellId, @NonNull SparseArray<BarringServiceInfo> barringServiceInfos)283 public BarringInfo(@Nullable CellIdentity barringCellId, 284 @NonNull SparseArray<BarringServiceInfo> barringServiceInfos) { 285 mCellIdentity = barringCellId; 286 mBarringServiceInfos = barringServiceInfos; 287 } 288 289 /** 290 * Get the BarringServiceInfo for a specified service. 291 * 292 * @return a BarringServiceInfo struct describing the current barring status for a service 293 */ getBarringServiceInfo(@arringServiceType int service)294 public @NonNull BarringServiceInfo getBarringServiceInfo(@BarringServiceType int service) { 295 BarringServiceInfo bsi = mBarringServiceInfos.get(service); 296 // If barring is reported but not for a particular service, then we report the barring 297 // type as UNKNOWN; if the modem reports barring info but doesn't report for a particular 298 // service then we can safely assume that the service isn't barred (for instance because 299 // that particular service isn't applicable to the current RAN). 300 return (bsi != null) ? bsi : mBarringServiceInfos.size() > 0 301 ? BARRING_SERVICE_INFO_UNBARRED : BARRING_SERVICE_INFO_UNKNOWN; 302 } 303 304 /** @hide */ 305 @SystemApi createLocationInfoSanitizedCopy()306 public @NonNull BarringInfo createLocationInfoSanitizedCopy() { 307 // The only thing that would need sanitizing is the CellIdentity 308 if (mCellIdentity == null) return this; 309 310 return new BarringInfo(mCellIdentity.sanitizeLocationInfo(), mBarringServiceInfos); 311 } 312 313 /** @hide */ BarringInfo(Parcel p)314 public BarringInfo(Parcel p) { 315 mCellIdentity = p.readParcelable(CellIdentity.class.getClassLoader(), android.telephony.CellIdentity.class); 316 mBarringServiceInfos = p.readSparseArray(BarringServiceInfo.class.getClassLoader(), android.telephony.BarringInfo.BarringServiceInfo.class); 317 } 318 319 @Override writeToParcel(@onNull Parcel dest, int flags)320 public void writeToParcel(@NonNull Parcel dest, int flags) { 321 dest.writeParcelable(mCellIdentity, flags); 322 dest.writeSparseArray(mBarringServiceInfos); 323 } 324 325 public static final @NonNull Parcelable.Creator<BarringInfo> CREATOR = 326 new Parcelable.Creator<BarringInfo>() { 327 @Override 328 public BarringInfo createFromParcel(Parcel source) { 329 return new BarringInfo(source); 330 } 331 332 @Override 333 public BarringInfo[] newArray(int size) { 334 return new BarringInfo[size]; 335 } 336 }; 337 338 @Override describeContents()339 public int describeContents() { 340 return 0; 341 } 342 343 @Override hashCode()344 public int hashCode() { 345 int hash = mCellIdentity != null ? mCellIdentity.hashCode() : 7; 346 for (int i = 0; i < mBarringServiceInfos.size(); i++) { 347 hash = hash + 15 * mBarringServiceInfos.keyAt(i); 348 hash = hash + 31 * mBarringServiceInfos.valueAt(i).hashCode(); 349 } 350 return hash; 351 } 352 353 @Override equals(Object rhs)354 public boolean equals(Object rhs) { 355 if (!(rhs instanceof BarringInfo)) return false; 356 357 BarringInfo bi = (BarringInfo) rhs; 358 359 if (hashCode() != bi.hashCode()) return false; 360 361 if (mBarringServiceInfos.size() != bi.mBarringServiceInfos.size()) return false; 362 363 for (int i = 0; i < mBarringServiceInfos.size(); i++) { 364 if (mBarringServiceInfos.keyAt(i) != bi.mBarringServiceInfos.keyAt(i)) return false; 365 if (!Objects.equals(mBarringServiceInfos.valueAt(i), 366 bi.mBarringServiceInfos.valueAt(i))) { 367 return false; 368 } 369 } 370 return true; 371 } 372 373 @Override toString()374 public String toString() { 375 return "BarringInfo {mCellIdentity=" + mCellIdentity 376 + ", mBarringServiceInfos=" + mBarringServiceInfos + "}"; 377 } 378 } 379