ContactEditorFragment.java revision 8d26c0a7214cf6520a4def851afa138a133a68a2
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;
660a49afa2ad697307cc04ef4cb86570574fa720f2Gary Maiimport com.android.contacts.editor.AggregationSuggestionEngine.Suggestion;
670a49afa2ad697307cc04ef4cb86570574fa720f2Gary Maiimport com.android.contacts.group.GroupUtil;
680a49afa2ad697307cc04ef4cb86570574fa720f2Gary Maiimport com.android.contacts.list.UiIntentActions;
6969c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.logging.ScreenEvent.ScreenType;
7069c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.AccountTypeManager;
7169c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.Contact;
7269c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.ContactLoader;
7369c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.RawContact;
7469c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.RawContactDelta;
7569c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.RawContactDeltaList;
7669c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.RawContactModifier;
7769c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.ValuesDelta;
784bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerottimport com.android.contacts.model.account.AccountInfo;
7969c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.account.AccountType;
8069c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.account.AccountWithDataSet;
814bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerottimport com.android.contacts.model.account.AccountsLoader;
8269c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.preference.ContactsPreferences;
83e48746654178e9448819f86b3129fd32f539b3c9Gary Maiimport com.android.contacts.quickcontact.InvisibleContactUtil;
847b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport com.android.contacts.quickcontact.QuickContactActivity;
850a49afa2ad697307cc04ef4cb86570574fa720f2Gary Maiimport com.android.contacts.util.ContactDisplayUtils;
867b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport com.android.contacts.util.ContactPhotoUtils;
870a49afa2ad697307cc04ef4cb86570574fa720f2Gary Maiimport com.android.contacts.util.ImplicitIntentsUtil;
880a49afa2ad697307cc04ef4cb86570574fa720f2Gary Maiimport com.android.contacts.util.MaterialColorMapUtils;
897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport com.android.contacts.util.UiClosables;
90a4adae163d83db9226b831f8c9705914e68b5cd1Gary Maiimport com.android.contactsbind.HelpUtils;
918d26c0a7214cf6520a4def851afa138a133a68a2Walter Jang
92807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerottimport com.google.common.base.Preconditions;
937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport com.google.common.collect.ImmutableList;
947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport com.google.common.collect.Lists;
957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
963efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jangimport java.io.FileNotFoundException;
9731a74ad969b650eb733e536569254ed3978c4f54Walter Jangimport java.util.ArrayList;
984bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerottimport java.util.Collections;
997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport java.util.HashSet;
1007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport java.util.Iterator;
1017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport java.util.List;
1027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jangimport java.util.Set;
1033efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
1043f990ba4e35a99078d831c041290e574a320caa5Walter Jang/**
1053f990ba4e35a99078d831c041290e574a320caa5Walter Jang * Contact editor with only the most important fields displayed initially.
1063f990ba4e35a99078d831c041290e574a320caa5Walter Jang */
107363af60ea23e5a3b945005712a16564ab69db18bGary Maipublic class ContactEditorFragment extends Fragment implements
1087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        ContactEditor, SplitContactConfirmationDialogFragment.Listener,
1097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        JoinContactConfirmationDialogFragment.Listener,
1107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        AggregationSuggestionEngine.Listener, AggregationSuggestionView.Listener,
1117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        CancelEditDialogFragment.Listener,
1128c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott        RawContactEditorView.Listener, PhotoEditorView.Listener,
1138c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott        AccountsLoader.AccountsListener {
1143f990ba4e35a99078d831c041290e574a320caa5Walter Jang
1157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    static final String TAG = "ContactEditor";
1167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final int LOADER_CONTACT = 1;
1187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final int LOADER_GROUPS = 2;
1194bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott    private static final int LOADER_ACCOUNTS = 3;
1207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1213efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    private static final String KEY_PHOTO_RAW_CONTACT_ID = "photo_raw_contact_id";
12228a27279554af7b1e5ff664d3da97954c462a797Walter Jang    private static final String KEY_UPDATED_PHOTOS = "updated_photos";
1233efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
1247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final List<String> VALID_INTENT_ACTIONS = new ArrayList<String>() {{
1257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        add(Intent.ACTION_EDIT);
1267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        add(Intent.ACTION_INSERT);
127363af60ea23e5a3b945005712a16564ab69db18bGary Mai        add(ContactEditorActivity.ACTION_SAVE_COMPLETED);
1287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }};
1297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_ACTION = "action";
1317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_URI = "uri";
1327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_AUTO_ADD_TO_DEFAULT_GROUP = "autoAddToDefaultGroup";
1337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_DISABLE_DELETE_MENU_OPTION = "disableDeleteMenuOption";
1347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_NEW_LOCAL_PROFILE = "newLocalProfile";
1357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_MATERIAL_PALETTE = "materialPalette";
136c135a5d502130aee06ffcc11170513053396e9b0Gary Mai    private static final String KEY_ACCOUNT = "saveToAccount";
1377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_VIEW_ID_GENERATOR = "viewidgenerator";
1387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_RAW_CONTACTS = "rawContacts";
1407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_EDIT_STATE = "state";
1427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_STATUS = "status";
1437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_HAS_NEW_CONTACT = "hasNewContact";
1457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_NEW_CONTACT_READY = "newContactDataReady";
1467b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_IS_EDIT = "isEdit";
1487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_EXISTING_CONTACT_READY = "existingContactDataReady";
1497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_IS_USER_PROFILE = "isUserProfile";
1517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_ENABLED = "enabled";
1537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Aggregation PopupWindow
1557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_AGGREGATION_SUGGESTIONS_RAW_CONTACT_ID =
1567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            "aggregationSuggestionsRawContactId";
1577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Join Activity
1597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final String KEY_CONTACT_ID_FOR_JOIN = "contactidforjoin";
1607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
161698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai    private static final String KEY_READ_ONLY_DISPLAY_NAME_ID = "readOnlyDisplayNameId";
162698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai    private static final String KEY_COPY_READ_ONLY_DISPLAY_NAME = "copyReadOnlyDisplayName";
1637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected static final int REQUEST_CODE_JOIN = 0;
1657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected static final int REQUEST_CODE_ACCOUNTS_CHANGED = 1;
1667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1677b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
1687b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * An intent extra that forces the editor to add the edited contact
1697b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * to the default group (e.g. "My Contacts").
1707b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
1717b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public static final String INTENT_EXTRA_ADD_TO_DEFAULT_DIRECTORY = "addToDefaultDirectory";
1727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public static final String INTENT_EXTRA_NEW_LOCAL_PROFILE = "newLocalProfile";
1747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public static final String INTENT_EXTRA_DISABLE_DELETE_MENU_OPTION =
1767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            "disableDeleteMenuOption";
1777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
1797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Intent key to pass the photo palette primary color calculated by
180363af60ea23e5a3b945005712a16564ab69db18bGary Mai     * {@link com.android.contacts.quickcontact.QuickContactActivity} to the editor.
1817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
1827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public static final String INTENT_EXTRA_MATERIAL_PALETTE_PRIMARY_COLOR =
1837b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            "material_palette_primary_color";
1847b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
1867b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Intent key to pass the photo palette secondary color calculated by
187363af60ea23e5a3b945005712a16564ab69db18bGary Mai     * {@link com.android.contacts.quickcontact.QuickContactActivity} to the editor.
1887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
1897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public static final String INTENT_EXTRA_MATERIAL_PALETTE_SECONDARY_COLOR =
1907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            "material_palette_secondary_color";
1917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1927b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
1937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Intent key to pass the ID of the photo to display on the editor.
1947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
195da20b47c2b85390a2c3772379e71203c5aab513cGary Mai    // TODO: This can be cleaned up if we decide to not pass the photo id through
196da20b47c2b85390a2c3772379e71203c5aab513cGary Mai    // QuickContactActivity.
1977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public static final String INTENT_EXTRA_PHOTO_ID = "photo_id";
1987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
200a6c80b378e03ebdf6b654dbdb12f2c665fe98a80Gary Mai     * Intent key to pass the ID of the raw contact id that should be displayed in the full editor
201a6c80b378e03ebdf6b654dbdb12f2c665fe98a80Gary Mai     * by itself.
202a6c80b378e03ebdf6b654dbdb12f2c665fe98a80Gary Mai     */
203a6c80b378e03ebdf6b654dbdb12f2c665fe98a80Gary Mai    public static final String INTENT_EXTRA_RAW_CONTACT_ID_TO_DISPLAY_ALONE =
204a6c80b378e03ebdf6b654dbdb12f2c665fe98a80Gary Mai            "raw_contact_id_to_display_alone";
205a6c80b378e03ebdf6b654dbdb12f2c665fe98a80Gary Mai
206a6c80b378e03ebdf6b654dbdb12f2c665fe98a80Gary Mai    /**
2077b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Intent extra to specify a {@link ContactEditor.SaveMode}.
2087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
2097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public static final String SAVE_MODE_EXTRA_KEY = "saveMode";
2107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
2127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Intent extra key for the contact ID to join the current contact to after saving.
2137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
2147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public static final String JOIN_CONTACT_ID_EXTRA_KEY = "joinContactId";
2157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
2177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Callbacks for Activities that host contact editors Fragments.
2187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
2197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public interface Listener {
2207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        /**
2227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         * Contact was not found, so somehow close this fragment. This is raised after a contact
2237b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         * is removed via Menu/Delete
2247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         */
2257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        void onContactNotFound();
2267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        /**
2287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         * Contact was split, so we can close now.
2297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         *
2307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         * @param newLookupUri The lookup uri of the new contact that should be shown to the user.
2317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         *                     The editor tries best to chose the most natural contact here.
2327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         */
2337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        void onContactSplit(Uri newLookupUri);
2347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        /**
2367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         * User has tapped Revert, close the fragment now.
2377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         */
2387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        void onReverted();
2397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        /**
2417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         * Contact was saved and the Fragment can now be closed safely.
2427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         */
2437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        void onSaveFinished(Intent resultIntent);
2447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        /**
246678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai         * User switched to editing a different raw contact (a suggestion from the
2477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         * aggregation engine).
2487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         */
249678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai        void onEditOtherRawContactRequested(Uri contactLookupUri, long rawContactId,
2507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                ArrayList<ContentValues> contentValues);
2517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        /**
2537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         * User has requested that contact be deleted.
2547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang         */
2557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        void onDeleteRequested(Uri contactUri);
2567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
2577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
2597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Adapter for aggregation suggestions displayed in a PopupWindow when
2607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * editor fields change.
2617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
2627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static final class AggregationSuggestionAdapter extends BaseAdapter {
2637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        private final LayoutInflater mLayoutInflater;
2647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        private final AggregationSuggestionView.Listener mListener;
2657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        private final List<AggregationSuggestionEngine.Suggestion> mSuggestions;
2667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
267678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai        public AggregationSuggestionAdapter(Activity activity,
2687b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                AggregationSuggestionView.Listener listener, List<Suggestion> suggestions) {
2697b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mLayoutInflater = activity.getLayoutInflater();
2707b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mListener = listener;
2717b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mSuggestions = suggestions;
2727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
2737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        @Override
2757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        public View getView(int position, View convertView, ViewGroup parent) {
2767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            final Suggestion suggestion = (Suggestion) getItem(position);
2777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            final AggregationSuggestionView suggestionView =
2787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    (AggregationSuggestionView) mLayoutInflater.inflate(
2797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                            R.layout.aggregation_suggestions_item, null);
2807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            suggestionView.setListener(mListener);
2817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            suggestionView.bindSuggestion(suggestion);
2827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return suggestionView;
2837b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
2847b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        @Override
2867b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        public long getItemId(int position) {
2877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return position;
2887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
2897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        @Override
2917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        public Object getItem(int position) {
2927b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return mSuggestions.get(position);
2937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
2947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
2957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        @Override
2967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        public int getCount() {
2977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return mSuggestions.size();
2987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
2997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
3007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected Context mContext;
3027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected Listener mListener;
3037b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
3057b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Views
3067b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
3077b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected LinearLayout mContent;
3087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected ListPopupWindow mAggregationSuggestionPopup;
3097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
3117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Parameters passed in on {@link #load}
3127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
3137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected String mAction;
3147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected Uri mLookupUri;
3157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected Bundle mIntentExtras;
3167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected boolean mAutoAddToDefaultGroup;
3177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected boolean mDisableDeleteMenuOption;
3187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected boolean mNewLocalProfile;
3197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected MaterialColorMapUtils.MaterialPalette mMaterialPalette;
3207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
3227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Helpers
3237b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
3247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected ContactEditorUtils mEditorUtils;
3257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected RawContactDeltaComparator mComparator;
3267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected ViewIdGenerator mViewIdGenerator;
3277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private AggregationSuggestionEngine mAggregationSuggestionEngine;
3287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
3307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Loaded data
3317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
3327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Used to store existing contact data so it can be re-applied during a rebind call,
3337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // i.e. account switch.
3347b75145e9b4fcd46c3cbb5678f8842934467b3aaGary Mai    protected Contact mContact;
3357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected ImmutableList<RawContact> mRawContacts;
3367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected Cursor mGroupMetaData;
3377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
3397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Editor state
3407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
3417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected RawContactDeltaList mState;
3427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected int mStatus;
3437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected long mRawContactIdToDisplayAlone = -1;
3447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Whether to show the new contact blank form and if it's corresponding delta is ready.
3467b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected boolean mHasNewContact;
3477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected AccountWithDataSet mAccountWithDataSet;
3484bd50d69d2b8934dbd4cbd634ad83807d9b02735Marcus Hagerott    protected List<AccountInfo> mWritableAccounts = Collections.emptyList();
3497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected boolean mNewContactDataReady;
3507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected boolean mNewContactAccountChanged;
3517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Whether it's an edit of existing contact and if it's corresponding delta is ready.
3537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected boolean mIsEdit;
3547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected boolean mExistingContactDataReady;
3557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Whether we are editing the "me" profile
3577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected boolean mIsUserProfile;
3587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Whether editor views and options menu items should be enabled
3607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private boolean mEnabled = true;
3617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Aggregation PopupWindow
3637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private long mAggregationSuggestionsRawContactId;
3647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Join Activity
3667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected long mContactIdForJoin;
3677b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3687b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Used to pre-populate the editor with a display name when a user edits a read-only contact.
369698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai    protected long mReadOnlyDisplayNameId;
370698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai    protected boolean mCopyReadOnlyName;
3717b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
3737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * The contact data loader listener.
3747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
3757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected final LoaderManager.LoaderCallbacks<Contact> mContactLoaderListener =
3767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            new LoaderManager.LoaderCallbacks<Contact>() {
3777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                protected long mLoaderStartTime;
3797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                @Override
3817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                public Loader<Contact> onCreateLoader(int id, Bundle args) {
3827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mLoaderStartTime = SystemClock.elapsedRealtime();
383e48746654178e9448819f86b3129fd32f539b3c9Gary Mai                    return new ContactLoader(mContext, mLookupUri,
384e48746654178e9448819f86b3129fd32f539b3c9Gary Mai                            /* postViewNotification */ true,
385e48746654178e9448819f86b3129fd32f539b3c9Gary Mai                            /* loadGroupMetaData */ true);
3867b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
3877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
3887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                @Override
3897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                public void onLoadFinished(Loader<Contact> loader, Contact contact) {
3907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    final long loaderCurrentTime = SystemClock.elapsedRealtime();
3917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    Log.v(TAG, "Time needed for loading: " + (loaderCurrentTime-mLoaderStartTime));
3927b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    if (!contact.isLoaded()) {
3937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        // Item has been deleted. Close activity without saving again.
3947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        Log.i(TAG, "No contact found. Closing activity");
3957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        mStatus = Status.CLOSING;
3967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        if (mListener != null) mListener.onContactNotFound();
3977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        return;
3987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    }
3997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mStatus = Status.EDITING;
4017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mLookupUri = contact.getLookupUri();
4027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    final long setDataStartTime = SystemClock.elapsedRealtime();
4037b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    setState(contact);
4047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    final long setDataEndTime = SystemClock.elapsedRealtime();
4057b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4067b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    Log.v(TAG, "Time needed for setting UI: " + (setDataEndTime - setDataStartTime));
4077b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
4087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                @Override
4107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                public void onLoaderReset(Loader<Contact> loader) {
4117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
4127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            };
4137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
4157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * The groups meta data loader listener.
4167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
4177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected final LoaderManager.LoaderCallbacks<Cursor> mGroupsLoaderListener =
4187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            new LoaderManager.LoaderCallbacks<Cursor>() {
4197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                @Override
4217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                public CursorLoader onCreateLoader(int id, Bundle args) {
4225c1bff2efa542ea112c3f2a1d1ed1e271c7691a7Gary Mai                    return new GroupMetaDataLoader(mContext, ContactsContract.Groups.CONTENT_URI,
4235c1bff2efa542ea112c3f2a1d1ed1e271c7691a7Gary Mai                            GroupUtil.ALL_GROUPS_SELECTION);
4247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
4257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                @Override
4277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
4287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mGroupMetaData = data;
4297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    setGroupMetaData();
4307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
4317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                @Override
4337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                public void onLoaderReset(Loader<Cursor> loader) {
4347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
4357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            };
4367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4373efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    private long mPhotoRawContactId;
43828a27279554af7b1e5ff664d3da97954c462a797Walter Jang    private Bundle mUpdatedPhotos = new Bundle();
4393efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
4403efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    @Override
4417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public Context getContext() {
4427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return getActivity();
4437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
4447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
4467b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onAttach(Activity activity) {
4477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        super.onAttach(activity);
4487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mContext = activity;
449a7978d5bc3fcbe62a40e59e29aebea668385a98aMarcus Hagerott        mEditorUtils = ContactEditorUtils.create(mContext);
4507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mComparator = new RawContactDeltaComparator(mContext);
4517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
4527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
4543efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    public void onCreate(Bundle savedState) {
4557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (savedState != null) {
4567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Restore mUri before calling super.onCreate so that onInitializeLoaders
4577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // would already have a uri and an action to work with
4587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mAction = savedState.getString(KEY_ACTION);
4597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mLookupUri = savedState.getParcelable(KEY_URI);
4607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
4617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4623efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang        super.onCreate(savedState);
4633efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
4647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (savedState == null) {
4657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mViewIdGenerator = new ViewIdGenerator();
4667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4677b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // mState can still be null because it may not have have finished loading before
4687b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // onSaveInstanceState was called.
4697b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mState = new RawContactDeltaList();
4707b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        } else {
4717b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mViewIdGenerator = savedState.getParcelable(KEY_VIEW_ID_GENERATOR);
4727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mAutoAddToDefaultGroup = savedState.getBoolean(KEY_AUTO_ADD_TO_DEFAULT_GROUP);
4747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mDisableDeleteMenuOption = savedState.getBoolean(KEY_DISABLE_DELETE_MENU_OPTION);
4757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mNewLocalProfile = savedState.getBoolean(KEY_NEW_LOCAL_PROFILE);
4767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mMaterialPalette = savedState.getParcelable(KEY_MATERIAL_PALETTE);
477c135a5d502130aee06ffcc11170513053396e9b0Gary Mai            mAccountWithDataSet = savedState.getParcelable(KEY_ACCOUNT);
4787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mRawContacts = ImmutableList.copyOf(savedState.<RawContact>getParcelableArrayList(
4797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    KEY_RAW_CONTACTS));
4807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // NOTE: mGroupMetaData is not saved/restored
4817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Read state from savedState. No loading involved here
4837b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mState = savedState.<RawContactDeltaList> getParcelable(KEY_EDIT_STATE);
4847b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mStatus = savedState.getInt(KEY_STATUS);
4857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4867b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mHasNewContact = savedState.getBoolean(KEY_HAS_NEW_CONTACT);
4877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mNewContactDataReady = savedState.getBoolean(KEY_NEW_CONTACT_READY);
4887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mIsEdit = savedState.getBoolean(KEY_IS_EDIT);
4907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mExistingContactDataReady = savedState.getBoolean(KEY_EXISTING_CONTACT_READY);
4917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4927b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mIsUserProfile = savedState.getBoolean(KEY_IS_USER_PROFILE);
4937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mEnabled = savedState.getBoolean(KEY_ENABLED);
4957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
4967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Aggregation PopupWindow
4977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mAggregationSuggestionsRawContactId = savedState.getLong(
4987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    KEY_AGGREGATION_SUGGESTIONS_RAW_CONTACT_ID);
4997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
5007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Join Activity
5017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mContactIdForJoin = savedState.getLong(KEY_CONTACT_ID_FOR_JOIN);
5027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
503698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            mReadOnlyDisplayNameId = savedState.getLong(KEY_READ_ONLY_DISPLAY_NAME_ID);
504698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            mCopyReadOnlyName = savedState.getBoolean(KEY_COPY_READ_ONLY_DISPLAY_NAME, false);
5057b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
5063efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang            mPhotoRawContactId = savedState.getLong(KEY_PHOTO_RAW_CONTACT_ID);
50728a27279554af7b1e5ff664d3da97954c462a797Walter Jang            mUpdatedPhotos = savedState.getParcelable(KEY_UPDATED_PHOTOS);
5083efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang        }
5093efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    }
5103efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
5113f990ba4e35a99078d831c041290e574a320caa5Walter Jang    @Override
5123f990ba4e35a99078d831c041290e574a320caa5Walter Jang    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
513ed8f6c9744dd38e089598acfba6fb90446954e6eWalter Jang        setHasOptionsMenu(true);
514ed8f6c9744dd38e089598acfba6fb90446954e6eWalter Jang
5153f990ba4e35a99078d831c041290e574a320caa5Walter Jang        final View view = inflater.inflate(
516363af60ea23e5a3b945005712a16564ab69db18bGary Mai                R.layout.contact_editor_fragment, container, false);
517f5dfea4a5c94382a632eae5c538881f7da726a50Walter Jang        mContent = (LinearLayout) view.findViewById(R.id.raw_contacts_editor_view);
5183f990ba4e35a99078d831c041290e574a320caa5Walter Jang        return view;
5193f990ba4e35a99078d831c041290e574a320caa5Walter Jang    }
5203f990ba4e35a99078d831c041290e574a320caa5Walter Jang
521ed8f6c9744dd38e089598acfba6fb90446954e6eWalter Jang    @Override
5227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onActivityCreated(Bundle savedInstanceState) {
5237b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        super.onActivityCreated(savedInstanceState);
5247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
5257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        validateAction(mAction);
5267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
5277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mState.isEmpty()) {
5287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // The delta list may not have finished loading before orientation change happens.
5297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // In this case, there will be a saved state but deltas will be missing.  Reload from
5307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // database.
5317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            if (Intent.ACTION_EDIT.equals(mAction)) {
5327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // Either
5337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // 1) orientation change but load never finished.
5347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // 2) not an orientation change so data needs to be loaded for first time.
5357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                getLoaderManager().initLoader(LOADER_CONTACT, null, mContactLoaderListener);
5367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                getLoaderManager().initLoader(LOADER_GROUPS, null, mGroupsLoaderListener);
5377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
5387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        } else {
5397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Orientation change, we already have mState, it was loaded by onCreate
5407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            bindEditors();
5417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
5427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
5437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // Handle initial actions only when existing state missing
5447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (savedInstanceState == null) {
545807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott            if (mIntentExtras != null) {
546807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott                final Account account = mIntentExtras == null ? null :
547807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott                        (Account) mIntentExtras.getParcelable(Intents.Insert.EXTRA_ACCOUNT);
548807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott                final String dataSet = mIntentExtras == null ? null :
549807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott                        mIntentExtras.getString(Intents.Insert.EXTRA_DATA_SET);
550807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott                mAccountWithDataSet = account != null
551807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott                        ? new AccountWithDataSet(account.name, account.type, dataSet)
552807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott                        : mIntentExtras.<AccountWithDataSet>getParcelable(
553807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott                                ContactEditorActivity.EXTRA_ACCOUNT_WITH_DATA_SET);
5547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
5557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
5567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            if (Intent.ACTION_EDIT.equals(mAction)) {
5577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                mIsEdit = true;
5587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            } else if (Intent.ACTION_INSERT.equals(mAction)) {
5597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                mHasNewContact = true;
5607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (mAccountWithDataSet != null) {
5617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    createContact(mAccountWithDataSet);
562807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott                } // else wait for accounts to be loaded
5637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
5647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
565807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott
566807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott        if (mHasNewContact) {
5678c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott            AccountsLoader.loadAccounts(this, LOADER_ACCOUNTS, AccountTypeManager.writableFilter());
568807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott        }
5697b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
5707b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
5717b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
5727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Checks if the requested action is valid.
5737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     *
5747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * @param action The action to test.
5757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * @throws IllegalArgumentException when the action is invalid.
5767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
5777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static void validateAction(String action) {
5787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (VALID_INTENT_ACTIONS.contains(action)) {
5797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return;
5807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
5817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        throw new IllegalArgumentException(
5827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                "Unknown action " + action + "; Supported actions: " + VALID_INTENT_ACTIONS);
5837b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
5847b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
5857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
5863efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    public void onSaveInstanceState(Bundle outState) {
5877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putString(KEY_ACTION, mAction);
5887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putParcelable(KEY_URI, mLookupUri);
5897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putBoolean(KEY_AUTO_ADD_TO_DEFAULT_GROUP, mAutoAddToDefaultGroup);
5907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putBoolean(KEY_DISABLE_DELETE_MENU_OPTION, mDisableDeleteMenuOption);
5917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putBoolean(KEY_NEW_LOCAL_PROFILE, mNewLocalProfile);
5927b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mMaterialPalette != null) {
5937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            outState.putParcelable(KEY_MATERIAL_PALETTE, mMaterialPalette);
5947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
5957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putParcelable(KEY_VIEW_ID_GENERATOR, mViewIdGenerator);
5967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
5977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putParcelableArrayList(KEY_RAW_CONTACTS, mRawContacts == null ?
5987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                Lists.<RawContact>newArrayList() : Lists.newArrayList(mRawContacts));
5997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // NOTE: mGroupMetaData is not saved
6007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
60136ceb4235ed685a222af86076dcf160ba124a583Gary Mai        outState.putParcelable(KEY_EDIT_STATE, mState);
6027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putInt(KEY_STATUS, mStatus);
6037b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putBoolean(KEY_HAS_NEW_CONTACT, mHasNewContact);
6047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putBoolean(KEY_NEW_CONTACT_READY, mNewContactDataReady);
6057b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putBoolean(KEY_IS_EDIT, mIsEdit);
6067b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putBoolean(KEY_EXISTING_CONTACT_READY, mExistingContactDataReady);
607c135a5d502130aee06ffcc11170513053396e9b0Gary Mai        outState.putParcelable(KEY_ACCOUNT, mAccountWithDataSet);
6087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putBoolean(KEY_IS_USER_PROFILE, mIsUserProfile);
6097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
6107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putBoolean(KEY_ENABLED, mEnabled);
6117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
6127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // Aggregation PopupWindow
6137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putLong(KEY_AGGREGATION_SUGGESTIONS_RAW_CONTACT_ID,
6147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                mAggregationSuggestionsRawContactId);
6157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
6167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // Join Activity
6177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        outState.putLong(KEY_CONTACT_ID_FOR_JOIN, mContactIdForJoin);
6187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
619698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        outState.putLong(KEY_READ_ONLY_DISPLAY_NAME_ID, mReadOnlyDisplayNameId);
620698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        outState.putBoolean(KEY_COPY_READ_ONLY_DISPLAY_NAME, mCopyReadOnlyName);
6217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
6223efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang        outState.putLong(KEY_PHOTO_RAW_CONTACT_ID, mPhotoRawContactId);
62328a27279554af7b1e5ff664d3da97954c462a797Walter Jang        outState.putParcelable(KEY_UPDATED_PHOTOS, mUpdatedPhotos);
6243efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang        super.onSaveInstanceState(outState);
6253efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    }
6263efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
6273efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    @Override
6287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onStop() {
6297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        super.onStop();
6307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        UiClosables.closeQuietly(mAggregationSuggestionPopup);
6317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
6327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
6337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
6347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onDestroy() {
6357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        super.onDestroy();
6367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mAggregationSuggestionEngine != null) {
6377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mAggregationSuggestionEngine.quit();
6387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
6397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
6407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
6417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
6427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onActivityResult(int requestCode, int resultCode, Intent data) {
6437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        switch (requestCode) {
6447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            case REQUEST_CODE_JOIN: {
6457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // Ignore failed requests
6467b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (resultCode != Activity.RESULT_OK) return;
6477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (data != null) {
6487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    final long contactId = ContentUris.parseId(data.getData());
6497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    if (hasPendingChanges()) {
6507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        // Ask the user if they want to save changes before doing the join
6517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        JoinContactConfirmationDialogFragment.show(this, contactId);
6527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    } else {
6537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        // Do the join immediately
6547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        joinAggregate(contactId);
6557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    }
6567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
6577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                break;
6587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
6597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            case REQUEST_CODE_ACCOUNTS_CHANGED: {
6607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // Bail if the account selector was not successful.
661807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott                if (resultCode != Activity.RESULT_OK || data == null ||
662807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott                        !data.hasExtra(Intents.Insert.EXTRA_ACCOUNT)) {
6637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    if (mListener != null) {
6647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        mListener.onReverted();
6657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    }
6667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    return;
6677b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
668807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott                AccountWithDataSet account = data.getParcelableExtra(
669807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott                        Intents.Insert.EXTRA_ACCOUNT);
670807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott                createContact(account);
6717b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                break;
6727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
6737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
6747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
6757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
6768c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott    @Override
6778c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott    public void onAccountsLoaded(List<AccountInfo> data) {
6788c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott        mWritableAccounts = data;
6798c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott        // The user may need to select a new account to save to
6808c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott        if (mAccountWithDataSet == null && mHasNewContact) {
6818c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott            selectAccountAndCreateContact();
6828c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott        }
6838c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott
6848c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott        final RawContactEditorView view = getContent();
6858c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott        if (view == null) {
6868c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott            return;
6878c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott        }
6888c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott        view.setAccounts(data);
6898c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott        if (mAccountWithDataSet == null && view.getCurrentRawContactDelta() == null) {
6908c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott            return;
6918c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott        }
6928c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott
6938c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott        final AccountWithDataSet account = mAccountWithDataSet != null
6948c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott                ? mAccountWithDataSet
6958c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott                : view.getCurrentRawContactDelta().getAccountWithDataSet();
6968c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott
6978c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott        // The current account was removed
6988c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott        if (!AccountInfo.contains(data, account) && !data.isEmpty()) {
6998c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott            if (isReadyToBindEditors()) {
7008c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott                onRebindEditorsForNewContact(getContent().getCurrentRawContactDelta(),
7018c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott                        account, data.get(0).getAccount());
7028c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott            } else {
7038c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott                mAccountWithDataSet = data.get(0).getAccount();
7048c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott            }
7058c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott        }
7068c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott    }
7078c6b5bdb3812fcbe5680fafca59d2ab9ec90d839Marcus Hagerott
7087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
7097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Options menu
7107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
7117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
7127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
7137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onCreateOptionsMenu(Menu menu, final MenuInflater inflater) {
7147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        inflater.inflate(R.menu.edit_contact, menu);
7157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
7167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
7177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
7187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onPrepareOptionsMenu(Menu menu) {
7197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // This supports the keyboard shortcut to save changes to a contact but shouldn't be visible
7207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // because the custom action bar contains the "save" button now (not the overflow menu).
7217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // TODO: Find a better way to handle shortcuts, i.e. onKeyDown()?
7227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final MenuItem saveMenu = menu.findItem(R.id.menu_save);
7237b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final MenuItem splitMenu = menu.findItem(R.id.menu_split);
7247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final MenuItem joinMenu = menu.findItem(R.id.menu_join);
7257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final MenuItem deleteMenu = menu.findItem(R.id.menu_delete);
7267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
7275eda257528e45fe6ae59cca3f1178590b53662f8Gary Mai        // TODO: b/30771904, b/31827701, temporarily disable these items until we get them to work
7285eda257528e45fe6ae59cca3f1178590b53662f8Gary Mai        // on a raw contact level.
7295eda257528e45fe6ae59cca3f1178590b53662f8Gary Mai        joinMenu.setVisible(false);
7305eda257528e45fe6ae59cca3f1178590b53662f8Gary Mai        splitMenu.setVisible(false);
7315eda257528e45fe6ae59cca3f1178590b53662f8Gary Mai        deleteMenu.setVisible(false);
7327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // Save menu is invisible when there's only one read only contact in the editor.
733d7faa65c1349a7ded4d2d478822c07d024e5e792Gary Mai        saveMenu.setVisible(!isEditingReadOnlyRawContact());
7347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (saveMenu.isVisible()) {
7357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Since we're using a custom action layout we have to manually hook up the handler.
7367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            saveMenu.getActionView().setOnClickListener(new View.OnClickListener() {
7377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                @Override
7387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                public void onClick(View v) {
7397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    onOptionsItemSelected(saveMenu);
7407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
7417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            });
7427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
7437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
7447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        int size = menu.size();
7457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        for (int i = 0; i < size; i++) {
7467b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            menu.getItem(i).setEnabled(mEnabled);
7477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
7487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
7497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
7507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
751c90cc15b804fb00339a3b98e5c951549f9b03599Walter Jang    public boolean onOptionsItemSelected(MenuItem item) {
752c90cc15b804fb00339a3b98e5c951549f9b03599Walter Jang        if (item.getItemId() == android.R.id.home) {
753c90cc15b804fb00339a3b98e5c951549f9b03599Walter Jang            return revert();
754c90cc15b804fb00339a3b98e5c951549f9b03599Walter Jang        }
7557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
7567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final Activity activity = getActivity();
7577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (activity == null || activity.isFinishing() || activity.isDestroyed()) {
7587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // If we no longer are attached to a running activity want to
7597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // drain this event.
7607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return true;
7617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
7627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
763b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott        final int id = item.getItemId();
764b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott        if (id == R.id.menu_save) {
765b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott            return save(SaveMode.CLOSE);
766b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott        } else if (id == R.id.menu_delete) {
767b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott            if (mListener != null) mListener.onDeleteRequested(mLookupUri);
768b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott            return true;
769b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott        } else if (id == R.id.menu_split) {
770b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott            return doSplitContactAction();
771b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott        } else if (id == R.id.menu_join) {
772b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott            return doJoinContactAction();
773b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott        } else if (id == R.id.menu_help) {
774b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott            HelpUtils.launchHelpAndFeedbackForContactScreen(getActivity());
775b697ed768fb817f94524f6c3992547665df331c4Marcus Hagerott            return true;
7767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
7777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
7787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return false;
7797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
7807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
7817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
7827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public boolean revert() {
7837b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mState.isEmpty() || !hasPendingChanges()) {
7847b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            onCancelEditConfirmed();
7857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        } else {
7867b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            CancelEditDialogFragment.show(this);
7877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
7887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return true;
7897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
7907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
7917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
7927b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onCancelEditConfirmed() {
7937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // When this Fragment is closed we don't want it to auto-save
7947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mStatus = Status.CLOSING;
7957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mListener != null) {
7967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mListener.onReverted();
7977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
7987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
7997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
8017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onSplitContactConfirmed(boolean hasPendingChanges) {
8027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mState.isEmpty()) {
8037b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // This may happen when this Fragment is recreated by the system during users
8047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // confirming the split action (and thus this method is called just before onCreate()),
8057b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // for example.
8067b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            Log.e(TAG, "mState became null during the user's confirming split action. " +
8077b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    "Cannot perform the save action.");
8087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return;
8097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
8107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (!hasPendingChanges && mHasNewContact) {
8127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // If the user didn't add anything new, we don't want to split out the newly created
8137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // raw contact into a name-only contact so remove them.
8147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            final Iterator<RawContactDelta> iterator = mState.iterator();
8157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            while (iterator.hasNext()) {
8167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                final RawContactDelta rawContactDelta = iterator.next();
8177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (rawContactDelta.getRawContactId() < 0) {
8187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    iterator.remove();
8197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
8207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
8217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
8227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mState.markRawContactsForSplitting();
8237b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        save(SaveMode.SPLIT);
8247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
8257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
826b9065ddb28a2040cabda251891be2062b5260217Gary Mai    @Override
827b9065ddb28a2040cabda251891be2062b5260217Gary Mai    public void onSplitContactCanceled() {}
828b9065ddb28a2040cabda251891be2062b5260217Gary Mai
8297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private boolean doSplitContactAction() {
8307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (!hasValidState()) return false;
8317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        SplitContactConfirmationDialogFragment.show(this, hasPendingChanges());
8337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return true;
8347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
8357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private boolean doJoinContactAction() {
8377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (!hasValidState() || mLookupUri == null) {
8387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return false;
8397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
8407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // If we just started creating a new contact and haven't added any data, it's too
8427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // early to do a join
8437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mState.size() == 1 && mState.get(0).isContactInsert()
8447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                && !hasPendingChanges()) {
8457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            Toast.makeText(mContext, R.string.toast_join_with_empty_contact,
8467b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    Toast.LENGTH_LONG).show();
8477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return true;
8487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
8497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        showJoinAggregateActivity(mLookupUri);
8517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return true;
8527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
8537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
8557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onJoinContactConfirmed(long joinContactId) {
8567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        doSaveAction(SaveMode.JOIN, joinContactId);
8577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
8587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
859c90cc15b804fb00339a3b98e5c951549f9b03599Walter Jang    @Override
8607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public boolean save(int saveMode) {
8617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (!hasValidState() || mStatus != Status.EDITING) {
8627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return false;
8637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
8647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // If we are about to close the editor - there is no need to refresh the data
866363af60ea23e5a3b945005712a16564ab69db18bGary Mai        if (saveMode == SaveMode.CLOSE || saveMode == SaveMode.EDITOR
8677b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                || saveMode == SaveMode.SPLIT) {
8687b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            getLoaderManager().destroyLoader(LOADER_CONTACT);
8697b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
8707b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8717b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mStatus = Status.SAVING;
8727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (!hasPendingChanges()) {
8747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            if (mLookupUri == null && saveMode == SaveMode.RELOAD) {
8757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // We don't have anything to save and there isn't even an existing contact yet.
8767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // Nothing to do, simply go back to editing mode
8777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                mStatus = Status.EDITING;
8787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                return true;
8797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
8807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            onSaveCompleted(/* hadChanges =*/ false, saveMode,
8817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    /* saveSucceeded =*/ mLookupUri != null, mLookupUri, /* joinContactId =*/ null);
8827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return true;
8837b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
8847b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        setEnabled(false);
8867b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return doSaveAction(saveMode, /* joinContactId */ null);
8887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
8897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
8917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // State accessor methods
8927b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
8937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
8947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
8957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Check if our internal {@link #mState} is valid, usually checked before
8967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * performing user actions.
8977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
8987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private boolean hasValidState() {
8997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return mState.size() > 0;
9007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
9017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
9027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private boolean isEditingUserProfile() {
9037b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return mNewLocalProfile || mIsUserProfile;
9047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
9057b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
9067b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
9075a00de39004d298de4daee3e183add5eff17102cGary Mai     * Whether the contact being edited is composed of read-only raw contacts
9087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * aggregated with a newly created writable raw contact.
9097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
9107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private boolean isEditingReadOnlyRawContactWithNewContact() {
9115a00de39004d298de4daee3e183add5eff17102cGary Mai        return mHasNewContact && mState.size() > 1;
9127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
9137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
9147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
915d7faa65c1349a7ded4d2d478822c07d024e5e792Gary Mai     * @return true if the single raw contact we're looking at is read-only.
916d7faa65c1349a7ded4d2d478822c07d024e5e792Gary Mai     */
917d7faa65c1349a7ded4d2d478822c07d024e5e792Gary Mai    private boolean isEditingReadOnlyRawContact() {
918d7faa65c1349a7ded4d2d478822c07d024e5e792Gary Mai        return hasValidState() && mRawContactIdToDisplayAlone > 0
919d7faa65c1349a7ded4d2d478822c07d024e5e792Gary Mai                && !mState.getByRawContactId(mRawContactIdToDisplayAlone)
920d7faa65c1349a7ded4d2d478822c07d024e5e792Gary Mai                        .getAccountType(AccountTypeManager.getInstance(mContext))
921d7faa65c1349a7ded4d2d478822c07d024e5e792Gary Mai                                .areContactsWritable();
922d7faa65c1349a7ded4d2d478822c07d024e5e792Gary Mai    }
923d7faa65c1349a7ded4d2d478822c07d024e5e792Gary Mai
924d7faa65c1349a7ded4d2d478822c07d024e5e792Gary Mai    /**
9257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Return true if there are any edits to the current contact which need to
9267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * be saved.
9277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
9287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private boolean hasPendingRawContactChanges(Set<String> excludedMimeTypes) {
9297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
9307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return RawContactModifier.hasChanges(mState, accountTypes, excludedMimeTypes);
9317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
9327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
9337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
9347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Determines if changes were made in the editor that need to be saved, while taking into
9357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * account that name changes are not real for read-only contacts.
9367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * See go/editing-read-only-contacts
9377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
9387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private boolean hasPendingChanges() {
939698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        if (isEditingReadOnlyRawContactWithNewContact()) {
9407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // We created a new raw contact delta with a default display name.
9417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // We must test for pending changes while ignoring the default display name.
942698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final ValuesDelta beforeDelta = mState.getByRawContactId(mReadOnlyDisplayNameId)
943698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai                    .getSuperPrimaryEntry(StructuredName.CONTENT_ITEM_TYPE);
944698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final ValuesDelta pendingDelta = mState
945698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai                    .getSuperPrimaryEntry(StructuredName.CONTENT_ITEM_TYPE);
946698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            if (structuredNamesAreEqual(beforeDelta, pendingDelta)) {
9477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                final Set<String> excludedMimeTypes = new HashSet<>();
9487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                excludedMimeTypes.add(StructuredName.CONTENT_ITEM_TYPE);
9497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                return hasPendingRawContactChanges(excludedMimeTypes);
9507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
9517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return true;
9527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
9537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return hasPendingRawContactChanges(/* excludedMimeTypes =*/ null);
9547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
9557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
9567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
957698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai     * Compares the two {@link ValuesDelta} to see if the structured name is changed. We made a copy
958698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai     * of a read only delta and now we want to check if the copied delta has changes.
959698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai     *
960698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai     * @param before original {@link ValuesDelta}
961698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai     * @param after copied {@link ValuesDelta}
962698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai     * @return true if the copied {@link ValuesDelta} has all the same values in the structured
963698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai     * name fields as the original.
964698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai     */
965698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai    private boolean structuredNamesAreEqual(ValuesDelta before, ValuesDelta after) {
9665a00de39004d298de4daee3e183add5eff17102cGary Mai        if (before == after) return true;
967698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        if (before == null || after == null) return false;
968698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        final ContentValues original = before.getBefore();
969698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        final ContentValues pending = after.getAfter();
970698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        if (original != null && pending != null) {
971a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai            final String beforeDisplayName = original.getAsString(StructuredName.DISPLAY_NAME);
972698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final String afterDisplayName = pending.getAsString(StructuredName.DISPLAY_NAME);
973698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            if (!TextUtils.equals(beforeDisplayName, afterDisplayName)) return false;
974698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai
975698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final String beforePrefix = original.getAsString(StructuredName.PREFIX);
976698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final String afterPrefix = pending.getAsString(StructuredName.PREFIX);
977698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            if (!TextUtils.equals(beforePrefix, afterPrefix)) return false;
978698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai
979698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final String beforeFirstName = original.getAsString(StructuredName.GIVEN_NAME);
980698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final String afterFirstName = pending.getAsString(StructuredName.GIVEN_NAME);
981698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            if (!TextUtils.equals(beforeFirstName, afterFirstName)) return false;
982698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai
983698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final String beforeMiddleName = original.getAsString(StructuredName.MIDDLE_NAME);
984698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final String afterMiddleName = pending.getAsString(StructuredName.MIDDLE_NAME);
985698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            if (!TextUtils.equals(beforeMiddleName, afterMiddleName)) return false;
986698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai
987698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final String beforeLastName = original.getAsString(StructuredName.FAMILY_NAME);
988698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final String afterLastName = pending.getAsString(StructuredName.FAMILY_NAME);
989698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            if (!TextUtils.equals(beforeLastName, afterLastName)) return false;
990698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai
991698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final String beforeSuffix = original.getAsString(StructuredName.SUFFIX);
992698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            final String afterSuffix = pending.getAsString(StructuredName.SUFFIX);
993698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            return TextUtils.equals(beforeSuffix, afterSuffix);
994698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        }
995698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        return false;
996698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai    }
997698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai
9987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
9997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Account creation
10007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
10017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
10027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private void selectAccountAndCreateContact() {
1003807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott        Preconditions.checkNotNull(mWritableAccounts, "Accounts must be loaded first");
10047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // If this is a local profile, then skip the logic about showing the accounts changed
10057b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // activity and create a phone-local contact.
10067b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mNewLocalProfile) {
10077b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            createContact(null);
10087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return;
10097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
10107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1011807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott        final List<AccountWithDataSet> accounts = AccountInfo.extractAccounts(mWritableAccounts);
10127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // If there is no default account or the accounts have changed such that we need to
10137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // prompt the user again, then launch the account prompt.
1014807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott        if (mEditorUtils.shouldShowAccountChangedNotification(accounts)) {
10157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            Intent intent = new Intent(mContext, ContactEditorAccountsChangedActivity.class);
10167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Prevent a second instance from being started on rotates
101780ab7ea6a518410594058c74f32c4b551097edbdMarcus Hagerott            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
10187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mStatus = Status.SUB_ACTIVITY;
10197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            startActivityForResult(intent, REQUEST_CODE_ACCOUNTS_CHANGED);
10207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        } else {
10213107b25dcaea54943c58f984084fa9b348ea1885Gary Mai            // Make sure the default account is automatically set if there is only one non-device
10223107b25dcaea54943c58f984084fa9b348ea1885Gary Mai            // account.
1023807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott            mEditorUtils.maybeUpdateDefaultAccount(accounts);
10247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Otherwise, there should be a default account. Then either create a local contact
10257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // (if default account is null) or create a contact with the specified account.
1026807e6208d6bc4ff1a6b0b4d8900229df27077246Marcus Hagerott            AccountWithDataSet defaultAccount = mEditorUtils.getOnlyOrDefaultAccount(accounts);
10277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            createContact(defaultAccount);
10287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
10297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
10307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
10317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
10327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Shows account creation screen associated with a given account.
10337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     *
10347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * @param account may be null to signal a device-local contact should be created.
10357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
10367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private void createContact(AccountWithDataSet account) {
10377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
10387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final AccountType accountType = accountTypes.getAccountTypeForAccount(account);
10397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1040aebf3206766a05cce290245f09506adb789b6e37Gary Mai        setStateForNewContact(account, accountType, isEditingUserProfile());
10417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
10427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
10437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
10447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Data binding
10457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
10467b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
10477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private void setState(Contact contact) {
10487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // If we have already loaded data, we do not want to change it here to not confuse the user
10497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (!mState.isEmpty()) {
10507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            Log.v(TAG, "Ignoring background change. This will have to be rebased later");
10517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return;
10527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
10537b75145e9b4fcd46c3cbb5678f8842934467b3aaGary Mai        mContact = contact;
10544ceabed629c43cb247fd4a0faa36c09bd5ec999aGary Mai        mRawContacts = contact.getRawContacts();
10557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
10567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // Check for writable raw contacts.  If there are none, then we need to create one so user
10577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // can edit.  For the user profile case, there is already an editable contact.
10587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (!contact.isUserProfile() && !contact.isWritableContact(mContext)) {
10597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mHasNewContact = true;
1060698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            mReadOnlyDisplayNameId = contact.getNameRawContactId();
1061698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            mCopyReadOnlyName = true;
10627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // This is potentially an asynchronous call and will add deltas to list.
10637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            selectAccountAndCreateContact();
10647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        } else {
10657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mHasNewContact = false;
10667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
10677b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1068698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        setStateForExistingContact(contact.isUserProfile(), mRawContacts);
1069e48746654178e9448819f86b3129fd32f539b3c9Gary Mai        if (mAutoAddToDefaultGroup
1070e48746654178e9448819f86b3129fd32f539b3c9Gary Mai                && InvisibleContactUtil.isInvisibleAndAddable(contact, getContext())) {
1071e48746654178e9448819f86b3129fd32f539b3c9Gary Mai            InvisibleContactUtil.markAddToDefaultGroup(contact, mState, getContext());
1072e48746654178e9448819f86b3129fd32f539b3c9Gary Mai        }
10737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
10747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
10757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
10767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Prepare {@link #mState} for a newly created phone-local contact.
10777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
10787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private void setStateForNewContact(AccountWithDataSet account, AccountType accountType,
10797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            boolean isUserProfile) {
10807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        setStateForNewContact(account, accountType, /* oldState =*/ null,
10817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                /* oldAccountType =*/ null, isUserProfile);
10827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
10837b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
10847b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
10857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Prepare {@link #mState} for a newly created phone-local contact, migrating the state
10867b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * specified by oldState and oldAccountType.
10877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
10887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private void setStateForNewContact(AccountWithDataSet account, AccountType accountType,
10897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            RawContactDelta oldState, AccountType oldAccountType, boolean isUserProfile) {
10907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mStatus = Status.EDITING;
10919f691e8b1c30dcdae230daebd26da0f225f74008Gary Mai        mAccountWithDataSet = account;
10927b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mState.add(createNewRawContactDelta(account, accountType, oldState, oldAccountType));
10937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mIsUserProfile = isUserProfile;
10947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mNewContactDataReady = true;
10957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        bindEditors();
10967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
10977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
10987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
10997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Returns a {@link RawContactDelta} for a new contact suitable for addition into
11007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * {@link #mState}.
11017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     *
11027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * If oldState and oldAccountType are specified, the state specified by those parameters
11037b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * is migrated to the result {@link RawContactDelta}.
11047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
11057b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private RawContactDelta createNewRawContactDelta(AccountWithDataSet account,
11067b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            AccountType accountType, RawContactDelta oldState, AccountType oldAccountType) {
11077b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final RawContact rawContact = new RawContact();
11087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (account != null) {
11097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            rawContact.setAccount(account);
11107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        } else {
11117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            rawContact.setAccountToLocal();
11127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
11137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final RawContactDelta result = new RawContactDelta(
11157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                ValuesDelta.fromAfter(rawContact.getValues()));
11167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (oldState == null) {
11177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Parse any values from incoming intent
11187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            RawContactModifier.parseExtras(mContext, accountType, result, mIntentExtras);
11197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        } else {
11207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            RawContactModifier.migrateStateForNewContact(
11217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mContext, oldState, result, oldAccountType, accountType);
11227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
11237b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // Ensure we have some default fields (if the account type does not support a field,
11257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // ensureKind will not add it, so it is safe to add e.g. Event)
112662ec0b10c0ddc00053df39aeaed1f3316116e849Gary Mai        RawContactModifier.ensureKindExists(result, accountType, StructuredName.CONTENT_ITEM_TYPE);
11277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        RawContactModifier.ensureKindExists(result, accountType, Phone.CONTENT_ITEM_TYPE);
11287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        RawContactModifier.ensureKindExists(result, accountType, Email.CONTENT_ITEM_TYPE);
11297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        RawContactModifier.ensureKindExists(result, accountType, Organization.CONTENT_ITEM_TYPE);
11307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        RawContactModifier.ensureKindExists(result, accountType, Event.CONTENT_ITEM_TYPE);
11317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        RawContactModifier.ensureKindExists(result, accountType,
11327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                StructuredPostal.CONTENT_ITEM_TYPE);
11337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // Set the correct URI for saving the contact as a profile
11357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mNewLocalProfile) {
11367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            result.setProfileQueryUri();
11377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
11387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return result;
11407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
11417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
11437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Prepare {@link #mState} for an existing contact.
11447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
1145698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai    private void setStateForExistingContact(boolean isUserProfile,
11467b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            ImmutableList<RawContact> rawContacts) {
11477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        setEnabled(true);
11487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mState.addAll(rawContacts.iterator());
11507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        setIntentExtras(mIntentExtras);
11517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mIntentExtras = null;
11527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        // For user profile, change the contacts query URI
11547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mIsUserProfile = isUserProfile;
11557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        boolean localProfileExists = false;
11567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mIsUserProfile) {
11587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            for (RawContactDelta rawContactDelta : mState) {
11597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // For profile contacts, we need a different query URI
11607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                rawContactDelta.setProfileQueryUri();
11617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // Try to find a local profile contact
11627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (rawContactDelta.getValues().getAsString(RawContacts.ACCOUNT_TYPE) == null) {
11637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    localProfileExists = true;
11647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
11657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
11667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Editor should always present a local profile for editing
11677b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // TODO(wjang): Need to figure out when this case comes up.  We can't do this if we're
11687b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // going to prune all but the one raw contact that we're trying to display by itself.
11697b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            if (!localProfileExists && mRawContactIdToDisplayAlone <= 0) {
11707b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                mState.add(createLocalRawContactDelta());
11717b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
11727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
11737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mExistingContactDataReady = true;
11747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        bindEditors();
11757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
11767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
11787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Set the enabled state of editors.
11797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
11807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private void setEnabled(boolean enabled) {
11817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mEnabled != enabled) {
11827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mEnabled = enabled;
11837b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11847b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Enable/disable editors
11857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            if (mContent != null) {
11867b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                int count = mContent.getChildCount();
11877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                for (int i = 0; i < count; i++) {
11887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mContent.getChildAt(i).setEnabled(enabled);
11897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
11907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
11917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11927b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // Maybe invalidate the options menu
11937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            final Activity activity = getActivity();
11947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            if (activity != null) activity.invalidateOptionsMenu();
11957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
11967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
11977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
11987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
11997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Returns a {@link RawContactDelta} for a local contact suitable for addition into
12007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * {@link #mState}.
12017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
12027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private static RawContactDelta createLocalRawContactDelta() {
12037b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final RawContact rawContact = new RawContact();
12047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        rawContact.setAccountToLocal();
12057b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
12067b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final RawContactDelta result = new RawContactDelta(
12077b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                ValuesDelta.fromAfter(rawContact.getValues()));
12087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        result.setProfileQueryUri();
12097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
12107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return result;
12117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
12127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1213698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai    private void copyReadOnlyName() {
1214698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        // We should only ever be doing this if we're creating a new writable contact to attach to
1215698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        // a read only contact.
1216698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        if (!isEditingReadOnlyRawContactWithNewContact()) {
1217698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            return;
1218698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        }
1219698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        final int writableIndex = mState.indexOfFirstWritableRawContact(getContext());
1220698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        final RawContactDelta writable = mState.get(writableIndex);
12217b75145e9b4fcd46c3cbb5678f8842934467b3aaGary Mai        final RawContactDelta readOnly = mState.getByRawContactId(mContact.getNameRawContactId());
1222698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        final ValuesDelta writeNameDelta = writable
1223698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai                .getSuperPrimaryEntry(StructuredName.CONTENT_ITEM_TYPE);
1224698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        final ValuesDelta readNameDelta = readOnly
1225698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai                .getSuperPrimaryEntry(StructuredName.CONTENT_ITEM_TYPE);
1226698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        mCopyReadOnlyName = false;
1227860698b8d4542a55da5ec40032a361433b525aadGary Mai        if (writeNameDelta == null || readNameDelta == null) {
1228860698b8d4542a55da5ec40032a361433b525aadGary Mai            return;
1229860698b8d4542a55da5ec40032a361433b525aadGary Mai        }
1230860698b8d4542a55da5ec40032a361433b525aadGary Mai        writeNameDelta.copyStructuredNameFieldsFrom(readNameDelta);
1231698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai    }
1232698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai
12337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
12347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Bind editors using {@link #mState} and other members initialized from the loaded (or new)
12357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Contact.
12367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
1237ba59deb669cf377bedf08af53c9196db3c1cc404Walter Jang    protected void bindEditors() {
1238cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang        if (!isReadyToBindEditors()) {
1239cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang            return;
1240cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang        }
1241cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang
1242d35e5eff8737e757a4179d49dfe9c7db999b4e9dWalter Jang        // Add input fields for the loaded Contact
1243363af60ea23e5a3b945005712a16564ab69db18bGary Mai        final RawContactEditorView editorView = getContent();
1244b6ca272f26b47ecef8fafe94326c4d553576c521Walter Jang        editorView.setListener(this);
1245698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        if (mCopyReadOnlyName) {
1246698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            copyReadOnlyName();
1247698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai        }
1248678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai        editorView.setState(mState, mMaterialPalette, mViewIdGenerator,
12499a55237f705453caae1f8aa3576a9acd7596d5ecWalter Jang                mHasNewContact, mIsUserProfile, mAccountWithDataSet,
12505a00de39004d298de4daee3e183add5eff17102cGary Mai                mRawContactIdToDisplayAlone);
1251079598fa2e09c22bb672715a9559b9d8973044d5Gary Mai        if (isEditingReadOnlyRawContact()) {
125215646ce3e2e7a7f889976dc5684ecbc3029230c2Gary Mai            final Toolbar toolbar = getEditorActivity().getToolbar();
125315646ce3e2e7a7f889976dc5684ecbc3029230c2Gary Mai            if (toolbar != null) {
125415646ce3e2e7a7f889976dc5684ecbc3029230c2Gary Mai                toolbar.setTitle(R.string.contact_editor_title_read_only_contact);
1255d8f3da6a4ea4054bd47959db85657a7e01d28358Gary Mai                // Set activity title for Talkback
1256d8f3da6a4ea4054bd47959db85657a7e01d28358Gary Mai                getEditorActivity().setTitle(R.string.contact_editor_title_read_only_contact);
1257bd9ef3c60669d71543b3506d4959c1fe4be409dcJohn Shao                toolbar.setNavigationIcon(R.drawable.quantum_ic_arrow_back_vd_theme_24);
125815646ce3e2e7a7f889976dc5684ecbc3029230c2Gary Mai                toolbar.setNavigationContentDescription(R.string.back_arrow_content_description);
1259bd9ef3c60669d71543b3506d4959c1fe4be409dcJohn Shao                toolbar.getNavigationIcon().setAutoMirrored(true);
1260079598fa2e09c22bb672715a9559b9d8973044d5Gary Mai            }
1261079598fa2e09c22bb672715a9559b9d8973044d5Gary Mai        }
1262cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang
1263d35e5eff8737e757a4179d49dfe9c7db999b4e9dWalter Jang        // Set up the photo widget
126431a74ad969b650eb733e536569254ed3978c4f54Walter Jang        editorView.setPhotoListener(this);
12653efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang        mPhotoRawContactId = editorView.getPhotoRawContactId();
126631a74ad969b650eb733e536569254ed3978c4f54Walter Jang        // If there is an updated full resolution photo apply it now, this will be the case if
126731a74ad969b650eb733e536569254ed3978c4f54Walter Jang        // the user selects or takes a new photo, then rotates the device.
126831a74ad969b650eb733e536569254ed3978c4f54Walter Jang        final Uri uri = (Uri) mUpdatedPhotos.get(String.valueOf(mPhotoRawContactId));
126931a74ad969b650eb733e536569254ed3978c4f54Walter Jang        if (uri != null) {
127031a74ad969b650eb733e536569254ed3978c4f54Walter Jang            editorView.setFullSizePhoto(uri);
127141b3ea1c712f01164feb55455f1391564cb76deeWalter Jang        }
12723efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang
1273d35e5eff8737e757a4179d49dfe9c7db999b4e9dWalter Jang        // The editor is ready now so make it visible
1274678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai        editorView.setEnabled(mEnabled);
1275d35e5eff8737e757a4179d49dfe9c7db999b4e9dWalter Jang        editorView.setVisibility(View.VISIBLE);
1276d35e5eff8737e757a4179d49dfe9c7db999b4e9dWalter Jang
1277d35e5eff8737e757a4179d49dfe9c7db999b4e9dWalter Jang        // Refresh the ActionBar as the visibility of the join command
1278d35e5eff8737e757a4179d49dfe9c7db999b4e9dWalter Jang        // Activity can be null if we have been detached from the Activity.
1279cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang        invalidateOptionsMenu();
1280cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang    }
1281cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang
12827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
12837b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Invalidates the options menu if we are still associated with an Activity.
12847b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
12857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private void invalidateOptionsMenu() {
12867b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final Activity activity = getActivity();
12877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (activity != null) {
12887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            activity.invalidateOptionsMenu();
12897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
12907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
12917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1292cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang    private boolean isReadyToBindEditors() {
1293cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang        if (mState.isEmpty()) {
1294cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang            if (Log.isLoggable(TAG, Log.VERBOSE)) {
1295cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang                Log.v(TAG, "No data to bind editors");
1296cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang            }
1297cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang            return false;
1298cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang        }
1299cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang        if (mIsEdit && !mExistingContactDataReady) {
1300cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang            if (Log.isLoggable(TAG, Log.VERBOSE)) {
1301cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang                Log.v(TAG, "Existing contact data is not ready to bind editors.");
1302cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang            }
1303cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang            return false;
1304cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang        }
1305cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang        if (mHasNewContact && !mNewContactDataReady) {
1306cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang            if (Log.isLoggable(TAG, Log.VERBOSE)) {
1307cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang                Log.v(TAG, "New contact data is not ready to bind editors.");
1308cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang            }
1309cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang            return false;
1310cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang        }
1311cab3dcec1401a32aff583d946b4a9f8af954358fWalter Jang        return true;
1312ba59deb669cf377bedf08af53c9196db3c1cc404Walter Jang    }
1313ba59deb669cf377bedf08af53c9196db3c1cc404Walter Jang
13147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
13157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Removes a current editor ({@link #mState}) and rebinds new editor for a new account.
13167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Some of old data are reused with new restriction enforced by the new account.
13177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     *
13187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * @param oldState Old data being edited.
13197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * @param oldAccount Old account associated with oldState.
13207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * @param newAccount New account to be used.
13217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
13227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private void rebindEditorsForNewContact(
13237b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            RawContactDelta oldState, AccountWithDataSet oldAccount,
13247b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            AccountWithDataSet newAccount) {
13257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
13267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        AccountType oldAccountType = accountTypes.getAccountTypeForAccount(oldAccount);
13277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        AccountType newAccountType = accountTypes.getAccountTypeForAccount(newAccount);
13287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1329aebf3206766a05cce290245f09506adb789b6e37Gary Mai        mExistingContactDataReady = false;
1330aebf3206766a05cce290245f09506adb789b6e37Gary Mai        mNewContactDataReady = false;
1331aebf3206766a05cce290245f09506adb789b6e37Gary Mai        mState = new RawContactDeltaList();
1332aebf3206766a05cce290245f09506adb789b6e37Gary Mai        setStateForNewContact(newAccount, newAccountType, oldState, oldAccountType,
1333aebf3206766a05cce290245f09506adb789b6e37Gary Mai                isEditingUserProfile());
1334aebf3206766a05cce290245f09506adb789b6e37Gary Mai        if (mIsEdit) {
1335698cee7d410f06b0c883c11f53481bfa5b2b787aGary Mai            setStateForExistingContact(isEditingUserProfile(), mRawContacts);
13367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
13377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
13387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
13397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
13407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // ContactEditor
13417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
13427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
13437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
13447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void setListener(Listener listener) {
13457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mListener = listener;
13467b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
13477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
13487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
13497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void load(String action, Uri lookupUri, Bundle intentExtras) {
13507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mAction = action;
13517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mLookupUri = lookupUri;
13527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mIntentExtras = intentExtras;
13537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
13547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mIntentExtras != null) {
13557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mAutoAddToDefaultGroup =
13567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mIntentExtras.containsKey(INTENT_EXTRA_ADD_TO_DEFAULT_DIRECTORY);
13577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mNewLocalProfile =
13587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mIntentExtras.getBoolean(INTENT_EXTRA_NEW_LOCAL_PROFILE);
13597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mDisableDeleteMenuOption =
13607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mIntentExtras.getBoolean(INTENT_EXTRA_DISABLE_DELETE_MENU_OPTION);
13617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            if (mIntentExtras.containsKey(INTENT_EXTRA_MATERIAL_PALETTE_PRIMARY_COLOR)
13627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    && mIntentExtras.containsKey(INTENT_EXTRA_MATERIAL_PALETTE_SECONDARY_COLOR)) {
13637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                mMaterialPalette = new MaterialColorMapUtils.MaterialPalette(
13647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        mIntentExtras.getInt(INTENT_EXTRA_MATERIAL_PALETTE_PRIMARY_COLOR),
13657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        mIntentExtras.getInt(INTENT_EXTRA_MATERIAL_PALETTE_SECONDARY_COLOR));
13667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
1367a6c80b378e03ebdf6b654dbdb12f2c665fe98a80Gary Mai            mRawContactIdToDisplayAlone = mIntentExtras
1368a6c80b378e03ebdf6b654dbdb12f2c665fe98a80Gary Mai                    .getLong(INTENT_EXTRA_RAW_CONTACT_ID_TO_DISPLAY_ALONE);
13697b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
13707b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
13717b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
13727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
13737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void setIntentExtras(Bundle extras) {
13745336e6ef1924162b94942cbd8f69202d553822daGary Mai        getContent().setIntentExtras(extras);
13757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
13767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
13777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
13787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onJoinCompleted(Uri uri) {
13797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        onSaveCompleted(false, SaveMode.RELOAD, uri != null, uri, /* joinContactId */ null);
13807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
13817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1382e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey
1383e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey    private String getNameToDisplay(Uri contactUri) {
1384c000d2ee0e292d9b160f65ab74ebd1258346046bGary Mai        // The contact has been deleted or the uri is otherwise no longer right.
1385c000d2ee0e292d9b160f65ab74ebd1258346046bGary Mai        if (contactUri == null) {
1386c000d2ee0e292d9b160f65ab74ebd1258346046bGary Mai            return null;
1387c000d2ee0e292d9b160f65ab74ebd1258346046bGary Mai        }
1388e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey        final ContentResolver resolver = mContext.getContentResolver();
1389e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey        final Cursor cursor = resolver.query(contactUri, new String[]{
1390e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey                ContactsContract.Contacts.DISPLAY_NAME,
1391e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey                ContactsContract.Contacts.DISPLAY_NAME_ALTERNATIVE}, null, null, null);
1392a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai
1393a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai        if (cursor != null) {
1394a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai            try {
1395a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai                if (cursor.moveToFirst()) {
1396a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai                    final String displayName = cursor.getString(0);
1397a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai                    final String displayNameAlt = cursor.getString(1);
1398a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai                    cursor.close();
1399a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai                    return ContactDisplayUtils.getPreferredDisplayName(displayName, displayNameAlt,
1400a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai                            new ContactsPreferences(mContext));
1401a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai                }
1402a4adae163d83db9226b831f8c9705914e68b5cd1Gary Mai            } finally {
1403e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey                cursor.close();
1404e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey            }
1405e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey        }
1406e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey        return null;
1407e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey    }
1408e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey
1409e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey
14107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
14117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onSaveCompleted(boolean hadChanges, int saveMode, boolean saveSucceeded,
14127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            Uri contactLookupUri, Long joinContactId) {
14137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (hadChanges) {
14147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            if (saveSucceeded) {
14157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                switch (saveMode) {
14167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    case SaveMode.JOIN:
14177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        break;
14187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    case SaveMode.SPLIT:
14197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        Toast.makeText(mContext, R.string.contactUnlinkedToast, Toast.LENGTH_SHORT)
14207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                                .show();
14217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        break;
14227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    default:
1423e5a140a1b60854a08a0ea0dc2068e9bf7cb058e6James Laskey                        final String displayName = getNameToDisplay(contactLookupUri);
1424b1671053e48d14f2c620f48bc5f2cd915b51a002James Laskey                        final String toastMessage;
1425b1671053e48d14f2c620f48bc5f2cd915b51a002James Laskey                        if (!TextUtils.isEmpty(displayName)) {
1426b1671053e48d14f2c620f48bc5f2cd915b51a002James Laskey                            toastMessage = getResources().getString(
1427b1671053e48d14f2c620f48bc5f2cd915b51a002James Laskey                                    R.string.contactSavedNamedToast, displayName);
1428b1671053e48d14f2c620f48bc5f2cd915b51a002James Laskey                        } else {
1429b1671053e48d14f2c620f48bc5f2cd915b51a002James Laskey                            toastMessage = getResources().getString(R.string.contactSavedToast);
1430b1671053e48d14f2c620f48bc5f2cd915b51a002James Laskey                        }
1431b1671053e48d14f2c620f48bc5f2cd915b51a002James Laskey                        Toast.makeText(mContext, toastMessage, Toast.LENGTH_SHORT).show();
14327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
14337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
14347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            } else {
14357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                Toast.makeText(mContext, R.string.contactSavedErrorToast, Toast.LENGTH_LONG).show();
14367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
14377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
14387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        switch (saveMode) {
14397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            case SaveMode.CLOSE: {
14408d26c0a7214cf6520a4def851afa138a133a68a2Walter Jang                final Intent resultIntent;
14417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (saveSucceeded && contactLookupUri != null) {
14427b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    final Uri lookupUri = ContactEditorUtils.maybeConvertToLegacyLookupUri(
14437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                            mContext, contactLookupUri, mLookupUri);
14448d26c0a7214cf6520a4def851afa138a133a68a2Walter Jang                    resultIntent = ImplicitIntentsUtil.composeQuickContactIntent(
14458d26c0a7214cf6520a4def851afa138a133a68a2Walter Jang                            mContext, lookupUri, ScreenType.EDITOR);
14468d26c0a7214cf6520a4def851afa138a133a68a2Walter Jang                    resultIntent.putExtra(QuickContactActivity.EXTRA_CONTACT_EDITED, true);
14477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                } else {
14487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    resultIntent = null;
14497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
14507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // It is already saved, so prevent it from being saved again
14517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                mStatus = Status.CLOSING;
14527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (mListener != null) mListener.onSaveFinished(resultIntent);
14537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                break;
14547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
1455363af60ea23e5a3b945005712a16564ab69db18bGary Mai            case SaveMode.EDITOR: {
14567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                // It is already saved, so prevent it from being saved again
14577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                mStatus = Status.CLOSING;
14587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (mListener != null) mListener.onSaveFinished(/* resultIntent= */ null);
14597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                break;
14607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
14617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            case SaveMode.JOIN:
14627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (saveSucceeded && contactLookupUri != null && joinContactId != null) {
14637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    joinAggregate(joinContactId);
14647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
14657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                break;
14667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            case SaveMode.RELOAD:
14677b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (saveSucceeded && contactLookupUri != null) {
14687b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    // If this was in INSERT, we are changing into an EDIT now.
14697b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    // If it already was an EDIT, we are changing to the new Uri now
14707b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mState = new RawContactDeltaList();
14717b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    load(Intent.ACTION_EDIT, contactLookupUri, null);
14727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mStatus = Status.LOADING;
14737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    getLoaderManager().restartLoader(LOADER_CONTACT, null, mContactLoaderListener);
14747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
14757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                break;
14767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
14777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            case SaveMode.SPLIT:
14787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                mStatus = Status.CLOSING;
14797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                if (mListener != null) {
14807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    mListener.onContactSplit(contactLookupUri);
14817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                } else {
14827b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                    Log.d(TAG, "No listener registered, can not call onSplitFinished");
14837b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                }
14847b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                break;
14857b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
14867b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
14877b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
14887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
14897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Shows a list of aggregates that can be joined into the currently viewed aggregate.
14907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     *
14917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * @param contactLookupUri the fresh URI for the currently edited contact (after saving it)
14927b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
14937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private void showJoinAggregateActivity(Uri contactLookupUri) {
14947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (contactLookupUri == null || !isAdded()) {
14957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return;
14967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
14977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
14987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mContactIdForJoin = ContentUris.parseId(contactLookupUri);
14997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final Intent intent = new Intent(mContext, ContactSelectionActivity.class);
15007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        intent.setAction(UiIntentActions.PICK_JOIN_CONTACT_ACTION);
15017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        intent.putExtra(UiIntentActions.TARGET_CONTACT_ID_EXTRA_KEY, mContactIdForJoin);
15027b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        startActivityForResult(intent, REQUEST_CODE_JOIN);
15037b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
15047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15057b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
15067b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Aggregation PopupWindow
15077b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
15087b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
15107b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Triggers an asynchronous search for aggregation suggestions.
15117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
15127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    protected void acquireAggregationSuggestions(Context context,
15137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            long rawContactId, ValuesDelta valuesDelta) {
15147b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mAggregationSuggestionsRawContactId = rawContactId;
15157b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mAggregationSuggestionEngine == null) {
15177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mAggregationSuggestionEngine = new AggregationSuggestionEngine(context);
15187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mAggregationSuggestionEngine.setListener(this);
15197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mAggregationSuggestionEngine.start();
15207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
15217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15227b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mAggregationSuggestionEngine.setContactId(getContactId());
1523220d10cd7095f5ab803ff6155d7adaa576a8c4ffGary Mai        mAggregationSuggestionEngine.setAccountFilter(
1524220d10cd7095f5ab803ff6155d7adaa576a8c4ffGary Mai                getContent().getCurrentRawContactDelta().getAccountWithDataSet());
15257b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15267b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mAggregationSuggestionEngine.onNameChange(valuesDelta);
15277b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
15287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
15307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Returns the contact ID for the currently edited contact or 0 if the contact is new.
15317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
15327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private long getContactId() {
15337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        for (RawContactDelta rawContact : mState) {
15347b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            Long contactId = rawContact.getValues().getAsLong(RawContacts.CONTACT_ID);
15357b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            if (contactId != null) {
15367b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                return contactId;
15377b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
15387b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
15397b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return 0;
15407b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
15417b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15423f990ba4e35a99078d831c041290e574a320caa5Walter Jang    @Override
15437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void onAggregationSuggestionChange() {
15447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final Activity activity = getActivity();
15457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if ((activity != null && activity.isFinishing())
15467b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                || !isVisible() ||  mState.isEmpty() || mStatus != Status.EDITING) {
15477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return;
15487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
15497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        UiClosables.closeQuietly(mAggregationSuggestionPopup);
15517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mAggregationSuggestionEngine.getSuggestedContactCount() == 0) {
15537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return;
15547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
15557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
1556da20b47c2b85390a2c3772379e71203c5aab513cGary Mai        final View anchorView = getAggregationAnchorView();
15577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (anchorView == null) {
15587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return; // Raw contact deleted?
15597b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
15607b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mAggregationSuggestionPopup = new ListPopupWindow(mContext, null);
15617b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mAggregationSuggestionPopup.setAnchorView(anchorView);
15627b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mAggregationSuggestionPopup.setWidth(anchorView.getWidth());
15637b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mAggregationSuggestionPopup.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED);
15647b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mAggregationSuggestionPopup.setAdapter(
15657b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                new AggregationSuggestionAdapter(
15667b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        getActivity(),
15677b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        /* listener =*/ this,
15687b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                        mAggregationSuggestionEngine.getSuggestions()));
15697b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mAggregationSuggestionPopup.setOnItemClickListener(new AdapterView.OnItemClickListener() {
15707b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            @Override
15717b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
15727b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                final AggregationSuggestionView suggestionView = (AggregationSuggestionView) view;
15737b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                suggestionView.handleItemClickEvent();
15747b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                UiClosables.closeQuietly(mAggregationSuggestionPopup);
15757b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                mAggregationSuggestionPopup = null;
15767b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            }
15777b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        });
15787b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mAggregationSuggestionPopup.show();
15797b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
15807b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15817b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
1582da20b47c2b85390a2c3772379e71203c5aab513cGary Mai     * Returns the editor view that should be used as the anchor for aggregation suggestions.
15837b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
1584da20b47c2b85390a2c3772379e71203c5aab513cGary Mai    protected View getAggregationAnchorView() {
1585d35e5eff8737e757a4179d49dfe9c7db999b4e9dWalter Jang        return getContent().getAggregationAnchorView();
1586d35e5eff8737e757a4179d49dfe9c7db999b4e9dWalter Jang    }
1587d35e5eff8737e757a4179d49dfe9c7db999b4e9dWalter Jang
15887b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
15897b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Joins the suggested contact (specified by the id's of constituent raw
15907b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * contacts), save all changes, and stay in the editor.
15917b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
15927b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    public void doJoinSuggestedContact(long[] rawContactIds) {
15937b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (!hasValidState() || mStatus != Status.EDITING) {
15947b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            return;
15957b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
15967b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
15977b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        mState.setJoinWithRawContacts(rawContactIds);
15987b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        save(SaveMode.RELOAD);
15997b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
16007b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
16017b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    @Override
1602678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai    public void onEditAction(Uri contactLookupUri, long rawContactId) {
1603678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai        SuggestionEditConfirmationDialogFragment.show(this, contactLookupUri, rawContactId);
16047b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
16057b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
16067b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
1607678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai     * Abandons the currently edited contact and switches to editing the selected raw contact,
1608678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai     * transferring all the data there
16097b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
1610678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai    public void doEditSuggestedContact(Uri contactUri, long rawContactId) {
16117b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (mListener != null) {
16127b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            // make sure we don't save this contact when closing down
16137b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            mStatus = Status.CLOSING;
1614678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai            mListener.onEditOtherRawContactRequested(contactUri, rawContactId,
1615678108ebb9926a79ad0d7ac4f11417dec1583d42Gary Mai                    getContent().getCurrentRawContactDelta().getContentValues());
16167b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
16177b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
16187b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
16197b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
16207b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Sets group metadata on all bound editors.
16217b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
162292f8ccc1f15df787b7434224857c056721281046Walter Jang    protected void setGroupMetaData() {
1623f10ca15ffa550b36805d2330fc210b58601a215cWalter Jang        if (mGroupMetaData != null) {
1624f10ca15ffa550b36805d2330fc210b58601a215cWalter Jang            getContent().setGroupMetaData(mGroupMetaData);
1625f10ca15ffa550b36805d2330fc210b58601a215cWalter Jang        }
16263f990ba4e35a99078d831c041290e574a320caa5Walter Jang    }
16273f990ba4e35a99078d831c041290e574a320caa5Walter Jang
16287b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
16297b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Persist the accumulated editor deltas.
16307b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     *
16317b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * @param joinContactId the raw contact ID to join the contact being saved to after the save,
16327b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     *         may be null.
16337b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
1634e3373dceb689209533e95a2cfbfbf1d9008ab6f6Walter Jang    protected boolean doSaveAction(int saveMode, Long joinContactId) {
163549ed2033f83005f92c30068ae33c3138d75e1825Walter Jang        final Intent intent = ContactSaveService.createSaveContactIntent(mContext, mState,
163649ed2033f83005f92c30068ae33c3138d75e1825Walter Jang                SAVE_MODE_EXTRA_KEY, saveMode, isEditingUserProfile(),
163749ed2033f83005f92c30068ae33c3138d75e1825Walter Jang                ((Activity) mContext).getClass(),
1638363af60ea23e5a3b945005712a16564ab69db18bGary Mai                ContactEditorActivity.ACTION_SAVE_COMPLETED, mUpdatedPhotos,
1639e3373dceb689209533e95a2cfbfbf1d9008ab6f6Walter Jang                JOIN_CONTACT_ID_EXTRA_KEY, joinContactId);
1640dd7d456a080f48d93aa3a9f9b04da0f17a8833a7Wenyi Wang        return startSaveService(mContext, intent, saveMode);
164149ed2033f83005f92c30068ae33c3138d75e1825Walter Jang    }
164249ed2033f83005f92c30068ae33c3138d75e1825Walter Jang
16437b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    private boolean startSaveService(Context context, Intent intent, int saveMode) {
16447b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        final boolean result = ContactSaveService.startService(
16457b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang                context, intent, saveMode);
16467b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        if (!result) {
16477b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang            onCancelEditConfirmed();
16487b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        }
16497b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang        return result;
16507b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    }
16517b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
16527b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
16537b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    // Join Activity
16547b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    //
16557b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang
16567b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang    /**
16577b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     * Performs aggregation with the contact selected by the user from suggestions or A-Z list.
16587b0970fd1db1a97f1be915d66d07f4dc8499f96dWalter Jang     */
165949ed2033f83005f92c30068ae33c3138d75e1825Walter Jang    protected void joinAggregate(final long contactId) {
166049ed2033f83005f92c30068ae33c3138d75e1825Walter Jang        final Intent intent = ContactSaveService.createJoinContactsIntent(
1661363af60ea23e5a3b945005712a16564ab69db18bGary Mai                mContext, mContactIdForJoin, contactId, ContactEditorActivity.class,
1662363af60ea23e5a3b945005712a16564ab69db18bGary Mai                ContactEditorActivity.ACTION_JOIN_COMPLETED);
166349ed2033f83005f92c30068ae33c3138d75e1825Walter Jang        mContext.startService(intent);
16643f990ba4e35a99078d831c041290e574a320caa5Walter Jang    }
1665b6ca272f26b47ecef8fafe94326c4d553576c521Walter Jang
166631a74ad969b650eb733e536569254ed3978c4f54Walter Jang    public void removePhoto() {
166731a74ad969b650eb733e536569254ed3978c4f54Walter Jang        getContent().removePhoto();
166831a74ad969b650eb733e536569254ed3978c4f54Walter Jang        mUpdatedPhotos.remove(String.valueOf(mPhotoRawContactId));
16690e72ce9d97e0133a5f7cc348eef363bef9395979Walter Jang    }
16700e72ce9d97e0133a5f7cc348eef363bef9395979Walter Jang
167131a74ad969b650eb733e536569254ed3978c4f54Walter Jang    public void updatePhoto(Uri uri) throws FileNotFoundException {
167231a74ad969b650eb733e536569254ed3978c4f54Walter Jang        final Bitmap bitmap = ContactPhotoUtils.getBitmapFromUri(getActivity(), uri);
167331a74ad969b650eb733e536569254ed3978c4f54Walter Jang        if (bitmap == null || bitmap.getHeight() <= 0 || bitmap.getWidth() <= 0) {
16749bc9ba878cf7f77a2a6b3200a6ab716d13f1affcWenyi Wang            Toast.makeText(mContext, R.string.contactPhotoSavedErrorToast,
167531a74ad969b650eb733e536569254ed3978c4f54Walter Jang                    Toast.LENGTH_SHORT).show();
167631a74ad969b650eb733e536569254ed3978c4f54Walter Jang            return;
16770e72ce9d97e0133a5f7cc348eef363bef9395979Walter Jang        }
167831a74ad969b650eb733e536569254ed3978c4f54Walter Jang        mUpdatedPhotos.putParcelable(String.valueOf(mPhotoRawContactId), uri);
167931a74ad969b650eb733e536569254ed3978c4f54Walter Jang        getContent().updatePhoto(uri);
16800e72ce9d97e0133a5f7cc348eef363bef9395979Walter Jang    }
16810e72ce9d97e0133a5f7cc348eef363bef9395979Walter Jang
1682da20b47c2b85390a2c3772379e71203c5aab513cGary Mai    public void setPrimaryPhoto() {
1683da20b47c2b85390a2c3772379e71203c5aab513cGary Mai        getContent().setPrimaryPhoto();
16840e72ce9d97e0133a5f7cc348eef363bef9395979Walter Jang    }
16850e72ce9d97e0133a5f7cc348eef363bef9395979Walter Jang
16860e72ce9d97e0133a5f7cc348eef363bef9395979Walter Jang    @Override
1687151f3e6883e5785019f7b5083dc8baf3e305dc18Walter Jang    public void onNameFieldChanged(long rawContactId, ValuesDelta valuesDelta) {
1688151f3e6883e5785019f7b5083dc8baf3e305dc18Walter Jang        final Activity activity = getActivity();
1689151f3e6883e5785019f7b5083dc8baf3e305dc18Walter Jang        if (activity == null || activity.isFinishing()) {
1690151f3e6883e5785019f7b5083dc8baf3e305dc18Walter Jang            return;
1691151f3e6883e5785019f7b5083dc8baf3e305dc18Walter Jang        }
169245b86d5e83a7d6eca4abe5cdfece2e9050b1809cWalter Jang        acquireAggregationSuggestions(activity, rawContactId, valuesDelta);
1693151f3e6883e5785019f7b5083dc8baf3e305dc18Walter Jang    }
1694151f3e6883e5785019f7b5083dc8baf3e305dc18Walter Jang
16955a7a23bdb698b8e741a425c9617c5e33e6314cddWalter Jang    @Override
1696708ea9e6f6f671178c0424f89e911000d4f330dcWalter Jang    public void onRebindEditorsForNewContact(RawContactDelta oldState,
1697708ea9e6f6f671178c0424f89e911000d4f330dcWalter Jang            AccountWithDataSet oldAccount, AccountWithDataSet newAccount) {
1698708ea9e6f6f671178c0424f89e911000d4f330dcWalter Jang        mNewContactAccountChanged = true;
1699708ea9e6f6f671178c0424f89e911000d4f330dcWalter Jang        rebindEditorsForNewContact(oldState, oldAccount, newAccount);
1700708ea9e6f6f671178c0424f89e911000d4f330dcWalter Jang    }
1701708ea9e6f6f671178c0424f89e911000d4f330dcWalter Jang
170279658e14360a4ec75530a9dcae338f48c9d5f043Walter Jang    @Override
170379658e14360a4ec75530a9dcae338f48c9d5f043Walter Jang    public void onBindEditorsFailed() {
170479658e14360a4ec75530a9dcae338f48c9d5f043Walter Jang        final Activity activity = getActivity();
170579658e14360a4ec75530a9dcae338f48c9d5f043Walter Jang        if (activity != null && !activity.isFinishing()) {
1706363af60ea23e5a3b945005712a16564ab69db18bGary Mai            Toast.makeText(activity, R.string.editor_failed_to_load,
170779658e14360a4ec75530a9dcae338f48c9d5f043Walter Jang                    Toast.LENGTH_SHORT).show();
170879658e14360a4ec75530a9dcae338f48c9d5f043Walter Jang            activity.setResult(Activity.RESULT_CANCELED);
170979658e14360a4ec75530a9dcae338f48c9d5f043Walter Jang            activity.finish();
171079658e14360a4ec75530a9dcae338f48c9d5f043Walter Jang        }
171179658e14360a4ec75530a9dcae338f48c9d5f043Walter Jang    }
171279658e14360a4ec75530a9dcae338f48c9d5f043Walter Jang
1713d675315606e8be431e6e5487e0b1cc33036a6ed7Walter Jang    @Override
1714d675315606e8be431e6e5487e0b1cc33036a6ed7Walter Jang    public void onEditorsBound() {
17153cb77bbf7119749ed4854a4b981fcabcf55823beWenyi Wang        final Activity activity = getActivity();
17163cb77bbf7119749ed4854a4b981fcabcf55823beWenyi Wang        if (activity == null || activity.isFinishing()) {
17173cb77bbf7119749ed4854a4b981fcabcf55823beWenyi Wang            return;
17183cb77bbf7119749ed4854a4b981fcabcf55823beWenyi Wang        }
1719d675315606e8be431e6e5487e0b1cc33036a6ed7Walter Jang        getLoaderManager().initLoader(LOADER_GROUPS, null, mGroupsLoaderListener);
1720d675315606e8be431e6e5487e0b1cc33036a6ed7Walter Jang    }
1721d675315606e8be431e6e5487e0b1cc33036a6ed7Walter Jang
172231a74ad969b650eb733e536569254ed3978c4f54Walter Jang    @Override
172331a74ad969b650eb733e536569254ed3978c4f54Walter Jang    public void onPhotoEditorViewClicked() {
17243f18d6197a54aad10bea9c5cc2c89ca82809e793Walter Jang        // For contacts composed of a single writable raw contact, or raw contacts have no more
17253f18d6197a54aad10bea9c5cc2c89ca82809e793Walter Jang        // than 1 photo, clicking the photo view simply opens the source photo dialog
172631a74ad969b650eb733e536569254ed3978c4f54Walter Jang        getEditorActivity().changePhoto(getPhotoMode());
172731a74ad969b650eb733e536569254ed3978c4f54Walter Jang    }
172831a74ad969b650eb733e536569254ed3978c4f54Walter Jang
172931a74ad969b650eb733e536569254ed3978c4f54Walter Jang    private int getPhotoMode() {
1730da20b47c2b85390a2c3772379e71203c5aab513cGary Mai        return getContent().isWritablePhotoSet() ? PhotoActionPopup.Modes.WRITE_ABLE_PHOTO
1731da20b47c2b85390a2c3772379e71203c5aab513cGary Mai                : PhotoActionPopup.Modes.NO_PHOTO;
173231a74ad969b650eb733e536569254ed3978c4f54Walter Jang    }
173331a74ad969b650eb733e536569254ed3978c4f54Walter Jang
1734363af60ea23e5a3b945005712a16564ab69db18bGary Mai    private ContactEditorActivity getEditorActivity() {
1735363af60ea23e5a3b945005712a16564ab69db18bGary Mai        return (ContactEditorActivity) getActivity();
173631a74ad969b650eb733e536569254ed3978c4f54Walter Jang    }
173731a74ad969b650eb733e536569254ed3978c4f54Walter Jang
1738363af60ea23e5a3b945005712a16564ab69db18bGary Mai    private RawContactEditorView getContent() {
1739363af60ea23e5a3b945005712a16564ab69db18bGary Mai        return (RawContactEditorView) mContent;
17403efae4aeae8715fbfcf67c56f123da49330ea01aWalter Jang    }
17413f990ba4e35a99078d831c041290e574a320caa5Walter Jang}
1742