Merge "Import translations. DO NOT MERGE" into ub-contactsdialer-h-dev
diff --git a/res/layout-land/contacts_unavailable_fragment_content.xml b/res/layout-land/contacts_unavailable_fragment_content.xml
index 234d7c4..35aa90d 100644
--- a/res/layout-land/contacts_unavailable_fragment_content.xml
+++ b/res/layout-land/contacts_unavailable_fragment_content.xml
@@ -14,64 +14,61 @@
      limitations under the License.
 -->
 
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:gravity="center_horizontal">
+    android:layout_height="match_parent"
+    android:gravity="center_horizontal"
+    android:orientation="vertical">
 
-    <LinearLayout
-        android:orientation="vertical"
+    <ImageView
+        android:id="@+id/empty_image"
+        android:layout_width="@dimen/contacts_no_account_empty_image_width"
+        android:layout_height="wrap_content"
+        android:adjustViewBounds="true"
+        android:scaleType="centerInside"
+        android:src="@drawable/contacts_no_account_empty" />
+
+    <TextView
+        android:id="@+id/message"
+        style="@style/EmptyStateTextStyle"
         android:layout_width="wrap_content"
-        android:layout_height="wrap_content">
-
-        <ImageView
-            android:id="@+id/empty_image"
-            android:layout_width="@dimen/contacts_no_account_empty_image_width"
-            android:layout_height="wrap_content"
-            android:scaleType="centerInside"
-            android:adjustViewBounds="true"
-            android:src="@drawable/contacts_no_account_empty"/>
-
-        <TextView
-            android:id="@+id/message"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="@dimen/contacts_no_account_empty_text_padding_top"
-            android:layout_gravity="center_horizontal"
-            style="@style/EmptyStateTextStyle"/>
-
-        <ProgressBar
-            android:id="@+id/progress"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            style="?android:attr/progressBarStyleHorizontal"
-            android:indeterminate="true"
-            android:layout_gravity="center_horizontal"
-            android:layout_marginTop="12dp" />
-    </LinearLayout>
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
+        android:layout_marginTop="@dimen/contacts_no_account_empty_text_padding_top" />
 
     <LinearLayout
         android:id="@+id/buttons_container"
-        android:orientation="horizontal"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:gravity="center_horizontal">
+        android:gravity="center_horizontal"
+        android:orientation="horizontal">
 
         <Button
             android:id="@+id/add_account_button"
+            style="@style/NoAccountViewButtonStyle"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_marginEnd="@dimen/contacts_no_account_buttons_margin"
-            android:text="@string/contacts_unavailable_add_account"
-            style="@style/NoAccountViewButtonStyle"/>
+            android:text="@string/contacts_unavailable_add_account" />
 
         <Button
             android:id="@+id/import_contacts_button"
+            style="@style/NoAccountViewButtonStyle"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:text="@string/contacts_unavailable_import_contacts"
-            style="@style/NoAccountViewButtonStyle"/>
+            android:text="@string/contacts_unavailable_import_contacts" />
     </LinearLayout>
+
+    <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+        <ProgressBar
+            android:id="@+id/progress"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:indeterminate="true"
+            android:visibility="gone" />
+    </FrameLayout>
 </LinearLayout>
diff --git a/res/layout/contacts_unavailable_fragment_content.xml b/res/layout/contacts_unavailable_fragment_content.xml
index 860490d..dd04ebe 100644
--- a/res/layout/contacts_unavailable_fragment_content.xml
+++ b/res/layout/contacts_unavailable_fragment_content.xml
@@ -14,61 +14,52 @@
      limitations under the License.
 -->
 
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:gravity="center_horizontal">
+    android:layout_height="match_parent"
+    android:gravity="center_horizontal"
+    android:orientation="vertical">
 
     <ImageView
         android:id="@+id/empty_image"
         android:layout_width="@dimen/contacts_no_account_empty_image_width"
         android:layout_height="wrap_content"
-        android:scaleType="centerInside"
         android:adjustViewBounds="true"
-        android:src="@drawable/contacts_no_account_empty"/>
+        android:scaleType="centerInside"
+        android:src="@drawable/contacts_no_account_empty" />
 
-    <LinearLayout
-        android:orientation="vertical"
+    <TextView
+        android:id="@+id/message"
+        style="@style/EmptyStateTextStyle"
         android:layout_width="wrap_content"
-        android:layout_height="wrap_content">
+        android:layout_height="wrap_content"
+        android:layout_marginTop="@dimen/contacts_no_account_empty_text_padding_top" />
 
-        <TextView
-            android:id="@+id/message"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="@dimen/contacts_no_account_empty_text_padding_top"
-            style="@style/EmptyStateTextStyle"/>
+    <Button
+        android:id="@+id/add_account_button"
+        style="@style/NoAccountViewButtonStyle"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="@dimen/contacts_no_account_empty_button_padding_top"
+        android:text="@string/contacts_unavailable_add_account" />
+
+    <Button
+        android:id="@+id/import_contacts_button"
+        style="@style/NoAccountViewButtonStyle"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/contacts_unavailable_import_contacts" />
+
+    <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
 
         <ProgressBar
             android:id="@+id/progress"
-            android:layout_width="match_parent"
+            android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            style="?android:attr/progressBarStyleHorizontal"
+            android:layout_gravity="center"
             android:indeterminate="true"
-            android:layout_gravity="center_horizontal"
-            android:layout_marginTop="12dp" />
-    </LinearLayout>
-
-    <LinearLayout
-        android:orientation="vertical"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content">
-
-        <Button
-            android:id="@+id/add_account_button"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="@dimen/contacts_no_account_empty_button_padding_top"
-            android:text="@string/contacts_unavailable_add_account"
-            style="@style/NoAccountViewButtonStyle"/>
-
-        <Button
-            android:id="@+id/import_contacts_button"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:text="@string/contacts_unavailable_import_contacts"
-            style="@style/NoAccountViewButtonStyle"/>
-    </LinearLayout>
+            android:visibility="gone" />
+    </FrameLayout>
 </LinearLayout>
