Merge "Import translations. DO NOT MERGE" into ub-contactsdialer-i-dev
diff --git a/res/layout/contact_editor_activity.xml b/res/layout/contact_editor_activity.xml
index 9224ea0..36fc64a 100644
--- a/res/layout/contact_editor_activity.xml
+++ b/res/layout/contact_editor_activity.xml
@@ -16,20 +16,21 @@
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:id="@+id/fragment_container"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:orientation="vertical">
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/fragment_container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
 
-    <Toolbar
+    <android.support.v7.widget.Toolbar
         android:id="@+id/toolbar"
         style="@style/EditorActionBarStyle"
         android:layout_width="match_parent"
         android:layout_height="?android:attr/actionBarSize"
         android:background="?android:attr/colorPrimary"
         android:elevation="4dp"
-        android:navigationContentDescription="@string/cancel_button_content_description"
-        android:navigationIcon="@drawable/quantum_ic_close_vd_theme_24"
-        android:title="@string/contact_editor_title_existing_contact" />
+        app:navigationContentDescription="@string/cancel_button_content_description"
+        app:navigationIcon="@drawable/quantum_ic_close_vd_theme_24"
+        app:title="@string/contact_editor_title_existing_contact" />
 
 </LinearLayout>
\ No newline at end of file
diff --git a/res/layout/photo_editor_view.xml b/res/layout/photo_editor_view.xml
index 05f1a85..b9f32a0 100644
--- a/res/layout/photo_editor_view.xml
+++ b/res/layout/photo_editor_view.xml
@@ -43,6 +43,7 @@
             android:layout_marginBottom="16dp"
             android:layout_marginEnd="16dp"
             android:background="?android:attr/selectableItemBackground"
+            android:tint="@android:color/white"
             android:src="@drawable/quantum_ic_camera_alt_vd_theme_24" />
 
     <View
diff --git a/res/menu/edit_contact.xml b/res/menu/edit_contact.xml
index a62acc8..039c657 100644
--- a/res/menu/edit_contact.xml
+++ b/res/menu/edit_contact.xml
@@ -14,11 +14,12 @@
      limitations under the License.
 -->
 
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
     <item
         android:id="@+id/menu_save"
-        android:showAsAction="always"
-        android:actionLayout="@layout/editor_save_button"
+        app:showAsAction="always"
+        app:actionLayout="@layout/editor_save_button"
         android:title="@string/menu_save" />
 
     <item
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 26761db..31c0f6b 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -15,12 +15,10 @@
 -->
 <resources>
 
-    <style name="EditorActivityTheme" parent="@style/PeopleTheme">
-        <item name="android:listViewStyle">@style/ListViewStyle</item>
-        <item name="android:actionBarStyle">@style/EditorActionBarStyle</item>
-        <item name="android:colorButtonNormal">@color/background_primary</item>
-        <item name="android:windowActionBar">false</item>
-        <item name="android:windowNoTitle">true</item>
+    <style name="EditorActivityTheme" parent="@style/PeopleActivityTheme">
+        <item name="actionBarStyle">@style/EditorActionBarStyle</item>
+        <item name="colorButtonNormal">@color/background_primary</item>
+        <item name="windowActionModeOverlay">true</item>
     </style>
 
     <style name="Theme.QuickContact" parent="@style/PeopleTheme">
@@ -208,7 +206,7 @@
         <item name="icon">@android:color/transparent</item>
     </style>
 
-    <style name="EditorActionBarStyle" parent="@style/ContactsActionBarStyle">
+    <style name="EditorActionBarStyle" parent="@style/ContactsToolbarStyle">
         <item name="android:contentInsetStart">72dp</item>
         <item name="android:contentInsetStartWithNavigation">72dp</item>
         <item name="android:titleTextAppearance">@style/ContactsActionBarTitleText</item>
@@ -265,10 +263,6 @@
         <item name="android:tint">@color/action_bar_button_text_color</item>
     </style>
 
-    <style name="ListViewDropdownStyle" parent="@android:style/Widget.ListView.DropDown">
-        <item name="android:listSelector">?android:attr/listChoiceBackgroundIndicator</item>
-    </style>
-
     <style name="ContactPickerTheme" parent="PeopleActivityTheme">
     </style>
 
diff --git a/src/com/android/contacts/activities/AttachPhotoActivity.java b/src/com/android/contacts/activities/AttachPhotoActivity.java
index ea9eda5..24f9029 100644
--- a/src/com/android/contacts/activities/AttachPhotoActivity.java
+++ b/src/com/android/contacts/activities/AttachPhotoActivity.java
@@ -42,15 +42,20 @@
 import com.android.contacts.ContactsUtils;
 import com.android.contacts.R;
 import com.android.contacts.editor.ContactEditorUtils;
