Stop using private APIs as much as possible.

- remove CharsetUtils stuffs
- remove private APIs in PhoneNumberUtils/TextUtils.

We keep the hidden flag "Data.FOR_EXPORT_ONLY", so this code still
needs access to private API. We don't remove it right now since we
may still need it while we confirmed that the other stuffs are "ok"
to be removed. Some more investigation will be needed in the future
to remove the flag.

Bug: 3143497
Change-Id: I074a7798d2208c3e14a524bd5f307a91ac50f735
diff --git a/Android.mk b/Android.mk
index 2a68819..9df7773 100644
--- a/Android.mk
+++ b/Android.mk
@@ -15,12 +15,12 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
+# Comment in when we don't want private API (methods with @hide)
+# LOCAL_SDK_VERSION := current
+
 LOCAL_MODULE := com.android.vcard
 LOCAL_SRC_FILES := $(call all-java-files-under, java)
 
-# Use ext for using Quoted-Printable codec.
-LOCAL_JAVA_LIBRARIES := ext
-
 include $(BUILD_STATIC_JAVA_LIBRARY)
 
 # Build the test package.
diff --git a/java/com/android/vcard/VCardBuilder.java b/java/com/android/vcard/VCardBuilder.java
index 7fa9e92..42567bd 100644
--- a/java/com/android/vcard/VCardBuilder.java
+++ b/java/com/android/vcard/VCardBuilder.java
@@ -15,6 +15,8 @@
  */
 package com.android.vcard;
 
+import com.android.vcard.VCardUtils.PhoneNumberUtilsPort;
+
 import android.content.ContentValues;
 import android.provider.ContactsContract.CommonDataKinds.Email;
 import android.provider.ContactsContract.CommonDataKinds.Event;
@@ -29,10 +31,8 @@
 import android.provider.ContactsContract.CommonDataKinds.StructuredName;
 import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
 import android.provider.ContactsContract.CommonDataKinds.Website;
-import android.telephony.PhoneNumberUtils;
 import android.text.TextUtils;
 import android.util.Base64;
-import android.util.CharsetUtils;
 import android.util.Log;
 
 import java.io.UnsupportedEncodingException;
@@ -165,17 +165,17 @@
                 if (TextUtils.isEmpty(charset)) {
                     mCharset = SHIFT_JIS;
                 } else {
-                    try {
+                    /*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) {
+                /*if (mIsDoCoMo) {
                     try {
                         charset = CharsetUtils.charsetForVendor(SHIFT_JIS, "docomo").name();
                     } catch (UnsupportedCharsetException e) {
@@ -193,7 +193,7 @@
                                 + "Use SHIFT_JIS as is.");
                         charset = SHIFT_JIS;
                     }
-                }
+                }*/
                 mCharset = charset;
             }
             mVCardCharsetParameter = "CHARSET=" + SHIFT_JIS;
@@ -205,13 +205,14 @@
                 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;
             }
@@ -855,7 +856,8 @@
                         if (!phoneSet.contains(actualPhoneNumber)) {
                             final int phoneFormat = VCardUtils.getPhoneNumberFormat(mVCardType);
                             String formatted =
-                                    PhoneNumberUtils.formatNumber(actualPhoneNumber, phoneFormat);
+                                    PhoneNumberUtilsPort.formatNumber(
+                                            actualPhoneNumber, phoneFormat);
 
                             // In vCard 4.0, value type must be "a single URI value",
                             // not just a phone number. (Based on vCard 4.0 rev.13)
diff --git a/java/com/android/vcard/VCardComposer.java b/java/com/android/vcard/VCardComposer.java
index 3b37607..f7e7d52 100644
--- a/java/com/android/vcard/VCardComposer.java
+++ b/java/com/android/vcard/VCardComposer.java
@@ -44,7 +44,6 @@
 import android.provider.ContactsContract.RawContacts;
 import android.provider.ContactsContract.RawContactsEntity;
 import android.text.TextUtils;
-import android.util.CharsetUtils;
 import android.util.Log;
 
 import java.io.BufferedWriter;
@@ -56,7 +55,6 @@
 import java.io.Writer;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
-import java.nio.charset.UnsupportedCharsetException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -330,8 +328,9 @@
                 VCardConfig.isVersion30(vcardType) && UTF_8.equalsIgnoreCase(charset));
 
         if (mIsDoCoMo || shouldAppendCharsetParam) {
+            // TODO: clean up once we're sure CharsetUtils are really unnecessary any more.
             if (SHIFT_JIS.equalsIgnoreCase(charset)) {
-                if (mIsDoCoMo) {
+                /*if (mIsDoCoMo) {
                     try {
                         charset = CharsetUtils.charsetForVendor(SHIFT_JIS, "docomo").name();
                     } catch (UnsupportedCharsetException e) {
@@ -344,12 +343,12 @@
                     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."); */
+                        // Log.e(LOG_TAG,
+                        // "Career-specific SHIFT_JIS was not found. "
+                        // + "Use SHIFT_JIS as is.");
                         charset = SHIFT_JIS;
                     }
-                }
+                }*/
                 mCharset = charset;
             } else {
                 /* Log.w(LOG_TAG,
@@ -358,13 +357,14 @@
                 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;
                 }
             }
@@ -372,13 +372,13 @@
             if (TextUtils.isEmpty(charset)) {
                 mCharset = UTF_8;
             } else {
-                try {
+                /*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;
             }
         }
@@ -530,6 +530,7 @@
         //      they are hidden from the view of this method, though contact id itself exists.
         EntityIterator entityIterator = null;
         try {
+            // TODO: confirm whether we can safely remove Data.FOR_EXPORT_ONLY or not.
             final Uri uri = RawContactsEntity.CONTENT_URI.buildUpon()
                     // .appendQueryParameter("for_export_only", "1")
                     .appendQueryParameter(Data.FOR_EXPORT_ONLY, "1")
diff --git a/java/com/android/vcard/VCardEntry.java b/java/com/android/vcard/VCardEntry.java
index 655a80f..d07c274 100644
--- a/java/com/android/vcard/VCardEntry.java
+++ b/java/com/android/vcard/VCardEntry.java
@@ -15,6 +15,8 @@
  */
 package com.android.vcard;
 
+import com.android.vcard.VCardUtils.PhoneNumberUtilsPort;
+
 import android.accounts.Account;
 import android.content.ContentProviderOperation;
 import android.content.ContentProviderResult;
@@ -39,7 +41,6 @@
 import android.provider.ContactsContract.Contacts;
 import android.provider.ContactsContract.Data;
 import android.provider.ContactsContract.RawContacts;
-import android.telephony.PhoneNumberUtils;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -510,8 +511,8 @@
             }
 
             final int formattingType = VCardUtils.getPhoneNumberFormat(mVCardType);
