Merge "TM#setNetworkSelectionModeAutomatic hang muliple minutes"
diff --git a/Android.bp b/Android.bp
index e7ca068..4357f12 100644
--- a/Android.bp
+++ b/Android.bp
@@ -15,6 +15,23 @@
// Build the Phone app which includes the emergency dialer. See Contacts
// for the 'other' dialer.
+package {
+ default_applicable_licenses: ["packages_services_Telephony_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "packages_services_Telephony_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
android_app {
name: "TeleService",
diff --git a/apex/Android.bp b/apex/Android.bp
index a7137d9..a0e5713 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "packages_services_Telephony_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["packages_services_Telephony_license"],
+}
+
apex_defaults {
name: "com.android.telephony-defaults",
@@ -9,6 +18,8 @@
key: "com.android.telephony.key",
certificate: ":com.android.telephony.certificate",
+
+ updatable: false,
}
apex {
diff --git a/apex/testing/Android.bp b/apex/testing/Android.bp
index 10455a4..1138b5e 100644
--- a/apex/testing/Android.bp
+++ b/apex/testing/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "packages_services_Telephony_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["packages_services_Telephony_license"],
+}
+
apex {
name: "test_com.android.telephony",
visibility: [
@@ -22,4 +31,4 @@
file_contexts: ":com.android.telephony-file_contexts",
// Test APEX, should never be installed
installable: false,
-}
\ No newline at end of file
+}
diff --git a/ecc/conversion_toolset_v1/proto/Android.bp b/ecc/conversion_toolset_v1/proto/Android.bp
index e1e0643..632ab40 100644
--- a/ecc/conversion_toolset_v1/proto/Android.bp
+++ b/ecc/conversion_toolset_v1/proto/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "packages_services_Telephony_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["packages_services_Telephony_license"],
+}
+
java_library_static {
name: "ecc-protos-lite",
proto: {
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;
diff --git a/testapps/EmbmsServiceTestApp/Android.bp b/testapps/EmbmsServiceTestApp/Android.bp
index e4a54cb..584e5bd 100644
--- a/testapps/EmbmsServiceTestApp/Android.bp
+++ b/testapps/EmbmsServiceTestApp/Android.bp
@@ -1,4 +1,13 @@
// Build the Sample Embms Services
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "packages_services_Telephony_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["packages_services_Telephony_license"],
+}
+
android_app {
name: "EmbmsTestService",
srcs: ["src/**/*.java"],
diff --git a/testapps/EmbmsTestDownloadApp/Android.bp b/testapps/EmbmsTestDownloadApp/Android.bp
index 63f4e83..c1b9425 100644
--- a/testapps/EmbmsTestDownloadApp/Android.bp
+++ b/testapps/EmbmsTestDownloadApp/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "packages_services_Telephony_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["packages_services_Telephony_license"],
+}
+
src_dirs = ["src"]
res_dirs = ["res"]
android_test {
diff --git a/testapps/EmbmsTestStreamingApp/Android.bp b/testapps/EmbmsTestStreamingApp/Android.bp
index 814c5ca..9f082ee 100644
--- a/testapps/EmbmsTestStreamingApp/Android.bp
+++ b/testapps/EmbmsTestStreamingApp/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "packages_services_Telephony_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["packages_services_Telephony_license"],
+}
+
android_test {
name: "EmbmsTestStreamingApp",
srcs: ["src/**/*.java"],
diff --git a/testapps/GbaTestApp/Android.bp b/testapps/GbaTestApp/Android.bp
index cb6df4e..b3c45dd 100644
--- a/testapps/GbaTestApp/Android.bp
+++ b/testapps/GbaTestApp/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "packages_services_Telephony_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["packages_services_Telephony_license"],
+}
+
android_test {
name: "GbaTestApp",
static_libs: [
diff --git a/testapps/ImsTestService/Android.bp b/testapps/ImsTestService/Android.bp
index a0b4edb..7073749 100644
--- a/testapps/ImsTestService/Android.bp
+++ b/testapps/ImsTestService/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "packages_services_Telephony_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["packages_services_Telephony_license"],
+}
+
android_app {
name: "ImsTestApp",
static_libs: [
diff --git a/testapps/SmsManagerTestApp/Android.bp b/testapps/SmsManagerTestApp/Android.bp
index 5333eab..e451b2d 100644
--- a/testapps/SmsManagerTestApp/Android.bp
+++ b/testapps/SmsManagerTestApp/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "packages_services_Telephony_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["packages_services_Telephony_license"],
+}
+
android_app {
name: "SmsManagerTestApp",
srcs: ["src/**/*.java"],
diff --git a/testapps/TelephonyManagerTestApp/Android.bp b/testapps/TelephonyManagerTestApp/Android.bp
index 8a37c99..e95d62f 100644
--- a/testapps/TelephonyManagerTestApp/Android.bp
+++ b/testapps/TelephonyManagerTestApp/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "packages_services_Telephony_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["packages_services_Telephony_license"],
+}
+
android_test {
name: "TelephonyManagerTestApp",
srcs: ["src/**/*.java"],
diff --git a/testapps/TelephonyRegistryTestApp/Android.bp b/testapps/TelephonyRegistryTestApp/Android.bp
index fec5286..2439461 100644
--- a/testapps/TelephonyRegistryTestApp/Android.bp
+++ b/testapps/TelephonyRegistryTestApp/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "packages_services_Telephony_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["packages_services_Telephony_license"],
+}
+
android_test {
name: "TelephonyRegistryTestApp",
srcs: ["src/**/*.java"],
diff --git a/testapps/TestRcsApp/TestApp/Android.bp b/testapps/TestRcsApp/TestApp/Android.bp
index dfa1f2e..49feff8 100644
--- a/testapps/TestRcsApp/TestApp/Android.bp
+++ b/testapps/TestRcsApp/TestApp/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "packages_services_Telephony_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["packages_services_Telephony_license"],
+}
+
android_app {
name: "TestRcsApp",
@@ -15,5 +24,3 @@
sdk_version: "system_current",
min_sdk_version: "30",
}
-
-
diff --git a/testapps/TestRcsApp/TestApp/AndroidManifest.xml b/testapps/TestRcsApp/TestApp/AndroidManifest.xml
index 6e52949..d57ec94 100644
--- a/testapps/TestRcsApp/TestApp/AndroidManifest.xml
+++ b/testapps/TestRcsApp/TestApp/AndroidManifest.xml
@@ -19,8 +19,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.android.sample.rcsclient"
- android:versionCode="3"
- android:versionName="1.0.2_UP1.0">
+ android:versionCode="4"
+ android:versionName="1.0.3">
<uses-sdk
android:minSdkVersion="30"
diff --git a/testapps/TestRcsApp/aosp_test_rcsclient/Android.bp b/testapps/TestRcsApp/aosp_test_rcsclient/Android.bp
index eef34c8..413b5e8 100644
--- a/testapps/TestRcsApp/aosp_test_rcsclient/Android.bp
+++ b/testapps/TestRcsApp/aosp_test_rcsclient/Android.bp
@@ -1,5 +1,24 @@
+package {
+ default_applicable_licenses: [
+ "packages_services_Telephony_testapps_TestRcsApp_aosp_test_rcsclient_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "packages_services_Telephony_testapps_TestRcsApp_aosp_test_rcsclient_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "LICENSE",
+ ],
+}
+
android_library {
name: "aosp_test_rcs_client_base",
@@ -23,5 +42,3 @@
sdk_version: "system_current",
min_sdk_version: "30",
}
-
-
diff --git a/testapps/TestRcsApp/aosp_test_rcsclient/javatests/com/android/libraries/rcs/simpleclient/protocol/cpim/SimpleCpimMessageTest.java b/testapps/TestRcsApp/aosp_test_rcsclient/javatests/com/android/libraries/rcs/simpleclient/protocol/cpim/SimpleCpimMessageTest.java
new file mode 100644
index 0000000..2dda33f
--- /dev/null
+++ b/testapps/TestRcsApp/aosp_test_rcsclient/javatests/com/android/libraries/rcs/simpleclient/protocol/cpim/SimpleCpimMessageTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.libraries.rcs.simpleclient.protocol.cpim;
+
+import static com.google.common.truth.Truth.assertThat;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class SimpleCpimMessageTest {
+ private static final String SAMPLE_CPIM =
+ "From: MR SANDERS <im:piglet@100akerwood.com>\r\n"
+ + "To: Depressed Donkey <im:eeyore@100akerwood.com>\r\n"
+ + "DateTime: 2000-12-13T13:40:00-08:00\r\n"
+ + "Subject: the weather will be fine today\r\n"
+ + "Subject:;lang=fr beau temps prevu pour aujourd'hui\r\n"
+ + "NS: MyFeatures <mid:MessageFeatures@id.foo.com>\r\n"
+ + "Require: MyFeatures.VitalMessageOption\r\n"
+ + "MyFeatures.VitalMessageOption: Confirmation-requested\r\n"
+ + "MyFeatures.WackyMessageOption: Use-silly-font\r\n"
+ + "\r\n"
+ + "Content-type: text/plain; charset=utf-8\r\n"
+ + "Content-ID: <1234567890@foo.com>\r\n"
+ + "\r\n"
+ + "body";
+
+ @Test
+ public void parse_successful() throws Exception {
+ SimpleCpimMessage cpim = SimpleCpimMessage.parse(SAMPLE_CPIM.getBytes(UTF_8));
+
+ assertThat(cpim.namespaces()).containsEntry("MyFeatures", "mid:MessageFeatures@id.foo.com");
+ assertThat(cpim.headers()).containsEntry("Require", "MyFeatures.VitalMessageOption");
+ assertThat(cpim.contentType()).isEqualTo("text/plain; charset=utf-8");
+ assertThat(cpim.content()).isEqualTo("body");
+ }
+}
diff --git a/testapps/TestRcsApp/aosp_test_rcsclient/javatests/com/android/libraries/rcs/simpleclient/service/chat/SimpleChatSessionTest.java b/testapps/TestRcsApp/aosp_test_rcsclient/javatests/com/android/libraries/rcs/simpleclient/service/chat/SimpleChatSessionTest.java
index 5c2e995..2723940 100644
--- a/testapps/TestRcsApp/aosp_test_rcsclient/javatests/com/android/libraries/rcs/simpleclient/service/chat/SimpleChatSessionTest.java
+++ b/testapps/TestRcsApp/aosp_test_rcsclient/javatests/com/android/libraries/rcs/simpleclient/service/chat/SimpleChatSessionTest.java
@@ -35,14 +35,14 @@
import gov.nist.javax.sip.message.SIPRequest;
import gov.nist.javax.sip.message.SIPResponse;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
import java.util.List;
import javax.sip.message.Message;
import javax.sip.message.Request;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
@RunWith(AndroidJUnit4.class)
public class SimpleChatSessionTest {
private static final String LOCAL_URI = "tel:+1234567890";
@@ -126,6 +126,16 @@
public String getPlaniHeader() {
return "IEEE-802.11;i-wlan-node-id=PLANI01EB5B0";
}
+
+ @Override
+ public String getUserAgentHeader() {
+ return "Test-Client";
+ }
+
+ @Override
+ public int getMaxPayloadSizeOnUdp() {
+ return 0;
+ }
};
private final SimpleRcsClientContext context =
new SimpleRcsClientContext(
diff --git a/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/protocol/cpim/CpimUtils.java b/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/protocol/cpim/CpimUtils.java
index b621257..6bb8eec 100644
--- a/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/protocol/cpim/CpimUtils.java
+++ b/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/protocol/cpim/CpimUtils.java
@@ -16,8 +16,9 @@
package com.android.libraries.rcs.simpleclient.protocol.cpim;
-import java.time.LocalDate;
import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
import java.util.Random;
/** Collections of utility functions for CPIM */
@@ -28,6 +29,7 @@
private CpimUtils() {
}
+ @SuppressWarnings("AndroidJdkLibsChecker")
public static SimpleCpimMessage createForText(String text) {
return SimpleCpimMessage.newBuilder()
.addNamespace("imdn", "urn:ietf:params:imdn")
@@ -35,7 +37,8 @@
.addHeader("imdn.Disposition-Notification", "positive-delivery, display")
.addHeader("To", ANONYMOUS_URI)
.addHeader("From", ANONYMOUS_URI)
- .addHeader("DateTime", LocalDate.now(ZoneId.systemDefault()).toString())
+ .addHeader("DateTime", ZonedDateTime.now(ZoneId.systemDefault()).format(
+ DateTimeFormatter.ISO_INSTANT))
.setContentType("text/plain")
.setContent(text)
.build();
@@ -43,6 +46,6 @@
private static String generateImdnMessageId() {
Random random = new Random();
- return "Test_" + random.nextLong();
+ return "Test_" + random.nextInt(1000000);
}
}
diff --git a/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/protocol/cpim/SimpleCpimMessage.java b/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/protocol/cpim/SimpleCpimMessage.java
index aeb6b11..e2efafe 100644
--- a/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/protocol/cpim/SimpleCpimMessage.java
+++ b/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/protocol/cpim/SimpleCpimMessage.java
@@ -16,11 +16,19 @@
package com.android.libraries.rcs.simpleclient.protocol.cpim;
+import android.text.TextUtils;
import com.google.auto.value.AutoValue;
+import com.google.common.base.Ascii;
import com.google.common.base.Utf8;
import com.google.common.collect.ImmutableMap;
-
+import com.google.common.io.CharStreams;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
* The CPIM implementation as per RFC 3862. This class supports minimal fields that is required to
@@ -30,10 +38,9 @@
public abstract class SimpleCpimMessage {
private static final String CRLF = "\r\n";
private static final String COLSP = ": ";
-
- public static SimpleCpimMessage.Builder newBuilder() {
- return new AutoValue_SimpleCpimMessage.Builder();
- }
+ private static final Pattern NAMESPACE_HEADER_PATTERN =
+ Pattern.compile("NS:\\s+(\\S+)\\s+<(.+)>");
+ private static final Pattern HEADER_PATTERN = Pattern.compile("([^\\s:]+):\\s+(.+)");
public abstract ImmutableMap<String, String> namespaces();
@@ -61,13 +68,50 @@
builder.append(CRLF);
builder.append("Content-Type").append(COLSP).append(contentType());
- builder.append("Content-Length").append(COLSP).append(Utf8.encodedLength(content()));
builder.append(CRLF);
+ builder.append("Content-Length").append(COLSP).append(Utf8.encodedLength(content()));
+ builder.append(CRLF).append(CRLF);
builder.append(content());
return builder.toString();
}
+ public static SimpleCpimMessage parse(byte[] content) throws IOException {
+ BufferedReader reader =
+ new BufferedReader(new InputStreamReader(new ByteArrayInputStream(content)));
+ Builder builder = newBuilder();
+
+ String line = reader.readLine();
+ while (!TextUtils.isEmpty(line)) {
+ Matcher namespaceMatcher = NAMESPACE_HEADER_PATTERN.matcher(line);
+ Matcher headerMatcher = HEADER_PATTERN.matcher(line);
+ if (namespaceMatcher.matches()) {
+ builder.addNamespace(namespaceMatcher.group(1), namespaceMatcher.group(2));
+ } else if (headerMatcher.matches()) {
+ builder.addHeader(headerMatcher.group(1), headerMatcher.group(2));
+ }
+
+ line = reader.readLine();
+ }
+
+ line = reader.readLine();
+ while (!TextUtils.isEmpty(line)) {
+ Matcher headerMatcher = HEADER_PATTERN.matcher(line);
+ if (headerMatcher.matches()) {
+ if (Ascii.equalsIgnoreCase("content-type", headerMatcher.group(1))) {
+ builder.setContentType(headerMatcher.group(2));
+ }
+ }
+
+ line = reader.readLine();
+ }
+
+ String body = CharStreams.toString(reader);
+ builder.setContent(body);
+
+ return builder.build();
+ }
+
@AutoValue.Builder
public abstract static class Builder {
public abstract ImmutableMap.Builder<String, String> namespacesBuilder();
@@ -90,4 +134,8 @@
return this;
}
}
+
+ public static SimpleCpimMessage.Builder newBuilder() {
+ return new AutoValue_SimpleCpimMessage.Builder();
+ }
}
diff --git a/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/protocol/msrp/MsrpConstants.java b/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/protocol/msrp/MsrpConstants.java
index ad1b98e..ba424c6 100644
--- a/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/protocol/msrp/MsrpConstants.java
+++ b/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/protocol/msrp/MsrpConstants.java
@@ -44,8 +44,12 @@
public static final String HEADER_TO_PATH = "To-Path";
public static final String HEADER_FROM_PATH = "From-Path";
public static final String HEADER_FAILURE_REPORT = "Failure-Report";
+ public static final String HEADER_SUCCESS_REPORT = "Success-Report";
+ public static final String REPORT_VALUE_YES = "yes";
+ public static final String REPORT_VALUE_NO = "no";
+
public static final int RESPONSE_CODE_OK = 200;
private MsrpConstants() {
}
-}
\ No newline at end of file
+}
diff --git a/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/protocol/sip/SipUtils.java b/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/protocol/sip/SipUtils.java
index 2f95bef..7605fb5 100644
--- a/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/protocol/sip/SipUtils.java
+++ b/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/protocol/sip/SipUtils.java
@@ -22,7 +22,8 @@
import android.text.TextUtils;
import android.util.Log;
-import com.android.libraries.rcs.simpleclient.protocol.sdp.SdpUtils;
+import androidx.annotation.Nullable;
+
import com.android.libraries.rcs.simpleclient.protocol.sdp.SimpleSdpMessage;
import com.google.common.base.Ascii;
@@ -259,7 +260,7 @@
request.setCallId(invite.getCallId());
- Via via = (Via) request.getTopmostVia().clone();
+ Via via = (Via) invite.getTopmostVia().clone();
via.removeParameter("branch");
request.addHeader(via);
request.addHeader(
@@ -280,12 +281,13 @@
* @param code The status code of the response.
*/
public static SIPResponse buildInviteResponse(
- SipSessionConfiguration configuration, SIPRequest invite, int code)
+ SipSessionConfiguration configuration,
+ SIPRequest invite,
+ int code,
+ @Nullable SimpleSdpMessage sdp)
throws ParseException {
SIPResponse response = invite.createResponse(code);
if (code == Response.OK) {
- SimpleSdpMessage sdp = SdpUtils.createSdpForMsrp(configuration.getLocalIpAddress(),
- false);
response.setMessageContent(SDP_CONTENT_TYPE, SDP_CONTENT_SUB_TYPE, sdp.encode());
}
diff --git a/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/service/chat/MinimalCpmChatService.java b/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/service/chat/MinimalCpmChatService.java
index 01a1061..b204de6 100644
--- a/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/service/chat/MinimalCpmChatService.java
+++ b/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/service/chat/MinimalCpmChatService.java
@@ -21,6 +21,8 @@
import android.text.TextUtils;
import android.util.Log;
+import androidx.annotation.Nullable;
+
import com.android.libraries.rcs.simpleclient.SimpleRcsClientContext;
import com.android.libraries.rcs.simpleclient.protocol.msrp.MsrpManager;
import com.android.libraries.rcs.simpleclient.protocol.sip.SipSession;
@@ -45,8 +47,6 @@
import javax.sip.message.Request;
import javax.sip.message.Response;
-import androidx.annotation.Nullable;
-
/**
* Minimal CPM chat session service that provides the interface creating a {@link SimpleChatSession}
* instance using {@link SipDelegateConnection}.
@@ -162,7 +162,8 @@
SipUtils.buildInviteResponse(
mContext.getSipSession().getSessionConfiguration(),
request,
- Response.METHOD_NOT_ALLOWED);
+ Response.METHOD_NOT_ALLOWED,
+ null);
sendSipResponse(response, /* session= */ null)
.addListener(() -> {
}, MoreExecutors.directExecutor());
diff --git a/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/service/chat/SimpleChatSession.java b/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/service/chat/SimpleChatSession.java
index 74472d7..6813c91 100644
--- a/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/service/chat/SimpleChatSession.java
+++ b/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/service/chat/SimpleChatSession.java
@@ -31,6 +31,7 @@
import com.android.libraries.rcs.simpleclient.protocol.cpim.SimpleCpimMessage;
import com.android.libraries.rcs.simpleclient.protocol.msrp.MsrpChunk;
import com.android.libraries.rcs.simpleclient.protocol.msrp.MsrpChunk.Continuation;
+import com.android.libraries.rcs.simpleclient.protocol.msrp.MsrpChunkHeader;
import com.android.libraries.rcs.simpleclient.protocol.msrp.MsrpConstants;
import com.android.libraries.rcs.simpleclient.protocol.msrp.MsrpManager;
import com.android.libraries.rcs.simpleclient.protocol.msrp.MsrpSession;
@@ -109,6 +110,8 @@
// Build a new CPIM message and send it out through the MSRP session.
SimpleCpimMessage cpim = CpimUtils.createForText(msg);
+ Log.i(TAG, "Encoded CPIM:" + cpim.encode());
+
byte[] content = cpim.encode().getBytes(UTF_8);
MsrpChunk msrpChunk =
MsrpChunk.newBuilder()
@@ -118,12 +121,18 @@
.continuation(Continuation.COMPLETE)
.addHeader(MsrpConstants.HEADER_TO_PATH, mRemoteSdp.getPath().get())
.addHeader(MsrpConstants.HEADER_FROM_PATH, mLocalSdp.getPath().get())
+ .addHeader(MsrpConstants.HEADER_FAILURE_REPORT,
+ MsrpConstants.REPORT_VALUE_YES)
+ .addHeader(MsrpConstants.HEADER_SUCCESS_REPORT,
+ MsrpConstants.REPORT_VALUE_NO)
.addHeader(
MsrpConstants.HEADER_BYTE_RANGE,
String.format("1-%d/%d", content.length, content.length))
.addHeader(MsrpConstants.HEADER_MESSAGE_ID, MsrpUtils.generateRandomId())
.addHeader(MsrpConstants.HEADER_CONTENT_TYPE, CPIM_CONTENT_TYPE)
.build();
+
+ Log.i(TAG, "Send a MSRP chunk: " + msrpChunk);
Futures.addCallback(
session.send(msrpChunk),
new FutureCallback<MsrpChunk>() {
@@ -213,11 +222,13 @@
updateRemoteUri(mInviteRequest);
+ SipSessionConfiguration configuration = mContext.getSipSession().getSessionConfiguration();
+ SimpleSdpMessage sdp = SdpUtils.createSdpForMsrp(configuration.getLocalIpAddress(), false);
+
// Automatically reply back to the invite by building a pre-canned response.
try {
- SIPResponse response =
- SipUtils.buildInviteResponse(
- mContext.getSipSession().getSessionConfiguration(), invite, statusCode);
+ SIPResponse response = SipUtils.buildInviteResponse(configuration, invite, statusCode,
+ sdp);
return Futures.transform(
mService.sendSipResponse(response, this), result -> null,
MoreExecutors.directExecutor());
@@ -339,41 +350,53 @@
return;
}
+ SimpleSdpMessage sdp;
try {
- SimpleSdpMessage sdp =
- SimpleSdpMessage.parse(new ByteArrayInputStream(response.getRawContent()));
- startMsrpSession(sdp);
+ sdp = SimpleSdpMessage.parse(new ByteArrayInputStream(response.getRawContent()));
} catch (ParseException | IOException e) {
notifyFailure("Invalid SDP in INVITE", CODE_ERROR_UNSPECIFIED);
+ return;
}
- if (mInviteRequest != null) {
- SIPRequest ack = mInviteRequest.createAckRequest((To) response.getToHeader());
- Futures.addCallback(
- mService.sendSipRequest(ack, this),
- new FutureCallback<Boolean>() {
- @Override
- public void onSuccess(Boolean result) {
- if (result) {
- mStartFuture.set(null);
- mStartFuture = null;
- } else {
- notifyFailure("Failed to send ACK", CODE_ERROR_UNSPECIFIED);
- }
- }
+ if (mInviteRequest == null) {
+ notifyFailure("No INVITE request sent out", CODE_ERROR_UNSPECIFIED);
+ return;
+ }
- @Override
- public void onFailure(Throwable t) {
+ SIPRequest ack = mInviteRequest.createAckRequest((To) response.getToHeader());
+ Futures.addCallback(
+ mService.sendSipRequest(ack, this),
+ new FutureCallback<Boolean>() {
+ @Override
+ public void onSuccess(Boolean result) {
+ if (result) {
+ startMsrpSession(sdp);
+ mRemoteSdp = sdp;
+ } else {
notifyFailure("Failed to send ACK", CODE_ERROR_UNSPECIFIED);
}
- },
- MoreExecutors.directExecutor());
- }
+ }
+
+ @Override
+ public void onFailure(Throwable t) {
+ notifyFailure("Failed to send ACK", CODE_ERROR_UNSPECIFIED);
+ }
+ },
+ MoreExecutors.directExecutor());
}
private void notifyFailure(String message, @ErrorCode int code) {
- mStartFuture.setException(new ChatServiceException(message, code));
- mStartFuture = null;
+ if (mStartFuture != null) {
+ mStartFuture.setException(new ChatServiceException(message, code));
+ mStartFuture = null;
+ }
+ }
+
+ private void notifySuccess() {
+ if (mStartFuture != null) {
+ mStartFuture.set(null);
+ mStartFuture = null;
+ }
}
private void startMsrpSession(SimpleSdpMessage remoteSdp) {
@@ -387,16 +410,17 @@
@Override
public void onSuccess(MsrpSession result) {
mMsrpSession = result;
+ notifySuccess();
}
@Override
public void onFailure(Throwable t) {
Log.e(TAG, "Failed to create msrp session", t);
+ notifyFailure("Failed to establish msrp session",
+ CODE_ERROR_UNSPECIFIED);
terminate()
.addListener(
- () -> {
- Log.d(TAG, "Session terminated");
- },
+ () -> Log.d(TAG, "Session terminated"),
MoreExecutors.directExecutor());
}
},
@@ -408,11 +432,29 @@
private void receiveMsrpChunk(MsrpChunk chunk) {
Log.d(TAG, "Received msrp= " + chunk + " conversation=" + mConversationId);
- if (mListener != null) {
- // TODO(b/173186571): Parse CPIM and invoke onMessageReceived()
+
+ MsrpChunkHeader contentTypeHeader = chunk.header("Content-Type");
+ if (chunk.content().length == 0 || contentTypeHeader == null) {
+ Log.i(TAG, "No content or Content-Type header, drop it");
+ return;
+ }
+
+ String contentType = contentTypeHeader.value();
+ if ("message/cpim".equals(contentType)) {
+ try {
+ SimpleCpimMessage cpim = SimpleCpimMessage.parse(chunk.content());
+ if (mListener != null) {
+ mListener.onMessageReceived(cpim);
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Error while parsing cpim message.", e);
+ }
+ } else {
+ Log.w(TAG, contentType + " is not supported.");
}
}
+
/** Set new listener for this session. */
public void setListener(@Nullable ChatSessionListener listener) {
mListener = listener;
diff --git a/tests/Android.bp b/tests/Android.bp
index 4eacf6d..c180476 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "packages_services_Telephony_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["packages_services_Telephony_license"],
+}
+
android_test {
name: "TeleServiceTests",
@@ -50,4 +59,3 @@
],
}
-
diff --git a/tests/src/com/android/phone/SimPhonebookProviderTest.java b/tests/src/com/android/phone/SimPhonebookProviderTest.java
index 1d48694..8778529 100644
--- a/tests/src/com/android/phone/SimPhonebookProviderTest.java
+++ b/tests/src/com/android/phone/SimPhonebookProviderTest.java
@@ -78,10 +78,7 @@
@RunWith(AndroidJUnit4.class)
public final class SimPhonebookProviderTest {
- // Emojis aren't currently supported for the ADN record label.
private static final String EMOJI = new String(Character.toChars(0x1F642));
- private static final String UNSUPPORTED_NAME = ":)=" + EMOJI + ";ni=日;hon=本;";
- private static final String UNSUPPORTED_NAME2 = "日本" + EMOJI;
private static final Correspondence<AdnRecord, AdnRecord> ADN_RECORD_IS_EQUAL =
Correspondence.from(AdnRecord::isEqual, "isEqual");
@@ -674,6 +671,30 @@
}
@Test
+ public void insert_nameWithNonGsmCharacters_addsAdnRecord() {
+ setupSimsWithSubscriptionIds(1);
+ mIccPhoneBook.makeAllEfsSupported(1);
+
+ ContentValues values = new ContentValues();
+ String name = "abc日本" + EMOJI;
+ values.put(SimRecords.NAME, name);
+ values.put(SimRecords.PHONE_NUMBER, "8005550101");
+
+ Uri uri = mResolver.insert(SimRecords.getContentUri(1, EF_ADN), values);
+
+ List<AdnRecord> records = mIccPhoneBook.getAdnRecordsInEfForSubscriber(
+ 1, IccConstants.EF_ADN).stream()
+ .filter(((Predicate<AdnRecord>) AdnRecord::isEmpty).negate())
+ .collect(Collectors.toList());
+
+ assertThat(records)
+ .comparingElementsUsing(ADN_RECORD_IS_EQUAL)
+ .containsExactly(new AdnRecord(IccConstants.EF_ADN, 1, name, "8005550101"));
+
+ assertThat(uri).isEqualTo(SimRecords.getItemUri(1, ElementaryFiles.EF_ADN, 1));
+ }
+
+ @Test
public void insert_nullValues_returnsNull() {
setupSimsWithSubscriptionIds(1);
mIccPhoneBook.makeAllEfsSupported(1);
@@ -753,7 +774,7 @@
mIccPhoneBook.setRecordsSize(1, IccConstants.EF_ADN, 1, 25);
ContentValues values = new ContentValues();
- // Name is limited to 11 characters
+ // Name is limited to 11 characters when the max record size is 25
values.put(SimRecords.NAME, "1234567890ab");
values.put(SimRecords.PHONE_NUMBER, "8005550102");
@@ -761,6 +782,13 @@
() -> mResolver.insert(SimRecords.getContentUri(1, EF_ADN), values));
assertThat(e).hasMessageThat().isEqualTo(SimRecords.NAME + " is too long.");
+
+ // 2 bytes per character and 4 for the emoji. So this is 14 characters long.
+ values.put(SimRecords.NAME, "abc日本" + EMOJI);
+ e = assertThrows(IllegalArgumentException.class,
+ () -> mResolver.insert(SimRecords.getContentUri(1, EF_ADN), values));
+
+ assertThat(e).hasMessageThat().isEqualTo(SimRecords.NAME + " is too long.");
}
@Test
@@ -780,36 +808,22 @@
}
@Test
- public void insert_illegalCharacters_throwsCorrectException() {
+ public void insert_numberWithInvalidCharacters_throwsCorrectException() {
setupSimsWithSubscriptionIds(1);
mIccPhoneBook.setRecordsSize(1, IccConstants.EF_ADN, 1, 32);
ContentValues values = new ContentValues();
values.put(SimRecords.NAME, "Name");
- values.put(SimRecords.PHONE_NUMBER, "1800J550A0B");
+ values.put(SimRecords.PHONE_NUMBER, "(800)555-0190 x7777");
IllegalArgumentException e = assertThrows(IllegalArgumentException.class,
- () -> mResolver.insert(SimRecords.getContentUri(1, EF_ADN), values));
+ () -> mResolver.insert(SimRecords.getContentUri(1, ElementaryFiles.EF_ADN),
+ values,
+ null));
assertThat(e).hasMessageThat().isEqualTo(
SimRecords.PHONE_NUMBER + " contains unsupported characters.");
- values.put(SimRecords.NAME, UNSUPPORTED_NAME);
- values.put(SimRecords.PHONE_NUMBER, "18005550101");
-
- e = assertThrows(IllegalArgumentException.class,
- () -> mResolver.insert(SimRecords.getContentUri(1, EF_ADN), values));
- assertThat(e).hasMessageThat().isEqualTo(
- SimRecords.NAME + " contains unsupported characters.");
-
- values.put(SimRecords.NAME, UNSUPPORTED_NAME2);
- values.put(SimRecords.PHONE_NUMBER, "18005550101");
-
- e = assertThrows(IllegalArgumentException.class,
- () -> mResolver.insert(SimRecords.getContentUri(1, EF_ADN), values));
- assertThat(e).hasMessageThat().isEqualTo(
- SimRecords.NAME + " contains unsupported characters.");
-
- // The inserts didn't actually add any data.
+ // The insert didn't actually change the data.
assertThat(mIccPhoneBook.getAllValidRecords()).isEmpty();
}
@@ -996,7 +1010,7 @@
}
@Test
- public void update_nameOrNumberWithInvalidCharacters_throwsCorrectException() {
+ public void update_numberWithInvalidCharacters_throwsCorrectException() {
setupSimsWithSubscriptionIds(1);
mIccPhoneBook.setRecordsSize(1, IccConstants.EF_ADN, 1, 32);
mIccPhoneBook.addRecord(1, IccConstants.EF_ADN, "Initial", "8005550101");
@@ -1012,18 +1026,7 @@
assertThat(e).hasMessageThat().isEqualTo(
SimRecords.PHONE_NUMBER + " contains unsupported characters.");
- // Unicode fffe is a unicode non-character
- values.put(SimRecords.NAME, UNSUPPORTED_NAME);
- values.put(SimRecords.PHONE_NUMBER, "18005550102");
-
- e = assertThrows(IllegalArgumentException.class,
- () -> mResolver.update(SimRecords.getItemUri(1, ElementaryFiles.EF_ADN, 1),
- values,
- null));
- assertThat(e).hasMessageThat().isEqualTo(
- SimRecords.NAME + " contains unsupported characters.");
-
- // The updates didn't actually change the data.
+ // The update didn't actually change the data.
assertThat(mIccPhoneBook.getAllValidRecords())
.comparingElementsUsing(Correspondence.from(AdnRecord::isEqual, "isEqual"))
.containsExactly(new AdnRecord(IccConstants.EF_ADN, 1, "Initial", "8005550101"));
@@ -1179,76 +1182,26 @@
}
@Test
- public void validateName_validName_returnsValueIsCorrect() {
- setupSimsWithSubscriptionIds(1);
- String validName = "First Last";
- // See AdnRecord#FOOTER_SIZE_BYTES
- mIccPhoneBook.setRecordsSize(1, IccConstants.EF_ADN, 10, validName.length() + 14);
- SimRecords.NameValidationResult validationResult = SimRecords.validateName(mResolver, 1,
- EF_ADN, validName);
+ public void getEncodedNameLength_returnsValueIsCorrect() {
+ String name = "";
+ int length = SimRecords.getEncodedNameLength(mResolver, name);
+ assertThat(length).isEqualTo(0);
- assertThat(validationResult.isValid()).isTrue();
- assertThat(validationResult.getName()).isEqualTo(validName);
- assertThat(validationResult.getSanitizedName()).isEqualTo(validName);
- assertThat(validationResult.getEncodedLength()).isEqualTo(validName.length());
- assertThat(validationResult.getMaxEncodedLength()).isEqualTo(validName.length());
+ name = "First Last";
+ length = SimRecords.getEncodedNameLength(mResolver, name);
+ assertThat(length).isEqualTo(name.length());
- mIccPhoneBook.setRecordsSize(1, IccConstants.EF_ADN, 10, 40);
- validationResult = SimRecords.validateName(mResolver, 1, EF_ADN, validName);
- assertThat(validationResult.getMaxEncodedLength()).isEqualTo(40 - 14);
- }
+ name = "日本";
+ length = SimRecords.getEncodedNameLength(mResolver, name);
+ assertThat(length).isEqualTo(name.length() * 2 + 1);
- @Test
- public void validateName_nameTooLong_returnsValueIsCorrect() {
- setupSimsWithSubscriptionIds(1);
- String tooLongName = "First Last";
- mIccPhoneBook.setRecordsSize(1, IccConstants.EF_ADN, 10, tooLongName.length() + 14 - 1);
- SimRecords.NameValidationResult validationResult = SimRecords.validateName(mResolver, 1,
- EF_ADN, tooLongName);
+ name = EMOJI;
+ length = SimRecords.getEncodedNameLength(mResolver, name);
+ assertThat(length).isEqualTo(name.length() * 2 + 1);
- assertThat(validationResult.isValid()).isFalse();
- assertThat(validationResult.getName()).isEqualTo(tooLongName);
- assertThat(validationResult.getSanitizedName()).isEqualTo(tooLongName);
- assertThat(validationResult.getEncodedLength()).isEqualTo(tooLongName.length());
- assertThat(validationResult.getMaxEncodedLength()).isEqualTo(tooLongName.length() - 1);
- }
-
- @Test
- public void validateName_nameWithUnsupportedCharacters_returnsValueIsCorrect() {
- setupSimsWithSubscriptionIds(1);
- mIccPhoneBook.setRecordsSize(1, IccConstants.EF_ADN, 10, 40);
- SimRecords.NameValidationResult validationResult = SimRecords.validateName(mResolver, 1,
- EF_ADN, UNSUPPORTED_NAME);
-
- assertThat(validationResult.isValid()).isFalse();
- assertThat(validationResult.getName()).isEqualTo(UNSUPPORTED_NAME);
- assertThat(validationResult.getSanitizedName()).isEqualTo(":)= ;ni= ;hon= ;");
- assertThat(validationResult.getEncodedLength()).isEqualTo(UNSUPPORTED_NAME.length());
- assertThat(validationResult.getMaxEncodedLength()).isEqualTo(
- AdnRecord.getMaxAlphaTagBytes(40));
- }
-
- @Test
- public void validateName_emptyString_returnsValueIsCorrect() {
- setupSimsWithSubscriptionIds(1);
- mIccPhoneBook.setRecordsSize(1, IccConstants.EF_ADN, 10, 40);
- SimRecords.NameValidationResult validationResult = SimRecords.validateName(mResolver, 1,
- EF_ADN, "");
-
- assertThat(validationResult.isValid()).isTrue();
- assertThat(validationResult.getName()).isEqualTo("");
- assertThat(validationResult.getSanitizedName()).isEqualTo("");
- assertThat(validationResult.getEncodedLength()).isEqualTo(0);
- assertThat(validationResult.getMaxEncodedLength()).isEqualTo(
- AdnRecord.getMaxAlphaTagBytes(40));
-
- // Null is equivalent to empty
- validationResult = SimRecords.validateName(mResolver, 1, EF_ADN, null);
- assertThat(validationResult.getName()).isEqualTo("");
- assertThat(validationResult.getSanitizedName()).isEqualTo("");
- assertThat(validationResult.getEncodedLength()).isEqualTo(0);
- assertThat(validationResult.getMaxEncodedLength()).isEqualTo(
- AdnRecord.getMaxAlphaTagBytes(40));
+ name = "abc日本" + EMOJI;
+ length = SimRecords.getEncodedNameLength(mResolver, name);
+ assertThat(length).isEqualTo(name.length() * 2 + 1);
}
private void setupSimsWithSubscriptionIds(int... subscriptionIds) {