Let ImportVCardActivity choose an account if multiple account exist.
Remove VCardActivity, which does nothing effective.
Remove getReopenableUri(), since this change the method unnecessary.

Bug: 2528512
Bug: 2568427
Change-Id: I1ffb4171fefaad1ddc7406fe5447876d4c647610
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 1e9b525..04d0cf4 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -448,9 +448,9 @@
             </intent-filter>
         </activity>
 
-        <activity android:name=".VCardActivity"
-            android:theme="@android:style/Theme.NoTitleBar" >
-             <intent-filter>
+        <activity android:name=".ImportVCardActivity"
+            android:theme="@style/BackgroundOnly">
+            <intent-filter>
                 <action android:name="android.intent.action.VIEW" />
                 <data android:mimeType="text/directory" />
                 <data android:mimeType="text/x-vcard" />
@@ -458,9 +458,6 @@
             </intent-filter>
         </activity>
 
-        <activity android:name=".ImportVCardActivity"
-            android:theme="@style/BackgroundOnly" />
-
         <activity android:name=".ExportVCardActivity"
             android:theme="@style/BackgroundOnly" />
     </application>
diff --git a/src/com/android/contacts/ImportVCardActivity.java b/src/com/android/contacts/ImportVCardActivity.java
index 4dcf5d5..adc2f67 100644
--- a/src/com/android/contacts/ImportVCardActivity.java
+++ b/src/com/android/contacts/ImportVCardActivity.java
@@ -31,7 +31,6 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Environment;
-import android.os.FileUtils;
 import android.os.Handler;
 import android.os.PowerManager;
 import android.pim.vcard.VCardConfig;
@@ -54,12 +53,12 @@
 import android.text.style.RelativeSizeSpan;
 import android.util.Log;
 
-import java.io.BufferedOutputStream;
+import com.android.contacts.model.Sources;
+import com.android.contacts.util.AccountSelectionUtil;
+
 import java.io.File;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.OutputStream;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
@@ -109,6 +108,8 @@
     private static final boolean DO_PERFORMANCE_PROFILE = false;
 
     private Handler mHandler = new Handler();  // Run on the UI thread.
+
+    private AccountSelectionUtil.AccountSelectedListener mAccountSelectionListener;
     private Account mAccount;
 
     private ProgressDialog mProgressDialogForScanVCard;
