UI tweaks to ImportDialogFragment

It's now able to show the number of contacts on the SIM card for the
SIM options if the counts are passed as arguments.

Test
manual: verify that ImportDialogFragment UI reflects changes

Bug 31781331
Change-Id: I5b20287ae504470866af2ad83c61794876fdbf7e
diff --git a/res/layout/select_dialog_item.xml b/res/layout/select_dialog_item.xml
index 0c524fd..1215aa9 100644
--- a/res/layout/select_dialog_item.xml
+++ b/res/layout/select_dialog_item.xml
@@ -19,14 +19,35 @@
   in the contact editor. This is similar to the framework's select_dialog_item_material.xml layout
   except the text appearance is medium and the padding is set to match the material spec.
 -->
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@android:id/text1"
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="48dp"
-    android:textAlignment="viewStart"
-    android:textColor="@color/contacts_text_color"
-    android:textSize="16sp"
-    android:gravity="center_vertical"
-    android:paddingStart="24dip"
-    android:paddingEnd="24dip"
-    android:ellipsize="marquee" />
\ No newline at end of file
+    android:layout_height="56dp"
+    android:orientation="vertical"
+    android:paddingBottom="8dp"
+    android:paddingEnd="24dp"
+    android:paddingStart="24dp"
+    android:paddingTop="8dp">
+
+    <TextView
+        android:id="@+id/primary_text"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        android:ellipsize="marquee"
+        android:gravity="start|center_vertical"
+        android:textAlignment="viewStart"
+        android:textAppearance="?android:textAppearanceListItem"
+        android:textSize="16sp"/>
+
+    <TextView
+        android:id="@+id/secondary_text"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:ellipsize="marquee"
+        android:gravity="center_vertical|start"
+        android:textAlignment="viewStart"
+        android:textAppearance="?android:textAppearanceListItemSecondary"
+        android:textColor="?android:textColorSecondary"
+        />
+</LinearLayout>
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 36315a2..d8f3362 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1370,13 +1370,35 @@
     <string name="dialog_new_contact_account">Save imported contacts to:</string>
 
     <!-- Action string for selecting SIM for importing contacts -->
-    <string name="import_from_sim">Import from SIM card</string>
+    <string name="import_from_sim">SIM card</string>
 
     <!-- Action string for selecting a SIM subscription for importing contacts -->
-    <string name="import_from_sim_summary_fmt">Import from SIM <xliff:g id="sim_name">%1$s</xliff:g></string>
+    <string name="import_from_sim_summary_fmt">SIM <xliff:g id="sim_name">%1$s</xliff:g></string>
+
+    <!-- Secondary string showing the number of SIM contacts for the SIM card on the action for
+         importing from that SIM. Only shown if there is no phone number available for the SIM card
+         [CHAR LIMIT=25] -->
+    <plurals name="import_from_sim_secondary_contact_count_fmt">
+        <item quantity="one">1 contact</item>
+        <item quantity="other">%1$d contacts</item>
+    </plurals>
+
+    <!-- Secondary string showing the number of SIM contacts and phone number for the SIM card
+         on the action for importing that SIM. Note that the bullet character is purely a visual
+         separator between the contact count and phone number; it has no grammatical meaning in
+         this string [CHAR LIMIT=35]-->
+    <plurals name="import_from_sim_secondary_template">
+        <item quantity="one"><xliff:g id="count">^1</xliff:g> contact • <xliff:g id="phone_number">^2</xliff:g></item>
+        <item quantity="other"><xliff:g id="count">^1</xliff:g> contacts • <xliff:g id="phone_number">^2</xliff:g></item>
+    </plurals>
+
+
 
     <!-- Action string for selecting a .vcf file to import contacts from [CHAR LIMIT=30] -->
-    <string name="import_from_vcf_file" product="default">Import from .vcf file</string>
+    <string name="import_from_vcf_file" product="default">.vcf file</string>
+
+    <!-- Message shown on Import from dialog when there is nothing available to import (no .vcf option or SIM cards) [CHAR LIMIT=NONE] -->
+    <string name="nothing_to_import_message">Nothing to import</string>
 
     <!-- Dialog message asking the user for confirmation before starting to import contacts from a .vcf file. [CHAR LIMIT=NONE] -->
     <string name="import_from_vcf_file_confirmation_message" product="default">Import contacts from vCard?</string>
