Update SimPhonebookProvider for UCS-2 name encoding
This eliminates the need to check for unsupported characters and hence
name validation now only checks the encoded length.
Test: atest TeleServiceTests:SimPhonebookProviderTest
Bug: 154363919
Change-Id: Ifdc85751d1991e44da2e947ad5de8878ecc57ea2
diff --git a/src/com/android/phone/SimPhonebookProvider.java b/src/com/android/phone/SimPhonebookProvider.java
index 8307672..7a1e93c 100644
--- a/src/com/android/phone/SimPhonebookProvider.java
+++ b/src/com/android/phone/SimPhonebookProvider.java
@@ -59,7 +59,6 @@
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.List;
-import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
@@ -106,7 +105,6 @@
private static final int ELEMENTARY_FILES_ITEM = 101;
private static final int SIM_RECORDS = 200;
private static final int SIM_RECORDS_ITEM = 201;
- private static final int VALIDATE_NAME = 300;
static {
URI_MATCHER.addURI(SimPhonebookContract.AUTHORITY,
@@ -120,10 +118,6 @@
SimPhonebookContract.SUBSCRIPTION_ID_PATH_SEGMENT + "/#/*", SIM_RECORDS);
URI_MATCHER.addURI(SimPhonebookContract.AUTHORITY,
SimPhonebookContract.SUBSCRIPTION_ID_PATH_SEGMENT + "/#/*/#", SIM_RECORDS_ITEM);
- URI_MATCHER.addURI(SimPhonebookContract.AUTHORITY,
- SimPhonebookContract.SUBSCRIPTION_ID_PATH_SEGMENT + "/#/*/"
- + SimRecords.VALIDATE_NAME_PATH_SEGMENT,
- VALIDATE_NAME);
}
// Only allow 1 write at a time to prevent races; the mutations are based on reads of the
@@ -209,6 +203,31 @@
return true;
}
+ @Nullable
+ @Override
+ public Bundle call(@NonNull String method, @Nullable String arg, @Nullable Bundle extras) {
+ if (SimRecords.GET_ENCODED_NAME_LENGTH_METHOD_NAME.equals(method)) {
+ // No permissions checks needed. This isn't leaking any sensitive information since the
+ // name we are checking is provided by the caller.
+ return callForEncodedNameLength(arg);
+ }
+ return super.call(method, arg, extras);
+ }
+
+ private Bundle callForEncodedNameLength(String name) {
+ Bundle result = new Bundle();
+ result.putInt(SimRecords.EXTRA_ENCODED_NAME_LENGTH, getEncodedNameLength(name));
+ return result;
+ }
+
+ private int getEncodedNameLength(String name) {
+ if (Strings.isNullOrEmpty(name)) {
+ return 0;
+ } else {
+ byte[] encoded = AdnRecord.encodeAlphaTag(name);
+ return encoded.length;
+ }
+ }
@Nullable
@Override
@@ -231,8 +250,6 @@
case SIM_RECORDS_ITEM:
return querySimRecordsItem(PhonebookArgs.forSimRecordsItem(uri, queryArgs),
projection);
- case VALIDATE_NAME:
- return queryValidateName(PhonebookArgs.forValidateName(uri, queryArgs), queryArgs);
default:
throw new IllegalArgumentException("Unsupported Uri " + uri);
}
@@ -402,21 +419,6 @@
return result;
}
- private Cursor queryValidateName(PhonebookArgs args, @Nullable Bundle queryArgs) {
- if (queryArgs == null) {
- throw new IllegalArgumentException(SimRecords.NAME + " is required.");
- }
- validateSubscriptionAndEf(args);
- String name = queryArgs.getString(SimRecords.NAME);
-
- // Cursor extras are used to return the result.
- Cursor result = new MatrixCursor(new String[0], 0);
- Bundle extras = new Bundle();
- extras.putParcelable(SimRecords.EXTRA_NAME_VALIDATION_RESULT, validateName(args, name));
- result.setExtras(extras);
- return result;
- }
-
@Nullable
@Override
public String getType(@NonNull Uri uri) {
@@ -665,23 +667,6 @@
}
}
- private SimRecords.NameValidationResult validateName(
- PhonebookArgs args, @Nullable String name) {
- name = Strings.nullToEmpty(name);
- int recordSize = getRecordSize(getRecordsSizeForEf(args));
- // Validating the name consists of encoding the record in the binary format that it is
- // stored on the SIM then decoding it and checking whether the decoded name is the same.
- // The AOSP implementation of AdnRecord replaces unsupported characters with spaces during
- // encoding.
- // TODO: It would be good to update AdnRecord to support UCS-2 on the encode path (it
- // supports it on the decode path). Right now it's not supported and so any non-latin
- // characters will not be valid (at least in the AOSP implementation).
- byte[] encodedName = AdnRecord.encodeAlphaTag(name);
- String sanitizedName = AdnRecord.decodeAlphaTag(encodedName, 0, encodedName.length);
- return new SimRecords.NameValidationResult(name, sanitizedName,
- encodedName.length, AdnRecord.getMaxAlphaTagBytes(recordSize));
- }
-
private void validatePhoneNumber(@Nullable String phoneNumber) {
if (phoneNumber == null || phoneNumber.isEmpty()) {
throw new IllegalArgumentException(SimRecords.PHONE_NUMBER + " is required.");
@@ -715,13 +700,11 @@
validatePhoneNumber(phoneNumber);
String name = values.getAsString(SimRecords.NAME);
- SimRecords.NameValidationResult result = validateName(args, name);
+ int length = getEncodedNameLength(name);
+ int maxLength = AdnRecord.getMaxAlphaTagBytes(getRecordSize(getRecordsSizeForEf(args)));
- if (result.getEncodedLength() > result.getMaxEncodedLength()) {
+ if (length > maxLength) {
throw new IllegalArgumentException(SimRecords.NAME + " is too long.");
- } else if (!Objects.equals(result.getName(), result.getSanitizedName())) {
- throw new IllegalArgumentException(
- SimRecords.NAME + " contains unsupported characters.");
}
}
@@ -895,19 +878,6 @@
queryArgs);
}
- /**
- * Pattern: subid/${subscriptionId}/${efName}/validate_name
- *
- * @see SimRecords#validateName(ContentResolver, int, int, String)
- * @see #VALIDATE_NAME
- */
- static PhonebookArgs forValidateName(Uri uri, Bundle queryArgs) {
- int subscriptionId = parseSubscriptionIdFromUri(uri, 1);
- String efName = uri.getPathSegments().get(2);
- return PhonebookArgs.createFromEfName(
- uri, subscriptionId, efName, -1, queryArgs);
- }
-
private static int parseSubscriptionIdFromUri(Uri uri, int pathIndex) {
if (pathIndex == -1) {
return SubscriptionManager.INVALID_SUBSCRIPTION_ID;