diff --git a/res/menu/edit_contact.xml b/res/menu/edit_contact.xml
index 9bf067f..a62acc8 100644
--- a/res/menu/edit_contact.xml
+++ b/res/menu/edit_contact.xml
@@ -34,15 +34,6 @@
         android:title="@string/menu_deleteContact" />
 
     <item
-        android:id="@+id/menu_set_ringtone"
-        android:title="@string/menu_set_ring_tone" />
-
-    <item
-        android:id="@+id/menu_send_to_voicemail"
-        android:checkable="true"
-        android:title="@string/menu_redirect_calls_to_vm" />
-
-    <item
         android:id="@+id/menu_help"
         android:title="@string/menu_help" />
 </menu>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index f3e2a04..896d4e6 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -231,9 +231,6 @@
     <dimen name="quickcontact_expanding_button_section_height">48dp</dimen>
     <dimen name="quickcontact_expanding_button_section_padding">8dp</dimen>
 
-    <!-- Top margin of the text message when provider status is busy -->
-    <dimen name="update_contact_list_top_margin">188dp</dimen>
-
     <dimen name="expanding_entry_card_item_icon_height">24dp</dimen>
     <dimen name="expanding_entry_card_item_icon_width">24dp</dimen>
 
diff --git a/res/values/donottranslate_config.xml b/res/values/donottranslate_config.xml
index d3c4966..c6542fb 100644
--- a/res/values/donottranslate_config.xml
+++ b/res/values/donottranslate_config.xml
@@ -26,14 +26,6 @@
          the overlay will fill this in during build time. -->
     <string name="help_url_people_main"></string>
 
-    <!-- Help URL pointing to adding contacts in People. This is intentionally empty because
-         the overlay will fill this in during build time. -->
-    <string name="help_url_people_add"></string>
-
-    <!-- Help URL pointing to editing contacts in People. This is intentionally empty because
-         the overlay will fill this in during build time. -->
-    <string name="help_url_people_edit"></string>
-
     <!-- File Authority for the photo picker -->
     <string name="photo_file_provider_authority">com.android.contacts.files</string>
 
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 0efa091..8ae0401 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -508,9 +508,6 @@
     <!-- An option in the 'Contact photo' dialog, if there is already a photo [CHAR LIMIT=50] -->
     <string name="pick_new_photo">Select new photo</string>
 
-    <!-- Text shown in the contacts app while the background process updates contacts after a system upgrade [CHAR LIMIT=300] -->
-    <string name="upgrade_in_progress">Contact list is being updated.</string>
-
     <!-- Title shown in the search result activity of contacts app while searching.  [CHAR LIMIT=20] -->
     <string name="search_results_searching">Searching\u2026</string>
 
@@ -920,9 +917,6 @@
     <!-- Content description of photo in photo picker indicating a photo from unknown account is selected. -->
     <string name="photo_view_description_checked_no_info">Photo from unknown account checked</string>
 
-    <!-- Text shown in the contacts app while the background process updates contacts after a locale change [CHAR LIMIT=150]-->
-    <string name="locale_change_in_progress">Contact list is being updated to reflect the change of language.\n\nPlease wait&#8230;</string>
-
     <!-- Left drawer menu item to open contacts assistant cards. [CHAR LIMIT=20]-->
     <string name="menu_assistant">Assistant</string>
 
diff --git a/src-bind/com/android/contactsbind/analytics/AnalyticsUtil.java b/src-bind/com/android/contactsbind/analytics/AnalyticsUtil.java
index e48e8f2..53b59eb 100644
--- a/src-bind/com/android/contactsbind/analytics/AnalyticsUtil.java
+++ b/src-bind/com/android/contactsbind/analytics/AnalyticsUtil.java
@@ -25,27 +25,4 @@
      * Initialize this class and setup automatic activity tracking.
      */
     public static void initialize(Application application) { }
-
-    /**
-     * Log a screen view for {@param fragment}.
-     */
-    public static void sendScreenView(Fragment fragment) {}
-
-    public static void sendScreenView(Fragment fragment, Activity activity) {}
-
-    public static void sendScreenView(Fragment fragment, Activity activity, String tag) {}
-
-    public static void sendScreenView(String fragmentName, Activity activity, String tag) {}
-
-    /**
-     * Logs a event to the analytics server.
-     *
-     * @param application The application the tracker is stored in.
-     * @param category The category for the event.
-     * @param action The event action.
-     * @param label The event label.
-     * @param value The value associated with the event.
-     */
-    public static void sendEvent(Application application, String category, String action,
-            String label, long value) { }
 }
