diff --git a/core/java/android/pim/vcard/VCardBuilder.java b/core/java/android/pim/vcard/VCardBuilder.java index 0a6415dd200cd..c2b342f673ac5 100644 --- a/core/java/android/pim/vcard/VCardBuilder.java +++ b/core/java/android/pim/vcard/VCardBuilder.java @@ -47,7 +47,22 @@ import java.util.Map; import java.util.Set; /** - * The class which lets users create their own vCard String. + *

+ * The class which lets users create their own vCard String. Typical usage is as follows: + *

+ *
final VCardBuilder builder = new VCardBuilder(vcardType);
+ * builder.appendNameProperties(contentValuesListMap.get(StructuredName.CONTENT_ITEM_TYPE))
+ *     .appendNickNames(contentValuesListMap.get(Nickname.CONTENT_ITEM_TYPE))
+ *     .appendPhones(contentValuesListMap.get(Phone.CONTENT_ITEM_TYPE))
+ *     .appendEmails(contentValuesListMap.get(Email.CONTENT_ITEM_TYPE))
+ *     .appendPostals(contentValuesListMap.get(StructuredPostal.CONTENT_ITEM_TYPE))
+ *     .appendOrganizations(contentValuesListMap.get(Organization.CONTENT_ITEM_TYPE))
+ *     .appendWebsites(contentValuesListMap.get(Website.CONTENT_ITEM_TYPE))
+ *     .appendPhotos(contentValuesListMap.get(Photo.CONTENT_ITEM_TYPE))
+ *     .appendNotes(contentValuesListMap.get(Note.CONTENT_ITEM_TYPE))
+ *     .appendEvents(contentValuesListMap.get(Event.CONTENT_ITEM_TYPE))
+ *     .appendIms(contentValuesListMap.get(Im.CONTENT_ITEM_TYPE))
+ *     .appendRelation(contentValuesListMap.get(Relation.CONTENT_ITEM_TYPE)); 
*/ public class VCardBuilder { private static final String LOG_TAG = "VCardBuilder"; @@ -81,7 +96,6 @@ public class VCardBuilder { private static final String VCARD_PARAM_ENCODING_BASE64_V30 = "ENCODING=b"; private static final String SHIFT_JIS = "SHIFT_JIS"; - private static final String UTF_8 = "UTF-8"; private final int mVCardType; @@ -92,21 +106,28 @@ public class VCardBuilder { private final boolean mShouldUseQuotedPrintable; private final boolean mUsesAndroidProperty; private final boolean mUsesDefactProperty; - private final boolean mUsesUtf8; - private final boolean mUsesShiftJis; private final boolean mAppendTypeParamName; private final boolean mRefrainsQPToNameProperties; private final boolean mNeedsToConvertPhoneticString; private final boolean mShouldAppendCharsetParam; - private final String mCharsetString; + private final String mCharset; private final String mVCardCharsetParameter; private StringBuilder mBuilder; private boolean mEndAppended; public VCardBuilder(final int vcardType) { + // Default charset should be used + this(vcardType, null); + } + + /** + * @param vcardType + * @param charset If null, we use default charset for export. + */ + public VCardBuilder(final int vcardType, String charset) { mVCardType = vcardType; mIsV30 = VCardConfig.isV30(vcardType); @@ -116,40 +137,77 @@ public class VCardBuilder { mOnlyOneNoteFieldIsAvailable = VCardConfig.onlyOneNoteFieldIsAvailable(vcardType); mUsesAndroidProperty = VCardConfig.usesAndroidSpecificProperty(vcardType); mUsesDefactProperty = VCardConfig.usesDefactProperty(vcardType); - mUsesUtf8 = VCardConfig.usesUtf8(vcardType); - mUsesShiftJis = VCardConfig.usesShiftJis(vcardType); mRefrainsQPToNameProperties = VCardConfig.shouldRefrainQPToNameProperties(vcardType); mAppendTypeParamName = VCardConfig.appendTypeParamName(vcardType); mNeedsToConvertPhoneticString = VCardConfig.needsToConvertPhoneticString(vcardType); - mShouldAppendCharsetParam = !(mIsV30 && mUsesUtf8); + final boolean shouldUseUtf8 = VCardConfig.shouldUseUtf8ForExport(vcardType); + final boolean shouldUseShiftJis = VCardConfig.shouldUseShiftJisForExport(vcardType); - if (mIsDoCoMo) { - String charset; - try { - charset = CharsetUtils.charsetForVendor(SHIFT_JIS, "docomo").name(); - } catch (UnsupportedCharsetException e) { - Log.e(LOG_TAG, "DoCoMo-specific SHIFT_JIS was not found. Use SHIFT_JIS as is."); - charset = SHIFT_JIS; + // vCard 2.1 requires charset. + // vCard 3.0 does not allow it but we found some devices use it to determine + // the exact charset. + // We currently append it only when charset other than UTF_8 is used. + mShouldAppendCharsetParam = !(mIsV30 && shouldUseUtf8); + + if (VCardConfig.isDoCoMo(vcardType) || shouldUseShiftJis) { + if (!SHIFT_JIS.equalsIgnoreCase(charset)) { + Log.w(LOG_TAG, + "The charset \"" + charset + "\" is used while " + + SHIFT_JIS + " is needed to be used."); + if (TextUtils.isEmpty(charset)) { + mCharset = SHIFT_JIS; + } else { + try { + charset = CharsetUtils.charsetForVendor(charset).name(); + } catch (UnsupportedCharsetException e) { + Log.i(LOG_TAG, + "Career-specific \"" + charset + "\" was not found (as usual). " + + "Use it as is."); + } + mCharset = charset; + } + } else { + if (mIsDoCoMo) { + try { + charset = CharsetUtils.charsetForVendor(SHIFT_JIS, "docomo").name(); + } catch (UnsupportedCharsetException e) { + Log.e(LOG_TAG, + "DoCoMo-specific SHIFT_JIS was not found. " + + "Use SHIFT_JIS as is."); + charset = SHIFT_JIS; + } + } else { + try { + charset = CharsetUtils.charsetForVendor(SHIFT_JIS).name(); + } catch (UnsupportedCharsetException e) { + Log.e(LOG_TAG, + "Career-specific SHIFT_JIS was not found. " + + "Use SHIFT_JIS as is."); + charset = SHIFT_JIS; + } + } + mCharset = charset; } - mCharsetString = charset; - // Do not use mCharsetString bellow since it is different from "SHIFT_JIS" but - // may be "DOCOMO_SHIFT_JIS" or something like that (internal expression used in - // Android, not shown to the public). - mVCardCharsetParameter = "CHARSET=" + SHIFT_JIS; - } else if (mUsesShiftJis) { - String charset; - try { - charset = CharsetUtils.charsetForVendor(SHIFT_JIS).name(); - } catch (UnsupportedCharsetException e) { - Log.e(LOG_TAG, "Vendor-specific SHIFT_JIS was not found. Use SHIFT_JIS as is."); - charset = SHIFT_JIS; - } - mCharsetString = charset; mVCardCharsetParameter = "CHARSET=" + SHIFT_JIS; } else { - mCharsetString = UTF_8; - mVCardCharsetParameter = "CHARSET=" + UTF_8; + if (TextUtils.isEmpty(charset)) { + Log.i(LOG_TAG, + "Use the charset \"" + VCardConfig.DEFAULT_EXPORT_CHARSET + + "\" for export."); + mCharset = VCardConfig.DEFAULT_EXPORT_CHARSET; + mVCardCharsetParameter = "CHARSET=" + VCardConfig.DEFAULT_EXPORT_CHARSET; + } else { + try { + charset = CharsetUtils.charsetForVendor(charset).name(); + } catch (UnsupportedCharsetException e) { + Log.i(LOG_TAG, + "Career-specific \"" + charset + "\" was not found (as usual). " + + "Use it as is."); + } + mCharset = charset; + mVCardCharsetParameter = "CHARSET=" + charset; + } } clear(); } @@ -379,8 +437,8 @@ public class VCardBuilder { mBuilder.append(VCardConstants.PROPERTY_FN); // Note: "CHARSET" param is not allowed in vCard 3.0, but we may add it - // when it would be useful for external importers, assuming no external - // importer allows this vioration. + // when it would be useful or necessary for external importers, + // assuming the external importer allows this vioration of the spec. if (shouldAppendCharsetParam(displayName)) { mBuilder.append(VCARD_PARAM_SEPARATOR); mBuilder.append(mVCardCharsetParameter); @@ -454,18 +512,18 @@ public class VCardBuilder { mBuilder.append(VCARD_END_OF_LINE); } else if (mIsJapaneseMobilePhone) { // Note: There is no appropriate property for expressing - // phonetic name in vCard 2.1, while there is in + // phonetic name (Yomigana in Japanese) in vCard 2.1, while there is in // vCard 3.0 (SORT-STRING). - // We chose to use DoCoMo's way when the device is Japanese one - // since it is supported by - // a lot of Japanese mobile phones. This is "X-" property, so - // any parser hopefully would not get confused with this. + // We use DoCoMo's way when the device is Japanese one since it is already + // supported by a lot of Japanese mobile phones. + // This is "X-" property, so any parser hopefully would not get + // confused with this. // // Also, DoCoMo's specification requires vCard composer to use just the first // column. // i.e. - // o SOUND;X-IRMC-N:Miyakawa Daisuke;;;; - // x SOUND;X-IRMC-N:Miyakawa;Daisuke;;; + // good: SOUND;X-IRMC-N:Miyakawa Daisuke;;;; + // bad : SOUND;X-IRMC-N:Miyakawa;Daisuke;;; mBuilder.append(VCardConstants.PROPERTY_SOUND); mBuilder.append(VCARD_PARAM_SEPARATOR); mBuilder.append(VCardConstants.PARAM_TYPE_X_IRMC_N); @@ -519,10 +577,10 @@ public class VCardBuilder { mBuilder.append(encodedPhoneticGivenName); } } - mBuilder.append(VCARD_ITEM_SEPARATOR); - mBuilder.append(VCARD_ITEM_SEPARATOR); - mBuilder.append(VCARD_ITEM_SEPARATOR); - mBuilder.append(VCARD_ITEM_SEPARATOR); + mBuilder.append(VCARD_ITEM_SEPARATOR); // family;given + mBuilder.append(VCARD_ITEM_SEPARATOR); // given;middle + mBuilder.append(VCARD_ITEM_SEPARATOR); // middle;prefix + mBuilder.append(VCARD_ITEM_SEPARATOR); // prefix;suffix mBuilder.append(VCARD_END_OF_LINE); } @@ -549,7 +607,7 @@ public class VCardBuilder { mBuilder.append(VCARD_DATA_SEPARATOR); mBuilder.append(encodedPhoneticGivenName); mBuilder.append(VCARD_END_OF_LINE); - } + } // if (!TextUtils.isEmpty(phoneticGivenName)) if (!TextUtils.isEmpty(phoneticMiddleName)) { final boolean reallyUseQuotedPrintable = (mShouldUseQuotedPrintable && @@ -572,7 +630,7 @@ public class VCardBuilder { mBuilder.append(VCARD_DATA_SEPARATOR); mBuilder.append(encodedPhoneticMiddleName); mBuilder.append(VCARD_END_OF_LINE); - } + } // if (!TextUtils.isEmpty(phoneticGivenName)) if (!TextUtils.isEmpty(phoneticFamilyName)) { final boolean reallyUseQuotedPrintable = (mShouldUseQuotedPrintable && @@ -595,7 +653,7 @@ public class VCardBuilder { mBuilder.append(VCARD_DATA_SEPARATOR); mBuilder.append(encodedPhoneticFamilyName); mBuilder.append(VCARD_END_OF_LINE); - } + } // if (!TextUtils.isEmpty(phoneticFamilyName)) } } @@ -903,21 +961,21 @@ public class VCardBuilder { encodedCountry = escapeCharacters(rawCountry); encodedNeighborhood = escapeCharacters(rawNeighborhood); } - final StringBuffer addressBuffer = new StringBuffer(); - addressBuffer.append(encodedPoBox); - addressBuffer.append(VCARD_ITEM_SEPARATOR); - addressBuffer.append(VCARD_ITEM_SEPARATOR); - addressBuffer.append(encodedStreet); - addressBuffer.append(VCARD_ITEM_SEPARATOR); - addressBuffer.append(encodedLocality); - addressBuffer.append(VCARD_ITEM_SEPARATOR); - addressBuffer.append(encodedRegion); - addressBuffer.append(VCARD_ITEM_SEPARATOR); - addressBuffer.append(encodedPostalCode); - addressBuffer.append(VCARD_ITEM_SEPARATOR); - addressBuffer.append(encodedCountry); + final StringBuilder addressBuilder = new StringBuilder(); + addressBuilder.append(encodedPoBox); + addressBuilder.append(VCARD_ITEM_SEPARATOR); // PO BOX ; Extended Address + addressBuilder.append(VCARD_ITEM_SEPARATOR); // Extended Address : Street + addressBuilder.append(encodedStreet); + addressBuilder.append(VCARD_ITEM_SEPARATOR); // Street : Locality + addressBuilder.append(encodedLocality); + addressBuilder.append(VCARD_ITEM_SEPARATOR); // Locality : Region + addressBuilder.append(encodedRegion); + addressBuilder.append(VCARD_ITEM_SEPARATOR); // Region : Postal Code + addressBuilder.append(encodedPostalCode); + addressBuilder.append(VCARD_ITEM_SEPARATOR); // Postal Code : Country + addressBuilder.append(encodedCountry); return new PostalStruct( - reallyUseQuotedPrintable, appendCharset, addressBuffer.toString()); + reallyUseQuotedPrintable, appendCharset, addressBuilder.toString()); } else { // VCardUtils.areAllEmpty(rawAddressArray) == true // Try to use FORMATTED_ADDRESS instead. final String rawFormattedAddress = @@ -940,16 +998,16 @@ public class VCardBuilder { // We use the second value ("Extended Address") just because Japanese mobile phones // do so. If the other importer expects the value be in the other field, some flag may // be needed. - final StringBuffer addressBuffer = new StringBuffer(); - addressBuffer.append(VCARD_ITEM_SEPARATOR); - addressBuffer.append(encodedFormattedAddress); - addressBuffer.append(VCARD_ITEM_SEPARATOR); - addressBuffer.append(VCARD_ITEM_SEPARATOR); - addressBuffer.append(VCARD_ITEM_SEPARATOR); - addressBuffer.append(VCARD_ITEM_SEPARATOR); - addressBuffer.append(VCARD_ITEM_SEPARATOR); + final StringBuilder addressBuilder = new StringBuilder(); + addressBuilder.append(VCARD_ITEM_SEPARATOR); // PO BOX ; Extended Address + addressBuilder.append(encodedFormattedAddress); + addressBuilder.append(VCARD_ITEM_SEPARATOR); // Extended Address : Street + addressBuilder.append(VCARD_ITEM_SEPARATOR); // Street : Locality + addressBuilder.append(VCARD_ITEM_SEPARATOR); // Locality : Region + addressBuilder.append(VCARD_ITEM_SEPARATOR); // Region : Postal Code + addressBuilder.append(VCARD_ITEM_SEPARATOR); // Postal Code : Country return new PostalStruct( - reallyUseQuotedPrintable, appendCharset, addressBuffer.toString()); + reallyUseQuotedPrintable, appendCharset, addressBuilder.toString()); } } @@ -1146,6 +1204,8 @@ public class VCardBuilder { } public VCardBuilder appendEvents(final List contentValuesList) { + // There's possibility where a given object may have more than one birthday, which + // is inappropriate. We just build one birthday. if (contentValuesList != null) { String primaryBirthday = null; String secondaryBirthday = null; @@ -1213,16 +1273,19 @@ public class VCardBuilder { return this; } + /** + * @param emitEveryTime If true, builder builds the line even when there's no entry. + */ public void appendPostalLine(final int type, final String label, final ContentValues contentValues, - final boolean isPrimary, final boolean emitLineEveryTime) { + final boolean isPrimary, final boolean emitEveryTime) { final boolean reallyUseQuotedPrintable; final boolean appendCharset; final String addressValue; { PostalStruct postalStruct = tryConstructPostalStruct(contentValues); if (postalStruct == null) { - if (emitLineEveryTime) { + if (emitEveryTime) { reallyUseQuotedPrintable = false; appendCharset = false; addressValue = ""; @@ -1537,7 +1600,8 @@ public class VCardBuilder { mBuilder.append(VCARD_END_OF_LINE); } - public void appendAndroidSpecificProperty(final String mimeType, ContentValues contentValues) { + public void appendAndroidSpecificProperty( + final String mimeType, ContentValues contentValues) { if (!sAllowedAndroidPropertySet.contains(mimeType)) { return; } @@ -1659,7 +1723,7 @@ public class VCardBuilder { encodedValue = encodeQuotedPrintable(rawValue); } else { // TODO: one line may be too huge, which may be invalid in vCard spec, though - // several (even well-known) applications do not care this. + // several (even well-known) applications do not care that violation. encodedValue = escapeCharacters(rawValue); } @@ -1794,9 +1858,9 @@ public class VCardBuilder { byte[] strArray = null; try { - strArray = str.getBytes(mCharsetString); + strArray = str.getBytes(mCharset); } catch (UnsupportedEncodingException e) { - Log.e(LOG_TAG, "Charset " + mCharsetString + " cannot be used. " + Log.e(LOG_TAG, "Charset " + mCharset + " cannot be used. " + "Try default charset"); strArray = str.getBytes(); } diff --git a/core/java/android/pim/vcard/VCardComposer.java b/core/java/android/pim/vcard/VCardComposer.java index dc0d86466ee5f..1bc77856c963f 100644 --- a/core/java/android/pim/vcard/VCardComposer.java +++ b/core/java/android/pim/vcard/VCardComposer.java @@ -41,6 +41,7 @@ import android.provider.ContactsContract.CommonDataKinds.Relation; import android.provider.ContactsContract.CommonDataKinds.StructuredName; import android.provider.ContactsContract.CommonDataKinds.StructuredPostal; import android.provider.ContactsContract.CommonDataKinds.Website; +import android.text.TextUtils; import android.util.CharsetUtils; import android.util.Log; @@ -61,15 +62,11 @@ import java.util.Map; /** *

- * The class for composing VCard from Contacts information. Note that this is - * completely differnt implementation from - * android.syncml.pim.vcard.VCardComposer, which is not maintained anymore. + * The class for composing vCard from Contacts information. *

- * *

* Usually, this class should be used like this. *

- * *
VCardComposer composer = null;
  * try {
  *     composer = new VCardComposer(context);
@@ -94,14 +91,17 @@ import java.util.Map;
  *         composer.terminate();
  *     }
  * } 
+ *

+ * Users have to manually take care of memory efficiency. Even one vCard may contain + * image of non-trivial size for mobile devices. + *

+ *

+ * In default, Default {@link VCardBuilder} class is used to build each vCard. + *

*/ public class VCardComposer { private static final String LOG_TAG = "VCardComposer"; - public static final int DEFAULT_PHONE_TYPE = Phone.TYPE_HOME; - public static final int DEFAULT_POSTAL_TYPE = StructuredPostal.TYPE_HOME; - public static final int DEFAULT_EMAIL_TYPE = Email.TYPE_OTHER; - public static final String FAILURE_REASON_FAILED_TO_GET_DATABASE_INFO = "Failed to get database information"; @@ -119,6 +119,8 @@ public class VCardComposer { public static final String VCARD_TYPE_STRING_DOCOMO = "docomo"; + // Strictly speaking, "Shift_JIS" is the most appropriate, but we use upper version here, + // since usual vCard devices for Japanese devices already use it. private static final String SHIFT_JIS = "SHIFT_JIS"; private static final String UTF_8 = "UTF-8"; @@ -141,7 +143,7 @@ public class VCardComposer { sImMap.put(Im.PROTOCOL_ICQ, VCardConstants.PROPERTY_X_ICQ); sImMap.put(Im.PROTOCOL_JABBER, VCardConstants.PROPERTY_X_JABBER); sImMap.put(Im.PROTOCOL_SKYPE, VCardConstants.PROPERTY_X_SKYPE_USERNAME); - // Google talk is a special case. + // We don't add Google talk here since it has to be handled separately. } public static interface OneEntryHandler { @@ -152,37 +154,37 @@ public class VCardComposer { /** *

- * An useful example handler, which emits VCard String to outputstream one by one. + * An useful handler for emitting vCard String to an OutputStream object one by one. *

*

* The input OutputStream object is closed() on {@link #onTerminate()}. - * Must not close the stream outside. + * Must not close the stream outside this class. *

*/ public class HandlerForOutputStream implements OneEntryHandler { @SuppressWarnings("hiding") private static final String LOG_TAG = "vcard.VCardComposer.HandlerForOutputStream"; - final private OutputStream mOutputStream; // mWriter will close this. - private Writer mWriter; - private boolean mOnTerminateIsCalled = false; + final private OutputStream mOutputStream; // mWriter will close this. + protected Writer mWriter; + /** * Input stream will be closed on the detruction of this object. */ - public HandlerForOutputStream(OutputStream outputStream) { + public HandlerForOutputStream(final OutputStream outputStream) { mOutputStream = outputStream; } - public boolean onInit(Context context) { + public final boolean onInit(final Context context) { try { mWriter = new BufferedWriter(new OutputStreamWriter( - mOutputStream, mCharsetString)); + mOutputStream, mCharset)); } catch (UnsupportedEncodingException e1) { - Log.e(LOG_TAG, "Unsupported charset: " + mCharsetString); + Log.e(LOG_TAG, "Unsupported charset: " + mCharset); mErrorReason = "Encoding is not supported (usually this does not happen!): " - + mCharsetString; + + mCharset; return false; } @@ -205,7 +207,7 @@ public class VCardComposer { return true; } - public boolean onEntryCreated(String vcard) { + public final boolean onEntryCreated(String vcard) { try { mWriter.write(vcard); } catch (IOException e) { @@ -218,7 +220,7 @@ public class VCardComposer { return true; } - public void onTerminate() { + public final void onTerminate() { mOnTerminateIsCalled = true; if (mWriter != null) { try { @@ -235,14 +237,21 @@ public class VCardComposer { "IOException during closing the output stream: " + e.getMessage()); } finally { - try { - mWriter.close(); - } catch (IOException e) { - } + closeOutputStream(); } } } + // Users can override this if they want to (e.g. if they don't want to close the stream). + // TODO: Should expose bare OutputStream instead? + public void closeOutputStream() { + try { + mWriter.close(); + } catch (IOException e) { + Log.w(LOG_TAG, "IOException is thrown during close(). Ignoring."); + } + } + @Override public void finalize() { if (!mOnTerminateIsCalled) { @@ -257,11 +266,10 @@ public class VCardComposer { private final ContentResolver mContentResolver; private final boolean mIsDoCoMo; - private final boolean mUsesShiftJis; private Cursor mCursor; private int mIdColumn; - private final String mCharsetString; + private final String mCharset; private boolean mTerminateIsCalled; private final List mHandlerList; @@ -272,11 +280,14 @@ public class VCardComposer { }; public VCardComposer(Context context) { - this(context, VCardConfig.VCARD_TYPE_DEFAULT, true); + this(context, VCardConfig.VCARD_TYPE_DEFAULT, null, true); } + /** + * The variant which sets charset to null and sets careHandlerErrors to true. + */ public VCardComposer(Context context, int vcardType) { - this(context, vcardType, true); + this(context, vcardType, null, true); } public VCardComposer(Context context, String vcardTypeStr, boolean careHandlerErrors) { @@ -284,40 +295,88 @@ public class VCardComposer { } /** - * Construct for supporting call log entry vCard composing. + * The variant which sets charset to null. */ public VCardComposer(final Context context, final int vcardType, final boolean careHandlerErrors) { + this(context, vcardType, null, careHandlerErrors); + } + + /** + * Construct for supporting call log entry vCard composing. + * + * @param context Context to be used during the composition. + * @param vcardType The type of vCard, typically available via {@link VCardConfig}. + * @param charset The charset to be used. Use null when you don't need the charset. + * @param careHandlerErrors If true, This object returns false everytime + * a Handler object given via {{@link #addHandler(OneEntryHandler)} returns false. + * If false, this ignores those errors. + */ + public VCardComposer(final Context context, final int vcardType, + String charset, + final boolean careHandlerErrors) { mContext = context; mVCardType = vcardType; mCareHandlerErrors = careHandlerErrors; mContentResolver = context.getContentResolver(); mIsDoCoMo = VCardConfig.isDoCoMo(vcardType); - mUsesShiftJis = VCardConfig.usesShiftJis(vcardType); mHandlerList = new ArrayList(); - if (mIsDoCoMo) { - String charset; - try { - charset = CharsetUtils.charsetForVendor(SHIFT_JIS, "docomo").name(); - } catch (UnsupportedCharsetException e) { - Log.e(LOG_TAG, "DoCoMo-specific SHIFT_JIS was not found. Use SHIFT_JIS as is."); - charset = SHIFT_JIS; + if (mIsDoCoMo || VCardConfig.shouldUseShiftJisForExport(vcardType)) { + if (!SHIFT_JIS.equalsIgnoreCase(charset)) { + Log.w(LOG_TAG, + "The charset \"" + charset + "\" is used while " + + SHIFT_JIS + " is needed to be used."); + if (TextUtils.isEmpty(charset)) { + mCharset = SHIFT_JIS; + } else { + try { + charset = CharsetUtils.charsetForVendor(charset).name(); + } catch (UnsupportedCharsetException e) { + Log.i(LOG_TAG, + "Career-specific \"" + charset + "\" was not found (as usual). " + + "Use it as is."); + } + mCharset = charset; + } + } else { + if (mIsDoCoMo) { + try { + charset = CharsetUtils.charsetForVendor(SHIFT_JIS, "docomo").name(); + } catch (UnsupportedCharsetException e) { + Log.e(LOG_TAG, + "DoCoMo-specific SHIFT_JIS was not found. " + + "Use SHIFT_JIS as is."); + charset = SHIFT_JIS; + } + } else { + try { + charset = CharsetUtils.charsetForVendor(SHIFT_JIS).name(); + } catch (UnsupportedCharsetException e) { + Log.e(LOG_TAG, + "Career-specific SHIFT_JIS was not found. " + + "Use SHIFT_JIS as is."); + charset = SHIFT_JIS; + } + } + mCharset = charset; } - mCharsetString = charset; - } else if (mUsesShiftJis) { - String charset; - try { - charset = CharsetUtils.charsetForVendor(SHIFT_JIS).name(); - } catch (UnsupportedCharsetException e) { - Log.e(LOG_TAG, "Vendor-specific SHIFT_JIS was not found. Use SHIFT_JIS as is."); - charset = SHIFT_JIS; - } - mCharsetString = charset; } else { - mCharsetString = UTF_8; + if (TextUtils.isEmpty(charset)) { + mCharset = UTF_8; + } else { + try { + charset = CharsetUtils.charsetForVendor(charset).name(); + } catch (UnsupportedCharsetException e) { + Log.i(LOG_TAG, + "Career-specific \"" + charset + "\" was not found (as usual). " + + "Use it as is."); + } + mCharset = charset; + } } + Log.d(LOG_TAG, "use the charset \"" + mCharset + "\""); } /** @@ -351,7 +410,7 @@ public class VCardComposer { } if (mCareHandlerErrors) { - List finishedList = new ArrayList( + final List finishedList = new ArrayList( mHandlerList.size()); for (OneEntryHandler handler : mHandlerList) { if (!handler.onInit(mContext)) { @@ -414,7 +473,7 @@ public class VCardComposer { mErrorReason = FAILURE_REASON_NOT_INITIALIZED; return false; } - String vcard; + final String vcard; try { if (mIdColumn >= 0) { vcard = createOneEntryInternal(mCursor.getString(mIdColumn), @@ -437,8 +496,7 @@ public class VCardComposer { mCursor.moveToNext(); } - // This function does not care the OutOfMemoryError on the handler side - // :-P + // This function does not care the OutOfMemoryError on the handler side :-P if (mCareHandlerErrors) { List finishedList = new ArrayList( mHandlerList.size()); @@ -457,7 +515,7 @@ public class VCardComposer { } private String createOneEntryInternal(final String contactId, - Method getEntityIteratorMethod) throws VCardException { + final Method getEntityIteratorMethod) throws VCardException { final Map> contentValuesListMap = new HashMap>(); // The resolver may return the entity iterator with no data. It is possible. @@ -527,20 +585,34 @@ public class VCardComposer { } } - final VCardBuilder builder = new VCardBuilder(mVCardType); - builder.appendNameProperties(contentValuesListMap.get(StructuredName.CONTENT_ITEM_TYPE)) - .appendNickNames(contentValuesListMap.get(Nickname.CONTENT_ITEM_TYPE)) - .appendPhones(contentValuesListMap.get(Phone.CONTENT_ITEM_TYPE)) - .appendEmails(contentValuesListMap.get(Email.CONTENT_ITEM_TYPE)) - .appendPostals(contentValuesListMap.get(StructuredPostal.CONTENT_ITEM_TYPE)) - .appendOrganizations(contentValuesListMap.get(Organization.CONTENT_ITEM_TYPE)) - .appendWebsites(contentValuesListMap.get(Website.CONTENT_ITEM_TYPE)) - .appendPhotos(contentValuesListMap.get(Photo.CONTENT_ITEM_TYPE)) - .appendNotes(contentValuesListMap.get(Note.CONTENT_ITEM_TYPE)) - .appendEvents(contentValuesListMap.get(Event.CONTENT_ITEM_TYPE)) - .appendIms(contentValuesListMap.get(Im.CONTENT_ITEM_TYPE)) - .appendRelation(contentValuesListMap.get(Relation.CONTENT_ITEM_TYPE)); - return builder.toString(); + return buildVCard(contentValuesListMap); + } + + /** + * Builds and returns vCard using given map, whose key is CONTENT_ITEM_TYPE defined in + * {ContactsContract}. Developers can override this method to customize the output. + */ + public String buildVCard(final Map> contentValuesListMap) { + if (contentValuesListMap == null) { + Log.e(LOG_TAG, "The given map is null. Ignore and return empty String"); + return ""; + } else { + final VCardBuilder builder = new VCardBuilder(mVCardType, mCharset); + // TODO: Android-specific X attributes? + builder.appendNameProperties(contentValuesListMap.get(StructuredName.CONTENT_ITEM_TYPE)) + .appendNickNames(contentValuesListMap.get(Nickname.CONTENT_ITEM_TYPE)) + .appendPhones(contentValuesListMap.get(Phone.CONTENT_ITEM_TYPE)) + .appendEmails(contentValuesListMap.get(Email.CONTENT_ITEM_TYPE)) + .appendPostals(contentValuesListMap.get(StructuredPostal.CONTENT_ITEM_TYPE)) + .appendOrganizations(contentValuesListMap.get(Organization.CONTENT_ITEM_TYPE)) + .appendWebsites(contentValuesListMap.get(Website.CONTENT_ITEM_TYPE)) + .appendPhotos(contentValuesListMap.get(Photo.CONTENT_ITEM_TYPE)) + .appendNotes(contentValuesListMap.get(Note.CONTENT_ITEM_TYPE)) + .appendEvents(contentValuesListMap.get(Event.CONTENT_ITEM_TYPE)) + .appendIms(contentValuesListMap.get(Im.CONTENT_ITEM_TYPE)) + .appendRelation(contentValuesListMap.get(Relation.CONTENT_ITEM_TYPE)); + return builder.toString(); + } } public void terminate() { @@ -563,26 +635,38 @@ public class VCardComposer { @Override public void finalize() { if (!mTerminateIsCalled) { + Log.w(LOG_TAG, "terminate() is not called yet. We call it in finalize() step."); terminate(); } } + /** + * @return returns the number of available entities. The return value is undefined + * when this object is not ready yet (typically when {{@link #init()} is not called + * or when {@link #terminate()} is already called). + */ public int getCount() { if (mCursor == null) { + Log.w(LOG_TAG, "This object is not ready yet."); return 0; } return mCursor.getCount(); } + /** + * @return true when there's no entity to be built. The return value is undefined + * when this object is not ready yet. + */ public boolean isAfterLast() { if (mCursor == null) { + Log.w(LOG_TAG, "This object is not ready yet."); return false; } return mCursor.isAfterLast(); } /** - * @return Return the error reason if possible. + * @return Returns the error reason. */ public String getErrorReason() { return mErrorReason; diff --git a/core/java/android/pim/vcard/VCardConfig.java b/core/java/android/pim/vcard/VCardConfig.java index 3442ae732ab4b..40566caeacc88 100644 --- a/core/java/android/pim/vcard/VCardConfig.java +++ b/core/java/android/pim/vcard/VCardConfig.java @@ -43,10 +43,28 @@ public class VCardConfig { /* package */ static final int PARSE_TYPE_FOMA = 3; // For Japanese FOMA mobile phones. /* package */ static final int PARSE_TYPE_WINDOWS_MOBILE_JP = 4; - // Assumes that "iso-8859-1" is able to map "all" 8bit characters to some unicode and - // decode the unicode to the original charset. If not, this setting will cause some bug. - public static final String DEFAULT_CHARSET = "iso-8859-1"; - + /** + *

+ * The charset used during import. + *

+ *

+ * We cannot determine which charset should be used to interpret a given vCard file, + * while we have to decode sime encoded data (e.g. BASE64) to binary. + * In order to avoid "misinterpretation" of charset as much as possible, + * "ISO-8859-1" (a.k.a Latin-1) is first used for reading a stream. + * When charset is specified in a property (with "CHARSET=..." parameter), + * the string is decoded to raw bytes and encoded into the specific charset, + * assuming "ISO-8859-1" is able to map "all" 8bit characters to some unicode, + * and it has 1 to 1 mapping in all 8bit characters. + * If the assumption is not correct, this setting will cause some bug. + *

+ */ + /* package */ static final String DEFAULT_TEMPORARY_CHARSET = "ISO-8859-1"; + + // TODO: still intermediate procedures uses this charset. Fix it. + public static final String DEFAULT_IMPORT_CHARSET = "ISO-8859-1"; + public static final String DEFAULT_EXPORT_CHARSET = "UTF-8"; + public static final int FLAG_V21 = 0; public static final int FLAG_V30 = 1; @@ -58,10 +76,13 @@ public class VCardConfig { private static final int NAME_ORDER_MASK = 0xC; // 0x10 is reserved for safety - - private static final int FLAG_CHARSET_UTF8 = 0; - private static final int FLAG_CHARSET_SHIFT_JIS = 0x100; - private static final int FLAG_CHARSET_MASK = 0xF00; + + /* + * These flags are ignored when charset is explicitly given by a caller. + */ + private static final int FLAG_USE_UTF8_FOR_EXPORT = 0; + private static final int FLAG_USE_SHIFT_JIS_FOR_EXPORT = 0x100; + private static final int FLAG_CHARSET_MASK_FOR_EKPORT = 0xF00; /** * The flag indicating the vCard composer will add some "X-" properties used only in Android @@ -196,7 +217,7 @@ public class VCardConfig { *

*/ public static final int VCARD_TYPE_V21_GENERIC_UTF8 = - (FLAG_V21 | NAME_ORDER_DEFAULT | FLAG_CHARSET_UTF8 | + (FLAG_V21 | NAME_ORDER_DEFAULT | FLAG_USE_UTF8_FOR_EXPORT | FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY); /* package */ static String VCARD_TYPE_V21_GENERIC_UTF8_STR = "v21_generic"; @@ -210,7 +231,7 @@ public class VCardConfig { *

*/ public static final int VCARD_TYPE_V30_GENERIC_UTF8 = - (FLAG_V30 | NAME_ORDER_DEFAULT | FLAG_CHARSET_UTF8 | + (FLAG_V30 | NAME_ORDER_DEFAULT | FLAG_USE_UTF8_FOR_EXPORT | FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY); /* package */ static final String VCARD_TYPE_V30_GENERIC_UTF8_STR = "v30_generic"; @@ -222,7 +243,7 @@ public class VCardConfig { *

*/ public static final int VCARD_TYPE_V21_EUROPE_UTF8 = - (FLAG_V21 | NAME_ORDER_EUROPE | FLAG_CHARSET_UTF8 | + (FLAG_V21 | NAME_ORDER_EUROPE | FLAG_USE_UTF8_FOR_EXPORT | FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY); /* package */ static final String VCARD_TYPE_V21_EUROPE_UTF8_STR = "v21_europe"; @@ -236,7 +257,7 @@ public class VCardConfig { *

*/ public static final int VCARD_TYPE_V30_EUROPE_UTF8 = - (FLAG_V30 | NAME_ORDER_EUROPE | FLAG_CHARSET_UTF8 | + (FLAG_V30 | NAME_ORDER_EUROPE | FLAG_USE_UTF8_FOR_EXPORT | FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY); /* package */ static final String VCARD_TYPE_V30_EUROPE_STR = "v30_europe"; @@ -250,7 +271,7 @@ public class VCardConfig { *

*/ public static final int VCARD_TYPE_V21_JAPANESE_UTF8 = - (FLAG_V21 | NAME_ORDER_JAPANESE | FLAG_CHARSET_UTF8 | + (FLAG_V21 | NAME_ORDER_JAPANESE | FLAG_USE_UTF8_FOR_EXPORT | FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY); /* package */ static final String VCARD_TYPE_V21_JAPANESE_UTF8_STR = "v21_japanese_utf8"; @@ -265,7 +286,7 @@ public class VCardConfig { *

*/ public static final int VCARD_TYPE_V21_JAPANESE_SJIS = - (FLAG_V21 | NAME_ORDER_JAPANESE | FLAG_CHARSET_SHIFT_JIS | + (FLAG_V21 | NAME_ORDER_JAPANESE | FLAG_USE_SHIFT_JIS_FOR_EXPORT | FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY); /* package */ static final String VCARD_TYPE_V21_JAPANESE_SJIS_STR = "v21_japanese_sjis"; @@ -280,7 +301,7 @@ public class VCardConfig { *

*/ public static final int VCARD_TYPE_V30_JAPANESE_SJIS = - (FLAG_V30 | NAME_ORDER_JAPANESE | FLAG_CHARSET_SHIFT_JIS | + (FLAG_V30 | NAME_ORDER_JAPANESE | FLAG_USE_SHIFT_JIS_FOR_EXPORT | FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY); /* package */ static final String VCARD_TYPE_V30_JAPANESE_SJIS_STR = "v30_japanese_sjis"; @@ -294,7 +315,7 @@ public class VCardConfig { *

*/ public static final int VCARD_TYPE_V30_JAPANESE_UTF8 = - (FLAG_V30 | NAME_ORDER_JAPANESE | FLAG_CHARSET_UTF8 | + (FLAG_V30 | NAME_ORDER_JAPANESE | FLAG_USE_UTF8_FOR_EXPORT | FLAG_USE_DEFACT_PROPERTY | FLAG_USE_ANDROID_PROPERTY); /* package */ static final String VCARD_TYPE_V30_JAPANESE_UTF8_STR = "v30_japanese_utf8"; @@ -310,7 +331,7 @@ public class VCardConfig { *

*/ public static final int VCARD_TYPE_V21_JAPANESE_MOBILE = - (FLAG_V21 | NAME_ORDER_JAPANESE | FLAG_CHARSET_SHIFT_JIS | + (FLAG_V21 | NAME_ORDER_JAPANESE | FLAG_USE_SHIFT_JIS_FOR_EXPORT | FLAG_CONVERT_PHONETIC_NAME_STRINGS | FLAG_REFRAIN_QP_TO_NAME_PROPERTIES); @@ -379,12 +400,17 @@ public class VCardConfig { return !isV30(vcardType); } - public static boolean usesUtf8(final int vcardType) { - return ((vcardType & FLAG_CHARSET_MASK) == FLAG_CHARSET_UTF8); + /* package */ static boolean shouldUseUtf8ForExport(final int vcardType) { + return ((vcardType & FLAG_CHARSET_MASK_FOR_EKPORT) == FLAG_USE_UTF8_FOR_EXPORT); } - public static boolean usesShiftJis(final int vcardType) { - return ((vcardType & FLAG_CHARSET_MASK) == FLAG_CHARSET_SHIFT_JIS); + /** + * Shift_JIS (a charset for Japanese text files) needs special handling to select + * carrer specific variants. + * @hide just for test + */ + public static boolean shouldUseShiftJisForExport(final int vcardType) { + return ((vcardType & FLAG_CHARSET_MASK_FOR_EKPORT) == FLAG_USE_SHIFT_JIS_FOR_EXPORT); } public static int getNameOrderType(final int vcardType) { diff --git a/core/java/android/pim/vcard/VCardEntryConstructor.java b/core/java/android/pim/vcard/VCardEntryConstructor.java index 290ca2bfec14d..4efb105e8abfc 100644 --- a/core/java/android/pim/vcard/VCardEntryConstructor.java +++ b/core/java/android/pim/vcard/VCardEntryConstructor.java @@ -80,7 +80,7 @@ public class VCardEntryConstructor implements VCardInterpreter { if (inputCharset != null) { mInputCharset = inputCharset; } else { - mInputCharset = VCardConfig.DEFAULT_CHARSET; + mInputCharset = VCardConfig.DEFAULT_TEMPORARY_CHARSET; } if (charsetForDetodedBytes != null) { mCharsetForDecodedBytes = charsetForDetodedBytes; diff --git a/core/java/android/pim/vcard/VCardParser.java b/core/java/android/pim/vcard/VCardParser.java index 57c52a646cdde..b38ea93fd3ab3 100644 --- a/core/java/android/pim/vcard/VCardParser.java +++ b/core/java/android/pim/vcard/VCardParser.java @@ -34,26 +34,17 @@ public abstract class VCardParser { /** *

- * Parses the given stream and send the VCard data into VCardBuilderBase object. + * Parses the given stream and send the vCard data into VCardBuilderBase object. * * Note that vCard 2.1 specification allows "CHARSET" parameter, and some career sets * local encoding to it. For example, Japanese phone career uses Shift_JIS, which is - * formally allowed in VCard 2.1, but not recommended in VCard 3.0. In VCard 2.1, - * In some exreme case, some VCard may have different charsets in one VCard (though - * we do not see any device which emits such kind of malicious data) + * formally allowed in vCard 2.1, but not allowed in vCard 3.0. In vCard 2.1, + * In some exreme case, it is allowed for vCard to have different charsets in one vCard. *

*

- * In order to avoid "misunderstanding" charset as much as possible, this method - * use "ISO-8859-1" for reading the stream. When charset is specified in some property - * (with "CHARSET=..." parameter), the string is decoded to raw bytes and encoded to - * the charset. This method assumes that "ISO-8859-1" has 1 to 1 mapping in all 8bit - * characters, which is not completely sure. In some cases, this "decoding-encoding" - * scheme may fail. To avoid the case, - *

- *

- * We recommend you to use {@link VCardSourceDetector} and detect which kind of source the - * VCard comes from and explicitly specify a charset using the result. + * We recommend you use {@link VCardSourceDetector} and detect which kind of source the + * vCard comes from and explicitly specify a charset using the result. *

* * @param is The source to parse. @@ -61,27 +52,24 @@ public abstract class VCardParser { * @return Returns true for success. Otherwise returns false. * @throws IOException, VCardException */ - public abstract boolean parse(InputStream is, VCardInterpreter interepreter) - throws IOException, VCardException; - + public final boolean parse(InputStream is, VCardInterpreter interepreter) + throws IOException, VCardException { + return parse(is, VCardConfig.DEFAULT_TEMPORARY_CHARSET, interepreter); + } + /** *

* The method variants which accept charset. *

- *

- * RFC 2426 "recommends" (not forces) to use UTF-8, so it may be OK to use - * UTF-8 as an encoding when parsing vCard 3.0. But note that some Japanese - * phone uses Shift_JIS as a charset (e.g. W61SH), and another uses - * "CHARSET=SHIFT_JIS", which is explicitly prohibited in vCard 3.0 specification (e.g. W53K). - *

* * @param is The source to parse. * @param charset Charset to be used. - * @param builder The VCardBuilderBase object. + * @param interpreter The VCardBuilderBase object. * @return Returns true when successful. Otherwise returns false. * @throws IOException, VCardException */ - public abstract boolean parse(InputStream is, String charset, VCardInterpreter builder) + public abstract boolean parse(InputStream is, String charset, + VCardInterpreter interpreter) throws IOException, VCardException; /** diff --git a/core/java/android/pim/vcard/VCardParser_V21.java b/core/java/android/pim/vcard/VCardParser_V21.java index fe8cfb07776c1..4f8515060501c 100644 --- a/core/java/android/pim/vcard/VCardParser_V21.java +++ b/core/java/android/pim/vcard/VCardParser_V21.java @@ -68,7 +68,28 @@ public class VCardParser_V21 extends VCardParser { private static final HashSet sAvailableEncodingV21 = new HashSet(Arrays.asList( "7BIT", "8BIT", "QUOTED-PRINTABLE", "BASE64", "B")); - + + private static final class CustomBufferedReader extends BufferedReader { + private long mTime; + + public CustomBufferedReader(Reader in) { + super(in); + } + + @Override + public String readLine() throws IOException { + long start = System.currentTimeMillis(); + String ret = super.readLine(); + long end = System.currentTimeMillis(); + mTime += end - start; + return ret; + } + + public long getTotalmillisecond() { + return mTime; + } + } + // Used only for parsing END:VCARD. private String mPreviousLine; @@ -839,19 +860,17 @@ public class VCardParser_V21 extends VCardParser { return null; } } - - @Override - public boolean parse(final InputStream is, final VCardInterpreter builder) - throws IOException, VCardException { - return parse(is, VCardConfig.DEFAULT_CHARSET, builder); - } - + @Override public boolean parse(InputStream is, String charset, VCardInterpreter builder) throws IOException, VCardException { - if (charset == null) { - charset = VCardConfig.DEFAULT_CHARSET; + if (is == null) { + throw new NullPointerException("InputStream must not be null."); } + if (charset == null) { + charset = VCardConfig.DEFAULT_TEMPORARY_CHARSET; + } + final InputStreamReader tmpReader = new InputStreamReader(is, charset); if (VCardConfig.showPerformanceLog()) { mReader = new CustomBufferedReader(tmpReader); @@ -913,24 +932,3 @@ public class VCardParser_V21 extends VCardParser { return false; } } - -class CustomBufferedReader extends BufferedReader { - private long mTime; - - public CustomBufferedReader(Reader in) { - super(in); - } - - @Override - public String readLine() throws IOException { - long start = System.currentTimeMillis(); - String ret = super.readLine(); - long end = System.currentTimeMillis(); - mTime += end - start; - return ret; - } - - public long getTotalmillisecond() { - return mTime; - } -} diff --git a/core/tests/coretests/src/android/pim/vcard/VCardJapanizationTests.java b/core/tests/coretests/src/android/pim/vcard/VCardJapanizationTests.java index 5b60342c872b3..c9e85dc141aa4 100644 --- a/core/tests/coretests/src/android/pim/vcard/VCardJapanizationTests.java +++ b/core/tests/coretests/src/android/pim/vcard/VCardJapanizationTests.java @@ -17,15 +17,13 @@ package android.pim.vcard; import android.content.ContentValues; -import android.pim.vcard.VCardConfig; +import android.pim.vcard.PropertyNodesVerifierElem.TypeSet; import android.provider.ContactsContract.CommonDataKinds.Nickname; import android.provider.ContactsContract.CommonDataKinds.Note; import android.provider.ContactsContract.CommonDataKinds.Phone; import android.provider.ContactsContract.CommonDataKinds.StructuredName; import android.provider.ContactsContract.CommonDataKinds.StructuredPostal; -import android.pim.vcard.PropertyNodesVerifierElem.TypeSet; - import java.util.Arrays; public class VCardJapanizationTests extends VCardTestsBase { @@ -114,7 +112,7 @@ public class VCardJapanizationTests extends VCardTestsBase { .put(StructuredName.PHONETIC_GIVEN_NAME, "\u305F\u308D\u3046"); final ContentValues contentValues = - (VCardConfig.usesShiftJis(vcardType) ? + (VCardConfig.shouldUseShiftJisForExport(vcardType) ? (VCardConfig.isV30(vcardType) ? mContentValuesForSJis : mContentValuesForQPAndSJis) : (VCardConfig.isV30(vcardType) ? null : mContentValuesForQPAndUtf8)); @@ -214,7 +212,7 @@ public class VCardJapanizationTests extends VCardTestsBase { .put(StructuredPostal.TYPE, StructuredPostal.TYPE_CUSTOM) .put(StructuredPostal.LABEL, "\u304A\u3082\u3061\u304B\u3048\u308A"); - ContentValues contentValues = (VCardConfig.usesShiftJis(vcardType) ? + ContentValues contentValues = (VCardConfig.shouldUseShiftJisForExport(vcardType) ? (VCardConfig.isV30(vcardType) ? mContentValuesForSJis : mContentValuesForQPAndSJis) : (VCardConfig.isV30(vcardType) ? mContentValuesForUtf8 : diff --git a/core/tests/coretests/src/android/pim/vcard/VCardVerifier.java b/core/tests/coretests/src/android/pim/vcard/VCardVerifier.java index bfc315829c2da..7f5816095592f 100644 --- a/core/tests/coretests/src/android/pim/vcard/VCardVerifier.java +++ b/core/tests/coretests/src/android/pim/vcard/VCardVerifier.java @@ -214,7 +214,7 @@ import java.util.Arrays; InputStream is = null; try { String charset = - (VCardConfig.usesShiftJis(mVCardType) ? "SHIFT_JIS" : "UTF-8"); + (VCardConfig.shouldUseShiftJisForExport(mVCardType) ? "SHIFT_JIS" : "UTF-8"); is = new ByteArrayInputStream(vcard.getBytes(charset)); mTestCase.assertEquals(true, parser.parse(is, null, builder)); } catch (IOException e) { @@ -292,8 +292,7 @@ import java.util.Arrays; while (!composer.isAfterLast()) { try { final Method mockGetEntityIteratorMethod = getMockGetEntityIteratorMethod(); - mTestCase.assertTrue( - composer.createOneEntry(getMockGetEntityIteratorMethod())); + mTestCase.assertTrue(composer.createOneEntry(getMockGetEntityIteratorMethod())); } catch (Exception e) { e.printStackTrace(); mTestCase.fail(); diff --git a/core/tests/coretests/src/android/pim/vcard/VNodeBuilder.java b/core/tests/coretests/src/android/pim/vcard/VNodeBuilder.java index 0e6c3259b5fa7..1e607dde10ccc 100644 --- a/core/tests/coretests/src/android/pim/vcard/VNodeBuilder.java +++ b/core/tests/coretests/src/android/pim/vcard/VNodeBuilder.java @@ -68,7 +68,7 @@ public class VNodeBuilder implements VCardInterpreter { private boolean mStrictLineBreakParsing; public VNodeBuilder() { - this(VCardConfig.DEFAULT_CHARSET, TARGET_CHARSET, false); + this(VCardConfig.DEFAULT_IMPORT_CHARSET, TARGET_CHARSET, false); } public VNodeBuilder(String charset, boolean strictLineBreakParsing) { @@ -83,7 +83,7 @@ public class VNodeBuilder implements VCardInterpreter { if (sourceCharset != null) { mSourceCharset = sourceCharset; } else { - mSourceCharset = VCardConfig.DEFAULT_CHARSET; + mSourceCharset = VCardConfig.DEFAULT_IMPORT_CHARSET; } if (targetCharset != null) { mTargetCharset = targetCharset;