@@ -1622,7 +1644,7 @@
     <string name="dialog_export">Export contacts</string>
 
     <!-- Dialog title when importing contacts from an external source. [CHAR LIMIT=36] -->
-    <string name="dialog_import">Import contacts</string>
+    <string name="dialog_import">Import contacts from</string>
 
     <!-- Toast indicating that sharing a contact has failed. [CHAR LIMIT=NONE]  -->
     <string name="share_error">This contact can\'t be shared.</string>
@@ -1864,4 +1886,5 @@
 
     <!-- Generic label for the SIM card when there is only a single SIM in the device [CHAR LIMIT=10]-->
     <string name="single_sim_display_label">SIM</string>
+
 </resources>
diff --git a/src/com/android/contacts/common/interactions/ExportDialogFragment.java b/src/com/android/contacts/common/interactions/ExportDialogFragment.java
index 84a43dd..3925833 100644
--- a/src/com/android/contacts/common/interactions/ExportDialogFragment.java
+++ b/src/com/android/contacts/common/interactions/ExportDialogFragment.java
@@ -97,10 +97,14 @@
                 R.layout.select_dialog_item) {
             @Override
             public View getView(int position, View convertView, ViewGroup parent) {
-                final TextView result = (TextView)(convertView != null ? convertView :
-                        dialogInflater.inflate(R.layout.select_dialog_item, parent, false));
+                final View result = convertView != null ? convertView :
+                        dialogInflater.inflate(R.layout.select_dialog_item, parent, false);
 
-                result.setText(getItem(position).mLabel);
+                final TextView text = (TextView) result.findViewById(R.id.primary_text);
+                final View secondaryText = result.findViewById(R.id.secondary_text);
+                secondaryText.setVisibility(View.GONE);
+
+                text.setText(getItem(position).mLabel);
                 return result;
             }
         };
diff --git a/src/com/android/contacts/common/interactions/ImportDialogFragment.java b/src/com/android/contacts/common/interactions/ImportDialogFragment.java
index 2268854..f3ce748 100644
--- a/src/com/android/contacts/common/interactions/ImportDialogFragment.java
+++ b/src/com/android/contacts/common/interactions/ImportDialogFragment.java
@@ -25,8 +25,8 @@
 import android.content.DialogInterface;
 import android.content.res.Resources;
 import android.os.Bundle;
-import android.provider.ContactsContract.Contacts;
-import android.telephony.SubscriptionManager;
+import android.support.v4.text.TextUtilsCompat;
+import android.text.SpannableString;
 import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
 import android.util.Log;
@@ -43,6 +43,7 @@
 import com.android.contacts.common.database.SimContactDao;
 import com.android.contacts.common.model.AccountTypeManager;
 import com.android.contacts.common.model.SimCard;
+import com.android.contacts.common.model.SimContact;
 import com.android.contacts.common.model.account.AccountWithDataSet;
 import com.android.contacts.common.util.AccountSelectionUtil;
 import com.android.contacts.common.util.AccountsListAdapter.AccountListFilter;
@@ -62,28 +63,30 @@
 
     public static final String EXTRA_SIM_ONLY = "extraSimOnly";
 
+    public static final String EXTRA_SIM_CONTACT_COUNT_PREFIX = "simContactCount_";
+
     private boolean mSimOnly = false;
     private SimContactDao mSimDao;
 
-    private final String[] LOOKUP_PROJECTION = new String[] {
-            Contacts.LOOKUP_KEY
-    };
-
-    private SubscriptionManager mSubscriptionManager;
-
     /** Preferred way to show this dialog */
     public static void show(FragmentManager fragmentManager) {
         final ImportDialogFragment fragment = new ImportDialogFragment();
         fragment.show(fragmentManager, TAG);
     }
 
