QuickContactActivity.java revision 793e73c859ed839c28cc37d80d62bde0a361c78a
1edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann/*
2edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * Copyright (C) 2009 The Android Open Source Project
3edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann *
4edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * Licensed under the Apache License, Version 2.0 (the "License");
5edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * you may not use this file except in compliance with the License.
6edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * You may obtain a copy of the License at
7edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann *
8edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann *      http://www.apache.org/licenses/LICENSE-2.0
9edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann *
10edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * Unless required by applicable law or agreed to in writing, software
11edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * distributed under the License is distributed on an "AS IS" BASIS,
12edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * See the License for the specific language governing permissions and
14edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * limitations under the License.
15edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann */
16edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
17edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannpackage com.android.contacts.quickcontact;
18edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
19ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulosimport android.accounts.Account;
208a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwellimport android.animation.ArgbEvaluator;
21b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwellimport android.animation.ObjectAnimator;
22edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.app.Activity;
23d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport android.app.Fragment;
24cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmannimport android.app.LoaderManager.LoaderCallbacks;
25eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.app.SearchManager;
26752cccf954bd6070c5fb623875314951c8e9849dBrian Attwellimport android.content.ActivityNotFoundException;
27edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.content.ContentUris;
28ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulosimport android.content.ContentValues;
296bb01347eab60f95deafdfe523b0c368707210f3Brian Attwellimport android.content.Context;
30edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.content.Intent;
31cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmannimport android.content.Loader;
32dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulosimport android.content.pm.PackageManager;
33dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulosimport android.content.pm.ResolveInfo;
3423e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulosimport android.content.res.Resources;
3531b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport android.graphics.Bitmap;
3695c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwellimport android.graphics.BitmapFactory;
378a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwellimport android.graphics.Color;
38eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.graphics.PorterDuff;
39eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.graphics.PorterDuffColorFilter;
4031b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport android.graphics.drawable.BitmapDrawable;
418a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwellimport android.graphics.drawable.ColorDrawable;
4231b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport android.graphics.drawable.Drawable;
43eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.net.ParseException;
44edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.net.Uri;
45eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.net.WebAddress;
4631b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport android.os.AsyncTask;
47edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.os.Bundle;
488a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwellimport android.os.Trace;
49eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.provider.CalendarContract;
50752cccf954bd6070c5fb623875314951c8e9849dBrian Attwellimport android.provider.ContactsContract;
51edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Email;
52eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.provider.ContactsContract.CommonDataKinds.Event;
53eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.provider.ContactsContract.CommonDataKinds.GroupMembership;
54eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.provider.ContactsContract.CommonDataKinds.Identity;
55eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.provider.ContactsContract.CommonDataKinds.Im;
56eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.provider.ContactsContract.CommonDataKinds.Nickname;
57eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.provider.ContactsContract.CommonDataKinds.Note;
58eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.provider.ContactsContract.CommonDataKinds.Organization;
59edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Phone;
60eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.provider.ContactsContract.CommonDataKinds.Relation;
61edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.SipAddress;
62edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
63edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Website;
64752cccf954bd6070c5fb623875314951c8e9849dBrian Attwellimport android.provider.ContactsContract.Contacts;
6560e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulosimport android.provider.ContactsContract.Data;
66ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulosimport android.provider.ContactsContract.Directory;
67eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.provider.ContactsContract.DisplayNameSources;
68ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulosimport android.provider.ContactsContract.DataUsageFeedback;
69ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulosimport android.provider.ContactsContract.Intents;
70edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.QuickContact;
71edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.RawContacts;
7231b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport android.support.v7.graphics.Palette;
731cd88e3ecfa72f43c3fe25c912d9f67848f11e60Jay Shraunerimport android.telecomm.PhoneAccount;
7470e3f4f45c040a2d09bfb46462242b450cf20b29Nancy Chenimport android.telecomm.TelecommManager;
75edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.text.TextUtils;
76edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.util.Log;
772a4207fb39330e840436215c896cde911489e111Paul Soulosimport android.view.ContextMenu;
782a4207fb39330e840436215c896cde911489e111Paul Soulosimport android.view.ContextMenu.ContextMenuInfo;
79d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport android.view.Menu;
80d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport android.view.MenuInflater;
81eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.view.MenuItem;
82f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chenimport android.view.MotionEvent;
83edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.view.View;
84edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.view.View.OnClickListener;
852a4207fb39330e840436215c896cde911489e111Paul Soulosimport android.view.View.OnCreateContextMenuListener;
8610d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawaimport android.view.WindowManager;
87edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.widget.Toast;
88d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport android.widget.Toolbar;
89edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
9072b3ab1d8a62f228a540b05f4ed6373e494c7d72Christine Chenimport com.android.contacts.ContactSaveService;
91d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport com.android.contacts.ContactsActivity;
922d150da246632b1649999cfabed776133b097775Brian Attwellimport com.android.contacts.NfcHandler;
93e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.R;
94eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.CallUtil;
952a4207fb39330e840436215c896cde911489e111Paul Soulosimport com.android.contacts.common.ClipboardUtils;
96eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.Collapser;
97eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.ContactsUtils;
98d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport com.android.contacts.common.editor.SelectAccountDialogFragment;
9970e3f4f45c040a2d09bfb46462242b450cf20b29Nancy Chenimport com.android.contacts.common.interactions.TouchPointManager;
10031b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport com.android.contacts.common.lettertiles.LetterTileDrawable;
101752cccf954bd6070c5fb623875314951c8e9849dBrian Attwellimport com.android.contacts.common.list.ShortcutIntentBuilder;
102752cccf954bd6070c5fb623875314951c8e9849dBrian Attwellimport com.android.contacts.common.list.ShortcutIntentBuilder.OnShortcutIntentCreatedListener;
1030d5588da244d0992c3ff8f25d0875fdf95a8c644Chiao Chengimport com.android.contacts.common.model.AccountTypeManager;
104cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.Contact;
105cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.ContactLoader;
106cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.RawContact;
107428f008513d1591cc08fcfe2cf0c9237fb313241Chiao Chengimport com.android.contacts.common.model.account.AccountType;
108d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport com.android.contacts.common.model.account.AccountWithDataSet;
109cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.dataitem.DataItem;
110428f008513d1591cc08fcfe2cf0c9237fb313241Chiao Chengimport com.android.contacts.common.model.dataitem.DataKind;
111cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.dataitem.EmailDataItem;
112eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.EventDataItem;
113cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.dataitem.ImDataItem;
114eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.NicknameDataItem;
115eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.NoteDataItem;
116eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.OrganizationDataItem;
117b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulosimport com.android.contacts.common.model.dataitem.PhoneDataItem;
118eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.RelationDataItem;
119eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.SipAddressDataItem;
120eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.StructuredNameDataItem;
121eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.StructuredPostalDataItem;
122eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.WebsiteDataItem;
123eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.util.DateUtils;
124faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwellimport com.android.contacts.common.util.MaterialColorMapUtils;
125faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwellimport com.android.contacts.common.util.MaterialColorMapUtils.MaterialPalette;
126d41ab8ace81a2e44f8b28aa8782679b9e9cca1b9Brian Attwellimport com.android.contacts.common.util.ViewUtil;
127333091ae754ddfc25714c14b9b89534be24379f9Paul Soulosimport com.android.contacts.detail.ContactDisplayUtils;
128899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulosimport com.android.contacts.interactions.CalendarInteractionsLoader;
129ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulosimport com.android.contacts.interactions.CallLogInteractionsLoader;
1308a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwellimport com.android.contacts.interactions.ContactDeletionInteraction;
131b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulosimport com.android.contacts.interactions.ContactInteraction;
132b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulosimport com.android.contacts.interactions.SmsInteractionsLoader;
1332d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport com.android.contacts.quickcontact.ExpandingEntryCardView.Entry;
1342a4207fb39330e840436215c896cde911489e111Paul Soulosimport com.android.contacts.quickcontact.ExpandingEntryCardView.EntryContextMenuInfo;
1352ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulosimport com.android.contacts.quickcontact.ExpandingEntryCardView.EntryTag;
136e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwellimport com.android.contacts.quickcontact.ExpandingEntryCardView.ExpandingEntryCardViewListener;
137e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.util.ImageViewDrawableSetter;
138eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.util.PhoneCapabilityTester;
139b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwellimport com.android.contacts.util.SchedulingUtils;
140eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.util.StructuredPostalUtils;
141b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwellimport com.android.contacts.widget.MultiShrinkScroller;
142b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwellimport com.android.contacts.widget.MultiShrinkScroller.MultiShrinkScrollerListener;
14302eaf11669d25fd885606b3b0700358323532cddBrian Attwellimport com.android.contacts.widget.QuickContactImageView;
14402eaf11669d25fd885606b3b0700358323532cddBrian Attwell
145e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.google.common.base.Preconditions;
146e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.google.common.collect.Lists;
147e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Cheng
1482d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport java.util.ArrayList;
149899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulosimport java.util.Arrays;
150eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport java.util.Calendar;
151b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulosimport java.util.Collections;
152b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulosimport java.util.Comparator;
153eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport java.util.Date;
154edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport java.util.HashMap;
155edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport java.util.List;
156b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulosimport java.util.Map;
157edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
158edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann/**
159edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * Mostly translucent {@link Activity} that shows QuickContact dialog. It loads
160edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * data asynchronously, and then shows a popup with details centered around
161edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * {@link Intent#getSourceBounds()}.
162edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann */
163d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellpublic class QuickContactActivity extends ContactsActivity {
1648a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell
1658a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell    /**
1668a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell     * QuickContacts immediately takes up the full screen. All possible information is shown.
1678a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell     * This value for {@link android.provider.ContactsContract.QuickContact#EXTRA_MODE}
1688a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell     * should only be used by the Contacts app.
1698a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell     */
1708a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell    public static final int MODE_FULLY_EXPANDED = 4;
1718a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell
172edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    private static final String TAG = "QuickContact";
173edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
1749b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell    private static final String KEY_THEME_COLOR = "theme_color";
1759b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell
1769b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell    private static final int ANIMATION_STATUS_BAR_COLOR_CHANGE_DURATION = 150;
1778a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell    private static final int REQUEST_CODE_CONTACT_EDITOR_ACTIVITY = 1;
178bfa9442453c1d86e11e56702f9b8ef0e8e0da0b1Brian Attwell    private static final int SCRIM_COLOR = Color.argb(0xC8, 0, 0, 0);
179ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos    private static final int REQUEST_CODE_CONTACT_SELECTION_ACTIVITY = 2;
180ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos    private static final String MIMETYPE_SMS = "vnd.android-dir/mms-sms";
181dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki
182752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell    /** This is the Intent action to install a shortcut in the launcher. */
183752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell    private static final String ACTION_INSTALL_SHORTCUT =
184752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell            "com.android.launcher.action.INSTALL_SHORTCUT";
185edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
186edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    @SuppressWarnings("deprecation")
187edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    private static final String LEGACY_AUTHORITY = android.provider.Contacts.AUTHORITY;
188edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
189e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos    private static final String MIMETYPE_GPLUS_PROFILE =
190e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos            "vnd.android.cursor.item/vnd.googleplus.profile";
191e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos    private static final String INTENT_DATA_GPLUS_PROFILE_ADD_TO_CIRCLE = "Add to circle";
192e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos    private static final String MIMETYPE_HANGOUTS =
193e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos            "vnd.android.cursor.item/vnd.googleplus.profile.comm";
194e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos    private static final String INTENT_DATA_HANGOUTS_VIDEO = "Start video call";
19548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos    private static final String CALL_ORIGIN_QUICK_CONTACTS_ACTIVITY =
19648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos            "com.android.contacts.quickcontact.QuickContactActivity";
197e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos
19863176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell    /**
19963176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell     * The URI used to load the the Contact. Once the contact is loaded, use Contact#getLookupUri()
20063176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell     * instead of referencing this URI.
20163176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell     */
202edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    private Uri mLookupUri;
203edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    private String[] mExcludeMimes;
2048a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell    private int mExtraMode;
2058a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell    private int mStatusBarColor;
2068a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell    private boolean mHasAlreadyBeenOpened;
20797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos    private boolean mOnlyOnePhoneNumber;
20897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos    private boolean mOnlyOneEmail;
209edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
21002eaf11669d25fd885606b3b0700358323532cddBrian Attwell    private QuickContactImageView mPhotoView;
211eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos    private ExpandingEntryCardView mContactCard;
2126095369885edcca566a812b551886e29c7ff8039Brian Attwell    private ExpandingEntryCardView mNoContactDetailsCard;
213b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos    private ExpandingEntryCardView mRecentCard;
214eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos    private ExpandingEntryCardView mAboutCard;
215b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell    private MultiShrinkScroller mScroller;
216d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell    private SelectAccountDialogFragmentListener mSelectAccountFragmentListener;
2176bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell    private AsyncTask<Void, Void, Cp2DataCardModel> mEntriesAndActionsTask;
21830e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell    private AsyncTask<Void, Void, Void> mRecentDataTask;
2196bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell    /**
2206bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell     * The last copy of Cp2DataCardModel that was passed to {@link #populateContactAndAboutCard}.
2216bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell     */
2226bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell    private Cp2DataCardModel mCachedCp2DataCardModel;
223f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell    /**
224f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell     *  This scrim's opacity is controlled in two different ways. 1) Before the initial entrance
225f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell     *  animation finishes, the opacity is animated by a value animator. This is designed to
226f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell     *  distract the user from the length of the initial loading time. 2) After the initial
227f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell     *  entrance animation, the opacity is directly related to scroll position.
228f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell     */
2299b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell    private ColorDrawable mWindowScrim;
230f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell    private boolean mIsEntranceAnimationFinished;
231a3859ed9ff9f315d492e199620a08ae35ab8569fBrian Attwell    private MaterialColorMapUtils mMaterialColorMapUtils;
2328477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell    private boolean mIsExitAnimationInProgress;
2338571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell    private boolean mHasComputedThemeColor;
234edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
235a42ef76251778161d27bc07db214b8c81720e476Paul Soulos    /**
236a42ef76251778161d27bc07db214b8c81720e476Paul Soulos     * Used to stop the ExpandingEntry cards from adjusting between an entry click and the intent
237a42ef76251778161d27bc07db214b8c81720e476Paul Soulos     * being launched.
238a42ef76251778161d27bc07db214b8c81720e476Paul Soulos     */
239a42ef76251778161d27bc07db214b8c81720e476Paul Soulos    private boolean mHasIntentLaunched;
240a42ef76251778161d27bc07db214b8c81720e476Paul Soulos
2416cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee    private Contact mContactData;
2429815d7f98baf80ce51b0cf1f01f48a3dbb9a9db9Daniel Lehmann    private ContactLoader mContactLoader;
2439b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell    private PorterDuffColorFilter mColorFilter;
2449815d7f98baf80ce51b0cf1f01f48a3dbb9a9db9Daniel Lehmann
2459758a92fac3e9f64892d893c992f6020d7fe3bfdJosh Gargus    private final ImageViewDrawableSetter mPhotoSetter = new ImageViewDrawableSetter();
2469758a92fac3e9f64892d893c992f6020d7fe3bfdJosh Gargus
247edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    /**
248cb4fcc7ef75c33411d2b900db7933c5bc4336527Paul Soulos     * {@link #LEADING_MIMETYPES} is used to sort MIME-types.
249edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     *
250edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     * <p>The MIME-types in {@link #LEADING_MIMETYPES} appear in the front of the dialog,
251edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     * in the order specified here.</p>
252edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     */
253edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    private static final List<String> LEADING_MIMETYPES = Lists.newArrayList(
254cb4fcc7ef75c33411d2b900db7933c5bc4336527Paul Soulos            Phone.CONTENT_ITEM_TYPE, SipAddress.CONTENT_ITEM_TYPE, Email.CONTENT_ITEM_TYPE,
255405ae406379ad9c47770783afc76a660f6c55fcaPaul Soulos            StructuredPostal.CONTENT_ITEM_TYPE);
256edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
257a153dba33c2152332c5706178a367f52b0550723Paul Soulos    private static final List<String> SORTED_ABOUT_CARD_MIMETYPES = Lists.newArrayList(
258a153dba33c2152332c5706178a367f52b0550723Paul Soulos            Nickname.CONTENT_ITEM_TYPE,
259a153dba33c2152332c5706178a367f52b0550723Paul Soulos            // Phonetic name is inserted after nickname if it is available.
260a153dba33c2152332c5706178a367f52b0550723Paul Soulos            // No mimetype for phonetic name exists.
261a153dba33c2152332c5706178a367f52b0550723Paul Soulos            Website.CONTENT_ITEM_TYPE,
262a153dba33c2152332c5706178a367f52b0550723Paul Soulos            Organization.CONTENT_ITEM_TYPE,
263a153dba33c2152332c5706178a367f52b0550723Paul Soulos            Event.CONTENT_ITEM_TYPE,
264a153dba33c2152332c5706178a367f52b0550723Paul Soulos            Relation.CONTENT_ITEM_TYPE,
265a153dba33c2152332c5706178a367f52b0550723Paul Soulos            Im.CONTENT_ITEM_TYPE,
266a153dba33c2152332c5706178a367f52b0550723Paul Soulos            GroupMembership.CONTENT_ITEM_TYPE,
267a153dba33c2152332c5706178a367f52b0550723Paul Soulos            Identity.CONTENT_ITEM_TYPE,
268a153dba33c2152332c5706178a367f52b0550723Paul Soulos            Note.CONTENT_ITEM_TYPE);
269eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos
270b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos    /** Id for the background contact loader */
271b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos    private static final int LOADER_CONTACT_ID = 0;
272b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos
273ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    private static final String KEY_LOADER_EXTRA_PHONES =
274ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos            QuickContactActivity.class.getCanonicalName() + ".KEY_LOADER_EXTRA_PHONES";
275ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos
276b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos    /** Id for the background Sms Loader */
277b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos    private static final int LOADER_SMS_ID = 1;
278b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos    private static final int MAX_SMS_RETRIEVE = 3;
279ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos
280ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    /** Id for the back Calendar Loader */
281899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos    private static final int LOADER_CALENDAR_ID = 2;
282ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    private static final String KEY_LOADER_EXTRA_EMAILS =
283ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos            QuickContactActivity.class.getCanonicalName() + ".KEY_LOADER_EXTRA_EMAILS";
284899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos    private static final int MAX_PAST_CALENDAR_RETRIEVE = 3;
285899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos    private static final int MAX_FUTURE_CALENDAR_RETRIEVE = 3;
286899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos    private static final long PAST_MILLISECOND_TO_SEARCH_LOCAL_CALENDAR =
28740d7a65c6e68967f3f486715b194c144d93c296fPaul Soulos            1L * 24L * 60L * 60L * 1000L /* 1 day */;
288899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos    private static final long FUTURE_MILLISECOND_TO_SEARCH_LOCAL_CALENDAR =
28940d7a65c6e68967f3f486715b194c144d93c296fPaul Soulos            7L * 24L * 60L * 60L * 1000L /* 7 days */;
290899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos
291ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    /** Id for the background Call Log Loader */
292ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    private static final int LOADER_CALL_LOG_ID = 3;
293ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    private static final int MAX_CALL_LOG_RETRIEVE = 3;
2946095369885edcca566a812b551886e29c7ff8039Brian Attwell    private static final int MIN_NUM_CONTACT_ENTRIES_SHOWN = 3;
2956095369885edcca566a812b551886e29c7ff8039Brian Attwell    private static final int MIN_NUM_COLLAPSED_RECENT_ENTRIES_SHOWN = 3;
2966095369885edcca566a812b551886e29c7ff8039Brian Attwell    private static final int CARD_ENTRY_ID_EDIT_CONTACT = -2;
297ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos
298ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos
299ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    private static final int[] mRecentLoaderIds = new int[]{
300ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos        LOADER_SMS_ID,
301ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos        LOADER_CALENDAR_ID,
302ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos        LOADER_CALL_LOG_ID};
303a8fce966f48d84af82f5ad767aa7986740ca7b26Paul Soulos    private Map<Integer, List<ContactInteraction>> mRecentLoaderResults = new HashMap<>();
304b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos
305d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell    private static final String FRAGMENT_TAG_SELECT_ACCOUNT = "select_account_fragment";
3066cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee
3072d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    final OnClickListener mEntryClickHandler = new OnClickListener() {
3082d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        @Override
3092d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        public void onClick(View v) {
3102ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos            final Object entryTagObject = v.getTag();
3112ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos            if (entryTagObject == null || !(entryTagObject instanceof EntryTag)) {
3122ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos                Log.w(TAG, "EntryTag was not used correctly");
3136095369885edcca566a812b551886e29c7ff8039Brian Attwell                return;
3146095369885edcca566a812b551886e29c7ff8039Brian Attwell            }
3152ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos            final EntryTag entryTag = (EntryTag) entryTagObject;
3162ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos            final Intent intent = entryTag.getIntent();
3172ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos            final int dataId = entryTag.getId();
3182ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos
3192ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos            if (dataId == CARD_ENTRY_ID_EDIT_CONTACT) {
3202ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos                editContact();
3212d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos                return;
3222d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            }
323ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos
324ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos            // Default to USAGE_TYPE_CALL. Usage is summed among all types for sorting each data id
325ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos            // so the exact usage type is not necessary in all cases
326ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos            String usageType = DataUsageFeedback.USAGE_TYPE_CALL;
327ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos
32820bdf9d2d21e1c82513f798ef4205b9d1713996dPaul Soulos            final Uri intentUri = intent.getData();
32920bdf9d2d21e1c82513f798ef4205b9d1713996dPaul Soulos            if ((intentUri != null && intentUri.getScheme() != null &&
3301cd88e3ecfa72f43c3fe25c912d9f67848f11e60Jay Shrauner                    intentUri.getScheme().equals(ContactsUtils.SCHEME_SMSTO)) ||
331ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos                    (intent.getType() != null && intent.getType().equals(MIMETYPE_SMS))) {
332ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos                usageType = DataUsageFeedback.USAGE_TYPE_SHORT_TEXT;
333ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos            }
334ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos
335ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos            // Data IDs start at 1 so anything less is invalid
336ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos            if (dataId > 0) {
33720bdf9d2d21e1c82513f798ef4205b9d1713996dPaul Soulos                final Uri dataUsageUri = DataUsageFeedback.FEEDBACK_URI.buildUpon()
338ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos                        .appendPath(String.valueOf(dataId))
339ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos                        .appendQueryParameter(DataUsageFeedback.USAGE_TYPE, usageType)
340ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos                        .build();
341ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos                final boolean successful = getContentResolver().update(
34220bdf9d2d21e1c82513f798ef4205b9d1713996dPaul Soulos                        dataUsageUri, new ContentValues(), null, null) > 0;
343ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos                if (!successful) {
344ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos                    Log.w(TAG, "DataUsageFeedback increment failed");
345ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos                }
346ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos            } else {
347ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos                Log.w(TAG, "Invalid Data ID");
348ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos            }
349ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos
35070e3f4f45c040a2d09bfb46462242b450cf20b29Nancy Chen            // Pass the touch point through the intent for use in the InCallUI
35170e3f4f45c040a2d09bfb46462242b450cf20b29Nancy Chen            if (Intent.ACTION_CALL.equals(intent.getAction())) {
3521f8a3fda87bf61e579d61e3fdd246548943d070aNancy Chen                if (TouchPointManager.getInstance().hasValidPoint()) {
35370e3f4f45c040a2d09bfb46462242b450cf20b29Nancy Chen                    Bundle extras = new Bundle();
3541f8a3fda87bf61e579d61e3fdd246548943d070aNancy Chen                    extras.putParcelable(TouchPointManager.TOUCH_POINT,
3551f8a3fda87bf61e579d61e3fdd246548943d070aNancy Chen                            TouchPointManager.getInstance().getPoint());
35670e3f4f45c040a2d09bfb46462242b450cf20b29Nancy Chen                    intent.putExtra(TelecommManager.EXTRA_OUTGOING_CALL_EXTRAS, extras);
35770e3f4f45c040a2d09bfb46462242b450cf20b29Nancy Chen                }
35870e3f4f45c040a2d09bfb46462242b450cf20b29Nancy Chen            }
35970e3f4f45c040a2d09bfb46462242b450cf20b29Nancy Chen
360793e73c859ed839c28cc37d80d62bde0a361c78aPaul Soulos            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
361793e73c859ed839c28cc37d80d62bde0a361c78aPaul Soulos
362a42ef76251778161d27bc07db214b8c81720e476Paul Soulos            mHasIntentLaunched = true;
363ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos            startActivity(intent);
3642d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
3652d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    };
3662d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
367e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell    final ExpandingEntryCardViewListener mExpandingEntryCardViewListener
368e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell            = new ExpandingEntryCardViewListener() {
369e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell        @Override
370e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell        public void onCollapse(int heightDelta) {
371e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell            mScroller.prepareForShrinkingScrollChild(heightDelta);
372e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell        }
3730cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
3740cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        @Override
3750cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        public void onExpand(int heightDelta) {
3760cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos            mScroller.prepareForExpandingScrollChild();
3770cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        }
378e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell    };
379e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell
38097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos    private interface ContextMenuIds {
38197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos        static final int COPY_TEXT = 0;
38297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos        static final int CLEAR_DEFAULT = 1;
38397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos        static final int SET_DEFAULT = 2;
38497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos    }
38597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos
3862a4207fb39330e840436215c896cde911489e111Paul Soulos    private final OnCreateContextMenuListener mEntryContextMenuListener =
3872a4207fb39330e840436215c896cde911489e111Paul Soulos            new OnCreateContextMenuListener() {
3882a4207fb39330e840436215c896cde911489e111Paul Soulos        @Override
3892a4207fb39330e840436215c896cde911489e111Paul Soulos        public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
3902a4207fb39330e840436215c896cde911489e111Paul Soulos            if (menuInfo == null) {
3912a4207fb39330e840436215c896cde911489e111Paul Soulos                return;
3922a4207fb39330e840436215c896cde911489e111Paul Soulos            }
39397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            final EntryContextMenuInfo info = (EntryContextMenuInfo) menuInfo;
3942a4207fb39330e840436215c896cde911489e111Paul Soulos            menu.setHeaderTitle(info.getCopyText());
39597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            menu.add(ContextMenu.NONE, ContextMenuIds.COPY_TEXT,
39697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                    ContextMenu.NONE, getString(R.string.copy_text));
39797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos
39897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            // Don't allow setting or clearing of defaults for non-editable contacts
39997f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            if (!isContactEditable()) {
40097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                return;
40197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            }
40297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos
40397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            final String selectedMimeType = info.getMimeType();
40497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos
40597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            // Defaults to true will only enable the detail to be copied to the clipboard.
40697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            boolean onlyOneOfMimeType = true;
40797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos
40897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            // Only allow primary support for Phone and Email content types
40997f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            if (Phone.CONTENT_ITEM_TYPE.equals(selectedMimeType)) {
41097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                onlyOneOfMimeType = mOnlyOnePhoneNumber;
41197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            } else if (Email.CONTENT_ITEM_TYPE.equals(selectedMimeType)) {
41297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                onlyOneOfMimeType = mOnlyOneEmail;
41397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            }
41497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos
41597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            // Checking for previously set default
41697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            if (info.isSuperPrimary()) {
41797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                menu.add(ContextMenu.NONE, ContextMenuIds.CLEAR_DEFAULT,
41897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                        ContextMenu.NONE, getString(R.string.clear_default));
41997f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            } else if (!onlyOneOfMimeType) {
42097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                menu.add(ContextMenu.NONE, ContextMenuIds.SET_DEFAULT,
42197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                        ContextMenu.NONE, getString(R.string.set_default));
42297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            }
4232a4207fb39330e840436215c896cde911489e111Paul Soulos        }
4242a4207fb39330e840436215c896cde911489e111Paul Soulos    };
4252a4207fb39330e840436215c896cde911489e111Paul Soulos
4262a4207fb39330e840436215c896cde911489e111Paul Soulos    @Override
4272a4207fb39330e840436215c896cde911489e111Paul Soulos    public boolean onContextItemSelected(MenuItem item) {
4282a4207fb39330e840436215c896cde911489e111Paul Soulos        EntryContextMenuInfo menuInfo;
4292a4207fb39330e840436215c896cde911489e111Paul Soulos        try {
4302a4207fb39330e840436215c896cde911489e111Paul Soulos            menuInfo = (EntryContextMenuInfo) item.getMenuInfo();
4312a4207fb39330e840436215c896cde911489e111Paul Soulos        } catch (ClassCastException e) {
4322a4207fb39330e840436215c896cde911489e111Paul Soulos            Log.e(TAG, "bad menuInfo", e);
4332a4207fb39330e840436215c896cde911489e111Paul Soulos            return false;
4342a4207fb39330e840436215c896cde911489e111Paul Soulos        }
4352a4207fb39330e840436215c896cde911489e111Paul Soulos
43697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos        switch (item.getItemId()) {
43797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            case ContextMenuIds.COPY_TEXT:
43897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                ClipboardUtils.copyText(this, menuInfo.getCopyLabel(), menuInfo.getCopyText(),
43997f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                        true);
44097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                return true;
44197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            case ContextMenuIds.SET_DEFAULT:
44297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                final Intent setIntent = ContactSaveService.createSetSuperPrimaryIntent(this,
44397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                        menuInfo.getId());
44497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                this.startService(setIntent);
44597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                return true;
44697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            case ContextMenuIds.CLEAR_DEFAULT:
44797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                final Intent clearIntent = ContactSaveService.createClearPrimaryIntent(this,
44897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                        menuInfo.getId());
44997f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                this.startService(clearIntent);
45097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                return true;
45197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            default:
45297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                throw new IllegalArgumentException("Unknown menu option " + item.getItemId());
45397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos        }
4542a4207fb39330e840436215c896cde911489e111Paul Soulos    }
4552a4207fb39330e840436215c896cde911489e111Paul Soulos
456d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell    /**
457d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell     * Headless fragment used to handle account selection callbacks invoked from
458d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell     * {@link DirectoryContactUtil}.
459d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell     */
460d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell    public static class SelectAccountDialogFragmentListener extends Fragment
461d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell            implements SelectAccountDialogFragment.Listener {
462d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell
463d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        private QuickContactActivity mQuickContactActivity;
464d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell
465d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        public SelectAccountDialogFragmentListener() {}
466d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell
467d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        @Override
468d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        public void onAccountChosen(AccountWithDataSet account, Bundle extraArgs) {
469d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell            DirectoryContactUtil.createCopy(mQuickContactActivity.mContactData.getContentValues(),
470d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell                    account, mQuickContactActivity);
471d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        }
472d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell
473d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        @Override
474d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        public void onAccountSelectorCancelled() {}
475d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell
476d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        /**
477d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell         * Set the parent activity. Since rotation can cause this fragment to be used across
478d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell         * more than one activity instance, we need to explicitly set this value instead
479d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell         * of making this class non-static.
480d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell         */
481d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        public void setQuickContactActivity(QuickContactActivity quickContactActivity) {
482d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell            mQuickContactActivity = quickContactActivity;
483d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        }
484d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell    }
485d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell
486b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell    final MultiShrinkScrollerListener mMultiShrinkScrollerListener
487b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell            = new MultiShrinkScrollerListener() {
488b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell        @Override
489b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell        public void onScrolledOffBottom() {
490f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell            finish();
491b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell        }
4928a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell
4938a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        @Override
4948a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        public void onEnterFullscreen() {
4958a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell            updateStatusBarColor();
4968a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        }
4978a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell
4988a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        @Override
4998a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        public void onExitFullscreen() {
5008a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell            updateStatusBarColor();
5018a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        }
5028477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell
5038477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell        @Override
5048477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell        public void onStartScrollOffBottom() {
5058477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell            mIsExitAnimationInProgress = true;
5068477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell        }
5078477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell
5088477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell        @Override
509f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell        public void onEntranceAnimationDone() {
510f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell            mIsEntranceAnimationFinished = true;
511f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell        }
512f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell
513f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell        @Override
514f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell        public void onTransparentViewHeightChange(float ratio) {
515f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell            if (mIsEntranceAnimationFinished) {
516f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell                mWindowScrim.setAlpha((int) (0xFF * ratio));
5178477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell            }
5188477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell        }
519b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell    };
520b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell
521eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos
522eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos    /**
523eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos     * Data items are compared to the same mimetype based off of three qualities:
524eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos     * 1. Super primary
525eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos     * 2. Primary
526eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos     * 3. Times used
527eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos     */
528eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos    private final Comparator<DataItem> mWithinMimeTypeDataItemComparator =
529eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            new Comparator<DataItem>() {
530eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        @Override
531eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        public int compare(DataItem lhs, DataItem rhs) {
532eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            if (!lhs.getMimeType().equals(rhs.getMimeType())) {
533eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                Log.wtf(TAG, "Comparing DataItems with different mimetypes lhs.getMimeType(): " +
534eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                        lhs.getMimeType() + " rhs.getMimeType(): " + rhs.getMimeType());
535eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                return 0;
536eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            }
537eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos
538eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            if (lhs.isSuperPrimary()) {
539eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                return -1;
540eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            } else if (rhs.isSuperPrimary()) {
541eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                return 1;
542eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            } else if (lhs.isPrimary() && !rhs.isPrimary()) {
543eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                return -1;
544eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            } else if (!lhs.isPrimary() && rhs.isPrimary()) {
545eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                return 1;
546eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            } else {
547eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                final int lhsTimesUsed =
548eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                        lhs.getTimesUsed() == null ? 0 : lhs.getTimesUsed();
549eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                final int rhsTimesUsed =
550eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                        rhs.getTimesUsed() == null ? 0 : rhs.getTimesUsed();
551eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos
552eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                return rhsTimesUsed - lhsTimesUsed;
553eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            }
554eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        }
555eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos    };
556eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos
557cb4fcc7ef75c33411d2b900db7933c5bc4336527Paul Soulos    /**
558cb4fcc7ef75c33411d2b900db7933c5bc4336527Paul Soulos     * Sorts among different mimetypes based off:
559cb4fcc7ef75c33411d2b900db7933c5bc4336527Paul Soulos     * 1. Times used
560cb4fcc7ef75c33411d2b900db7933c5bc4336527Paul Soulos     * 2. Last time used
561cb4fcc7ef75c33411d2b900db7933c5bc4336527Paul Soulos     * 3. Statically defined
562cb4fcc7ef75c33411d2b900db7933c5bc4336527Paul Soulos     */
563eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos    private final Comparator<List<DataItem>> mAmongstMimeTypeDataItemComparator =
564eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            new Comparator<List<DataItem>> () {
565eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        @Override
566eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        public int compare(List<DataItem> lhsList, List<DataItem> rhsList) {
567eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            DataItem lhs = lhsList.get(0);
568eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            DataItem rhs = rhsList.get(0);
569eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            final int lhsTimesUsed = lhs.getTimesUsed() == null ? 0 : lhs.getTimesUsed();
570eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            final int rhsTimesUsed = rhs.getTimesUsed() == null ? 0 : rhs.getTimesUsed();
571eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            final int timesUsedDifference = rhsTimesUsed - lhsTimesUsed;
572eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            if (timesUsedDifference != 0) {
573eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                return timesUsedDifference;
574eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            }
575eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos
576eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            final long lhsLastTimeUsed =
577eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                    lhs.getLastTimeUsed() == null ? 0 : lhs.getLastTimeUsed();
578eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            final long rhsLastTimeUsed =
579eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                    rhs.getLastTimeUsed() == null ? 0 : rhs.getLastTimeUsed();
580eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            final long lastTimeUsedDifference = rhsLastTimeUsed - lhsLastTimeUsed;
581eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            if (lastTimeUsedDifference > 0) {
582eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                return 1;
583eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            } else if (lastTimeUsedDifference < 0) {
584eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                return -1;
585eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            }
586eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos
587eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            // Times used and last time used are the same. Resort to statically defined.
588eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            final String lhsMimeType = lhs.getMimeType();
589eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            final String rhsMimeType = rhs.getMimeType();
590eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            for (String mimeType : LEADING_MIMETYPES) {
591eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                if (lhsMimeType.equals(mimeType)) {
592eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                    return -1;
593eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                } else if (rhsMimeType.equals(mimeType)) {
594eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                    return 1;
595eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                }
596eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            }
597eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            return 0;
598eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        }
599eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos    };
600eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos
601edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    @Override
602f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chen    public boolean dispatchTouchEvent(MotionEvent ev) {
603f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chen        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
604f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chen            TouchPointManager.getInstance().setPoint((int) ev.getRawX(), (int) ev.getRawY());
605f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chen        }
606f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chen        return super.dispatchTouchEvent(ev);
607f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chen    }
608f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chen
609f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chen    @Override
6108a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell    protected void onCreate(Bundle savedInstanceState) {
6118a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        Trace.beginSection("onCreate()");
6128a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        super.onCreate(savedInstanceState);
613edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
6148a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        getWindow().setStatusBarColor(Color.TRANSPARENT);
6152426cb015ba4cb679a525bd1ffe223527375468cDaniel Lehmann
616d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        processIntent(getIntent());
617dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki
61810d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawa        // Show QuickContact in front of soft input
61910d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawa        getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
62010d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawa                WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
62110d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawa
622edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        setContentView(R.layout.quickcontact_activity);
623edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
624a3859ed9ff9f315d492e199620a08ae35ab8569fBrian Attwell        mMaterialColorMapUtils = new MaterialColorMapUtils(getResources());
625a3859ed9ff9f315d492e199620a08ae35ab8569fBrian Attwell
6260cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos        mScroller = (MultiShrinkScroller) findViewById(R.id.multiscroller);
6270cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos
628eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        mContactCard = (ExpandingEntryCardView) findViewById(R.id.communication_card);
6296095369885edcca566a812b551886e29c7ff8039Brian Attwell        mNoContactDetailsCard = (ExpandingEntryCardView) findViewById(R.id.no_contact_data_card);
630b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos        mRecentCard = (ExpandingEntryCardView) findViewById(R.id.recent_card);
631eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        mAboutCard = (ExpandingEntryCardView) findViewById(R.id.about_card);
632edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
6336095369885edcca566a812b551886e29c7ff8039Brian Attwell        mNoContactDetailsCard.setOnClickListener(mEntryClickHandler);
634eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        mContactCard.setOnClickListener(mEntryClickHandler);
635eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        mContactCard.setExpandButtonText(
63623889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos        getResources().getString(R.string.expanding_entry_card_view_see_all));
6372a4207fb39330e840436215c896cde911489e111Paul Soulos        mContactCard.setOnCreateContextMenuListener(mEntryContextMenuListener);
638b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos
639b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos        mRecentCard.setOnClickListener(mEntryClickHandler);
640b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos        mRecentCard.setTitle(getResources().getString(R.string.recent_card_title));
641edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
642eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        mAboutCard.setOnClickListener(mEntryClickHandler);
6432a4207fb39330e840436215c896cde911489e111Paul Soulos        mAboutCard.setOnCreateContextMenuListener(mEntryContextMenuListener);
644eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos
64502eaf11669d25fd885606b3b0700358323532cddBrian Attwell        mPhotoView = (QuickContactImageView) findViewById(R.id.photo);
64663176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell        final View transparentView = findViewById(R.id.transparent_view);
6470d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell        if (mScroller != null) {
64863176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell            transparentView.setOnClickListener(new OnClickListener() {
6490d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell                @Override
6500d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell                public void onClick(View v) {
6510d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell                    mScroller.scrollOffBottom();
6520d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell                }
6530d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell            });
6540d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell        }
655edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
656d41ab8ace81a2e44f8b28aa8782679b9e9cca1b9Brian Attwell        // Allow a shadow to be shown under the toolbar.
657d41ab8ace81a2e44f8b28aa8782679b9e9cca1b9Brian Attwell        ViewUtil.addRectangularOutlineProvider(findViewById(R.id.toolbar_parent), getResources());
658d41ab8ace81a2e44f8b28aa8782679b9e9cca1b9Brian Attwell
659d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
660d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        setActionBar(toolbar);
6619b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell        getActionBar().setTitle(null);
6629b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell        // Put a TextView with a known resource id into the ActionBar. This allows us to easily
6639b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell        // find the correct TextView location & size later.
6649b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell        toolbar.addView(getLayoutInflater().inflate(R.layout.quickcontact_title_placeholder, null));
6656219668d0612f7522bd15a9d34c6232cb15b9a6cYorke Lee
6668a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        mHasAlreadyBeenOpened = savedInstanceState != null;
667f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell        mIsEntranceAnimationFinished = mHasAlreadyBeenOpened;
6689b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell        mWindowScrim = new ColorDrawable(SCRIM_COLOR);
669f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell        mWindowScrim.setAlpha(0);
6709b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell        getWindow().setBackgroundDrawable(mWindowScrim);
671edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
672c33ae17c9816b770041ee1f9ccde10e7c7eee491Brian Attwell        mScroller.initialize(mMultiShrinkScrollerListener, mExtraMode == MODE_FULLY_EXPANDED);
673ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell        // mScroller needs to perform asynchronous measurements after initalize(), therefore
674ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell        // we can't mark this as GONE.
675ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell        mScroller.setVisibility(View.INVISIBLE);
6768a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell
6779b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell        setHeaderNameText(R.string.missing_name);
6789b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell
679d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        mSelectAccountFragmentListener= (SelectAccountDialogFragmentListener) getFragmentManager()
680d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell                .findFragmentByTag(FRAGMENT_TAG_SELECT_ACCOUNT);
681d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        if (mSelectAccountFragmentListener == null) {
682d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell            mSelectAccountFragmentListener = new SelectAccountDialogFragmentListener();
683d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell            getFragmentManager().beginTransaction().add(0, mSelectAccountFragmentListener,
684d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell                    FRAGMENT_TAG_SELECT_ACCOUNT).commit();
685d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell            mSelectAccountFragmentListener.setRetainInstance(true);
686d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        }
687d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        mSelectAccountFragmentListener.setQuickContactActivity(this);
68823889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos
689f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell        SchedulingUtils.doOnPreDraw(mScroller, /* drawNextFrame = */ true,
690f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell                new Runnable() {
691f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell                    @Override
692f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell                    public void run() {
693f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell                        if (!mHasAlreadyBeenOpened) {
694f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell                            // The initial scrim opacity must match the scrim opacity that would be
695f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell                            // achieved by scrolling to the starting position.
696f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell                            final float alphaRatio = mExtraMode == MODE_FULLY_EXPANDED ?
697f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell                                    1 : mScroller.getStartingTransparentHeightRatio();
698f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell                            final int duration = getResources().getInteger(
699f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell                                    android.R.integer.config_shortAnimTime);
700f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell                            final int desiredAlpha = (int) (0xFF * alphaRatio);
701f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell                            ObjectAnimator o = ObjectAnimator.ofInt(mWindowScrim, "alpha", 0,
702f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell                                    desiredAlpha).setDuration(duration);
703f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell
704f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell                            o.start();
705f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell                        }
706f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell                    }
707f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell                });
708f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell
7099b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell        if (savedInstanceState != null) {
7109b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell            final int color = savedInstanceState.getInt(KEY_THEME_COLOR, 0);
711ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell            SchedulingUtils.doOnPreDraw(mScroller, /* drawNextFrame = */ false,
712ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell                    new Runnable() {
713ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell                        @Override
714ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell                        public void run() {
715ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell                            // Need to wait for the pre draw before setting the initial scroll
716ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell                            // value. Prior to pre draw all scroll values are invalid.
717ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell                            if (mHasAlreadyBeenOpened) {
718ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell                                mScroller.setVisibility(View.VISIBLE);
719ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell                                mScroller.setScroll(mScroller.getScrollNeededToBeFullScreen());
720ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell                            }
721ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell                            // Need to wait for pre draw for setting the theme color. Setting the
722ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell                            // header tint before the MultiShrinkScroller has been measured will
723ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell                            // cause incorrect tinting calculations.
724ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell                            if (color != 0) {
725a3859ed9ff9f315d492e199620a08ae35ab8569fBrian Attwell                                setThemeColor(mMaterialColorMapUtils
726a3859ed9ff9f315d492e199620a08ae35ab8569fBrian Attwell                                        .calculatePrimaryAndSecondaryColor(color));
7279b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell                            }
728ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell                        }
729ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell                    });
7309b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell        }
7319b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell
7328a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        Trace.endSection();
7338a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell    }
7348a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell
735405ae406379ad9c47770783afc76a660f6c55fcaPaul Soulos    @Override
736405ae406379ad9c47770783afc76a660f6c55fcaPaul Soulos    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
7378a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        if (requestCode == REQUEST_CODE_CONTACT_EDITOR_ACTIVITY &&
7388a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell                resultCode == ContactDeletionInteraction.RESULT_CODE_DELETED) {
7398a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell            // The contact that we were showing has been deleted.
7408a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell            finish();
741ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos        } else if (requestCode == REQUEST_CODE_CONTACT_SELECTION_ACTIVITY &&
742ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos                resultCode != RESULT_CANCELED) {
743ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos            processIntent(data);
744b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell        }
7458a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell    }
746dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki
7478a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell    @Override
7488a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell    protected void onNewIntent(Intent intent) {
7498a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        super.onNewIntent(intent);
7508a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        mHasAlreadyBeenOpened = true;
751f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell        mIsEntranceAnimationFinished = true;
7528571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell        mHasComputedThemeColor = false;
753d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        processIntent(intent);
754d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell    }
755d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell
7569b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell    @Override
7579b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell    public void onSaveInstanceState(Bundle savedInstanceState) {
7589b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell        super.onSaveInstanceState(savedInstanceState);
7599b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell        if (mColorFilter != null) {
7609b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell            savedInstanceState.putInt(KEY_THEME_COLOR, mColorFilter.getColor());
7619b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell        }
7629b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell    }
7639b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell
764d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell    private void processIntent(Intent intent) {
765d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        Uri lookupUri = intent.getData();
766d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell
767d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        // Check to see whether it comes from the old version.
768d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        if (lookupUri != null && LEGACY_AUTHORITY.equals(lookupUri.getAuthority())) {
769d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell            final long rawContactId = ContentUris.parseId(lookupUri);
770d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell            lookupUri = RawContacts.getContactLookupUri(getContentResolver(),
771d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell                    ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId));
772d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        }
773d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        mExtraMode = getIntent().getIntExtra(QuickContact.EXTRA_MODE,
774d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell                QuickContact.MODE_LARGE);
775d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        final Uri oldLookupUri = mLookupUri;
776d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell
777d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        mLookupUri = Preconditions.checkNotNull(lookupUri, "missing lookupUri");
778d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        mExcludeMimes = intent.getStringArrayExtra(QuickContact.EXTRA_EXCLUDE_MIMES);
779d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        if (oldLookupUri == null) {
780d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell            mContactLoader = (ContactLoader) getLoaderManager().initLoader(
781d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell                    LOADER_CONTACT_ID, null, mLoaderContactCallbacks);
782d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        } else if (oldLookupUri != mLookupUri) {
783d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell            // After copying a directory contact, the contact URI changes. Therefore,
784d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell            // we need to restart the loader and reload the new contact.
785899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos            for (int interactionLoaderId : mRecentLoaderIds) {
786899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos                getLoaderManager().destroyLoader(interactionLoaderId);
787899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos            }
788405ae406379ad9c47770783afc76a660f6c55fcaPaul Soulos            mContactLoader = (ContactLoader) getLoaderManager().restartLoader(
789405ae406379ad9c47770783afc76a660f6c55fcaPaul Soulos                    LOADER_CONTACT_ID, null, mLoaderContactCallbacks);
790d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        }
7912d150da246632b1649999cfabed776133b097775Brian Attwell
7922d150da246632b1649999cfabed776133b097775Brian Attwell        NfcHandler.register(this, mLookupUri);
7932426cb015ba4cb679a525bd1ffe223527375468cDaniel Lehmann    }
794edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
795b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell    private void runEntranceAnimation() {
7968a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        if (mHasAlreadyBeenOpened) {
7978a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell            return;
7988a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        }
7998a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        mHasAlreadyBeenOpened = true;
800c33ae17c9816b770041ee1f9ccde10e7c7eee491Brian Attwell        mScroller.scrollUpForEntranceAnimation(mExtraMode != MODE_FULLY_EXPANDED);
801b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell    }
802b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell
80381281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan    /** Assign this string to the view if it is not empty. */
804d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell    private void setHeaderNameText(int resId) {
8059b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell        if (mScroller != null) {
806f43f573340fd9de5d30b43d7c96cac1ec9021e58Brian Attwell            mScroller.setTitle(getText(resId) == null ? null : getText(resId).toString());
8079b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell        }
80881281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan    }
80981281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan
81081281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan    /** Assign this string to the view if it is not empty. */
811f43f573340fd9de5d30b43d7c96cac1ec9021e58Brian Attwell    private void setHeaderNameText(String value) {
812d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        if (!TextUtils.isEmpty(value)) {
8139b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell            if (mScroller != null) {
814f43f573340fd9de5d30b43d7c96cac1ec9021e58Brian Attwell                mScroller.setTitle(value);
8159b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell            }
81681281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan        }
81781281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan    }
81881281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan
81981281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan    /**
820edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     * Check if the given MIME-type appears in the list of excluded MIME-types
821edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     * that the most-recent caller requested.
822edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     */
823edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    private boolean isMimeExcluded(String mimeType) {
824edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        if (mExcludeMimes == null) return false;
825edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        for (String excludedMime : mExcludeMimes) {
826edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann            if (TextUtils.equals(excludedMime, mimeType)) {
827edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann                return true;
828edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann            }
829edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        }
830edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        return false;
831edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    }
832edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
833edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    /**
834cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann     * Handle the result from the ContactLoader
835edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     */
8368a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell    private void bindContactData(final Contact data) {
8378a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        Trace.beginSection("bindContactData");
8386cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee        mContactData = data;
839d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        invalidateOptionsMenu();
840edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
8418a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        Trace.endSection();
8428a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        Trace.beginSection("Set display photo & name");
843dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki
84402eaf11669d25fd885606b3b0700358323532cddBrian Attwell        mPhotoView.setIsBusiness(mContactData.isDisplayNameFromOrganization());
8456219668d0612f7522bd15a9d34c6232cb15b9a6cYorke Lee        mPhotoSetter.setupContactPhoto(data, mPhotoView);
84631b2d42fb0889e61515d27314aa5a245147100daBrian Attwell        extractAndApplyTintFromPhotoViewAsynchronously();
8474936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell        analyzeWhitenessOfPhotoAsynchronously();
848333091ae754ddfc25714c14b9b89534be24379f9Paul Soulos        setHeaderNameText(ContactDisplayUtils.getDisplayName(this, data).toString());
849edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
8508a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        Trace.endSection();
851dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki
8526bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        mEntriesAndActionsTask = new AsyncTask<Void, Void, Cp2DataCardModel>() {
8538a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell
8548a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell            @Override
8556bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell            protected Cp2DataCardModel doInBackground(
856eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                    Void... params) {
857eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                return generateDataModelFromContact(data);
8588a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell            }
8598a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell
8608a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell            @Override
8616bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell            protected void onPostExecute(Cp2DataCardModel cardDataModel) {
8626bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell                super.onPostExecute(cardDataModel);
8638a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell                // Check that original AsyncTask parameters are still valid and the activity
8648a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell                // is still running before binding to UI. A new intent could invalidate
8658a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell                // the results, for example.
8668a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell                if (data == mContactData && !isCancelled()) {
8676bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell                    bindDataToCards(cardDataModel);
8688a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell                    showActivity();
8698a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell                }
8708a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell            }
8718a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        };
8728a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        mEntriesAndActionsTask.execute();
8738a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell    }
8748a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell
8756bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell    private void bindDataToCards(Cp2DataCardModel cp2DataCardModel) {
8766bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        startInteractionLoaders(cp2DataCardModel);
8776bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        populateContactAndAboutCard(cp2DataCardModel);
878eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos    }
879eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos
8806bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell    private void startInteractionLoaders(Cp2DataCardModel cp2DataCardModel) {
8816bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        final Map<String, List<DataItem>> dataItemsMap = cp2DataCardModel.dataItemsMap;
8826bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        final List<DataItem> phoneDataItems = dataItemsMap.get(Phone.CONTENT_ITEM_TYPE);
88397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos        if (phoneDataItems != null && phoneDataItems.size() == 1) {
88497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            mOnlyOnePhoneNumber = true;
88597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos        }
886eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        String[] phoneNumbers = null;
887eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        if (phoneDataItems != null) {
888eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            phoneNumbers = new String[phoneDataItems.size()];
889eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            for (int i = 0; i < phoneDataItems.size(); ++i) {
890eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                phoneNumbers[i] = ((PhoneDataItem) phoneDataItems.get(i)).getNumber();
891eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            }
892eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        }
893ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos        final Bundle phonesExtraBundle = new Bundle();
894eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        phonesExtraBundle.putStringArray(KEY_LOADER_EXTRA_PHONES, phoneNumbers);
895eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos
896eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        Trace.beginSection("start sms loader");
8978a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        getLoaderManager().initLoader(
8988a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell                LOADER_SMS_ID,
899ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos                phonesExtraBundle,
900ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos                mLoaderInteractionsCallbacks);
901ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos        Trace.endSection();
902ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos
903ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos        Trace.beginSection("start call log loader");
904ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos        getLoaderManager().initLoader(
905ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos                LOADER_CALL_LOG_ID,
906ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos                phonesExtraBundle,
9078a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell                mLoaderInteractionsCallbacks);
908899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos        Trace.endSection();
9098a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell
910eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos
911899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos        Trace.beginSection("start calendar loader");
9126bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        final List<DataItem> emailDataItems = dataItemsMap.get(Email.CONTENT_ITEM_TYPE);
91397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos        if (emailDataItems != null && emailDataItems.size() == 1) {
91497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            mOnlyOneEmail = true;
91597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos        }
916eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        String[] emailAddresses = null;
917eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        if (emailDataItems != null) {
918eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            emailAddresses = new String[emailDataItems.size()];
919eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            for (int i = 0; i < emailDataItems.size(); ++i) {
920eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                emailAddresses[i] = ((EmailDataItem) emailDataItems.get(i)).getAddress();
921eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            }
922eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        }
923ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos        final Bundle emailsExtraBundle = new Bundle();
924eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        emailsExtraBundle.putStringArray(KEY_LOADER_EXTRA_EMAILS, emailAddresses);
925899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos        getLoaderManager().initLoader(
926899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos                LOADER_CALENDAR_ID,
927ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos                emailsExtraBundle,
928899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos                mLoaderInteractionsCallbacks);
9298a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        Trace.endSection();
9308a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell    }
9318a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell
9328a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell    private void showActivity() {
9338a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        if (mScroller != null) {
9348a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell            mScroller.setVisibility(View.VISIBLE);
9358a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell            SchedulingUtils.doOnPreDraw(mScroller, /* drawNextFrame = */ false,
9368a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell                    new Runnable() {
9378a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell                        @Override
9388a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell                        public void run() {
9398a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell                            runEntranceAnimation();
9408a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell                        }
9418a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell                    });
9428a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        }
9438a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell    }
9448a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell
9456bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell    private List<List<Entry>> buildAboutCardEntries(Map<String, List<DataItem>> dataItemsMap) {
946a153dba33c2152332c5706178a367f52b0550723Paul Soulos        final List<List<Entry>> aboutCardEntries = new ArrayList<>();
947a153dba33c2152332c5706178a367f52b0550723Paul Soulos        for (String mimetype : SORTED_ABOUT_CARD_MIMETYPES) {
9486bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell            final List<DataItem> mimeTypeItems = dataItemsMap.get(mimetype);
949a153dba33c2152332c5706178a367f52b0550723Paul Soulos            if (mimeTypeItems == null) {
950a153dba33c2152332c5706178a367f52b0550723Paul Soulos                continue;
951a153dba33c2152332c5706178a367f52b0550723Paul Soulos            }
9526bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell            // Set aboutCardTitleOut = null, since SORTED_ABOUT_CARD_MIMETYPES doesn't contain
9536bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell            // the name mimetype.
9546bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell            final List<Entry> aboutEntries = dataItemsToEntries(mimeTypeItems,
9556bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell                    /* aboutCardTitleOut = */ null);
956a153dba33c2152332c5706178a367f52b0550723Paul Soulos            if (aboutEntries.size() > 0) {
957a153dba33c2152332c5706178a367f52b0550723Paul Soulos                aboutCardEntries.add(aboutEntries);
958a153dba33c2152332c5706178a367f52b0550723Paul Soulos            }
959a153dba33c2152332c5706178a367f52b0550723Paul Soulos        }
960a153dba33c2152332c5706178a367f52b0550723Paul Soulos        return aboutCardEntries;
961a153dba33c2152332c5706178a367f52b0550723Paul Soulos    }
962a153dba33c2152332c5706178a367f52b0550723Paul Soulos
963a42ef76251778161d27bc07db214b8c81720e476Paul Soulos    @Override
964a42ef76251778161d27bc07db214b8c81720e476Paul Soulos    protected void onResume() {
965a42ef76251778161d27bc07db214b8c81720e476Paul Soulos        super.onResume();
966a42ef76251778161d27bc07db214b8c81720e476Paul Soulos        // If returning from a launched activity, repopulate the contact and about card
967a42ef76251778161d27bc07db214b8c81720e476Paul Soulos        if (mHasIntentLaunched) {
968a42ef76251778161d27bc07db214b8c81720e476Paul Soulos            mHasIntentLaunched = false;
9696bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell            populateContactAndAboutCard(mCachedCp2DataCardModel);
970a42ef76251778161d27bc07db214b8c81720e476Paul Soulos        }
971a42ef76251778161d27bc07db214b8c81720e476Paul Soulos    }
972a42ef76251778161d27bc07db214b8c81720e476Paul Soulos
9736bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell    private void populateContactAndAboutCard(Cp2DataCardModel cp2DataCardModel) {
9746bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        mCachedCp2DataCardModel = cp2DataCardModel;
9756bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        if (mHasIntentLaunched || cp2DataCardModel == null) {
976a42ef76251778161d27bc07db214b8c81720e476Paul Soulos            return;
977a42ef76251778161d27bc07db214b8c81720e476Paul Soulos        }
978eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        Trace.beginSection("bind contact card");
979eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos
9806bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        final List<List<Entry>> contactCardEntries = cp2DataCardModel.contactCardEntries;
9816bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        final List<List<Entry>> aboutCardEntries = cp2DataCardModel.aboutCardEntries;
9826bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        final String customAboutCardName = cp2DataCardModel.customAboutCardName;
983eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos
984eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        if (contactCardEntries.size() > 0) {
985eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            mContactCard.initialize(contactCardEntries,
986eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                    /* numInitialVisibleEntries = */ MIN_NUM_CONTACT_ENTRIES_SHOWN,
987c8e2a91807b581194566eb45019fa16e2268b462Paul Soulos                    /* isExpanded = */ mContactCard.isExpanded(),
98889966b4ed8cc9d385e5ac6b4a7e9e08ada387eb0Paul Soulos                    /* isAlwaysExpanded = */ false,
9890cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos                    mExpandingEntryCardViewListener,
9900cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos                    mScroller);
991eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            mContactCard.setVisibility(View.VISIBLE);
992eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        } else {
993eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            mContactCard.setVisibility(View.GONE);
994eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        }
995eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        Trace.endSection();
9968a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell
997eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        Trace.beginSection("bind about card");
998c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos        // Phonetic name is not a data item, so the entry needs to be created separately
999c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos        final String phoneticName = mContactData.getPhoneticName();
1000c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos        if (!TextUtils.isEmpty(phoneticName)) {
1001c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos            Entry phoneticEntry = new Entry(/* viewId = */ -1,
1002c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos                    /* icon = */ null,
1003c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos                    getResources().getString(R.string.name_phonetic),
1004c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos                    phoneticName,
1005c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos                    /* text = */ null,
100623e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                    /* primaryContentDescription = */ null,
1007c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos                    /* intent = */ null,
1008c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos                    /* alternateIcon = */ null,
1009c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos                    /* alternateIntent = */ null,
1010c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos                    /* alternateContentDescription = */ null,
1011c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos                    /* shouldApplyColor = */ false,
10122a4207fb39330e840436215c896cde911489e111Paul Soulos                    /* isEditable = */ false,
10132a4207fb39330e840436215c896cde911489e111Paul Soulos                    /* EntryContextMenuInfo = */ new EntryContextMenuInfo(phoneticName,
101497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                            getResources().getString(R.string.name_phonetic),
101597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                            /* mimeType = */ null, /* id = */ -1, /* isPrimary = */ false),
101648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    /* thirdIcon = */ null,
101748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    /* thirdIntent = */ null,
101848290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos                    /* thirdContentDescription = */ null,
101948290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos                    /* iconResourceId = */ 0);
1020c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos            List<Entry> phoneticList = new ArrayList<>();
1021c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos            phoneticList.add(phoneticEntry);
1022a153dba33c2152332c5706178a367f52b0550723Paul Soulos            // Phonetic name comes after nickname. Check to see if the first entry type is nickname
1023a0fa4c18dc111ceea9ff47f35ee01fecc1003578Paul Soulos            if (aboutCardEntries.size() > 0 && aboutCardEntries.get(0).get(0).getHeader().equals(
1024a153dba33c2152332c5706178a367f52b0550723Paul Soulos                    getResources().getString(R.string.header_nickname_entry))) {
1025a153dba33c2152332c5706178a367f52b0550723Paul Soulos                aboutCardEntries.add(1, phoneticList);
1026a153dba33c2152332c5706178a367f52b0550723Paul Soulos            } else {
1027a153dba33c2152332c5706178a367f52b0550723Paul Soulos                aboutCardEntries.add(0, phoneticList);
1028a153dba33c2152332c5706178a367f52b0550723Paul Soulos            }
1029c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos        }
1030c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos
10316bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        if (!TextUtils.isEmpty(customAboutCardName)) {
10326bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell            mAboutCard.setTitle(customAboutCardName);
10336bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        }
10346bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell
1035cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos        if (aboutCardEntries.size() > 0) {
1036cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos            mAboutCard.initialize(aboutCardEntries,
1037cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                    /* numInitialVisibleEntries = */ 1,
1038cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                    /* isExpanded = */ true,
1039cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                    /* isAlwaysExpanded = */ true,
1040cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                    mExpandingEntryCardViewListener,
1041cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos                    mScroller);
1042cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos        }
10436095369885edcca566a812b551886e29c7ff8039Brian Attwell
10446095369885edcca566a812b551886e29c7ff8039Brian Attwell        if (contactCardEntries.size() == 0 && aboutCardEntries.size() == 0) {
10456095369885edcca566a812b551886e29c7ff8039Brian Attwell            initializeNoContactDetailCard();
10466095369885edcca566a812b551886e29c7ff8039Brian Attwell        } else {
10476095369885edcca566a812b551886e29c7ff8039Brian Attwell            mNoContactDetailsCard.setVisibility(View.GONE);
10486095369885edcca566a812b551886e29c7ff8039Brian Attwell        }
10496095369885edcca566a812b551886e29c7ff8039Brian Attwell
1050a8fce966f48d84af82f5ad767aa7986740ca7b26Paul Soulos        // If the Recent card is already initialized (all recent data is loaded), show the About
1051a8fce966f48d84af82f5ad767aa7986740ca7b26Paul Soulos        // card if it has entries. Otherwise About card visibility will be set in bindRecentData()
1052a8fce966f48d84af82f5ad767aa7986740ca7b26Paul Soulos        if (isAllRecentDataLoaded() && aboutCardEntries.size() > 0) {
1053a8fce966f48d84af82f5ad767aa7986740ca7b26Paul Soulos            mAboutCard.setVisibility(View.VISIBLE);
1054a8fce966f48d84af82f5ad767aa7986740ca7b26Paul Soulos        }
1055eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        Trace.endSection();
1056eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos    }
1057eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos
1058eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos    /**
10596095369885edcca566a812b551886e29c7ff8039Brian Attwell     * Create a card that shows "Add email" and "Add phone number" entries in grey.
10606095369885edcca566a812b551886e29c7ff8039Brian Attwell     */
10616095369885edcca566a812b551886e29c7ff8039Brian Attwell    private void initializeNoContactDetailCard() {
10626095369885edcca566a812b551886e29c7ff8039Brian Attwell        final Drawable phoneIcon = getResources().getDrawable(
10636095369885edcca566a812b551886e29c7ff8039Brian Attwell                R.drawable.ic_phone_24dp).mutate();
10646095369885edcca566a812b551886e29c7ff8039Brian Attwell        final Entry phonePromptEntry = new Entry(CARD_ENTRY_ID_EDIT_CONTACT,
10656095369885edcca566a812b551886e29c7ff8039Brian Attwell                phoneIcon, getString(R.string.quickcontact_add_phone_number),
106623e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                /* subHeader = */ null, /* text = */ null, /* primaryContentDescription = */ null,
106723e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                getEditContactIntent(),
1068dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos                /* alternateIcon = */ null, /* alternateIntent = */ null,
1069714455bba22b99d168a2e864dfbc74a6e30dfdb6Paul Soulos                /* alternateContentDescription = */ null, /* shouldApplyColor = */ true,
107048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                /* isEditable = */ false, /* EntryContextMenuInfo = */ null,
107148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                /* thirdIcon = */ null, /* thirdIntent = */ null,
107248290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos                /* thirdContentDescription = */ null, R.drawable.ic_phone_24dp);
10736095369885edcca566a812b551886e29c7ff8039Brian Attwell
10746095369885edcca566a812b551886e29c7ff8039Brian Attwell        final Drawable emailIcon = getResources().getDrawable(
10756095369885edcca566a812b551886e29c7ff8039Brian Attwell                R.drawable.ic_email_24dp).mutate();
10766095369885edcca566a812b551886e29c7ff8039Brian Attwell        final Entry emailPromptEntry = new Entry(CARD_ENTRY_ID_EDIT_CONTACT,
10776095369885edcca566a812b551886e29c7ff8039Brian Attwell                emailIcon, getString(R.string.quickcontact_add_email), /* subHeader = */ null,
107823e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                /* text = */ null, /* primaryContentDescription = */ null,
107923e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                getEditContactIntent(), /* alternateIcon = */ null,
1080dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos                /* alternateIntent = */ null, /* alternateContentDescription = */ null,
10812a4207fb39330e840436215c896cde911489e111Paul Soulos                /* shouldApplyColor = */ true, /* isEditable = */ false,
108248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                /* EntryContextMenuInfo = */ null, /* thirdIcon = */ null,
108348290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos                /* thirdIntent = */ null, /* thirdContentDescription = */ null,
108448290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos                R.drawable.ic_email_24dp);
10856095369885edcca566a812b551886e29c7ff8039Brian Attwell
10866095369885edcca566a812b551886e29c7ff8039Brian Attwell        final List<List<Entry>> promptEntries = new ArrayList<>();
10876095369885edcca566a812b551886e29c7ff8039Brian Attwell        promptEntries.add(new ArrayList<Entry>(1));
10886095369885edcca566a812b551886e29c7ff8039Brian Attwell        promptEntries.add(new ArrayList<Entry>(1));
10896095369885edcca566a812b551886e29c7ff8039Brian Attwell        promptEntries.get(0).add(phonePromptEntry);
10906095369885edcca566a812b551886e29c7ff8039Brian Attwell        promptEntries.get(1).add(emailPromptEntry);
10916095369885edcca566a812b551886e29c7ff8039Brian Attwell
10926095369885edcca566a812b551886e29c7ff8039Brian Attwell        final int subHeaderTextColor = getResources().getColor(
10936095369885edcca566a812b551886e29c7ff8039Brian Attwell                R.color.quickcontact_entry_sub_header_text_color);
10946095369885edcca566a812b551886e29c7ff8039Brian Attwell        final PorterDuffColorFilter greyColorFilter =
10956095369885edcca566a812b551886e29c7ff8039Brian Attwell                new PorterDuffColorFilter(subHeaderTextColor, PorterDuff.Mode.SRC_ATOP);
1096c8e2a91807b581194566eb45019fa16e2268b462Paul Soulos        mNoContactDetailsCard.initialize(promptEntries, 2, /* isExpanded = */ true,
10970cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos                /* isAlwaysExpanded = */ true, mExpandingEntryCardViewListener, mScroller);
10986095369885edcca566a812b551886e29c7ff8039Brian Attwell        mNoContactDetailsCard.setVisibility(View.VISIBLE);
10996095369885edcca566a812b551886e29c7ff8039Brian Attwell        mNoContactDetailsCard.setEntryHeaderColor(subHeaderTextColor);
11006095369885edcca566a812b551886e29c7ff8039Brian Attwell        mNoContactDetailsCard.setColorAndFilter(subHeaderTextColor, greyColorFilter);
11016095369885edcca566a812b551886e29c7ff8039Brian Attwell    }
11026095369885edcca566a812b551886e29c7ff8039Brian Attwell
11036095369885edcca566a812b551886e29c7ff8039Brian Attwell    /**
1104eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos     * Builds the {@link DataItem}s Map out of the Contact.
1105eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos     * @param data The contact to build the data from.
1106eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos     * @return A pair containing a list of data items sorted within mimetype and sorted
1107eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos     *  amongst mimetype. The map goes from mimetype string to the sorted list of data items within
1108eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos     *  mimetype
1109eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos     */
11106bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell    private Cp2DataCardModel generateDataModelFromContact(
1111eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            Contact data) {
1112eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        Trace.beginSection("Build data items map");
1113eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos
1114eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        final Map<String, List<DataItem>> dataItemsMap = new HashMap<>();
11158bf96e78497ea9c8c893bcb357fc1e3175fb2e9bBrian Attwell
11168a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        final ResolveCache cache = ResolveCache.getInstance(this);
1117851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu        for (RawContact rawContact : data.getRawContacts()) {
1118851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu            for (DataItem dataItem : rawContact.getDataItems()) {
1119eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                dataItem.setRawContactId(rawContact.getId());
1120eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos
1121851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu                final String mimeType = dataItem.getMimeType();
1122eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                if (mimeType == null) continue;
1123eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos
112447b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng                final AccountType accountType = rawContact.getAccountType(this);
112547b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng                final DataKind dataKind = AccountTypeManager.getInstance(this)
112647b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng                        .getKindOrFallback(accountType, mimeType);
1127eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                if (dataKind == null) continue;
1128cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann
1129eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                dataItem.setDataKind(dataKind);
1130b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos
1131eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                final boolean hasData = !TextUtils.isEmpty(dataItem.buildDataString(this,
1132eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                        dataKind));
1133899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos
1134eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                if (isMimeExcluded(mimeType) || !hasData) continue;
1135edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
1136eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                List<DataItem> dataItemListByType = dataItemsMap.get(mimeType);
1137eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                if (dataItemListByType == null) {
1138eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                    dataItemListByType = new ArrayList<>();
1139eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                    dataItemsMap.put(mimeType, dataItemListByType);
1140edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann                }
1141eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                dataItemListByType.add(dataItem);
1142edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann            }
1143edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        }
11448a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        Trace.endSection();
1145edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
1146eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        Trace.beginSection("sort within mimetypes");
114716339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos        /*
114816339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos         * Sorting is a multi part step. The end result is to a have a sorted list of the most
1149eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos         * used data items, one per mimetype. Then, within each mimetype, the list of data items
1150eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos         * for that type is also sorted, based off of {super primary, primary, times used} in that
1151eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos         * order.
115216339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos         */
1153eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        final List<List<DataItem>> dataItemsList = new ArrayList<>();
1154eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        for (List<DataItem> mimeTypeDataItems : dataItemsMap.values()) {
1155eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            // Remove duplicate data items
1156eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            Collapser.collapseList(mimeTypeDataItems, this);
1157eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            // Sort within mimetype
1158eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            Collections.sort(mimeTypeDataItems, mWithinMimeTypeDataItemComparator);
1159eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            // Add to the list of data item lists
1160eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            dataItemsList.add(mimeTypeDataItems);
1161edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        }
1162eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        Trace.endSection();
1163edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
1164eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        Trace.beginSection("sort amongst mimetypes");
1165eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        // Sort amongst mimetypes to bubble up the top data items for the contact card
1166eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        Collections.sort(dataItemsList, mAmongstMimeTypeDataItemComparator);
1167eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        Trace.endSection();
116816339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos
11696bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        Trace.beginSection("cp2 data items to entries");
11706bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell
11716bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        final List<List<Entry>> contactCardEntries = new ArrayList<>();
11726bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        final List<List<Entry>> aboutCardEntries = buildAboutCardEntries(dataItemsMap);
11736bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        final MutableString aboutCardName = new MutableString();
11746bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell
11756bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        for (int i = 0; i < dataItemsList.size(); ++i) {
11766bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell            final List<DataItem> dataItemsByMimeType = dataItemsList.get(i);
11776bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell            final DataItem topDataItem = dataItemsByMimeType.get(0);
11786bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell            if (SORTED_ABOUT_CARD_MIMETYPES.contains(topDataItem.getMimeType())) {
11796bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell                // About card mimetypes are built in buildAboutCardEntries, skip here
11806bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell                continue;
11816bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell            } else {
11826bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell                List<Entry> contactEntries = dataItemsToEntries(dataItemsList.get(i),
11836bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell                        aboutCardName);
11846bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell                if (contactEntries.size() > 0) {
11856bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell                    contactCardEntries.add(contactEntries);
11866bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell                }
11876bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell            }
11886bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        }
11896bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell
11906bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        Trace.endSection();
11916bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell
11926bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        final Cp2DataCardModel dataModel = new Cp2DataCardModel();
11936bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        dataModel.customAboutCardName = aboutCardName.value;
11946bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        dataModel.aboutCardEntries = aboutCardEntries;
11956bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        dataModel.contactCardEntries = contactCardEntries;
11966bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        dataModel.dataItemsMap = dataItemsMap;
11976bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        return dataModel;
11986bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell    }
11996bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell
12006bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell    /**
12016bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell     * Class used to hold the About card and Contact cards' data model that gets generated
12026bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell     * on a background thread. All data is from CP2.
12036bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell     */
12046bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell    private static class Cp2DataCardModel {
12056bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        /**
12066bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell         * A map between a mimetype string and the corresponding list of data items. The data items
12076bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell         * are in sorted order using mWithinMimeTypeDataItemComparator.
12086bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell         */
12096bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        public Map<String, List<DataItem>> dataItemsMap;
12106bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        public List<List<Entry>> aboutCardEntries;
12116bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        public List<List<Entry>> contactCardEntries;
12126bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        public String customAboutCardName;
12136bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell    }
12146bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell
12156bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell    private static class MutableString {
12166bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        public String value;
1217eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos    }
1218edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
1219eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos    /**
1220eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos     * Converts a {@link DataItem} into an {@link ExpandingEntryCardView.Entry} for display.
1221eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos     * If the {@link ExpandingEntryCardView.Entry} has no visual elements, null is returned.
12226bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell     *
12236bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell     * This runs on a background thread. This is set as static to avoid accidentally adding
12246bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell     * additional dependencies on unsafe things (like the Activity).
12256bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell     *
1226eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos     * @param dataItem The {@link DataItem} to convert.
1227eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos     * @return The {@link ExpandingEntryCardView.Entry}, or null if no visual elements are present.
1228eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos     */
12296bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell    private static Entry dataItemToEntry(DataItem dataItem,
12306bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell            Context context, Contact contactData,
12316bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell            final MutableString aboutCardName) {
1232eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        Drawable icon = null;
1233eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        String header = null;
1234eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        String subHeader = null;
1235eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        Drawable subHeaderIcon = null;
1236eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        String text = null;
1237eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        Drawable textIcon = null;
123823e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos        StringBuilder primaryContentDescription = new StringBuilder();
1239eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        Intent intent = null;
124048ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos        boolean shouldApplyColor = true;
1241dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        Drawable alternateIcon = null;
1242dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        Intent alternateIntent = null;
124323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos        StringBuilder alternateContentDescription = new StringBuilder();
1244eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        final boolean isEditable = false;
12452a4207fb39330e840436215c896cde911489e111Paul Soulos        EntryContextMenuInfo entryContextMenuInfo = null;
124648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        Drawable thirdIcon = null;
124748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        Intent thirdIntent = null;
124848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos        String thirdContentDescription = null;
124948290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos        int iconResourceId = 0;
1250eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos
12516bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        context = context.getApplicationContext();
125223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos        final Resources res = context.getResources();
1253eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        DataKind kind = dataItem.getDataKind();
1254eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos
1255eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        if (dataItem instanceof ImDataItem) {
1256eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            final ImDataItem im = (ImDataItem) dataItem;
12576bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell            intent = ContactsUtils.buildImIntent(context, im).first;
1258eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            final boolean isEmail = im.isCreatedFromEmail();
12597de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos            final int protocol;
12607de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos            if (!im.isProtocolValid()) {
12617de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos                protocol = Im.PROTOCOL_CUSTOM;
12627de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos            } else {
12637de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos                protocol = isEmail ? Im.PROTOCOL_GOOGLE_TALK : im.getProtocol();
12647de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos            }
12657de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos            if (protocol == Im.PROTOCOL_CUSTOM) {
12667de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos                // If the protocol is custom, display the "IM" entry header as well to distinguish
12677de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos                // this entry from other ones
126823e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                header = res.getString(R.string.header_im_entry);
126923e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                subHeader = Im.getProtocolLabel(res, protocol,
12707de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos                        im.getCustomProtocol()).toString();
12717de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos                text = im.getData();
12727de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos            } else {
127323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                header = Im.getProtocolLabel(res, protocol,
12747de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos                        im.getCustomProtocol()).toString();
12757de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos                subHeader = im.getData();
12767de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos            }
127797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            entryContextMenuInfo = new EntryContextMenuInfo(im.getData(), header,
127897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                    dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary());
1279eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        } else if (dataItem instanceof OrganizationDataItem) {
1280eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            final OrganizationDataItem organization = (OrganizationDataItem) dataItem;
128123e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos            header = res.getString(R.string.header_organization_entry);
1282eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            subHeader = organization.getCompany();
128397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header,
128497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                    dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary());
1285eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            text = organization.getTitle();
1286eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        } else if (dataItem instanceof NicknameDataItem) {
1287eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            final NicknameDataItem nickname = (NicknameDataItem) dataItem;
1288eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            // Build nickname entries
1289eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            final boolean isNameRawContact =
12906bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell                (contactData.getNameRawContactId() == dataItem.getRawContactId());
1291eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos
1292eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            final boolean duplicatesTitle =
1293eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                isNameRawContact
12946bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell                && contactData.getDisplayNameSource() == DisplayNameSources.NICKNAME;
1295eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos
1296eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            if (!duplicatesTitle) {
129723e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                header = res.getString(R.string.header_nickname_entry);
1298eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                subHeader = nickname.getName();
129997f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header,
130097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                        dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary());
1301eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            }
1302eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        } else if (dataItem instanceof NoteDataItem) {
1303eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            final NoteDataItem note = (NoteDataItem) dataItem;
130423e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos            header = res.getString(R.string.header_note_entry);
1305eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            subHeader = note.getNote();
130697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header,
130797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                    dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary());
1308eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        } else if (dataItem instanceof WebsiteDataItem) {
1309eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            final WebsiteDataItem website = (WebsiteDataItem) dataItem;
131023e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos            header = res.getString(R.string.header_website_entry);
1311eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            subHeader = website.getUrl();
131297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header,
131397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                    dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary());
1314eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            try {
13156bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell                final WebAddress webAddress = new WebAddress(website.buildDataString(context,
13166bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell                        kind));
1317eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                intent = new Intent(Intent.ACTION_VIEW, Uri.parse(webAddress.toString()));
1318eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            } catch (final ParseException e) {
13196bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell                Log.e(TAG, "Couldn't parse website: " + website.buildDataString(context, kind));
1320eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            }
1321eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        } else if (dataItem instanceof EventDataItem) {
1322eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            final EventDataItem event = (EventDataItem) dataItem;
13236bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell            final String dataString = event.buildDataString(context, kind);
1324eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            final Calendar cal = DateUtils.parseDate(dataString, false);
1325eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            if (cal != null) {
1326eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                final Date nextAnniversary =
1327eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                        DateUtils.getNextAnnualDate(cal);
1328eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                final Uri.Builder builder = CalendarContract.CONTENT_URI.buildUpon();
1329eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                builder.appendPath("time");
1330eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                ContentUris.appendId(builder, nextAnniversary.getTime());
1331eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                intent = new Intent(Intent.ACTION_VIEW).setData(builder.build());
1332eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            }
133323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos            header = res.getString(R.string.header_event_entry);
1334f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos            if (event.hasKindTypeColumn(kind)) {
133523e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                subHeader = Event.getTypeLabel(res, event.getKindTypeColumn(kind),
13367de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos                        event.getLabel()).toString();
1337f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos            }
13386bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell            text = DateUtils.formatDate(context, dataString);
133997f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            entryContextMenuInfo = new EntryContextMenuInfo(text, header,
134097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                    dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary());
1341eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        } else if (dataItem instanceof RelationDataItem) {
1342eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            final RelationDataItem relation = (RelationDataItem) dataItem;
13436bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell            final String dataString = relation.buildDataString(context, kind);
1344eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            if (!TextUtils.isEmpty(dataString)) {
1345eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                intent = new Intent(Intent.ACTION_SEARCH);
1346eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                intent.putExtra(SearchManager.QUERY, dataString);
1347eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                intent.setType(Contacts.CONTENT_TYPE);
1348eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            }
134923e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos            header = res.getString(R.string.header_relation_entry);
1350eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            subHeader = relation.getName();
135197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos            entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header,
135297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                    dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary());
1353f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos            if (relation.hasKindTypeColumn(kind)) {
135423e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                text = Relation.getTypeLabel(res,
13556bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell                        relation.getKindTypeColumn(kind),
1356f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos                        relation.getLabel()).toString();
1357f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos            }
1358eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        } else if (dataItem instanceof PhoneDataItem) {
1359eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            final PhoneDataItem phone = (PhoneDataItem) dataItem;
1360eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            if (!TextUtils.isEmpty(phone.getNumber())) {
136123e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                primaryContentDescription.append(res.getString(R.string.call_other)).append(" ");
13626bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell                header = phone.buildDataString(context, kind);
13632a4207fb39330e840436215c896cde911489e111Paul Soulos                entryContextMenuInfo = new EntryContextMenuInfo(header,
136497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                        res.getString(R.string.phoneLabelsGroup), dataItem.getMimeType(),
136597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                        dataItem.getId(), dataItem.isSuperPrimary());
1366f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos                if (phone.hasKindTypeColumn(kind)) {
136723e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                    text = Phone.getTypeLabel(res, phone.getKindTypeColumn(kind),
1368f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos                            phone.getLabel()).toString();
136923e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                    primaryContentDescription.append(text).append(" ");
1370f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos                }
137123e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                primaryContentDescription.append(header);
137223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                icon = res.getDrawable(R.drawable.ic_phone_24dp);
137348290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos                iconResourceId = R.drawable.ic_phone_24dp;
13746bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell                if (PhoneCapabilityTester.isPhone(context)) {
1375eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                    intent = CallUtil.getCallIntent(phone.getNumber());
137616339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos                }
1377dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos                alternateIntent = new Intent(Intent.ACTION_SENDTO,
13781cd88e3ecfa72f43c3fe25c912d9f67848f11e60Jay Shrauner                        Uri.fromParts(ContactsUtils.SCHEME_SMSTO, phone.getNumber(), null));
137948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos
138023e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                alternateIcon = res.getDrawable(R.drawable.ic_message_24dp);
138123e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                alternateContentDescription.append(res.getString(R.string.sms_custom, header));
138248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos
138348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                // Add video call button if supported
1384f764730a34da560db87206f9a48390d4c8085365Paul Soulos                if (CallUtil.isVideoEnabled(context)) {
138523e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                    thirdIcon = res.getDrawable(R.drawable.ic_videocam);
138648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    thirdIntent = CallUtil.getVideoCallIntent(phone.getNumber(),
138748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                            CALL_ORIGIN_QUICK_CONTACTS_ACTIVITY);
138848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    thirdContentDescription =
138923e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                            res.getString(R.string.description_video_call);
139048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                }
1391eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            }
1392eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        } else if (dataItem instanceof EmailDataItem) {
1393eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            final EmailDataItem email = (EmailDataItem) dataItem;
1394eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            final String address = email.getData();
1395eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            if (!TextUtils.isEmpty(address)) {
139623e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                primaryContentDescription.append(res.getString(R.string.email_other)).append(" ");
13971cd88e3ecfa72f43c3fe25c912d9f67848f11e60Jay Shrauner                final Uri mailUri = Uri.fromParts(ContactsUtils.SCHEME_MAILTO, address, null);
1398eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                intent = new Intent(Intent.ACTION_SENDTO, mailUri);
1399eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                header = email.getAddress();
14002a4207fb39330e840436215c896cde911489e111Paul Soulos                entryContextMenuInfo = new EntryContextMenuInfo(header,
140197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                        res.getString(R.string.emailLabelsGroup), dataItem.getMimeType(),
140297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                        dataItem.getId(), dataItem.isSuperPrimary());
1403f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos                if (email.hasKindTypeColumn(kind)) {
140423e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                    text = Email.getTypeLabel(res, email.getKindTypeColumn(kind),
1405f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos                            email.getLabel()).toString();
140623e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                    primaryContentDescription.append(text).append(" ");
1407f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos                }
140823e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                primaryContentDescription.append(header);
140923e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                icon = res.getDrawable(R.drawable.ic_email_24dp);
141048290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos                iconResourceId = R.drawable.ic_email_24dp;
1411eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            }
1412eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        } else if (dataItem instanceof StructuredPostalDataItem) {
1413eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            StructuredPostalDataItem postal = (StructuredPostalDataItem) dataItem;
1414eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            final String postalAddress = postal.getFormattedAddress();
1415eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            if (!TextUtils.isEmpty(postalAddress)) {
141623e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                primaryContentDescription.append(res.getString(R.string.map_other)).append(" ");
1417eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                intent = StructuredPostalUtils.getViewPostalAddressIntent(postalAddress);
1418eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                header = postal.getFormattedAddress();
14192a4207fb39330e840436215c896cde911489e111Paul Soulos                entryContextMenuInfo = new EntryContextMenuInfo(header,
142097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                        res.getString(R.string.postalLabelsGroup), dataItem.getMimeType(),
142197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                        dataItem.getId(), dataItem.isSuperPrimary());
1422f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos                if (postal.hasKindTypeColumn(kind)) {
142323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                    text = StructuredPostal.getTypeLabel(res,
1424f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos                            postal.getKindTypeColumn(kind), postal.getLabel()).toString();
142523e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                    primaryContentDescription.append(text).append(" ");
1426f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos                }
142723e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                primaryContentDescription.append(header);
14286a4d2736d772cc5cbb79d04e115f2d6117826860Paul Soulos                alternateIntent =
14296a4d2736d772cc5cbb79d04e115f2d6117826860Paul Soulos                        StructuredPostalUtils.getViewPostalAddressDirectionsIntent(postalAddress);
143023e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                alternateIcon = res.getDrawable(R.drawable.ic_directions_24dp);
143123e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                alternateContentDescription.append(res.getString(
143223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                        R.string.content_description_directions)).append(" ").append(header);
143323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                icon = res.getDrawable(R.drawable.ic_place_24dp);
143448290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos                iconResourceId = R.drawable.ic_place_24dp;
1435eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            }
1436eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        } else if (dataItem instanceof SipAddressDataItem) {
14376bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell            if (PhoneCapabilityTester.isSipPhone(context)) {
1438eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                final SipAddressDataItem sip = (SipAddressDataItem) dataItem;
1439eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                final String address = sip.getSipAddress();
1440eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                if (!TextUtils.isEmpty(address)) {
144123e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                    primaryContentDescription.append(res.getString(R.string.call_other)).append(
144223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                            " ");
14431cd88e3ecfa72f43c3fe25c912d9f67848f11e60Jay Shrauner                    final Uri callUri = Uri.fromParts(PhoneAccount.SCHEME_SIP, address, null);
1444eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                    intent = CallUtil.getCallIntent(callUri);
14451cda01b35a37f79b22e907cc970314b8c0a9e00cPaul Soulos                    header = address;
14462a4207fb39330e840436215c896cde911489e111Paul Soulos                    entryContextMenuInfo = new EntryContextMenuInfo(header,
144797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                            res.getString(R.string.phoneLabelsGroup), dataItem.getMimeType(),
144897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                            dataItem.getId(), dataItem.isSuperPrimary());
14491cda01b35a37f79b22e907cc970314b8c0a9e00cPaul Soulos                    if (sip.hasKindTypeColumn(kind)) {
145023e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                        text = SipAddress.getTypeLabel(res,
14516bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell                                sip.getKindTypeColumn(kind), sip.getLabel()).toString();
145223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                        primaryContentDescription.append(text).append(" ");
14531cda01b35a37f79b22e907cc970314b8c0a9e00cPaul Soulos                    }
145423e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                    primaryContentDescription.append(header);
145523e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                    icon = res.getDrawable(R.drawable.ic_dialer_sip_black_24dp);
145648290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos                    iconResourceId = R.drawable.ic_dialer_sip_black_24dp;
145716339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos                }
1458edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann            }
1459eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        } else if (dataItem instanceof StructuredNameDataItem) {
1460eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            final String givenName = ((StructuredNameDataItem) dataItem).getGivenName();
1461eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            if (!TextUtils.isEmpty(givenName)) {
146223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                aboutCardName.value = res.getString(R.string.about_card_title) +
14636bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell                        " " + givenName;
1464eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            } else {
146523e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                aboutCardName.value = res.getString(R.string.about_card_title);
1466eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            }
1467eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        } else {
1468eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            // Custom DataItem
14696bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell            header = dataItem.buildDataStringForDisplay(context, kind);
1470eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            text = kind.typeColumn;
1471eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            intent = new Intent(Intent.ACTION_VIEW);
147260e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            final Uri uri = ContentUris.withAppendedId(Data.CONTENT_URI, dataItem.getId());
147360e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos            intent.setDataAndType(uri, dataItem.getMimeType());
1474e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos
1475e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos            if (intent != null) {
1476e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos                final String mimetype = intent.getType();
1477e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos
1478e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos                // Attempt to use known icons for known 3p types. Otherwise default to ResolveCache
1479e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos                switch (mimetype) {
1480e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos                    case MIMETYPE_GPLUS_PROFILE:
1481e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos                        if (INTENT_DATA_GPLUS_PROFILE_ADD_TO_CIRCLE.equals(
1482e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos                                intent.getDataString())) {
148323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                            icon = res.getDrawable(
1484e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos                                    R.drawable.ic_add_to_circles_black_24);
148548290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos                            iconResourceId = R.drawable.ic_add_to_circles_black_24;
1486e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos                        } else {
148723e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                            icon = res.getDrawable(R.drawable.ic_google_plus_24dp);
148848290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos                            iconResourceId = R.drawable.ic_google_plus_24dp;
1489e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos                        }
1490e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos                        break;
1491e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos                    case MIMETYPE_HANGOUTS:
1492e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos                        if (INTENT_DATA_HANGOUTS_VIDEO.equals(intent.getDataString())) {
149323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                            icon = res.getDrawable(R.drawable.ic_hangout_video_24dp);
149448290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos                            iconResourceId = R.drawable.ic_hangout_video_24dp;
1495e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos                        } else {
149623e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                            icon = res.getDrawable(R.drawable.ic_hangout_24dp);
149748290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos                            iconResourceId = R.drawable.ic_hangout_24dp;
1498e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos                        }
1499e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos                        break;
1500e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos                    default:
150197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                        entryContextMenuInfo = new EntryContextMenuInfo(header, mimetype,
150297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                                dataItem.getMimeType(), dataItem.getId(),
150397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos                                dataItem.isSuperPrimary());
15046bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell                        icon = ResolveCache.getInstance(context).getIcon(
1505e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos                                dataItem.getMimeType(), intent);
1506e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos                        // Call mutate to create a new Drawable.ConstantState for color filtering
1507e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos                        if (icon != null) {
1508e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos                            icon.mutate();
1509e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos                        }
151048ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos                        shouldApplyColor = false;
1511e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos                }
1512e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos            }
1513eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        }
1514b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos
1515eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        if (intent != null) {
1516eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            // Do not set the intent is there are no resolves
15176bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell            if (!PhoneCapabilityTester.isIntentRegistered(context, intent)) {
1518eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                intent = null;
1519eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            }
1520eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        }
1521eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos
1522dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        if (alternateIntent != null) {
1523dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos            // Do not set the alternate intent is there are no resolves
15246bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell            if (!PhoneCapabilityTester.isIntentRegistered(context, alternateIntent)) {
1525dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos                alternateIntent = null;
1526f0d04c11b649e953177e79722d05fa048e53273dJay Shrauner            } else if (TextUtils.isEmpty(alternateContentDescription)) {
1527f0d04c11b649e953177e79722d05fa048e53273dJay Shrauner                // Attempt to use package manager to find a suitable content description if needed
152823e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                alternateContentDescription.append(getIntentResolveLabel(alternateIntent, context));
1529dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos            }
1530dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        }
1531dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos
1532eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        // If the Entry has no visual elements, return null
1533eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        if (icon == null && TextUtils.isEmpty(header) && TextUtils.isEmpty(subHeader) &&
1534eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                subHeaderIcon == null && TextUtils.isEmpty(text) && textIcon == null) {
1535eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            return null;
1536eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        }
1537eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos
1538fa238949855fba3b28a57fad3d585b13e80362bbBrian Attwell        // Ignore dataIds from the Me profile.
1539ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos        final int dataId = dataItem.getId() > Integer.MAX_VALUE ?
1540ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos                -1 : (int) dataItem.getId();
1541ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos
154223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos        return new Entry(dataId, icon, header, subHeader, subHeaderIcon, text, textIcon,
154323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                primaryContentDescription.toString(), intent, alternateIcon, alternateIntent,
154423e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                alternateContentDescription.toString(), shouldApplyColor, isEditable,
154548290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos                entryContextMenuInfo, thirdIcon, thirdIntent, thirdContentDescription,
154648290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos                iconResourceId);
1547eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos    }
1548eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos
15496bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell    private List<Entry> dataItemsToEntries(List<DataItem> dataItems,
15506bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell            MutableString aboutCardTitleOut) {
1551eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        final List<Entry> entries = new ArrayList<>();
1552eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        for (DataItem dataItem : dataItems) {
15536bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell            final Entry entry = dataItemToEntry(dataItem, this, mContactData, aboutCardTitleOut);
1554eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            if (entry != null) {
1555eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos                entries.add(entry);
1556eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            }
1557eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        }
1558eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        return entries;
1559edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    }
1560edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
15616bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell    private static String getIntentResolveLabel(Intent intent, Context context) {
15626bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        final List<ResolveInfo> matches = context.getPackageManager().queryIntentActivities(intent,
1563dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos                PackageManager.MATCH_DEFAULT_ONLY);
1564dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos
1565dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        // Pick first match, otherwise best found
1566dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        ResolveInfo bestResolve = null;
1567dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        final int size = matches.size();
1568dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        if (size == 1) {
1569dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos            bestResolve = matches.get(0);
1570dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        } else if (size > 1) {
15716bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell            bestResolve = ResolveCache.getInstance(context).getBestResolve(intent, matches);
1572dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        }
1573dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos
1574dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        if (bestResolve == null) {
1575dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos            return null;
1576dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos        }
1577dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos
15786bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell        return String.valueOf(bestResolve.loadLabel(context.getPackageManager()));
1579dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos    }
1580dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos
1581edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    /**
158231b2d42fb0889e61515d27314aa5a245147100daBrian Attwell     * Asynchronously extract the most vibrant color from the PhotoView. Once extracted,
158331b2d42fb0889e61515d27314aa5a245147100daBrian Attwell     * apply this tint to {@link MultiShrinkScroller}. This operation takes about 20-30ms
158431b2d42fb0889e61515d27314aa5a245147100daBrian Attwell     * on a Nexus 5.
158531b2d42fb0889e61515d27314aa5a245147100daBrian Attwell     */
158631b2d42fb0889e61515d27314aa5a245147100daBrian Attwell    private void extractAndApplyTintFromPhotoViewAsynchronously() {
158731b2d42fb0889e61515d27314aa5a245147100daBrian Attwell        if (mScroller == null) {
158831b2d42fb0889e61515d27314aa5a245147100daBrian Attwell            return;
158931b2d42fb0889e61515d27314aa5a245147100daBrian Attwell        }
159031b2d42fb0889e61515d27314aa5a245147100daBrian Attwell        final Drawable imageViewDrawable = mPhotoView.getDrawable();
1591faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell        new AsyncTask<Void, Void, MaterialPalette>() {
159231b2d42fb0889e61515d27314aa5a245147100daBrian Attwell            @Override
1593faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell            protected MaterialPalette doInBackground(Void... params) {
1594faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell
159595c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell                if (imageViewDrawable instanceof BitmapDrawable
159695c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell                        && mContactData.getThumbnailPhotoBinaryData() != null
159795c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell                        && mContactData.getThumbnailPhotoBinaryData().length > 0) {
159895c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell                    // Perform the color analysis on the thumbnail instead of the full sized
159995c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell                    // image, so that our results will be as similar as possible to the Bugle
160095c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell                    // app.
160195c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell                    final Bitmap bitmap = BitmapFactory.decodeByteArray(
160295c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell                            mContactData.getThumbnailPhotoBinaryData(), 0,
160395c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell                            mContactData.getThumbnailPhotoBinaryData().length);
160495c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell                    try {
160595c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell                        final int primaryColor = colorFromBitmap(bitmap);
160695c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell                        if (primaryColor != 0) {
160795c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell                            return mMaterialColorMapUtils.calculatePrimaryAndSecondaryColor(
160895c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell                                    primaryColor);
160995c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell                        }
161095c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell                    } finally {
161195c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell                        bitmap.recycle();
1612faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell                    }
16138a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell                }
16148a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell                if (imageViewDrawable instanceof LetterTileDrawable) {
1615faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell                    final int primaryColor = ((LetterTileDrawable) imageViewDrawable).getColor();
1616a3859ed9ff9f315d492e199620a08ae35ab8569fBrian Attwell                    return mMaterialColorMapUtils.calculatePrimaryAndSecondaryColor(primaryColor);
161731b2d42fb0889e61515d27314aa5a245147100daBrian Attwell                }
1618a3859ed9ff9f315d492e199620a08ae35ab8569fBrian Attwell                return MaterialColorMapUtils.getDefaultPrimaryAndSecondaryColors(getResources());
161931b2d42fb0889e61515d27314aa5a245147100daBrian Attwell            }
162031b2d42fb0889e61515d27314aa5a245147100daBrian Attwell
162131b2d42fb0889e61515d27314aa5a245147100daBrian Attwell            @Override
1622faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell            protected void onPostExecute(MaterialPalette palette) {
1623faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell                super.onPostExecute(palette);
16248571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell                if (mHasComputedThemeColor) {
16258571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell                    // If we had previously computed a theme color from the contact photo,
16268571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell                    // then do not update the theme color. Changing the theme color several
16278571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell                    // seconds after QC has started, as a result of an updated/upgraded photo,
16288571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell                    // is a jarring experience. On the other hand, changing the theme color after
16298571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell                    // a rotation or onNewIntent() is perfectly fine.
16308571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell                    return;
16318571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell                }
16328571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell                // Check that the Photo has not changed. If it has changed, the new tint
16338571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell                // color needs to be extracted
16348571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell                if (imageViewDrawable == mPhotoView.getDrawable()) {
16358571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell                    mHasComputedThemeColor = true;
1636faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell                    setThemeColor(palette);
163731b2d42fb0889e61515d27314aa5a245147100daBrian Attwell                }
163831b2d42fb0889e61515d27314aa5a245147100daBrian Attwell            }
163931b2d42fb0889e61515d27314aa5a245147100daBrian Attwell        }.execute();
164031b2d42fb0889e61515d27314aa5a245147100daBrian Attwell    }
164131b2d42fb0889e61515d27314aa5a245147100daBrian Attwell
16424936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell    /**
16434936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell     * Examine how many white pixels are in the bitmap in order to determine whether or not
16444936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell     * we need gradient overlays on top of the image.
16454936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell     */
16464936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell    private void analyzeWhitenessOfPhotoAsynchronously() {
16474936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell        final Drawable imageViewDrawable = mPhotoView.getDrawable();
16484936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell        new AsyncTask<Void, Void, Boolean>() {
16494936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell            @Override
16504936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell            protected Boolean doInBackground(Void... params) {
16514936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell                if (imageViewDrawable instanceof BitmapDrawable) {
16524936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell                    final Bitmap bitmap = ((BitmapDrawable) imageViewDrawable).getBitmap();
16534936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell                    return WhitenessUtils.isBitmapWhiteAtTopOrBottom(bitmap);
16544936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell                }
16554936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell                return !(imageViewDrawable instanceof LetterTileDrawable);
16564936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell            }
16574936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell
16584936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell            @Override
16594936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell            protected void onPostExecute(Boolean isWhite) {
16604936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell                super.onPostExecute(isWhite);
16614936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell                mScroller.setUseGradient(isWhite);
16624936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell            }
16634936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell        }.execute();
16644936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell    }
16654936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell
1666faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell    private void setThemeColor(MaterialPalette palette) {
16679b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell        // If the color is invalid, use the predefined default
1668faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell        final int primaryColor = palette.mPrimaryColor;
1669faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell        mScroller.setHeaderTintColor(primaryColor);
1670faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell        mStatusBarColor = palette.mSecondaryColor;
16719b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell        updateStatusBarColor();
16728571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell
16739b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell        mColorFilter =
1674faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell                new PorterDuffColorFilter(primaryColor, PorterDuff.Mode.SRC_ATOP);
1675faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell        mContactCard.setColorAndFilter(primaryColor, mColorFilter);
1676faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell        mRecentCard.setColorAndFilter(primaryColor, mColorFilter);
1677faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell        mAboutCard.setColorAndFilter(primaryColor, mColorFilter);
16789b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell    }
16799b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell
16808a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell    private void updateStatusBarColor() {
16818a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        if (mScroller == null) {
16828a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell            return;
16838a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        }
16848a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        final int desiredStatusBarColor;
16858a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        // Only use a custom status bar color if QuickContacts touches the top of the viewport.
16868a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        if (mScroller.getScrollNeededToBeFullScreen() <= 0) {
16878a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell            desiredStatusBarColor = mStatusBarColor;
16888a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        } else {
16898a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell            desiredStatusBarColor = Color.TRANSPARENT;
16908a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        }
16918a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        // Animate to the new color.
1692847bf2cd3946b1801c83c745d7183aed5143b44cBrian Attwell        final ObjectAnimator animation = ObjectAnimator.ofInt(getWindow(), "statusBarColor",
1693847bf2cd3946b1801c83c745d7183aed5143b44cBrian Attwell                getWindow().getStatusBarColor(), desiredStatusBarColor);
1694847bf2cd3946b1801c83c745d7183aed5143b44cBrian Attwell        animation.setDuration(ANIMATION_STATUS_BAR_COLOR_CHANGE_DURATION);
1695847bf2cd3946b1801c83c745d7183aed5143b44cBrian Attwell        animation.setEvaluator(new ArgbEvaluator());
1696847bf2cd3946b1801c83c745d7183aed5143b44cBrian Attwell        animation.start();
16978a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell    }
16988a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell
16998a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell    private int colorFromBitmap(Bitmap bitmap) {
17008a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        // Author of Palette recommends using 24 colors when analyzing profile photos.
17018a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        final int NUMBER_OF_PALETTE_COLORS = 24;
17028a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        final Palette palette = Palette.generate(bitmap, NUMBER_OF_PALETTE_COLORS);
1703a0f20f77e1b4f6cde5934d8b3348d93b58fd6362Brian Attwell        if (palette != null && palette.getVibrantSwatch() != null) {
1704a0f20f77e1b4f6cde5934d8b3348d93b58fd6362Brian Attwell            return palette.getVibrantSwatch().getRgb();
17058a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        }
17068a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        return 0;
17078a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell    }
17088a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell
1709b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos    private List<Entry> contactInteractionsToEntries(List<ContactInteraction> interactions) {
1710eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        final List<Entry> entries = new ArrayList<>();
1711b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos        for (ContactInteraction interaction : interactions) {
1712ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos            entries.add(new Entry(/* id = */ -1,
1713ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos                    interaction.getIcon(this),
1714b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos                    interaction.getViewHeader(this),
1715b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos                    interaction.getViewBody(this),
1716b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos                    interaction.getBodyIcon(this),
1717b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos                    interaction.getViewFooter(this),
1718b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos                    interaction.getFooterIcon(this),
171923e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                    interaction.getContentDescription(this),
1720b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos                    interaction.getIntent(),
1721dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos                    /* alternateIcon = */ null,
1722dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos                    /* alternateIntent = */ null,
1723dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos                    /* alternateContentDescription = */ null,
172448ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos                    /* shouldApplyColor = */ true,
17252a4207fb39330e840436215c896cde911489e111Paul Soulos                    /* isEditable = */ false,
172648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    /* EntryContextMenuInfo = */ null,
172748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    /* thirdIcon = */ null,
172848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos                    /* thirdIntent = */ null,
172948290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos                    /* thirdContentDescription = */ null,
173048290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos                    interaction.getIconResourceId()));
1731b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos        }
1732b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos        return entries;
1733b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos    }
1734b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos
1735eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos    private final LoaderCallbacks<Contact> mLoaderContactCallbacks =
1736851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu            new LoaderCallbacks<Contact>() {
1737cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann        @Override
1738851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu        public void onLoaderReset(Loader<Contact> loader) {
1739405ae406379ad9c47770783afc76a660f6c55fcaPaul Soulos            mContactData = null;
1740cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann        }
1741cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann
1742cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann        @Override
1743851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu        public void onLoadFinished(Loader<Contact> loader, Contact data) {
17448a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell            Trace.beginSection("onLoadFinished()");
17458a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell
1746cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann            if (isFinishing()) {
1747cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann                return;
1748cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann            }
1749cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann            if (data.isError()) {
1750cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann                // This shouldn't ever happen, so throw an exception. The {@link ContactLoader}
1751cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann                // should log the actual exception.
1752cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann                throw new IllegalStateException("Failed to load contact", data.getException());
1753cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann            }
1754cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann            if (data.isNotFound()) {
17558a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell                if (mHasAlreadyBeenOpened) {
17568a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell                    finish();
17578a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell                } else {
17588a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell                    Log.i(TAG, "No contact found: " + ((ContactLoader)loader).getLookupUri());
17598a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell                    Toast.makeText(QuickContactActivity.this, R.string.invalidContactMessage,
17608a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell                            Toast.LENGTH_LONG).show();
17618a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell                }
1762cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann                return;
1763cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann            }
1764cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann
1765b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos            bindContactData(data);
1766cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann
17678a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell            Trace.endSection();
1768cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann        }
1769cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann
1770cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann        @Override
1771851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu        public Loader<Contact> onCreateLoader(int id, Bundle args) {
1772cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann            if (mLookupUri == null) {
1773cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann                Log.wtf(TAG, "Lookup uri wasn't initialized. Loader was started too early");
1774cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann            }
1775d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell            // Load all contact data. We need loadGroupMetaData=true to determine whether the
1776d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell            // contact is invisible. If it is, we need to display an "Add to Contacts" MenuItem.
1777b2b435a944947fbf1965c3bb7c202a97f0273259Yorke Lee            return new ContactLoader(getApplicationContext(), mLookupUri,
1778d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell                    true /*loadGroupMetaData*/, false /*loadInvitableAccountTypes*/,
17798571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell                    true /*postViewNotification*/, true /*computeFormattedPhoneNumber*/);
1780cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann        }
1781cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann    };
1782b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos
1783b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell    @Override
1784b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell    public void onBackPressed() {
1785b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell        if (mScroller != null) {
17868477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell            if (!mIsExitAnimationInProgress) {
17878477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell                mScroller.scrollOffBottom();
17888477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell            }
1789b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell        } else {
1790b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell            super.onBackPressed();
1791b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell        }
1792b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell    }
1793b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos
17948a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell    @Override
17958a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell    public void finish() {
17968a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        super.finish();
17978a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell
17988a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        // override transitions to skip the standard window animations
17998a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        overridePendingTransition(0, 0);
18008a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell    }
18018a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell
1802eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos    private final LoaderCallbacks<List<ContactInteraction>> mLoaderInteractionsCallbacks =
1803b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos            new LoaderCallbacks<List<ContactInteraction>>() {
1804b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos
1805b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos        @Override
1806b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos        public Loader<List<ContactInteraction>> onCreateLoader(int id, Bundle args) {
1807b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos            Log.v(TAG, "onCreateLoader");
1808b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos            Loader<List<ContactInteraction>> loader = null;
1809b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos            switch (id) {
1810b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos                case LOADER_SMS_ID:
1811b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos                    Log.v(TAG, "LOADER_SMS_ID");
1812b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos                    loader = new SmsInteractionsLoader(
1813b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos                            QuickContactActivity.this,
1814ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos                            args.getStringArray(KEY_LOADER_EXTRA_PHONES),
1815b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos                            MAX_SMS_RETRIEVE);
1816b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos                    break;
1817899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos                case LOADER_CALENDAR_ID:
1818899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos                    Log.v(TAG, "LOADER_CALENDAR_ID");
1819ae4cafed699b7cd6c5d4dad855bc0d4948452983Paul Soulos                    final String[] emailsArray = args.getStringArray(KEY_LOADER_EXTRA_EMAILS);
1820ae4cafed699b7cd6c5d4dad855bc0d4948452983Paul Soulos                    List<String> emailsList = null;
1821ae4cafed699b7cd6c5d4dad855bc0d4948452983Paul Soulos                    if (emailsArray != null) {
1822ae4cafed699b7cd6c5d4dad855bc0d4948452983Paul Soulos                        emailsList = Arrays.asList(args.getStringArray(KEY_LOADER_EXTRA_EMAILS));
1823ae4cafed699b7cd6c5d4dad855bc0d4948452983Paul Soulos                    }
1824899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos                    loader = new CalendarInteractionsLoader(
1825899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos                            QuickContactActivity.this,
1826ae4cafed699b7cd6c5d4dad855bc0d4948452983Paul Soulos                            emailsList,
1827899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos                            MAX_FUTURE_CALENDAR_RETRIEVE,
1828899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos                            MAX_PAST_CALENDAR_RETRIEVE,
1829899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos                            FUTURE_MILLISECOND_TO_SEARCH_LOCAL_CALENDAR,
1830899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos                            PAST_MILLISECOND_TO_SEARCH_LOCAL_CALENDAR);
1831899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos                    break;
1832ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos                case LOADER_CALL_LOG_ID:
1833ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos                    Log.v(TAG, "LOADER_CALL_LOG_ID");
1834ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos                    loader = new CallLogInteractionsLoader(
1835ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos                            QuickContactActivity.this,
1836ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos                            args.getStringArray(KEY_LOADER_EXTRA_PHONES),
1837ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos                            MAX_CALL_LOG_RETRIEVE);
1838b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos            }
1839b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos            return loader;
1840b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos        }
1841b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos
1842b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos        @Override
1843b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos        public void onLoadFinished(Loader<List<ContactInteraction>> loader,
1844b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos                List<ContactInteraction> data) {
1845b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos            mRecentLoaderResults.put(loader.getId(), data);
1846b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos
1847b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos            if (isAllRecentDataLoaded()) {
1848b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos                bindRecentData();
1849b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos            }
1850b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos        }
1851b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos
1852b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos        @Override
1853b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos        public void onLoaderReset(Loader<List<ContactInteraction>> loader) {
1854b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos            mRecentLoaderResults.remove(loader.getId());
1855b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos        }
1856b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos    };
1857b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos
1858b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos    private boolean isAllRecentDataLoaded() {
1859b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos        return mRecentLoaderResults.size() == mRecentLoaderIds.length;
1860b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos    }
1861b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos
1862b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos    private void bindRecentData() {
1863eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        final List<ContactInteraction> allInteractions = new ArrayList<>();
186430e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell        final List<List<Entry>> interactionsWrapper = new ArrayList<>();
1865b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos
186630e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell        mRecentDataTask = new AsyncTask<Void, Void, Void>() {
1867b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos            @Override
186830e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell            protected Void doInBackground(Void... params) {
186930e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                Trace.beginSection("sort recent loader results");
187030e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell
187130e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                for (List<ContactInteraction> loaderInteractions : mRecentLoaderResults.values()) {
187230e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                    allInteractions.addAll(loaderInteractions);
187330e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                }
187430e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell
187530e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                // Sort the interactions by most recent
187630e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                Collections.sort(allInteractions, new Comparator<ContactInteraction>() {
187730e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                    @Override
187830e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                    public int compare(ContactInteraction a, ContactInteraction b) {
187930e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                        return a.getInteractionDate() >= b.getInteractionDate() ? -1 : 1;
188030e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                    }
188130e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                });
188230e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell
188330e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                Trace.endSection();
188430e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                Trace.beginSection("contactInteractionsToEntries");
188530e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell
188630e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                // Wrap each interaction in its own list so that an icon is displayed for each entry
188730e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                for (Entry contactInteraction : contactInteractionsToEntries(allInteractions)) {
188830e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                    List<Entry> entryListWrapper = new ArrayList<>(1);
188930e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                    entryListWrapper.add(contactInteraction);
189030e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                    interactionsWrapper.add(entryListWrapper);
189130e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                }
189230e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell
189330e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                Trace.endSection();
189430e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                return null;
1895b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos            }
189630e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell
189730e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell            @Override
189830e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell            protected void onPostExecute(Void aVoid) {
189930e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                super.onPostExecute(aVoid);
190030e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                Trace.beginSection("initialize recents card");
190130e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell
190230e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                if (allInteractions.size() > 0) {
190330e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                    mRecentCard.initialize(interactionsWrapper,
1904b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos                    /* numInitialVisibleEntries = */ MIN_NUM_COLLAPSED_RECENT_ENTRIES_SHOWN,
1905c8e2a91807b581194566eb45019fa16e2268b462Paul Soulos                    /* isExpanded = */ mRecentCard.isExpanded(), /* isAlwaysExpanded = */ false,
190630e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                            mExpandingEntryCardViewListener, mScroller);
190730e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                    mRecentCard.setVisibility(View.VISIBLE);
190830e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                }
1909eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos
191030e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                Trace.endSection();
191130e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell
191230e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                // About card is initialized along with the contact card, but since it appears after
191330e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                // the recent card in the UI, we hold off until making it visible until the recent
191430e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                // card is also ready to avoid stuttering.
191530e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                if (mAboutCard.shouldShow()) {
191630e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                    mAboutCard.setVisibility(View.VISIBLE);
191730e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                } else {
191830e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                    mAboutCard.setVisibility(View.GONE);
191930e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                }
192030e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell                mRecentDataTask = null;
192130e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell            }
192230e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell        };
192330e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell        mRecentDataTask.execute();
1924b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos    }
19258a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell
19268a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell    @Override
19278a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell    protected void onStop() {
19288a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        super.onStop();
19298a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell
19308a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        if (mEntriesAndActionsTask != null) {
19318a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell            // Once the activity is stopped, we will no longer want to bind mEntriesAndActionsTask's
19328a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell            // results on the UI thread. In some circumstances Activities are killed without
19338a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell            // onStop() being called. This is not a problem, because in these circumstances
19348a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell            // the entire process will be killed.
19358a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell            mEntriesAndActionsTask.cancel(/* mayInterruptIfRunning = */ false);
19368a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell        }
193730e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell        if (mRecentDataTask != null) {
193830e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell            mRecentDataTask.cancel(/* mayInterruptIfRunning = */ false);
193930e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell        }
19408a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell    }
194123889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos
194223889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos    /**
1943d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell     * Returns true if it is possible to edit the current contact.
1944d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell     */
1945d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell    private boolean isContactEditable() {
1946d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        return mContactData != null && !mContactData.isDirectoryEntry();
1947d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell    }
1948d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell
1949a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell    /**
1950a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell     * Returns true if it is possible to share the current contact.
1951a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell     */
1952a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell    private boolean isContactShareable() {
1953a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell        return mContactData != null && !mContactData.isDirectoryEntry();
1954a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell    }
1955a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell
19566095369885edcca566a812b551886e29c7ff8039Brian Attwell    private Intent getEditContactIntent() {
195763176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell        final Intent intent = new Intent(Intent.ACTION_EDIT, mContactData.getLookupUri());
1958d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
19596095369885edcca566a812b551886e29c7ff8039Brian Attwell        return intent;
19606095369885edcca566a812b551886e29c7ff8039Brian Attwell    }
19616095369885edcca566a812b551886e29c7ff8039Brian Attwell
19626095369885edcca566a812b551886e29c7ff8039Brian Attwell    private void editContact() {
1963a42ef76251778161d27bc07db214b8c81720e476Paul Soulos        mHasIntentLaunched = true;
1964c00a0b5370f0714f6af1ea9b3e29b10f25e91af0Zheng Fu        mContactLoader.cacheResult();
19656095369885edcca566a812b551886e29c7ff8039Brian Attwell        startActivityForResult(getEditContactIntent(), REQUEST_CODE_CONTACT_EDITOR_ACTIVITY);
1966d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell    }
1967d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell
1968d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell    private void toggleStar(MenuItem starredMenuItem) {
1969d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        // Make sure there is a contact
197063176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell        if (mContactData != null) {
1971d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell            // Read the current starred value from the UI instead of using the last
1972d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell            // loaded state. This allows rapid tapping without writing the same
1973d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell            // value several times
1974d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell            final boolean isStarred = starredMenuItem.isChecked();
1975d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell
1976d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell            // To improve responsiveness, swap out the picture (and tag) in the UI already
1977333091ae754ddfc25714c14b9b89534be24379f9Paul Soulos            ContactDisplayUtils.configureStarredMenuItem(starredMenuItem,
1978d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell                    mContactData.isDirectoryEntry(), mContactData.isUserProfile(),
1979d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell                    !isStarred);
1980d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell
1981d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell            // Now perform the real save
1982eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos            final Intent intent = ContactSaveService.createSetStarredIntent(
198363176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell                    QuickContactActivity.this, mContactData.getLookupUri(), !isStarred);
1984d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell            startService(intent);
198535ccdba7b8b2270204f7f96d824d258e408fe6efBrian Attwell
198635ccdba7b8b2270204f7f96d824d258e408fe6efBrian Attwell            final CharSequence accessibilityText = !isStarred
198735ccdba7b8b2270204f7f96d824d258e408fe6efBrian Attwell                    ? getResources().getText(R.string.description_action_menu_add_star)
198835ccdba7b8b2270204f7f96d824d258e408fe6efBrian Attwell                    : getResources().getText(R.string.description_action_menu_remove_star);
198935ccdba7b8b2270204f7f96d824d258e408fe6efBrian Attwell            // Accessibility actions need to have an associated view. We can't access the MenuItem's
199035ccdba7b8b2270204f7f96d824d258e408fe6efBrian Attwell            // underlying view, so put this accessibility action on the root view.
199135ccdba7b8b2270204f7f96d824d258e408fe6efBrian Attwell            mScroller.announceForAccessibility(accessibilityText);
1992d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        }
1993d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell    }
1994d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell
1995752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell    /**
1996752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell     * Calls into the contacts provider to get a pre-authorized version of the given URI.
1997752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell     */
1998752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell    private Uri getPreAuthorizedUri(Uri uri) {
1999752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell        final Bundle uriBundle = new Bundle();
2000752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell        uriBundle.putParcelable(ContactsContract.Authorization.KEY_URI_TO_AUTHORIZE, uri);
2001752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell        final Bundle authResponse = getContentResolver().call(
2002752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell                ContactsContract.AUTHORITY_URI,
2003752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell                ContactsContract.Authorization.AUTHORIZATION_METHOD,
2004752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell                null,
2005752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell                uriBundle);
2006752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell        if (authResponse != null) {
2007752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell            return (Uri) authResponse.getParcelable(
2008752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell                    ContactsContract.Authorization.KEY_AUTHORIZED_URI);
2009752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell        } else {
2010752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell            return uri;
2011752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell        }
2012752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell    }
20132d150da246632b1649999cfabed776133b097775Brian Attwell
2014752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell    private void shareContact() {
2015752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell        final String lookupKey = mContactData.getLookupKey();
2016752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell        Uri shareUri = Uri.withAppendedPath(Contacts.CONTENT_VCARD_URI, lookupKey);
2017752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell        if (mContactData.isUserProfile()) {
2018752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell            // User is sharing the profile.  We don't want to force the receiver to have
2019752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell            // the highly-privileged READ_PROFILE permission, so we need to request a
2020752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell            // pre-authorized URI from the provider.
2021752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell            shareUri = getPreAuthorizedUri(shareUri);
2022752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell        }
2023752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell
2024752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell        final Intent intent = new Intent(Intent.ACTION_SEND);
2025752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell        intent.setType(Contacts.CONTENT_VCARD_TYPE);
2026752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell        intent.putExtra(Intent.EXTRA_STREAM, shareUri);
2027752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell
2028752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell        // Launch chooser to share contact via
2029752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell        final CharSequence chooseTitle = getText(R.string.share_via);
2030752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell        final Intent chooseIntent = Intent.createChooser(intent, chooseTitle);
2031752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell
2032752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell        try {
2033a42ef76251778161d27bc07db214b8c81720e476Paul Soulos            mHasIntentLaunched = true;
2034752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell            this.startActivity(chooseIntent);
2035eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        } catch (final ActivityNotFoundException ex) {
2036752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell            Toast.makeText(this, R.string.share_error, Toast.LENGTH_SHORT).show();
2037752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell        }
2038752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell    }
2039752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell
2040752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell    /**
2041752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell     * Creates a launcher shortcut with the current contact.
2042752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell     */
2043752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell    private void createLauncherShortcutWithContact() {
2044752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell        final ShortcutIntentBuilder builder = new ShortcutIntentBuilder(this,
2045752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell                new OnShortcutIntentCreatedListener() {
2046752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell
2047752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell                    @Override
2048752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell                    public void onShortcutIntentCreated(Uri uri, Intent shortcutIntent) {
2049752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell                        // Broadcast the shortcutIntent to the launcher to create a
2050752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell                        // shortcut to this contact
2051752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell                        shortcutIntent.setAction(ACTION_INSTALL_SHORTCUT);
2052752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell                        QuickContactActivity.this.sendBroadcast(shortcutIntent);
2053752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell
2054752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell                        // Send a toast to give feedback to the user that a shortcut to this
2055752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell                        // contact was added to the launcher.
2056752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell                        Toast.makeText(QuickContactActivity.this,
2057752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell                                R.string.createContactShortcutSuccessful,
2058752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell                                Toast.LENGTH_SHORT).show();
2059752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell                    }
2060752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell
2061752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell                });
206263176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell        builder.createContactShortcutIntent(mContactData.getLookupUri());
2063752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell    }
2064752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell
206566965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell    private boolean isShortcutCreatable() {
206666965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell        final Intent createShortcutIntent = new Intent();
206766965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell        createShortcutIntent.setAction(ACTION_INSTALL_SHORTCUT);
206866965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell        final List<ResolveInfo> receivers = getPackageManager()
206966965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell                .queryBroadcastReceivers(createShortcutIntent, 0);
207066965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell        return receivers != null && receivers.size() > 0;
207166965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell    }
207266965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell
2073d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell    @Override
2074d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell    public boolean onCreateOptionsMenu(Menu menu) {
2075eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos        final MenuInflater inflater = getMenuInflater();
2076d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        inflater.inflate(R.menu.quickcontact, menu);
2077d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        return true;
2078d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell    }
2079d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell
2080d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell    @Override
2081d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell    public boolean onPrepareOptionsMenu(Menu menu) {
2082d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        if (mContactData != null) {
2083d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell            final MenuItem starredMenuItem = menu.findItem(R.id.menu_star);
2084333091ae754ddfc25714c14b9b89534be24379f9Paul Soulos            ContactDisplayUtils.configureStarredMenuItem(starredMenuItem,
2085d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell                    mContactData.isDirectoryEntry(), mContactData.isUserProfile(),
2086d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell                    mContactData.getStarred());
2087a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell
2088d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell            // Configure edit MenuItem
2089d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell            final MenuItem editMenuItem = menu.findItem(R.id.menu_edit);
2090d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell            editMenuItem.setVisible(true);
2091d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell            if (DirectoryContactUtil.isDirectoryContact(mContactData) || InvisibleContactUtil
2092d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell                    .isInvisibleAndAddable(mContactData, this)) {
209330cfd121ad8c8adb83cf417ff1d40a8ba1e3761dBrian Attwell                editMenuItem.setIcon(R.drawable.ic_person_add_tinted_24dp);
20942e4214c79170cdb6c1b8b6ff0408925d3f512becBrian Attwell                editMenuItem.setTitle(R.string.menu_add_contact);
2095d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell            } else if (isContactEditable()) {
2096d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell                editMenuItem.setIcon(R.drawable.ic_create_24dp);
20972e4214c79170cdb6c1b8b6ff0408925d3f512becBrian Attwell                editMenuItem.setTitle(R.string.menu_editContact);
2098d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell            } else {
2099d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell                editMenuItem.setVisible(false);
2100d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell            }
2101a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell
2102a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell            final MenuItem shareMenuItem = menu.findItem(R.id.menu_share);
2103a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell            shareMenuItem.setVisible(isContactShareable());
2104a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell
210566965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell            final MenuItem shortcutMenuItem = menu.findItem(R.id.menu_create_contact_shortcut);
210666965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell            shortcutMenuItem.setVisible(isShortcutCreatable());
210766965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell
21088a6d0022b07640d4a1fb8b264c8822bbab2981adPaul Soulos            return true;
2109d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        }
21108a6d0022b07640d4a1fb8b264c8822bbab2981adPaul Soulos        return false;
2111d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell    }
2112d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell
2113d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell    @Override
2114d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell    public boolean onOptionsItemSelected(MenuItem item) {
2115d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        switch (item.getItemId()) {
2116d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell            case R.id.menu_star:
2117d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell                toggleStar(item);
2118d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell                return true;
2119d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell            case R.id.menu_edit:
2120d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell                if (DirectoryContactUtil.isDirectoryContact(mContactData)) {
2121ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos                    // This action is used to launch the contact selector, with the option of
2122ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos                    // creating a new contact. Creating a new contact is an INSERT, while selecting
2123ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos                    // an exisiting one is an edit. The fields in the edit screen will be
2124ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos                    // prepopulated with data.
2125ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos
2126ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos                    final Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
2127ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos                    intent.setType(Contacts.CONTENT_ITEM_TYPE);
2128ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos
2129ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos                    // Only pre-fill the name field if the provided display name is an organization
2130ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos                    // name or better (e.g. structured name, nickname)
2131ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos                    if (mContactData.getDisplayNameSource() >= DisplayNameSources.ORGANIZATION) {
2132ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos                        intent.putExtra(Intents.Insert.NAME, mContactData.getDisplayName());
2133ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos                    }
2134ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos                    ArrayList<ContentValues> values = mContactData.getContentValues();
2135ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos                    // Last time used and times used are aggregated values from the usage stat
2136ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos                    // table. They need to be removed from data values so the SQL table can insert
2137ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos                    // properly
2138ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos                    for (ContentValues value : values) {
2139ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos                        value.remove(Data.LAST_TIME_USED);
2140ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos                        value.remove(Data.TIMES_USED);
2141ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos                    }
2142ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos                    intent.putExtra(Intents.Insert.DATA, values);
2143ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos
2144ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos                    // If the contact can only export to the same account, add it to the intent.
2145ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos                    // Otherwise the ContactEditorFragment will show a dialog for selecting an
2146ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos                    // account.
2147ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos                    if (mContactData.getDirectoryExportSupport() ==
2148ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos                            Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY) {
2149ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos                        intent.putExtra(Intents.Insert.ACCOUNT,
2150ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos                                new Account(mContactData.getDirectoryAccountName(),
2151ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos                                        mContactData.getDirectoryAccountType()));
2152ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos                        intent.putExtra(Intents.Insert.DATA_SET,
2153ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos                                mContactData.getRawContacts().get(0).getDataSet());
2154ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos                    }
2155ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos
2156ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos                    startActivityForResult(intent, REQUEST_CODE_CONTACT_SELECTION_ACTIVITY);
2157d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell                } else if (InvisibleContactUtil.isInvisibleAndAddable(mContactData, this)) {
2158d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell                    InvisibleContactUtil.addToDefaultGroup(mContactData, this);
2159d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell                } else if (isContactEditable()) {
2160d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell                    editContact();
2161d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell                }
2162d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell                return true;
2163752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell            case R.id.menu_share:
2164752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell                shareContact();
2165752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell                return true;
2166752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell            case R.id.menu_create_contact_shortcut:
2167752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell                createLauncherShortcutWithContact();
2168752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell                return true;
2169d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell            default:
2170d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell                return super.onOptionsItemSelected(item);
2171d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell        }
217223889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos    }
2173edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann}
2174