Merge "Import translations. DO NOT MERGE" into ub-contactsdialer-master-dev
diff --git a/AndroidManifest_common.xml b/AndroidManifest_common.xml
index c616c1e..8fc97ac 100644
--- a/AndroidManifest_common.xml
+++ b/AndroidManifest_common.xml
@@ -351,7 +351,20 @@
             </intent-filter>
         </activity>
 
-        <activity
+         <!-- Keep support for apps that expect the Compact editor -->
+         <activity-alias android:name="com.android.contacts.activities.CompactContactEditorActivity"
+             android:exported="true"
+             android:targetActivity=".activities.ContactEditorActivity">
+             <intent-filter android:priority="-1">
+                 <action android:name="android.intent.action.INSERT" />
+                 <category android:name="android.intent.category.DEFAULT" />
+                 <data android:mimeType="vnd.android.cursor.dir/person" />
+                 <data android:mimeType="vnd.android.cursor.dir/contact" />
+                 <data android:mimeType="vnd.android.cursor.dir/raw_contact" />
+             </intent-filter>
+         </activity-alias>
+
+         <activity
             android:name=".activities.ContactEditorSpringBoardActivity"
             android:noHistory="true"
             android:theme="@style/TransparentThemeAppCompat">
diff --git a/res/drawable/ic_arrow_drop_down_black_24dp.xml b/res/drawable/ic_arrow_drop_down_black_24dp.xml
new file mode 100644
index 0000000..ebf2123
--- /dev/null
+++ b/res/drawable/ic_arrow_drop_down_black_24dp.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M7,10l5,5 5,-5z"/>
+</vector>
diff --git a/res/drawable/ic_close_24dp.xml b/res/drawable/ic_close_24dp.xml
index 52070d5..bcbb759 100644
--- a/res/drawable/ic_close_24dp.xml
+++ b/res/drawable/ic_close_24dp.xml
@@ -18,7 +18,7 @@
         android:width="24dp"
         android:height="24dp"
         android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
+        android:viewportHeight="24.0" >
     <path
         android:fillColor="@android:color/white"
         android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
diff --git a/res/layout/fragment_sim_import.xml b/res/layout/fragment_sim_import.xml
index b0eb280..d6d3acf 100644
--- a/res/layout/fragment_sim_import.xml
+++ b/res/layout/fragment_sim_import.xml
@@ -26,14 +26,13 @@
 
         <android.support.v7.widget.Toolbar
             android:id="@+id/toolbar"
-            style="@style/ContactsToolbarStyle"
+            style="@style/LightToolbarStyle"
             android:layout_width="match_parent"
             android:layout_height="?attr/actionBarSize"
-            android:background="?attr/colorPrimary"
-            android:elevation="4dp"
-            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
+            android:elevation="3dp"
+            android:theme="@style/LightToolbarThemeOverlay"
             app:navigationContentDescription="@string/sim_import_cancel_content_description"
-            app:navigationIcon="@drawable/ic_close_dk"
+            app:navigationIcon="@drawable/ic_close_24dp"
             app:title="@string/sim_import_title_none_selected">
 
             <Button
@@ -41,19 +40,56 @@
                 style="@style/Widget.AppCompat.Button.Borderless"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_gravity="right|center_vertical"
+                android:layout_gravity="end|center_vertical"
                 android:text="@string/sim_import_button_text"
                 />
         </android.support.v7.widget.Toolbar>
 
-        <FrameLayout
+
+        <!-- This is managed by AccountHeaderPresenter so the IDs in this section must
+             match the equivalent views in layout/editor_account_header.xml -->
+        <LinearLayout
+            xmlns:android="http://schemas.android.com/apk/res/android"
+            android:id="@+id/account_header_container"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:background="?android:colorBackground"
-            android:elevation="4dp">
+            android:minHeight="48dp"
+            android:orientation="horizontal"
+            android:paddingEnd="32dp"
+            android:paddingStart="16dp">
 
-            <include layout="@layout/editor_account_header"/>
-        </FrameLayout>
+            <ImageView
+                android:id="@+id/account_type_icon"
+                android:layout_width="24dp"
+                android:layout_height="24dp"
+                android:layout_gravity="center_vertical"
+                android:layout_marginEnd="32dp"/>
+
+            <TextView
+                android:id="@+id/account_name"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_vertical"
+                android:layout_weight="1"
+                android:ellipsize="end"
+                android:gravity="center_vertical"
+                android:lines="1"
+                android:maxLines="1"
+                android:textColor="@color/secondary_text_color"
+                android:textSize="16sp"/>
+
+            <ImageView
+                android:id="@+id/account_expander_icon"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginRight="9dp"
+                android:layout_gravity="center_vertical"
+                android:scaleType="center"
+                android:src="@drawable/ic_arrow_drop_down_black_24dp"
+                android:tint="?android:textColorSecondary"
+                android:visibility="gone"/>
+        </LinearLayout>
 
         <FrameLayout
             android:layout_width="match_parent"
diff --git a/res/layout/join_contact_picker_section_header.xml b/res/layout/join_contact_picker_section_header.xml
index 7dafb49..f39cafd 100644
--- a/res/layout/join_contact_picker_section_header.xml
+++ b/res/layout/join_contact_picker_section_header.xml
@@ -23,8 +23,9 @@
     <TextView
         android:id="@+id/text"
         style="@style/ContactListSeparatorTextViewStyle"
