am faed3374: Switch from CALL -> CALL_PRIVILEGED

* commit 'faed337493039d8b149aace3816000cd396c99fe':
  Switch from CALL -> CALL_PRIVILEGED
diff --git a/src/com/android/contacts/common/CallUtil.java b/src/com/android/contacts/common/CallUtil.java
index 32bd9e1..3a932ab 100644
--- a/src/com/android/contacts/common/CallUtil.java
+++ b/src/com/android/contacts/common/CallUtil.java
@@ -116,6 +116,13 @@
     }
 
     /**
+     * A variant of {@link #getCallIntent(android.net.Uri)} for calling Voicemail.
+     */
+    public static Intent getVoicemailIntent() {
+        return getCallIntent(Uri.fromParts(PhoneAccount.SCHEME_VOICEMAIL, "", null));
+    }
+
+    /**
      * A variant of {@link #getCallIntent(android.net.Uri)} but also accept a call
      * origin and {@code Account} and {@code VideoCallProfile} state.
      * For more information about call origin, see comments in Phone package (PhoneApp).
diff --git a/src/com/android/contacts/common/interactions/ImportExportDialogFragment.java b/src/com/android/contacts/common/interactions/ImportExportDialogFragment.java
index 8d87714..99b8df5 100644
--- a/src/com/android/contacts/common/interactions/ImportExportDialogFragment.java
+++ b/src/com/android/contacts/common/interactions/ImportExportDialogFragment.java
@@ -28,7 +28,10 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.provider.ContactsContract.Contacts;
+import android.telephony.SubInfoRecord;
+import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
+import android.text.TextUtils;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -47,6 +50,7 @@
 import com.android.contacts.common.vcard.VCardCommonArguments;
 import com.android.dialerbind.analytics.AnalyticsDialogFragment;
 
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -57,6 +61,7 @@
     public static final String TAG = "ImportExportDialogFragment";
 
     private static final String KEY_RES_ID = "resourceId";
+    private static final String KEY_SUBSCRIPTION_ID = "subscriptionId";
     private static final String ARG_CONTACTS_ARE_AVAILABLE = "CONTACTS_ARE_AVAILABLE";
 
     private final String[] LOOKUP_PROJECTION = new String[] {
@@ -91,15 +96,14 @@
                 VCardCommonArguments.ARG_CALLING_ACTIVITY);
 
         // Adapter that shows a list of string resources
-        final ArrayAdapter<Integer> adapter = new ArrayAdapter<Integer>(getActivity(),
+        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));
 
-                final int resId = getItem(position);
-                result.setText(resId);
+                result.setText(getItem(position).mLabel);
                 return result;
             }
         };
@@ -107,21 +111,32 @@
         final TelephonyManager manager =
                 (TelephonyManager) getActivity().getSystemService(Context.TELEPHONY_SERVICE);
 
-        if (manager != null && manager.hasIccCard()
-                && res.getBoolean(R.bool.config_allow_sim_import)) {
-            adapter.add(R.string.import_from_sim);
-        }
         if (res.getBoolean(R.bool.config_allow_import_from_sdcard)) {
-            adapter.add(R.string.import_from_sdcard);
+            adapter.add(new AdapterEntry(getString(R.string.import_from_sdcard),
+                    R.string.import_from_sdcard));
+        }
+        if (manager != null && res.getBoolean(R.bool.config_allow_sim_import)) {
+            final List<SubInfoRecord> subInfoRecords = getAllSubInfoList();
+            if (subInfoRecords.size() == 1) {
+                adapter.add(new AdapterEntry(getString(R.string.import_from_sim),
+                        R.string.import_from_sim, subInfoRecords.get(0).subId));
+            } else {
+                for (SubInfoRecord record : subInfoRecords) {
+                    adapter.add(new AdapterEntry(getSubDescription(record),
+                            R.string.import_from_sim, record.subId));
+                }
+            }
         }
         if (res.getBoolean(R.bool.config_allow_export_to_sdcard)) {
             if (contactsAreAvailable) {
-                adapter.add(R.string.export_to_sdcard);
+                adapter.add(new AdapterEntry(getString(R.string.export_to_sdcard),
+                        R.string.export_to_sdcard));
             }
         }
         if (res.getBoolean(R.bool.config_allow_share_visible_contacts)) {
             if (contactsAreAvailable) {
-                adapter.add(R.string.share_visible_contacts);
+                adapter.add(new AdapterEntry(getString(R.string.share_visible_contacts),
+                        R.string.share_visible_contacts));
             }
         }
 
@@ -130,11 +145,12 @@
             @Override
             public void onClick(DialogInterface dialog, int which) {
                 boolean dismissDialog;
-                final int resId = adapter.getItem(which);
+                final int resId = adapter.getItem(which).mChoiceResourceId;
                 switch (resId) {
                     case R.string.import_from_sim:
                     case R.string.import_from_sdcard: {
-                        dismissDialog = handleImportRequest(resId);
+                        dismissDialog = handleImportRequest(resId,
+                                adapter.getItem(which).mSubscriptionId);
                         break;
                     }
                     case R.string.export_to_sdcard: {
@@ -207,7 +223,7 @@
      *
      * @return {@code true} if the dialog show be closed.  {@code false} otherwise.
      */