-            formattedNumber = PhoneNumberUtils.formatNumber(builder.toString(), formattingType);
-        }
+            formattedNumber = PhoneNumberUtilsPort.formatNumber(builder.toString(), formattingType);
+         }
         PhoneData phoneData = new PhoneData(type, formattedNumber, label, isPrimary);
         mPhoneList.add(phoneData);
     }
diff --git a/java/com/android/vcard/VCardEntryConstructor.java b/java/com/android/vcard/VCardEntryConstructor.java
index 55d2d48..3326ac1 100644
--- a/java/com/android/vcard/VCardEntryConstructor.java
+++ b/java/com/android/vcard/VCardEntryConstructor.java
@@ -18,12 +18,8 @@
 import android.accounts.Account;
 import android.text.TextUtils;
 import android.util.Base64;
-import android.util.CharsetUtils;
 import android.util.Log;
 
-import java.io.UnsupportedEncodingException;
-import java.nio.ByteBuffer;
-import java.nio.charset.Charset;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
@@ -203,7 +199,8 @@
         // Just translate the charset of a given String from inputCharset to a system one. 
         return VCardUtils.convertStringCharset(value, sourceCharset, targetCharset);
     }
-    
+
+    @Override
     public void propertyValues(List<String> values) {
         if (values == null || values.isEmpty()) {
             return;
@@ -215,8 +212,11 @@
                 mCurrentProperty.getParameters(VCardConstants.PARAM_ENCODING);
         final String encoding =
             ((encodingCollection != null) ? encodingCollection.iterator().next() : null);
-        String targetCharset = CharsetUtils.nameForDefaultVendor(
-                ((charsetCollection != null) ? charsetCollection.iterator().next() : null));
+
+        // String targetCharset = CharsetUtils.nameForDefaultVendor(
+        //    ((charsetCollection != null) ? charsetCollection.iterator().next() : null));
+        String targetCharset =
+            ((charsetCollection != null) ? charsetCollection.iterator().next() : null);
         if (TextUtils.isEmpty(targetCharset)) {
             targetCharset = VCardConfig.DEFAULT_IMPORT_CHARSET;
         }
diff --git a/java/com/android/vcard/VCardUtils.java b/java/com/android/vcard/VCardUtils.java
index 1bd35ba..5385cbf 100644
--- a/java/com/android/vcard/VCardUtils.java
+++ b/java/com/android/vcard/VCardUtils.java
@@ -23,6 +23,7 @@
 import android.provider.ContactsContract.CommonDataKinds.Phone;
 import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
 import android.telephony.PhoneNumberUtils;
+import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -86,6 +87,38 @@
         }
     }
 
+    /**
+     * Ported methods which are hidden in {@link PhoneNumberUtils}.
+     */
+    public static class PhoneNumberUtilsPort {
+        public static String formatNumber(String source, int defaultFormattingType) {
+            final SpannableStringBuilder text = new SpannableStringBuilder(source);
+            PhoneNumberUtils.formatNumber(text, defaultFormattingType);
+            return text.toString();
+        }
+    }
+
+    /**
+     * Ported methods which are hidden in {@link TextUtils}.
+     */
+    public static class TextUtilsPort {
+        public static boolean isPrintableAscii(final char c) {
+            final int asciiFirst = 0x20;
+            final int asciiLast = 0x7E;  // included
+            return (asciiFirst <= c && c <= asciiLast) || c == '\r' || c == '\n';
+        }
+
+        public static boolean isPrintableAsciiOnly(final CharSequence str) {
+            final int len = str.length();
+            for (int i = 0; i < len; i++) {
+                if (!isPrintableAscii(str.charAt(i))) {
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+
     // Note that not all types are included in this map/set, since, for example, TYPE_HOME_FAX is
     // converted to two parameter Strings. These only contain some minor fields valid in both
     // vCard and current (as of 2009-08-07) Contacts structure. 
@@ -434,7 +467,7 @@
             if (TextUtils.isEmpty(value)) {
                 continue;
             }
-            if (!TextUtils.isPrintableAsciiOnly(value)) {
+            if (!TextUtilsPort.isPrintableAsciiOnly(value)) {
                 return false;
             }
         }