Merge "Add API to check if a SIM card matches carrier restrictions."

This commit is contained in:
Michele Berionne
2019-02-11 23:47:25 +00:00
committed by Gerrit Code Review
2 changed files with 123 additions and 0 deletions

View File

@@ -5529,6 +5529,7 @@ package android.telephony {
method @NonNull public java.util.List<android.service.carrier.CarrierIdentifier> getExcludedCarriers();
method public int getMultiSimPolicy();
method public boolean isAllCarriersAllowed();
method public java.util.List<java.lang.Boolean> isCarrierIdentifiersAllowed(@NonNull java.util.List<android.service.carrier.CarrierIdentifier>);
method public void writeToParcel(android.os.Parcel, int);
field public static final int CARRIER_RESTRICTION_DEFAULT_ALLOWED = 1; // 0x1
field public static final int CARRIER_RESTRICTION_DEFAULT_NOT_ALLOWED = 0; // 0x0

View File

@@ -27,6 +27,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* Contains the list of carrier restrictions.
@@ -93,6 +94,9 @@ public final class CarrierRestrictionRules implements Parcelable {
value = {CARRIER_RESTRICTION_DEFAULT_NOT_ALLOWED, CARRIER_RESTRICTION_DEFAULT_ALLOWED})
public @interface CarrierRestrictionDefault {}
/* Wild character for comparison */
private static final char WILD_CHARACTER = '?';
private List<CarrierIdentifier> mAllowedCarriers;
private List<CarrierIdentifier> mExcludedCarriers;
@CarrierRestrictionDefault
@@ -165,6 +169,124 @@ public final class CarrierRestrictionRules implements Parcelable {
return mMultiSimPolicy;
}
/**
* Tests an array of carriers with the carrier restriction configuration. The list of carrier
* ids passed as argument does not need to be the same as currently present in the device.
*
* @param carrierIds list of {@link CarrierIdentifier}, one for each SIM slot on the device
* @return a list of boolean with the same size as input, indicating if each
* {@link CarrierIdentifier} is allowed or not.
*/
public List<Boolean> isCarrierIdentifiersAllowed(@NonNull List<CarrierIdentifier> carrierIds) {
ArrayList<Boolean> result = new ArrayList<>(carrierIds.size());
// First calculate the result for each slot independently
for (int i = 0; i < carrierIds.size(); i++) {
boolean inAllowedList = isCarrierIdInList(carrierIds.get(i), mAllowedCarriers);
boolean inExcludedList = isCarrierIdInList(carrierIds.get(i), mExcludedCarriers);
if (mCarrierRestrictionDefault == CARRIER_RESTRICTION_DEFAULT_NOT_ALLOWED) {
result.add((inAllowedList && !inExcludedList) ? true : false);
} else {
result.add((inExcludedList && !inAllowedList) ? false : true);
}
}
// Apply the multi-slot policy, if needed.
if (mMultiSimPolicy == MULTISIM_POLICY_ONE_VALID_SIM_MUST_BE_PRESENT) {
for (boolean b : result) {
if (b) {
result.replaceAll(x -> true);
break;
}
}
}
return result;
}
/**
* Indicates if a certain carrier {@code id} is present inside a {@code list}
*
* @return true if the carrier {@code id} is present, false otherwise
*/
private static boolean isCarrierIdInList(CarrierIdentifier id, List<CarrierIdentifier> list) {
for (CarrierIdentifier listItem : list) {
// Compare MCC and MNC
if (!patternMatch(id.getMcc(), listItem.getMcc())
|| !patternMatch(id.getMnc(), listItem.getMnc())) {
continue;
}
// Compare SPN. Comparison is on the complete strings, case insensitive and with wild
// characters.
String listItemValue = convertNullToEmpty(listItem.getSpn());
String idValue = convertNullToEmpty(id.getSpn());
if (!listItemValue.isEmpty()) {
if (!patternMatch(idValue, listItemValue)) {
continue;
}
}
// The IMSI of the configuration can be shorter than actual IMSI in the SIM card.
listItemValue = convertNullToEmpty(listItem.getImsi());
idValue = convertNullToEmpty(id.getImsi());
if (!patternMatch(
idValue.substring(0, Math.min(idValue.length(), listItemValue.length())),
listItemValue)) {
continue;
}
// The GID1 of the configuration can be shorter than actual GID1 in the SIM card.
listItemValue = convertNullToEmpty(listItem.getGid1());
idValue = convertNullToEmpty(id.getGid1());
if (!patternMatch(
idValue.substring(0, Math.min(idValue.length(), listItemValue.length())),
listItemValue)) {
continue;
}
// The GID2 of the configuration can be shorter than actual GID2 in the SIM card.
listItemValue = convertNullToEmpty(listItem.getGid2());
idValue = convertNullToEmpty(id.getGid2());
if (!patternMatch(
idValue.substring(0, Math.min(idValue.length(), listItemValue.length())),
listItemValue)) {
continue;
}
// Valid match was found in the list
return true;
}
return false;
}
private static String convertNullToEmpty(String value) {
return Objects.toString(value, "");
}
/**
* Performs a case insensitive string comparison against a given pattern. The character '?'
* is used in the pattern as wild character in the comparison. The string must have the same
* length as the pattern.
*
* @param str string to match
* @param pattern string containing the pattern
* @return true in case of match, false otherwise
*/
private static boolean patternMatch(String str, String pattern) {
if (str.length() != pattern.length()) {
return false;
}
String lowerCaseStr = str.toLowerCase();
String lowerCasePattern = pattern.toLowerCase();
for (int i = 0; i < lowerCasePattern.length(); i++) {
if (lowerCasePattern.charAt(i) != lowerCaseStr.charAt(i)
&& lowerCasePattern.charAt(i) != WILD_CHARACTER) {
return false;
}
}
return true;
}
/**
* {@link Parcelable#writeToParcel}
*/