-        android:paddingLeft="8dip"
-        android:paddingRight="8dip"
-        android:paddingStart="8dip"
-        android:paddingEnd="8dip" />
+        android:textAlignment="viewStart"
+        android:paddingLeft="24dip"
+        android:paddingRight="24dip"
+        android:paddingStart="24dip"
+        android:paddingEnd="24dip"/>
 </LinearLayout>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index d3431fb..d603973 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -148,8 +148,8 @@
     <!-- For join screen. Mainly for tablet. -->
     <dimen name="join_header_left_margin">@dimen/contact_browser_list_header_left_margin</dimen>
     <dimen name="join_header_right_margin">@dimen/contact_browser_list_header_right_margin</dimen>
-    <dimen name="join_header_top_margin">16dip</dimen>
-    <dimen name="join_header_bottom_margin">0dip</dimen>
+    <dimen name="join_header_top_margin">12dip</dimen>
+    <dimen name="join_header_bottom_margin">12dip</dimen>
 
     <dimen name="contact_filter_header_min_height">24dip</dimen>
 
diff --git a/res/values/strings.xml b/res/values/strings.xml
index de283bb..70b8d9e 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -972,9 +972,9 @@
     <string name="permission_explanation_subheader_SMS">Messages</string>
 
     <!-- The header text for hamburger promo [CHAR LIMIT=60]-->
-    <string name="hamburger_feature_highlight_header">Organize your list</string>
+    <string name="hamburger_feature_highlight_header">Suggestions</string>
     <!-- The body text for hamburger promo [CHAR LIMIT=200]-->
-    <string name="hamburger_feature_highlight_body">Clean up duplicates &amp; group contacts by label</string>
+    <string name="hamburger_feature_highlight_body">Keep your contacts organized and useful</string>
 
     <!-- The label for the action shown in a snackbar after an operation that modifies some data is performed.
          The user can click on the action to rollback the modification-->
@@ -1850,9 +1850,6 @@
     <!-- Toolbar title shown when importing SIM contacts and none are selected -->
     <string name="sim_import_title_none_selected">Select contacts</string>
 
-    <!-- Toolbar title shown when importing SIM contacts and some are selected -->
-    <string name="sim_import_title_some_selected_fmt"><xliff:g id="count">%d</xliff:g> Selected</string>
-
     <!-- Message shown when the SIM import screen is displayed but there are no contacts on the
          SIM card  -->
     <string name="sim_import_empty_message">No contacts on your SIM card</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index ab1a4ba..b762177 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -231,6 +231,21 @@
         <item name="titleTextAppearance">@style/ContactsActionBarTitleTextAppCompat</item>
     </style>
 
+    <style name="LightToolbarNavigationButtonStyle" parent="@style/Widget.AppCompat.Toolbar.Button.Navigation">
+        <item name="android:tint">?android:textColorSecondary</item>
+    </style>
+
+    <style name="LightToolbarThemeOverlay" parent="@style/ThemeOverlay.AppCompat.ActionBar">
+        <item name="toolbarNavigationButtonStyle">@style/LightToolbarNavigationButtonStyle</item>
+    </style>
+
+    <style name="LightToolbarStyle" parent="@style/Widget.AppCompat.Toolbar">
+        <item name="android:background">@color/contextual_selection_bar_color</item>
+        <item name="background">@color/contextual_selection_bar_color</item>
+        <item name="android:titleTextAppearance">@style/ContactsActionBarTitleTextBlack</item>
+        <item name="titleTextAppearance">@style/ContactsActionBarTitleTextBlack</item>
+    </style>
+
     <!-- Text in the action bar at the top of the screen -->
     <style name="ContactsActionBarTitleText"
            parent="@android:style/TextAppearance.Material.Widget.ActionBar.Title">
diff --git a/src/com/android/contacts/ContactsDrawerActivity.java b/src/com/android/contacts/ContactsDrawerActivity.java
index 770298e..b7ae71a 100644
--- a/src/com/android/contacts/ContactsDrawerActivity.java
+++ b/src/com/android/contacts/ContactsDrawerActivity.java
@@ -823,9 +823,9 @@
             onAccountChosen(accounts.get(0), /* extraArgs */ null);
             return;
         }
-        SelectAccountDialogFragment.show(getFragmentManager(), null,
-                R.string.dialog_new_group_account, AccountListFilter.ACCOUNTS_GROUP_WRITABLE,
-                /* extraArgs */ null, TAG_SELECT_ACCOUNT_DIALOG);
+        SelectAccountDialogFragment.show(getFragmentManager(), R.string.dialog_new_group_account,
+                AccountListFilter.ACCOUNTS_GROUP_WRITABLE, /* extraArgs */ null,
+                TAG_SELECT_ACCOUNT_DIALOG);
     }
 
     @Override
diff --git a/src/com/android/contacts/SimImportFragment.java b/src/com/android/contacts/SimImportFragment.java
index d9030a8..66be41b 100644
--- a/src/com/android/contacts/SimImportFragment.java
+++ b/src/com/android/contacts/SimImportFragment.java
@@ -27,11 +27,13 @@
 import android.support.annotation.Nullable;
 import android.support.design.widget.Snackbar;
 import android.support.v4.util.ArrayMap;
+import android.support.v4.view.ViewCompat;
 import android.support.v4.widget.ContentLoadingProgressBar;
 import android.support.v7.widget.Toolbar;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.AbsListView;
 import android.widget.AdapterView;
 import android.widget.ListView;
 
@@ -47,9 +49,11 @@
 import com.android.contacts.common.model.account.AccountWithDataSet;
 import com.android.contacts.common.preference.ContactsPreferences;
 import com.android.contacts.editor.AccountHeaderPresenter;
+import com.google.common.primitives.Longs;
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeSet;
@@ -60,22 +64,22 @@
  */
 public class SimImportFragment extends DialogFragment
         implements LoaderManager.LoaderCallbacks<SimImportFragment.LoaderResult>,