-    private boolean handleImportRequest(int resId) {
+    private boolean handleImportRequest(int resId, long subscriptionId) {
         // There are three possibilities:
         // - more than one accounts -> ask the user
         // - just one account -> use the account without asking the user
@@ -219,6 +235,7 @@
             // Send over to the account selector
             final Bundle args = new Bundle();
             args.putInt(KEY_RES_ID, resId);
+            args.putLong(KEY_SUBSCRIPTION_ID, subscriptionId);
             SelectAccountDialogFragment.show(
                     getFragmentManager(), this,
                     R.string.dialog_new_contact_account,
@@ -231,7 +248,7 @@
         }
 
         AccountSelectionUtil.doImport(getActivity(), resId,
-                (size == 1 ? accountList.get(0) : null));
+                (size == 1 ? accountList.get(0) : null), subscriptionId);
         return true; // Close the dialog.
     }
 
@@ -240,7 +257,8 @@
      */
     @Override
     public void onAccountChosen(AccountWithDataSet account, Bundle extraArgs) {
-        AccountSelectionUtil.doImport(getActivity(), extraArgs.getInt(KEY_RES_ID), account);
+        AccountSelectionUtil.doImport(getActivity(), extraArgs.getInt(KEY_RES_ID),
+                account, extraArgs.getLong(KEY_SUBSCRIPTION_ID));
 
         // At this point the dialog is still showing (which is why we can use getActivity() above)
         // So close it.
@@ -252,4 +270,49 @@
         // See onAccountChosen() -- at this point the dialog is still showing.  Close it.
         dismiss();
     }
+
+    /**
+     * Return the same values as {@link SubscriptionManager#getAllSubInfoList()} without relying
+     * on any hidden methods.
+     */
+    // TODO: replace with a method that doesn't make assumptions about the number of SIM slots
+    private static List<SubInfoRecord> getAllSubInfoList() {
+        final List<SubInfoRecord> subInfoRecords0 = SubscriptionManager.getSubInfoUsingSlotId(0);
+        final List<SubInfoRecord> subInfoRecords1 = SubscriptionManager.getSubInfoUsingSlotId(1);
+        if (subInfoRecords0 == null && subInfoRecords1 != null) {
+            return subInfoRecords1;
+        }
+        if (subInfoRecords0 != null && subInfoRecords1 == null) {
+            return subInfoRecords0;
+        }
+        if (subInfoRecords0 == null && subInfoRecords1 == null) {
+            return Collections.EMPTY_LIST;
+        }
+        subInfoRecords0.addAll(subInfoRecords1);
+        return subInfoRecords0;
+    }
+
+    private String getSubDescription(SubInfoRecord record) {
+        if (TextUtils.isEmpty(record.number)) {
+            // Don't include the phone number in the description, since we don't know the number.
+            return getString(R.string.import_from_sim_summary_no_number, record.displayName);
+        }
+        return getString(R.string.import_from_sim_summary, record.displayName, record.number);
+    }
+
+    private static class AdapterEntry {
+        public final String mLabel;
+        public final int mChoiceResourceId;
+        public final long mSubscriptionId;
+
+        public AdapterEntry(String label, int resId, long subscriptionId) {
+            mLabel = label;
+            mChoiceResourceId = resId;
+            mSubscriptionId = subscriptionId;
+        }
+
+        public AdapterEntry(String label, int resId) {
+            this(label, resId, SubscriptionManager.INVALID_SUB_ID);
+        }
+    }
 }
diff --git a/src/com/android/contacts/common/util/AccountSelectionUtil.java b/src/com/android/contacts/common/util/AccountSelectionUtil.java
index ab32736..68217b9 100644
--- a/src/com/android/contacts/common/util/AccountSelectionUtil.java
+++ b/src/com/android/contacts/common/util/AccountSelectionUtil.java
@@ -22,6 +22,7 @@
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.net.Uri;
+import android.telephony.SubscriptionManager;
 import android.util.Log;
 import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