-    /**
-     * Create an instance that will only have items for the SIM cards (VCF will not be included).
-     */
-    public static void showForSimOnly(FragmentManager fragmentManager) {
+    public static void show(FragmentManager fragmentManager, List<SimCard> sims,
+            boolean includeVcf) {
         final ImportDialogFragment fragment = new ImportDialogFragment();
-        Bundle args = new Bundle();
-        args.putBoolean(EXTRA_SIM_ONLY, true);
+        final Bundle args = new Bundle();
+        args.putBoolean(EXTRA_SIM_ONLY, !includeVcf);
+        for (SimCard sim : sims) {
+            final List<SimContact> contacts = sim.getContacts();
+            if (contacts == null) {
+                continue;
+            }
+            args.putInt(EXTRA_SIM_CONTACT_COUNT_PREFIX + sim.getSimId(), contacts.size());
+        }
+
         fragment.setArguments(args);
         fragment.show(fragmentManager, TAG);
     }
@@ -92,6 +95,8 @@
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
+        setStyle(STYLE_NORMAL, R.style.ContactsAlertDialogThemeAppCompat);
+
         final Bundle args = getArguments();
         mSimOnly = args != null && args.getBoolean(EXTRA_SIM_ONLY, false);
         mSimDao = SimContactDao.create(getContext());
@@ -109,21 +114,62 @@
 
     @Override
     public Dialog onCreateDialog(Bundle savedInstanceState) {
-        // Wrap our context to inflate list items using the correct theme
-        final LayoutInflater dialogInflater = (LayoutInflater)getActivity()
-                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        final LayoutInflater dialogInflater = (LayoutInflater)
+                getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 
         // Adapter that shows a list of string resources
         final ArrayAdapter<AdapterEntry> adapter = new ArrayAdapter<AdapterEntry>(getActivity(),
                 R.layout.select_dialog_item) {
+
             @Override
             public View getView(int position, View convertView, ViewGroup parent) {
-                final TextView result = (TextView)(convertView != null ? convertView :
-                        dialogInflater.inflate(R.layout.select_dialog_item, parent, false));
-
-                result.setText(getItem(position).mLabel);
+                final View result = convertView != null ? convertView :
+                        dialogInflater.inflate(R.layout.select_dialog_item, parent, false);
+                final TextView primaryText = (TextView) result.findViewById(R.id.primary_text);
+                final TextView secondaryText = (TextView) result.findViewById(R.id.secondary_text);
+                final AdapterEntry entry = getItem(position);
+                secondaryText.setVisibility(View.GONE);
+                if (entry.mChoiceResourceId == R.string.import_from_sim) {
+                    final CharSequence secondary = getSimSecondaryText(entry.mSim);
+                    if (TextUtils.isEmpty(secondary)) {
+                        secondaryText.setVisibility(View.GONE);
+                    } else {
+                        secondaryText.setText(secondary);
+                        secondaryText.setVisibility(View.VISIBLE);
+                    }
+                }
+                primaryText.setText(entry.mLabel);
                 return result;
             }
+
+            CharSequence getSimSecondaryText(SimCard sim) {
+                int count = getSimContactCount(sim);
+
+                CharSequence phone = sim.getFormattedPhone();
+                if (phone == null) {
+                    phone = sim.getPhone();
+                }
+                if (phone != null) {
+                    phone = PhoneNumberUtilsCompat.createTtsSpannable(phone);
+                }
+
+                if (count != -1 && phone != null) {
+                    // We use a template instead of format string so that the TTS span is preserved
+                    final CharSequence template = getResources()
+                            .getQuantityString(R.plurals.import_from_sim_secondary_template, count);
+                    return TextUtils.expandTemplate(template, String.valueOf(count), phone);
+                } else if (phone != null) {
+                    return phone;
+                } else if (count != -1) {
+                    // count != -1
+                    return getResources()
+                            .getQuantityString(
+                                    R.plurals.import_from_sim_secondary_contact_count_fmt, count,
+                                    count);
+                } else {
+                    return null;
+                }
+            }
         };
 
         addItems(adapter);
@@ -135,10 +181,9 @@
                 boolean dismissDialog;
                 final int resId = adapter.getItem(which).mChoiceResourceId;
                 if (resId == R.string.import_from_sim) {
-                    dismissDialog = handleSimImportRequest(adapter.getItem(which).mSubscriptionId);
+                    dismissDialog = handleSimImportRequest(adapter.getItem(which).mSim);
                 } else if (resId == R.string.import_from_vcf_file) {
-                        dismissDialog = handleImportRequest(resId,
-                                adapter.getItem(which).mSubscriptionId);
+                        dismissDialog = handleImportRequest(resId, SimCard.NO_SUBSCRIPTION_ID);
                 } else {
                     dismissDialog = true;
                     Log.e(TAG, "Unexpected resource: "
@@ -149,12 +194,29 @@
                 }
             }
         };
-        final TextView title = (TextView) View.inflate(getActivity(), R.layout.dialog_title, null);
-        title.setText(R.string.dialog_import);
-        return new AlertDialog.Builder(getActivity())
-                .setCustomTitle(title)
-                .setSingleChoiceItems(adapter, -1, clickListener)
-                .create();
+
+        final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), getTheme())
+                .setTitle(R.string.dialog_import)
+                .setNegativeButton(android.R.string.cancel, null);
+        if (adapter.isEmpty()) {
+            // Handle edge case; e.g. SIM card was removed.
+            builder.setMessage(R.string.nothing_to_import_message);
+        } else {
+            builder.setSingleChoiceItems(adapter, -1, clickListener);
+        }
+
+        return builder.create();
+    }
+
+    private int getSimContactCount(SimCard sim) {
+        if (sim.getContacts() != null) {
+            return sim.getContacts().size();
+        }
+        final Bundle args = getArguments();
+        if (args == null) {
+            return -1;
+        }
+        return args.getInt(EXTRA_SIM_CONTACT_COUNT_PREFIX + sim.getSimId(), -1);
     }
 
     private void addItems(ArrayAdapter<AdapterEntry> adapter) {
@@ -167,17 +229,18 @@
 
         if (sims.size() == 1) {
             adapter.add(new AdapterEntry(getString(R.string.import_from_sim),
-                    R.string.import_from_sim, SimCard.NO_SUBSCRIPTION_ID));
+                    R.string.import_from_sim, sims.get(0)));
             return;
         }
