13f990ba4e35a99078d831c041290e574a320caa5Walter Jang/*
23f990ba4e35a99078d831c041290e574a320caa5Walter Jang * Copyright (C) 2015 The Android Open Source Project
33f990ba4e35a99078d831c041290e574a320caa5Walter Jang *
43f990ba4e35a99078d831c041290e574a320caa5Walter Jang * Licensed under the Apache License, Version 2.0 (the "License");
53f990ba4e35a99078d831c041290e574a320caa5Walter Jang * you may not use this file except in compliance with the License.
63f990ba4e35a99078d831c041290e574a320caa5Walter Jang * You may obtain a copy of the License at
73f990ba4e35a99078d831c041290e574a320caa5Walter Jang *
83f990ba4e35a99078d831c041290e574a320caa5Walter Jang *      http://www.apache.org/licenses/LICENSE-2.0
93f990ba4e35a99078d831c041290e574a320caa5Walter Jang *
103f990ba4e35a99078d831c041290e574a320caa5Walter Jang * Unless required by applicable law or agreed to in writing, software
113f990ba4e35a99078d831c041290e574a320caa5Walter Jang * distributed under the License is distributed on an "AS IS" BASIS,
123f990ba4e35a99078d831c041290e574a320caa5Walter Jang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133f990ba4e35a99078d831c041290e574a320caa5Walter Jang * See the License for the specific language governing permissions and
143f990ba4e35a99078d831c041290e574a320caa5Walter Jang * limitations under the License
153f990ba4e35a99078d831c041290e574a320caa5Walter Jang */
163f990ba4e35a99078d831c041290e574a320caa5Walter Jang
173f990ba4e35a99078d831c041290e574a320caa5Walter Jangpackage com.android.contacts.editor;
183f990ba4e35a99078d831c041290e574a320caa5Walter Jang
197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.accounts.Account;
2049ed2033f83005f92c30068ae33c3138d75e1825Walter Jangimport android.app.Activity;
217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.app.Fragment;
227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.app.LoaderManager;
23e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskeyimport android.content.ContentResolver;
247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.content.ContentUris;
257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.content.ContentValues;
267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.content.Context;
277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.content.CursorLoader;
283f990ba4e35a99078d831c041290e574a320caa5Walter Jangimport android.content.Intent;
297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.content.Loader;
307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.database.Cursor;
313efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jangimport android.graphics.Bitmap;
323efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jangimport android.net.Uri;
333f990ba4e35a99078d831c041290e574a320caa5Walter Jangimport android.os.Bundle;
347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.os.SystemClock;
357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.provider.ContactsContract;
367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.provider.ContactsContract.CommonDataKinds.Email;
377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.provider.ContactsContract.CommonDataKinds.Event;
387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.provider.ContactsContract.CommonDataKinds.Organization;
397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.provider.ContactsContract.CommonDataKinds.Phone;
407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.provider.ContactsContract.CommonDataKinds.StructuredName;
417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.provider.ContactsContract.Intents;
437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.provider.ContactsContract.RawContacts;
44c40f3e945c43ff1ff90abb7fb2daf56aba315e10Gary Maiimport android.support.v7.widget.Toolbar;
45e394595987e288807b8c02c78d7d33e854f152b1Walter Jangimport android.text.TextUtils;
46cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jangimport android.util.Log;
473f990ba4e35a99078d831c041290e574a320caa5Walter Jangimport android.view.LayoutInflater;
487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.view.Menu;
497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.view.MenuInflater;
50c90cc15b804fb00339a3b98e5c951549f9b03599Walter Jangimport android.view.MenuItem;
513f990ba4e35a99078d831c041290e574a320caa5Walter Jangimport android.view.View;
523f990ba4e35a99078d831c041290e574a320caa5Walter Jangimport android.view.ViewGroup;
537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.widget.AdapterView;
547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.widget.BaseAdapter;
553f990ba4e35a99078d831c041290e574a320caa5Walter Jangimport android.widget.LinearLayout;
567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport android.widget.ListPopupWindow;
5779658e14360a4ec75530a9dcae338f48c9d5f043Walter Jangimport android.widget.Toast;
583f990ba4e35a99078d831c041290e574a320caa5Walter Jang
597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport com.android.contacts.ContactSaveService;
607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport com.android.contacts.GroupMetaDataLoader;
617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport com.android.contacts.R;
62a4adae163d83db9226b831f8c9705914e68b5cd1Gary Maiimport com.android.contacts.activities.ContactEditorAccountsChangedActivity;
63363af60ea23e5a3b945005712a16564ab69db18bGary Maiimport com.android.contacts.activities.ContactEditorActivity;
64363af60ea23e5a3b945005712a16564ab69db18bGary Maiimport com.android.contacts.activities.ContactEditorActivity.ContactEditor;
657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport com.android.contacts.activities.ContactSelectionActivity;
661e899dc127a212bfd2198fe7adba5c33eb4cd751Gary Maiimport com.android.contacts.activities.RequestPermissionsActivity;
670a49afa2ad697307cc04ef4cb86570574fa720f2Gary Maiimport com.android.contacts.editor.AggregationSuggestionEngine.Suggestion;
680a49afa2ad697307cc04ef4cb86570574fa720f2Gary Maiimport com.android.contacts.group.GroupUtil;
690a49afa2ad697307cc04ef4cb86570574fa720f2Gary Maiimport com.android.contacts.list.UiIntentActions;
7069c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.logging.ScreenEvent.ScreenType;
7169c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.AccountTypeManager;
7269c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.Contact;
7369c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.ContactLoader;
7469c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.RawContact;
7569c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.RawContactDelta;
7669c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.RawContactDeltaList;
7769c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.RawContactModifier;
7869c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.ValuesDelta;
794bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerottimport com.android.contacts.model.account.AccountInfo;
8069c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.account.AccountType;
8169c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.account.AccountWithDataSet;
824bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerottimport com.android.contacts.model.account.AccountsLoader;
8369c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.preference.ContactsPreferences;
84e48746654178e9448819f86b3129fd32f539b3c9Gary Maiimport com.android.contacts.quickcontact.InvisibleContactUtil;
857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport com.android.contacts.quickcontact.QuickContactActivity;
860a49afa2ad697307cc04ef4cb86570574fa720f2Gary Maiimport com.android.contacts.util.ContactDisplayUtils;
877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport com.android.contacts.util.ContactPhotoUtils;
880a49afa2ad697307cc04ef4cb86570574fa720f2Gary Maiimport com.android.contacts.util.ImplicitIntentsUtil;
890a49afa2ad697307cc04ef4cb86570574fa720f2Gary Maiimport com.android.contacts.util.MaterialColorMapUtils;
907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport com.android.contacts.util.UiClosables;
91a4adae163d83db9226b831f8c9705914e68b5cd1Gary Maiimport com.android.contactsbind.HelpUtils;
928d26c0a7214cf6520a4def851afa138a133a68a2Walter Jang
93807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerottimport com.google.common.base.Preconditions;
947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport com.google.common.collect.ImmutableList;
957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport com.google.common.collect.Lists;
967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
973efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jangimport java.io.FileNotFoundException;
9831a74ad969b650eb733e536569254ed3978c4f54Walter Jangimport java.util.ArrayList;
994bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerottimport java.util.Collections;
1007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport java.util.HashSet;
1017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport java.util.Iterator;
1027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport java.util.List;
1037b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport java.util.Set;
1043efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
1053f990ba4e35a99078d831c041290e574a320caa5Walter Jang/**
1063f990ba4e35a99078d831c041290e574a320caa5Walter Jang * Contact editor with only the most important fields displayed initially.
1073f990ba4e35a99078d831c041290e574a320caa5Walter Jang */
108363af60ea23e5a3b945005712a16564ab69db18bGary Maipublic class ContactEditorFragment extends Fragment implements
1097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        ContactEditor, SplitContactConfirmationDialogFragment.Listener,
1107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        JoinContactConfirmationDialogFragment.Listener,
1117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        AggregationSuggestionEngine.Listener, AggregationSuggestionView.Listener,
1127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        CancelEditDialogFragment.Listener,
1138c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott        RawContactEditorView.Listener, PhotoEditorView.Listener,
1148c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott        AccountsLoader.AccountsListener {
1153f990ba4e35a99078d831c041290e574a320caa5Walter Jang
1167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    static final String TAG = "ContactEditor";
1177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final int LOADER_CONTACT = 1;
1197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final int LOADER_GROUPS = 2;
1204bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott    private static final int LOADER_ACCOUNTS = 3;
1217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1223efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    private static final String KEY_PHOTO_RAW_CONTACT_ID = "photo_raw_contact_id";
12328a27279554af7b1e5ff664d3da97954c462a797Walter Jang    private static final String KEY_UPDATED_PHOTOS = "updated_photos";
1243efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
1257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final List<String> VALID_INTENT_ACTIONS = new ArrayList<String>() {{
1267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        add(Intent.ACTION_EDIT);
1277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        add(Intent.ACTION_INSERT);
128363af60ea23e5a3b945005712a16564ab69db18bGary Mai        add(ContactEditorActivity.ACTION_SAVE_COMPLETED);
1297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }};
1307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_ACTION = "action";
1327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_URI = "uri";
1337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_AUTO_ADD_TO_DEFAULT_GROUP = "autoAddToDefaultGroup";
1347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_DISABLE_DELETE_MENU_OPTION = "disableDeleteMenuOption";
1357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_NEW_LOCAL_PROFILE = "newLocalProfile";
1367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_MATERIAL_PALETTE = "materialPalette";
137c135a5d502130aee06ffcc11170513053396e9b0Gary Mai    private static final String KEY_ACCOUNT = "saveToAccount";
1387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_VIEW_ID_GENERATOR = "viewidgenerator";
1397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_RAW_CONTACTS = "rawContacts";
1417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_EDIT_STATE = "state";
1437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_STATUS = "status";
1447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_HAS_NEW_CONTACT = "hasNewContact";
1467b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_NEW_CONTACT_READY = "newContactDataReady";
1477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_IS_EDIT = "isEdit";
1497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_EXISTING_CONTACT_READY = "existingContactDataReady";
1507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_IS_USER_PROFILE = "isUserProfile";
1527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_ENABLED = "enabled";
1547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Aggregation PopupWindow
1567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_AGGREGATION_SUGGESTIONS_RAW_CONTACT_ID =
1577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            "aggregationSuggestionsRawContactId";
1587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Join Activity
1607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_CONTACT_ID_FOR_JOIN = "contactidforjoin";
1617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
162698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai    private static final String KEY_READ_ONLY_DISPLAY_NAME_ID = "readOnlyDisplayNameId";
163698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai    private static final String KEY_COPY_READ_ONLY_DISPLAY_NAME = "copyReadOnlyDisplayName";
1647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected static final int REQUEST_CODE_JOIN = 0;
1667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected static final int REQUEST_CODE_ACCOUNTS_CHANGED = 1;
1677b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1687b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
1697b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * An intent extra that forces the editor to add the edited contact
1707b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * to the default group (e.g. "My Contacts").
1717b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
1727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public static final String INTENT_EXTRA_ADD_TO_DEFAULT_DIRECTORY = "addToDefaultDirectory";
1737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public static final String INTENT_EXTRA_NEW_LOCAL_PROFILE = "newLocalProfile";
1757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public static final String INTENT_EXTRA_DISABLE_DELETE_MENU_OPTION =
1777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            "disableDeleteMenuOption";
1787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
1807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Intent key to pass the photo palette primary color calculated by
181363af60ea23e5a3b945005712a16564ab69db18bGary Mai     * {@link com.android.contacts.quickcontact.QuickContactActivity} to the editor.
1827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
1837b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public static final String INTENT_EXTRA_MATERIAL_PALETTE_PRIMARY_COLOR =
1847b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            "material_palette_primary_color";
1857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1867b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
1877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Intent key to pass the photo palette secondary color calculated by
188363af60ea23e5a3b945005712a16564ab69db18bGary Mai     * {@link com.android.contacts.quickcontact.QuickContactActivity} to the editor.
1897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
1907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public static final String INTENT_EXTRA_MATERIAL_PALETTE_SECONDARY_COLOR =
1917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            "material_palette_secondary_color";
1927b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
1947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Intent key to pass the ID of the photo to display on the editor.
1957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
196da20b47c2b85390a2c3772379e71203c5aab513cGary Mai    // TODO: This can be cleaned up if we decide to not pass the photo id through
197da20b47c2b85390a2c3772379e71203c5aab513cGary Mai    // QuickContactActivity.
1987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public static final String INTENT_EXTRA_PHOTO_ID = "photo_id";
1997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
201a6c80b378e03ebdf6b654dbdb12f2c665fe98a80Gary Mai     * Intent key to pass the ID of the raw contact id that should be displayed in the full editor
202a6c80b378e03ebdf6b654dbdb12f2c665fe98a80Gary Mai     * by itself.
203a6c80b378e03ebdf6b654dbdb12f2c665fe98a80Gary Mai     */
204a6c80b378e03ebdf6b654dbdb12f2c665fe98a80Gary Mai    public static final String INTENT_EXTRA_RAW_CONTACT_ID_TO_DISPLAY_ALONE =
205a6c80b378e03ebdf6b654dbdb12f2c665fe98a80Gary Mai            "raw_contact_id_to_display_alone";
206a6c80b378e03ebdf6b654dbdb12f2c665fe98a80Gary Mai
207a6c80b378e03ebdf6b654dbdb12f2c665fe98a80Gary Mai    /**
2087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Intent extra to specify a {@link ContactEditor.SaveMode}.
2097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
2107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public static final String SAVE_MODE_EXTRA_KEY = "saveMode";
2117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
2137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Intent extra key for the contact ID to join the current contact to after saving.
2147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
2157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public static final String JOIN_CONTACT_ID_EXTRA_KEY = "joinContactId";
2167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
2187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Callbacks for Activities that host contact editors Fragments.
2197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
2207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public interface Listener {
2217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        /**
2237b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         * Contact was not found, so somehow close this fragment. This is raised after a contact
2247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         * is removed via Menu/Delete
2257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         */
2267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        void onContactNotFound();
2277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        /**
2297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         * Contact was split, so we can close now.
2307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         *
2317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         * @param newLookupUri The lookup uri of the new contact that should be shown to the user.
2327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         *                     The editor tries best to chose the most natural contact here.
2337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         */
2347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        void onContactSplit(Uri newLookupUri);
2357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        /**
2377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         * User has tapped Revert, close the fragment now.
2387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         */
2397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        void onReverted();
2407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        /**
2427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         * Contact was saved and the Fragment can now be closed safely.
2437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         */
2447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        void onSaveFinished(Intent resultIntent);
2457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2467b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        /**
247678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai         * User switched to editing a different raw contact (a suggestion from the
2487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         * aggregation engine).
2497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         */
250678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai        void onEditOtherRawContactRequested(Uri contactLookupUri, long rawContactId,
2517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                ArrayList<ContentValues> contentValues);
2527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        /**
2547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         * User has requested that contact be deleted.
2557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         */
2567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        void onDeleteRequested(Uri contactUri);
2577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
2587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
2607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Adapter for aggregation suggestions displayed in a PopupWindow when
2617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * editor fields change.
2627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
2637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final class AggregationSuggestionAdapter extends BaseAdapter {
2647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        private final LayoutInflater mLayoutInflater;
2657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        private final AggregationSuggestionView.Listener mListener;
2667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        private final List<AggregationSuggestionEngine.Suggestion> mSuggestions;
2677b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
268678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai        public AggregationSuggestionAdapter(Activity activity,
2697b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                AggregationSuggestionView.Listener listener, List<Suggestion> suggestions) {
2707b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mLayoutInflater = activity.getLayoutInflater();
2717b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mListener = listener;
2727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mSuggestions = suggestions;
2737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
2747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        @Override
2767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        public View getView(int position, View convertView, ViewGroup parent) {
2777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            final Suggestion suggestion = (Suggestion) getItem(position);
2787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            final AggregationSuggestionView suggestionView =
2797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    (AggregationSuggestionView) mLayoutInflater.inflate(
2807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                            R.layout.aggregation_suggestions_item, null);
2817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            suggestionView.setListener(mListener);
2827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            suggestionView.bindSuggestion(suggestion);
2837b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return suggestionView;
2847b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
2857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2867b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        @Override
2877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        public long getItemId(int position) {
2887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return position;
2897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
2907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        @Override
2927b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        public Object getItem(int position) {
2937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return mSuggestions.get(position);
2947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
2957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        @Override
2977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        public int getCount() {
2987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return mSuggestions.size();
2997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
3007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
3017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected Context mContext;
3037b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected Listener mListener;
3047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3057b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
3067b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Views
3077b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
3087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected LinearLayout mContent;
3097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected ListPopupWindow mAggregationSuggestionPopup;
3107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
3127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Parameters passed in on {@link #load}
3137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
3147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected String mAction;
3157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected Uri mLookupUri;
3167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected Bundle mIntentExtras;
3177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected boolean mAutoAddToDefaultGroup;
3187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected boolean mDisableDeleteMenuOption;
3197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected boolean mNewLocalProfile;
3207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected MaterialColorMapUtils.MaterialPalette mMaterialPalette;
3217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
3237b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Helpers
3247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
3257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected ContactEditorUtils mEditorUtils;
3267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected RawContactDeltaComparator mComparator;
3277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected ViewIdGenerator mViewIdGenerator;
3287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private AggregationSuggestionEngine mAggregationSuggestionEngine;
3297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
3317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Loaded data
3327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
3337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Used to store existing contact data so it can be re-applied during a rebind call,
3347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // i.e. account switch.
3357b75145e9b4fcd46c3cbb5678f8842934467b3aaGary Mai    protected Contact mContact;
3367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected ImmutableList<RawContact> mRawContacts;
3377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected Cursor mGroupMetaData;
3387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
3407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Editor state
3417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
3427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected RawContactDeltaList mState;
3437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected int mStatus;
3447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected long mRawContactIdToDisplayAlone = -1;
3457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3467b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Whether to show the new contact blank form and if it's corresponding delta is ready.
3477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected boolean mHasNewContact;
3487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected AccountWithDataSet mAccountWithDataSet;
3494bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott    protected List<AccountInfo> mWritableAccounts = Collections.emptyList();
3507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected boolean mNewContactDataReady;
3517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected boolean mNewContactAccountChanged;
3527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Whether it's an edit of existing contact and if it's corresponding delta is ready.
3547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected boolean mIsEdit;
3557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected boolean mExistingContactDataReady;
3567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Whether we are editing the "me" profile
3587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected boolean mIsUserProfile;
3597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Whether editor views and options menu items should be enabled
3617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private boolean mEnabled = true;
3627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Aggregation PopupWindow
3647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private long mAggregationSuggestionsRawContactId;
3657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Join Activity
3677b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected long mContactIdForJoin;
3687b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3697b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Used to pre-populate the editor with a display name when a user edits a read-only contact.
370698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai    protected long mReadOnlyDisplayNameId;
371698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai    protected boolean mCopyReadOnlyName;
3727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
3747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * The contact data loader listener.
3757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
3767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected final LoaderManager.LoaderCallbacks<Contact> mContactLoaderListener =
3777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            new LoaderManager.LoaderCallbacks<Contact>() {
3787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                protected long mLoaderStartTime;
3807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                @Override
3827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                public Loader<Contact> onCreateLoader(int id, Bundle args) {
3837b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mLoaderStartTime = SystemClock.elapsedRealtime();
384e48746654178e9448819f86b3129fd32f539b3c9Gary Mai                    return new ContactLoader(mContext, mLookupUri,
385e48746654178e9448819f86b3129fd32f539b3c9Gary Mai                            /* postViewNotification */ true,
386e48746654178e9448819f86b3129fd32f539b3c9Gary Mai                            /* loadGroupMetaData */ true);
3877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
3887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                @Override
3907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                public void onLoadFinished(Loader<Contact> loader, Contact contact) {
3917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    final long loaderCurrentTime = SystemClock.elapsedRealtime();
39257a0e98eed836b72dd3dc3540b9cac029266ed7cWenyi Wang                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
39357a0e98eed836b72dd3dc3540b9cac029266ed7cWenyi Wang                        Log.v(TAG,
39457a0e98eed836b72dd3dc3540b9cac029266ed7cWenyi Wang                                "Time needed for loading: " + (loaderCurrentTime-mLoaderStartTime));
39557a0e98eed836b72dd3dc3540b9cac029266ed7cWenyi Wang                    }
3967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    if (!contact.isLoaded()) {
3977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        // Item has been deleted. Close activity without saving again.
3987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        Log.i(TAG, "No contact found. Closing activity");
3997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        mStatus = Status.CLOSING;
4007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        if (mListener != null) mListener.onContactNotFound();
4017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        return;
4027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    }
4037b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mStatus = Status.EDITING;
4057b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mLookupUri = contact.getLookupUri();
4067b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    final long setDataStartTime = SystemClock.elapsedRealtime();
4077b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    setState(contact);
4087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    final long setDataEndTime = SystemClock.elapsedRealtime();
40957a0e98eed836b72dd3dc3540b9cac029266ed7cWenyi Wang                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
41057a0e98eed836b72dd3dc3540b9cac029266ed7cWenyi Wang                        Log.v(TAG, "Time needed for setting UI: "
41157a0e98eed836b72dd3dc3540b9cac029266ed7cWenyi Wang                                + (setDataEndTime - setDataStartTime));
41257a0e98eed836b72dd3dc3540b9cac029266ed7cWenyi Wang                    }
4137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
4147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                @Override
4167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                public void onLoaderReset(Loader<Contact> loader) {
4177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
4187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            };
4197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
4217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * The groups meta data loader listener.
4227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
4237b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected final LoaderManager.LoaderCallbacks<Cursor> mGroupsLoaderListener =
4247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            new LoaderManager.LoaderCallbacks<Cursor>() {
4257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                @Override
4277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                public CursorLoader onCreateLoader(int id, Bundle args) {
4285c1bff2efa542ea112c3f2a1d1ed1e271c7691a7Gary Mai                    return new GroupMetaDataLoader(mContext, ContactsContract.Groups.CONTENT_URI,
4295c1bff2efa542ea112c3f2a1d1ed1e271c7691a7Gary Mai                            GroupUtil.ALL_GROUPS_SELECTION);
4307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
4317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                @Override
4337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
4347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mGroupMetaData = data;
4357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    setGroupMetaData();
4367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
4377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                @Override
4397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                public void onLoaderReset(Loader<Cursor> loader) {
4407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
4417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            };
4427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4433efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    private long mPhotoRawContactId;
44428a27279554af7b1e5ff664d3da97954c462a797Walter Jang    private Bundle mUpdatedPhotos = new Bundle();
4453efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
4463efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    @Override
4477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public Context getContext() {
4487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return getActivity();
4497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
4507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
4527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onAttach(Activity activity) {
4537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        super.onAttach(activity);
4547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mContext = activity;
455a7978d5bc3fcbe62a40e59e29aebea668385a98aMarcus Hagerott        mEditorUtils = ContactEditorUtils.create(mContext);
4567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mComparator = new RawContactDeltaComparator(mContext);
4577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
4587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
4603efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    public void onCreate(Bundle savedState) {
4617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (savedState != null) {
4627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Restore mUri before calling super.onCreate so that onInitializeLoaders
4637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // would already have a uri and an action to work with
4647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mAction = savedState.getString(KEY_ACTION);
4657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mLookupUri = savedState.getParcelable(KEY_URI);
4667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
4677b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4683efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang        super.onCreate(savedState);
4693efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
4707b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (savedState == null) {
4717b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mViewIdGenerator = new ViewIdGenerator();
4727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // mState can still be null because it may not have have finished loading before
4747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // onSaveInstanceState was called.
4757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mState = new RawContactDeltaList();
4767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        } else {
4777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mViewIdGenerator = savedState.getParcelable(KEY_VIEW_ID_GENERATOR);
4787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mAutoAddToDefaultGroup = savedState.getBoolean(KEY_AUTO_ADD_TO_DEFAULT_GROUP);
4807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mDisableDeleteMenuOption = savedState.getBoolean(KEY_DISABLE_DELETE_MENU_OPTION);
4817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mNewLocalProfile = savedState.getBoolean(KEY_NEW_LOCAL_PROFILE);
4827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mMaterialPalette = savedState.getParcelable(KEY_MATERIAL_PALETTE);
483c135a5d502130aee06ffcc11170513053396e9b0Gary Mai            mAccountWithDataSet = savedState.getParcelable(KEY_ACCOUNT);
4847b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mRawContacts = ImmutableList.copyOf(savedState.<RawContact>getParcelableArrayList(
4857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    KEY_RAW_CONTACTS));
4867b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // NOTE: mGroupMetaData is not saved/restored
4877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Read state from savedState. No loading involved here
4897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mState = savedState.<RawContactDeltaList> getParcelable(KEY_EDIT_STATE);
4907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mStatus = savedState.getInt(KEY_STATUS);
4917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4927b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mHasNewContact = savedState.getBoolean(KEY_HAS_NEW_CONTACT);
4937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mNewContactDataReady = savedState.getBoolean(KEY_NEW_CONTACT_READY);
4947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mIsEdit = savedState.getBoolean(KEY_IS_EDIT);
4967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mExistingContactDataReady = savedState.getBoolean(KEY_EXISTING_CONTACT_READY);
4977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mIsUserProfile = savedState.getBoolean(KEY_IS_USER_PROFILE);
4997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
5007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mEnabled = savedState.getBoolean(KEY_ENABLED);
5017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
5027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Aggregation PopupWindow
5037b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mAggregationSuggestionsRawContactId = savedState.getLong(
5047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    KEY_AGGREGATION_SUGGESTIONS_RAW_CONTACT_ID);
5057b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
5067b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Join Activity
5077b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mContactIdForJoin = savedState.getLong(KEY_CONTACT_ID_FOR_JOIN);
5087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
509698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            mReadOnlyDisplayNameId = savedState.getLong(KEY_READ_ONLY_DISPLAY_NAME_ID);
510698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            mCopyReadOnlyName = savedState.getBoolean(KEY_COPY_READ_ONLY_DISPLAY_NAME, false);
5117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
5123efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang            mPhotoRawContactId = savedState.getLong(KEY_PHOTO_RAW_CONTACT_ID);
51328a27279554af7b1e5ff664d3da97954c462a797Walter Jang            mUpdatedPhotos = savedState.getParcelable(KEY_UPDATED_PHOTOS);
5143efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang        }
5153efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    }
5163efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
5173f990ba4e35a99078d831c041290e574a320caa5Walter Jang    @Override
5183f990ba4e35a99078d831c041290e574a320caa5Walter Jang    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
519ed8f6c9744dd38e089598acfba6fb90446954e6eWalter Jang        setHasOptionsMenu(true);
520ed8f6c9744dd38e089598acfba6fb90446954e6eWalter Jang
5213f990ba4e35a99078d831c041290e574a320caa5Walter Jang        final View view = inflater.inflate(
522363af60ea23e5a3b945005712a16564ab69db18bGary Mai                R.layout.contact_editor_fragment, container, false);
523f5dfea4a5c94382a632eae5c538881f7da726a50Walter Jang        mContent = (LinearLayout) view.findViewById(R.id.raw_contacts_editor_view);
5243f990ba4e35a99078d831c041290e574a320caa5Walter Jang        return view;
5253f990ba4e35a99078d831c041290e574a320caa5Walter Jang    }
5263f990ba4e35a99078d831c041290e574a320caa5Walter Jang
527ed8f6c9744dd38e089598acfba6fb90446954e6eWalter Jang    @Override
5287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onActivityCreated(Bundle savedInstanceState) {
5297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        super.onActivityCreated(savedInstanceState);
5307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
5317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        validateAction(mAction);
5327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
5337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mState.isEmpty()) {
5347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // The delta list may not have finished loading before orientation change happens.
5357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // In this case, there will be a saved state but deltas will be missing.  Reload from
5367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // database.
5377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            if (Intent.ACTION_EDIT.equals(mAction)) {
5387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // Either
5397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // 1) orientation change but load never finished.
5407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // 2) not an orientation change so data needs to be loaded for first time.
5417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                getLoaderManager().initLoader(LOADER_CONTACT, null, mContactLoaderListener);
5427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                getLoaderManager().initLoader(LOADER_GROUPS, null, mGroupsLoaderListener);
5437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
5447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        } else {
5457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Orientation change, we already have mState, it was loaded by onCreate
5467b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            bindEditors();
5477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
5487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
5497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // Handle initial actions only when existing state missing
5507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (savedInstanceState == null) {
551807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott            if (mIntentExtras != null) {
552807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott                final Account account = mIntentExtras == null ? null :
553807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott                        (Account) mIntentExtras.getParcelable(Intents.Insert.EXTRA_ACCOUNT);
554807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott                final String dataSet = mIntentExtras == null ? null :
555807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott                        mIntentExtras.getString(Intents.Insert.EXTRA_DATA_SET);
556807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott                mAccountWithDataSet = account != null
557807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott                        ? new AccountWithDataSet(account.name, account.type, dataSet)
558807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott                        : mIntentExtras.<AccountWithDataSet>getParcelable(
559807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott                                ContactEditorActivity.EXTRA_ACCOUNT_WITH_DATA_SET);
5607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
5617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
5627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            if (Intent.ACTION_EDIT.equals(mAction)) {
5637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                mIsEdit = true;
5647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            } else if (Intent.ACTION_INSERT.equals(mAction)) {
5657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                mHasNewContact = true;
5667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (mAccountWithDataSet != null) {
5677b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    createContact(mAccountWithDataSet);
568807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott                } // else wait for accounts to be loaded
5697b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
5707b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
571807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott
572807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott        if (mHasNewContact) {
5738c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott            AccountsLoader.loadAccounts(this, LOADER_ACCOUNTS, AccountTypeManager.writableFilter());
574807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott        }
5757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
5767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
5777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
5787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Checks if the requested action is valid.
5797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     *
5807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * @param action The action to test.
5817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * @throws IllegalArgumentException when the action is invalid.
5827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
5837b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static void validateAction(String action) {
5847b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (VALID_INTENT_ACTIONS.contains(action)) {
5857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return;
5867b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
5877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        throw new IllegalArgumentException(
5887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                "Unknown action " + action + "; Supported actions: " + VALID_INTENT_ACTIONS);
5897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
5907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
5917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
5923efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    public void onSaveInstanceState(Bundle outState) {
5937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putString(KEY_ACTION, mAction);
5947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putParcelable(KEY_URI, mLookupUri);
5957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putBoolean(KEY_AUTO_ADD_TO_DEFAULT_GROUP, mAutoAddToDefaultGroup);
5967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putBoolean(KEY_DISABLE_DELETE_MENU_OPTION, mDisableDeleteMenuOption);
5977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putBoolean(KEY_NEW_LOCAL_PROFILE, mNewLocalProfile);
5987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mMaterialPalette != null) {
5997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            outState.putParcelable(KEY_MATERIAL_PALETTE, mMaterialPalette);
6007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
6017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putParcelable(KEY_VIEW_ID_GENERATOR, mViewIdGenerator);
6027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
6037b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putParcelableArrayList(KEY_RAW_CONTACTS, mRawContacts == null ?
6047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                Lists.<RawContact>newArrayList() : Lists.newArrayList(mRawContacts));
6057b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // NOTE: mGroupMetaData is not saved
6067b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
60736ceb4235ed685a222af86076dcf160ba124a583Gary Mai        outState.putParcelable(KEY_EDIT_STATE, mState);
6087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putInt(KEY_STATUS, mStatus);
6097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putBoolean(KEY_HAS_NEW_CONTACT, mHasNewContact);
6107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putBoolean(KEY_NEW_CONTACT_READY, mNewContactDataReady);
6117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putBoolean(KEY_IS_EDIT, mIsEdit);
6127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putBoolean(KEY_EXISTING_CONTACT_READY, mExistingContactDataReady);
613c135a5d502130aee06ffcc11170513053396e9b0Gary Mai        outState.putParcelable(KEY_ACCOUNT, mAccountWithDataSet);
6147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putBoolean(KEY_IS_USER_PROFILE, mIsUserProfile);
6157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
6167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putBoolean(KEY_ENABLED, mEnabled);
6177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
6187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // Aggregation PopupWindow
6197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putLong(KEY_AGGREGATION_SUGGESTIONS_RAW_CONTACT_ID,
6207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                mAggregationSuggestionsRawContactId);
6217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
6227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // Join Activity
6237b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putLong(KEY_CONTACT_ID_FOR_JOIN, mContactIdForJoin);
6247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
625698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        outState.putLong(KEY_READ_ONLY_DISPLAY_NAME_ID, mReadOnlyDisplayNameId);
626698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        outState.putBoolean(KEY_COPY_READ_ONLY_DISPLAY_NAME, mCopyReadOnlyName);
6277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
6283efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang        outState.putLong(KEY_PHOTO_RAW_CONTACT_ID, mPhotoRawContactId);
62928a27279554af7b1e5ff664d3da97954c462a797Walter Jang        outState.putParcelable(KEY_UPDATED_PHOTOS, mUpdatedPhotos);
6303efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang        super.onSaveInstanceState(outState);
6313efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    }
6323efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
6333efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    @Override
6347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onStop() {
6357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        super.onStop();
6367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        UiClosables.closeQuietly(mAggregationSuggestionPopup);
6377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
6387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
6397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
6407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onDestroy() {
6417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        super.onDestroy();
6427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mAggregationSuggestionEngine != null) {
6437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mAggregationSuggestionEngine.quit();
6447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
6457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
6467b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
6477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
6487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onActivityResult(int requestCode, int resultCode, Intent data) {
6497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        switch (requestCode) {
6507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            case REQUEST_CODE_JOIN: {
6517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // Ignore failed requests
6527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (resultCode != Activity.RESULT_OK) return;
6537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (data != null) {
6547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    final long contactId = ContentUris.parseId(data.getData());
6557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    if (hasPendingChanges()) {
6567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        // Ask the user if they want to save changes before doing the join
6577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        JoinContactConfirmationDialogFragment.show(this, contactId);
6587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    } else {
6597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        // Do the join immediately
6607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        joinAggregate(contactId);
6617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    }
6627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
6637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                break;
6647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
6657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            case REQUEST_CODE_ACCOUNTS_CHANGED: {
6667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // Bail if the account selector was not successful.
667807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott                if (resultCode != Activity.RESULT_OK || data == null ||
668807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott                        !data.hasExtra(Intents.Insert.EXTRA_ACCOUNT)) {
6697b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    if (mListener != null) {
6707b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        mListener.onReverted();
6717b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    }
6727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    return;
6737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
674807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott                AccountWithDataSet account = data.getParcelableExtra(
675807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott                        Intents.Insert.EXTRA_ACCOUNT);
676807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott                createContact(account);
6777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                break;
6787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
6797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
6807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
6817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
6828c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott    @Override
6838c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott    public void onAccountsLoaded(List<AccountInfo> data) {
6848c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott        mWritableAccounts = data;
6858c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott        // The user may need to select a new account to save to
6868c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott        if (mAccountWithDataSet == null && mHasNewContact) {
6878c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott            selectAccountAndCreateContact();
6888c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott        }
6898c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott
6908c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott        final RawContactEditorView view = getContent();
6918c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott        if (view == null) {
6928c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott            return;
6938c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott        }
6948c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott        view.setAccounts(data);
6958c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott        if (mAccountWithDataSet == null && view.getCurrentRawContactDelta() == null) {
6968c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott            return;
6978c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott        }
6988c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott
6998c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott        final AccountWithDataSet account = mAccountWithDataSet != null
7008c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott                ? mAccountWithDataSet
7018c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott                : view.getCurrentRawContactDelta().getAccountWithDataSet();
7028c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott
7038c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott        // The current account was removed
7048c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott        if (!AccountInfo.contains(data, account) && !data.isEmpty()) {
7058c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott            if (isReadyToBindEditors()) {
7068c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott                onRebindEditorsForNewContact(getContent().getCurrentRawContactDelta(),
7078c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott                        account, data.get(0).getAccount());
7088c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott            } else {
7098c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott                mAccountWithDataSet = data.get(0).getAccount();
7108c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott            }
7118c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott        }
7128c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott    }
7138c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott
7147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
7157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Options menu
7167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
7177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
7187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
7197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onCreateOptionsMenu(Menu menu, final MenuInflater inflater) {
7207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        inflater.inflate(R.menu.edit_contact, menu);
7217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
7227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
7237b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
7247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onPrepareOptionsMenu(Menu menu) {
7257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // This supports the keyboard shortcut to save changes to a contact but shouldn't be visible
7267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // because the custom action bar contains the "save" button now (not the overflow menu).
7277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // TODO: Find a better way to handle shortcuts, i.e. onKeyDown()?
7287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final MenuItem saveMenu = menu.findItem(R.id.menu_save);
7297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final MenuItem splitMenu = menu.findItem(R.id.menu_split);
7307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final MenuItem joinMenu = menu.findItem(R.id.menu_join);
7317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final MenuItem deleteMenu = menu.findItem(R.id.menu_delete);
7327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
7335eda257528e45fe6ae59cca3f1178590b53662f8Gary Mai        // TODO: b/30771904, b/31827701, temporarily disable these items until we get them to work
7345eda257528e45fe6ae59cca3f1178590b53662f8Gary Mai        // on a raw contact level.
7355eda257528e45fe6ae59cca3f1178590b53662f8Gary Mai        joinMenu.setVisible(false);
7365eda257528e45fe6ae59cca3f1178590b53662f8Gary Mai        splitMenu.setVisible(false);
7375eda257528e45fe6ae59cca3f1178590b53662f8Gary Mai        deleteMenu.setVisible(false);
7387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // Save menu is invisible when there's only one read only contact in the editor.
739d7faa65c1349a7ded4d2d478822c07d024e5e792Gary Mai        saveMenu.setVisible(!isEditingReadOnlyRawContact());
7407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (saveMenu.isVisible()) {
7417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Since we're using a custom action layout we have to manually hook up the handler.
7427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            saveMenu.getActionView().setOnClickListener(new View.OnClickListener() {
7437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                @Override
7447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                public void onClick(View v) {
7457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    onOptionsItemSelected(saveMenu);
7467b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
7477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            });
7487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
7497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
7507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        int size = menu.size();
7517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        for (int i = 0; i < size; i++) {
7527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            menu.getItem(i).setEnabled(mEnabled);
7537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
7547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
7557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
7567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
757c90cc15b804fb00339a3b98e5c951549f9b03599Walter Jang    public boolean onOptionsItemSelected(MenuItem item) {
758c90cc15b804fb00339a3b98e5c951549f9b03599Walter Jang        if (item.getItemId() == android.R.id.home) {
759c90cc15b804fb00339a3b98e5c951549f9b03599Walter Jang            return revert();
760c90cc15b804fb00339a3b98e5c951549f9b03599Walter Jang        }
7617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
7627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final Activity activity = getActivity();
7637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (activity == null || activity.isFinishing() || activity.isDestroyed()) {
7647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // If we no longer are attached to a running activity want to
7657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // drain this event.
7667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return true;
7677b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
7687b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
769b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott        final int id = item.getItemId();
770b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott        if (id == R.id.menu_save) {
771b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott            return save(SaveMode.CLOSE);
772b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott        } else if (id == R.id.menu_delete) {
773b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott            if (mListener != null) mListener.onDeleteRequested(mLookupUri);
774b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott            return true;
775b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott        } else if (id == R.id.menu_split) {
776b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott            return doSplitContactAction();
777b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott        } else if (id == R.id.menu_join) {
778b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott            return doJoinContactAction();
779b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott        } else if (id == R.id.menu_help) {
780b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott            HelpUtils.launchHelpAndFeedbackForContactScreen(getActivity());
781b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott            return true;
7827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
7837b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
7847b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return false;
7857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
7867b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
7877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
7887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public boolean revert() {
7897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mState.isEmpty() || !hasPendingChanges()) {
7907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            onCancelEditConfirmed();
7917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        } else {
7927b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            CancelEditDialogFragment.show(this);
7937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
7947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return true;
7957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
7967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
7977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
7987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onCancelEditConfirmed() {
7997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // When this Fragment is closed we don't want it to auto-save
8007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mStatus = Status.CLOSING;
8017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mListener != null) {
8027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mListener.onReverted();
8037b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
8047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
8057b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8067b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
8077b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onSplitContactConfirmed(boolean hasPendingChanges) {
8087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mState.isEmpty()) {
8097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // This may happen when this Fragment is recreated by the system during users
8107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // confirming the split action (and thus this method is called just before onCreate()),
8117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // for example.
8127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            Log.e(TAG, "mState became null during the user's confirming split action. " +
8137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    "Cannot perform the save action.");
8147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return;
8157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
8167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (!hasPendingChanges && mHasNewContact) {
8187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // If the user didn't add anything new, we don't want to split out the newly created
8197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // raw contact into a name-only contact so remove them.
8207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            final Iterator<RawContactDelta> iterator = mState.iterator();
8217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            while (iterator.hasNext()) {
8227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                final RawContactDelta rawContactDelta = iterator.next();
8237b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (rawContactDelta.getRawContactId() < 0) {
8247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    iterator.remove();
8257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
8267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
8277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
8287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mState.markRawContactsForSplitting();
8297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        save(SaveMode.SPLIT);
8307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
8317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
832b9065ddb28a2040cabda251891be2062b5260217Gary Mai    @Override
833b9065ddb28a2040cabda251891be2062b5260217Gary Mai    public void onSplitContactCanceled() {}
834b9065ddb28a2040cabda251891be2062b5260217Gary Mai
8357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private boolean doSplitContactAction() {
8367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (!hasValidState()) return false;
8377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        SplitContactConfirmationDialogFragment.show(this, hasPendingChanges());
8397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return true;
8407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
8417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private boolean doJoinContactAction() {
8437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (!hasValidState() || mLookupUri == null) {
8447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return false;
8457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
8467b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // If we just started creating a new contact and haven't added any data, it's too
8487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // early to do a join
8497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mState.size() == 1 && mState.get(0).isContactInsert()
8507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                && !hasPendingChanges()) {
8517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            Toast.makeText(mContext, R.string.toast_join_with_empty_contact,
8527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    Toast.LENGTH_LONG).show();
8537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return true;
8547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
8557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        showJoinAggregateActivity(mLookupUri);
8577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return true;
8587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
8597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
8617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onJoinContactConfirmed(long joinContactId) {
8627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        doSaveAction(SaveMode.JOIN, joinContactId);
8637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
8647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
865c90cc15b804fb00339a3b98e5c951549f9b03599Walter Jang    @Override
8667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public boolean save(int saveMode) {
8677b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (!hasValidState() || mStatus != Status.EDITING) {
8687b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return false;
8697b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
8707b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8717b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // If we are about to close the editor - there is no need to refresh the data
872363af60ea23e5a3b945005712a16564ab69db18bGary Mai        if (saveMode == SaveMode.CLOSE || saveMode == SaveMode.EDITOR
8737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                || saveMode == SaveMode.SPLIT) {
8747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            getLoaderManager().destroyLoader(LOADER_CONTACT);
8757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
8767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mStatus = Status.SAVING;
8787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (!hasPendingChanges()) {
8807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            if (mLookupUri == null && saveMode == SaveMode.RELOAD) {
8817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // We don't have anything to save and there isn't even an existing contact yet.
8827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // Nothing to do, simply go back to editing mode
8837b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                mStatus = Status.EDITING;
8847b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                return true;
8857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
8867b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            onSaveCompleted(/* hadChanges =*/ false, saveMode,
8877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    /* saveSucceeded =*/ mLookupUri != null, mLookupUri, /* joinContactId =*/ null);
8887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return true;
8897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
8907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        setEnabled(false);
8927b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return doSaveAction(saveMode, /* joinContactId */ null);
8947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
8957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
8977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // State accessor methods
8987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
8997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
9007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
9017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Check if our internal {@link #mState} is valid, usually checked before
9027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * performing user actions.
9037b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
9047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private boolean hasValidState() {
9057b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return mState.size() > 0;
9067b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
9077b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
9087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private boolean isEditingUserProfile() {
9097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return mNewLocalProfile || mIsUserProfile;
9107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
9117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
9127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
9135a00de39004d298de4daee3e183add5eff17102cGary Mai     * Whether the contact being edited is composed of read-only raw contacts
9147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * aggregated with a newly created writable raw contact.
9157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
9167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private boolean isEditingReadOnlyRawContactWithNewContact() {
9175a00de39004d298de4daee3e183add5eff17102cGary Mai        return mHasNewContact && mState.size() > 1;
9187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
9197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
9207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
921d7faa65c1349a7ded4d2d478822c07d024e5e792Gary Mai     * @return true if the single raw contact we're looking at is read-only.
922d7faa65c1349a7ded4d2d478822c07d024e5e792Gary Mai     */
923d7faa65c1349a7ded4d2d478822c07d024e5e792Gary Mai    private boolean isEditingReadOnlyRawContact() {
924d7faa65c1349a7ded4d2d478822c07d024e5e792Gary Mai        return hasValidState() && mRawContactIdToDisplayAlone > 0
925d7faa65c1349a7ded4d2d478822c07d024e5e792Gary Mai                && !mState.getByRawContactId(mRawContactIdToDisplayAlone)
926d7faa65c1349a7ded4d2d478822c07d024e5e792Gary Mai                        .getAccountType(AccountTypeManager.getInstance(mContext))
927d7faa65c1349a7ded4d2d478822c07d024e5e792Gary Mai                                .areContactsWritable();
928d7faa65c1349a7ded4d2d478822c07d024e5e792Gary Mai    }
929d7faa65c1349a7ded4d2d478822c07d024e5e792Gary Mai
930d7faa65c1349a7ded4d2d478822c07d024e5e792Gary Mai    /**
9317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Return true if there are any edits to the current contact which need to
9327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * be saved.
9337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
9347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private boolean hasPendingRawContactChanges(Set<String> excludedMimeTypes) {
9357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
9367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return RawContactModifier.hasChanges(mState, accountTypes, excludedMimeTypes);
9377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
9387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
9397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
9407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Determines if changes were made in the editor that need to be saved, while taking into
9417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * account that name changes are not real for read-only contacts.
9427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * See go/editing-read-only-contacts
9437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
9447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private boolean hasPendingChanges() {
945698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        if (isEditingReadOnlyRawContactWithNewContact()) {
9467b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // We created a new raw contact delta with a default display name.
9477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // We must test for pending changes while ignoring the default display name.
948698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final ValuesDelta beforeDelta = mState.getByRawContactId(mReadOnlyDisplayNameId)
949698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai                    .getSuperPrimaryEntry(StructuredName.CONTENT_ITEM_TYPE);
950698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final ValuesDelta pendingDelta = mState
951698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai                    .getSuperPrimaryEntry(StructuredName.CONTENT_ITEM_TYPE);
952698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            if (structuredNamesAreEqual(beforeDelta, pendingDelta)) {
9537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                final Set<String> excludedMimeTypes = new HashSet<>();
9547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                excludedMimeTypes.add(StructuredName.CONTENT_ITEM_TYPE);
9557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                return hasPendingRawContactChanges(excludedMimeTypes);
9567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
9577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return true;
9587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
9597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return hasPendingRawContactChanges(/* excludedMimeTypes =*/ null);
9607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
9617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
9627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
963698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai     * Compares the two {@link ValuesDelta} to see if the structured name is changed. We made a copy
964698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai     * of a read only delta and now we want to check if the copied delta has changes.
965698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai     *
966698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai     * @param before original {@link ValuesDelta}
967698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai     * @param after copied {@link ValuesDelta}
968698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai     * @return true if the copied {@link ValuesDelta} has all the same values in the structured
969698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai     * name fields as the original.
970698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai     */
971698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai    private boolean structuredNamesAreEqual(ValuesDelta before, ValuesDelta after) {
9725a00de39004d298de4daee3e183add5eff17102cGary Mai        if (before == after) return true;
973698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        if (before == null || after == null) return false;
974698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        final ContentValues original = before.getBefore();
975698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        final ContentValues pending = after.getAfter();
976698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        if (original != null && pending != null) {
977a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai            final String beforeDisplayName = original.getAsString(StructuredName.DISPLAY_NAME);
978698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final String afterDisplayName = pending.getAsString(StructuredName.DISPLAY_NAME);
979698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            if (!TextUtils.equals(beforeDisplayName, afterDisplayName)) return false;
980698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai
981698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final String beforePrefix = original.getAsString(StructuredName.PREFIX);
982698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final String afterPrefix = pending.getAsString(StructuredName.PREFIX);
983698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            if (!TextUtils.equals(beforePrefix, afterPrefix)) return false;
984698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai
985698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final String beforeFirstName = original.getAsString(StructuredName.GIVEN_NAME);
986698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final String afterFirstName = pending.getAsString(StructuredName.GIVEN_NAME);
987698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            if (!TextUtils.equals(beforeFirstName, afterFirstName)) return false;
988698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai
989698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final String beforeMiddleName = original.getAsString(StructuredName.MIDDLE_NAME);
990698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final String afterMiddleName = pending.getAsString(StructuredName.MIDDLE_NAME);
991698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            if (!TextUtils.equals(beforeMiddleName, afterMiddleName)) return false;
992698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai
993698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final String beforeLastName = original.getAsString(StructuredName.FAMILY_NAME);
994698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final String afterLastName = pending.getAsString(StructuredName.FAMILY_NAME);
995698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            if (!TextUtils.equals(beforeLastName, afterLastName)) return false;
996698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai
997698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final String beforeSuffix = original.getAsString(StructuredName.SUFFIX);
998698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final String afterSuffix = pending.getAsString(StructuredName.SUFFIX);
999698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            return TextUtils.equals(beforeSuffix, afterSuffix);
1000698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        }
1001698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        return false;
1002698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai    }
1003698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai
10047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
10057b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Account creation
10067b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
10077b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
10087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private void selectAccountAndCreateContact() {
1009807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott        Preconditions.checkNotNull(mWritableAccounts, "Accounts must be loaded first");
10107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // If this is a local profile, then skip the logic about showing the accounts changed
10117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // activity and create a phone-local contact.
10127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mNewLocalProfile) {
10137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            createContact(null);
10147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return;
10157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
10167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1017807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott        final List<AccountWithDataSet> accounts = AccountInfo.extractAccounts(mWritableAccounts);
10187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // If there is no default account or the accounts have changed such that we need to
10197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // prompt the user again, then launch the account prompt.
1020807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott        if (mEditorUtils.shouldShowAccountChangedNotification(accounts)) {
10217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            Intent intent = new Intent(mContext, ContactEditorAccountsChangedActivity.class);
10227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Prevent a second instance from being started on rotates
102380ab7ea6a518410594058c74f32c4b551097edbdMarcus Hagerott            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
10247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mStatus = Status.SUB_ACTIVITY;
10257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            startActivityForResult(intent, REQUEST_CODE_ACCOUNTS_CHANGED);
10267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        } else {
10273107b25dcaea54943c58f984084fa9b348ea1885Gary Mai            // Make sure the default account is automatically set if there is only one non-device
10283107b25dcaea54943c58f984084fa9b348ea1885Gary Mai            // account.
1029807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott            mEditorUtils.maybeUpdateDefaultAccount(accounts);
10307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Otherwise, there should be a default account. Then either create a local contact
10317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // (if default account is null) or create a contact with the specified account.
1032807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott            AccountWithDataSet defaultAccount = mEditorUtils.getOnlyOrDefaultAccount(accounts);
10337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            createContact(defaultAccount);
10347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
10357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
10367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
10377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
10387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Shows account creation screen associated with a given account.
10397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     *
10407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * @param account may be null to signal a device-local contact should be created.
10417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
10427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private void createContact(AccountWithDataSet account) {
10437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
10447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final AccountType accountType = accountTypes.getAccountTypeForAccount(account);
10457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1046aebf3206766a05cce290245f09506adb789b6e37Gary Mai        setStateForNewContact(account, accountType, isEditingUserProfile());
10477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
10487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
10497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
10507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Data binding
10517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
10527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
10537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private void setState(Contact contact) {
10547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // If we have already loaded data, we do not want to change it here to not confuse the user
10557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (!mState.isEmpty()) {
105657a0e98eed836b72dd3dc3540b9cac029266ed7cWenyi Wang            if (Log.isLoggable(TAG, Log.VERBOSE)) {
105757a0e98eed836b72dd3dc3540b9cac029266ed7cWenyi Wang                Log.v(TAG, "Ignoring background change. This will have to be rebased later");
105857a0e98eed836b72dd3dc3540b9cac029266ed7cWenyi Wang            }
10597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return;
10607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
10617b75145e9b4fcd46c3cbb5678f8842934467b3aaGary Mai        mContact = contact;
10624ceabed629c43cb247fd4a0faa36c09bd5ec999aGary Mai        mRawContacts = contact.getRawContacts();
10637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
10647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // Check for writable raw contacts.  If there are none, then we need to create one so user
10657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // can edit.  For the user profile case, there is already an editable contact.
10667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (!contact.isUserProfile() && !contact.isWritableContact(mContext)) {
10677b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mHasNewContact = true;
1068698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            mReadOnlyDisplayNameId = contact.getNameRawContactId();
1069698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            mCopyReadOnlyName = true;
10707b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // This is potentially an asynchronous call and will add deltas to list.
10717b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            selectAccountAndCreateContact();
10727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        } else {
10737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mHasNewContact = false;
10747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
10757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1076698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        setStateForExistingContact(contact.isUserProfile(), mRawContacts);
1077e48746654178e9448819f86b3129fd32f539b3c9Gary Mai        if (mAutoAddToDefaultGroup
1078e48746654178e9448819f86b3129fd32f539b3c9Gary Mai                && InvisibleContactUtil.isInvisibleAndAddable(contact, getContext())) {
1079e48746654178e9448819f86b3129fd32f539b3c9Gary Mai            InvisibleContactUtil.markAddToDefaultGroup(contact, mState, getContext());
1080e48746654178e9448819f86b3129fd32f539b3c9Gary Mai        }
10817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
10827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
10837b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
10847b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Prepare {@link #mState} for a newly created phone-local contact.
10857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
10867b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private void setStateForNewContact(AccountWithDataSet account, AccountType accountType,
10877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            boolean isUserProfile) {
10887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        setStateForNewContact(account, accountType, /* oldState =*/ null,
10897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                /* oldAccountType =*/ null, isUserProfile);
10907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
10917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
10927b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
10937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Prepare {@link #mState} for a newly created phone-local contact, migrating the state
10947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * specified by oldState and oldAccountType.
10957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
10967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private void setStateForNewContact(AccountWithDataSet account, AccountType accountType,
10977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            RawContactDelta oldState, AccountType oldAccountType, boolean isUserProfile) {
10987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mStatus = Status.EDITING;
10999f691e8b1c30dcdae230daebd26da0f225f74008Gary Mai        mAccountWithDataSet = account;
11007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mState.add(createNewRawContactDelta(account, accountType, oldState, oldAccountType));
11017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mIsUserProfile = isUserProfile;
11027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mNewContactDataReady = true;
11037b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        bindEditors();
11047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
11057b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11067b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
11077b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Returns a {@link RawContactDelta} for a new contact suitable for addition into
11087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * {@link #mState}.
11097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     *
11107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * If oldState and oldAccountType are specified, the state specified by those parameters
11117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * is migrated to the result {@link RawContactDelta}.
11127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
11137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private RawContactDelta createNewRawContactDelta(AccountWithDataSet account,
11147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            AccountType accountType, RawContactDelta oldState, AccountType oldAccountType) {
11157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final RawContact rawContact = new RawContact();
11167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (account != null) {
11177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            rawContact.setAccount(account);
11187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        } else {
11197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            rawContact.setAccountToLocal();
11207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
11217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final RawContactDelta result = new RawContactDelta(
11237b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                ValuesDelta.fromAfter(rawContact.getValues()));
11247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (oldState == null) {
11257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Parse any values from incoming intent
11267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            RawContactModifier.parseExtras(mContext, accountType, result, mIntentExtras);
11277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        } else {
11287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            RawContactModifier.migrateStateForNewContact(
11297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mContext, oldState, result, oldAccountType, accountType);
11307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
11317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // Ensure we have some default fields (if the account type does not support a field,
11337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // ensureKind will not add it, so it is safe to add e.g. Event)
113462ec0b10c0ddc00053df39aeaed1f3316116e849Gary Mai        RawContactModifier.ensureKindExists(result, accountType, StructuredName.CONTENT_ITEM_TYPE);
11357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        RawContactModifier.ensureKindExists(result, accountType, Phone.CONTENT_ITEM_TYPE);
11367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        RawContactModifier.ensureKindExists(result, accountType, Email.CONTENT_ITEM_TYPE);
11377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        RawContactModifier.ensureKindExists(result, accountType, Organization.CONTENT_ITEM_TYPE);
11387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        RawContactModifier.ensureKindExists(result, accountType, Event.CONTENT_ITEM_TYPE);
11397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        RawContactModifier.ensureKindExists(result, accountType,
11407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                StructuredPostal.CONTENT_ITEM_TYPE);
11417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // Set the correct URI for saving the contact as a profile
11437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mNewLocalProfile) {
11447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            result.setProfileQueryUri();
11457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
11467b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return result;
11487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
11497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
11517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Prepare {@link #mState} for an existing contact.
11527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
1153698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai    private void setStateForExistingContact(boolean isUserProfile,
11547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            ImmutableList<RawContact> rawContacts) {
11557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        setEnabled(true);
11567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mState.addAll(rawContacts.iterator());
11587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        setIntentExtras(mIntentExtras);
11597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mIntentExtras = null;
11607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // For user profile, change the contacts query URI
11627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mIsUserProfile = isUserProfile;
11637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        boolean localProfileExists = false;
11647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mIsUserProfile) {
11667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            for (RawContactDelta rawContactDelta : mState) {
11677b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // For profile contacts, we need a different query URI
11687b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                rawContactDelta.setProfileQueryUri();
11697b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // Try to find a local profile contact
11707b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (rawContactDelta.getValues().getAsString(RawContacts.ACCOUNT_TYPE) == null) {
11717b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    localProfileExists = true;
11727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
11737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
11747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Editor should always present a local profile for editing
11757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // TODO(wjang): Need to figure out when this case comes up.  We can't do this if we're
11767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // going to prune all but the one raw contact that we're trying to display by itself.
11777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            if (!localProfileExists && mRawContactIdToDisplayAlone <= 0) {
11787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                mState.add(createLocalRawContactDelta());
11797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
11807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
11817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mExistingContactDataReady = true;
11827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        bindEditors();
11837b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
11847b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
11867b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Set the enabled state of editors.
11877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
11887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private void setEnabled(boolean enabled) {
11897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mEnabled != enabled) {
11907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mEnabled = enabled;
11917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11927b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Enable/disable editors
11937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            if (mContent != null) {
11947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                int count = mContent.getChildCount();
11957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                for (int i = 0; i < count; i++) {
11967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mContent.getChildAt(i).setEnabled(enabled);
11977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
11987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
11997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
12007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Maybe invalidate the options menu
12017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            final Activity activity = getActivity();
12027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            if (activity != null) activity.invalidateOptionsMenu();
12037b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
12047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
12057b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
12067b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
12077b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Returns a {@link RawContactDelta} for a local contact suitable for addition into
12087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * {@link #mState}.
12097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
12107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static RawContactDelta createLocalRawContactDelta() {
12117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final RawContact rawContact = new RawContact();
12127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        rawContact.setAccountToLocal();
12137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
12147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final RawContactDelta result = new RawContactDelta(
12157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                ValuesDelta.fromAfter(rawContact.getValues()));
12167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        result.setProfileQueryUri();
12177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
12187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return result;
12197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
12207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1221698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai    private void copyReadOnlyName() {
1222698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        // We should only ever be doing this if we're creating a new writable contact to attach to
1223698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        // a read only contact.
1224698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        if (!isEditingReadOnlyRawContactWithNewContact()) {
1225698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            return;
1226698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        }
1227698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        final int writableIndex = mState.indexOfFirstWritableRawContact(getContext());
1228698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        final RawContactDelta writable = mState.get(writableIndex);
12297b75145e9b4fcd46c3cbb5678f8842934467b3aaGary Mai        final RawContactDelta readOnly = mState.getByRawContactId(mContact.getNameRawContactId());
1230698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        final ValuesDelta writeNameDelta = writable
1231698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai                .getSuperPrimaryEntry(StructuredName.CONTENT_ITEM_TYPE);
1232698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        final ValuesDelta readNameDelta = readOnly
1233698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai                .getSuperPrimaryEntry(StructuredName.CONTENT_ITEM_TYPE);
1234698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        mCopyReadOnlyName = false;
1235860698b8d4542a55da5ec40032a361433b525aadGary Mai        if (writeNameDelta == null || readNameDelta == null) {
1236860698b8d4542a55da5ec40032a361433b525aadGary Mai            return;
1237860698b8d4542a55da5ec40032a361433b525aadGary Mai        }
1238860698b8d4542a55da5ec40032a361433b525aadGary Mai        writeNameDelta.copyStructuredNameFieldsFrom(readNameDelta);
1239698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai    }
1240698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai
12417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
12427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Bind editors using {@link #mState} and other members initialized from the loaded (or new)
12437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Contact.
12447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
1245ba59deb669cf377bedf08af53c9196db3c1cc404Walter Jang    protected void bindEditors() {
1246cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang        if (!isReadyToBindEditors()) {
1247cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang            return;
1248cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang        }
1249cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang
1250d35e5eff8737e757a4179d49dfe9c7db999b4e9dWalter Jang        // Add input fields for the loaded Contact
1251363af60ea23e5a3b945005712a16564ab69db18bGary Mai        final RawContactEditorView editorView = getContent();
1252b6ca272f26b47ecef8fafe94326c4d553576c521Walter Jang        editorView.setListener(this);
1253698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        if (mCopyReadOnlyName) {
1254698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            copyReadOnlyName();
1255698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        }
1256678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai        editorView.setState(mState, mMaterialPalette, mViewIdGenerator,
12579a55237f705453caae1f8aa3576a9acd7596d5ecWalter Jang                mHasNewContact, mIsUserProfile, mAccountWithDataSet,
12585a00de39004d298de4daee3e183add5eff17102cGary Mai                mRawContactIdToDisplayAlone);
1259079598fa2e09c22bb672715a9559b9d8973044d5Gary Mai        if (isEditingReadOnlyRawContact()) {
126015646ce3e2e7a7f889976dc5684ecbc3029230c2Gary Mai            final Toolbar toolbar = getEditorActivity().getToolbar();
126115646ce3e2e7a7f889976dc5684ecbc3029230c2Gary Mai            if (toolbar != null) {
126215646ce3e2e7a7f889976dc5684ecbc3029230c2Gary Mai                toolbar.setTitle(R.string.contact_editor_title_read_only_contact);
1263d8f3da6a4ea4054bd47959db85657a7e01d28358Gary Mai                // Set activity title for Talkback
1264d8f3da6a4ea4054bd47959db85657a7e01d28358Gary Mai                getEditorActivity().setTitle(R.string.contact_editor_title_read_only_contact);
1265bd9ef3c60669d71543b3506d4959c1fe4be409dcJohn Shao                toolbar.setNavigationIcon(R.drawable.quantum_ic_arrow_back_vd_theme_24);
126615646ce3e2e7a7f889976dc5684ecbc3029230c2Gary Mai                toolbar.setNavigationContentDescription(R.string.back_arrow_content_description);
1267bd9ef3c60669d71543b3506d4959c1fe4be409dcJohn Shao                toolbar.getNavigationIcon().setAutoMirrored(true);
1268079598fa2e09c22bb672715a9559b9d8973044d5Gary Mai            }
1269079598fa2e09c22bb672715a9559b9d8973044d5Gary Mai        }
1270cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang
1271d35e5eff8737e757a4179d49dfe9c7db999b4e9dWalter Jang        // Set up the photo widget
127231a74ad969b650eb733e536569254ed3978c4f54Walter Jang        editorView.setPhotoListener(this);
12733efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang        mPhotoRawContactId = editorView.getPhotoRawContactId();
127431a74ad969b650eb733e536569254ed3978c4f54Walter Jang        // If there is an updated full resolution photo apply it now, this will be the case if
127531a74ad969b650eb733e536569254ed3978c4f54Walter Jang        // the user selects or takes a new photo, then rotates the device.
127631a74ad969b650eb733e536569254ed3978c4f54Walter Jang        final Uri uri = (Uri) mUpdatedPhotos.get(String.valueOf(mPhotoRawContactId));
127731a74ad969b650eb733e536569254ed3978c4f54Walter Jang        if (uri != null) {
127831a74ad969b650eb733e536569254ed3978c4f54Walter Jang            editorView.setFullSizePhoto(uri);
127941b3ea1c712f01164feb55455f1391564cb76deeWalter Jang        }
12803efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
1281d35e5eff8737e757a4179d49dfe9c7db999b4e9dWalter Jang        // The editor is ready now so make it visible
1282678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai        editorView.setEnabled(mEnabled);
1283d35e5eff8737e757a4179d49dfe9c7db999b4e9dWalter Jang        editorView.setVisibility(View.VISIBLE);
1284d35e5eff8737e757a4179d49dfe9c7db999b4e9dWalter Jang
1285d35e5eff8737e757a4179d49dfe9c7db999b4e9dWalter Jang        // Refresh the ActionBar as the visibility of the join command
1286d35e5eff8737e757a4179d49dfe9c7db999b4e9dWalter Jang        // Activity can be null if we have been detached from the Activity.
1287cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang        invalidateOptionsMenu();
1288cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang    }
1289cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang
12907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
12917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Invalidates the options menu if we are still associated with an Activity.
12927b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
12937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private void invalidateOptionsMenu() {
12947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final Activity activity = getActivity();
12957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (activity != null) {
12967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            activity.invalidateOptionsMenu();
12977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
12987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
12997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1300cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang    private boolean isReadyToBindEditors() {
1301cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang        if (mState.isEmpty()) {
1302cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang            if (Log.isLoggable(TAG, Log.VERBOSE)) {
1303cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang                Log.v(TAG, "No data to bind editors");
1304cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang            }
1305cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang            return false;
1306cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang        }
1307cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang        if (mIsEdit && !mExistingContactDataReady) {
1308cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang            if (Log.isLoggable(TAG, Log.VERBOSE)) {
1309cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang                Log.v(TAG, "Existing contact data is not ready to bind editors.");
1310cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang            }
1311cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang            return false;
1312cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang        }
1313cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang        if (mHasNewContact && !mNewContactDataReady) {
1314cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang            if (Log.isLoggable(TAG, Log.VERBOSE)) {
1315cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang                Log.v(TAG, "New contact data is not ready to bind editors.");
1316cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang            }
1317cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang            return false;
1318cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang        }
13191e899dc127a212bfd2198fe7adba5c33eb4cd751Gary Mai        // Don't attempt to bind anything if we have no permissions.
13201e899dc127a212bfd2198fe7adba5c33eb4cd751Gary Mai        return RequestPermissionsActivity.hasRequiredPermissions(mContext);
1321ba59deb669cf377bedf08af53c9196db3c1cc404Walter Jang    }
1322ba59deb669cf377bedf08af53c9196db3c1cc404Walter Jang
13237b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
13247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Removes a current editor ({@link #mState}) and rebinds new editor for a new account.
13257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Some of old data are reused with new restriction enforced by the new account.
13267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     *
13277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * @param oldState Old data being edited.
13287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * @param oldAccount Old account associated with oldState.
13297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * @param newAccount New account to be used.
13307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
13317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private void rebindEditorsForNewContact(
13327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            RawContactDelta oldState, AccountWithDataSet oldAccount,
13337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            AccountWithDataSet newAccount) {
13347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
13357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        AccountType oldAccountType = accountTypes.getAccountTypeForAccount(oldAccount);
13367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        AccountType newAccountType = accountTypes.getAccountTypeForAccount(newAccount);
13377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1338aebf3206766a05cce290245f09506adb789b6e37Gary Mai        mExistingContactDataReady = false;
1339aebf3206766a05cce290245f09506adb789b6e37Gary Mai        mNewContactDataReady = false;
1340aebf3206766a05cce290245f09506adb789b6e37Gary Mai        mState = new RawContactDeltaList();
1341aebf3206766a05cce290245f09506adb789b6e37Gary Mai        setStateForNewContact(newAccount, newAccountType, oldState, oldAccountType,
1342aebf3206766a05cce290245f09506adb789b6e37Gary Mai                isEditingUserProfile());
1343aebf3206766a05cce290245f09506adb789b6e37Gary Mai        if (mIsEdit) {
1344698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            setStateForExistingContact(isEditingUserProfile(), mRawContacts);
13457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
13467b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
13477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
13487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
13497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // ContactEditor
13507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
13517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
13527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
13537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void setListener(Listener listener) {
13547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mListener = listener;
13557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
13567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
13577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
13587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void load(String action, Uri lookupUri, Bundle intentExtras) {
13597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mAction = action;
13607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mLookupUri = lookupUri;
13617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mIntentExtras = intentExtras;
13627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
13637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mIntentExtras != null) {
13647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mAutoAddToDefaultGroup =
13657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mIntentExtras.containsKey(INTENT_EXTRA_ADD_TO_DEFAULT_DIRECTORY);
13667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mNewLocalProfile =
13677b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mIntentExtras.getBoolean(INTENT_EXTRA_NEW_LOCAL_PROFILE);
13687b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mDisableDeleteMenuOption =
13697b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mIntentExtras.getBoolean(INTENT_EXTRA_DISABLE_DELETE_MENU_OPTION);
13707b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            if (mIntentExtras.containsKey(INTENT_EXTRA_MATERIAL_PALETTE_PRIMARY_COLOR)
13717b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    && mIntentExtras.containsKey(INTENT_EXTRA_MATERIAL_PALETTE_SECONDARY_COLOR)) {
13727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                mMaterialPalette = new MaterialColorMapUtils.MaterialPalette(
13737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        mIntentExtras.getInt(INTENT_EXTRA_MATERIAL_PALETTE_PRIMARY_COLOR),
13747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        mIntentExtras.getInt(INTENT_EXTRA_MATERIAL_PALETTE_SECONDARY_COLOR));
13757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
1376a6c80b378e03ebdf6b654dbdb12f2c665fe98a80Gary Mai            mRawContactIdToDisplayAlone = mIntentExtras
1377a6c80b378e03ebdf6b654dbdb12f2c665fe98a80Gary Mai                    .getLong(INTENT_EXTRA_RAW_CONTACT_ID_TO_DISPLAY_ALONE);
13787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
13797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
13807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
13817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
13827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void setIntentExtras(Bundle extras) {
13835336e6ef1924162b94942cbd8f69202d553822daGary Mai        getContent().setIntentExtras(extras);
13847b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
13857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
13867b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
13877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onJoinCompleted(Uri uri) {
13887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        onSaveCompleted(false, SaveMode.RELOAD, uri != null, uri, /* joinContactId */ null);
13897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
13907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1391e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey
1392e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey    private String getNameToDisplay(Uri contactUri) {
1393c000d2ee0e292d9b160f65ab74ebd1258346046bGary Mai        // The contact has been deleted or the uri is otherwise no longer right.
1394c000d2ee0e292d9b160f65ab74ebd1258346046bGary Mai        if (contactUri == null) {
1395c000d2ee0e292d9b160f65ab74ebd1258346046bGary Mai            return null;
1396c000d2ee0e292d9b160f65ab74ebd1258346046bGary Mai        }
1397e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey        final ContentResolver resolver = mContext.getContentResolver();
1398e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey        final Cursor cursor = resolver.query(contactUri, new String[]{
1399e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey                ContactsContract.Contacts.DISPLAY_NAME,
1400e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey                ContactsContract.Contacts.DISPLAY_NAME_ALTERNATIVE}, null, null, null);
1401a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai
1402a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai        if (cursor != null) {
1403a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai            try {
1404a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai                if (cursor.moveToFirst()) {
1405a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai                    final String displayName = cursor.getString(0);
1406a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai                    final String displayNameAlt = cursor.getString(1);
1407a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai                    cursor.close();
1408a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai                    return ContactDisplayUtils.getPreferredDisplayName(displayName, displayNameAlt,
1409a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai                            new ContactsPreferences(mContext));
1410a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai                }
1411a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai            } finally {
1412e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey                cursor.close();
1413e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey            }
1414e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey        }
1415e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey        return null;
1416e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey    }
1417e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey
1418e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey
14197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
14207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onSaveCompleted(boolean hadChanges, int saveMode, boolean saveSucceeded,
14217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            Uri contactLookupUri, Long joinContactId) {
14227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (hadChanges) {
14237b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            if (saveSucceeded) {
14247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                switch (saveMode) {
14257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    case SaveMode.JOIN:
14267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        break;
14277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    case SaveMode.SPLIT:
14287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        Toast.makeText(mContext, R.string.contactUnlinkedToast, Toast.LENGTH_SHORT)
14297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                                .show();
14307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        break;
14317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    default:
1432e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey                        final String displayName = getNameToDisplay(contactLookupUri);
1433b1671053e48d14f2c620f48bc5f2cd915b51a002James Laskey                        final String toastMessage;
1434b1671053e48d14f2c620f48bc5f2cd915b51a002James Laskey                        if (!TextUtils.isEmpty(displayName)) {
1435b1671053e48d14f2c620f48bc5f2cd915b51a002James Laskey                            toastMessage = getResources().getString(
1436b1671053e48d14f2c620f48bc5f2cd915b51a002James Laskey                                    R.string.contactSavedNamedToast, displayName);
1437b1671053e48d14f2c620f48bc5f2cd915b51a002James Laskey                        } else {
1438b1671053e48d14f2c620f48bc5f2cd915b51a002James Laskey                            toastMessage = getResources().getString(R.string.contactSavedToast);
1439b1671053e48d14f2c620f48bc5f2cd915b51a002James Laskey                        }
1440b1671053e48d14f2c620f48bc5f2cd915b51a002James Laskey                        Toast.makeText(mContext, toastMessage, Toast.LENGTH_SHORT).show();
14417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
14427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
14437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            } else {
14447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                Toast.makeText(mContext, R.string.contactSavedErrorToast, Toast.LENGTH_LONG).show();
14457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
14467b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
14477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        switch (saveMode) {
14487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            case SaveMode.CLOSE: {
14498d26c0a7214cf6520a4def851afa138a133a68a2Walter Jang                final Intent resultIntent;
14507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (saveSucceeded && contactLookupUri != null) {
14517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    final Uri lookupUri = ContactEditorUtils.maybeConvertToLegacyLookupUri(
14527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                            mContext, contactLookupUri, mLookupUri);
14538d26c0a7214cf6520a4def851afa138a133a68a2Walter Jang                    resultIntent = ImplicitIntentsUtil.composeQuickContactIntent(
14548d26c0a7214cf6520a4def851afa138a133a68a2Walter Jang                            mContext, lookupUri, ScreenType.EDITOR);
14558d26c0a7214cf6520a4def851afa138a133a68a2Walter Jang                    resultIntent.putExtra(QuickContactActivity.EXTRA_CONTACT_EDITED, true);
14567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                } else {
14577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    resultIntent = null;
14587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
14597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // It is already saved, so prevent it from being saved again
14607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                mStatus = Status.CLOSING;
14617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (mListener != null) mListener.onSaveFinished(resultIntent);
14627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                break;
14637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
1464363af60ea23e5a3b945005712a16564ab69db18bGary Mai            case SaveMode.EDITOR: {
14657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // It is already saved, so prevent it from being saved again
14667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                mStatus = Status.CLOSING;
14677b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (mListener != null) mListener.onSaveFinished(/* resultIntent= */ null);
14687b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                break;
14697b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
14707b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            case SaveMode.JOIN:
14717b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (saveSucceeded && contactLookupUri != null && joinContactId != null) {
14727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    joinAggregate(joinContactId);
14737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
14747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                break;
14757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            case SaveMode.RELOAD:
14767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (saveSucceeded && contactLookupUri != null) {
14777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    // If this was in INSERT, we are changing into an EDIT now.
14787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    // If it already was an EDIT, we are changing to the new Uri now
14797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mState = new RawContactDeltaList();
14807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    load(Intent.ACTION_EDIT, contactLookupUri, null);
14817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mStatus = Status.LOADING;
14827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    getLoaderManager().restartLoader(LOADER_CONTACT, null, mContactLoaderListener);
14837b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
14847b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                break;
14857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
14867b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            case SaveMode.SPLIT:
14877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                mStatus = Status.CLOSING;
14887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (mListener != null) {
14897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mListener.onContactSplit(contactLookupUri);
149057a0e98eed836b72dd3dc3540b9cac029266ed7cWenyi Wang                } else if (Log.isLoggable(TAG, Log.DEBUG)) {
14917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    Log.d(TAG, "No listener registered, can not call onSplitFinished");
14927b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
14937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                break;
14947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
14957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
14967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
14977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
14987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Shows a list of aggregates that can be joined into the currently viewed aggregate.
14997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     *
15007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * @param contactLookupUri the fresh URI for the currently edited contact (after saving it)
15017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
15027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private void showJoinAggregateActivity(Uri contactLookupUri) {
15037b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (contactLookupUri == null || !isAdded()) {
15047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return;
15057b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
15067b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15077b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mContactIdForJoin = ContentUris.parseId(contactLookupUri);
15087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final Intent intent = new Intent(mContext, ContactSelectionActivity.class);
15097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        intent.setAction(UiIntentActions.PICK_JOIN_CONTACT_ACTION);
15107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        intent.putExtra(UiIntentActions.TARGET_CONTACT_ID_EXTRA_KEY, mContactIdForJoin);
15117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        startActivityForResult(intent, REQUEST_CODE_JOIN);
15127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
15137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
15157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Aggregation PopupWindow
15167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
15177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
15197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Triggers an asynchronous search for aggregation suggestions.
15207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
15217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected void acquireAggregationSuggestions(Context context,
15227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            long rawContactId, ValuesDelta valuesDelta) {
15237b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mAggregationSuggestionsRawContactId = rawContactId;
15247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mAggregationSuggestionEngine == null) {
15267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mAggregationSuggestionEngine = new AggregationSuggestionEngine(context);
15277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mAggregationSuggestionEngine.setListener(this);
15287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mAggregationSuggestionEngine.start();
15297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
15307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mAggregationSuggestionEngine.setContactId(getContactId());
1532220d10cd7095f5ab803ff6155d7adaa576a8c4ffGary Mai        mAggregationSuggestionEngine.setAccountFilter(
1533220d10cd7095f5ab803ff6155d7adaa576a8c4ffGary Mai                getContent().getCurrentRawContactDelta().getAccountWithDataSet());
15347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mAggregationSuggestionEngine.onNameChange(valuesDelta);
15367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
15377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
15397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Returns the contact ID for the currently edited contact or 0 if the contact is new.
15407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
15417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private long getContactId() {
15427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        for (RawContactDelta rawContact : mState) {
15437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            Long contactId = rawContact.getValues().getAsLong(RawContacts.CONTACT_ID);
15447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            if (contactId != null) {
15457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                return contactId;
15467b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
15477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
15487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return 0;
15497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
15507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15513f990ba4e35a99078d831c041290e574a320caa5Walter Jang    @Override
15527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onAggregationSuggestionChange() {
15537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final Activity activity = getActivity();
15547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if ((activity != null && activity.isFinishing())
15557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                || !isVisible() ||  mState.isEmpty() || mStatus != Status.EDITING) {
15567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return;
15577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
15587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        UiClosables.closeQuietly(mAggregationSuggestionPopup);
15607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mAggregationSuggestionEngine.getSuggestedContactCount() == 0) {
15627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return;
15637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
15647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1565da20b47c2b85390a2c3772379e71203c5aab513cGary Mai        final View anchorView = getAggregationAnchorView();
15667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (anchorView == null) {
15677b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return; // Raw contact deleted?
15687b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
15697b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mAggregationSuggestionPopup = new ListPopupWindow(mContext, null);
15707b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mAggregationSuggestionPopup.setAnchorView(anchorView);
15717b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mAggregationSuggestionPopup.setWidth(anchorView.getWidth());
15727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mAggregationSuggestionPopup.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED);
15737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mAggregationSuggestionPopup.setAdapter(
15747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                new AggregationSuggestionAdapter(
15757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        getActivity(),
15767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        /* listener =*/ this,
15777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        mAggregationSuggestionEngine.getSuggestions()));
15787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mAggregationSuggestionPopup.setOnItemClickListener(new AdapterView.OnItemClickListener() {
15797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            @Override
15807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
15817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                final AggregationSuggestionView suggestionView = (AggregationSuggestionView) view;
15827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                suggestionView.handleItemClickEvent();
15837b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                UiClosables.closeQuietly(mAggregationSuggestionPopup);
15847b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                mAggregationSuggestionPopup = null;
15857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
15867b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        });
15877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mAggregationSuggestionPopup.show();
15887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
15897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
1591da20b47c2b85390a2c3772379e71203c5aab513cGary Mai     * Returns the editor view that should be used as the anchor for aggregation suggestions.
15927b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
1593da20b47c2b85390a2c3772379e71203c5aab513cGary Mai    protected View getAggregationAnchorView() {
1594d35e5eff8737e757a4179d49dfe9c7db999b4e9dWalter Jang        return getContent().getAggregationAnchorView();
1595d35e5eff8737e757a4179d49dfe9c7db999b4e9dWalter Jang    }
1596d35e5eff8737e757a4179d49dfe9c7db999b4e9dWalter Jang
15977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
15987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Joins the suggested contact (specified by the id's of constituent raw
15997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * contacts), save all changes, and stay in the editor.
16007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
16017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void doJoinSuggestedContact(long[] rawContactIds) {
16027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (!hasValidState() || mStatus != Status.EDITING) {
16037b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return;
16047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
16057b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
16067b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mState.setJoinWithRawContacts(rawContactIds);
16077b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        save(SaveMode.RELOAD);
16087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
16097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
16107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
1611678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai    public void onEditAction(Uri contactLookupUri, long rawContactId) {
1612678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai        SuggestionEditConfirmationDialogFragment.show(this, contactLookupUri, rawContactId);
16137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
16147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
16157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
1616678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai     * Abandons the currently edited contact and switches to editing the selected raw contact,
1617678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai     * transferring all the data there
16187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
1619678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai    public void doEditSuggestedContact(Uri contactUri, long rawContactId) {
16207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mListener != null) {
16217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // make sure we don't save this contact when closing down
16227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mStatus = Status.CLOSING;
1623678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai            mListener.onEditOtherRawContactRequested(contactUri, rawContactId,
1624678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai                    getContent().getCurrentRawContactDelta().getContentValues());
16257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
16267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
16277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
16287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
16297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Sets group metadata on all bound editors.
16307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
163192f8ccc1f15df787b7434224857c056721281046Walter Jang    protected void setGroupMetaData() {
1632f10ca15ffa550b36805d2330fc210b58601a215cWalter Jang        if (mGroupMetaData != null) {
1633f10ca15ffa550b36805d2330fc210b58601a215cWalter Jang            getContent().setGroupMetaData(mGroupMetaData);
1634f10ca15ffa550b36805d2330fc210b58601a215cWalter Jang        }
16353f990ba4e35a99078d831c041290e574a320caa5Walter Jang    }
16363f990ba4e35a99078d831c041290e574a320caa5Walter Jang
16377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
16387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Persist the accumulated editor deltas.
16397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     *
16407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * @param joinContactId the raw contact ID to join the contact being saved to after the save,
16417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     *         may be null.
16427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
1643e3373dceb689209533e95a2cfbfbf1d9008ab6f6Walter Jang    protected boolean doSaveAction(int saveMode, Long joinContactId) {
164449ed2033f83005f92c30068ae33c3138d75e1825Walter Jang        final Intent intent = ContactSaveService.createSaveContactIntent(mContext, mState,
164549ed2033f83005f92c30068ae33c3138d75e1825Walter Jang                SAVE_MODE_EXTRA_KEY, saveMode, isEditingUserProfile(),
164649ed2033f83005f92c30068ae33c3138d75e1825Walter Jang                ((Activity) mContext).getClass(),
1647363af60ea23e5a3b945005712a16564ab69db18bGary Mai                ContactEditorActivity.ACTION_SAVE_COMPLETED, mUpdatedPhotos,
1648e3373dceb689209533e95a2cfbfbf1d9008ab6f6Walter Jang                JOIN_CONTACT_ID_EXTRA_KEY, joinContactId);
1649dd7d456a080f48d93aa3a9f9b04da0f17a8833a7Wenyi Wang        return startSaveService(mContext, intent, saveMode);
165049ed2033f83005f92c30068ae33c3138d75e1825Walter Jang    }
165149ed2033f83005f92c30068ae33c3138d75e1825Walter Jang
16527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private boolean startSaveService(Context context, Intent intent, int saveMode) {
16537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final boolean result = ContactSaveService.startService(
16547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                context, intent, saveMode);
16557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (!result) {
16567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            onCancelEditConfirmed();
16577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
16587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return result;
16597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
16607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
16617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
16627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Join Activity
16637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
16647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
16657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
16667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Performs aggregation with the contact selected by the user from suggestions or A-Z list.
16677b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
166849ed2033f83005f92c30068ae33c3138d75e1825Walter Jang    protected void joinAggregate(final long contactId) {
166949ed2033f83005f92c30068ae33c3138d75e1825Walter Jang        final Intent intent = ContactSaveService.createJoinContactsIntent(
1670363af60ea23e5a3b945005712a16564ab69db18bGary Mai                mContext, mContactIdForJoin, contactId, ContactEditorActivity.class,
1671363af60ea23e5a3b945005712a16564ab69db18bGary Mai                ContactEditorActivity.ACTION_JOIN_COMPLETED);
167249ed2033f83005f92c30068ae33c3138d75e1825Walter Jang        mContext.startService(intent);
16733f990ba4e35a99078d831c041290e574a320caa5Walter Jang    }
1674b6ca272f26b47ecef8fafe94326c4d553576c521Walter Jang
167531a74ad969b650eb733e536569254ed3978c4f54Walter Jang    public void removePhoto() {
167631a74ad969b650eb733e536569254ed3978c4f54Walter Jang        getContent().removePhoto();
167731a74ad969b650eb733e536569254ed3978c4f54Walter Jang        mUpdatedPhotos.remove(String.valueOf(mPhotoRawContactId));
16780e72ce9d97e0133a5f7cc348eef363bef9395979Walter Jang    }
16790e72ce9d97e0133a5f7cc348eef363bef9395979Walter Jang
168031a74ad969b650eb733e536569254ed3978c4f54Walter Jang    public void updatePhoto(Uri uri) throws FileNotFoundException {
168131a74ad969b650eb733e536569254ed3978c4f54Walter Jang        final Bitmap bitmap = ContactPhotoUtils.getBitmapFromUri(getActivity(), uri);
168231a74ad969b650eb733e536569254ed3978c4f54Walter Jang        if (bitmap == null || bitmap.getHeight() <= 0 || bitmap.getWidth() <= 0) {
16839bc9ba878cf7f77a2a6b3200a6ab716d13f1affcWenyi Wang            Toast.makeText(mContext, R.string.contactPhotoSavedErrorToast,
168431a74ad969b650eb733e536569254ed3978c4f54Walter Jang                    Toast.LENGTH_SHORT).show();
168531a74ad969b650eb733e536569254ed3978c4f54Walter Jang            return;
16860e72ce9d97e0133a5f7cc348eef363bef9395979Walter Jang        }
168731a74ad969b650eb733e536569254ed3978c4f54Walter Jang        mUpdatedPhotos.putParcelable(String.valueOf(mPhotoRawContactId), uri);
168831a74ad969b650eb733e536569254ed3978c4f54Walter Jang        getContent().updatePhoto(uri);
16890e72ce9d97e0133a5f7cc348eef363bef9395979Walter Jang    }
16900e72ce9d97e0133a5f7cc348eef363bef9395979Walter Jang
1691da20b47c2b85390a2c3772379e71203c5aab513cGary Mai    public void setPrimaryPhoto() {
1692da20b47c2b85390a2c3772379e71203c5aab513cGary Mai        getContent().setPrimaryPhoto();
16930e72ce9d97e0133a5f7cc348eef363bef9395979Walter Jang    }
16940e72ce9d97e0133a5f7cc348eef363bef9395979Walter Jang
16950e72ce9d97e0133a5f7cc348eef363bef9395979Walter Jang    @Override
1696151f3e6883e5785019f7b5083dc8baf3e305dc18Walter Jang    public void onNameFieldChanged(long rawContactId, ValuesDelta valuesDelta) {
1697151f3e6883e5785019f7b5083dc8baf3e305dc18Walter Jang        final Activity activity = getActivity();
1698151f3e6883e5785019f7b5083dc8baf3e305dc18Walter Jang        if (activity == null || activity.isFinishing()) {
1699151f3e6883e5785019f7b5083dc8baf3e305dc18Walter Jang            return;
1700151f3e6883e5785019f7b5083dc8baf3e305dc18Walter Jang        }
170145b86d5e83a7d6eca4abe5cdfece2e9050b1809cWalter Jang        acquireAggregationSuggestions(activity, rawContactId, valuesDelta);
1702151f3e6883e5785019f7b5083dc8baf3e305dc18Walter Jang    }
1703151f3e6883e5785019f7b5083dc8baf3e305dc18Walter Jang
17045a7a23bdb698b8e741a425c9617c5e33e6314cddWalter Jang    @Override
1705708ea9e6f6f671178c0424f89e911000d4f330dcWalter Jang    public void onRebindEditorsForNewContact(RawContactDelta oldState,
1706708ea9e6f6f671178c0424f89e911000d4f330dcWalter Jang            AccountWithDataSet oldAccount, AccountWithDataSet newAccount) {
1707708ea9e6f6f671178c0424f89e911000d4f330dcWalter Jang        mNewContactAccountChanged = true;
1708708ea9e6f6f671178c0424f89e911000d4f330dcWalter Jang        rebindEditorsForNewContact(oldState, oldAccount, newAccount);
1709708ea9e6f6f671178c0424f89e911000d4f330dcWalter Jang    }
1710708ea9e6f6f671178c0424f89e911000d4f330dcWalter Jang
171179658e14360a4ec75530a9dcae338f48c9d5f043Walter Jang    @Override
171279658e14360a4ec75530a9dcae338f48c9d5f043Walter Jang    public void onBindEditorsFailed() {
171379658e14360a4ec75530a9dcae338f48c9d5f043Walter Jang        final Activity activity = getActivity();
171479658e14360a4ec75530a9dcae338f48c9d5f043Walter Jang        if (activity != null && !activity.isFinishing()) {
1715363af60ea23e5a3b945005712a16564ab69db18bGary Mai            Toast.makeText(activity, R.string.editor_failed_to_load,
171679658e14360a4ec75530a9dcae338f48c9d5f043Walter Jang                    Toast.LENGTH_SHORT).show();
171779658e14360a4ec75530a9dcae338f48c9d5f043Walter Jang            activity.setResult(Activity.RESULT_CANCELED);
171879658e14360a4ec75530a9dcae338f48c9d5f043Walter Jang            activity.finish();
171979658e14360a4ec75530a9dcae338f48c9d5f043Walter Jang        }
172079658e14360a4ec75530a9dcae338f48c9d5f043Walter Jang    }
172179658e14360a4ec75530a9dcae338f48c9d5f043Walter Jang
1722d675315606e8be431e6e5487e0b1cc33036a6ed7Walter Jang    @Override
1723d675315606e8be431e6e5487e0b1cc33036a6ed7Walter Jang    public void onEditorsBound() {
17243cb77bbf7119749ed4854a4b981fcabcf55823beWenyi Wang        final Activity activity = getActivity();
17253cb77bbf7119749ed4854a4b981fcabcf55823beWenyi Wang        if (activity == null || activity.isFinishing()) {
17263cb77bbf7119749ed4854a4b981fcabcf55823beWenyi Wang            return;
17273cb77bbf7119749ed4854a4b981fcabcf55823beWenyi Wang        }
1728d675315606e8be431e6e5487e0b1cc33036a6ed7Walter Jang        getLoaderManager().initLoader(LOADER_GROUPS, null, mGroupsLoaderListener);
1729d675315606e8be431e6e5487e0b1cc33036a6ed7Walter Jang    }
1730d675315606e8be431e6e5487e0b1cc33036a6ed7Walter Jang
173131a74ad969b650eb733e536569254ed3978c4f54Walter Jang    @Override
173231a74ad969b650eb733e536569254ed3978c4f54Walter Jang    public void onPhotoEditorViewClicked() {
17333f18d6197a54aad10bea9c5cc2c89ca82809e793Walter Jang        // For contacts composed of a single writable raw contact, or raw contacts have no more
17343f18d6197a54aad10bea9c5cc2c89ca82809e793Walter Jang        // than 1 photo, clicking the photo view simply opens the source photo dialog
173531a74ad969b650eb733e536569254ed3978c4f54Walter Jang        getEditorActivity().changePhoto(getPhotoMode());
173631a74ad969b650eb733e536569254ed3978c4f54Walter Jang    }
173731a74ad969b650eb733e536569254ed3978c4f54Walter Jang
173831a74ad969b650eb733e536569254ed3978c4f54Walter Jang    private int getPhotoMode() {
1739da20b47c2b85390a2c3772379e71203c5aab513cGary Mai        return getContent().isWritablePhotoSet() ? PhotoActionPopup.Modes.WRITE_ABLE_PHOTO
1740da20b47c2b85390a2c3772379e71203c5aab513cGary Mai                : PhotoActionPopup.Modes.NO_PHOTO;
174131a74ad969b650eb733e536569254ed3978c4f54Walter Jang    }
174231a74ad969b650eb733e536569254ed3978c4f54Walter Jang
1743363af60ea23e5a3b945005712a16564ab69db18bGary Mai    private ContactEditorActivity getEditorActivity() {
1744363af60ea23e5a3b945005712a16564ab69db18bGary Mai        return (ContactEditorActivity) getActivity();
174531a74ad969b650eb733e536569254ed3978c4f54Walter Jang    }
174631a74ad969b650eb733e536569254ed3978c4f54Walter Jang
1747363af60ea23e5a3b945005712a16564ab69db18bGary Mai    private RawContactEditorView getContent() {
1748363af60ea23e5a3b945005712a16564ab69db18bGary Mai        return (RawContactEditorView) mContent;
17493efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    }
17503f990ba4e35a99078d831c041290e574a320caa5Walter Jang}
1751