@@ -54,22 +55,31 @@
 
         final private Context mContext;
         final private int mResId;
+        final private long mSubscriptionId;
 
         final protected List<AccountWithDataSet> mAccountList;
 
         public AccountSelectedListener(Context context, List<AccountWithDataSet> accountList,
-                int resId) {
+                int resId, long subscriptionId) {
             if (accountList == null || accountList.size() == 0) {
                 Log.e(LOG_TAG, "The size of Account list is 0.");
             }
             mContext = context;
             mAccountList = accountList;
             mResId = resId;
+            mSubscriptionId = subscriptionId;
+        }
+
+        public AccountSelectedListener(Context context, List<AccountWithDataSet> accountList,
+                int resId) {
+            // Subscription id is only needed for importing from SIM card. We can safely ignore
+            // its value for SD card importing.
+            this(context, accountList, resId, SubscriptionManager.INVALID_SUB_ID);
         }
 
         public void onClick(DialogInterface dialog, int which) {
             dialog.dismiss();
-            doImport(mContext, mResId, mAccountList.get(which));
+            doImport(mContext, mResId, mAccountList.get(which), mSubscriptionId);
         }
     }
 
@@ -150,10 +160,11 @@
             .create();
     }
 
-    public static void doImport(Context context, int resId, AccountWithDataSet account) {
+    public static void doImport(Context context, int resId, AccountWithDataSet account,
+            long subscriptionId) {
         switch (resId) {
             case R.string.import_from_sim: {
-                doImportFromSim(context, account);
+                doImportFromSim(context, account, subscriptionId);
                 break;
             }
             case R.string.import_from_sdcard: {
@@ -163,7 +174,8 @@
         }
     }
 
-    public static void doImportFromSim(Context context, AccountWithDataSet account) {
+    public static void doImportFromSim(Context context, AccountWithDataSet account,
+            long subscriptionId) {
         Intent importIntent = new Intent(Intent.ACTION_VIEW);
         importIntent.setType("vnd.android.cursor.item/sim-contact");
         if (account != null) {
@@ -171,6 +183,7 @@
             importIntent.putExtra("account_type", account.type);
             importIntent.putExtra("data_set", account.dataSet);
         }
+        importIntent.putExtra("subscription_id", subscriptionId);
         importIntent.setClassName("com.android.phone", "com.android.phone.SimContacts");
         context.startActivity(importIntent);
     }
diff --git a/src/com/android/contacts/common/vcard/ImportVCardActivity.java b/src/com/android/contacts/common/vcard/ImportVCardActivity.java
index 70c9821..62e8431 100644
--- a/src/com/android/contacts/common/vcard/ImportVCardActivity.java
+++ b/src/com/android/contacts/common/vcard/ImportVCardActivity.java
@@ -109,8 +109,6 @@
 
     final static String CACHED_URIS = "cached_uris";
 
-    private AccountSelectionUtil.AccountSelectedListener mAccountSelectionListener;
-
     private AccountWithDataSet mAccount;
 
     private ProgressDialog mProgressDialogForScanVCard;
@@ -891,14 +889,6 @@
     @Override
     protected Dialog onCreateDialog(int resId, Bundle bundle) {
         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, mCancelListener);
-            }
             case R.id.dialog_searching_vcard: {
                 if (mProgressDialogForScanVCard == null) {
                     String message = getString(R.string.searching_vcard_message);
diff --git a/src/com/android/contacts/common/widget/SelectPhoneAccountDialogFragment.java b/src/com/android/contacts/common/widget/SelectPhoneAccountDialogFragment.java
new file mode 100644
index 0000000..0dbe70a
--- /dev/null
+++ b/src/com/android/contacts/common/widget/SelectPhoneAccountDialogFragment.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.contacts.common.widget;
+
+import android.telecom.PhoneAccount;
+import android.telecom.PhoneAccountHandle;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.FragmentManager;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.telecom.TelecomManager;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ListAdapter;
+import android.widget.TextView;
+
+import com.android.contacts.common.R;
+
+import java.util.List;
+
+/**
+ * Dialog that allows the user to select a phone accounts for a given action. Optionally provides
+ * the choice to set the phone account as default.
+ */
+public class SelectPhoneAccountDialogFragment extends DialogFragment {
+    private boolean mCanSetDefault;
+    private List<PhoneAccountHandle> mAccountHandles;
+    private boolean mIsSelected;
+    private boolean mIsDefaultChecked;
+    private TelecomManager mTelecomManager;
+    private SelectPhoneAccountListener mListener;
+
+    /**
+     * Shows the account selection dialog.
+     * This is the preferred way to show this dialog.
+     *
+     * @param fragmentManager The fragment manager.
+     * @param accountHandles The {@code PhoneAccountHandle}s available to select from.
+     */
+    public static void showAccountDialog(FragmentManager fragmentManager, boolean canSetDefault,
+            List<PhoneAccountHandle> accountHandles, SelectPhoneAccountListener listener) {
+        SelectPhoneAccountDialogFragment fragment =
+                new SelectPhoneAccountDialogFragment(canSetDefault, accountHandles, listener);
+        fragment.show(fragmentManager, "selectAccount");
+    }
+
+    public SelectPhoneAccountDialogFragment(boolean canSetDefault,
+            List<PhoneAccountHandle> accountHandles, SelectPhoneAccountListener listener) {
+        super();
+        mCanSetDefault = canSetDefault;
+        mAccountHandles = accountHandles;
+        mListener = listener;
+    }
+
+    public interface SelectPhoneAccountListener {
+        void onPhoneAccountSelected(PhoneAccountHandle selectedAccountHandle, boolean setDefault);
+        void onDialogDismissed();
+    }
+
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        mIsSelected = false;
+        mIsDefaultChecked = false;
+        mTelecomManager =
+                (TelecomManager) getActivity().getSystemService(Context.TELECOM_SERVICE);
+
+        final DialogInterface.OnClickListener selectionListener =
+                new DialogInterface.OnClickListener() {
+            @Override
+            public void onClick(DialogInterface dialog, int which) {
+                mIsSelected = true;
+                PhoneAccountHandle selectedAccountHandle = mAccountHandles.get(which);
+                mListener.onPhoneAccountSelected(selectedAccountHandle, mIsDefaultChecked);
+            }
+        };
+
+        final CompoundButton.OnCheckedChangeListener checkListener =
+                new CompoundButton.OnCheckedChangeListener() {
+            @Override
+            public void onCheckedChanged(CompoundButton check, boolean isChecked) {
+                mIsDefaultChecked = isChecked;
+            }
+        };
+
+        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+        ListAdapter selectAccountListAdapter = new SelectAccountListAdapter(
+                builder.getContext(),
+                R.layout.select_account_list_item,
+                mAccountHandles);
+
+        AlertDialog dialog = builder.setTitle(R.string.select_account_dialog_title)
+                .setAdapter(selectAccountListAdapter, selectionListener)
+                .create();
+
+        if (mCanSetDefault) {
+            // Generate custom checkbox view
+            LinearLayout checkboxLayout = (LinearLayout) getActivity()
+                    .getLayoutInflater()
+                    .inflate(R.layout.default_account_checkbox, null);
+
+            CheckBox cb =
+                    (CheckBox) checkboxLayout.findViewById(R.id.default_account_checkbox_view);
+            cb.setOnCheckedChangeListener(checkListener);
+
+            dialog.getListView().addFooterView(checkboxLayout);
+        }
+
+        return dialog;
+    }
+
+    private class SelectAccountListAdapter extends ArrayAdapter<PhoneAccountHandle> {
+        private Context mContext;
+        private int mResId;
+
+        public SelectAccountListAdapter(
+                Context context, int resource, List<PhoneAccountHandle> accountHandles) {
+            super(context, resource, accountHandles);
+            mContext = context;
+            mResId = resource;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            LayoutInflater inflater = (LayoutInflater)
+                    mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+            View rowView;
+            final ViewHolder holder;
+
+            if (convertView == null) {
+                // Cache views for faster scrolling
+                rowView = inflater.inflate(mResId, null);
+                holder = new ViewHolder();
+                holder.textView = (TextView) rowView.findViewById(R.id.text);
+                holder.imageView = (ImageView) rowView.findViewById(R.id.icon);
+                rowView.setTag(holder);
+            }
+            else {
+                rowView = convertView;
+                holder = (ViewHolder) rowView.getTag();
+            }
+
+            PhoneAccountHandle accountHandle = getItem(position);
+            PhoneAccount account = mTelecomManager.getPhoneAccount(accountHandle);
+            holder.textView.setText(account.getLabel());
+            holder.imageView.setImageDrawable(account.getIcon(mContext));
+            return rowView;
+        }
+
+        private class ViewHolder {
+            TextView textView;
+            ImageView imageView;
+        }
+    }
+
+    @Override
+    public void onPause() {
+        if (!mIsSelected) {
+            mListener.onDialogDismissed();
+        }
+        super.onPause();
+    }
+}
\ No newline at end of file