\ No newline at end of file
diff --git a/src/com/android/contacts/SimImportFragment.java b/src/com/android/contacts/SimImportFragment.java
index 7421df4..7ce00d2 100644
--- a/src/com/android/contacts/SimImportFragment.java
+++ b/src/com/android/contacts/SimImportFragment.java
@@ -57,7 +57,7 @@
         implements LoaderManager.LoaderCallbacks<ArrayList<SimContact>>,
         MultiSelectEntryContactListAdapter.SelectedContactsListener {
 
-    private static final String KEY_ACCOUNT = "account";
+    private static final String KEY_SELECTED_IDS = "selectedIds";
     private static final String ARG_SUBSCRIPTION_ID = "subscriptionId";
     public static final int NO_SUBSCRIPTION_ID = -1;
 
@@ -70,11 +70,14 @@
     private ListView mListView;
     private View mImportButton;
 
+    private long[] mSelectedContacts;
+
     private int mSubscriptionId;
 
     @Override
     public void onCreate(final Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+
         setStyle(STYLE_NORMAL, R.style.PeopleThemeAppCompat_FullScreenDialog);
         mPreferences = new ContactsPreferences(getContext());
         mAccountTypeManager = AccountTypeManager.getInstance(getActivity());
@@ -87,6 +90,9 @@
         final Bundle args = getArguments();
         mSubscriptionId = args == null ? NO_SUBSCRIPTION_ID : args.getInt(ARG_SUBSCRIPTION_ID,
                 NO_SUBSCRIPTION_ID);
+
+        if (savedInstanceState == null) return;
+        mSelectedContacts = savedInstanceState.getLongArray(KEY_SELECTED_IDS);
     }
 
     @Override
@@ -112,8 +118,7 @@
         mAccountHeaderPresenter = new AccountHeaderPresenter(
                 view.findViewById(R.id.account_header_container));
         if (savedInstanceState != null) {
-            AccountWithDataSet account = savedInstanceState.getParcelable(KEY_ACCOUNT);
-            mAccountHeaderPresenter.setCurrentAccount(account);
+            mAccountHeaderPresenter.onRestoreInstanceState(savedInstanceState);
         } else {
             final AccountWithDataSet currentDefaultAccount = AccountWithDataSet
                     .getDefaultOrBestFallback(mPreferences, mAccountTypeManager);
@@ -164,7 +169,10 @@
     @Override
     public void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
-        outState.putParcelable(KEY_ACCOUNT, mAccountHeaderPresenter.getCurrentAccount());
+        mAccountHeaderPresenter.onSaveInstanceState(outState);
+        if (mAdapter != null) {
+            outState.putLongArray(KEY_SELECTED_IDS, mAdapter.getSelectedContactIdsArray());
+        }
     }
 
     @Override
@@ -177,8 +185,11 @@
             ArrayList<SimContact> data) {
         mListView.setEmptyView(getView().findViewById(R.id.empty_message));
         mAdapter.setContacts(data);
-        // we default to selecting all contacts.
-        mAdapter.selectAll();
+        if (mSelectedContacts != null) {
+            mAdapter.select(mSelectedContacts);
+        } else {
+            mAdapter.selectAll();
+        }
         mLoadingIndicator.hide();
     }
 
@@ -293,6 +304,14 @@
             }
             setSelectedContactIds(selected);
         }
+
+        public void select(long[] contacts) {
+            final TreeSet<Long> selected = new TreeSet<>();
+            for (long contact : contacts) {
+                selected.add(contact);
+            }
+            setSelectedContactIds(selected);
+        }
     }
 
     public static class SimContactLoader extends AsyncTaskLoader<ArrayList<SimContact>> {
diff --git a/src/com/android/contacts/activities/ContactEditorActivity.java b/src/com/android/contacts/activities/ContactEditorActivity.java
index 1845a52..3052a24 100644
--- a/src/com/android/contacts/activities/ContactEditorActivity.java
+++ b/src/com/android/contacts/activities/ContactEditorActivity.java
@@ -164,7 +164,7 @@
         void load(String action, Uri lookupUri, Bundle intentExtras);
 
         /**
-         * Applies extras from the hosting Activity to the first writable raw contact.
+         * Applies extras from the hosting Activity to the writable raw contact.
          */
         void setIntentExtras(Bundle extras);
 
diff --git a/src/com/android/contacts/activities/ContactEditorSpringBoardActivity.java b/src/com/android/contacts/activities/ContactEditorSpringBoardActivity.java
index 5b71c48..69dccb5 100644
--- a/src/com/android/contacts/activities/ContactEditorSpringBoardActivity.java
+++ b/src/com/android/contacts/activities/ContactEditorSpringBoardActivity.java
@@ -30,7 +30,8 @@
  * This activity has noHistory set to true, and all intents coming out from it have
  * {@code FLAG_ACTIVITY_FORWARD_RESULT} set.
  */
-public class ContactEditorSpringBoardActivity extends AppCompatContactsActivity  {
+public class ContactEditorSpringBoardActivity extends AppCompatContactsActivity implements
+        PickRawContactDialogFragment.PickRawContactListener {
     private static final String TAG = "EditorSpringBoard";
     private static final String TAG_RAW_CONTACTS_DIALOG = "rawContactsDialog";
     private static final int LOADER_RAW_CONTACTS = 1;
@@ -109,13 +110,17 @@
         if (ContactsContract.AUTHORITY.equals(authority) &&
                 RawContacts.CONTENT_ITEM_TYPE.equals(type)) {
             final long rawContactId = ContentUris.parseId(mUri);
-            final Intent editorIntent = getIntentForRawContact(rawContactId);
-            ImplicitIntentsUtil.startActivityInApp(this, editorIntent);
+            startEditorAndForwardExtras(getIntentForRawContact(rawContactId));
         } else {
             getLoaderManager().initLoader(LOADER_RAW_CONTACTS, null, mRawContactLoaderListener);
         }
     }
 
+    @Override
+    public void onPickRawContact(long rawContactId) {
+        startEditorAndForwardExtras(getIntentForRawContact(rawContactId));
+    }
+
     /**
      * Start the dialog to pick the raw contact to edit.
      */
@@ -134,7 +139,7 @@
             ft.remove(oldFragment);
         }
         final PickRawContactDialogFragment newFragment = PickRawContactDialogFragment.getInstance(
-                mUri, mCursor, mMaterialPalette, mIsUserProfile);
+                 mCursor, mIsUserProfile);
         ft.add(newFragment, TAG_RAW_CONTACTS_DIALOG);
         // commitAllowingStateLoss is safe in this activity because the fragment entirely depends
         // on the result of the loader. Even if we lose the fragment because the activity was
