Delays text watcher creation in dialpad

PhoneNumberFormattingTextWatcher relies on AsYouTypeFormatter in
PhoneNumberUtil, which causes disk read (StrictMode violation)

Bug: 4599424
Change-Id: Ib67c72cb8e0705eb801bdfe5a368bfcb48ccb637
diff --git a/src/com/android/contacts/dialpad/DialpadFragment.java b/src/com/android/contacts/dialpad/DialpadFragment.java
index 347d705..af706b8 100644
--- a/src/com/android/contacts/dialpad/DialpadFragment.java
+++ b/src/com/android/contacts/dialpad/DialpadFragment.java
@@ -24,6 +24,7 @@
 import com.android.internal.telephony.ITelephony;
 import com.android.phone.CallLogAsync;
 import com.android.phone.HapticFeedback;
+import com.google.i18n.phonenumbers.PhoneNumberUtil;
 
 import android.app.Activity;
 import android.app.Fragment;
@@ -37,6 +38,7 @@
 import android.media.AudioManager;
 import android.media.ToneGenerator;
 import android.net.Uri;
+import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -146,7 +148,34 @@
 
     private String mCurrentCountryIso;
 
-    PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
+    /**
+     * May be null for a moment and filled by AsyncTask. Must not be touched outside UI thread.
+     */
+    private PhoneNumberFormattingTextWatcher mTextWatcher;
+
+    /**
+     * Delays {@link PhoneNumberFormattingTextWatcher} creation as it may cause disk read operation.
+     */
+    private final AsyncTask<Void, Void, Void> mTextWatcherLoadAsyncTask =
+            new AsyncTask<Void, Void, Void>() {
+
+        private PhoneNumberFormattingTextWatcher mTemporaryWatcher;
+
+        @Override
+        protected Void doInBackground(Void... params) {
+            mTemporaryWatcher = new PhoneNumberFormattingTextWatcher(mCurrentCountryIso);
+            return null;
+        }
+
+        @Override
+        protected void onPostExecute(Void result) {
+            // Should be in UI thread.
+            mTextWatcher = mTemporaryWatcher;
+            mDigits.addTextChangedListener(mTextWatcher);
+        }
+    };
+
+    private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
             /**
              * Listen for phone state changes so that we can take down the
              * "dialpad chooser" if the phone becomes idle while the
@@ -228,7 +257,14 @@
         mDigits.setOnKeyListener(this);
         mDigits.addTextChangedListener(this);
 
-        maybeAddNumberFormatting();
+        if (mTextWatcher == null) {
+            if (mTextWatcherLoadAsyncTask.getStatus() == AsyncTask.Status.PENDING) {
+                // Start loading text watcher for phone number, which requires disk read.
+                mTextWatcherLoadAsyncTask.execute();
+            }
+        } else {
+            mDigits.addTextChangedListener(mTextWatcher);
+        }
 
         // Check for the presence of the keypad
         View oneButton = fragmentView.findViewById(R.id.one);
@@ -283,10 +319,6 @@
         return mDigits;
     }
 
-    private void maybeAddNumberFormatting() {
-        mDigits.addTextChangedListener(new PhoneNumberFormattingTextWatcher(mCurrentCountryIso));
-    }
-
     /**
      * Handles the intent that launched us.
      *