@@ -201,12 +202,7 @@
             // Even in such cases, some should be done.
             try {
                 if (mUri != null) {  // Read one vCard expressed by mUri
-                    final Uri uri = getReopenableUri(mUri);
-                    if (uri == null) {
-                        shouldCallFinish = false;
-                        return;
-                    }
-
+                    final Uri targetUri = mUri;
                     mProgressDialogForReadVCard.setProgressNumberFormat("");
                     mProgressDialogForReadVCard.setProgress(0);
 
@@ -222,13 +218,13 @@
                             Arrays.asList(counter, detector));
                     boolean result;
                     try {
-                        result = readOneVCardFile(uri,
+                        result = readOneVCardFile(targetUri,
                                 VCardConfig.DEFAULT_CHARSET, builderCollection, null, true, null);
                     } catch (VCardNestedException e) {
                         try {
                             // Assume that VCardSourceDetector was able to detect the source.
                             // Try again with the detector.
-                            result = readOneVCardFile(uri,
+                            result = readOneVCardFile(targetUri,
                                     VCardConfig.DEFAULT_CHARSET, counter, detector, false, null);
                         } catch (VCardNestedException e2) {
                             result = false;
@@ -250,7 +246,7 @@
                     mProgressDialogForReadVCard.setIndeterminate(false);
                     mProgressDialogForReadVCard.setMax(counter.getCount());
                     String charset = detector.getEstimatedCharset();
-                    createdUri = doActuallyReadOneVCard(uri, null, charset, true, detector,
+                    createdUri = doActuallyReadOneVCard(targetUri, null, charset, true, detector,
                             mErrorFileNameList);
                 } else {  // Read multiple files.
                     mProgressDialogForReadVCard.setProgressNumberFormat(
@@ -263,16 +259,12 @@
                             return;
                         }
                         // TODO: detect scheme!
-                        final Uri uri = getReopenableUri(
-                                Uri.parse("file://" + vcardFile.getCanonicalPath()));
-                        if (uri == null) {
-                            shouldCallFinish = false;
-                            return;
-                        }
+                        final Uri targetUri =
+                            Uri.parse("file://" + vcardFile.getCanonicalPath());
 
                         VCardSourceDetector detector = new VCardSourceDetector();
                         try {
-                            if (!readOneVCardFile(uri, VCardConfig.DEFAULT_CHARSET,
+                            if (!readOneVCardFile(targetUri, VCardConfig.DEFAULT_CHARSET,
                                     detector, null, true, mErrorFileNameList)) {
                                 continue;
                             }
@@ -280,7 +272,7 @@
                             // Assume that VCardSourceDetector was able to detect the source.
                         }
                         String charset = detector.getEstimatedCharset();
-                        doActuallyReadOneVCard(uri, mAccount,
+                        doActuallyReadOneVCard(targetUri, mAccount,
                                 charset, false, detector, mErrorFileNameList);
                         mProgressDialogForReadVCard.incrementProgressBy(1);
                     }
@@ -333,49 +325,6 @@
             }
         }
 
-        private Uri getReopenableUri(final Uri uri) {
-            if ("file".equals(uri.getScheme())) {
-                return uri;
-            } else {
-                // We may not be able to scan a given uri more than once when it does not
-                // point to a local file, while it is necessary to scan it more than once
-                // because of vCard limitation. We rely on a local temporary file instead.
-                //
-                // e.g. Email app's AttachmentProvider is able to give us a content Uri
-                // with an attachment file, but we cannot "sometimes" (not always) scan
-                // the Uri more than once because of permission revocation.
-                InputStream is = null;
-                OutputStream os = null;
-                Uri reopenableUri = null;
-                try {
-                    is = mResolver.openInputStream(uri);
-                    File dir = getDir("tmp", MODE_PRIVATE);
-                    mTempFile = dir.createTempFile("vcf", null, dir);
-                    FileUtils.copyToFile(is, mTempFile);
-                    reopenableUri = Uri.parse("file://" + mTempFile.getCanonicalPath());
-                } catch (IOException e) {
-                    mHandler.post(new DialogDisplayer(
-                            getString(R.string.fail_reason_io_error) +
-                            ": " + e.getLocalizedMessage()));
-                    return null;
-                } finally {
-                    if (is != null) {
-                        try {
-                            is.close();
-                        } catch (IOException e) {
-                        }
-                    }
-                    if (os != null) {
-                        try {
-                            os.close();
-                        } catch (IOException e) {
-                        }
-                    }
-                }
-                return reopenableUri;
-            }
-        }
-
         private Uri doActuallyReadOneVCard(Uri uri, Account account,
                 String charset, boolean showEntryParseProgress,
                 VCardSourceDetector detector, List<String> errorFileNameList) {
@@ -783,7 +732,7 @@
     protected void onCreate(Bundle bundle) {
         super.onCreate(bundle);
 
-        Intent intent = getIntent();
+        final Intent intent = getIntent();
         if (intent != null) {
             final String accountName = intent.getStringExtra("account_name");
             final String accountType = intent.getStringExtra("account_type");
@@ -794,6 +743,41 @@
             Log.e(LOG_TAG, "intent does not exist");
         }
 
+        // The caller often does not know account information at all, so we show the UI instead.
+        if (mAccount == null) {
+            // There's three possibilities:
+            // - more than one accounts -> ask the user
+            // - just one account -> use the account without asking the user
+            // - no account -> use phone-local storage without asking the user
+            final Sources sources = Sources.getInstance(this);
+            final List<Account> accountList = sources.getAccounts(true);
+            final int size = accountList.size();
+            if (size > 1) {
+                final int resId = R.string.import_from_sdcard;
+                mAccountSelectionListener =
+                    new AccountSelectionUtil.AccountSelectedListener(
+                            this, accountList, resId) {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        dialog.dismiss();
+                        mAccount = mAccountList.get(which);
+                        // Instead of using Intent mechanism, call the relevant private method,
+                        // to avoid throwing an Intent to itself again.
+                        startImport();
+                    }
+                };
+                showDialog(resId);
+                return;
+            } else {
+                mAccount = size > 0 ? accountList.get(0) : null;
+            }
+        }
+
+        startImport();
+    }
+
+    private void startImport() {
+        Intent intent = getIntent();
         final String action = intent.getAction();
         final Uri uri = intent.getData();
         Log.v(LOG_TAG, "action = " + action + " ; path = " + uri);
@@ -805,13 +789,21 @@
         if (uri != null) {
             importOneVCardFromSDCard(uri);
         } else {
-            startImportVCardFromSdCard();
+            doScanExternalStorageAndImportVCard();
         }
     }
 
     @Override
     protected Dialog onCreateDialog(int resId) {
         switch (resId) {
+            case R.string.import_from_sdcard: {
+                if (mAccountSelectionListener == null) {
+                    throw new NullPointerException(
+                            "mAccountSelectionListener must not be null.");
+                }
+                return AccountSelectionUtil.getSelectAccountDialog(this, resId,
+                        mAccountSelectionListener);
+            }
             case R.id.dialog_searching_vcard: {
                 if (mProgressDialogForScanVCard == null) {
                     String title = getString(R.string.searching_vcard_title);
@@ -938,15 +930,12 @@
         }
     }
 
-    /* public methods */
-
     /**
-     * Tries to start importing VCard. If there's no SDCard available,
-     * an error dialog is shown. If there is, start scanning using another thread
-     * and shows a progress dialog. Several interactions will occur.
-     * This method should be called from a thread with a looper (like Activity).
+     * Scans vCard in external storage (typically SDCard) and tries to import it.
+     * - When there's no SDCard available, an error dialog is shown.
+     * - When multiple vCard files are available, asks a user to select one.
      */
-    public void startImportVCardFromSdCard() {
+    private void doScanExternalStorageAndImportVCard() {
         // TODO: should use getExternalStorageState().
         final File file = Environment.getExternalStorageDirectory();
         if (!file.exists() || !file.isDirectory() || !file.canRead()) {
diff --git a/src/com/android/contacts/VCardActivity.java b/src/com/android/contacts/VCardActivity.java
deleted file mode 100644
index ef04be6..0000000
--- a/src/com/android/contacts/VCardActivity.java
+++ /dev/null
@@ -1,62 +0,0 @@
-//package com.motorola.vcardshare;
-
-package com.android.contacts;
-
-import java.util.List;
-import com.android.contacts.model.Sources;
-import com.android.contacts.util.AccountSelectionUtil;
-import android.accounts.Account;
-import android.app.Activity;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-import android.util.Log;
-
-public class VCardActivity extends Activity {
-    private static final String TAG = "VCardActivity";
-    public static final int IMPORT_TYPE_GOOGLE = 0;
-    public static final int IMPORT_TYPE_EXCHANGE = 1;
-
-    /** Called when the activity is first created. */
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.vcardshare_main);
-
-        Intent intent = getIntent();
-        String action = intent.getAction();
-        Log.v(TAG, "action is " + action);
-        Uri path = intent.getData();
-        Log.v(TAG, "path is " + path);
-        String mimeType = intent.getType();
-        Log.v(TAG, "mimeType is " + mimeType);
-
-        if (action.equals(Intent.ACTION_VIEW)) {
-
-            AccountSelectionUtil.mVCardShare = true;
-            AccountSelectionUtil.mPath = path;
-            handleImportRequest(R.string.import_from_sdcard);
-        } else {
-            Log.w(TAG, "VcardActivity not handle such action: " + action);
-        }
-        finish();
-    }
-    
-    private void handleImportRequest(int resId) {
-        // There's three possibilities:
-        // - more than one accounts -> ask the user
-        // - just one account -> use the account without asking the user
-        // - no account -> use phone-local storage without asking the user
-        final Sources sources = Sources.getInstance(this);
-        final List<Account> accountList = sources.getAccounts(true);
-        final int size = accountList.size();
-        Log.v(TAG, "account num =  " + size);
-
-        if (size > 1) {
-            // showDialog(resId);
-            AccountSelectionUtil.getSelectAccountDialog(this, resId);
-        }
-
-        AccountSelectionUtil.doImport(this, resId, (size == 1 ? accountList.get(0) : null));
-    }
-}
diff --git a/src/com/android/contacts/util/AccountSelectionUtil.java b/src/com/android/contacts/util/AccountSelectionUtil.java
index e32ef69..3618fad 100644
--- a/src/com/android/contacts/util/AccountSelectionUtil.java
+++ b/src/com/android/contacts/util/AccountSelectionUtil.java
@@ -50,13 +50,14 @@
 
     public static Uri mPath;
 
-    private static class AccountSelectedListener
-            implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener {
+    public static class AccountSelectedListener
+            implements DialogInterface.OnClickListener {
 
         final private Context mContext;
-        final private List<Account> mAccountList;
         final private int mResId;
 
+        final protected List<Account> mAccountList;
+
         public AccountSelectedListener(Context context, List<Account> accountList, int resId) {
             if (accountList == null || accountList.size() == 0) {
                 Log.e(LOG_TAG, "The size of Account list is 0.");
@@ -70,17 +71,19 @@
             dialog.dismiss();
             doImport(mContext, mResId, mAccountList.get(which));
         }
-
-        public void onCancel(DialogInterface dialog) {
-            dialog.dismiss();
-        }
     }
 
     public static Dialog getSelectAccountDialog(Context context, int resId) {
-        return getSelectAccountDialog(context, resId, null);
+        return getSelectAccountDialog(context, resId, null, null);
     }
 
     public static Dialog getSelectAccountDialog(Context context, int resId,
+            DialogInterface.OnClickListener onClickListener) {
+        return getSelectAccountDialog(context, resId, onClickListener, null);
+    }
+
+    public static Dialog getSelectAccountDialog(Context context, int resId,
+            DialogInterface.OnClickListener onClickListener,
             DialogInterface.OnCancelListener onCancelListener) {
         final Sources sources = Sources.getInstance(context);
         final List<Account> writableAccountList = sources.getAccounts(true);
@@ -123,12 +126,22 @@
             }
         };
 
-        AccountSelectedListener accountSelectedListener =
-            new AccountSelectedListener(context, writableAccountList, resId);
+        if (onClickListener == null) {
+            AccountSelectedListener accountSelectedListener =
+                new AccountSelectedListener(context, writableAccountList, resId);
+            onClickListener = accountSelectedListener;
+        }
+        if (onCancelListener == null) {
+            onCancelListener = new DialogInterface.OnCancelListener() {
+                public void onCancel(DialogInterface dialog) {
+                    dialog.dismiss();
+                }
+            };
+        }
         return new AlertDialog.Builder(context)
             .setTitle(R.string.dialog_new_contact_account)
-            .setSingleChoiceItems(accountAdapter, 0, accountSelectedListener)
-            .setOnCancelListener(accountSelectedListener)
+            .setSingleChoiceItems(accountAdapter, 0, onClickListener)
+            .setOnCancelListener(onCancelListener)
             .create();
     }