@@ -163,7 +168,7 @@
         // Destroy the loader to prevent multiple onLoadFinished calls in case CP2 is updating in
         // the background.
         getLoaderManager().destroyLoader(LOADER_RAW_CONTACTS);
-        ImplicitIntentsUtil.startActivityInApp(this, intent);
+        startEditorAndForwardExtras(intent);
     }
 
     /**
@@ -195,4 +200,15 @@
         intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
         return intent;
     }
+
+    /**
+     * Starts the given intent within the app, attaching any extras to it that were passed to us.
+     */
+    private void startEditorAndForwardExtras(Intent intent) {
+        final Bundle extras = getIntent().getExtras();
+        if (extras != null) {
+            intent.putExtras(extras);
+        }
+        ImplicitIntentsUtil.startActivityInApp(this, intent);
+    }
 }
diff --git a/src/com/android/contacts/common/list/PhoneNumberPickerFragment.java b/src/com/android/contacts/common/list/PhoneNumberPickerFragment.java
index 3b7ed6b..bbbd794 100644
--- a/src/com/android/contacts/common/list/PhoneNumberPickerFragment.java
+++ b/src/com/android/contacts/common/list/PhoneNumberPickerFragment.java
@@ -29,10 +29,6 @@
 
 import com.android.contacts.common.R;
 import com.android.contacts.common.list.ShortcutIntentBuilder.OnShortcutIntentCreatedListener;
-import com.android.contactsbind.analytics.AnalyticsUtil;
-
-import org.json.JSONException;
-import org.json.JSONObject;
 
 /**
  * Fragment containing a phone number list for picking.
@@ -169,12 +165,6 @@
                         + " adapter is ready. Ignoring");
             }
         }
-
-        // Get the lookup key and track any analytics
-        final String lookupKey = getLookupKey(position);
-        if (!TextUtils.isEmpty(lookupKey)) {
-            maybeTrackAnalytics(lookupKey);
-        }
     }
 
     protected void cacheContactInfo(int position) {
@@ -304,42 +294,4 @@
     protected int getCallInitiationType(boolean isRemoteDirectory) {
         return OnPhoneNumberPickerActionListener.CALL_INITIATION_UNKNOWN;
     }
-
-    /**
-     * Where a lookup key contains analytic event information, logs the associated analytics event.
-     *
-     * @param lookupKey The lookup key JSON object.
-     */
-    private void maybeTrackAnalytics(String lookupKey) {
-        try {
-            JSONObject json = new JSONObject(lookupKey);
-
-            String analyticsCategory = json.getString(
-                    PhoneNumberListAdapter.PhoneQuery.ANALYTICS_CATEGORY);
-            String analyticsAction = json.getString(
-                    PhoneNumberListAdapter.PhoneQuery.ANALYTICS_ACTION);
-            String analyticsValue = json.getString(
-                    PhoneNumberListAdapter.PhoneQuery.ANALYTICS_VALUE);
-
-            if (TextUtils.isEmpty(analyticsCategory) || TextUtils.isEmpty(analyticsAction) ||
-                    TextUtils.isEmpty(analyticsValue)) {
-                return;
-            }
-
-            // Assume that the analytic value being tracked could be a float value, but just cast
-            // to a long so that the analytic server can handle it.
-            long value;
-            try {
-                float floatValue = Float.parseFloat(analyticsValue);
-                value = (long) floatValue;
-            } catch (NumberFormatException nfe) {
-                return;
-            }
-
-            AnalyticsUtil.sendEvent(getActivity().getApplication(), analyticsCategory,
-                    analyticsAction, "" /* label */, value);
-        } catch (JSONException e) {
-            // Not an error; just a lookup key that doesn't have the right information.
-        }
-    }
 }
diff --git a/src/com/android/contacts/editor/AccountHeaderPresenter.java b/src/com/android/contacts/editor/AccountHeaderPresenter.java
index de2b014..5323c60 100644
--- a/src/com/android/contacts/editor/AccountHeaderPresenter.java
+++ b/src/com/android/contacts/editor/AccountHeaderPresenter.java
@@ -16,6 +16,7 @@
 package com.android.contacts.editor;
 
 import android.content.Context;
+import android.os.Bundle;
 import android.support.annotation.NonNull;
 import android.support.annotation.StringRes;
 import android.view.View;
@@ -42,6 +43,8 @@
  */
 public class AccountHeaderPresenter {
 
+    private static final String KEY_SELECTED_ACCOUNT = "accountHeaderSelectedAccount";
+
     public interface Observer {
         void onChange(AccountHeaderPresenter sender);
 
@@ -100,6 +103,18 @@
         return mCurrentAccount;
     }
 
+    public void onSaveInstanceState(Bundle outState) {
+        outState.putParcelable(KEY_SELECTED_ACCOUNT, mCurrentAccount);
+    }
+
+    public void onRestoreInstanceState(Bundle savedInstanceState) {
+        if (savedInstanceState == null) return;
+        if (mCurrentAccount == null) {
+            mCurrentAccount = savedInstanceState.getParcelable(KEY_SELECTED_ACCOUNT);
+        }
+        updateDisplayedAccount();
+    }
+
     private void updateDisplayedAccount() {
         mAccountHeaderContainer.setVisibility(View.GONE);
         if (mCurrentAccount == null) return;
@@ -146,31 +161,40 @@
         final View.OnClickListener onClickListener = new View.OnClickListener() {
             @Override
             public void onClick(View v) {
-                final ListPopupWindow popup = new ListPopupWindow(mContext, null);
-                final AccountsListAdapter adapter =
-                        new AccountsListAdapter(mContext,
-                                AccountsListAdapter.AccountListFilter.ACCOUNTS_CONTACT_WRITABLE,
-                                mCurrentAccount);
-                popup.setWidth(mAccountHeaderContainer.getWidth());
-                popup.setAnchorView(mAccountHeaderContainer);
-                popup.setAdapter(adapter);
-                popup.setModal(true);
-                popup.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED);
-                popup.setOnItemClickListener(new AdapterView.OnItemClickListener() {
-                    @Override
-                    public void onItemClick(AdapterView<?> parent, View view, int position,
-                            long id) {
-                        UiClosables.closeQuietly(popup);
-                        final AccountWithDataSet newAccount = adapter.getItem(position);
-                        setCurrentAccount(newAccount);
-                    }
-                });
-                popup.show();
+                showPopup();
             }
         };
         setUpAccountSelector(nameLabel.toString(), onClickListener);
     }
 