-        for (SimCard sim : sims) {
-            adapter.add(new AdapterEntry(getSimDescription(sim), R.string.import_from_sim,
-                    sim.getSubscriptionId()));
+        for (int i = 0; i < sims.size(); i++) {
+            final SimCard sim = sims.get(i);
+            adapter.add(new AdapterEntry(getSimDescription(sim, i), R.string.import_from_sim, sim));
         }
     }
 
-    private boolean handleSimImportRequest(int subscriptionId) {
-        SimImportFragment.newInstance(subscriptionId).show(getFragmentManager(), "SimImport");
+    private boolean handleSimImportRequest(SimCard sim) {
+        SimImportFragment.newInstance(sim.getSubscriptionId()).show(getFragmentManager(),
+                "SimImport");
         return true;
     }
 
@@ -235,38 +298,30 @@
         dismiss();
     }
 
-    private CharSequence getSimDescription(SimCard sim) {
+    private CharSequence getSimDescription(SimCard sim, int index) {
         final CharSequence name = sim.getDisplayName();
-        CharSequence number = sim.getFormattedPhone();
-        // If formatting fails use the raw phone number
-        if (number == null) {
-            number = sim.getPhone();
-        }
-        if (number != null) {
-            number = PhoneNumberUtilsCompat.createTtsSpannable(number);
-        }
-        if (TextUtils.isEmpty(number)) {
+        if (name != null) {
             return getString(R.string.import_from_sim_summary_fmt, name);
+        } else {
+            return getString(R.string.import_from_sim_summary_fmt, String.valueOf(index));
         }
-        return new SpannableStringBuilder(getString(R.string.import_from_sim_summary_fmt, name))
-                .append('\n').append(number);
     }
 
     private static class AdapterEntry {
         public final CharSequence mLabel;
         public final int mChoiceResourceId;
-        public final int mSubscriptionId;
+        public final SimCard mSim;
 
-        public AdapterEntry(CharSequence label, int resId, int subId) {
+        public AdapterEntry(CharSequence label, int resId, SimCard sim) {
             mLabel = label;
             mChoiceResourceId = resId;
-            mSubscriptionId = subId;
+            mSim = sim;
         }
 
         public AdapterEntry(String label, int resId) {
             // Store a nonsense value for mSubscriptionId. If this constructor is used,
             // the mSubscriptionId value should not be read later.
-            this(label, resId, /* subId = */ -1);
+            this(label, resId, /* sim= */ null);
         }
     }
 }
diff --git a/src/com/android/contacts/common/model/SimCard.java b/src/com/android/contacts/common/model/SimCard.java
index 3c27cfe..c316ec4 100644
--- a/src/com/android/contacts/common/model/SimCard.java
+++ b/src/com/android/contacts/common/model/SimCard.java
@@ -110,6 +110,10 @@
         return PhoneNumberUtils.formatNumber(mPhoneNumber, mCountryCode);
     }
 
+    public boolean hasPhone() {
+        return mPhoneNumber != null;
+    }
+
     public String getCountryCode() {
         return mCountryCode;
     }