+import com.android.contacts.model.AccountTypeManager;
 import com.android.contacts.model.Contact;
 import com.android.contacts.model.ContactLoader;
 import com.android.contacts.model.RawContactDelta;
 import com.android.contacts.model.RawContactDeltaList;
 import com.android.contacts.model.RawContactModifier;
 import com.android.contacts.model.ValuesDelta;
+import com.android.contacts.model.account.AccountInfo;
 import com.android.contacts.model.account.AccountType;
 import com.android.contacts.model.account.AccountWithDataSet;
 import com.android.contacts.util.ContactPhotoUtils;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
 
 import java.io.FileNotFoundException;
 import java.util.List;
@@ -77,6 +82,8 @@
 
     private ContentResolver mContentResolver;
 
+    private ListenableFuture<List<AccountInfo>> mAccountsFuture;
+
     // Height and width (in pixels) to request for the photo - queried from the provider.
     private static int mPhotoDim;
     // Default photo dimension to use if unable to query the provider.
@@ -124,6 +131,10 @@
                 }
             }
         }
+
+        // Start loading accounts in case they are needed.
+        mAccountsFuture = AccountTypeManager.getInstance(this).filterAccountsAsync(
+                AccountTypeManager.writableFilter());
     }
 
     @Override
@@ -341,16 +352,26 @@
     }
 
     private void selectAccountAndCreateContact() {
+        Preconditions.checkNotNull(mAccountsFuture, "Accounts future must be initialized first");
         // If there is no default account or the accounts have changed such that we need to
         // prompt the user again, then launch the account prompt.
         final ContactEditorUtils editorUtils = ContactEditorUtils.create(this);
-        if (editorUtils.shouldShowAccountChangedNotification()) {
+
+        // Technically this could block but in reality this method won't be called until the user
+        // presses the save button which should allow plenty of time for the accounts to
+        // finish loading. Note also that this could be stale if the accounts have changed since
+        // we requested them but that's OK since ContactEditorAccountsChangedActivity will reload
+        // the accounts
+        final List<AccountInfo> accountInfos = Futures.getUnchecked(mAccountsFuture);
+
+        final List<AccountWithDataSet> accounts = AccountInfo.extractAccounts(accountInfos);
+        if (editorUtils.shouldShowAccountChangedNotification(accounts)) {
             Intent intent = new Intent(this, ContactEditorAccountsChangedActivity.class);
             startActivityForResult(intent, REQUEST_PICK_DEFAULT_ACCOUNT_FOR_NEW_CONTACT);
         } else {
             // Otherwise, there should be a default account. Then either create a null contact
             // (if default account is null) or create a contact with the specified account.
-            final AccountWithDataSet targetAccount = editorUtils.getOnlyOrDefaultAccount();
+            final AccountWithDataSet targetAccount = editorUtils.getOnlyOrDefaultAccount(accounts);
             createNewRawContact(targetAccount);
         }
     }
diff --git a/src/com/android/contacts/activities/ContactEditorActivity.java b/src/com/android/contacts/activities/ContactEditorActivity.java
index 326ff93..a33e92f 100644
--- a/src/com/android/contacts/activities/ContactEditorActivity.java
+++ b/src/com/android/contacts/activities/ContactEditorActivity.java
@@ -23,13 +23,13 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.provider.ContactsContract.QuickContact;
+import android.support.v7.widget.Toolbar;
 import android.util.Log;
 import android.view.View;
 import android.view.inputmethod.InputMethodManager;
-import android.widget.Toolbar;
 
+import com.android.contacts.AppCompatContactsActivity;
 import com.android.contacts.ContactSaveService;
-import com.android.contacts.ContactsActivity;
 import com.android.contacts.DynamicShortcuts;
 import com.android.contacts.R;
 import com.android.contacts.detail.PhotoSelectionHandler;
@@ -47,7 +47,7 @@
 /**
  * Contact editor with only the most important fields displayed initially.
  */
-public class ContactEditorActivity extends ContactsActivity implements
+public class ContactEditorActivity extends AppCompatContactsActivity implements
         PhotoSourceDialogFragment.Listener,
         DialogManager.DialogShowingViewActivity {
     private static final String TAG = "ContactEditorActivity";
@@ -60,13 +60,13 @@
     public static final int RESULT_CODE_EDITED = 4;
 
     /**
-     * The contact will be saved to the device local account when this is set for an insert. This
+     * The contact will be saved to this account when this is set for an insert. This
      * is necessary because {@link android.accounts.Account} cannot be created with null values
      * for the name and type and an Account is needed for
      * {@link android.provider.ContactsContract.Intents.Insert#EXTRA_ACCOUNT}
      */
-    public static final String EXTRA_SAVE_TO_DEVICE_FLAG =
-            "com.android.contacts.SAVE_TO_DEVICE_FLAG";
+    public static final String EXTRA_ACCOUNT_WITH_DATA_SET =
+            "com.android.contacts.ACCOUNT_WITH_DATA_SET";
 
     private static final String TAG_EDITOR_FRAGMENT = "editor_fragment";
 
@@ -346,6 +346,7 @@
 
         setContentView(R.layout.contact_editor_activity);
         mToolbar = (Toolbar) findViewById(R.id.toolbar);
+        setSupportActionBar(mToolbar);
         if (Intent.ACTION_EDIT.equals(action)) {
             mActionBarTitleResId = R.string.contact_editor_title_existing_contact;
         } else {
@@ -354,7 +355,6 @@
         mToolbar.setTitle(mActionBarTitleResId);
         // Set activity title for Talkback
         setTitle(mActionBarTitleResId);
-        setActionBar(mToolbar);
 
         if (savedState == null) {
             // Create the editor and photo selection fragments
diff --git a/src/com/android/contacts/editor/CancelEditDialogFragment.java b/src/com/android/contacts/editor/CancelEditDialogFragment.java
index 5a198ff..48cedff 100644
--- a/src/com/android/contacts/editor/CancelEditDialogFragment.java
+++ b/src/com/android/contacts/editor/CancelEditDialogFragment.java
@@ -16,11 +16,11 @@
 
 package com.android.contacts.editor;
 
-import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.DialogFragment;
 import android.content.DialogInterface;
 import android.os.Bundle;
+import android.support.v7.app.AlertDialog;
 
 import com.android.contacts.R;
 
diff --git a/src/com/android/contacts/editor/ContactEditorFragment.java b/src/com/android/contacts/editor/ContactEditorFragment.java
index 27a355f..ede4a37 100644
--- a/src/com/android/contacts/editor/ContactEditorFragment.java
+++ b/src/com/android/contacts/editor/ContactEditorFragment.java
@@ -41,6 +41,7 @@
 import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
 import android.provider.ContactsContract.Intents;
 import android.provider.ContactsContract.RawContacts;
+import android.support.v7.widget.Toolbar;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.LayoutInflater;
@@ -54,7 +55,6 @@
 import android.widget.LinearLayout;
 import android.widget.ListPopupWindow;
 import android.widget.Toast;
-import android.widget.Toolbar;
 
 import com.android.contacts.ContactSaveService;
 import com.android.contacts.Experiments;
@@ -91,7 +91,7 @@
 import com.android.contactsbind.HelpUtils;
 import com.android.contactsbind.ObjectFactory;
 import com.android.contactsbind.experiments.Flags;
-
+import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 
@@ -446,6 +446,10 @@
                 public void onLoadFinished(
                         Loader<List<AccountInfo>> loader, List<AccountInfo> data) {
                     mWritableAccounts = data;
+                    // The user may need to select a new account to save to
+                    if (mAccountWithDataSet == null && mHasNewContact) {
+                        selectAccountAndCreateContact();
+                    }
 
                     final RawContactEditorView view = getContent();
                     if (view == null) {
@@ -567,10 +571,6 @@
 
         validateAction(mAction);
 
-        if (!Intent.ACTION_EDIT.equals(mAction)) {
-            getLoaderManager().initLoader(LOADER_ACCOUNTS, null, mAccountsLoaderListener);
-        }
-
         if (mState.isEmpty()) {
             // The delta list may not have finished loading before orientation change happens.
             // In this case, there will be a saved state but deltas will be missing.  Reload from
@@ -589,12 +589,15 @@
 
         // Handle initial actions only when existing state missing
         if (savedInstanceState == null) {
-            final Account account = mIntentExtras == null ? null :
-                    (Account) mIntentExtras.getParcelable(Intents.Insert.EXTRA_ACCOUNT);
-            final String dataSet = mIntentExtras == null ? null :
-                    mIntentExtras.getString(Intents.Insert.EXTRA_DATA_SET);
-            if (account != null) {
-                mAccountWithDataSet = new AccountWithDataSet(account.name, account.type, dataSet);
+            if (mIntentExtras != null) {
+                final Account account = mIntentExtras == null ? null :
+                        (Account) mIntentExtras.getParcelable(Intents.Insert.EXTRA_ACCOUNT);
+                final String dataSet = mIntentExtras == null ? null :
+                        mIntentExtras.getString(Intents.Insert.EXTRA_DATA_SET);
+                mAccountWithDataSet = account != null
+                        ? new AccountWithDataSet(account.name, account.type, dataSet)
+                        : mIntentExtras.<AccountWithDataSet>getParcelable(
+                                ContactEditorActivity.EXTRA_ACCOUNT_WITH_DATA_SET);
             }
 
             if (Intent.ACTION_EDIT.equals(mAction)) {
@@ -603,16 +606,13 @@
                 mHasNewContact = true;
                 if (mAccountWithDataSet != null) {
                     createContact(mAccountWithDataSet);
-                } else if (mIntentExtras != null && mIntentExtras.getBoolean(
-                        ContactEditorActivity.EXTRA_SAVE_TO_DEVICE_FLAG, false)) {
-                    createContact(null);
-                } else {
-                    // No Account specified. Let the user choose
-                    // Load Accounts async so that we can present them
-                    selectAccountAndCreateContact();
-                }
+                } // else wait for accounts to be loaded
             }
         }
+
+        if (mHasNewContact) {
+            getLoaderManager().initLoader(LOADER_ACCOUNTS, null, mAccountsLoaderListener);
+        }
     }
 
     /**
@@ -705,25 +705,16 @@
             }
             case REQUEST_CODE_ACCOUNTS_CHANGED: {
                 // Bail if the account selector was not successful.
-                if (resultCode != Activity.RESULT_OK) {
+                if (resultCode != Activity.RESULT_OK || data == null ||
+                        !data.hasExtra(Intents.Insert.EXTRA_ACCOUNT)) {
                     if (mListener != null) {
                         mListener.onReverted();
                     }
                     return;
                 }
-                // If there's an account specified, use it.
-                if (data != null) {
-                    AccountWithDataSet account = data.getParcelableExtra(
-                            Intents.Insert.EXTRA_ACCOUNT);
-                    if (account != null) {
-                        createContact(account);
-                        return;
-                    }
-                }
-                // If there isn't an account specified, then this is likely a phone-local
-                // contact, so we should continue setting up the editor by automatically selecting
-                // the most appropriate account.
-                createContact();
+                AccountWithDataSet account = data.getParcelableExtra(
+                        Intents.Insert.EXTRA_ACCOUNT);
+                createContact(account);
                 break;
             }
         }
@@ -1024,6 +1015,7 @@
     //
 
     private void selectAccountAndCreateContact() {
+        Preconditions.checkNotNull(mWritableAccounts, "Accounts must be loaded first");
         // If this is a local profile, then skip the logic about showing the accounts changed
         // activity and create a phone-local contact.
         if (mNewLocalProfile) {
@@ -1031,9 +1023,10 @@
             return;
         }
 
+        final List<AccountWithDataSet> accounts = AccountInfo.extractAccounts(mWritableAccounts);
         // If there is no default account or the accounts have changed such that we need to
         // prompt the user again, then launch the account prompt.
-        if (mEditorUtils.shouldShowAccountChangedNotification()) {
+        if (mEditorUtils.shouldShowAccountChangedNotification(accounts)) {
             Intent intent = new Intent(mContext, ContactEditorAccountsChangedActivity.class);
             // Prevent a second instance from being started on rotates
             intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
@@ -1042,33 +1035,15 @@
         } else {
             // Make sure the default account is automatically set if there is only one non-device
             // account.
-            mEditorUtils.maybeUpdateDefaultAccount();
+            mEditorUtils.maybeUpdateDefaultAccount(accounts);
             // Otherwise, there should be a default account. Then either create a local contact
             // (if default account is null) or create a contact with the specified account.
-            AccountWithDataSet defaultAccount = mEditorUtils.getOnlyOrDefaultAccount();
+            AccountWithDataSet defaultAccount = mEditorUtils.getOnlyOrDefaultAccount(accounts);
             createContact(defaultAccount);
         }
     }
 
     /**
-     * Create a contact by automatically selecting the first account. If there's no available
-     * account, a device-local contact should be created.
-     */
-    private void createContact() {
-        final List<AccountWithDataSet> accounts =
-                AccountTypeManager.getInstance(mContext).getAccounts(true);
-        // No Accounts available. Create a phone-local contact.
-        if (accounts.isEmpty()) {
-            createContact(null);
-            return;
-        }
-
-        // We have an account switcher in "create-account" screen, so don't need to ask a user to
-        // select an account here.
-        createContact(accounts.get(0));
-    }
-
-    /**
      * Shows account creation screen associated with a given account.
      *
      * @param account may be null to signal a device-local contact should be created.
diff --git a/src/com/android/contacts/editor/ContactEditorUtils.java b/src/com/android/contacts/editor/ContactEditorUtils.java
index 4bb075c..517c2c7 100644
--- a/src/com/android/contacts/editor/ContactEditorUtils.java
+++ b/src/com/android/contacts/editor/ContactEditorUtils.java
@@ -27,17 +27,10 @@
 import android.provider.ContactsContract;
 import android.text.TextUtils;
 
-import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.model.account.AccountType;
 import com.android.contacts.model.account.AccountWithDataSet;
 import com.android.contacts.preference.ContactsPreferences;
 
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.Sets;
-
-import java.util.ArrayList;
 import java.util.List;
-import java.util.Set;
 
 /**
  * Utility methods for the "account changed" notification in the new contact creation flow.
@@ -46,16 +39,9 @@
     private static final String TAG = "ContactEditorUtils";
 
     private final ContactsPreferences mContactsPrefs;
-    private final AccountTypeManager mAccountTypes;
 
     private ContactEditorUtils(Context context) {
-        this(context, AccountTypeManager.getInstance(context));
-    }
-
-    @VisibleForTesting
-    ContactEditorUtils(Context context, AccountTypeManager accountTypes) {
         mContactsPrefs = new ContactsPreferences(context);
-        mAccountTypes = accountTypes;
     }
 
     public static ContactEditorUtils create(Context context) {
@@ -94,10 +80,6 @@
         mContactsPrefs.clearDefaultAccount();
     }
 
-    private List<AccountWithDataSet> getWritableAccounts() {
-        return mAccountTypes.getAccounts(true);
-    }
-
     /**
      * Saves the default account, which can later be obtained with {@link #getOnlyOrDefaultAccount}.
      *
@@ -121,8 +103,8 @@
      *
      * Also note that the returned account may have been removed already.
      */
-    public AccountWithDataSet getOnlyOrDefaultAccount() {
-        final List<AccountWithDataSet> currentWritableAccounts = getWritableAccounts();
+    public AccountWithDataSet getOnlyOrDefaultAccount(
+            List<AccountWithDataSet> currentWritableAccounts) {
         if (currentWritableAccounts.size() == 1) {
             return currentWritableAccounts.get(0);
         }
@@ -130,15 +112,14 @@
         return mContactsPrefs.getDefaultAccount();
     }
 
-    public boolean shouldShowAccountChangedNotification() {
-        return mContactsPrefs.shouldShowAccountChangedNotification(getWritableAccounts());
+    public boolean shouldShowAccountChangedNotification(List<AccountWithDataSet> writableAccounts) {
+        return mContactsPrefs.shouldShowAccountChangedNotification(writableAccounts);
     }
 
     /**
      * Sets the only non-device account to be default if it is not already.
      */
-    public void maybeUpdateDefaultAccount() {
-        final List<AccountWithDataSet> currentWritableAccounts = getWritableAccounts();
+    public void maybeUpdateDefaultAccount(List<AccountWithDataSet> currentWritableAccounts) {
         if (currentWritableAccounts.size() == 1) {
             final AccountWithDataSet onlyAccount = currentWritableAccounts.get(0);
             if (!onlyAccount.isNullAccount()
diff --git a/src/com/android/contacts/editor/PhotoSourceDialogFragment.java b/src/com/android/contacts/editor/PhotoSourceDialogFragment.java
index 2556b25..31d41b1 100644
--- a/src/com/android/contacts/editor/PhotoSourceDialogFragment.java
+++ b/src/com/android/contacts/editor/PhotoSourceDialogFragment.java
@@ -17,12 +17,12 @@
 package com.android.contacts.editor;
 
 import android.app.Activity;
-import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.DialogFragment;
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnClickListener;
 import android.os.Bundle;
+import android.support.v7.app.AlertDialog;
 import android.view.View;
 import android.widget.TextView;
 
diff --git a/src/com/android/contacts/editor/RawContactEditorView.java b/src/com/android/contacts/editor/RawContactEditorView.java
index 450d8c0..6d1f794 100644
--- a/src/com/android/contacts/editor/RawContactEditorView.java
+++ b/src/com/android/contacts/editor/RawContactEditorView.java
@@ -451,8 +451,9 @@
         mHasNewContact = hasNewContact;
         mIsUserProfile = isUserProfile;
         mPrimaryAccount = primaryAccount;
-        if (mPrimaryAccount == null) {
-            mPrimaryAccount = ContactEditorUtils.create(getContext()).getOnlyOrDefaultAccount();
+        if (mPrimaryAccount == null && mAccounts != null) {
+            mPrimaryAccount = ContactEditorUtils.create(getContext())
+                    .getOnlyOrDefaultAccount(AccountInfo.extractAccounts(mAccounts));
         }
         vlog("state: primary " + mPrimaryAccount);
 
diff --git a/src/com/android/contacts/editor/SuggestionEditConfirmationDialogFragment.java b/src/com/android/contacts/editor/SuggestionEditConfirmationDialogFragment.java
index f94d5dc..487a5ee 100644
--- a/src/com/android/contacts/editor/SuggestionEditConfirmationDialogFragment.java
+++ b/src/com/android/contacts/editor/SuggestionEditConfirmationDialogFragment.java
@@ -16,12 +16,12 @@
 
 package com.android.contacts.editor;
 
-import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.DialogFragment;
 import android.content.DialogInterface;
 import android.net.Uri;
 import android.os.Bundle;
+import android.support.v7.app.AlertDialog;
 
 import com.android.contacts.R;
 
diff --git a/src/com/android/contacts/util/AccountFilterUtil.java b/src/com/android/contacts/util/AccountFilterUtil.java
index 218604c..a7824f4 100644
--- a/src/com/android/contacts/util/AccountFilterUtil.java
+++ b/src/com/android/contacts/util/AccountFilterUtil.java
@@ -197,9 +197,8 @@
             intent.putExtra(Intents.Insert.EXTRA_ACCOUNT, account);
             intent.putExtra(Intents.Insert.EXTRA_DATA_SET, filter.dataSet);
         } else if (isDeviceContactsFilter(filter)) {
-            // It's OK to add this even though it's an implicit intent. If a different app
-            // receives the intent it should just ignore the flag.
-            intent.putExtra(ContactEditorActivity.EXTRA_SAVE_TO_DEVICE_FLAG, true);
+            intent.putExtra(ContactEditorActivity.EXTRA_ACCOUNT_WITH_DATA_SET,
+                    filter.toAccountWithDataSet());
         }
 
         try {
diff --git a/tests/src/com/android/contacts/editor/ContactEditorUtilsTest.java b/tests/src/com/android/contacts/editor/ContactEditorUtilsTest.java
index 9756a0c..a7d5c20 100644
--- a/tests/src/com/android/contacts/editor/ContactEditorUtilsTest.java
+++ b/tests/src/com/android/contacts/editor/ContactEditorUtilsTest.java
@@ -16,97 +16,89 @@
 
 package com.android.contacts.editor;
 
-import android.test.AndroidTestCase;
-import android.test.MoreAsserts;
-import android.test.suitebuilder.annotation.SmallTest;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
 
 import com.android.contacts.model.account.AccountType;
 import com.android.contacts.model.account.AccountWithDataSet;
-import com.android.contacts.test.mocks.MockAccountTypeManager;
 
-import com.google.common.collect.Sets;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
-import java.util.Collection;
-import java.util.Set;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
 
 /**
  * Test case for {@link ContactEditorUtils}.
  *
  * adb shell am instrument -w -e class com.android.contacts.editor.ContactEditorUtilsTest \
        com.android.contacts.tests/android.test.InstrumentationTestRunner
+
+ * <p>It may make sense to just delete or move these tests since the code under test just forwards
+ * calls to {@link com.android.contacts.preference.ContactsPreferences} and that logic is already
+ * covered by {@link com.android.contacts.preference.ContactsPreferencesTest}
+ * </p>
  */
 @SmallTest
-public class ContactEditorUtilsTest extends AndroidTestCase {
-    private MockAccountTypeManager mAccountTypes;
+@RunWith(AndroidJUnit4.class)
+public class ContactEditorUtilsTest {
     private ContactEditorUtils mTarget;
 
-    private static final MockAccountType TYPE1 = new MockAccountType("type1", null, true);
-    private static final MockAccountType TYPE2 = new MockAccountType("type2", null, true);
-    private static final MockAccountType TYPE2EX = new MockAccountType("type2", "ext", true);
+    private static final String TYPE1 = "type1";
+    private static final String TYPE2 = "type2";
+    private static final String TYPE2_EXT = "ext";
 
-    // Only type 3 is "readonly".
-    private static final MockAccountType TYPE3 = new MockAccountType("type3", null, false);
+    private static final AccountWithDataSet ACCOUNT_1_A = new AccountWithDataSet("a", TYPE1, null);
+    private static final AccountWithDataSet ACCOUNT_1_B = new AccountWithDataSet("b", TYPE1, null);
 
-    private static final AccountWithDataSet ACCOUNT_1_A = new AccountWithDataSet(
-            "a", TYPE1.accountType, TYPE1.dataSet);
-    private static final AccountWithDataSet ACCOUNT_1_B = new AccountWithDataSet(
-            "b", TYPE1.accountType, TYPE1.dataSet);
-
-    private static final AccountWithDataSet ACCOUNT_2_A = new AccountWithDataSet(
-            "a", TYPE2.accountType, TYPE2.dataSet);
+    private static final AccountWithDataSet ACCOUNT_2_A = new AccountWithDataSet("a", TYPE2, null);
     private static final AccountWithDataSet ACCOUNT_2EX_A = new AccountWithDataSet(
-            "a", TYPE2EX.accountType, TYPE2EX.dataSet);
+            "a", TYPE2, TYPE2_EXT);
 
-    private static final AccountWithDataSet ACCOUNT_3_C = new AccountWithDataSet(
-            "c", TYPE3.accountType, TYPE3.dataSet);
-
-    @Override
-    protected void setUp() throws Exception {
-        // Initialize with 0 types, 0 accounts.
-        mAccountTypes = new MockAccountTypeManager(new AccountType[] {},
-                new AccountWithDataSet[] {});
-        mTarget = new ContactEditorUtils(getContext(), mAccountTypes);
+    @Before
+    public void setUp() throws Exception {
+        mTarget = ContactEditorUtils.create(InstrumentationRegistry.getTargetContext());
 
         // Clear the preferences.
         mTarget.cleanupForTest();
     }
 
-    private void setAccountTypes(AccountType... types) {
-        mAccountTypes.mTypes = types;
-    }
-
-    private void setAccounts(AccountWithDataSet... accounts) {
-        mAccountTypes.mAccounts = accounts;
-    }
-
     /**
      * Test for
      * - {@link ContactEditorUtils#saveDefaultAccount}
      * - {@link ContactEditorUtils#getOnlyOrDefaultAccount}
      */
+    @Test
     public void testSaveDefaultAccount() {
-        // Use these account types here.
-        setAccountTypes(TYPE1, TYPE2);
-
         mTarget.saveDefaultAccount(null);
-        assertNull(mTarget.getOnlyOrDefaultAccount());
+        assertNull(mTarget.getOnlyOrDefaultAccount(Collections.<AccountWithDataSet>emptyList()));
 
         mTarget.saveDefaultAccount(ACCOUNT_1_A);
-        assertEquals(ACCOUNT_1_A, mTarget.getOnlyOrDefaultAccount());
+        assertEquals(ACCOUNT_1_A, mTarget.getOnlyOrDefaultAccount(Collections.
+                <AccountWithDataSet>emptyList()));
     }
 
     /**
-     * Tests for {@link ContactEditorUtils#shouldShowAccountChangedNotification()}, starting with
-     * 0 accounts.
+     * Tests for
+     * {@link ContactEditorUtils#shouldShowAccountChangedNotification(List<AccountWithDataSet>)},
+     * starting with 0 accounts.
      */
+    @Test
     public void testShouldShowAccountChangedNotification_0Accounts() {
-        setAccountTypes(TYPE1);
-
-        // First launch -- always true.
-        assertTrue(mTarget.shouldShowAccountChangedNotification());
+        List<AccountWithDataSet> currentAccounts = new ArrayList<>();
+        assertTrue(mTarget.shouldShowAccountChangedNotification(currentAccounts));
 
         // We show the notification here, and user clicked "add account"
-        setAccounts(ACCOUNT_1_A);
+        currentAccounts.add(ACCOUNT_1_A);
 
         // Now we open the contact editor with the new account.
 
@@ -114,87 +106,85 @@
         mTarget.saveDefaultAccount(ACCOUNT_1_A);
 
         // Next time the user creates a contact, we don't show the notification.
-        assertFalse(mTarget.shouldShowAccountChangedNotification());
+        assertFalse(mTarget.shouldShowAccountChangedNotification(currentAccounts));
 
         // User added a new writable account, ACCOUNT_1_B.
-        setAccounts(ACCOUNT_1_A, ACCOUNT_1_B);
+        currentAccounts.add(ACCOUNT_1_B);
 
         // Since default account is still ACCOUNT_1_A, we don't show the notification.
-        assertFalse(mTarget.shouldShowAccountChangedNotification());
+        assertFalse(mTarget.shouldShowAccountChangedNotification(currentAccounts));
 
         // User saved a new contact.  We update the account list and the default account.
         mTarget.saveDefaultAccount(ACCOUNT_1_B);
 
         // User created another contact.  Now we don't show the notification.
-        assertFalse(mTarget.shouldShowAccountChangedNotification());
+        assertFalse(mTarget.shouldShowAccountChangedNotification(currentAccounts));
 
         // User installed a new contact sync adapter...
 
-        // Added a new account type: TYPE2, and the TYPE2EX extension.
-        setAccountTypes(TYPE1, TYPE2, TYPE2EX);
         // Add new accounts: ACCOUNT_2_A, ACCOUNT_2EX_A.
-        setAccounts(ACCOUNT_1_A, ACCOUNT_1_B, ACCOUNT_2_A, ACCOUNT_2EX_A);
+        currentAccounts.add(ACCOUNT_2_A);
+        currentAccounts.add(ACCOUNT_2EX_A);
 
         // New added account but default account is still not changed, so no notification.
-        assertFalse(mTarget.shouldShowAccountChangedNotification());
+        assertFalse(mTarget.shouldShowAccountChangedNotification(currentAccounts));
 
         // User saves a new contact, with a different default account.
         mTarget.saveDefaultAccount(ACCOUNT_2_A);
 
         // Next time user creates a contact, no notification.
-        assertFalse(mTarget.shouldShowAccountChangedNotification());
+        assertFalse(mTarget.shouldShowAccountChangedNotification(currentAccounts));
 
         // Remove ACCOUNT_2EX_A.
-        setAccountTypes(TYPE1, TYPE2, TYPE2EX);
-        setAccounts(ACCOUNT_1_A, ACCOUNT_1_B, ACCOUNT_2_A);
+        currentAccounts.remove(ACCOUNT_2EX_A);
 
         // ACCOUNT_2EX_A was not default, so no notification either.
-        assertFalse(mTarget.shouldShowAccountChangedNotification());
+        assertFalse(mTarget.shouldShowAccountChangedNotification(currentAccounts));
 
-        // Remove ACCOUNT_1_B, which is default.
-        setAccountTypes(TYPE1, TYPE2, TYPE2EX);
-        setAccounts(ACCOUNT_1_A, ACCOUNT_1_B);
+        // Remove ACCOUNT_2_A, which is default.
+        currentAccounts.remove(ACCOUNT_2_A);
 
         // Now we show the notification.
-        assertTrue(mTarget.shouldShowAccountChangedNotification());
+        assertTrue(mTarget.shouldShowAccountChangedNotification(currentAccounts));
 
         // Do not save the default account, and add a new account now.
-        setAccountTypes(TYPE1, TYPE2, TYPE2EX);
-        setAccounts(ACCOUNT_1_A, ACCOUNT_1_B, ACCOUNT_2EX_A);
+        currentAccounts.add(ACCOUNT_2EX_A);
 
         // No default account, so show notification.
-        assertTrue(mTarget.shouldShowAccountChangedNotification());
+        assertTrue(mTarget.shouldShowAccountChangedNotification(currentAccounts));
     }
 
     /**
-     * Tests for {@link ContactEditorUtils#shouldShowAccountChangedNotification()}, starting with
-     * 1 accounts.
+     * Tests for
+     * {@link ContactEditorUtils#shouldShowAccountChangedNotification(List<AccountWithDataSet>)},
+     * starting with 1 accounts.
      */
+    @Test
     public void testShouldShowAccountChangedNotification_1Account() {
-        setAccountTypes(TYPE1, TYPE2);
-        setAccounts(ACCOUNT_1_A);
-
         // Always returns false when 1 writable account.
-        assertFalse(mTarget.shouldShowAccountChangedNotification());
+        assertFalse(mTarget.shouldShowAccountChangedNotification(
+                Collections.singletonList(ACCOUNT_1_A)));
 
         // User saves a new contact.
         mTarget.saveDefaultAccount(ACCOUNT_1_A);
 
         // Next time, no notification.
-        assertFalse(mTarget.shouldShowAccountChangedNotification());
+        assertFalse(mTarget.shouldShowAccountChangedNotification(
+                Collections.singletonList(ACCOUNT_1_A)));
 
         // The rest is the same...
     }
 
     /**
-     * Tests for {@link ContactEditorUtils#shouldShowAccountChangedNotification()}, starting with
-     * 0 accounts, and the user selected "local only".
+     * Tests for
+     * {@link ContactEditorUtils#shouldShowAccountChangedNotification(List<AccountWithDataSet>)},
+     * starting with 0 accounts, and the user selected "local only".
      */
+    @Test
     public void testShouldShowAccountChangedNotification_0Account_localOnly() {
-        setAccountTypes(TYPE1);
-
         // First launch -- always true.
-        assertTrue(mTarget.shouldShowAccountChangedNotification());
+        assertTrue(mTarget.shouldShowAccountChangedNotification(Collections.
+                <AccountWithDataSet>emptyList()));
 
         // We show the notification here, and user clicked "keep local" and saved an contact.
         mTarget.saveDefaultAccount(AccountWithDataSet.getNullAccount());
@@ -202,31 +192,41 @@
         // Now there are no accounts, and default account is null.
 
         // The user created another contact, but this we shouldn't show the notification.
-        assertFalse(mTarget.shouldShowAccountChangedNotification());
+        assertFalse(mTarget.shouldShowAccountChangedNotification(Collections.
+                <AccountWithDataSet>emptyList()));
     }
 
+    @Test
     public void testShouldShowAccountChangedNotification_sanity_check() {
         // Prepare 1 account and save it as the default.
-        setAccountTypes(TYPE1);
-        setAccounts(ACCOUNT_1_A);
-
         mTarget.saveDefaultAccount(ACCOUNT_1_A);
 
         // Right after a save, the dialog shouldn't show up.
-        assertFalse(mTarget.shouldShowAccountChangedNotification());
+        assertFalse(mTarget.shouldShowAccountChangedNotification(
+                Collections.singletonList(ACCOUNT_1_A)));
 
         // Remove the default account to emulate broken preferences.
         mTarget.removeDefaultAccountForTest();
 
         // The dialog shouldn't show up.
         // The logic is, if there's a writable account, we'll pick it as default
-        assertFalse(mTarget.shouldShowAccountChangedNotification());
+        assertFalse(mTarget.shouldShowAccountChangedNotification(
+                Collections.singletonList(ACCOUNT_1_A)));
     }
 
-    private static <T> Set<T> toSet(Collection<T> collection) {
-        Set<T> ret = Sets.newHashSet();
-        ret.addAll(collection);
-        return ret;
+    @Test
+    public void testShouldShowAccountChangedNotification_nullAccount() {
+        final List<AccountWithDataSet> currentAccounts = new ArrayList<>();
+        final AccountWithDataSet nullAccount = AccountWithDataSet.getNullAccount();
+        currentAccounts.add(nullAccount);
+
+        assertTrue(mTarget.shouldShowAccountChangedNotification(currentAccounts));
+
+        // User chooses to keep the "device" account as the default
+        mTarget.saveDefaultAccount(nullAccount);
+
+        // Right after a save, the dialog shouldn't show up.
+        assertFalse(mTarget.shouldShowAccountChangedNotification(currentAccounts));
     }
 
     private static class MockAccountType extends AccountType {