+    private void showPopup() {
+        final ListPopupWindow popup = new ListPopupWindow(mContext);
+        final AccountsListAdapter adapter =
+                new AccountsListAdapter(mContext,
+                        AccountsListAdapter.AccountListFilter.ACCOUNTS_CONTACT_WRITABLE,
+                        mCurrentAccount);
+        popup.setWidth(mAccountHeaderContainer.getWidth());
+        popup.setAnchorView(mAccountHeaderContainer);
+        popup.setAdapter(adapter);
+        popup.setModal(true);
+        popup.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED);
+        popup.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+            @Override
+            public void onItemClick(AdapterView<?> parent, View view, int position,
+                    long id) {
+                UiClosables.closeQuietly(popup);
+                final AccountWithDataSet newAccount = adapter.getItem(position);
+                setCurrentAccount(newAccount);
+            }
+        });
+        mAccountHeaderContainer.post(new Runnable() {
+            @Override
+            public void run() {
+                popup.show();
+            }
+        });
+    }
+
     private void setUpAccountSelector(String nameLabel, View.OnClickListener listener) {
         addAccountHeader(nameLabel);
         // Add handlers for choosing another account to save to.
diff --git a/src/com/android/contacts/editor/ContactEditorFragment.java b/src/com/android/contacts/editor/ContactEditorFragment.java
index 455d9ae..0f1ff8e 100644
--- a/src/com/android/contacts/editor/ContactEditorFragment.java
+++ b/src/com/android/contacts/editor/ContactEditorFragment.java
@@ -20,7 +20,6 @@
 import android.app.Activity;
 import android.app.Fragment;
 import android.app.LoaderManager;
-import android.content.ActivityNotFoundException;
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.ContentValues;
@@ -30,7 +29,6 @@
 import android.content.Loader;
 import android.database.Cursor;
 import android.graphics.Bitmap;
-import android.media.RingtoneManager;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.SystemClock;
@@ -60,9 +58,9 @@
 import com.android.contacts.ContactSaveService;
 import com.android.contacts.GroupMetaDataLoader;
 import com.android.contacts.R;
+import com.android.contacts.activities.ContactEditorAccountsChangedActivity;
 import com.android.contacts.activities.ContactEditorActivity;
 import com.android.contacts.activities.ContactEditorActivity.ContactEditor;
-import com.android.contacts.activities.ContactEditorAccountsChangedActivity;
 import com.android.contacts.activities.ContactSelectionActivity;
 import com.android.contacts.common.Experiments;
 import com.android.contacts.common.logging.ScreenEvent.ScreenType;
@@ -86,9 +84,8 @@
 import com.android.contacts.quickcontact.InvisibleContactUtil;
 import com.android.contacts.quickcontact.QuickContactActivity;
 import com.android.contacts.util.ContactPhotoUtils;
-import com.android.contacts.util.HelpUtils;
-import com.android.contacts.util.PhoneCapabilityTester;
 import com.android.contacts.util.UiClosables;
+import com.android.contactsbind.HelpUtils;
 import com.android.contactsbind.ObjectFactory;
 import com.android.contactsbind.experiments.Flags;
 
@@ -146,11 +143,6 @@
     private static final String KEY_IS_EDIT = "isEdit";
     private static final String KEY_EXISTING_CONTACT_READY = "existingContactDataReady";
 
-    // Phone option menus
-    private static final String KEY_SEND_TO_VOICE_MAIL_STATE = "sendToVoicemailState";
-    private static final String KEY_ARE_PHONE_OPTIONS_CHANGEABLE = "arePhoneOptionsChangable";
-    private static final String KEY_CUSTOM_RINGTONE = "customRingtone";
-
     private static final String KEY_IS_USER_PROFILE = "isUserProfile";
 
     private static final String KEY_ENABLED = "enabled";
@@ -167,7 +159,6 @@
 
     protected static final int REQUEST_CODE_JOIN = 0;
     protected static final int REQUEST_CODE_ACCOUNTS_CHANGED = 1;
-    protected static final int REQUEST_CODE_PICK_RINGTONE = 2;
 
     private static final int CURRENT_API_VERSION = android.os.Build.VERSION.SDK_INT;
 
@@ -365,11 +356,6 @@
     // Whether we are editing the "me" profile
     protected boolean mIsUserProfile;
 
-    // Phone specific option menu items
-    private boolean mSendToVoicemailState;
-    private boolean mArePhoneOptionsChangable;
-    private String mCustomRingtone;
-
     // Whether editor views and options menu items should be enabled
     private boolean mEnabled = true;
 
@@ -415,7 +401,6 @@
                     mLookupUri = contact.getLookupUri();
                     final long setDataStartTime = SystemClock.elapsedRealtime();
                     setState(contact);
-                    setStateForPhoneMenuItems(contact);
                     final long setDataEndTime = SystemClock.elapsedRealtime();
 
                     Log.v(TAG, "Time needed for setting UI: " + (setDataEndTime - setDataStartTime));
@@ -506,11 +491,6 @@
 
             mIsUserProfile = savedState.getBoolean(KEY_IS_USER_PROFILE);
 
-            // Phone specific options menus
-            mSendToVoicemailState = savedState.getBoolean(KEY_SEND_TO_VOICE_MAIL_STATE);
-            mArePhoneOptionsChangable = savedState.getBoolean(KEY_ARE_PHONE_OPTIONS_CHANGEABLE);
-            mCustomRingtone = savedState.getString(KEY_CUSTOM_RINGTONE);
-
             mEnabled = savedState.getBoolean(KEY_ENABLED);
 
             // Aggregation PopupWindow
@@ -627,11 +607,6 @@
 
         outState.putBoolean(KEY_IS_USER_PROFILE, mIsUserProfile);
 
-        // Phone specific options
-        outState.putBoolean(KEY_SEND_TO_VOICE_MAIL_STATE, mSendToVoicemailState);
-        outState.putBoolean(KEY_ARE_PHONE_OPTIONS_CHANGEABLE, mArePhoneOptionsChangable);
-        outState.putString(KEY_CUSTOM_RINGTONE, mCustomRingtone);
-
         outState.putBoolean(KEY_ENABLED, mEnabled);
 
         // Aggregation PopupWindow
@@ -704,37 +679,13 @@
                 createContact();
                 break;
             }