-        MultiSelectEntryContactListAdapter.SelectedContactsListener {
+        MultiSelectEntryContactListAdapter.SelectedContactsListener, AbsListView.OnScrollListener {
 
-    private static final String KEY_SELECTED_IDS = "selectedIds";
+    private static final String KEY_SUFFIX_SELECTED_IDS = "_selectedIds";
     private static final String ARG_SUBSCRIPTION_ID = "subscriptionId";
 
     private ContactsPreferences mPreferences;
     private AccountTypeManager mAccountTypeManager;
     private SimContactAdapter mAdapter;
+    private View mAccountHeaderContainer;
     private AccountHeaderPresenter mAccountHeaderPresenter;
+    private float mAccountScrolledElevationPixels;
     private ContentLoadingProgressBar mLoadingIndicator;
     private Toolbar mToolbar;
     private ListView mListView;
     private View mImportButton;
 
-    private long[] mSelectedContacts;
-
     private int mSubscriptionId;
 
     @Override
@@ -96,9 +100,6 @@
         final Bundle args = getArguments();
         mSubscriptionId = args == null ? SimCard.NO_SUBSCRIPTION_ID :
                 args.getInt(ARG_SUBSCRIPTION_ID, SimCard.NO_SUBSCRIPTION_ID);
-
-        if (savedInstanceState == null) return;
-        mSelectedContacts = savedInstanceState.getLongArray(KEY_SELECTED_IDS);
     }
 
     @Override
@@ -121,8 +122,11 @@
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
         final View view = inflater.inflate(R.layout.fragment_sim_import, container, false);
 
+        mAccountHeaderContainer = view.findViewById(R.id.account_header_container);
+        mAccountScrolledElevationPixels = getResources()
+                .getDimension(R.dimen.contact_list_header_elevation);
         mAccountHeaderPresenter = new AccountHeaderPresenter(
-                view.findViewById(R.id.account_header_container));
+                mAccountHeaderContainer);
         if (savedInstanceState != null) {
             mAccountHeaderPresenter.onRestoreInstanceState(savedInstanceState);
         } else {
@@ -137,8 +141,10 @@
             }
         });
         mAdapter.setAccount(mAccountHeaderPresenter.getCurrentAccount());
+        restoreAdapterSelectedStates(savedInstanceState);
 
         mListView = (ListView) view.findViewById(R.id.list);
+        mListView.setOnScrollListener(this);
         mListView.setAdapter(mAdapter);
         mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
             @Override
@@ -160,7 +166,8 @@
                 dismiss();
             }
         });
-        mImportButton.setEnabled(mAdapter.getSelectedContactIds().size() > 0);
+        mImportButton.setVisibility(mAdapter.getSelectedContactIds().size() > 0 ?
+                View.VISIBLE : View.GONE);
 
         mToolbar = (Toolbar) view.findViewById(R.id.toolbar);
         mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@@ -188,9 +195,7 @@
     public void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
         mAccountHeaderPresenter.onSaveInstanceState(outState);
-        if (mAdapter != null && mAdapter.mContacts != null) {
-            outState.putLongArray(KEY_SELECTED_IDS, mAdapter.getSelectedContactIdsArray());
-        }
+        saveAdapterSelectedStates(outState);
     }
 
     @Override
@@ -207,17 +212,41 @@
             return;
         }
         mAdapter.setData(data);
-        if (mSelectedContacts != null) {
-            mAdapter.select(mSelectedContacts);
-        } else {
-            mAdapter.selectAll();
-        }
     }
 
     @Override
     public void onLoaderReset(Loader<LoaderResult> loader) {
     }
 
+    private void restoreAdapterSelectedStates(Bundle savedInstanceState) {
+        if (savedInstanceState == null) {
+            return;
+        }
+
+        final List<AccountWithDataSet> accounts = mAccountTypeManager.getAccounts(true);
+        for (AccountWithDataSet account : accounts) {
+            final long[] selections = savedInstanceState.getLongArray(
+                    account.stringify() + KEY_SUFFIX_SELECTED_IDS);
+            if (selections != null) {
+                mAdapter.setSelectionsForAccount(account, selections);
+            }
+        }
+    }
+
+    private void saveAdapterSelectedStates(Bundle outState) {
+        if (mAdapter == null) {
+            return;
+        }
+
+        // Make sure the selections are up-to-date
+        mAdapter.storeCurrentSelections();
+        for (Map.Entry<AccountWithDataSet, TreeSet<Long>> entry :
+                mAdapter.getSelectedIds().entrySet()) {
+            final long[] ids = Longs.toArray(entry.getValue());
+            outState.putLongArray(entry.getKey().stringify() + KEY_SUFFIX_SELECTED_IDS, ids);
+        }
+    }
+
     private void importCurrentSelections() {
         ContactSaveService.startService(getContext(), ContactSaveService
                 .createImportFromSimIntent(getContext(), mSubscriptionId,
@@ -240,11 +269,10 @@
         if (selectedCount == 0) {
             mToolbar.setTitle(R.string.sim_import_title_none_selected);
         } else {
-            mToolbar.setTitle(getString(R.string.sim_import_title_some_selected_fmt,
-                    selectedCount));
+            mToolbar.setTitle(String.valueOf(selectedCount));
         }
         if (mImportButton != null) {
-            mImportButton.setEnabled(selectedCount > 0);
+            mImportButton.setVisibility(selectedCount > 0 ? View.VISIBLE : View.GONE);
         }
     }
 
@@ -255,6 +283,24 @@
         return getActivity();
     }
 
+    @Override
+    public void onScrollStateChanged(AbsListView view, int scrollState) { }
+
+    @Override
+    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
+            int totalItemCount) {
+        int firstCompletelyVisibleItem = firstVisibleItem;
+        if (view != null && view.getChildAt(0) != null && view.getChildAt(0).getTop() < 0) {
+            firstCompletelyVisibleItem++;
+        }
+
+        if (firstCompletelyVisibleItem == 0) {
+            ViewCompat.setElevation(mAccountHeaderContainer, 0);
+        } else {
+            ViewCompat.setElevation(mAccountHeaderContainer, mAccountScrolledElevationPixels);
+        }
+    }
+
     /**
      * Creates a fragment that will display contacts stored on the default SIM card
      */
