QuickContactActivity.java revision 31b2d42fb0889e61515d27314aa5a245147100da
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
19b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwellimport android.animation.ObjectAnimator;
20edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.app.Activity;
21cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmannimport android.app.LoaderManager.LoaderCallbacks;
22edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.content.ContentUris;
23edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.content.Context;
24edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.content.Intent;
25cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmannimport android.content.Loader;
26edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.content.pm.PackageManager;
2731b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport android.graphics.Bitmap;
2831b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport android.graphics.Canvas;
2931b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport android.graphics.drawable.BitmapDrawable;
3031b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport android.graphics.drawable.Drawable;
31edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.net.Uri;
3231b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport android.os.AsyncTask;
33edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.os.Bundle;
34edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Email;
35edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Phone;
36edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.SipAddress;
37edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
38edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.CommonDataKinds.Website;
39edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.Contacts;
406cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Leeimport android.provider.ContactsContract.DisplayNameSources;
416cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Leeimport android.provider.ContactsContract.Intents.Insert;
426cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Leeimport android.provider.ContactsContract.Directory;
43edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.QuickContact;
44edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.provider.ContactsContract.RawContacts;
4531b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport android.support.v7.graphics.Palette;
46edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.text.TextUtils;
47edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.util.Log;
48edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.view.View;
49edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.view.View.OnClickListener;
5010d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawaimport android.view.WindowManager;
51edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.widget.ImageView;
52edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.widget.TextView;
53edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.widget.Toast;
54edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
5572b3ab1d8a62f228a540b05f4ed6373e494c7d72Christine Chenimport com.android.contacts.ContactSaveService;
56d7ca03e23948c3b2d5f97ec5598d8b50e3fc0b25Chiao Chengimport com.android.contacts.common.Collapser;
57e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.R;
5831b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport com.android.contacts.common.lettertiles.LetterTileDrawable;
590d5588da244d0992c3ff8f25d0875fdf95a8c644Chiao Chengimport com.android.contacts.common.model.AccountTypeManager;
60cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.Contact;
61cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.ContactLoader;
62cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.RawContact;
63428f008513d1591cc08fcfe2cf0c9237fb313241Chiao Chengimport com.android.contacts.common.model.account.AccountType;
64cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.dataitem.DataItem;
65428f008513d1591cc08fcfe2cf0c9237fb313241Chiao Chengimport com.android.contacts.common.model.dataitem.DataKind;
66cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.dataitem.EmailDataItem;
67cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.dataitem.ImDataItem;
68d9eab4da8b9946b76a2091e5cce6c858663ef1bbChiao Chengimport com.android.contacts.common.util.Constants;
69cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.util.DataStatus;
702e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Leeimport com.android.contacts.common.util.UriUtils;
712d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport com.android.contacts.quickcontact.ExpandingEntryCardView.Entry;
72e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.util.ImageViewDrawableSetter;
739f2a5e78c9604d9c407f1464c7cb72ec5f2bb04dChiao Chengimport com.android.contacts.common.util.StopWatch;
74b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwellimport com.android.contacts.util.SchedulingUtils;
75b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwellimport com.android.contacts.widget.MultiShrinkScroller;
76b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwellimport com.android.contacts.widget.MultiShrinkScroller.MultiShrinkScrollerListener;
772d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
78e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.google.common.base.Preconditions;
79e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.google.common.collect.Lists;
80e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Cheng
812d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport java.util.ArrayList;
82edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport java.util.HashMap;
83edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport java.util.HashSet;
84edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport java.util.List;
85edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport java.util.Set;
86edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
87edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann/**
88edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * Mostly translucent {@link Activity} that shows QuickContact dialog. It loads
89edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * data asynchronously, and then shows a popup with details centered around
90edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * {@link Intent#getSourceBounds()}.
91edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann */
92edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannpublic class QuickContactActivity extends Activity {
93edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    private static final String TAG = "QuickContact";
94edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
95edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    private static final boolean TRACE_LAUNCH = false;
96edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    private static final String TRACE_TAG = "quickcontact";
97b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell    private static final int ANIMATION_DURATION = 250;
98dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki    private static final boolean ENABLE_STOPWATCH = false;
99dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki
100edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
101edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    @SuppressWarnings("deprecation")
102edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    private static final String LEGACY_AUTHORITY = android.provider.Contacts.AUTHORITY;
103edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
104edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    private Uri mLookupUri;
105edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    private String[] mExcludeMimes;
106edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    private List<String> mSortedActionMimeTypes = Lists.newArrayList();
107edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
108edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    private View mPhotoContainer;
109edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
1106219668d0612f7522bd15a9d34c6232cb15b9a6cYorke Lee    private ImageView mPhotoView;
1115ec23fdf243596717197a0c45495f24492cf0641Paul Soulos    private ImageView mEditOrAddContactImage;
11272b3ab1d8a62f228a540b05f4ed6373e494c7d72Christine Chen    private ImageView mStarImage;
1132d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private ExpandingEntryCardView mCommunicationCard;
114b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell    private MultiShrinkScroller mScroller;
115edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
1166cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee    private Contact mContactData;
1179815d7f98baf80ce51b0cf1f01f48a3dbb9a9db9Daniel Lehmann    private ContactLoader mContactLoader;
1189815d7f98baf80ce51b0cf1f01f48a3dbb9a9db9Daniel Lehmann
1199758a92fac3e9f64892d893c992f6020d7fe3bfdJosh Gargus    private final ImageViewDrawableSetter mPhotoSetter = new ImageViewDrawableSetter();
1209758a92fac3e9f64892d893c992f6020d7fe3bfdJosh Gargus
121edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    /**
122edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     * Keeps the default action per mimetype. Empty if no default actions are set
123edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     */
124edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    private HashMap<String, Action> mDefaultsMap = new HashMap<String, Action>();
125edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
126edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    /**
127edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     * Set of {@link Action} that are associated with the aggregate currently
128edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     * displayed by this dialog, represented as a map from {@link String}
129edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     * MIME-type to a list of {@link Action}.
130edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     */
131edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    private ActionMultiMap mActions = new ActionMultiMap();
132edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
133edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    /**
134edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     * {@link #LEADING_MIMETYPES} and {@link #TRAILING_MIMETYPES} are used to sort MIME-types.
135edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     *
136edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     * <p>The MIME-types in {@link #LEADING_MIMETYPES} appear in the front of the dialog,
137edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     * in the order specified here.</p>
138edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     *
139edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     * <p>The ones in {@link #TRAILING_MIMETYPES} appear in the end of the dialog, in the order
140edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     * specified here.</p>
141edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     *
142edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     * <p>The rest go between them, in the order in the array.</p>
143edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     */
144edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    private static final List<String> LEADING_MIMETYPES = Lists.newArrayList(
145edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann            Phone.CONTENT_ITEM_TYPE, SipAddress.CONTENT_ITEM_TYPE, Email.CONTENT_ITEM_TYPE);
146edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
147edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    /** See {@link #LEADING_MIMETYPES}. */
148edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    private static final List<String> TRAILING_MIMETYPES = Lists.newArrayList(
149edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann            StructuredPostal.CONTENT_ITEM_TYPE, Website.CONTENT_ITEM_TYPE);
150edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
151cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann    /** Id for the background loader */
152cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann    private static final int LOADER_ID = 0;
153edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
154dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki    private StopWatch mStopWatch = ENABLE_STOPWATCH
155dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki            ? StopWatch.start("QuickContact") : StopWatch.getNullStopWatch();
156dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki
1575ec23fdf243596717197a0c45495f24492cf0641Paul Soulos    final OnClickListener mEditContactClickHandler = new OnClickListener() {
1586cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee        @Override
1596cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee        public void onClick(View v) {
1605ec23fdf243596717197a0c45495f24492cf0641Paul Soulos            final Intent intent = new Intent(Intent.ACTION_EDIT, mLookupUri);
1616cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee            mContactLoader.cacheResult();
1626cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
1636cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee            startActivity(intent);
1646cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee        }
1656cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee    };
1666cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee
1676cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee    final OnClickListener mAddToContactsClickHandler = new OnClickListener() {
1686cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee        @Override
1696cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee        public void onClick(View v) {
1706cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee            if (mContactData == null) {
1716cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee                Log.e(TAG, "Empty contact data when trying to add to contact");
1726cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee                return;
1736cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee            }
1746cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee            final Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
1756cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee            intent.setType(Contacts.CONTENT_ITEM_TYPE);
1766cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee
1776cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee            // Only pre-fill the name field if the provided display name is an organization
1786cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee            // name or better (e.g. structured name, nickname)
1796cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee            if (mContactData.getDisplayNameSource() >= DisplayNameSources.ORGANIZATION) {
1806cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee                intent.putExtra(Insert.NAME, mContactData.getDisplayName());
1816cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee            }
1826cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee            intent.putExtra(Insert.DATA, mContactData.getContentValues());
1836cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee            startActivity(intent);
1846cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee        }
1856cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee    };
1866cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee
1872d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    final OnClickListener mEntryClickHandler = new OnClickListener() {
1882d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        @Override
1892d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        public void onClick(View v) {
1902d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            Log.i(TAG, "mEntryClickHandler onClick");
1912d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            Object intent = v.getTag();
1922d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            if (intent == null || !(intent instanceof Intent)) {
1932d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos                return;
1942d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            }
1952d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            startActivity((Intent) intent);
1962d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
1972d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    };
1982d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos
199b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell    final MultiShrinkScrollerListener mMultiShrinkScrollerListener
200b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell            = new MultiShrinkScrollerListener() {
201b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell        @Override
202b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell        public void onScrolledOffBottom() {
203b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell            onBackPressed();
204b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell        }
205b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell    };
206b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell
207edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    @Override
208edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    protected void onCreate(Bundle icicle) {
209dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki        mStopWatch.lap("c"); // create start
210edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        super.onCreate(icicle);
211edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
212dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki        mStopWatch.lap("sc"); // super.onCreate
213dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki
2142426cb015ba4cb679a525bd1ffe223527375468cDaniel Lehmann        if (TRACE_LAUNCH) android.os.Debug.startMethodTracing(TRACE_TAG);
2152426cb015ba4cb679a525bd1ffe223527375468cDaniel Lehmann
216dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki        // Parse intent
217dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki        final Intent intent = getIntent();
218dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki
219dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki        Uri lookupUri = intent.getData();
220dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki
221dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki        // Check to see whether it comes from the old version.
222dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki        if (lookupUri != null && LEGACY_AUTHORITY.equals(lookupUri.getAuthority())) {
223dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki            final long rawContactId = ContentUris.parseId(lookupUri);
224dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki            lookupUri = RawContacts.getContactLookupUri(getContentResolver(),
225dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki                    ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId));
226dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki        }
227dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki
228dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki        mLookupUri = Preconditions.checkNotNull(lookupUri, "missing lookupUri");
229dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki
230dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki        mExcludeMimes = intent.getStringArrayExtra(QuickContact.EXTRA_EXCLUDE_MIMES);
231dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki
232dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki        mStopWatch.lap("i"); // intent parsed
233dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki
234dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki        mContactLoader = (ContactLoader) getLoaderManager().initLoader(
235dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki                LOADER_ID, null, mLoaderCallbacks);
236dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki
237dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki        mStopWatch.lap("ld"); // loader started
238dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki
23910d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawa        // Show QuickContact in front of soft input
24010d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawa        getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
24110d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawa                WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
24210d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawa
243edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        setContentView(R.layout.quickcontact_activity);
244edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
245dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki        mStopWatch.lap("l"); // layout inflated
246dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki
2475ec23fdf243596717197a0c45495f24492cf0641Paul Soulos        mEditOrAddContactImage = (ImageView) findViewById(R.id.contact_edit_image);
24872b3ab1d8a62f228a540b05f4ed6373e494c7d72Christine Chen        mStarImage = (ImageView) findViewById(R.id.quickcontact_star_button);
2492d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mCommunicationCard = (ExpandingEntryCardView) findViewById(R.id.communication_card);
250b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell        mScroller = (MultiShrinkScroller) findViewById(R.id.multiscroller);
2512d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mCommunicationCard.setTitle(getResources().getString(R.string.communication_card_title));
252edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
253b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell        if (mScroller != null) {
254b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell            mScroller.initialize(mMultiShrinkScrollerListener);
255b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell        }
256b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell
2575ec23fdf243596717197a0c45495f24492cf0641Paul Soulos        mEditOrAddContactImage.setOnClickListener(mEditContactClickHandler);
2582d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mCommunicationCard.setOnClickListener(mEntryClickHandler);
259edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
260edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        // find and prepare correct header view
261edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        mPhotoContainer = findViewById(R.id.photo_container);
2626219668d0612f7522bd15a9d34c6232cb15b9a6cYorke Lee
26381281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan        setHeaderNameText(R.id.name, R.string.missing_name);
264edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
2656219668d0612f7522bd15a9d34c6232cb15b9a6cYorke Lee        mPhotoView = (ImageView) mPhotoContainer.findViewById(R.id.photo);
2665ec23fdf243596717197a0c45495f24492cf0641Paul Soulos        mPhotoView.setOnClickListener(mEditContactClickHandler);
2676219668d0612f7522bd15a9d34c6232cb15b9a6cYorke Lee
268dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki        mStopWatch.lap("v"); // view initialized
269edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
270b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell        if (mScroller != null) {
271b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell            mScroller.setVisibility(View.GONE);
272b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell        }
273dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki
274dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki        mStopWatch.lap("cf"); // onCreate finished
2752426cb015ba4cb679a525bd1ffe223527375468cDaniel Lehmann    }
276edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
277b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell    private void runEntranceAnimation() {
278b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell        final int bottomScroll = mScroller.getScrollUntilOffBottom() - 1;
279b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell        final ObjectAnimator scrollAnimation
280b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell                = ObjectAnimator.ofInt(mScroller, "scroll", -bottomScroll, 0);
281b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell        scrollAnimation.setDuration(ANIMATION_DURATION);
282b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell        scrollAnimation.start();
283b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell    }
284b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell
28581281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan    /** Assign this string to the view if it is not empty. */
28681281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan    private void setHeaderNameText(int id, int resId) {
28781281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan        setHeaderNameText(id, getText(resId));
28881281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan    }
28981281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan
29081281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan    /** Assign this string to the view if it is not empty. */
29181281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan    private void setHeaderNameText(int id, CharSequence value) {
29281281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan        final View view = mPhotoContainer.findViewById(id);
29381281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan        if (view instanceof TextView) {
29481281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan            if (!TextUtils.isEmpty(value)) {
29581281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan                ((TextView)view).setText(value);
29681281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan            }
29781281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan        }
29881281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan    }
29981281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan
30081281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan    /**
301edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     * Check if the given MIME-type appears in the list of excluded MIME-types
302edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     * that the most-recent caller requested.
303edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     */
304edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    private boolean isMimeExcluded(String mimeType) {
305edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        if (mExcludeMimes == null) return false;
306edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        for (String excludedMime : mExcludeMimes) {
307edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann            if (TextUtils.equals(excludedMime, mimeType)) {
308edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann                return true;
309edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann            }
310edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        }
311edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        return false;
312edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    }
313edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
314edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    /**
315cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann     * Handle the result from the ContactLoader
316edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     */
317851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu    private void bindData(Contact data) {
3186cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee        mContactData = data;
319edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        final ResolveCache cache = ResolveCache.getInstance(this);
320edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        final Context context = this;
321edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
3225ec23fdf243596717197a0c45495f24492cf0641Paul Soulos        mEditOrAddContactImage.setVisibility(isMimeExcluded(Contacts.CONTENT_ITEM_TYPE) ?
3236cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee                View.GONE : View.VISIBLE);
32472b3ab1d8a62f228a540b05f4ed6373e494c7d72Christine Chen        final boolean isStarred = data.getStarred();
32572b3ab1d8a62f228a540b05f4ed6373e494c7d72Christine Chen        if (isStarred) {
32672b3ab1d8a62f228a540b05f4ed6373e494c7d72Christine Chen            mStarImage.setImageResource(R.drawable.ic_favorite_on_lt);
32769f67d00a13279c010d2dde4414a0600dff99294Ben Gilad            mStarImage.setContentDescription(
32869f67d00a13279c010d2dde4414a0600dff99294Ben Gilad                getResources().getString(R.string.menu_removeStar));
32972b3ab1d8a62f228a540b05f4ed6373e494c7d72Christine Chen        } else {
33072b3ab1d8a62f228a540b05f4ed6373e494c7d72Christine Chen            mStarImage.setImageResource(R.drawable.ic_favorite_off_lt);
33169f67d00a13279c010d2dde4414a0600dff99294Ben Gilad            mStarImage.setContentDescription(
33269f67d00a13279c010d2dde4414a0600dff99294Ben Gilad                getResources().getString(R.string.menu_addStar));
33372b3ab1d8a62f228a540b05f4ed6373e494c7d72Christine Chen        }
33472b3ab1d8a62f228a540b05f4ed6373e494c7d72Christine Chen        final Uri lookupUri = data.getLookupUri();
33572b3ab1d8a62f228a540b05f4ed6373e494c7d72Christine Chen
3362e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee        // If this is a json encoded URI, there is no local contact to star
3372e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee        if (UriUtils.isEncodedContactUri(lookupUri)) {
3382e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee            mStarImage.setVisibility(View.GONE);
3396cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee
3406cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee            // If directory export support is not allowed, then don't allow the user to add
3416cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee            // to contacts
3426cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee            if (mContactData.getDirectoryExportSupport() == Directory.EXPORT_SUPPORT_NONE) {
34388df7126c8052ff0676587835662496399e44413Yorke Lee                configureHeaderClickActions(false);
3446cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee            } else {
34588df7126c8052ff0676587835662496399e44413Yorke Lee                configureHeaderClickActions(true);
3466cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee            }
3472e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee        } else {
34888df7126c8052ff0676587835662496399e44413Yorke Lee            configureHeaderClickActions(false);
3492e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee            mStarImage.setVisibility(View.VISIBLE);
3502e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee            mStarImage.setOnClickListener(new OnClickListener() {
3512e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee                @Override
3522e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee                public void onClick(View view) {
3532e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee                    // Toggle "starred" state
3542e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee                    // Make sure there is a contact
3552e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee                    if (lookupUri != null) {
3562e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee                        // Changes the state of the image already before sending updates to the
3572e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee                        // database
3582e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee                        if (isStarred) {
3592e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee                            mStarImage.setImageResource(R.drawable.ic_favorite_off_lt);
3602e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee                        } else {
3612e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee                            mStarImage.setImageResource(R.drawable.ic_favorite_on_lt);
3622e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee                        }
3632e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee
3642e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee                        // Now perform the real save
3652e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee                        final Intent intent = ContactSaveService.createSetStarredIntent(context,
3662e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee                                lookupUri, !isStarred);
3672e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee                        context.startService(intent);
3682e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee                    }
36972b3ab1d8a62f228a540b05f4ed6373e494c7d72Christine Chen                }
3702e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee            });
3712e3858324cfca8f1f8f8bf0c6ec533979df0a250Yorke Lee        }
372edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
373edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        mDefaultsMap.clear();
374edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
375851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu        mStopWatch.lap("sph"); // Start photo setting
376dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki
3776219668d0612f7522bd15a9d34c6232cb15b9a6cYorke Lee        mPhotoSetter.setupContactPhoto(data, mPhotoView);
37831b2d42fb0889e61515d27314aa5a245147100daBrian Attwell        extractAndApplyTintFromPhotoViewAsynchronously();
379edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
380dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki        mStopWatch.lap("ph"); // Photo set
381dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki
382851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu        for (RawContact rawContact : data.getRawContacts()) {
383851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu            for (DataItem dataItem : rawContact.getDataItems()) {
384851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu                final String mimeType = dataItem.getMimeType();
38547b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng                final AccountType accountType = rawContact.getAccountType(this);
38647b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng                final DataKind dataKind = AccountTypeManager.getInstance(this)
38747b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng                        .getKindOrFallback(accountType, mimeType);
388cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann
389cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann                // Skip this data item if MIME-type excluded
390cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann                if (isMimeExcluded(mimeType)) continue;
391cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann
392851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu                final long dataId = dataItem.getId();
393851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu                final boolean isPrimary = dataItem.isPrimary();
394851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu                final boolean isSuperPrimary = dataItem.isSuperPrimary();
395cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann
39647b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng                if (dataKind != null) {
397cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann                    // Build an action for this data entry, find a mapping to a UI
398cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann                    // element, build its summary from the cursor, and collect it
399cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann                    // along with all others of this MIME-type.
40047b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng                    final Action action = new DataAction(context, dataItem, dataKind);
4018a0dd0f08ab11e9c6dad386e4411aeeb4c0cd73fMaurice Chu                    final boolean wasAdded = considerAdd(action, cache, isSuperPrimary);
402cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann                    if (wasAdded) {
403cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann                        // Remember the default
404cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann                        if (isSuperPrimary || (isPrimary && (mDefaultsMap.get(mimeType) == null))) {
405cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann                            mDefaultsMap.put(mimeType, action);
406edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann                        }
407edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann                    }
408edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann                }
409edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
410cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann                // Handle Email rows with presence data as Im entry
4119daca14706f3699c9e9d46dfb522132fc566e57eDaniel Lehmann                final DataStatus status = data.getStatuses().get(dataId);
412851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu                if (status != null && dataItem instanceof EmailDataItem) {
413851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu                    final EmailDataItem email = (EmailDataItem) dataItem;
414851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu                    final ImDataItem im = ImDataItem.createFromEmail(email);
41547b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng                    if (dataKind != null) {
41647b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng                        final DataAction action = new DataAction(context, im, dataKind);
4179daca14706f3699c9e9d46dfb522132fc566e57eDaniel Lehmann                        action.setPresence(status.getPresence());
4188a0dd0f08ab11e9c6dad386e4411aeeb4c0cd73fMaurice Chu                        considerAdd(action, cache, isSuperPrimary);
419cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann                    }
420edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann                }
421edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann            }
422edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        }
423edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
424dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki        mStopWatch.lap("e"); // Entities inflated
425dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki
426edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        // Collapse Action Lists (remove e.g. duplicate e-mail addresses from different sources)
427edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        for (List<Action> actionChildren : mActions.values()) {
428edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann            Collapser.collapseList(actionChildren);
429edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        }
430edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
431dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki        mStopWatch.lap("c"); // List collapsed
432dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki
433cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann        setHeaderNameText(R.id.name, data.getDisplayName());
434edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
4352d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        // List of Entry that makes up the ExpandingEntryCardView
4362d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        final List<Entry> entries = new ArrayList<>();
437edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        // All the mime-types to add.
438edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        final Set<String> containedTypes = new HashSet<String>(mActions.keySet());
439edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        mSortedActionMimeTypes.clear();
440edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        // First, add LEADING_MIMETYPES, which are most common.
441edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        for (String mimeType : LEADING_MIMETYPES) {
442edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann            if (containedTypes.contains(mimeType)) {
443edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann                mSortedActionMimeTypes.add(mimeType);
444edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann                containedTypes.remove(mimeType);
4452d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos                entries.addAll(actionsToEntries(mActions.get(mimeType)));
446edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann            }
447edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        }
448edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
449edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        // Add all the remaining ones that are not TRAILING
450edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        for (String mimeType : containedTypes.toArray(new String[containedTypes.size()])) {
451edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann            if (!TRAILING_MIMETYPES.contains(mimeType)) {
452edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann                mSortedActionMimeTypes.add(mimeType);
453edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann                containedTypes.remove(mimeType);
4542d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos                entries.addAll(actionsToEntries(mActions.get(mimeType)));
455edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann            }
456edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        }
457edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
458edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        // Then, add TRAILING_MIMETYPES, which are least common.
459edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        for (String mimeType : TRAILING_MIMETYPES) {
460edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann            if (containedTypes.contains(mimeType)) {
461edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann                containedTypes.remove(mimeType);
462edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann                mSortedActionMimeTypes.add(mimeType);
4632d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos                entries.addAll(actionsToEntries(mActions.get(mimeType)));
464edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann            }
465edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        }
46671032f3fb7038995297666602773ae023c1351c4Brian Attwell        mCommunicationCard.initialize(entries, /* numInitialVisibleEntries = */ 2,
4672d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos                /* isExpanded = */ false, /* themeColor = */ 0);
468dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki
469edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        final boolean hasData = !mSortedActionMimeTypes.isEmpty();
4702d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        mCommunicationCard.setVisibility(hasData ? View.VISIBLE: View.GONE);
471edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    }
472edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
473edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    /**
47431b2d42fb0889e61515d27314aa5a245147100daBrian Attwell     * Asynchronously extract the most vibrant color from the PhotoView. Once extracted,
47531b2d42fb0889e61515d27314aa5a245147100daBrian Attwell     * apply this tint to {@link MultiShrinkScroller}. This operation takes about 20-30ms
47631b2d42fb0889e61515d27314aa5a245147100daBrian Attwell     * on a Nexus 5.
47731b2d42fb0889e61515d27314aa5a245147100daBrian Attwell     */
47831b2d42fb0889e61515d27314aa5a245147100daBrian Attwell    private void extractAndApplyTintFromPhotoViewAsynchronously() {
47931b2d42fb0889e61515d27314aa5a245147100daBrian Attwell        if (mScroller == null) {
48031b2d42fb0889e61515d27314aa5a245147100daBrian Attwell            return;
48131b2d42fb0889e61515d27314aa5a245147100daBrian Attwell        }
48231b2d42fb0889e61515d27314aa5a245147100daBrian Attwell        final Drawable imageViewDrawable = mPhotoView.getDrawable();
48331b2d42fb0889e61515d27314aa5a245147100daBrian Attwell        new AsyncTask<Void, Void, Integer>() {
48431b2d42fb0889e61515d27314aa5a245147100daBrian Attwell            @Override
48531b2d42fb0889e61515d27314aa5a245147100daBrian Attwell            protected Integer doInBackground(Void... params) {
48631b2d42fb0889e61515d27314aa5a245147100daBrian Attwell                final Bitmap bitmap;
48731b2d42fb0889e61515d27314aa5a245147100daBrian Attwell                if (imageViewDrawable instanceof BitmapDrawable) {
48831b2d42fb0889e61515d27314aa5a245147100daBrian Attwell                    bitmap = ((BitmapDrawable) imageViewDrawable).getBitmap();
48931b2d42fb0889e61515d27314aa5a245147100daBrian Attwell                } else if (imageViewDrawable instanceof LetterTileDrawable) {
49031b2d42fb0889e61515d27314aa5a245147100daBrian Attwell                    // LetterTileDrawable doesn't normally draw unless it is visible. Therefore,
49131b2d42fb0889e61515d27314aa5a245147100daBrian Attwell                    // we need to directly ask it for its color via getColor(). We could directly
49231b2d42fb0889e61515d27314aa5a245147100daBrian Attwell                    // return this color. However, in the future Palette#generate() may incorporate
49331b2d42fb0889e61515d27314aa5a245147100daBrian Attwell                    // saturation boosting. So I want to use Palette#generate() for the sake of
49431b2d42fb0889e61515d27314aa5a245147100daBrian Attwell                    // consistency.
49531b2d42fb0889e61515d27314aa5a245147100daBrian Attwell                    final LetterTileDrawable tileDrawable = (LetterTileDrawable) imageViewDrawable;
49631b2d42fb0889e61515d27314aa5a245147100daBrian Attwell                    final int PALETTE_BITMAP_SIZE = 1;
49731b2d42fb0889e61515d27314aa5a245147100daBrian Attwell                    bitmap = Bitmap.createBitmap(PALETTE_BITMAP_SIZE,
49831b2d42fb0889e61515d27314aa5a245147100daBrian Attwell                            PALETTE_BITMAP_SIZE, Bitmap.Config.ARGB_8888);
49931b2d42fb0889e61515d27314aa5a245147100daBrian Attwell                    final Canvas canvas = new Canvas(bitmap);
50031b2d42fb0889e61515d27314aa5a245147100daBrian Attwell                    canvas.drawColor(tileDrawable.getColor());
50131b2d42fb0889e61515d27314aa5a245147100daBrian Attwell                } else {
50231b2d42fb0889e61515d27314aa5a245147100daBrian Attwell                    return 0;
50331b2d42fb0889e61515d27314aa5a245147100daBrian Attwell                }
50431b2d42fb0889e61515d27314aa5a245147100daBrian Attwell                // Author of Palette recommends using 24 colors when analyzing profile photos.
50531b2d42fb0889e61515d27314aa5a245147100daBrian Attwell                final int NUMBER_OF_PALETTE_COLORS = 24;
50631b2d42fb0889e61515d27314aa5a245147100daBrian Attwell                final Palette palette = Palette.generate(bitmap, NUMBER_OF_PALETTE_COLORS);
50731b2d42fb0889e61515d27314aa5a245147100daBrian Attwell                if (palette != null && palette.getVibrantColor() != null) {
50831b2d42fb0889e61515d27314aa5a245147100daBrian Attwell                    return palette.getVibrantColor().getRgb();
50931b2d42fb0889e61515d27314aa5a245147100daBrian Attwell                } else {
51031b2d42fb0889e61515d27314aa5a245147100daBrian Attwell                    return 0;
51131b2d42fb0889e61515d27314aa5a245147100daBrian Attwell                }
51231b2d42fb0889e61515d27314aa5a245147100daBrian Attwell            }
51331b2d42fb0889e61515d27314aa5a245147100daBrian Attwell
51431b2d42fb0889e61515d27314aa5a245147100daBrian Attwell            @Override
51531b2d42fb0889e61515d27314aa5a245147100daBrian Attwell            protected void onPostExecute(Integer color) {
51631b2d42fb0889e61515d27314aa5a245147100daBrian Attwell                super.onPostExecute(color);
51731b2d42fb0889e61515d27314aa5a245147100daBrian Attwell                if (color != 0 && imageViewDrawable == mPhotoView.getDrawable()) {
51831b2d42fb0889e61515d27314aa5a245147100daBrian Attwell                    // TODO: animate from the previous tint.
51931b2d42fb0889e61515d27314aa5a245147100daBrian Attwell                    mScroller.setHeaderTintColor(color);
52031b2d42fb0889e61515d27314aa5a245147100daBrian Attwell                }
52131b2d42fb0889e61515d27314aa5a245147100daBrian Attwell            }
52231b2d42fb0889e61515d27314aa5a245147100daBrian Attwell        }.execute();
52331b2d42fb0889e61515d27314aa5a245147100daBrian Attwell    }
52431b2d42fb0889e61515d27314aa5a245147100daBrian Attwell
52531b2d42fb0889e61515d27314aa5a245147100daBrian Attwell    /**
526edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     * Consider adding the given {@link Action}, which will only happen if
527edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     * {@link PackageManager} finds an application to handle
528edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     * {@link Action#getIntent()}.
5298a0dd0f08ab11e9c6dad386e4411aeeb4c0cd73fMaurice Chu     * @param action the action to handle
5308a0dd0f08ab11e9c6dad386e4411aeeb4c0cd73fMaurice Chu     * @param resolveCache cache of applications that can handle actions
5318a0dd0f08ab11e9c6dad386e4411aeeb4c0cd73fMaurice Chu     * @param front indicates whether to add the action to the front of the list
532edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     * @return true if action has been added
533edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     */
5348a0dd0f08ab11e9c6dad386e4411aeeb4c0cd73fMaurice Chu    private boolean considerAdd(Action action, ResolveCache resolveCache, boolean front) {
535edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        if (resolveCache.hasResolve(action)) {
5368a0dd0f08ab11e9c6dad386e4411aeeb4c0cd73fMaurice Chu            mActions.put(action.getMimeType(), action, front);
537edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann            return true;
538edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        }
539edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann        return false;
540edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    }
541edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
542edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    /**
54388df7126c8052ff0676587835662496399e44413Yorke Lee     * Bind the correct image resource and click handlers to the header views
54488df7126c8052ff0676587835662496399e44413Yorke Lee     *
54588df7126c8052ff0676587835662496399e44413Yorke Lee     * @param canAdd Whether or not the user can directly add information in this quick contact
54688df7126c8052ff0676587835662496399e44413Yorke Lee     * to their local contacts
54788df7126c8052ff0676587835662496399e44413Yorke Lee     */
54888df7126c8052ff0676587835662496399e44413Yorke Lee    private void configureHeaderClickActions(boolean canAdd) {
54988df7126c8052ff0676587835662496399e44413Yorke Lee        if (canAdd) {
550b8eb33c2ef87d0eeac209f43dab1fae51d9ed3ddPaul Soulos            mEditOrAddContactImage.setImageResource(R.drawable.ic_person_add_24dp);
5515ec23fdf243596717197a0c45495f24492cf0641Paul Soulos            mEditOrAddContactImage.setOnClickListener(mAddToContactsClickHandler);
55288df7126c8052ff0676587835662496399e44413Yorke Lee            mPhotoView.setOnClickListener(mAddToContactsClickHandler);
55388df7126c8052ff0676587835662496399e44413Yorke Lee        } else {
554b8eb33c2ef87d0eeac209f43dab1fae51d9ed3ddPaul Soulos            mEditOrAddContactImage.setImageResource(R.drawable.ic_create_24dp);
5555ec23fdf243596717197a0c45495f24492cf0641Paul Soulos            mEditOrAddContactImage.setOnClickListener(mEditContactClickHandler);
5565ec23fdf243596717197a0c45495f24492cf0641Paul Soulos            mPhotoView.setOnClickListener(mEditContactClickHandler);
55788df7126c8052ff0676587835662496399e44413Yorke Lee        }
55888df7126c8052ff0676587835662496399e44413Yorke Lee    }
55988df7126c8052ff0676587835662496399e44413Yorke Lee
56088df7126c8052ff0676587835662496399e44413Yorke Lee    /**
5612d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     * Converts a list of Action into a list of Entry
5622d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     * @param actions The list of Action to convert
5632d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos     * @return The converted list of Entry
564edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann     */
5652d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos    private List<Entry> actionsToEntries(List<Action> actions) {
5662d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        List<Entry> entries = new ArrayList<>();
5672d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        for (Action action :  actions) {
5682d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos            entries.add(new Entry(ResolveCache.getInstance(this).getIcon(action),
5692d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos                    action.getMimeType(), action.getSubtitle().toString(),
5702d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos                    action.getBody().toString(), action.getIntent(), /* isEditable= */ false));
5712d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        }
5722d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos        return entries;
573edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann    }
574edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann
575851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu    private LoaderCallbacks<Contact> mLoaderCallbacks =
576851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu            new LoaderCallbacks<Contact>() {
577cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann        @Override
578851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu        public void onLoaderReset(Loader<Contact> loader) {
579cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann        }
580cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann
581cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann        @Override
582851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu        public void onLoadFinished(Loader<Contact> loader, Contact data) {
583dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki            mStopWatch.lap("lf"); // onLoadFinished
584cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann            if (isFinishing()) {
585cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann                return;
586cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann            }
587cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann            if (data.isError()) {
588cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann                // This shouldn't ever happen, so throw an exception. The {@link ContactLoader}
589cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann                // should log the actual exception.
590cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann                throw new IllegalStateException("Failed to load contact", data.getException());
591cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann            }
592cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann            if (data.isNotFound()) {
593cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann                Log.i(TAG, "No contact found: " + ((ContactLoader)loader).getLookupUri());
594cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann                Toast.makeText(QuickContactActivity.this, R.string.invalidContactMessage,
595cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann                        Toast.LENGTH_LONG).show();
596cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann                return;
597cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann            }
598cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann
599cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann            bindData(data);
600cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann
601dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki            mStopWatch.lap("bd"); // bindData finished
602dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki
6032426cb015ba4cb679a525bd1ffe223527375468cDaniel Lehmann            if (TRACE_LAUNCH) android.os.Debug.stopMethodTracing();
604fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki            if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG)) {
605fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki                Log.d(Constants.PERFORMANCE_TAG, "QuickContact shown");
606fc0a89fdb1e0bfe5c47e733f867ca520e117316bMakoto Onuki            }
607cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann
608b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell            if (mScroller != null) {
609b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell                // Data bound and ready, pull curtain to show. Put this on the Handler to ensure
610b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell                // that the layout passes are completed
611b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell                mScroller.setVisibility(View.VISIBLE);
612b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell                SchedulingUtils.doOnPreDraw(mScroller, /* drawNextFrame = */ false,
613b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell                        new Runnable() {
614b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell                    @Override
615b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell                    public void run() {
616b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell                        runEntranceAnimation();
617b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell                    }
618b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell                });
619b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell            }
620dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki            mStopWatch.stopAndLog(TAG, 0);
621b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell            mStopWatch = StopWatch.getNullStopWatch();
622cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann        }
623cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann
624cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann        @Override
625851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu        public Loader<Contact> onCreateLoader(int id, Bundle args) {
626cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann            if (mLookupUri == null) {
627cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann                Log.wtf(TAG, "Lookup uri wasn't initialized. Loader was started too early");
628cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann            }
629b2b435a944947fbf1965c3bb7c202a97f0273259Yorke Lee            return new ContactLoader(getApplicationContext(), mLookupUri,
63045f23d4d67438c0561f74ef87b7028f6d74f7503Paul Sliwowski                    false /*loadGroupMetaData*/, false /*loadInvitableAccountTypes*/,
63145f23d4d67438c0561f74ef87b7028f6d74f7503Paul Sliwowski                    false /*postViewNotification*/, true /*computeFormattedPhoneNumber*/);
632cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann        }
633cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann    };
634b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell    @Override
635b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell    public void onBackPressed() {
636b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell        if (mScroller != null) {
637b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell            // TODO: implement exit animation if the scroller isn't already off the screen
638b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell            finish();
639b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell        } else {
640b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell            super.onBackPressed();
641b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell        }
642b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell    }
643edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann}
644