-            case REQUEST_CODE_PICK_RINGTONE: {
-                if (data != null) {
-                    final Uri pickedUri = data.getParcelableExtra(
-                            RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
-                    onRingtonePicked(pickedUri);
-                }
-                break;
-            }
         }
     }
 
-    private void onRingtonePicked(Uri pickedUri) {
-        mCustomRingtone = EditorUiUtils.getRingtoneStringFromUri(pickedUri, CURRENT_API_VERSION);
-        Intent intent = ContactSaveService.createSetRingtone(
-                mContext, mLookupUri, mCustomRingtone);
-        mContext.startService(intent);
-    }
-
     //
     // Options menu
     //
 
-    private void setStateForPhoneMenuItems(Contact contact) {
-        if (contact != null) {
-            mSendToVoicemailState = contact.isSendToVoicemail();
-            mCustomRingtone = contact.getCustomRingtone();
-            mArePhoneOptionsChangable = !contact.isDirectoryEntry()
-                    && PhoneCapabilityTester.isPhone(mContext);
-        }
-    }
-
     @Override
     public void onCreateOptionsMenu(Menu menu, final MenuInflater inflater) {
         inflater.inflate(R.menu.edit_contact, menu);
@@ -748,22 +699,8 @@
         final MenuItem saveMenu = menu.findItem(R.id.menu_save);
         final MenuItem splitMenu = menu.findItem(R.id.menu_split);
         final MenuItem joinMenu = menu.findItem(R.id.menu_join);
-        final MenuItem helpMenu = menu.findItem(R.id.menu_help);
-        final MenuItem sendToVoiceMailMenu = menu.findItem(R.id.menu_send_to_voicemail);
-        final MenuItem ringToneMenu = menu.findItem(R.id.menu_set_ringtone);
         final MenuItem deleteMenu = menu.findItem(R.id.menu_delete);
 
-        // Set visibility of menus
-
-        // help menu depending on whether this is inserting or editing
-        if (Intent.ACTION_INSERT.equals(mAction)) {
-            HelpUtils.prepareHelpMenuItem(mContext, helpMenu, R.string.help_url_people_add);
-        } else if (Intent.ACTION_EDIT.equals(mAction)) {
-            HelpUtils.prepareHelpMenuItem(mContext, helpMenu, R.string.help_url_people_edit);
-        } else {
-            // something else, so don't show the help menu
-            helpMenu.setVisible(false);
-        }
         // TODO: b/30771904, b/31827701, temporarily disable these items until we get them to work
         // on a raw contact level.
         joinMenu.setVisible(false);
@@ -781,17 +718,6 @@
             });
         }
 
-        if (mIsUserProfile) {
-            sendToVoiceMailMenu.setVisible(false);
-            ringToneMenu.setVisible(false);
-        } else {
-            // Hide telephony-related settings (ringtone, send to voicemail)
-            // if we don't have a telephone or are editing a new contact.
-            sendToVoiceMailMenu.setChecked(mSendToVoicemailState);
-            sendToVoiceMailMenu.setVisible(mArePhoneOptionsChangable);
-            ringToneMenu.setVisible(mArePhoneOptionsChangable);
-        }
-
         int size = menu.size();
         for (int i = 0; i < size; i++) {
             menu.getItem(i).setEnabled(mEnabled);
@@ -821,16 +747,8 @@
                 return doSplitContactAction();
             case R.id.menu_join:
                 return doJoinContactAction();
-            case R.id.menu_set_ringtone:
-                doPickRingtone();
-                return true;
-            case R.id.menu_send_to_voicemail:
-                // Update state and save
-                mSendToVoicemailState = !mSendToVoicemailState;
-                item.setChecked(mSendToVoicemailState);
-                final Intent intent = ContactSaveService.createSetSendToVoicemail(
-                        mContext, mLookupUri, mSendToVoicemailState);
-                mContext.startService(intent);
+            case R.id.menu_help:
+                HelpUtils.launchHelpAndFeedbackForContactScreen(getActivity());
                 return true;
         }
 
@@ -912,29 +830,6 @@
         doSaveAction(SaveMode.JOIN, joinContactId);
     }
 