@@ -306,6 +352,7 @@
             mExistingMap = result.accountsMap;
             changeCursor(SimContact.convertToContactsCursor(mContacts,
                     ContactQuery.CONTACT_PROJECTION_PRIMARY));
+            updateDisplayedSelections();
         }
 
         public void setAccount(AccountWithDataSet account) {
@@ -315,11 +362,25 @@
             }
 
             // Save the checked state for the current account.
+            storeCurrentSelections();
+            mSelectedAccount = account;
+            updateDisplayedSelections();
+        }
+
+        public void storeCurrentSelections() {
             if (mSelectedAccount != null) {
                 mPerAccountCheckedIds.put(mSelectedAccount, getSelectedContactIds());
             }
+        }
 
-            mSelectedAccount = account;
+        public Map<AccountWithDataSet, TreeSet<Long>> getSelectedIds() {
+            return mPerAccountCheckedIds;
+        }
+
+        private void updateDisplayedSelections() {
+            if (mContacts == null) {
+                return;
+            }
 
             TreeSet<Long> checked = mPerAccountCheckedIds.get(mSelectedAccount);
             if (checked == null) {
@@ -344,24 +405,12 @@
             return selected;
         }
 
-        public void selectAll() {
-            if (mContacts == null) return;
-
-            final TreeSet<Long> selected = new TreeSet<>();
-            for (SimContact contact : mContacts) {
-                if (!existsInCurrentAccount(contact)) {
-                    selected.add(contact.getId());
-                }
+        public void setSelectionsForAccount(AccountWithDataSet account, long[] contacts) {
+            final TreeSet<Long> selected = new TreeSet<>(Longs.asList(contacts));
+            mPerAccountCheckedIds.put(account, selected);
+            if (account.equals(mSelectedAccount)) {
+                updateDisplayedSelections();
             }
-            setSelectedContactIds(selected);
-        }
-
-        public void select(long[] contacts) {
-            final TreeSet<Long> selected = new TreeSet<>();
-            for (long contact : contacts) {
-                selected.add(contact);
-            }
-            setSelectedContactIds(selected);
         }
 
         public boolean existsInCurrentAccount(int position) {
diff --git a/src/com/android/contacts/activities/PeopleActivity.java b/src/com/android/contacts/activities/PeopleActivity.java
index 47fc2a3..0bf7908 100644
--- a/src/com/android/contacts/activities/PeopleActivity.java
+++ b/src/com/android/contacts/activities/PeopleActivity.java
@@ -825,9 +825,13 @@
                     R.id.contacts_list_container, mMembersFragment, TAG_GROUP_VIEW);
         } else if (isAssistantView()) {
             Fragment uiFragment = fragmentManager.findFragmentByTag(TAG_ASSISTANT);
+            Fragment unavailableFragment = fragmentManager.findFragmentByTag(TAG_UNAVAILABLE);
             if (uiFragment == null) {
                 uiFragment = ObjectFactory.getAssistantFragment();
             }
+            if (unavailableFragment != null) {
+                transaction.remove(unavailableFragment);
+            }
             transaction.replace(R.id.contacts_list_container, uiFragment, TAG_ASSISTANT);
             resetToolBarStatusBarColor();
         }
diff --git a/src/com/android/contacts/common/CallUtil.java b/src/com/android/contacts/common/CallUtil.java
index 88fca92..acfad52 100644
--- a/src/com/android/contacts/common/CallUtil.java
+++ b/src/com/android/contacts/common/CallUtil.java
@@ -20,6 +20,7 @@
 import com.android.contacts.common.compat.PhoneAccountSdkCompat;
 import com.android.contacts.common.util.PermissionsUtil;
 import com.android.contacts.common.util.PhoneNumberHelper;
+import com.android.contactsbind.FeedbackHelper;
 import com.android.phone.common.PhoneConstants;
 
 import android.content.Context;
@@ -41,6 +42,8 @@
  */
 public class CallUtil {
 
+    public static final String TAG = "CallUtil";
+
     /**
      * Indicates that the video calling is not available.
      */
@@ -140,26 +143,32 @@
             return VIDEO_CALLING_DISABLED;
         }
 
-        List<PhoneAccountHandle> accountHandles = telecommMgr.getCallCapablePhoneAccounts();
-        for (PhoneAccountHandle accountHandle : accountHandles) {
-            PhoneAccount account = telecommMgr.getPhoneAccount(accountHandle);
-            if (account != null) {
-                if (account.hasCapabilities(PhoneAccount.CAPABILITY_VIDEO_CALLING)) {
-                    // Builds prior to N do not have presence support.
-                    if (!CompatUtils.isVideoPresenceCompatible()) {
-                        return VIDEO_CALLING_ENABLED;
-                    }
+        try {
+            List<PhoneAccountHandle> accountHandles = telecommMgr.getCallCapablePhoneAccounts();
+            for (PhoneAccountHandle accountHandle : accountHandles) {
+                PhoneAccount account = telecommMgr.getPhoneAccount(accountHandle);
+                if (account != null) {
+                    if (account.hasCapabilities(PhoneAccount.CAPABILITY_VIDEO_CALLING)) {
+                        // Builds prior to N do not have presence support.
+                        if (!CompatUtils.isVideoPresenceCompatible()) {
+                            return VIDEO_CALLING_ENABLED;
+                        }
 
-                    int videoCapabilities = VIDEO_CALLING_ENABLED;
-                    if (account.hasCapabilities(
-                            PhoneAccountSdkCompat.CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE)) {
-                        videoCapabilities |= VIDEO_CALLING_PRESENCE;
+                        int videoCapabilities = VIDEO_CALLING_ENABLED;
+                        if (account.hasCapabilities(PhoneAccountSdkCompat
+                                .CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE)) {
+                            videoCapabilities |= VIDEO_CALLING_PRESENCE;
+                        }
+                        return videoCapabilities;
                     }
-                    return videoCapabilities;
                 }
             }
+            return VIDEO_CALLING_DISABLED;
+        } catch (SecurityException e) {
+            FeedbackHelper.sendFeedback(context, TAG,
+                    "Security exception when querying intent activities", e);
+            return VIDEO_CALLING_DISABLED;
         }
-        return VIDEO_CALLING_DISABLED;
     }
 
     /**
diff --git a/src/com/android/contacts/common/database/SimContactDao.java b/src/com/android/contacts/common/database/SimContactDao.java
index 8805c52..3175ce4 100644
--- a/src/com/android/contacts/common/database/SimContactDao.java
+++ b/src/com/android/contacts/common/database/SimContactDao.java
@@ -24,7 +24,6 @@
 import android.content.pm.PackageManager;
 import android.database.Cursor;
 import android.net.Uri;
-import android.os.AsyncTask;
 import android.os.Build;
 import android.os.RemoteException;
 import android.provider.BaseColumns;
@@ -40,14 +39,12 @@
 import android.util.SparseArray;
 
 import com.android.contacts.R;
-import com.android.contacts.common.Experiments;
 import com.android.contacts.common.compat.CompatUtils;
 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.PermissionsUtil;
 import com.android.contacts.util.SharedPreferenceUtil;
-import com.android.contactsbind.experiments.Flags;
 import com.google.common.base.Joiner;
 
 import java.util.ArrayList;
@@ -97,17 +94,6 @@
         mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
     }
 
-    public void warmupSimQueryIfNeeded() {
-        if (!canReadSimContacts()) return;
-
-        new AsyncTask<Void, Void, Void>() {
-            @Override
-            protected Void doInBackground(Void... params) {
-                getSimCardsWithContacts();
-                return null;
-            }
-        }.execute();
-    }
 
     public Context getContext() {
         return mContext;
@@ -279,13 +265,19 @@
         return contacts != null ? contacts : loadContactsForSim(sim);
     }
 
+    // See b/32831092
+    // Sometimes the SIM contacts provider seems to get stuck if read from multiple threads
+    // concurrently. So we just have a global lock around it to prevent potential issues.
+    private static final Object SIM_READ_LOCK = new Object();
     private ArrayList<SimContact> loadFrom(Uri uri) {
-        final Cursor cursor = mResolver.query(uri, null, null, null, null);
+        synchronized (SIM_READ_LOCK) {
+            final Cursor cursor = mResolver.query(uri, null, null, null, null);
 
-        try {
-            return loadFromCursor(cursor);
-        } finally {
-            cursor.close();
+            try {
+                return loadFromCursor(cursor);
+            } finally {
+                cursor.close();
+            }
         }
     }
 
@@ -423,10 +415,6 @@
         }
 
         @Override
-        public void warmupSimQueryIfNeeded() {
-        }
-
-        @Override
         public List<SimCard> getSimCards() {
             return SharedPreferenceUtil.restoreSimStates(getContext(), mSimCards);
         }
diff --git a/src/com/android/contacts/common/interactions/ImportDialogFragment.java b/src/com/android/contacts/common/interactions/ImportDialogFragment.java
index db7f621..a748b81 100644
--- a/src/com/android/contacts/common/interactions/ImportDialogFragment.java
+++ b/src/com/android/contacts/common/interactions/ImportDialogFragment.java
@@ -25,9 +25,6 @@
 import android.content.DialogInterface;
 import android.content.res.Resources;
 import android.os.Bundle;
-import android.support.v4.text.TextUtilsCompat;
-import android.text.SpannableString;
-import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.LayoutInflater;
@@ -54,12 +51,11 @@
 /**
  * An dialog invoked to import/export contacts.
  */
-public class ImportDialogFragment extends DialogFragment
-        implements SelectAccountDialogFragment.Listener {
+public class ImportDialogFragment extends DialogFragment {
     public static final String TAG = "ImportDialogFragment";
 
-    private static final String KEY_RES_ID = "resourceId";
-    private static final String KEY_SUBSCRIPTION_ID = "subscriptionId";
+    public static final String KEY_RES_ID = "resourceId";
+    public static final String KEY_SUBSCRIPTION_ID = "subscriptionId";
 
     public static final String EXTRA_SIM_ONLY = "extraSimOnly";
 
@@ -178,20 +174,16 @@
                 new DialogInterface.OnClickListener() {
             @Override
             public void onClick(DialogInterface dialog, int which) {
-                boolean dismissDialog;
                 final int resId = adapter.getItem(which).mChoiceResourceId;
                 if (resId == R.string.import_from_sim) {
-                    dismissDialog = handleSimImportRequest(adapter.getItem(which).mSim);
+                    handleSimImportRequest(adapter.getItem(which).mSim);
                 } else if (resId == R.string.import_from_vcf_file) {
-                        dismissDialog = handleImportRequest(resId, SimCard.NO_SUBSCRIPTION_ID);
+                    handleImportRequest(resId, SimCard.NO_SUBSCRIPTION_ID);
                 } else {
-                    dismissDialog = true;
                     Log.e(TAG, "Unexpected resource: "
                             + getActivity().getResources().getResourceEntryName(resId));
                 }
-                if (dismissDialog) {
-                    dialog.dismiss();
-                }
+                dialog.dismiss();
             }
         };
 
@@ -238,18 +230,15 @@
         }
     }
 
-    private boolean handleSimImportRequest(SimCard sim) {
+    private void handleSimImportRequest(SimCard sim) {
         SimImportFragment.newInstance(sim.getSubscriptionId()).show(getFragmentManager(),
                 "SimImport");
-        return true;
     }
 
     /**
      * Handle "import from SD".
-     *
-     * @return {@code true} if the dialog show be closed.  {@code false} otherwise.
      */
-    private boolean handleImportRequest(int resId, int subscriptionId) {
+    private void handleImportRequest(int resId, int subscriptionId) {
         // There are three possibilities:
         // - more than one accounts -> ask the user
         // - just one account -> use the account without asking the user
@@ -263,39 +252,13 @@
             args.putInt(KEY_RES_ID, resId);
             args.putInt(KEY_SUBSCRIPTION_ID, subscriptionId);
             SelectAccountDialogFragment.show(
-                    getFragmentManager(), this,
-                    R.string.dialog_new_contact_account,
+                    getFragmentManager(), R.string.dialog_new_contact_account,
                     AccountListFilter.ACCOUNTS_CONTACT_WRITABLE, args);
-
-            // In this case, because this DialogFragment is used as a target fragment to
-            // SelectAccountDialogFragment, we can't close it yet.  We close the dialog when
-            // we get a callback from it.
-            return false;
+        } else {
+            AccountSelectionUtil.doImport(getActivity(), resId,
+                    (size == 1 ? accountList.get(0) : null),
+                    (CompatUtils.isMSIMCompatible() ? subscriptionId : -1));
         }
-
-        AccountSelectionUtil.doImport(getActivity(), resId,
-                (size == 1 ? accountList.get(0) : null),
-                (CompatUtils.isMSIMCompatible() ? subscriptionId : -1));
-        return true; // Close the dialog.
-    }
-
-    /**
-     * Called when an account is selected on {@link SelectAccountDialogFragment}.
-     */
-    @Override
-    public void onAccountChosen(AccountWithDataSet account, Bundle extraArgs) {
-        AccountSelectionUtil.doImport(getActivity(), extraArgs.getInt(KEY_RES_ID),
-                account, extraArgs.getInt(KEY_SUBSCRIPTION_ID));
-
-        // At this point the dialog is still showing (which is why we can use getActivity() above)
-        // So close it.
-        dismiss();
-    }
-
-    @Override
-    public void onAccountSelectorCancelled() {
-        // See onAccountChosen() -- at this point the dialog is still showing.  Close it.
-        dismiss();
     }
 
     private CharSequence getSimDescription(SimCard sim, int index) {
diff --git a/src/com/android/contacts/common/model/account/BaseAccountType.java b/src/com/android/contacts/common/model/account/BaseAccountType.java
index 8d8b8e4..400b0e9 100644
--- a/src/com/android/contacts/common/model/account/BaseAccountType.java
+++ b/src/com/android/contacts/common/model/account/BaseAccountType.java
@@ -947,24 +947,24 @@
             kinds.add(kn);
 
             kn.fieldList.add(new EditField(StructuredName.PREFIX, R.string.name_prefix,
-                    FLAGS_PERSON_NAME).setLongForm(true));
+                    FLAGS_PERSON_NAME).setOptional(true));
             if (!displayOrderPrimary) {
                 kn.fieldList.add(new EditField(StructuredName.FAMILY_NAME, R.string.name_family,
                         FLAGS_PERSON_NAME));
                 kn.fieldList.add(new EditField(StructuredName.MIDDLE_NAME, R.string.name_middle,
-                        FLAGS_PERSON_NAME).setLongForm(true));
+                        FLAGS_PERSON_NAME).setOptional(true));
                 kn.fieldList.add(new EditField(StructuredName.GIVEN_NAME, R.string.name_given,
                         FLAGS_PERSON_NAME));
             } else {
                 kn.fieldList.add(new EditField(StructuredName.GIVEN_NAME, R.string.name_given,
                         FLAGS_PERSON_NAME));
                 kn.fieldList.add(new EditField(StructuredName.MIDDLE_NAME, R.string.name_middle,
-                        FLAGS_PERSON_NAME).setLongForm(true));
+                        FLAGS_PERSON_NAME).setOptional(true));
                 kn.fieldList.add(new EditField(StructuredName.FAMILY_NAME, R.string.name_family,
                         FLAGS_PERSON_NAME));
             }
             kn.fieldList.add(new EditField(StructuredName.SUFFIX, R.string.name_suffix,
-                    FLAGS_PERSON_NAME).setLongForm(true));
+                    FLAGS_PERSON_NAME).setOptional(true));
 
             // Phonetic name
             final DataKind kp = newDataKind(context, parser, attrs, true,
diff --git a/src/com/android/contacts/common/preference/ContactsPreferenceActivity.java b/src/com/android/contacts/common/preference/ContactsPreferenceActivity.java
index 030575d..4bdb12f 100644
--- a/src/com/android/contacts/common/preference/ContactsPreferenceActivity.java
+++ b/src/com/android/contacts/common/preference/ContactsPreferenceActivity.java
@@ -34,15 +34,19 @@
 import android.view.ViewGroup;
 
 import com.android.contacts.common.R;
+import com.android.contacts.common.interactions.ImportDialogFragment;
 import com.android.contacts.common.list.ProviderStatusWatcher;
+import com.android.contacts.common.model.account.AccountWithDataSet;
 import com.android.contacts.common.preference.DisplayOptionsPreferenceFragment.ProfileListener;
 import com.android.contacts.common.preference.DisplayOptionsPreferenceFragment.ProfileQuery;
+import com.android.contacts.common.util.AccountSelectionUtil;
+import com.android.contacts.editor.SelectAccountDialogFragment;
 
 /**
  * Contacts settings.
  */
-public final class ContactsPreferenceActivity extends PreferenceActivity implements
-        ProfileListener {
+public final class ContactsPreferenceActivity extends PreferenceActivity
+        implements ProfileListener, SelectAccountDialogFragment.Listener {
 
     private static final String TAG_ABOUT = "about_contacts";
     private static final String TAG_DISPLAY_OPTIONS = "display_options";
@@ -210,4 +214,14 @@
                 getFragmentManager().findFragmentByTag(TAG_DISPLAY_OPTIONS);
         fragment.updateMyInfoPreference(hasProfile, displayName, contactId);
     }
+
+    @Override
+    public void onAccountChosen(AccountWithDataSet account, Bundle extraArgs) {
+        AccountSelectionUtil.doImport(this, extraArgs.getInt(ImportDialogFragment
+                .KEY_RES_ID), account, extraArgs.getInt(ImportDialogFragment.KEY_SUBSCRIPTION_ID));
+    }
+
+    @Override
+    public void onAccountSelectorCancelled() {
+    }
 }
diff --git a/src/com/android/contacts/editor/AccountHeaderPresenter.java b/src/com/android/contacts/editor/AccountHeaderPresenter.java
index 5323c60..d4f613b 100644
--- a/src/com/android/contacts/editor/AccountHeaderPresenter.java
+++ b/src/com/android/contacts/editor/AccountHeaderPresenter.java
@@ -76,6 +76,8 @@
     public AccountHeaderPresenter(View container) {
         mContext = container.getContext();
         mAccountHeaderContainer = container;
+        // mAccountHeaderType is optional and may not be in the container view in which case
+        // the variable will be null
         mAccountHeaderType = (TextView) container.findViewById(R.id.account_type);
         mAccountHeaderName = (TextView) container.findViewById(R.id.account_name);
         mAccountHeaderIcon = (ImageView) container.findViewById(R.id.account_type_icon);
@@ -144,7 +146,9 @@
 
         // Set the account type
         final String selectorTitle = mContext.getResources().getString(mSelectorTitle);
-        mAccountHeaderType.setText(selectorTitle);
+        if (mAccountHeaderType != null) {
+            mAccountHeaderType.setText(selectorTitle);
+        }
 
         // Set the icon
         final AccountDisplayInfo displayInfo = mAccountDisplayInfoFactory
diff --git a/src/com/android/contacts/editor/SelectAccountDialogFragment.java b/src/com/android/contacts/editor/SelectAccountDialogFragment.java
index 34fac4f..4335239 100644
--- a/src/com/android/contacts/editor/SelectAccountDialogFragment.java
+++ b/src/com/android/contacts/editor/SelectAccountDialogFragment.java
@@ -20,7 +20,6 @@
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.DialogFragment;
-import android.app.Fragment;
 import android.app.FragmentManager;
 import android.content.DialogInterface;
 import android.os.Bundle;
@@ -48,22 +47,18 @@
      * Show the dialog.
      *
      * @param fragmentManager {@link FragmentManager}.
-     * @param targetFragment {@link Fragment} that implements {@link Listener}.
      * @param titleResourceId resource ID to use as the title.
      * @param accountListFilter account filter.
      * @param extraArgs Extra arguments, which will later be passed to
      *     {@link Listener#onAccountChosen}.  {@code null} will be converted to
      *     {@link Bundle#EMPTY}.
      */
-    public static <F extends Fragment & Listener> void show(FragmentManager fragmentManager,
-            F targetFragment, int titleResourceId,
+    public static void show(FragmentManager fragmentManager, int titleResourceId,
             AccountListFilter accountListFilter, Bundle extraArgs) {
-        show(fragmentManager, targetFragment, titleResourceId, accountListFilter, extraArgs,
-                /* tag */ null);
+        show(fragmentManager, titleResourceId, accountListFilter, extraArgs, /* tag */ null);
     }
 
-    public static <F extends Fragment & Listener> void show(FragmentManager fragmentManager,
-            F targetFragment, int titleResourceId,
+    public static void show(FragmentManager fragmentManager, int titleResourceId,
             AccountListFilter accountListFilter, Bundle extraArgs, String tag) {
         final Bundle args = new Bundle();
         args.putInt(KEY_TITLE_RES_ID, titleResourceId);
@@ -72,9 +67,6 @@
 
         final SelectAccountDialogFragment instance = new SelectAccountDialogFragment();
         instance.setArguments(args);
-        if (targetFragment != null) {
-            instance.setTargetFragment(targetFragment, 0);
-        }
         instance.show(fragmentManager, tag);
     }
 
@@ -115,14 +107,8 @@
         }
     }
 
-    @Override
-    public void onSaveInstanceState(Bundle b) {
-        setTargetFragment(null, -1);
-        super.onSaveInstanceState(b);
-    }
-
     /**
-     * Calls {@link Listener#onAccountChosen} of {@code targetFragment}.
+     * Calls {@link Listener#onAccountChosen}.
      */
     private void onAccountSelected(AccountWithDataSet account) {
         final Listener listener = getListener();
@@ -133,14 +119,9 @@
 
     private Listener getListener() {
         Listener listener = null;
-        final Fragment targetFragment = getTargetFragment();
-        if (targetFragment == null) {
-            final Activity activity = getActivity();
-            if (activity != null && activity instanceof Listener) {
-                listener = (Listener) activity;
-            }
-        } else if (targetFragment instanceof Listener) {
-            listener = (Listener) targetFragment;
+        final Activity activity = getActivity();
+        if (activity != null && activity instanceof Listener) {
+            listener = (Listener) activity;
         }
         return listener;
     }
diff --git a/src/com/android/contacts/list/JoinContactListFragment.java b/src/com/android/contacts/list/JoinContactListFragment.java
index d961f34..d827eb5 100644
--- a/src/com/android/contacts/list/JoinContactListFragment.java
+++ b/src/com/android/contacts/list/JoinContactListFragment.java
@@ -146,7 +146,7 @@
     @Override
     public JoinContactListAdapter createListAdapter() {
         JoinContactListAdapter adapter = new JoinContactListAdapter(getActivity());
-        adapter.setPhotoPosition(ContactListItemView.getDefaultPhotoPosition(true /* opposite */));
+        adapter.setPhotoPosition(ContactListItemView.getDefaultPhotoPosition(false /* opposite */));
         return adapter;
     }
 
diff --git a/src/com/android/contacts/list/MultiSelectEmailAddressesListAdapter.java b/src/com/android/contacts/list/MultiSelectEmailAddressesListAdapter.java
index b225ba4..af9ee52 100644
--- a/src/com/android/contacts/list/MultiSelectEmailAddressesListAdapter.java
+++ b/src/com/android/contacts/list/MultiSelectEmailAddressesListAdapter.java
@@ -160,7 +160,6 @@
         cursor.moveToPosition(position);
 
         bindViewId(view, cursor, EmailQuery.EMAIL_ID);
-        bindSectionHeaderAndDivider(view, position);
         if (isFirstEntry) {
             bindName(view, cursor);
             bindQuickContact(view, partition, cursor, EmailQuery.PHOTO_ID,
@@ -190,16 +189,6 @@
         view.showData(cursor, EmailQuery.EMAIL_ADDRESS);
     }
 
-    protected void bindSectionHeaderAndDivider(final ContactListItemView view, int position) {
-        final int section = getSectionForPosition(position);
-        if (getPositionForSection(section) == position) {
-            final String title = (String)getSections()[section];
-            view.setSectionHeader(title);
-        } else {
-            view.setSectionHeader(null);
-        }
-    }
-
     protected void bindName(final ContactListItemView view, Cursor cursor) {
         view.showDisplayName(cursor, EmailQuery.DISPLAY_NAME, getContactNameDisplayOrder());
     }
diff --git a/src/com/android/contacts/list/MultiSelectEmailAddressesListFragment.java b/src/com/android/contacts/list/MultiSelectEmailAddressesListFragment.java
index d14488a..956e473 100644
--- a/src/com/android/contacts/list/MultiSelectEmailAddressesListFragment.java
+++ b/src/com/android/contacts/list/MultiSelectEmailAddressesListFragment.java
@@ -38,7 +38,7 @@
 
     public MultiSelectEmailAddressesListFragment() {
         setPhotoLoaderEnabled(true);
-        setSectionHeaderDisplayEnabled(true);
+        setSectionHeaderDisplayEnabled(false);
         setSearchMode(false);
         setHasOptionsMenu(true);
         setListType(ListEvent.ListType.PICK_EMAIL);
diff --git a/src/com/android/contacts/list/MultiSelectPhoneNumbersListAdapter.java b/src/com/android/contacts/list/MultiSelectPhoneNumbersListAdapter.java
index b3574ab..985809b 100644
--- a/src/com/android/contacts/list/MultiSelectPhoneNumbersListAdapter.java
+++ b/src/com/android/contacts/list/MultiSelectPhoneNumbersListAdapter.java
@@ -160,7 +160,6 @@
         cursor.moveToPosition(position);
 
         bindViewId(view, cursor, PhoneQuery.PHONE_ID);
-        bindSectionHeaderAndDivider(view, position);
         if (isFirstEntry) {
             bindName(view, cursor);
             bindQuickContact(view, partition, cursor, PhoneQuery.PHOTO_ID,
@@ -190,15 +189,6 @@
         view.showData(cursor, PhoneQuery.PHONE_NUMBER);
     }
 
-    protected void bindSectionHeaderAndDivider(final ContactListItemView view, int position) {
-        if (isSectionHeaderDisplayEnabled()) {
-            Placement placement = getItemPlacementInSection(position);
-            view.setSectionHeader(placement.firstInSection ? placement.sectionHeader : null);
-        } else {
-            view.setSectionHeader(null);
-        }
-    }
-
     protected void bindName(final ContactListItemView view, Cursor cursor) {
         view.showDisplayName(cursor, PhoneQuery.DISPLAY_NAME, getContactNameDisplayOrder());
     }
diff --git a/src/com/android/contacts/list/MultiSelectPhoneNumbersListFragment.java b/src/com/android/contacts/list/MultiSelectPhoneNumbersListFragment.java
index 5a1a761..751449b 100644
--- a/src/com/android/contacts/list/MultiSelectPhoneNumbersListFragment.java
+++ b/src/com/android/contacts/list/MultiSelectPhoneNumbersListFragment.java
@@ -38,7 +38,7 @@
 
     public MultiSelectPhoneNumbersListFragment() {
         setPhotoLoaderEnabled(true);
-        setSectionHeaderDisplayEnabled(true);
+        setSectionHeaderDisplayEnabled(false);
         setSearchMode(false);
         setHasOptionsMenu(true);
         setListType(ListEvent.ListType.PICK_PHONE);