diff options
author | Andrew Cheng <chengandrew@google.com> | 2021-10-26 11:26:55 -0700 |
---|---|---|
committer | Andrew Cheng <chengca@google.com> | 2021-11-18 18:43:56 +0000 |
commit | b20bb3bcef5bde1ef05117f2dfc6571c284969f2 (patch) | |
tree | ddcd3c9846c98a2d3334ff7e1d2501c9cc53cd02 | |
parent | fffb220a0a695485714a4a9d08f69aaa4bd2e7be (diff) | |
download | vcard-b20bb3bcef5bde1ef05117f2dfc6571c284969f2.tar.gz |
Bluetooth sync adr-type "other" between two devices
{@link ContactsContract} has a {@link StructuredPostal.TYPE_OTHER}.
However, when a vCard is created in {@link VCardBuilder}, {@code
TYPE_OTHER} does not get mapped to anything, i.e., the {@code ADR} entry
in the vCard does not have a {@code TYPE=}. Then, when a vCard is parsed
in {@link VCardEntry}, it will get a null String when trying to get the
address's {@code TYPE=}, which it will then default to {@link
StructuredPostal.TYPE_HOME}.
As a result, if a user syncs contact information between two Android
devices using vCards (e.g., over Bluetooth), an address marked as type
"Other" on the source device will appear as type "Home" on the sink
device.
To correctly sync the type "Other", this CL uses the existing framework
in the vcard package that handles {@link ContactsContract}'s custom
types, i.e., prepending with "X-". According to RFC 2426, this
constitutes a valid "x-name", which constitutes a valid "adr-type".
Bug: 197177611
Test: atest AndroidVCardTests
Test: (Manual) Create a contact with address of type "other". Sync the
contact to a second device. Verify on the second device that the address
is still of type "other", and not of type "home". Also, in the Bluetooth
HCI snoop logs, look for the raw vCards, and verify in the "ADR" entry,
there is a "TYPE=X-OTHER". Note, both devices must be Android.
Change-Id: I47217041e52d2d1c57b206bf88cc3b763baae418
-rw-r--r-- | java/com/android/vcard/VCardBuilder.java | 4 | ||||
-rw-r--r-- | java/com/android/vcard/VCardConstants.java | 2 | ||||
-rw-r--r-- | java/com/android/vcard/VCardEntry.java | 7 | ||||
-rw-r--r-- | tests/res/raw/v30_adr_types.vcf | 8 | ||||
-rw-r--r-- | tests/src/com/android/vcard/tests/VCardExporterTests.java | 40 | ||||
-rw-r--r-- | tests/src/com/android/vcard/tests/VCardImporterTests.java | 28 | ||||
-rw-r--r-- | tests/src/com/android/vcard/tests/VCardJapanizationTests.java | 5 |
7 files changed, 93 insertions, 1 deletions
diff --git a/java/com/android/vcard/VCardBuilder.java b/java/com/android/vcard/VCardBuilder.java index d273347..c938d04 100644 --- a/java/com/android/vcard/VCardBuilder.java +++ b/java/com/android/vcard/VCardBuilder.java @@ -1489,6 +1489,10 @@ public class VCardBuilder { break; } case StructuredPostal.TYPE_OTHER: { + // {@code TYPE_OTHER} will be treated as a "custom type" in that a "X-" will be + // similarly prepended. According to RFC 2426, this constitutes a valid "x-name", + // which constitutes a valid "adr-type". + parameterList.add("X-" + VCardConstants.PARAM_ADR_EXTRA_TYPE_OTHER); break; } default: { diff --git a/java/com/android/vcard/VCardConstants.java b/java/com/android/vcard/VCardConstants.java index 67c07b7..ed0c34e 100644 --- a/java/com/android/vcard/VCardConstants.java +++ b/java/com/android/vcard/VCardConstants.java @@ -153,6 +153,8 @@ public class VCardConstants { public static final String PARAM_ADR_TYPE_PARCEL = "PARCEL"; public static final String PARAM_ADR_TYPE_DOM = "DOM"; public static final String PARAM_ADR_TYPE_INTL = "INTL"; + // {@link VCardBuilder} translates this type to "X-OTHER". + public static final String PARAM_ADR_EXTRA_TYPE_OTHER = "OTHER"; public static final String PARAM_LANGUAGE = "LANGUAGE"; diff --git a/java/com/android/vcard/VCardEntry.java b/java/com/android/vcard/VCardEntry.java index ee60578..8054bb7 100644 --- a/java/com/android/vcard/VCardEntry.java +++ b/java/com/android/vcard/VCardEntry.java @@ -2223,6 +2223,13 @@ public class VCardEntry { } else { label = typeStringOrg; } + // {@link ContactsContract} has a {@link StructuredPostal.TYPE_OTHER}, so + // if the custom type is "other", map it from {@code TYPE_CUSTOM} to + // {@code TYPE_OTHER}. + if (VCardConstants.PARAM_ADR_EXTRA_TYPE_OTHER.equals(label.toUpperCase())) { + type = StructuredPostal.TYPE_OTHER; + label = null; + } } } } diff --git a/tests/res/raw/v30_adr_types.vcf b/tests/res/raw/v30_adr_types.vcf new file mode 100644 index 0000000..55dd1b4 --- /dev/null +++ b/tests/res/raw/v30_adr_types.vcf @@ -0,0 +1,8 @@ +BEGIN:VCARD
+VERSION:3.0
+N:Familyname;Givenname;;;
+FN:Givenname Familyname
+ADR;TYPE=WORK:;;1010 Technology Pkwy\, Silicon City\, Somecountry;;;;
+ADR;TYPE=X-Other:;;123 Main St\, Anytown\, Anywhere;;;;
+ADR;TYPE=X-School:;;112358 Academic Lane\, College Town\, Someplace Great;;;;
+END:VCARD
diff --git a/tests/src/com/android/vcard/tests/VCardExporterTests.java b/tests/src/com/android/vcard/tests/VCardExporterTests.java index 42f9445..d83ca40 100644 --- a/tests/src/com/android/vcard/tests/VCardExporterTests.java +++ b/tests/src/com/android/vcard/tests/VCardExporterTests.java @@ -17,6 +17,7 @@ package com.android.vcard.tests; import com.android.vcard.VCardConfig; +import com.android.vcard.VCardConstants; import com.android.vcard.tests.testutils.ContactEntry; import com.android.vcard.tests.testutils.PropertyNodesVerifierElem; import com.android.vcard.tests.testutils.PropertyNodesVerifierElem.TypeSet; @@ -885,6 +886,45 @@ public class VCardExporterTests extends VCardTestsBase { testPostalWithBothStructuredAndFormattedCommon(V40); } + private void testPostalAddressTypeHandlingCommon(int vcardType) { + mVerifier.initForExportTest(vcardType); + + ContactEntry entry = mVerifier.addInputEntry(); + entry.addContentValues(StructuredPostal.CONTENT_ITEM_TYPE) + .put(StructuredPostal.STREET, "1010 Technology Pkwy") + .put(StructuredPostal.TYPE, StructuredPostal.TYPE_WORK); + entry.addContentValues(StructuredPostal.CONTENT_ITEM_TYPE) + .put(StructuredPostal.STREET, "123 Main St") + .put(StructuredPostal.TYPE, StructuredPostal.TYPE_OTHER); + entry.addContentValues(StructuredPostal.CONTENT_ITEM_TYPE) + .put(StructuredPostal.STREET, "112358 Academic Lane") + .put(StructuredPostal.TYPE, StructuredPostal.TYPE_CUSTOM) + .put(StructuredPostal.LABEL, "School"); + + PropertyNodesVerifierElem elem = mVerifier.addPropertyNodesVerifierElemWithEmptyName(); + elem.addExpectedNode("ADR", + Arrays.asList("", "", "1010 Technology Pkwy", "", "", "", ""), + new TypeSet(VCardConstants.PARAM_TYPE_WORK)); + elem.addExpectedNode("ADR", + Arrays.asList("", "", "123 Main St", "", "", "", ""), + new TypeSet("X-" + VCardConstants.PARAM_ADR_EXTRA_TYPE_OTHER)); + elem.addExpectedNode("ADR", + Arrays.asList("", "", "112358 Academic Lane", "", "", "", ""), + new TypeSet("X-School")); + } + + public void testPostalAddressTypeHandlingV21() { + testPostalAddressTypeHandlingCommon(V21); + } + + public void testPostalAddressTypeHandlingV30() { + testPostalAddressTypeHandlingCommon(V30); + } + + public void testPostalAddressTypeHandlingV40() { + testPostalAddressTypeHandlingCommon(V40); + } + private void testOrganizationCommon(int vcardType) { mVerifier.initForExportTest(vcardType); ContactEntry entry = mVerifier.addInputEntry(); diff --git a/tests/src/com/android/vcard/tests/VCardImporterTests.java b/tests/src/com/android/vcard/tests/VCardImporterTests.java index 7b4e669..b4713d0 100644 --- a/tests/src/com/android/vcard/tests/VCardImporterTests.java +++ b/tests/src/com/android/vcard/tests/VCardImporterTests.java @@ -555,6 +555,34 @@ public class VCardImporterTests extends VCardTestsBase { testComplicatedCase_Parsing(V21, R.raw.v21_complicated); } + public void testV30adr_types_various() { + mVerifier.initForImportTest(V30, R.raw.v30_adr_types); + ContentValuesVerifierElem elem = mVerifier.addContentValuesVerifierElem(); + elem.addExpected(StructuredName.CONTENT_ITEM_TYPE) + .put(StructuredName.FAMILY_NAME, "Familyname") + .put(StructuredName.GIVEN_NAME, "Givenname") + .put(StructuredName.DISPLAY_NAME, "Givenname Familyname"); + elem.addExpected(StructuredPostal.CONTENT_ITEM_TYPE) + .put(StructuredPostal.TYPE, StructuredPostal.TYPE_WORK) + .put(StructuredPostal.STREET, + "1010 Technology Pkwy, Silicon City, Somecountry") + .put(StructuredPostal.FORMATTED_ADDRESS, + "1010 Technology Pkwy, Silicon City, Somecountry"); + elem.addExpected(StructuredPostal.CONTENT_ITEM_TYPE) + .put(StructuredPostal.TYPE, StructuredPostal.TYPE_OTHER) + .put(StructuredPostal.STREET, + "123 Main St, Anytown, Anywhere") + .put(StructuredPostal.FORMATTED_ADDRESS, + "123 Main St, Anytown, Anywhere"); + elem.addExpected(StructuredPostal.CONTENT_ITEM_TYPE) + .put(StructuredPostal.TYPE, StructuredPostal.TYPE_CUSTOM) + .put(StructuredPostal.LABEL, "School") + .put(StructuredPostal.STREET, + "112358 Academic Lane, College Town, Someplace Great") + .put(StructuredPostal.FORMATTED_ADDRESS, + "112358 Academic Lane, College Town, Someplace Great"); + } + public void testV30ComplicatedCase_Parsing() { testComplicatedCase_Parsing(V30, R.raw.v30_complicated); } diff --git a/tests/src/com/android/vcard/tests/VCardJapanizationTests.java b/tests/src/com/android/vcard/tests/VCardJapanizationTests.java index 19f70df..5921e31 100644 --- a/tests/src/com/android/vcard/tests/VCardJapanizationTests.java +++ b/tests/src/com/android/vcard/tests/VCardJapanizationTests.java @@ -23,6 +23,7 @@ import android.provider.ContactsContract.CommonDataKinds.StructuredName; import android.provider.ContactsContract.CommonDataKinds.StructuredPostal; import com.android.vcard.VCardConfig; +import com.android.vcard.VCardConstants; import com.android.vcard.tests.testutils.ContactEntry; import com.android.vcard.tests.testutils.ContentValuesBuilder; import com.android.vcard.tests.testutils.PropertyNodesVerifierElem; @@ -325,7 +326,9 @@ public class VCardJapanizationTests extends VCardTestsBase { .addExpectedNode("X-REDUCTION", "") .addExpectedNode("X-NO", "") .addExpectedNode("X-DCM-HMN-MODE", "") - .addExpectedNode("ADR", Arrays.asList("2", "", "", "", "", "", "")); + .addExpectedNode("ADR", + Arrays.asList("2", "", "", "", "", "", ""), + new TypeSet("X-" + VCardConstants.PARAM_ADR_EXTRA_TYPE_OTHER)); } /** |