-    private void doPickRingtone() {
-        final Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
-        // Allow user to pick 'Default'
-        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true);
-        // Show only ringtones
-        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_RINGTONE);
-        // Allow the user to pick a silent ringtone
-        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, true);
-
-        final Uri ringtoneUri = EditorUiUtils.getRingtoneUriFromString(mCustomRingtone,
-                CURRENT_API_VERSION);
-
-        // Put checkmark next to the current ringtone for this contact
-        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, ringtoneUri);
-
-        // Launch!
-        try {
-            startActivityForResult(intent, REQUEST_CODE_PICK_RINGTONE);
-        } catch (ActivityNotFoundException ex) {
-            Toast.makeText(mContext, R.string.missing_app, Toast.LENGTH_SHORT).show();
-        }
-    }
-
     @Override
     public boolean save(int saveMode) {
         if (!hasValidState() || mStatus != Status.EDITING) {
@@ -1047,8 +942,7 @@
         final ContentValues original = before.getBefore();
         final ContentValues pending = after.getAfter();
         if (original != null && pending != null) {
-            final String beforeDisplayName = original.getAsString(
-                    StructuredName.DISPLAY_NAME);
+            final String beforeDisplayName = original.getAsString(StructuredName.DISPLAY_NAME);
             final String afterDisplayName = pending.getAsString(StructuredName.DISPLAY_NAME);
             if (!TextUtils.equals(beforeDisplayName, afterDisplayName)) return false;
 
@@ -1472,19 +1366,7 @@
 
     @Override
     public void setIntentExtras(Bundle extras) {
-        if (extras == null || extras.size() == 0) {
-            return;
-        }
-
-        final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
-        for (RawContactDelta state : mState) {
-            final AccountType type = state.getAccountType(accountTypes);
-            if (type.areContactsWritable()) {
-                // Apply extras to the first writable raw contact only
-                RawContactModifier.parseExtras(mContext, type, state, extras);
-                break;
-            }
-        }
+        getContent().setIntentExtras(extras);
     }
 
     @Override
@@ -1498,18 +1380,20 @@
         final Cursor cursor = resolver.query(contactUri, new String[]{
                 ContactsContract.Contacts.DISPLAY_NAME,
                 ContactsContract.Contacts.DISPLAY_NAME_ALTERNATIVE}, null, null, null);
-        try {
-            if (cursor.moveToFirst()) {
-                final String displayName = cursor.getString(0);
-                final String displayNameAlt = cursor.getString(1);
-                cursor.close();
-                return ContactDisplayUtils.getPreferredDisplayName(displayName, displayNameAlt,
-                        new ContactsPreferences(mContext));
-            }
-        } finally {
-            cursor.close();
-        }
 
+        if (cursor != null) {
+            try {
+                if (cursor.moveToFirst()) {
+                    final String displayName = cursor.getString(0);
+                    final String displayNameAlt = cursor.getString(1);
+                    cursor.close();
+                    return ContactDisplayUtils.getPreferredDisplayName(displayName, displayNameAlt,
+                            new ContactsPreferences(mContext));
+                }
+            } finally {
+                cursor.close();
+            }
+        }
         return null;
     }
 
diff --git a/src/com/android/contacts/editor/PickRawContactDialogFragment.java b/src/com/android/contacts/editor/PickRawContactDialogFragment.java
index 623d038..dd079a2 100644
--- a/src/com/android/contacts/editor/PickRawContactDialogFragment.java
+++ b/src/com/android/contacts/editor/PickRawContactDialogFragment.java
@@ -6,7 +6,6 @@
 import android.content.ContentUris;
 import android.content.Context;
 import android.content.DialogInterface;
-import android.content.Intent;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Bundle;
@@ -28,18 +27,19 @@
 import com.android.contacts.common.model.account.AccountWithDataSet;
 import com.android.contacts.common.model.account.GoogleAccountType;
 import com.android.contacts.common.preference.ContactsPreferences;
-import com.android.contacts.common.util.ImplicitIntentsUtil;
-import com.android.contacts.common.util.MaterialColorMapUtils.MaterialPalette;
 
 /**
+ * Should only be started from an activity that implements {@link PickRawContactListener}.
  * Dialog containing the raw contacts that make up a contact. On selection the editor is loaded
  * for the chosen raw contact.
  */
 public class PickRawContactDialogFragment extends DialogFragment {
-    private static final String ARGS_URI = "uri";
-    private static final String ARGS_MATERIAL_PALETTE = "materialPalette";
     private static final String ARGS_IS_USER_PROFILE = "isUserProfile";
 
+    public interface PickRawContactListener {
+        void onPickRawContact(long rawContactId);
+    }
+
     /**
      * Used to list the account info for the given raw contacts list.
      */
@@ -142,18 +142,12 @@
 
     // Cursor holding all raw contact rows for the given Contact.
     private Cursor mCursor;
-    // Uri for the whole Contact.
-    private Uri mUri;
     private CursorAdapter mAdapter;
-    private MaterialPalette mMaterialPalette;
     private boolean mIsUserProfile;
 
-    public static PickRawContactDialogFragment getInstance(Uri uri, Cursor cursor,
-            MaterialPalette materialPalette, boolean isUserProfile) {
+    public static PickRawContactDialogFragment getInstance(Cursor cursor, boolean isUserProfile) {
         final PickRawContactDialogFragment fragment = new PickRawContactDialogFragment();
         final Bundle args = new Bundle();
-        args.putParcelable(ARGS_URI, uri);
-        args.putParcelable(ARGS_MATERIAL_PALETTE, materialPalette);
         args.putBoolean(ARGS_IS_USER_PROFILE, isUserProfile);
         fragment.setArguments(args);
         fragment.setCursor(cursor);
@@ -162,6 +156,10 @@
 
     @Override
     public Dialog onCreateDialog(Bundle savedInstanceState) {
+        if (!(getActivity() instanceof PickRawContactListener)) {
+            throw new IllegalArgumentException(
+                    "Host activity doesn't implement PickRawContactListener");
+        }
         final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
         mAdapter = new RawContactAccountListAdapter(getContext(), mCursor);
         builder.setTitle(R.string.contact_editor_pick_raw_contact_dialog_title);
@@ -169,10 +167,7 @@
             @Override
             public void onClick(DialogInterface dialog, int which) {
                 final long rawContactId = mAdapter.getItemId(which);
-                final Intent intent = EditorIntents.createEditContactIntentForRawContact(
-                        getActivity(), mUri, rawContactId, mMaterialPalette);
-                intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
-                ImplicitIntentsUtil.startActivityInApp(getActivity(), intent);
+                ((PickRawContactListener) getActivity()).onPickRawContact(rawContactId);
             }
         });
         builder.setCancelable(true);
@@ -192,8 +187,6 @@
 
         final Bundle args = getArguments();
         if (args != null) {
-            mUri = args.getParcelable(ARGS_URI);
-            mMaterialPalette = args.getParcelable(ARGS_MATERIAL_PALETTE);
             mIsUserProfile = args.getBoolean(ARGS_IS_USER_PROFILE);
         }
     }
diff --git a/src/com/android/contacts/editor/RawContactEditorView.java b/src/com/android/contacts/editor/RawContactEditorView.java
index 1b37dab..fe7894a 100644
--- a/src/com/android/contacts/editor/RawContactEditorView.java
+++ b/src/com/android/contacts/editor/RawContactEditorView.java
@@ -21,6 +21,7 @@
 import android.database.Cursor;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
+import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.provider.ContactsContract.CommonDataKinds.Email;
@@ -223,6 +224,8 @@
 
     private boolean mIsExpanded;
 
+    private Bundle mIntentExtras;
+
     private ValuesDelta mPhotoValuesDelta;
 
     public RawContactEditorView(Context context) {
@@ -425,6 +428,10 @@
         }
     }
 
+    public void setIntentExtras(Bundle extras) {
+        mIntentExtras = extras;
+    }
+
     public void setState(RawContactDeltaList rawContactDeltas,
             MaterialColorMapUtils.MaterialPalette materialPalette, ViewIdGenerator viewIdGenerator,
             boolean hasNewContact, boolean isUserProfile, AccountWithDataSet primaryAccount,
@@ -455,6 +462,8 @@
             return;
         }
         pickRawContactDelta();
+        // Apply any intent extras now that we have selected a raw contact delta.
+        applyIntentExtras();
         parseRawContactDelta();
         if (mKindSectionDataMap.isEmpty()) {
             elog("No kind section data parsed from RawContactDelta(s)");
@@ -531,6 +540,17 @@
 
     }
 
+    private void applyIntentExtras() {
+        if (mIntentExtras == null || mIntentExtras.size() == 0) {
+            return;
+        }
+        final AccountTypeManager accountTypes = AccountTypeManager.getInstance(getContext());
+        final AccountType type = mCurrentRawContactDelta.getAccountType(accountTypes);
+
+        RawContactModifier.parseExtras(getContext(), type, mCurrentRawContactDelta, mIntentExtras);
+        mIntentExtras = null;
+    }
+
     private void parseRawContactDelta() {
         mKindSectionDataMap.clear();
         mSortedMimetypes.clear();
diff --git a/src/com/android/contacts/list/ContactsUnavailableFragment.java b/src/com/android/contacts/list/ContactsUnavailableFragment.java
index 72e6718..ef57d38 100644
--- a/src/com/android/contacts/list/ContactsUnavailableFragment.java
+++ b/src/com/android/contacts/list/ContactsUnavailableFragment.java
@@ -103,10 +103,9 @@
         }
         if (providerStatus == ProviderStatusCompat.STATUS_EMPTY) {
             updateViewsForEmptyStatus();
-        } else if (providerStatus == ProviderStatusCompat.STATUS_BUSY) {
-            updateViewsForBusyStatus(R.string.upgrade_in_progress);
-        } else if (providerStatus == ProviderStatusCompat.STATUS_CHANGING_LOCALE) {
-            updateViewsForBusyStatus(R.string.locale_change_in_progress);
+        } else if (providerStatus == ProviderStatusCompat.STATUS_BUSY
+                || providerStatus == ProviderStatusCompat.STATUS_CHANGING_LOCALE) {
+            updateViewsForBusyStatus();
         }
     }
 
@@ -122,22 +121,12 @@
 
     /**
      * Update views in the fragment when provider status is busy.
-     *
-     * @param resId resource ID of the string to show in mMessageView.
      */
-    private void updateViewsForBusyStatus(int resId) {
-        mMessageView.setText(resId);
-        mMessageView.setVisibility(View.VISIBLE);
+    private void updateViewsForBusyStatus() {
+        mMessageView.setVisibility(View.GONE);
         mImageView.setVisibility(View.GONE);
         updateButtonVisibility(View.GONE);
         mProgress.setVisibility(View.VISIBLE);
-
-        final ViewGroup.MarginLayoutParams layoutParams =
-                (ViewGroup.MarginLayoutParams) mMessageView.getLayoutParams();
-        final int marginTop =
-                (int) getResources().getDimension(R.dimen.update_contact_list_top_margin);
-        layoutParams.setMargins(0, marginTop, 0, 0);
-        mMessageView.setGravity(Gravity.CENTER_HORIZONTAL);
     }
 
     @Override
@@ -153,11 +142,6 @@
         }
     }
 
-    private boolean areContactsAvailable() {
-        return (mProviderStatus != null) && mProviderStatus.equals(ProviderStatus.STATUS_NORMAL);
-    }
-
-
     private void updateButtonVisibility(int visibility) {
         if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
             mAddAccountButton.setVisibility(visibility);