QuickContactActivity.java revision 8a3fe52802135be2402a5b216325615fb796a509
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; 730319222b43927d4d9ce7e2a9070f3543661b5782Tyler Gunnimport android.telecom.PhoneAccount; 740319222b43927d4d9ce7e2a9070f3543661b5782Tyler Gunnimport android.telecom.TelecomManager; 75c62cc7931593b4137f8a507689b653e1e15e1260Brian Attwellimport android.text.BidiFormatter; 76c62cc7931593b4137f8a507689b653e1e15e1260Brian Attwellimport android.text.TextDirectionHeuristics; 77edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.text.TextUtils; 78edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.util.Log; 792a4207fb39330e840436215c896cde911489e111Paul Soulosimport android.view.ContextMenu; 802a4207fb39330e840436215c896cde911489e111Paul Soulosimport android.view.ContextMenu.ContextMenuInfo; 81d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport android.view.Menu; 82d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport android.view.MenuInflater; 83eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport android.view.MenuItem; 84f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chenimport android.view.MotionEvent; 85edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.view.View; 86edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.view.View.OnClickListener; 872a4207fb39330e840436215c896cde911489e111Paul Soulosimport android.view.View.OnCreateContextMenuListener; 8810d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawaimport android.view.WindowManager; 89edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport android.widget.Toast; 90d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport android.widget.Toolbar; 91edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 9272b3ab1d8a62f228a540b05f4ed6373e494c7d72Christine Chenimport com.android.contacts.ContactSaveService; 93d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport com.android.contacts.ContactsActivity; 942d150da246632b1649999cfabed776133b097775Brian Attwellimport com.android.contacts.NfcHandler; 95e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.R; 96eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.CallUtil; 972a4207fb39330e840436215c896cde911489e111Paul Soulosimport com.android.contacts.common.ClipboardUtils; 98eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.Collapser; 99eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.ContactsUtils; 100d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport com.android.contacts.common.editor.SelectAccountDialogFragment; 10170e3f4f45c040a2d09bfb46462242b450cf20b29Nancy Chenimport com.android.contacts.common.interactions.TouchPointManager; 10231b2d42fb0889e61515d27314aa5a245147100daBrian Attwellimport com.android.contacts.common.lettertiles.LetterTileDrawable; 103752cccf954bd6070c5fb623875314951c8e9849dBrian Attwellimport com.android.contacts.common.list.ShortcutIntentBuilder; 104752cccf954bd6070c5fb623875314951c8e9849dBrian Attwellimport com.android.contacts.common.list.ShortcutIntentBuilder.OnShortcutIntentCreatedListener; 1050d5588da244d0992c3ff8f25d0875fdf95a8c644Chiao Chengimport com.android.contacts.common.model.AccountTypeManager; 106cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.Contact; 107cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.ContactLoader; 108cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.RawContact; 109428f008513d1591cc08fcfe2cf0c9237fb313241Chiao Chengimport com.android.contacts.common.model.account.AccountType; 110d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellimport com.android.contacts.common.model.account.AccountWithDataSet; 111cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.dataitem.DataItem; 112428f008513d1591cc08fcfe2cf0c9237fb313241Chiao Chengimport com.android.contacts.common.model.dataitem.DataKind; 113cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.dataitem.EmailDataItem; 114eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.EventDataItem; 115cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.dataitem.ImDataItem; 116eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.NicknameDataItem; 117eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.NoteDataItem; 118eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.OrganizationDataItem; 119b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulosimport com.android.contacts.common.model.dataitem.PhoneDataItem; 120eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.RelationDataItem; 121eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.SipAddressDataItem; 122eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.StructuredNameDataItem; 123eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.StructuredPostalDataItem; 124eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.model.dataitem.WebsiteDataItem; 125eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.common.util.DateUtils; 126faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwellimport com.android.contacts.common.util.MaterialColorMapUtils; 127faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwellimport com.android.contacts.common.util.MaterialColorMapUtils.MaterialPalette; 128d41ab8ace81a2e44f8b28aa8782679b9e9cca1b9Brian Attwellimport com.android.contacts.common.util.ViewUtil; 129333091ae754ddfc25714c14b9b89534be24379f9Paul Soulosimport com.android.contacts.detail.ContactDisplayUtils; 130f19dda97bfdef84e3f39ba069a981004a5c797b1Paul Soulosimport com.android.contacts.editor.ContactEditorFragment; 131899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulosimport com.android.contacts.interactions.CalendarInteractionsLoader; 132ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulosimport com.android.contacts.interactions.CallLogInteractionsLoader; 1338a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwellimport com.android.contacts.interactions.ContactDeletionInteraction; 134b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulosimport com.android.contacts.interactions.ContactInteraction; 135b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulosimport com.android.contacts.interactions.SmsInteractionsLoader; 1362d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport com.android.contacts.quickcontact.ExpandingEntryCardView.Entry; 1372a4207fb39330e840436215c896cde911489e111Paul Soulosimport com.android.contacts.quickcontact.ExpandingEntryCardView.EntryContextMenuInfo; 1382ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulosimport com.android.contacts.quickcontact.ExpandingEntryCardView.EntryTag; 139e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwellimport com.android.contacts.quickcontact.ExpandingEntryCardView.ExpandingEntryCardViewListener; 140e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.util.ImageViewDrawableSetter; 141eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.util.PhoneCapabilityTester; 142b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwellimport com.android.contacts.util.SchedulingUtils; 143eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport com.android.contacts.util.StructuredPostalUtils; 144b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwellimport com.android.contacts.widget.MultiShrinkScroller; 145b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwellimport com.android.contacts.widget.MultiShrinkScroller.MultiShrinkScrollerListener; 14602eaf11669d25fd885606b3b0700358323532cddBrian Attwellimport com.android.contacts.widget.QuickContactImageView; 147e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.google.common.base.Preconditions; 148e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.google.common.collect.Lists; 149e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Cheng 1502d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulosimport java.util.ArrayList; 151899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulosimport java.util.Arrays; 152eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport java.util.Calendar; 153b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulosimport java.util.Collections; 154b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulosimport java.util.Comparator; 155eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulosimport java.util.Date; 156edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport java.util.HashMap; 157edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmannimport java.util.List; 158b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulosimport java.util.Map; 159edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 160edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann/** 161edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * Mostly translucent {@link Activity} that shows QuickContact dialog. It loads 162edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * data asynchronously, and then shows a popup with details centered around 163edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * {@link Intent#getSourceBounds()}. 164edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann */ 165d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwellpublic class QuickContactActivity extends ContactsActivity { 1668a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 1678a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell /** 1688a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell * QuickContacts immediately takes up the full screen. All possible information is shown. 1698a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell * This value for {@link android.provider.ContactsContract.QuickContact#EXTRA_MODE} 1708a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell * should only be used by the Contacts app. 1718a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell */ 1728a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell public static final int MODE_FULLY_EXPANDED = 4; 1738a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 174edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private static final String TAG = "QuickContact"; 175edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 1769b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell private static final String KEY_THEME_COLOR = "theme_color"; 1779b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell 1789b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell private static final int ANIMATION_STATUS_BAR_COLOR_CHANGE_DURATION = 150; 1798a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private static final int REQUEST_CODE_CONTACT_EDITOR_ACTIVITY = 1; 1800b267fec5cb5b2d836057b16d0085be349be5243Brian Attwell private static final int SCRIM_COLOR = Color.argb(0xC8, 0, 0, 0); 181ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos private static final int REQUEST_CODE_CONTACT_SELECTION_ACTIVITY = 2; 182ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos private static final String MIMETYPE_SMS = "vnd.android-dir/mms-sms"; 183dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 184752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell /** This is the Intent action to install a shortcut in the launcher. */ 185752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell private static final String ACTION_INSTALL_SHORTCUT = 186752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell "com.android.launcher.action.INSTALL_SHORTCUT"; 187edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 188edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann @SuppressWarnings("deprecation") 189edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private static final String LEGACY_AUTHORITY = android.provider.Contacts.AUTHORITY; 190edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 191e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos private static final String MIMETYPE_GPLUS_PROFILE = 192e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos "vnd.android.cursor.item/vnd.googleplus.profile"; 1936a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos private static final String GPLUS_PROFILE_DATA_5_ADD_TO_CIRCLE = "addtocircle"; 1946a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos private static final String GPLUS_PROFILE_DATA_5_VIEW_PROFILE = "view"; 195e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos private static final String MIMETYPE_HANGOUTS = 196e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos "vnd.android.cursor.item/vnd.googleplus.profile.comm"; 1976a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos private static final String HANGOUTS_DATA_5_VIDEO = "hangout"; 1986a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos private static final String HANGOUTS_DATA_5_MESSAGE = "conversation"; 19948fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos private static final String CALL_ORIGIN_QUICK_CONTACTS_ACTIVITY = 20048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos "com.android.contacts.quickcontact.QuickContactActivity"; 201e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos 20263176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell /** 20363176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell * The URI used to load the the Contact. Once the contact is loaded, use Contact#getLookupUri() 20463176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell * instead of referencing this URI. 20563176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell */ 206edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private Uri mLookupUri; 207edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private String[] mExcludeMimes; 2088a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private int mExtraMode; 2098a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private int mStatusBarColor; 2108a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private boolean mHasAlreadyBeenOpened; 21197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos private boolean mOnlyOnePhoneNumber; 21297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos private boolean mOnlyOneEmail; 213edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 21402eaf11669d25fd885606b3b0700358323532cddBrian Attwell private QuickContactImageView mPhotoView; 215eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos private ExpandingEntryCardView mContactCard; 2166095369885edcca566a812b551886e29c7ff8039Brian Attwell private ExpandingEntryCardView mNoContactDetailsCard; 217b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos private ExpandingEntryCardView mRecentCard; 218eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos private ExpandingEntryCardView mAboutCard; 219b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell private MultiShrinkScroller mScroller; 220d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell private SelectAccountDialogFragmentListener mSelectAccountFragmentListener; 2216bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private AsyncTask<Void, Void, Cp2DataCardModel> mEntriesAndActionsTask; 22230e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell private AsyncTask<Void, Void, Void> mRecentDataTask; 2236bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell /** 2246bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell * The last copy of Cp2DataCardModel that was passed to {@link #populateContactAndAboutCard}. 2256bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell */ 2266bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private Cp2DataCardModel mCachedCp2DataCardModel; 227f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell /** 228f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell * This scrim's opacity is controlled in two different ways. 1) Before the initial entrance 229f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell * animation finishes, the opacity is animated by a value animator. This is designed to 230f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell * distract the user from the length of the initial loading time. 2) After the initial 231f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell * entrance animation, the opacity is directly related to scroll position. 232f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell */ 2339b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell private ColorDrawable mWindowScrim; 234f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell private boolean mIsEntranceAnimationFinished; 235a3859ed9ff9f315d492e199620a08ae35ab8569fBrian Attwell private MaterialColorMapUtils mMaterialColorMapUtils; 2368477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell private boolean mIsExitAnimationInProgress; 2378571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell private boolean mHasComputedThemeColor; 238edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 239a42ef76251778161d27bc07db214b8c81720e476Paul Soulos /** 240a42ef76251778161d27bc07db214b8c81720e476Paul Soulos * Used to stop the ExpandingEntry cards from adjusting between an entry click and the intent 241a42ef76251778161d27bc07db214b8c81720e476Paul Soulos * being launched. 242a42ef76251778161d27bc07db214b8c81720e476Paul Soulos */ 243a42ef76251778161d27bc07db214b8c81720e476Paul Soulos private boolean mHasIntentLaunched; 244a42ef76251778161d27bc07db214b8c81720e476Paul Soulos 2456cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee private Contact mContactData; 2469815d7f98baf80ce51b0cf1f01f48a3dbb9a9db9Daniel Lehmann private ContactLoader mContactLoader; 2479b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell private PorterDuffColorFilter mColorFilter; 2489815d7f98baf80ce51b0cf1f01f48a3dbb9a9db9Daniel Lehmann 2499758a92fac3e9f64892d893c992f6020d7fe3bfdJosh Gargus private final ImageViewDrawableSetter mPhotoSetter = new ImageViewDrawableSetter(); 2509758a92fac3e9f64892d893c992f6020d7fe3bfdJosh Gargus 251edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann /** 252cb4fcc7ef75c33411d2b900db7933c5bc4336527Paul Soulos * {@link #LEADING_MIMETYPES} is used to sort MIME-types. 253edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * 254edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * <p>The MIME-types in {@link #LEADING_MIMETYPES} appear in the front of the dialog, 255edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * in the order specified here.</p> 256edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann */ 257edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private static final List<String> LEADING_MIMETYPES = Lists.newArrayList( 258cb4fcc7ef75c33411d2b900db7933c5bc4336527Paul Soulos Phone.CONTENT_ITEM_TYPE, SipAddress.CONTENT_ITEM_TYPE, Email.CONTENT_ITEM_TYPE, 259405ae406379ad9c47770783afc76a660f6c55fcaPaul Soulos StructuredPostal.CONTENT_ITEM_TYPE); 260edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 261a153dba33c2152332c5706178a367f52b0550723Paul Soulos private static final List<String> SORTED_ABOUT_CARD_MIMETYPES = Lists.newArrayList( 262a153dba33c2152332c5706178a367f52b0550723Paul Soulos Nickname.CONTENT_ITEM_TYPE, 263a153dba33c2152332c5706178a367f52b0550723Paul Soulos // Phonetic name is inserted after nickname if it is available. 264a153dba33c2152332c5706178a367f52b0550723Paul Soulos // No mimetype for phonetic name exists. 265a153dba33c2152332c5706178a367f52b0550723Paul Soulos Website.CONTENT_ITEM_TYPE, 266a153dba33c2152332c5706178a367f52b0550723Paul Soulos Organization.CONTENT_ITEM_TYPE, 267a153dba33c2152332c5706178a367f52b0550723Paul Soulos Event.CONTENT_ITEM_TYPE, 268a153dba33c2152332c5706178a367f52b0550723Paul Soulos Relation.CONTENT_ITEM_TYPE, 269a153dba33c2152332c5706178a367f52b0550723Paul Soulos Im.CONTENT_ITEM_TYPE, 270a153dba33c2152332c5706178a367f52b0550723Paul Soulos GroupMembership.CONTENT_ITEM_TYPE, 271a153dba33c2152332c5706178a367f52b0550723Paul Soulos Identity.CONTENT_ITEM_TYPE, 272a153dba33c2152332c5706178a367f52b0550723Paul Soulos Note.CONTENT_ITEM_TYPE); 273eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 274c62cc7931593b4137f8a507689b653e1e15e1260Brian Attwell private static final BidiFormatter sBidiFormatter = BidiFormatter.getInstance(); 275c62cc7931593b4137f8a507689b653e1e15e1260Brian Attwell 276b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos /** Id for the background contact loader */ 277b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos private static final int LOADER_CONTACT_ID = 0; 278b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 279ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos private static final String KEY_LOADER_EXTRA_PHONES = 280ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos QuickContactActivity.class.getCanonicalName() + ".KEY_LOADER_EXTRA_PHONES"; 281ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 282b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos /** Id for the background Sms Loader */ 283b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos private static final int LOADER_SMS_ID = 1; 284b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos private static final int MAX_SMS_RETRIEVE = 3; 285ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 286ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos /** Id for the back Calendar Loader */ 287899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos private static final int LOADER_CALENDAR_ID = 2; 288ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos private static final String KEY_LOADER_EXTRA_EMAILS = 289ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos QuickContactActivity.class.getCanonicalName() + ".KEY_LOADER_EXTRA_EMAILS"; 290899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos private static final int MAX_PAST_CALENDAR_RETRIEVE = 3; 291899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos private static final int MAX_FUTURE_CALENDAR_RETRIEVE = 3; 292899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos private static final long PAST_MILLISECOND_TO_SEARCH_LOCAL_CALENDAR = 29340d7a65c6e68967f3f486715b194c144d93c296fPaul Soulos 1L * 24L * 60L * 60L * 1000L /* 1 day */; 294899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos private static final long FUTURE_MILLISECOND_TO_SEARCH_LOCAL_CALENDAR = 29540d7a65c6e68967f3f486715b194c144d93c296fPaul Soulos 7L * 24L * 60L * 60L * 1000L /* 7 days */; 296899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos 297ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos /** Id for the background Call Log Loader */ 298ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos private static final int LOADER_CALL_LOG_ID = 3; 299ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos private static final int MAX_CALL_LOG_RETRIEVE = 3; 3006095369885edcca566a812b551886e29c7ff8039Brian Attwell private static final int MIN_NUM_CONTACT_ENTRIES_SHOWN = 3; 3016095369885edcca566a812b551886e29c7ff8039Brian Attwell private static final int MIN_NUM_COLLAPSED_RECENT_ENTRIES_SHOWN = 3; 3026095369885edcca566a812b551886e29c7ff8039Brian Attwell private static final int CARD_ENTRY_ID_EDIT_CONTACT = -2; 303ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 304ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 305ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos private static final int[] mRecentLoaderIds = new int[]{ 306ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos LOADER_SMS_ID, 307ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos LOADER_CALENDAR_ID, 308ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos LOADER_CALL_LOG_ID}; 309a8fce966f48d84af82f5ad767aa7986740ca7b26Paul Soulos private Map<Integer, List<ContactInteraction>> mRecentLoaderResults = new HashMap<>(); 310b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 311d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell private static final String FRAGMENT_TAG_SELECT_ACCOUNT = "select_account_fragment"; 3126cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee 3132d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos final OnClickListener mEntryClickHandler = new OnClickListener() { 3142d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos @Override 3152d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos public void onClick(View v) { 3162ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos final Object entryTagObject = v.getTag(); 3172ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos if (entryTagObject == null || !(entryTagObject instanceof EntryTag)) { 3182ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos Log.w(TAG, "EntryTag was not used correctly"); 3196095369885edcca566a812b551886e29c7ff8039Brian Attwell return; 3206095369885edcca566a812b551886e29c7ff8039Brian Attwell } 3212ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos final EntryTag entryTag = (EntryTag) entryTagObject; 3222ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos final Intent intent = entryTag.getIntent(); 3232ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos final int dataId = entryTag.getId(); 3242ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos 3252ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos if (dataId == CARD_ENTRY_ID_EDIT_CONTACT) { 3262ed2a73d15bd80bced18e5924d3f84c8a9e5e5a5Paul Soulos editContact(); 3272d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos return; 3282d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 329ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos 330ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos // Default to USAGE_TYPE_CALL. Usage is summed among all types for sorting each data id 331ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos // so the exact usage type is not necessary in all cases 332ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos String usageType = DataUsageFeedback.USAGE_TYPE_CALL; 333ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos 33420bdf9d2d21e1c82513f798ef4205b9d1713996dPaul Soulos final Uri intentUri = intent.getData(); 33520bdf9d2d21e1c82513f798ef4205b9d1713996dPaul Soulos if ((intentUri != null && intentUri.getScheme() != null && 3361cd88e3ecfa72f43c3fe25c912d9f67848f11e60Jay Shrauner intentUri.getScheme().equals(ContactsUtils.SCHEME_SMSTO)) || 337ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos (intent.getType() != null && intent.getType().equals(MIMETYPE_SMS))) { 338ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos usageType = DataUsageFeedback.USAGE_TYPE_SHORT_TEXT; 339ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos } 340ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos 341ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos // Data IDs start at 1 so anything less is invalid 342ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos if (dataId > 0) { 34320bdf9d2d21e1c82513f798ef4205b9d1713996dPaul Soulos final Uri dataUsageUri = DataUsageFeedback.FEEDBACK_URI.buildUpon() 344ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos .appendPath(String.valueOf(dataId)) 345ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos .appendQueryParameter(DataUsageFeedback.USAGE_TYPE, usageType) 346ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos .build(); 347ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos final boolean successful = getContentResolver().update( 34820bdf9d2d21e1c82513f798ef4205b9d1713996dPaul Soulos dataUsageUri, new ContentValues(), null, null) > 0; 349ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos if (!successful) { 350ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos Log.w(TAG, "DataUsageFeedback increment failed"); 351ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos } 352ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos } else { 353ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos Log.w(TAG, "Invalid Data ID"); 354ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos } 355ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos 35670e3f4f45c040a2d09bfb46462242b450cf20b29Nancy Chen // Pass the touch point through the intent for use in the InCallUI 35770e3f4f45c040a2d09bfb46462242b450cf20b29Nancy Chen if (Intent.ACTION_CALL.equals(intent.getAction())) { 3581f8a3fda87bf61e579d61e3fdd246548943d070aNancy Chen if (TouchPointManager.getInstance().hasValidPoint()) { 35970e3f4f45c040a2d09bfb46462242b450cf20b29Nancy Chen Bundle extras = new Bundle(); 3601f8a3fda87bf61e579d61e3fdd246548943d070aNancy Chen extras.putParcelable(TouchPointManager.TOUCH_POINT, 3611f8a3fda87bf61e579d61e3fdd246548943d070aNancy Chen TouchPointManager.getInstance().getPoint()); 3620319222b43927d4d9ce7e2a9070f3543661b5782Tyler Gunn intent.putExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, extras); 36370e3f4f45c040a2d09bfb46462242b450cf20b29Nancy Chen } 36470e3f4f45c040a2d09bfb46462242b450cf20b29Nancy Chen } 36570e3f4f45c040a2d09bfb46462242b450cf20b29Nancy Chen 366793e73c859ed839c28cc37d80d62bde0a361c78aPaul Soulos intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 367793e73c859ed839c28cc37d80d62bde0a361c78aPaul Soulos 368a42ef76251778161d27bc07db214b8c81720e476Paul Soulos mHasIntentLaunched = true; 369417309a770568d7b278abc91c46a739020e48157Jay Shrauner try { 370417309a770568d7b278abc91c46a739020e48157Jay Shrauner startActivity(intent); 371417309a770568d7b278abc91c46a739020e48157Jay Shrauner } catch (ActivityNotFoundException ex) { 372417309a770568d7b278abc91c46a739020e48157Jay Shrauner Toast.makeText(QuickContactActivity.this, R.string.missing_app, 373417309a770568d7b278abc91c46a739020e48157Jay Shrauner Toast.LENGTH_SHORT).show(); 374417309a770568d7b278abc91c46a739020e48157Jay Shrauner } 3752d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos } 3762d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos }; 3772d48b5ae6664a7ae0ed9941f55fae9dc327bd640Paul Soulos 378e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell final ExpandingEntryCardViewListener mExpandingEntryCardViewListener 379e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell = new ExpandingEntryCardViewListener() { 380e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell @Override 381e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell public void onCollapse(int heightDelta) { 382e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell mScroller.prepareForShrinkingScrollChild(heightDelta); 383e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell } 3840cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos 3850cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos @Override 3860cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos public void onExpand(int heightDelta) { 3870cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos mScroller.prepareForExpandingScrollChild(); 3880cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos } 389e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell }; 390e8ce6ee1c5ab9f4f3dd11526337c70a8867647d9Brian Attwell 39197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos private interface ContextMenuIds { 39297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos static final int COPY_TEXT = 0; 39397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos static final int CLEAR_DEFAULT = 1; 39497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos static final int SET_DEFAULT = 2; 39597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos } 39697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos 3972a4207fb39330e840436215c896cde911489e111Paul Soulos private final OnCreateContextMenuListener mEntryContextMenuListener = 3982a4207fb39330e840436215c896cde911489e111Paul Soulos new OnCreateContextMenuListener() { 3992a4207fb39330e840436215c896cde911489e111Paul Soulos @Override 4002a4207fb39330e840436215c896cde911489e111Paul Soulos public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { 4012a4207fb39330e840436215c896cde911489e111Paul Soulos if (menuInfo == null) { 4022a4207fb39330e840436215c896cde911489e111Paul Soulos return; 4032a4207fb39330e840436215c896cde911489e111Paul Soulos } 40497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos final EntryContextMenuInfo info = (EntryContextMenuInfo) menuInfo; 4052a4207fb39330e840436215c896cde911489e111Paul Soulos menu.setHeaderTitle(info.getCopyText()); 40697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos menu.add(ContextMenu.NONE, ContextMenuIds.COPY_TEXT, 40797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos ContextMenu.NONE, getString(R.string.copy_text)); 40897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos 40997f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos // Don't allow setting or clearing of defaults for non-editable contacts 41097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos if (!isContactEditable()) { 41197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos return; 41297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos } 41397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos 41497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos final String selectedMimeType = info.getMimeType(); 41597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos 41697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos // Defaults to true will only enable the detail to be copied to the clipboard. 41797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos boolean onlyOneOfMimeType = true; 41897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos 41997f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos // Only allow primary support for Phone and Email content types 42097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos if (Phone.CONTENT_ITEM_TYPE.equals(selectedMimeType)) { 42197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos onlyOneOfMimeType = mOnlyOnePhoneNumber; 42297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos } else if (Email.CONTENT_ITEM_TYPE.equals(selectedMimeType)) { 42397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos onlyOneOfMimeType = mOnlyOneEmail; 42497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos } 42597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos 42697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos // Checking for previously set default 42797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos if (info.isSuperPrimary()) { 42897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos menu.add(ContextMenu.NONE, ContextMenuIds.CLEAR_DEFAULT, 42997f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos ContextMenu.NONE, getString(R.string.clear_default)); 43097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos } else if (!onlyOneOfMimeType) { 43197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos menu.add(ContextMenu.NONE, ContextMenuIds.SET_DEFAULT, 43297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos ContextMenu.NONE, getString(R.string.set_default)); 43397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos } 4342a4207fb39330e840436215c896cde911489e111Paul Soulos } 4352a4207fb39330e840436215c896cde911489e111Paul Soulos }; 4362a4207fb39330e840436215c896cde911489e111Paul Soulos 4372a4207fb39330e840436215c896cde911489e111Paul Soulos @Override 4382a4207fb39330e840436215c896cde911489e111Paul Soulos public boolean onContextItemSelected(MenuItem item) { 4392a4207fb39330e840436215c896cde911489e111Paul Soulos EntryContextMenuInfo menuInfo; 4402a4207fb39330e840436215c896cde911489e111Paul Soulos try { 4412a4207fb39330e840436215c896cde911489e111Paul Soulos menuInfo = (EntryContextMenuInfo) item.getMenuInfo(); 4422a4207fb39330e840436215c896cde911489e111Paul Soulos } catch (ClassCastException e) { 4432a4207fb39330e840436215c896cde911489e111Paul Soulos Log.e(TAG, "bad menuInfo", e); 4442a4207fb39330e840436215c896cde911489e111Paul Soulos return false; 4452a4207fb39330e840436215c896cde911489e111Paul Soulos } 4462a4207fb39330e840436215c896cde911489e111Paul Soulos 44797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos switch (item.getItemId()) { 44897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos case ContextMenuIds.COPY_TEXT: 44997f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos ClipboardUtils.copyText(this, menuInfo.getCopyLabel(), menuInfo.getCopyText(), 45097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos true); 45197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos return true; 45297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos case ContextMenuIds.SET_DEFAULT: 45397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos final Intent setIntent = ContactSaveService.createSetSuperPrimaryIntent(this, 45497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos menuInfo.getId()); 45597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos this.startService(setIntent); 45697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos return true; 45797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos case ContextMenuIds.CLEAR_DEFAULT: 45897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos final Intent clearIntent = ContactSaveService.createClearPrimaryIntent(this, 45997f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos menuInfo.getId()); 46097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos this.startService(clearIntent); 46197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos return true; 46297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos default: 46397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos throw new IllegalArgumentException("Unknown menu option " + item.getItemId()); 46497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos } 4652a4207fb39330e840436215c896cde911489e111Paul Soulos } 4662a4207fb39330e840436215c896cde911489e111Paul Soulos 467d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell /** 468d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell * Headless fragment used to handle account selection callbacks invoked from 469d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell * {@link DirectoryContactUtil}. 470d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell */ 471d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell public static class SelectAccountDialogFragmentListener extends Fragment 472d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell implements SelectAccountDialogFragment.Listener { 473d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 474d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell private QuickContactActivity mQuickContactActivity; 475d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 476d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell public SelectAccountDialogFragmentListener() {} 477d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 478d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell @Override 479d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell public void onAccountChosen(AccountWithDataSet account, Bundle extraArgs) { 480d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell DirectoryContactUtil.createCopy(mQuickContactActivity.mContactData.getContentValues(), 481d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell account, mQuickContactActivity); 482d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 483d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 484d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell @Override 485d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell public void onAccountSelectorCancelled() {} 486d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 487d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell /** 488d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell * Set the parent activity. Since rotation can cause this fragment to be used across 489d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell * more than one activity instance, we need to explicitly set this value instead 490d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell * of making this class non-static. 491d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell */ 492d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell public void setQuickContactActivity(QuickContactActivity quickContactActivity) { 493d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mQuickContactActivity = quickContactActivity; 494d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 495d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 496d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 497b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell final MultiShrinkScrollerListener mMultiShrinkScrollerListener 498b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell = new MultiShrinkScrollerListener() { 499b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell @Override 500b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell public void onScrolledOffBottom() { 501f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell finish(); 502b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell } 5038a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 5048a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell @Override 5058a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell public void onEnterFullscreen() { 5068a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell updateStatusBarColor(); 5078a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 5088a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 5098a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell @Override 5108a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell public void onExitFullscreen() { 5118a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell updateStatusBarColor(); 5128a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 5138477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell 5148477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell @Override 5158477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell public void onStartScrollOffBottom() { 5168477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell mIsExitAnimationInProgress = true; 5178477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell } 5188477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell 5198477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell @Override 520f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell public void onEntranceAnimationDone() { 521f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell mIsEntranceAnimationFinished = true; 522f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell } 523f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell 524f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell @Override 525f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell public void onTransparentViewHeightChange(float ratio) { 526f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell if (mIsEntranceAnimationFinished) { 527f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell mWindowScrim.setAlpha((int) (0xFF * ratio)); 5288477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell } 5298477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell } 530b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell }; 531b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell 532eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 533eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos /** 534eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * Data items are compared to the same mimetype based off of three qualities: 535eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * 1. Super primary 536eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * 2. Primary 537eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * 3. Times used 538eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos */ 539eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos private final Comparator<DataItem> mWithinMimeTypeDataItemComparator = 540eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos new Comparator<DataItem>() { 541eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos @Override 542eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos public int compare(DataItem lhs, DataItem rhs) { 543eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (!lhs.getMimeType().equals(rhs.getMimeType())) { 544eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Log.wtf(TAG, "Comparing DataItems with different mimetypes lhs.getMimeType(): " + 545eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos lhs.getMimeType() + " rhs.getMimeType(): " + rhs.getMimeType()); 546eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return 0; 547eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 548eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 549eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (lhs.isSuperPrimary()) { 550eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return -1; 551eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (rhs.isSuperPrimary()) { 552eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return 1; 553eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (lhs.isPrimary() && !rhs.isPrimary()) { 554eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return -1; 555eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (!lhs.isPrimary() && rhs.isPrimary()) { 556eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return 1; 557eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else { 558eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final int lhsTimesUsed = 559eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos lhs.getTimesUsed() == null ? 0 : lhs.getTimesUsed(); 560eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final int rhsTimesUsed = 561eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos rhs.getTimesUsed() == null ? 0 : rhs.getTimesUsed(); 562eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 563eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return rhsTimesUsed - lhsTimesUsed; 564eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 565eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 566eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos }; 567eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 568cb4fcc7ef75c33411d2b900db7933c5bc4336527Paul Soulos /** 569cb4fcc7ef75c33411d2b900db7933c5bc4336527Paul Soulos * Sorts among different mimetypes based off: 570cb4fcc7ef75c33411d2b900db7933c5bc4336527Paul Soulos * 1. Times used 571cb4fcc7ef75c33411d2b900db7933c5bc4336527Paul Soulos * 2. Last time used 572cb4fcc7ef75c33411d2b900db7933c5bc4336527Paul Soulos * 3. Statically defined 573cb4fcc7ef75c33411d2b900db7933c5bc4336527Paul Soulos */ 574eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos private final Comparator<List<DataItem>> mAmongstMimeTypeDataItemComparator = 575eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos new Comparator<List<DataItem>> () { 576eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos @Override 577eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos public int compare(List<DataItem> lhsList, List<DataItem> rhsList) { 578eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos DataItem lhs = lhsList.get(0); 579eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos DataItem rhs = rhsList.get(0); 580eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final int lhsTimesUsed = lhs.getTimesUsed() == null ? 0 : lhs.getTimesUsed(); 581eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final int rhsTimesUsed = rhs.getTimesUsed() == null ? 0 : rhs.getTimesUsed(); 582eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final int timesUsedDifference = rhsTimesUsed - lhsTimesUsed; 583eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (timesUsedDifference != 0) { 584eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return timesUsedDifference; 585eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 586eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 587eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final long lhsLastTimeUsed = 588eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos lhs.getLastTimeUsed() == null ? 0 : lhs.getLastTimeUsed(); 589eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final long rhsLastTimeUsed = 590eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos rhs.getLastTimeUsed() == null ? 0 : rhs.getLastTimeUsed(); 591eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final long lastTimeUsedDifference = rhsLastTimeUsed - lhsLastTimeUsed; 592eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (lastTimeUsedDifference > 0) { 593eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return 1; 594eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (lastTimeUsedDifference < 0) { 595eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return -1; 596eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 597eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 598eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos // Times used and last time used are the same. Resort to statically defined. 599eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final String lhsMimeType = lhs.getMimeType(); 600eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final String rhsMimeType = rhs.getMimeType(); 601eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos for (String mimeType : LEADING_MIMETYPES) { 602eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (lhsMimeType.equals(mimeType)) { 603eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return -1; 604eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (rhsMimeType.equals(mimeType)) { 605eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return 1; 606eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 607eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 608eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return 0; 609eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 610eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos }; 611eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 612edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann @Override 613f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chen public boolean dispatchTouchEvent(MotionEvent ev) { 614f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chen if (ev.getAction() == MotionEvent.ACTION_DOWN) { 615f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chen TouchPointManager.getInstance().setPoint((int) ev.getRawX(), (int) ev.getRawY()); 616f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chen } 617f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chen return super.dispatchTouchEvent(ev); 618f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chen } 619f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chen 620f619e432bcebb7f91c9ed88fc384abab16a9cd6aNancy Chen @Override 6218a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell protected void onCreate(Bundle savedInstanceState) { 6228a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.beginSection("onCreate()"); 6238a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell super.onCreate(savedInstanceState); 624edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 6258a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell getWindow().setStatusBarColor(Color.TRANSPARENT); 6262426cb015ba4cb679a525bd1ffe223527375468cDaniel Lehmann 627d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell processIntent(getIntent()); 628dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 62910d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawa // Show QuickContact in front of soft input 63010d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawa getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM, 63110d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawa WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); 63210d7df7bab8c332744fad64b9167c2ef061070e4Daisuke Miyakawa 633edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann setContentView(R.layout.quickcontact_activity); 634edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 635a3859ed9ff9f315d492e199620a08ae35ab8569fBrian Attwell mMaterialColorMapUtils = new MaterialColorMapUtils(getResources()); 636a3859ed9ff9f315d492e199620a08ae35ab8569fBrian Attwell 6370cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos mScroller = (MultiShrinkScroller) findViewById(R.id.multiscroller); 6380cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos 639eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos mContactCard = (ExpandingEntryCardView) findViewById(R.id.communication_card); 6406095369885edcca566a812b551886e29c7ff8039Brian Attwell mNoContactDetailsCard = (ExpandingEntryCardView) findViewById(R.id.no_contact_data_card); 641b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos mRecentCard = (ExpandingEntryCardView) findViewById(R.id.recent_card); 642eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos mAboutCard = (ExpandingEntryCardView) findViewById(R.id.about_card); 643edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 6446095369885edcca566a812b551886e29c7ff8039Brian Attwell mNoContactDetailsCard.setOnClickListener(mEntryClickHandler); 645eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos mContactCard.setOnClickListener(mEntryClickHandler); 646eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos mContactCard.setExpandButtonText( 64723889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos getResources().getString(R.string.expanding_entry_card_view_see_all)); 6482a4207fb39330e840436215c896cde911489e111Paul Soulos mContactCard.setOnCreateContextMenuListener(mEntryContextMenuListener); 649b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 650b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos mRecentCard.setOnClickListener(mEntryClickHandler); 651b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos mRecentCard.setTitle(getResources().getString(R.string.recent_card_title)); 652edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 653eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos mAboutCard.setOnClickListener(mEntryClickHandler); 6542a4207fb39330e840436215c896cde911489e111Paul Soulos mAboutCard.setOnCreateContextMenuListener(mEntryContextMenuListener); 655eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 65602eaf11669d25fd885606b3b0700358323532cddBrian Attwell mPhotoView = (QuickContactImageView) findViewById(R.id.photo); 65763176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell final View transparentView = findViewById(R.id.transparent_view); 6580d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell if (mScroller != null) { 65963176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell transparentView.setOnClickListener(new OnClickListener() { 6600d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell @Override 6610d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell public void onClick(View v) { 6620d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell mScroller.scrollOffBottom(); 6630d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell } 6640d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell }); 6650d90afea92dc37245d5c2cad4d6b8040f2faed5cBrian Attwell } 666edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 667d41ab8ace81a2e44f8b28aa8782679b9e9cca1b9Brian Attwell // Allow a shadow to be shown under the toolbar. 668d41ab8ace81a2e44f8b28aa8782679b9e9cca1b9Brian Attwell ViewUtil.addRectangularOutlineProvider(findViewById(R.id.toolbar_parent), getResources()); 669d41ab8ace81a2e44f8b28aa8782679b9e9cca1b9Brian Attwell 670d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 671d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell setActionBar(toolbar); 6729b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell getActionBar().setTitle(null); 6739b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell // Put a TextView with a known resource id into the ActionBar. This allows us to easily 6749b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell // find the correct TextView location & size later. 6759b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell toolbar.addView(getLayoutInflater().inflate(R.layout.quickcontact_title_placeholder, null)); 6766219668d0612f7522bd15a9d34c6232cb15b9a6cYorke Lee 6778a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell mHasAlreadyBeenOpened = savedInstanceState != null; 678f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell mIsEntranceAnimationFinished = mHasAlreadyBeenOpened; 6799b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell mWindowScrim = new ColorDrawable(SCRIM_COLOR); 680f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell mWindowScrim.setAlpha(0); 6819b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell getWindow().setBackgroundDrawable(mWindowScrim); 682edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 683c33ae17c9816b770041ee1f9ccde10e7c7eee491Brian Attwell mScroller.initialize(mMultiShrinkScrollerListener, mExtraMode == MODE_FULLY_EXPANDED); 684ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell // mScroller needs to perform asynchronous measurements after initalize(), therefore 685ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell // we can't mark this as GONE. 686ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell mScroller.setVisibility(View.INVISIBLE); 6878a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 6889b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell setHeaderNameText(R.string.missing_name); 6899b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell 690d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mSelectAccountFragmentListener= (SelectAccountDialogFragmentListener) getFragmentManager() 691d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell .findFragmentByTag(FRAGMENT_TAG_SELECT_ACCOUNT); 692d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell if (mSelectAccountFragmentListener == null) { 693d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mSelectAccountFragmentListener = new SelectAccountDialogFragmentListener(); 694d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell getFragmentManager().beginTransaction().add(0, mSelectAccountFragmentListener, 695d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell FRAGMENT_TAG_SELECT_ACCOUNT).commit(); 696d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mSelectAccountFragmentListener.setRetainInstance(true); 697d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 698d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mSelectAccountFragmentListener.setQuickContactActivity(this); 69923889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos 700f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell SchedulingUtils.doOnPreDraw(mScroller, /* drawNextFrame = */ true, 701f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell new Runnable() { 702f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell @Override 703f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell public void run() { 704f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell if (!mHasAlreadyBeenOpened) { 705f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell // The initial scrim opacity must match the scrim opacity that would be 706f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell // achieved by scrolling to the starting position. 707f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell final float alphaRatio = mExtraMode == MODE_FULLY_EXPANDED ? 708f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell 1 : mScroller.getStartingTransparentHeightRatio(); 709f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell final int duration = getResources().getInteger( 710f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell android.R.integer.config_shortAnimTime); 711f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell final int desiredAlpha = (int) (0xFF * alphaRatio); 712f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell ObjectAnimator o = ObjectAnimator.ofInt(mWindowScrim, "alpha", 0, 713f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell desiredAlpha).setDuration(duration); 714f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell 715f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell o.start(); 716f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell } 717f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell } 718f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell }); 719f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell 7209b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell if (savedInstanceState != null) { 7219b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell final int color = savedInstanceState.getInt(KEY_THEME_COLOR, 0); 722ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell SchedulingUtils.doOnPreDraw(mScroller, /* drawNextFrame = */ false, 723ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell new Runnable() { 724ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell @Override 725ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell public void run() { 726ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell // Need to wait for the pre draw before setting the initial scroll 727ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell // value. Prior to pre draw all scroll values are invalid. 728ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell if (mHasAlreadyBeenOpened) { 729ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell mScroller.setVisibility(View.VISIBLE); 730ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell mScroller.setScroll(mScroller.getScrollNeededToBeFullScreen()); 731ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell } 732ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell // Need to wait for pre draw for setting the theme color. Setting the 733ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell // header tint before the MultiShrinkScroller has been measured will 734ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell // cause incorrect tinting calculations. 735ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell if (color != 0) { 736a3859ed9ff9f315d492e199620a08ae35ab8569fBrian Attwell setThemeColor(mMaterialColorMapUtils 737a3859ed9ff9f315d492e199620a08ae35ab8569fBrian Attwell .calculatePrimaryAndSecondaryColor(color)); 7389b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell } 739ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell } 740ac3ed8e48cc474448aa5a7cfed5d6b95073b84f9Brian Attwell }); 7419b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell } 7429b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell 7438a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.endSection(); 7448a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 7458a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 746405ae406379ad9c47770783afc76a660f6c55fcaPaul Soulos @Override 747405ae406379ad9c47770783afc76a660f6c55fcaPaul Soulos protected void onActivityResult(int requestCode, int resultCode, Intent data) { 7488a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (requestCode == REQUEST_CODE_CONTACT_EDITOR_ACTIVITY && 7498a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell resultCode == ContactDeletionInteraction.RESULT_CODE_DELETED) { 7508a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // The contact that we were showing has been deleted. 7518a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell finish(); 752ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos } else if (requestCode == REQUEST_CODE_CONTACT_SELECTION_ACTIVITY && 753ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos resultCode != RESULT_CANCELED) { 754ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos processIntent(data); 755b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell } 7568a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 757dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 7588a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell @Override 7598a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell protected void onNewIntent(Intent intent) { 7608a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell super.onNewIntent(intent); 7618a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell mHasAlreadyBeenOpened = true; 762f1076dc20feb3ee0c687c818d70ffc1d25bef909Brian Attwell mIsEntranceAnimationFinished = true; 7638571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell mHasComputedThemeColor = false; 764d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell processIntent(intent); 765d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 766d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 7679b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell @Override 7689b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell public void onSaveInstanceState(Bundle savedInstanceState) { 7699b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell super.onSaveInstanceState(savedInstanceState); 7709b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell if (mColorFilter != null) { 7719b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell savedInstanceState.putInt(KEY_THEME_COLOR, mColorFilter.getColor()); 7729b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell } 7739b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell } 7749b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell 775d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell private void processIntent(Intent intent) { 776f19dda97bfdef84e3f39ba069a981004a5c797b1Paul Soulos if (intent == null) { 777f19dda97bfdef84e3f39ba069a981004a5c797b1Paul Soulos finish(); 778f19dda97bfdef84e3f39ba069a981004a5c797b1Paul Soulos return; 779f19dda97bfdef84e3f39ba069a981004a5c797b1Paul Soulos } 780d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell Uri lookupUri = intent.getData(); 781d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 782d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // Check to see whether it comes from the old version. 783d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell if (lookupUri != null && LEGACY_AUTHORITY.equals(lookupUri.getAuthority())) { 784d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell final long rawContactId = ContentUris.parseId(lookupUri); 785d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell lookupUri = RawContacts.getContactLookupUri(getContentResolver(), 786d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId)); 787d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 788d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mExtraMode = getIntent().getIntExtra(QuickContact.EXTRA_MODE, 789d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell QuickContact.MODE_LARGE); 790d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell final Uri oldLookupUri = mLookupUri; 791d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 792d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mLookupUri = Preconditions.checkNotNull(lookupUri, "missing lookupUri"); 793d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mExcludeMimes = intent.getStringArrayExtra(QuickContact.EXTRA_EXCLUDE_MIMES); 794d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell if (oldLookupUri == null) { 795d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mContactLoader = (ContactLoader) getLoaderManager().initLoader( 796d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell LOADER_CONTACT_ID, null, mLoaderContactCallbacks); 797d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } else if (oldLookupUri != mLookupUri) { 798d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // After copying a directory contact, the contact URI changes. Therefore, 799d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // we need to restart the loader and reload the new contact. 80059a585b78d061c84367ec24c71e137fae55d10ceBrian Attwell destroyInteractionLoaders(); 801405ae406379ad9c47770783afc76a660f6c55fcaPaul Soulos mContactLoader = (ContactLoader) getLoaderManager().restartLoader( 802405ae406379ad9c47770783afc76a660f6c55fcaPaul Soulos LOADER_CONTACT_ID, null, mLoaderContactCallbacks); 80359a585b78d061c84367ec24c71e137fae55d10ceBrian Attwell mCachedCp2DataCardModel = null; 804d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 8052d150da246632b1649999cfabed776133b097775Brian Attwell 8062d150da246632b1649999cfabed776133b097775Brian Attwell NfcHandler.register(this, mLookupUri); 8072426cb015ba4cb679a525bd1ffe223527375468cDaniel Lehmann } 808edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 80959a585b78d061c84367ec24c71e137fae55d10ceBrian Attwell private void destroyInteractionLoaders() { 81059a585b78d061c84367ec24c71e137fae55d10ceBrian Attwell for (int interactionLoaderId : mRecentLoaderIds) { 81159a585b78d061c84367ec24c71e137fae55d10ceBrian Attwell getLoaderManager().destroyLoader(interactionLoaderId); 81259a585b78d061c84367ec24c71e137fae55d10ceBrian Attwell } 81359a585b78d061c84367ec24c71e137fae55d10ceBrian Attwell } 81459a585b78d061c84367ec24c71e137fae55d10ceBrian Attwell 815b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell private void runEntranceAnimation() { 8168a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (mHasAlreadyBeenOpened) { 8178a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell return; 8188a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 8198a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell mHasAlreadyBeenOpened = true; 820c33ae17c9816b770041ee1f9ccde10e7c7eee491Brian Attwell mScroller.scrollUpForEntranceAnimation(mExtraMode != MODE_FULLY_EXPANDED); 821b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell } 822b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell 82381281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan /** Assign this string to the view if it is not empty. */ 824d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell private void setHeaderNameText(int resId) { 8259b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell if (mScroller != null) { 826f43f573340fd9de5d30b43d7c96cac1ec9021e58Brian Attwell mScroller.setTitle(getText(resId) == null ? null : getText(resId).toString()); 8279b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell } 82881281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan } 82981281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan 83081281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan /** Assign this string to the view if it is not empty. */ 831f43f573340fd9de5d30b43d7c96cac1ec9021e58Brian Attwell private void setHeaderNameText(String value) { 832d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell if (!TextUtils.isEmpty(value)) { 8339b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell if (mScroller != null) { 834f43f573340fd9de5d30b43d7c96cac1ec9021e58Brian Attwell mScroller.setTitle(value); 8359b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell } 83681281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan } 83781281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan } 83881281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan 83981281eefd5aaf339cbfa080ddfa6c6f63caca71aKatherine Kuan /** 840edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * Check if the given MIME-type appears in the list of excluded MIME-types 841edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann * that the most-recent caller requested. 842edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann */ 843edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann private boolean isMimeExcluded(String mimeType) { 844edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann if (mExcludeMimes == null) return false; 845edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann for (String excludedMime : mExcludeMimes) { 846edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann if (TextUtils.equals(excludedMime, mimeType)) { 847edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann return true; 848edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 849edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 850edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann return false; 851edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 852edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 853edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann /** 854cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann * Handle the result from the ContactLoader 855edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann */ 8568a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private void bindContactData(final Contact data) { 8578a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.beginSection("bindContactData"); 8586cb6f6f8304d4b42fc9db4bbb0cc4058ab53afe3Yorke Lee mContactData = data; 859d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell invalidateOptionsMenu(); 860edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 8618a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.endSection(); 8628a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.beginSection("Set display photo & name"); 863dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 86402eaf11669d25fd885606b3b0700358323532cddBrian Attwell mPhotoView.setIsBusiness(mContactData.isDisplayNameFromOrganization()); 8656219668d0612f7522bd15a9d34c6232cb15b9a6cYorke Lee mPhotoSetter.setupContactPhoto(data, mPhotoView); 86631b2d42fb0889e61515d27314aa5a245147100daBrian Attwell extractAndApplyTintFromPhotoViewAsynchronously(); 8674936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell analyzeWhitenessOfPhotoAsynchronously(); 868333091ae754ddfc25714c14b9b89534be24379f9Paul Soulos setHeaderNameText(ContactDisplayUtils.getDisplayName(this, data).toString()); 869edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 8708a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.endSection(); 871dfe8cc82e8aa31929bb85eb68b7de3492b875d57Makoto Onuki 8726bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell mEntriesAndActionsTask = new AsyncTask<Void, Void, Cp2DataCardModel>() { 8738a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 8748a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell @Override 8756bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell protected Cp2DataCardModel doInBackground( 876eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Void... params) { 877eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return generateDataModelFromContact(data); 8788a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 8798a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 8808a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell @Override 8816bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell protected void onPostExecute(Cp2DataCardModel cardDataModel) { 8826bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell super.onPostExecute(cardDataModel); 8838a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // Check that original AsyncTask parameters are still valid and the activity 8848a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // is still running before binding to UI. A new intent could invalidate 8858a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // the results, for example. 8868a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (data == mContactData && !isCancelled()) { 8876bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell bindDataToCards(cardDataModel); 8888a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell showActivity(); 8898a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 8908a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 8918a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell }; 8928a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell mEntriesAndActionsTask.execute(); 8938a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 8948a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 8956bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private void bindDataToCards(Cp2DataCardModel cp2DataCardModel) { 8966bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell startInteractionLoaders(cp2DataCardModel); 8976bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell populateContactAndAboutCard(cp2DataCardModel); 898eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 899eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 9006bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private void startInteractionLoaders(Cp2DataCardModel cp2DataCardModel) { 9016bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final Map<String, List<DataItem>> dataItemsMap = cp2DataCardModel.dataItemsMap; 9026bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final List<DataItem> phoneDataItems = dataItemsMap.get(Phone.CONTENT_ITEM_TYPE); 90397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos if (phoneDataItems != null && phoneDataItems.size() == 1) { 90497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos mOnlyOnePhoneNumber = true; 90597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos } 906eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos String[] phoneNumbers = null; 907eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (phoneDataItems != null) { 908eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos phoneNumbers = new String[phoneDataItems.size()]; 909eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos for (int i = 0; i < phoneDataItems.size(); ++i) { 910eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos phoneNumbers[i] = ((PhoneDataItem) phoneDataItems.get(i)).getNumber(); 911eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 912eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 913ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos final Bundle phonesExtraBundle = new Bundle(); 914eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos phonesExtraBundle.putStringArray(KEY_LOADER_EXTRA_PHONES, phoneNumbers); 915eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 916eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Trace.beginSection("start sms loader"); 9178a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell getLoaderManager().initLoader( 9188a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell LOADER_SMS_ID, 919ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos phonesExtraBundle, 920ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos mLoaderInteractionsCallbacks); 921ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos Trace.endSection(); 922ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 923ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos Trace.beginSection("start call log loader"); 924ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos getLoaderManager().initLoader( 925ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos LOADER_CALL_LOG_ID, 926ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos phonesExtraBundle, 9278a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell mLoaderInteractionsCallbacks); 928899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos Trace.endSection(); 9298a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 930eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 931899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos Trace.beginSection("start calendar loader"); 9326bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final List<DataItem> emailDataItems = dataItemsMap.get(Email.CONTENT_ITEM_TYPE); 93397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos if (emailDataItems != null && emailDataItems.size() == 1) { 93497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos mOnlyOneEmail = true; 93597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos } 936eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos String[] emailAddresses = null; 937eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (emailDataItems != null) { 938eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos emailAddresses = new String[emailDataItems.size()]; 939eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos for (int i = 0; i < emailDataItems.size(); ++i) { 940eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos emailAddresses[i] = ((EmailDataItem) emailDataItems.get(i)).getAddress(); 941eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 942eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 943ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos final Bundle emailsExtraBundle = new Bundle(); 944eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos emailsExtraBundle.putStringArray(KEY_LOADER_EXTRA_EMAILS, emailAddresses); 945899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos getLoaderManager().initLoader( 946899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos LOADER_CALENDAR_ID, 947ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos emailsExtraBundle, 948899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos mLoaderInteractionsCallbacks); 9498a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.endSection(); 9508a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 9518a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 9528a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private void showActivity() { 9538a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (mScroller != null) { 9548a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell mScroller.setVisibility(View.VISIBLE); 9558a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell SchedulingUtils.doOnPreDraw(mScroller, /* drawNextFrame = */ false, 9568a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell new Runnable() { 9578a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell @Override 9588a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell public void run() { 9598a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell runEntranceAnimation(); 9608a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 9618a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell }); 9628a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 9638a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 9648a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 9656bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private List<List<Entry>> buildAboutCardEntries(Map<String, List<DataItem>> dataItemsMap) { 966a153dba33c2152332c5706178a367f52b0550723Paul Soulos final List<List<Entry>> aboutCardEntries = new ArrayList<>(); 967a153dba33c2152332c5706178a367f52b0550723Paul Soulos for (String mimetype : SORTED_ABOUT_CARD_MIMETYPES) { 9686bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final List<DataItem> mimeTypeItems = dataItemsMap.get(mimetype); 969a153dba33c2152332c5706178a367f52b0550723Paul Soulos if (mimeTypeItems == null) { 970a153dba33c2152332c5706178a367f52b0550723Paul Soulos continue; 971a153dba33c2152332c5706178a367f52b0550723Paul Soulos } 9726bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell // Set aboutCardTitleOut = null, since SORTED_ABOUT_CARD_MIMETYPES doesn't contain 9736bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell // the name mimetype. 9746bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final List<Entry> aboutEntries = dataItemsToEntries(mimeTypeItems, 9756bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell /* aboutCardTitleOut = */ null); 976a153dba33c2152332c5706178a367f52b0550723Paul Soulos if (aboutEntries.size() > 0) { 977a153dba33c2152332c5706178a367f52b0550723Paul Soulos aboutCardEntries.add(aboutEntries); 978a153dba33c2152332c5706178a367f52b0550723Paul Soulos } 979a153dba33c2152332c5706178a367f52b0550723Paul Soulos } 980a153dba33c2152332c5706178a367f52b0550723Paul Soulos return aboutCardEntries; 981a153dba33c2152332c5706178a367f52b0550723Paul Soulos } 982a153dba33c2152332c5706178a367f52b0550723Paul Soulos 983a42ef76251778161d27bc07db214b8c81720e476Paul Soulos @Override 984a42ef76251778161d27bc07db214b8c81720e476Paul Soulos protected void onResume() { 985a42ef76251778161d27bc07db214b8c81720e476Paul Soulos super.onResume(); 986a42ef76251778161d27bc07db214b8c81720e476Paul Soulos // If returning from a launched activity, repopulate the contact and about card 987a42ef76251778161d27bc07db214b8c81720e476Paul Soulos if (mHasIntentLaunched) { 988a42ef76251778161d27bc07db214b8c81720e476Paul Soulos mHasIntentLaunched = false; 9896bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell populateContactAndAboutCard(mCachedCp2DataCardModel); 990a42ef76251778161d27bc07db214b8c81720e476Paul Soulos } 99159a585b78d061c84367ec24c71e137fae55d10ceBrian Attwell 99259a585b78d061c84367ec24c71e137fae55d10ceBrian Attwell // When exiting the activity and resuming, we want to force a full reload of all the 99359a585b78d061c84367ec24c71e137fae55d10ceBrian Attwell // interaction data in case something changed in the background. On screen rotation, 99459a585b78d061c84367ec24c71e137fae55d10ceBrian Attwell // we don't need to do this. And, mCachedCp2DataCardModel will be null, so we won't. 99559a585b78d061c84367ec24c71e137fae55d10ceBrian Attwell if (mCachedCp2DataCardModel != null) { 99659a585b78d061c84367ec24c71e137fae55d10ceBrian Attwell destroyInteractionLoaders(); 99759a585b78d061c84367ec24c71e137fae55d10ceBrian Attwell startInteractionLoaders(mCachedCp2DataCardModel); 99859a585b78d061c84367ec24c71e137fae55d10ceBrian Attwell } 999a42ef76251778161d27bc07db214b8c81720e476Paul Soulos } 1000a42ef76251778161d27bc07db214b8c81720e476Paul Soulos 10016bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private void populateContactAndAboutCard(Cp2DataCardModel cp2DataCardModel) { 10026bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell mCachedCp2DataCardModel = cp2DataCardModel; 10036bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell if (mHasIntentLaunched || cp2DataCardModel == null) { 1004a42ef76251778161d27bc07db214b8c81720e476Paul Soulos return; 1005a42ef76251778161d27bc07db214b8c81720e476Paul Soulos } 1006eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Trace.beginSection("bind contact card"); 1007eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 10086bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final List<List<Entry>> contactCardEntries = cp2DataCardModel.contactCardEntries; 10096bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final List<List<Entry>> aboutCardEntries = cp2DataCardModel.aboutCardEntries; 10106bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final String customAboutCardName = cp2DataCardModel.customAboutCardName; 1011eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 1012eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (contactCardEntries.size() > 0) { 1013eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos mContactCard.initialize(contactCardEntries, 1014eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos /* numInitialVisibleEntries = */ MIN_NUM_CONTACT_ENTRIES_SHOWN, 1015c8e2a91807b581194566eb45019fa16e2268b462Paul Soulos /* isExpanded = */ mContactCard.isExpanded(), 101689966b4ed8cc9d385e5ac6b4a7e9e08ada387eb0Paul Soulos /* isAlwaysExpanded = */ false, 10170cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos mExpandingEntryCardViewListener, 10180cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos mScroller); 1019eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos mContactCard.setVisibility(View.VISIBLE); 1020eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else { 1021eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos mContactCard.setVisibility(View.GONE); 1022eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1023eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Trace.endSection(); 10248a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 1025eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Trace.beginSection("bind about card"); 1026c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos // Phonetic name is not a data item, so the entry needs to be created separately 1027c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos final String phoneticName = mContactData.getPhoneticName(); 1028c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos if (!TextUtils.isEmpty(phoneticName)) { 1029c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos Entry phoneticEntry = new Entry(/* viewId = */ -1, 1030c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos /* icon = */ null, 1031c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos getResources().getString(R.string.name_phonetic), 1032c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos phoneticName, 10338a3fe52802135be2402a5b216325615fb796a509Walter Jang /* subHeaderIcon = */ null, 1034c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos /* text = */ null, 10358a3fe52802135be2402a5b216325615fb796a509Walter Jang /* textIcon = */ null, 103623e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos /* primaryContentDescription = */ null, 1037c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos /* intent = */ null, 1038c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos /* alternateIcon = */ null, 1039c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos /* alternateIntent = */ null, 1040c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos /* alternateContentDescription = */ null, 1041c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos /* shouldApplyColor = */ false, 10422a4207fb39330e840436215c896cde911489e111Paul Soulos /* isEditable = */ false, 10432a4207fb39330e840436215c896cde911489e111Paul Soulos /* EntryContextMenuInfo = */ new EntryContextMenuInfo(phoneticName, 104497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos getResources().getString(R.string.name_phonetic), 104597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos /* mimeType = */ null, /* id = */ -1, /* isPrimary = */ false), 104648fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos /* thirdIcon = */ null, 104748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos /* thirdIntent = */ null, 104848290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos /* thirdContentDescription = */ null, 104948290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos /* iconResourceId = */ 0); 1050c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos List<Entry> phoneticList = new ArrayList<>(); 1051c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos phoneticList.add(phoneticEntry); 1052a153dba33c2152332c5706178a367f52b0550723Paul Soulos // Phonetic name comes after nickname. Check to see if the first entry type is nickname 1053a0fa4c18dc111ceea9ff47f35ee01fecc1003578Paul Soulos if (aboutCardEntries.size() > 0 && aboutCardEntries.get(0).get(0).getHeader().equals( 1054a153dba33c2152332c5706178a367f52b0550723Paul Soulos getResources().getString(R.string.header_nickname_entry))) { 1055a153dba33c2152332c5706178a367f52b0550723Paul Soulos aboutCardEntries.add(1, phoneticList); 1056a153dba33c2152332c5706178a367f52b0550723Paul Soulos } else { 1057a153dba33c2152332c5706178a367f52b0550723Paul Soulos aboutCardEntries.add(0, phoneticList); 1058a153dba33c2152332c5706178a367f52b0550723Paul Soulos } 1059c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos } 1060c6e110946e2c51be6276591b85ac8abe169534a0Paul Soulos 10616bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell if (!TextUtils.isEmpty(customAboutCardName)) { 10626bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell mAboutCard.setTitle(customAboutCardName); 10636bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell } 10646bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell 1065cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos if (aboutCardEntries.size() > 0) { 1066cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos mAboutCard.initialize(aboutCardEntries, 1067cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos /* numInitialVisibleEntries = */ 1, 1068cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos /* isExpanded = */ true, 1069cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos /* isAlwaysExpanded = */ true, 1070cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos mExpandingEntryCardViewListener, 1071cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos mScroller); 1072cc5ec22992ee61d130cb2ee99a038fb1761b8d35Paul Soulos } 10736095369885edcca566a812b551886e29c7ff8039Brian Attwell 10746095369885edcca566a812b551886e29c7ff8039Brian Attwell if (contactCardEntries.size() == 0 && aboutCardEntries.size() == 0) { 10756095369885edcca566a812b551886e29c7ff8039Brian Attwell initializeNoContactDetailCard(); 10766095369885edcca566a812b551886e29c7ff8039Brian Attwell } else { 10776095369885edcca566a812b551886e29c7ff8039Brian Attwell mNoContactDetailsCard.setVisibility(View.GONE); 10786095369885edcca566a812b551886e29c7ff8039Brian Attwell } 10796095369885edcca566a812b551886e29c7ff8039Brian Attwell 1080a8fce966f48d84af82f5ad767aa7986740ca7b26Paul Soulos // If the Recent card is already initialized (all recent data is loaded), show the About 1081a8fce966f48d84af82f5ad767aa7986740ca7b26Paul Soulos // card if it has entries. Otherwise About card visibility will be set in bindRecentData() 1082a8fce966f48d84af82f5ad767aa7986740ca7b26Paul Soulos if (isAllRecentDataLoaded() && aboutCardEntries.size() > 0) { 1083a8fce966f48d84af82f5ad767aa7986740ca7b26Paul Soulos mAboutCard.setVisibility(View.VISIBLE); 1084a8fce966f48d84af82f5ad767aa7986740ca7b26Paul Soulos } 1085eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Trace.endSection(); 1086eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1087eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 1088eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos /** 10896095369885edcca566a812b551886e29c7ff8039Brian Attwell * Create a card that shows "Add email" and "Add phone number" entries in grey. 10906095369885edcca566a812b551886e29c7ff8039Brian Attwell */ 10916095369885edcca566a812b551886e29c7ff8039Brian Attwell private void initializeNoContactDetailCard() { 10926095369885edcca566a812b551886e29c7ff8039Brian Attwell final Drawable phoneIcon = getResources().getDrawable( 10936095369885edcca566a812b551886e29c7ff8039Brian Attwell R.drawable.ic_phone_24dp).mutate(); 10946095369885edcca566a812b551886e29c7ff8039Brian Attwell final Entry phonePromptEntry = new Entry(CARD_ENTRY_ID_EDIT_CONTACT, 10956095369885edcca566a812b551886e29c7ff8039Brian Attwell phoneIcon, getString(R.string.quickcontact_add_phone_number), 10968a3fe52802135be2402a5b216325615fb796a509Walter Jang /* subHeader = */ null, /* subHeaderIcon = */ null, /* text = */ null, 10978a3fe52802135be2402a5b216325615fb796a509Walter Jang /* textIcon = */ null, /* primaryContentDescription = */ null, 109823e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos getEditContactIntent(), 1099dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos /* alternateIcon = */ null, /* alternateIntent = */ null, 1100714455bba22b99d168a2e864dfbc74a6e30dfdb6Paul Soulos /* alternateContentDescription = */ null, /* shouldApplyColor = */ true, 110148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos /* isEditable = */ false, /* EntryContextMenuInfo = */ null, 110248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos /* thirdIcon = */ null, /* thirdIntent = */ null, 110348290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos /* thirdContentDescription = */ null, R.drawable.ic_phone_24dp); 11046095369885edcca566a812b551886e29c7ff8039Brian Attwell 11056095369885edcca566a812b551886e29c7ff8039Brian Attwell final Drawable emailIcon = getResources().getDrawable( 11066095369885edcca566a812b551886e29c7ff8039Brian Attwell R.drawable.ic_email_24dp).mutate(); 11076095369885edcca566a812b551886e29c7ff8039Brian Attwell final Entry emailPromptEntry = new Entry(CARD_ENTRY_ID_EDIT_CONTACT, 11086095369885edcca566a812b551886e29c7ff8039Brian Attwell emailIcon, getString(R.string.quickcontact_add_email), /* subHeader = */ null, 11098a3fe52802135be2402a5b216325615fb796a509Walter Jang /* subHeaderIcon = */ null, 11108a3fe52802135be2402a5b216325615fb796a509Walter Jang /* text = */ null, /* textIcon = */ null, /* primaryContentDescription = */ null, 111123e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos getEditContactIntent(), /* alternateIcon = */ null, 1112dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos /* alternateIntent = */ null, /* alternateContentDescription = */ null, 11132a4207fb39330e840436215c896cde911489e111Paul Soulos /* shouldApplyColor = */ true, /* isEditable = */ false, 111448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos /* EntryContextMenuInfo = */ null, /* thirdIcon = */ null, 111548290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos /* thirdIntent = */ null, /* thirdContentDescription = */ null, 111648290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos R.drawable.ic_email_24dp); 11176095369885edcca566a812b551886e29c7ff8039Brian Attwell 11186095369885edcca566a812b551886e29c7ff8039Brian Attwell final List<List<Entry>> promptEntries = new ArrayList<>(); 11196095369885edcca566a812b551886e29c7ff8039Brian Attwell promptEntries.add(new ArrayList<Entry>(1)); 11206095369885edcca566a812b551886e29c7ff8039Brian Attwell promptEntries.add(new ArrayList<Entry>(1)); 11216095369885edcca566a812b551886e29c7ff8039Brian Attwell promptEntries.get(0).add(phonePromptEntry); 11226095369885edcca566a812b551886e29c7ff8039Brian Attwell promptEntries.get(1).add(emailPromptEntry); 11236095369885edcca566a812b551886e29c7ff8039Brian Attwell 11246095369885edcca566a812b551886e29c7ff8039Brian Attwell final int subHeaderTextColor = getResources().getColor( 11256095369885edcca566a812b551886e29c7ff8039Brian Attwell R.color.quickcontact_entry_sub_header_text_color); 11266095369885edcca566a812b551886e29c7ff8039Brian Attwell final PorterDuffColorFilter greyColorFilter = 11276095369885edcca566a812b551886e29c7ff8039Brian Attwell new PorterDuffColorFilter(subHeaderTextColor, PorterDuff.Mode.SRC_ATOP); 1128c8e2a91807b581194566eb45019fa16e2268b462Paul Soulos mNoContactDetailsCard.initialize(promptEntries, 2, /* isExpanded = */ true, 11290cda9aeb01f1922fce2a9e87ae4c0146c177b4f0Paul Soulos /* isAlwaysExpanded = */ true, mExpandingEntryCardViewListener, mScroller); 11306095369885edcca566a812b551886e29c7ff8039Brian Attwell mNoContactDetailsCard.setVisibility(View.VISIBLE); 11316095369885edcca566a812b551886e29c7ff8039Brian Attwell mNoContactDetailsCard.setEntryHeaderColor(subHeaderTextColor); 11326095369885edcca566a812b551886e29c7ff8039Brian Attwell mNoContactDetailsCard.setColorAndFilter(subHeaderTextColor, greyColorFilter); 11336095369885edcca566a812b551886e29c7ff8039Brian Attwell } 11346095369885edcca566a812b551886e29c7ff8039Brian Attwell 11356095369885edcca566a812b551886e29c7ff8039Brian Attwell /** 1136eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * Builds the {@link DataItem}s Map out of the Contact. 1137eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * @param data The contact to build the data from. 1138eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * @return A pair containing a list of data items sorted within mimetype and sorted 1139eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * amongst mimetype. The map goes from mimetype string to the sorted list of data items within 1140eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * mimetype 1141eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos */ 11426bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private Cp2DataCardModel generateDataModelFromContact( 1143eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Contact data) { 1144eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Trace.beginSection("Build data items map"); 1145eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 1146eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final Map<String, List<DataItem>> dataItemsMap = new HashMap<>(); 11478bf96e78497ea9c8c893bcb357fc1e3175fb2e9bBrian Attwell 11488a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell final ResolveCache cache = ResolveCache.getInstance(this); 1149851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu for (RawContact rawContact : data.getRawContacts()) { 1150851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu for (DataItem dataItem : rawContact.getDataItems()) { 1151eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos dataItem.setRawContactId(rawContact.getId()); 1152eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 1153851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu final String mimeType = dataItem.getMimeType(); 1154eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (mimeType == null) continue; 1155eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 115647b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng final AccountType accountType = rawContact.getAccountType(this); 115747b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng final DataKind dataKind = AccountTypeManager.getInstance(this) 115847b6f70eadb118d815b4aaf5426c070bd75a38fbChiao Cheng .getKindOrFallback(accountType, mimeType); 1159eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (dataKind == null) continue; 1160cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann 1161eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos dataItem.setDataKind(dataKind); 1162b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 1163eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final boolean hasData = !TextUtils.isEmpty(dataItem.buildDataString(this, 1164eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos dataKind)); 1165899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos 1166eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (isMimeExcluded(mimeType) || !hasData) continue; 1167edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 1168eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos List<DataItem> dataItemListByType = dataItemsMap.get(mimeType); 1169eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (dataItemListByType == null) { 1170eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos dataItemListByType = new ArrayList<>(); 1171eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos dataItemsMap.put(mimeType, dataItemListByType); 1172edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 1173eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos dataItemListByType.add(dataItem); 1174edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 1175edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 11768a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.endSection(); 1177edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 1178eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Trace.beginSection("sort within mimetypes"); 117916339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos /* 118016339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos * Sorting is a multi part step. The end result is to a have a sorted list of the most 1181eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * used data items, one per mimetype. Then, within each mimetype, the list of data items 1182eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * for that type is also sorted, based off of {super primary, primary, times used} in that 1183eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * order. 118416339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos */ 1185eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final List<List<DataItem>> dataItemsList = new ArrayList<>(); 1186eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos for (List<DataItem> mimeTypeDataItems : dataItemsMap.values()) { 1187eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos // Remove duplicate data items 1188eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Collapser.collapseList(mimeTypeDataItems, this); 1189eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos // Sort within mimetype 1190eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Collections.sort(mimeTypeDataItems, mWithinMimeTypeDataItemComparator); 1191eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos // Add to the list of data item lists 1192eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos dataItemsList.add(mimeTypeDataItems); 1193edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 1194eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Trace.endSection(); 1195edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 1196eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Trace.beginSection("sort amongst mimetypes"); 1197eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos // Sort amongst mimetypes to bubble up the top data items for the contact card 1198eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Collections.sort(dataItemsList, mAmongstMimeTypeDataItemComparator); 1199eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Trace.endSection(); 120016339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos 12016bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell Trace.beginSection("cp2 data items to entries"); 12026bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell 12036bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final List<List<Entry>> contactCardEntries = new ArrayList<>(); 12046bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final List<List<Entry>> aboutCardEntries = buildAboutCardEntries(dataItemsMap); 12056bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final MutableString aboutCardName = new MutableString(); 12066bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell 12076bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell for (int i = 0; i < dataItemsList.size(); ++i) { 12086bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final List<DataItem> dataItemsByMimeType = dataItemsList.get(i); 12096bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final DataItem topDataItem = dataItemsByMimeType.get(0); 12106bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell if (SORTED_ABOUT_CARD_MIMETYPES.contains(topDataItem.getMimeType())) { 12116bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell // About card mimetypes are built in buildAboutCardEntries, skip here 12126bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell continue; 12136bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell } else { 12146bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell List<Entry> contactEntries = dataItemsToEntries(dataItemsList.get(i), 12156bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell aboutCardName); 12166bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell if (contactEntries.size() > 0) { 12176bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell contactCardEntries.add(contactEntries); 12186bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell } 12196bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell } 12206bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell } 12216bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell 12226bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell Trace.endSection(); 12236bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell 12246bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final Cp2DataCardModel dataModel = new Cp2DataCardModel(); 12256bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell dataModel.customAboutCardName = aboutCardName.value; 12266bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell dataModel.aboutCardEntries = aboutCardEntries; 12276bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell dataModel.contactCardEntries = contactCardEntries; 12286bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell dataModel.dataItemsMap = dataItemsMap; 12296bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell return dataModel; 12306bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell } 12316bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell 12326bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell /** 12336bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell * Class used to hold the About card and Contact cards' data model that gets generated 12346bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell * on a background thread. All data is from CP2. 12356bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell */ 12366bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private static class Cp2DataCardModel { 12376bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell /** 12386bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell * A map between a mimetype string and the corresponding list of data items. The data items 12396bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell * are in sorted order using mWithinMimeTypeDataItemComparator. 12406bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell */ 12416bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell public Map<String, List<DataItem>> dataItemsMap; 12426bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell public List<List<Entry>> aboutCardEntries; 12436bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell public List<List<Entry>> contactCardEntries; 12446bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell public String customAboutCardName; 12456bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell } 12466bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell 12476bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private static class MutableString { 12486bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell public String value; 1249eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1250edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 1251eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos /** 1252eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * Converts a {@link DataItem} into an {@link ExpandingEntryCardView.Entry} for display. 1253eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * If the {@link ExpandingEntryCardView.Entry} has no visual elements, null is returned. 12546bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell * 12556bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell * This runs on a background thread. This is set as static to avoid accidentally adding 12566bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell * additional dependencies on unsafe things (like the Activity). 12576bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell * 1258eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * @param dataItem The {@link DataItem} to convert. 12596a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos * @param secondDataItem A second {@link DataItem} to help build a full entry for some 12606a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos * mimetypes 1261eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos * @return The {@link ExpandingEntryCardView.Entry}, or null if no visual elements are present. 1262eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos */ 12636a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos private static Entry dataItemToEntry(DataItem dataItem, DataItem secondDataItem, 12646bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell Context context, Contact contactData, 12656bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final MutableString aboutCardName) { 1266eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Drawable icon = null; 1267eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos String header = null; 1268eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos String subHeader = null; 1269eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Drawable subHeaderIcon = null; 1270eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos String text = null; 1271eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Drawable textIcon = null; 127223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos StringBuilder primaryContentDescription = new StringBuilder(); 1273eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos Intent intent = null; 127448ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos boolean shouldApplyColor = true; 1275dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos Drawable alternateIcon = null; 1276dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos Intent alternateIntent = null; 127723e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos StringBuilder alternateContentDescription = new StringBuilder(); 1278eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final boolean isEditable = false; 12792a4207fb39330e840436215c896cde911489e111Paul Soulos EntryContextMenuInfo entryContextMenuInfo = null; 128048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos Drawable thirdIcon = null; 128148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos Intent thirdIntent = null; 128248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos String thirdContentDescription = null; 128348290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos int iconResourceId = 0; 1284eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 12856bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell context = context.getApplicationContext(); 128623e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos final Resources res = context.getResources(); 1287eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos DataKind kind = dataItem.getDataKind(); 1288eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 1289eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (dataItem instanceof ImDataItem) { 1290eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final ImDataItem im = (ImDataItem) dataItem; 12916bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell intent = ContactsUtils.buildImIntent(context, im).first; 1292eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final boolean isEmail = im.isCreatedFromEmail(); 12937de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos final int protocol; 12947de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos if (!im.isProtocolValid()) { 12957de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos protocol = Im.PROTOCOL_CUSTOM; 12967de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos } else { 12977de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos protocol = isEmail ? Im.PROTOCOL_GOOGLE_TALK : im.getProtocol(); 12987de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos } 12997de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos if (protocol == Im.PROTOCOL_CUSTOM) { 13007de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos // If the protocol is custom, display the "IM" entry header as well to distinguish 13017de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos // this entry from other ones 130223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos header = res.getString(R.string.header_im_entry); 130323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos subHeader = Im.getProtocolLabel(res, protocol, 13047de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos im.getCustomProtocol()).toString(); 13057de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos text = im.getData(); 13067de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos } else { 130723e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos header = Im.getProtocolLabel(res, protocol, 13087de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos im.getCustomProtocol()).toString(); 13097de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos subHeader = im.getData(); 13107de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos } 131197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos entryContextMenuInfo = new EntryContextMenuInfo(im.getData(), header, 131297f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary()); 1313eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (dataItem instanceof OrganizationDataItem) { 1314eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final OrganizationDataItem organization = (OrganizationDataItem) dataItem; 131523e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos header = res.getString(R.string.header_organization_entry); 1316eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos subHeader = organization.getCompany(); 131797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header, 131897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary()); 1319eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos text = organization.getTitle(); 1320eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (dataItem instanceof NicknameDataItem) { 1321eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final NicknameDataItem nickname = (NicknameDataItem) dataItem; 1322eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos // Build nickname entries 1323eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final boolean isNameRawContact = 13246bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell (contactData.getNameRawContactId() == dataItem.getRawContactId()); 1325eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 1326eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final boolean duplicatesTitle = 1327eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos isNameRawContact 13286bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell && contactData.getDisplayNameSource() == DisplayNameSources.NICKNAME; 1329eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 1330eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (!duplicatesTitle) { 133123e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos header = res.getString(R.string.header_nickname_entry); 1332eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos subHeader = nickname.getName(); 133397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header, 133497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary()); 1335eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1336eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (dataItem instanceof NoteDataItem) { 1337eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final NoteDataItem note = (NoteDataItem) dataItem; 133823e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos header = res.getString(R.string.header_note_entry); 1339eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos subHeader = note.getNote(); 134097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header, 134197f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary()); 1342eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (dataItem instanceof WebsiteDataItem) { 1343eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final WebsiteDataItem website = (WebsiteDataItem) dataItem; 134423e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos header = res.getString(R.string.header_website_entry); 1345eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos subHeader = website.getUrl(); 134697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header, 134797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary()); 1348eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos try { 13496bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final WebAddress webAddress = new WebAddress(website.buildDataString(context, 13506bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell kind)); 1351eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos intent = new Intent(Intent.ACTION_VIEW, Uri.parse(webAddress.toString())); 1352eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } catch (final ParseException e) { 13536bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell Log.e(TAG, "Couldn't parse website: " + website.buildDataString(context, kind)); 1354eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1355eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (dataItem instanceof EventDataItem) { 1356eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final EventDataItem event = (EventDataItem) dataItem; 13576bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final String dataString = event.buildDataString(context, kind); 1358eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final Calendar cal = DateUtils.parseDate(dataString, false); 1359eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (cal != null) { 1360eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final Date nextAnniversary = 1361eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos DateUtils.getNextAnnualDate(cal); 1362eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final Uri.Builder builder = CalendarContract.CONTENT_URI.buildUpon(); 1363eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos builder.appendPath("time"); 1364eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos ContentUris.appendId(builder, nextAnniversary.getTime()); 1365eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos intent = new Intent(Intent.ACTION_VIEW).setData(builder.build()); 1366eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 136723e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos header = res.getString(R.string.header_event_entry); 1368f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos if (event.hasKindTypeColumn(kind)) { 136923e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos subHeader = Event.getTypeLabel(res, event.getKindTypeColumn(kind), 13707de6f85b0ee66deda13505f545c6b7125b2ac462Paul Soulos event.getLabel()).toString(); 1371f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos } 13726bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell text = DateUtils.formatDate(context, dataString); 137397f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos entryContextMenuInfo = new EntryContextMenuInfo(text, header, 137497f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary()); 1375eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (dataItem instanceof RelationDataItem) { 1376eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final RelationDataItem relation = (RelationDataItem) dataItem; 13776bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final String dataString = relation.buildDataString(context, kind); 1378eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (!TextUtils.isEmpty(dataString)) { 1379eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos intent = new Intent(Intent.ACTION_SEARCH); 1380eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos intent.putExtra(SearchManager.QUERY, dataString); 1381eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos intent.setType(Contacts.CONTENT_TYPE); 1382eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 138323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos header = res.getString(R.string.header_relation_entry); 1384eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos subHeader = relation.getName(); 138597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos entryContextMenuInfo = new EntryContextMenuInfo(subHeader, header, 138697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getMimeType(), dataItem.getId(), dataItem.isSuperPrimary()); 1387f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos if (relation.hasKindTypeColumn(kind)) { 138823e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos text = Relation.getTypeLabel(res, 13896bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell relation.getKindTypeColumn(kind), 1390f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos relation.getLabel()).toString(); 1391f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos } 1392eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (dataItem instanceof PhoneDataItem) { 1393eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final PhoneDataItem phone = (PhoneDataItem) dataItem; 1394eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (!TextUtils.isEmpty(phone.getNumber())) { 139523e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.append(res.getString(R.string.call_other)).append(" "); 1396c62cc7931593b4137f8a507689b653e1e15e1260Brian Attwell header = sBidiFormatter.unicodeWrap(phone.buildDataString(context, kind), 1397c62cc7931593b4137f8a507689b653e1e15e1260Brian Attwell TextDirectionHeuristics.LTR); 13982a4207fb39330e840436215c896cde911489e111Paul Soulos entryContextMenuInfo = new EntryContextMenuInfo(header, 139997f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos res.getString(R.string.phoneLabelsGroup), dataItem.getMimeType(), 140097f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getId(), dataItem.isSuperPrimary()); 1401f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos if (phone.hasKindTypeColumn(kind)) { 140223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos text = Phone.getTypeLabel(res, phone.getKindTypeColumn(kind), 1403f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos phone.getLabel()).toString(); 140423e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.append(text).append(" "); 1405f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos } 140623e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.append(header); 140723e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos icon = res.getDrawable(R.drawable.ic_phone_24dp); 140848290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos iconResourceId = R.drawable.ic_phone_24dp; 14096bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell if (PhoneCapabilityTester.isPhone(context)) { 1410eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos intent = CallUtil.getCallIntent(phone.getNumber()); 141116339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos } 1412dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos alternateIntent = new Intent(Intent.ACTION_SENDTO, 14131cd88e3ecfa72f43c3fe25c912d9f67848f11e60Jay Shrauner Uri.fromParts(ContactsUtils.SCHEME_SMSTO, phone.getNumber(), null)); 141448fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos 141523e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos alternateIcon = res.getDrawable(R.drawable.ic_message_24dp); 141623e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos alternateContentDescription.append(res.getString(R.string.sms_custom, header)); 141748fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos 141848fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos // Add video call button if supported 1419f764730a34da560db87206f9a48390d4c8085365Paul Soulos if (CallUtil.isVideoEnabled(context)) { 142023e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos thirdIcon = res.getDrawable(R.drawable.ic_videocam); 142148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos thirdIntent = CallUtil.getVideoCallIntent(phone.getNumber(), 142248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos CALL_ORIGIN_QUICK_CONTACTS_ACTIVITY); 142348fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos thirdContentDescription = 142423e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos res.getString(R.string.description_video_call); 142548fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos } 1426eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1427eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (dataItem instanceof EmailDataItem) { 1428eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final EmailDataItem email = (EmailDataItem) dataItem; 1429eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final String address = email.getData(); 1430eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (!TextUtils.isEmpty(address)) { 143123e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.append(res.getString(R.string.email_other)).append(" "); 14321cd88e3ecfa72f43c3fe25c912d9f67848f11e60Jay Shrauner final Uri mailUri = Uri.fromParts(ContactsUtils.SCHEME_MAILTO, address, null); 1433eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos intent = new Intent(Intent.ACTION_SENDTO, mailUri); 1434eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos header = email.getAddress(); 14352a4207fb39330e840436215c896cde911489e111Paul Soulos entryContextMenuInfo = new EntryContextMenuInfo(header, 143697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos res.getString(R.string.emailLabelsGroup), dataItem.getMimeType(), 143797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getId(), dataItem.isSuperPrimary()); 1438f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos if (email.hasKindTypeColumn(kind)) { 143923e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos text = Email.getTypeLabel(res, email.getKindTypeColumn(kind), 1440f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos email.getLabel()).toString(); 144123e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.append(text).append(" "); 1442f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos } 144323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.append(header); 144423e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos icon = res.getDrawable(R.drawable.ic_email_24dp); 144548290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos iconResourceId = R.drawable.ic_email_24dp; 1446eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1447eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (dataItem instanceof StructuredPostalDataItem) { 1448eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos StructuredPostalDataItem postal = (StructuredPostalDataItem) dataItem; 1449eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final String postalAddress = postal.getFormattedAddress(); 1450eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (!TextUtils.isEmpty(postalAddress)) { 145123e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.append(res.getString(R.string.map_other)).append(" "); 1452eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos intent = StructuredPostalUtils.getViewPostalAddressIntent(postalAddress); 1453eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos header = postal.getFormattedAddress(); 14542a4207fb39330e840436215c896cde911489e111Paul Soulos entryContextMenuInfo = new EntryContextMenuInfo(header, 145597f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos res.getString(R.string.postalLabelsGroup), dataItem.getMimeType(), 145697f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getId(), dataItem.isSuperPrimary()); 1457f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos if (postal.hasKindTypeColumn(kind)) { 145823e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos text = StructuredPostal.getTypeLabel(res, 1459f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos postal.getKindTypeColumn(kind), postal.getLabel()).toString(); 146023e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.append(text).append(" "); 1461f9d5c0e24d1b11527475227549f9530127e9dc07Paul Soulos } 146223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.append(header); 14636a4d2736d772cc5cbb79d04e115f2d6117826860Paul Soulos alternateIntent = 14646a4d2736d772cc5cbb79d04e115f2d6117826860Paul Soulos StructuredPostalUtils.getViewPostalAddressDirectionsIntent(postalAddress); 146523e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos alternateIcon = res.getDrawable(R.drawable.ic_directions_24dp); 146623e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos alternateContentDescription.append(res.getString( 146723e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos R.string.content_description_directions)).append(" ").append(header); 146823e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos icon = res.getDrawable(R.drawable.ic_place_24dp); 146948290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos iconResourceId = R.drawable.ic_place_24dp; 1470eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1471eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (dataItem instanceof SipAddressDataItem) { 1472593e5a7f2551b7946ada9913408f649e530202c8Brian Attwell final SipAddressDataItem sip = (SipAddressDataItem) dataItem; 1473593e5a7f2551b7946ada9913408f649e530202c8Brian Attwell final String address = sip.getSipAddress(); 1474593e5a7f2551b7946ada9913408f649e530202c8Brian Attwell if (!TextUtils.isEmpty(address)) { 1475593e5a7f2551b7946ada9913408f649e530202c8Brian Attwell primaryContentDescription.append(res.getString(R.string.call_other)).append( 1476593e5a7f2551b7946ada9913408f649e530202c8Brian Attwell " "); 1477593e5a7f2551b7946ada9913408f649e530202c8Brian Attwell if (PhoneCapabilityTester.isSipPhone(context)) { 14781cd88e3ecfa72f43c3fe25c912d9f67848f11e60Jay Shrauner final Uri callUri = Uri.fromParts(PhoneAccount.SCHEME_SIP, address, null); 1479eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos intent = CallUtil.getCallIntent(callUri); 148016339336653fa028a2e02e1eee92851fe5084d1cPaul Soulos } 1481593e5a7f2551b7946ada9913408f649e530202c8Brian Attwell header = address; 1482593e5a7f2551b7946ada9913408f649e530202c8Brian Attwell entryContextMenuInfo = new EntryContextMenuInfo(header, 1483593e5a7f2551b7946ada9913408f649e530202c8Brian Attwell res.getString(R.string.phoneLabelsGroup), dataItem.getMimeType(), 1484593e5a7f2551b7946ada9913408f649e530202c8Brian Attwell dataItem.getId(), dataItem.isSuperPrimary()); 1485593e5a7f2551b7946ada9913408f649e530202c8Brian Attwell if (sip.hasKindTypeColumn(kind)) { 1486593e5a7f2551b7946ada9913408f649e530202c8Brian Attwell text = SipAddress.getTypeLabel(res, 1487593e5a7f2551b7946ada9913408f649e530202c8Brian Attwell sip.getKindTypeColumn(kind), sip.getLabel()).toString(); 1488593e5a7f2551b7946ada9913408f649e530202c8Brian Attwell primaryContentDescription.append(text).append(" "); 1489593e5a7f2551b7946ada9913408f649e530202c8Brian Attwell } 1490593e5a7f2551b7946ada9913408f649e530202c8Brian Attwell primaryContentDescription.append(header); 1491593e5a7f2551b7946ada9913408f649e530202c8Brian Attwell icon = res.getDrawable(R.drawable.ic_dialer_sip_black_24dp); 1492593e5a7f2551b7946ada9913408f649e530202c8Brian Attwell iconResourceId = R.drawable.ic_dialer_sip_black_24dp; 1493edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 1494eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else if (dataItem instanceof StructuredNameDataItem) { 1495eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final String givenName = ((StructuredNameDataItem) dataItem).getGivenName(); 1496eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (!TextUtils.isEmpty(givenName)) { 149723e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos aboutCardName.value = res.getString(R.string.about_card_title) + 14986bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell " " + givenName; 1499eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else { 150023e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos aboutCardName.value = res.getString(R.string.about_card_title); 1501eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1502eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } else { 1503eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos // Custom DataItem 15046bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell header = dataItem.buildDataStringForDisplay(context, kind); 1505eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos text = kind.typeColumn; 1506eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos intent = new Intent(Intent.ACTION_VIEW); 150760e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos final Uri uri = ContentUris.withAppendedId(Data.CONTENT_URI, dataItem.getId()); 150860e5108e39e54d0a7e4c6924b33597d338be3fb9Paul Soulos intent.setDataAndType(uri, dataItem.getMimeType()); 1509e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos 1510e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos if (intent != null) { 1511e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos final String mimetype = intent.getType(); 1512e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos 15136a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos // Build advanced entry for known 3p types. Otherwise default to ResolveCache icon. 1514e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos switch (mimetype) { 1515e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos case MIMETYPE_GPLUS_PROFILE: 15166a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos // If a secondDataItem is available, use it to build an entry with 15176a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos // alternate actions 15186a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos if (secondDataItem != null) { 151923e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos icon = res.getDrawable(R.drawable.ic_google_plus_24dp); 15206a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos alternateIcon = res.getDrawable(R.drawable.ic_add_to_circles_black_24); 15216a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos final GPlusOrHangoutsDataItemModel itemModel = 15226a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos new GPlusOrHangoutsDataItemModel(intent, alternateIntent, 15236a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataItem, secondDataItem, alternateContentDescription, 15246a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos header, text, context); 15256a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos 152697b1e2d6206ad8f64af6bc935451654204706661Paul Soulos populateGPlusOrHangoutsDataItemModel(itemModel); 152797b1e2d6206ad8f64af6bc935451654204706661Paul Soulos intent = itemModel.intent; 152897b1e2d6206ad8f64af6bc935451654204706661Paul Soulos alternateIntent = itemModel.alternateIntent; 152997b1e2d6206ad8f64af6bc935451654204706661Paul Soulos alternateContentDescription = itemModel.alternateContentDescription; 153097b1e2d6206ad8f64af6bc935451654204706661Paul Soulos header = itemModel.header; 153197b1e2d6206ad8f64af6bc935451654204706661Paul Soulos text = itemModel.text; 15326a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } else { 15336a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos if (GPLUS_PROFILE_DATA_5_ADD_TO_CIRCLE.equals( 15346a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos intent.getDataString())) { 15356a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos icon = res.getDrawable(R.drawable.ic_add_to_circles_black_24); 15366a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } else { 15376a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos icon = res.getDrawable(R.drawable.ic_google_plus_24dp); 15386a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } 1539e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos } 1540e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos break; 1541e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos case MIMETYPE_HANGOUTS: 15426a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos // If a secondDataItem is available, use it to build an entry with 15436a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos // alternate actions 15446a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos if (secondDataItem != null) { 154523e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos icon = res.getDrawable(R.drawable.ic_hangout_24dp); 15466a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos alternateIcon = res.getDrawable(R.drawable.ic_hangout_video_24dp); 154797b1e2d6206ad8f64af6bc935451654204706661Paul Soulos final GPlusOrHangoutsDataItemModel itemModel = 15486a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos new GPlusOrHangoutsDataItemModel(intent, alternateIntent, 15496a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataItem, secondDataItem, alternateContentDescription, 15506a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos header, text, context); 15516a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos 155297b1e2d6206ad8f64af6bc935451654204706661Paul Soulos populateGPlusOrHangoutsDataItemModel(itemModel); 155397b1e2d6206ad8f64af6bc935451654204706661Paul Soulos intent = itemModel.intent; 155497b1e2d6206ad8f64af6bc935451654204706661Paul Soulos alternateIntent = itemModel.alternateIntent; 155597b1e2d6206ad8f64af6bc935451654204706661Paul Soulos alternateContentDescription = itemModel.alternateContentDescription; 155697b1e2d6206ad8f64af6bc935451654204706661Paul Soulos header = itemModel.header; 155797b1e2d6206ad8f64af6bc935451654204706661Paul Soulos text = itemModel.text; 15586a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } else { 15596a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos if (HANGOUTS_DATA_5_VIDEO.equals(intent.getDataString())) { 15606a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos icon = res.getDrawable(R.drawable.ic_hangout_video_24dp); 15616a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } else { 15626a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos icon = res.getDrawable(R.drawable.ic_hangout_24dp); 15636a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } 1564e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos } 1565e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos break; 1566e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos default: 156797f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos entryContextMenuInfo = new EntryContextMenuInfo(header, mimetype, 156897f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.getMimeType(), dataItem.getId(), 156997f27809c3e6153ce0bc5050bc5ee466a646e8ecPaul Soulos dataItem.isSuperPrimary()); 15706bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell icon = ResolveCache.getInstance(context).getIcon( 1571e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos dataItem.getMimeType(), intent); 1572e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos // Call mutate to create a new Drawable.ConstantState for color filtering 1573e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos if (icon != null) { 1574e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos icon.mutate(); 1575e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos } 157648ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos shouldApplyColor = false; 1577e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos } 1578e005566a1616d6797fb7e204d0d41bd341b37543Paul Soulos } 1579eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1580b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 1581eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (intent != null) { 1582eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos // Do not set the intent is there are no resolves 15836bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell if (!PhoneCapabilityTester.isIntentRegistered(context, intent)) { 1584eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos intent = null; 1585eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1586eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1587eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 1588dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos if (alternateIntent != null) { 1589dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos // Do not set the alternate intent is there are no resolves 15906bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell if (!PhoneCapabilityTester.isIntentRegistered(context, alternateIntent)) { 1591dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos alternateIntent = null; 1592f0d04c11b649e953177e79722d05fa048e53273dJay Shrauner } else if (TextUtils.isEmpty(alternateContentDescription)) { 1593f0d04c11b649e953177e79722d05fa048e53273dJay Shrauner // Attempt to use package manager to find a suitable content description if needed 159423e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos alternateContentDescription.append(getIntentResolveLabel(alternateIntent, context)); 1595dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos } 1596dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos } 1597dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos 1598eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos // If the Entry has no visual elements, return null 1599eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos if (icon == null && TextUtils.isEmpty(header) && TextUtils.isEmpty(subHeader) && 1600eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos subHeaderIcon == null && TextUtils.isEmpty(text) && textIcon == null) { 1601eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return null; 1602eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1603eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 1604fa238949855fba3b28a57fad3d585b13e80362bbBrian Attwell // Ignore dataIds from the Me profile. 1605ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos final int dataId = dataItem.getId() > Integer.MAX_VALUE ? 1606ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos -1 : (int) dataItem.getId(); 1607ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos 160823e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos return new Entry(dataId, icon, header, subHeader, subHeaderIcon, text, textIcon, 160923e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos primaryContentDescription.toString(), intent, alternateIcon, alternateIntent, 161023e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos alternateContentDescription.toString(), shouldApplyColor, isEditable, 161148290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos entryContextMenuInfo, thirdIcon, thirdIntent, thirdContentDescription, 161248290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos iconResourceId); 1613eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1614eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 16156bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private List<Entry> dataItemsToEntries(List<DataItem> dataItems, 16166bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell MutableString aboutCardTitleOut) { 16176a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos // Hangouts and G+ use two data items to create one entry. 16186a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos if (dataItems.get(0).getMimeType().equals(MIMETYPE_GPLUS_PROFILE) || 16196a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataItems.get(0).getMimeType().equals(MIMETYPE_HANGOUTS)) { 16206a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos return gPlusOrHangoutsDataItemsToEntries(dataItems); 16216a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } else { 16226a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos final List<Entry> entries = new ArrayList<>(); 16236a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos for (DataItem dataItem : dataItems) { 16246a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos final Entry entry = dataItemToEntry(dataItem, /* secondDataItem = */ null, 16256a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos this, mContactData, aboutCardTitleOut); 16266a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos if (entry != null) { 16276a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos entries.add(entry); 16286a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } 16296a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } 16306a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos return entries; 16316a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } 16326a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } 16336a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos 16346a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos /** 16356a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos * G+ and Hangout entries are unique in that a single ExpandingEntryCardView.Entry consists 16366a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos * of two data items. This method attempts to build each entry using the two data items if 16376a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos * they are available. If there are more or less than two data items, a fall back is used 16386a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos * and each data item gets its own entry. 16396a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos */ 16406a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos private List<Entry> gPlusOrHangoutsDataItemsToEntries(List<DataItem> dataItems) { 1641eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final List<Entry> entries = new ArrayList<>(); 16426a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos final Map<Long, List<DataItem>> buckets = new HashMap<>(); 16436a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos // Put the data items into buckets based on the raw contact id 1644eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos for (DataItem dataItem : dataItems) { 16456a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos List<DataItem> bucket = buckets.get(dataItem.getRawContactId()); 16466a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos if (bucket == null) { 16476a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos bucket = new ArrayList<>(); 16486a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos buckets.put(dataItem.getRawContactId(), bucket); 16496a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } 16506a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos bucket.add(dataItem); 16516a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } 16526a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos 16536a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos // Use the buckets to build entries. If a bucket contains two data items, build the special 16546a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos // entry, otherwise fall back to the normal entry. 16556a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos for (List<DataItem> bucket : buckets.values()) { 16566a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos if (bucket.size() == 2) { 16576a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos // Use the pair to build an entry 16586a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos final Entry entry = dataItemToEntry(bucket.get(0), 16596a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos /* secondDataItem = */ bucket.get(1), this, mContactData, 16606a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos /* aboutCardName = */ null); 16616a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos if (entry != null) { 16626a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos entries.add(entry); 16636a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } 16646a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } else { 16656a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos for (DataItem dataItem : bucket) { 16666a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos final Entry entry = dataItemToEntry(dataItem, /* secondDataItem = */ null, 16676a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos this, mContactData, /* aboutCardName = */ null); 16686a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos if (entry != null) { 16696a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos entries.add(entry); 16706a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } 16716a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } 1672eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1673eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } 1674eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos return entries; 1675edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann } 1676edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann 16776a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos /** 16786a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos * Used for statically passing around G+ or Hangouts data items and entry fields to 16796a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos * populateGPlusOrHangoutsDataItemModel. 16806a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos */ 16816a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos private static final class GPlusOrHangoutsDataItemModel { 16826a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos public Intent intent; 16836a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos public Intent alternateIntent; 16846a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos public DataItem dataItem; 16856a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos public DataItem secondDataItem; 16866a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos public StringBuilder alternateContentDescription; 16876a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos public String header; 16886a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos public String text; 16896a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos public Context context; 16906a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos 16916a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos public GPlusOrHangoutsDataItemModel(Intent intent, Intent alternateIntent, DataItem dataItem, 16926a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos DataItem secondDataItem, StringBuilder alternateContentDescription, String header, 16936a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos String text, Context context) { 16946a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos this.intent = intent; 16956a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos this.alternateIntent = alternateIntent; 16966a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos this.dataItem = dataItem; 16976a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos this.secondDataItem = secondDataItem; 16986a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos this.alternateContentDescription = alternateContentDescription; 16996a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos this.header = header; 17006a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos this.text = text; 17016a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos this.context = context; 17026a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } 17036a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } 17046a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos 17056a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos private static void populateGPlusOrHangoutsDataItemModel( 17066a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos GPlusOrHangoutsDataItemModel dataModel) { 17076a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos final Intent secondIntent = new Intent(Intent.ACTION_VIEW); 17086a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos secondIntent.setDataAndType(ContentUris.withAppendedId(Data.CONTENT_URI, 17096a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataModel.secondDataItem.getId()), dataModel.secondDataItem.getMimeType()); 17106a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos // There is no guarantee the order the data items come in. Second 17116a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos // data item does not necessarily mean it's the alternate. 17126a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos // Hangouts video and Add to circles should be alternate. Swap if needed 17136a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos if (HANGOUTS_DATA_5_VIDEO.equals( 17146a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataModel.dataItem.getContentValues().getAsString(Data.DATA5)) || 17156a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos GPLUS_PROFILE_DATA_5_ADD_TO_CIRCLE.equals( 17166a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataModel.dataItem.getContentValues().getAsString(Data.DATA5))) { 17176a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataModel.alternateIntent = dataModel.intent; 17186a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataModel.alternateContentDescription = new StringBuilder(dataModel.header); 17196a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos 17206a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataModel.intent = secondIntent; 17216a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataModel.header = dataModel.secondDataItem.buildDataStringForDisplay(dataModel.context, 17226a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataModel.secondDataItem.getDataKind()); 17236a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataModel.text = dataModel.secondDataItem.getDataKind().typeColumn; 17246a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } else if (HANGOUTS_DATA_5_MESSAGE.equals( 17256a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataModel.dataItem.getContentValues().getAsString(Data.DATA5)) || 17266a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos GPLUS_PROFILE_DATA_5_VIEW_PROFILE.equals( 17276a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataModel.dataItem.getContentValues().getAsString(Data.DATA5))) { 17286a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataModel.alternateIntent = secondIntent; 17296a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataModel.alternateContentDescription = new StringBuilder( 17306a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataModel.secondDataItem.buildDataStringForDisplay(dataModel.context, 17316a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos dataModel.secondDataItem.getDataKind())); 17326a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } 17336a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos } 17346a2a1a7d87cd3c59d0e09abce0739ab4175a670ePaul Soulos 17356bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell private static String getIntentResolveLabel(Intent intent, Context context) { 17366bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell final List<ResolveInfo> matches = context.getPackageManager().queryIntentActivities(intent, 1737dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos PackageManager.MATCH_DEFAULT_ONLY); 1738dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos 1739dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos // Pick first match, otherwise best found 1740dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos ResolveInfo bestResolve = null; 1741dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos final int size = matches.size(); 1742dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos if (size == 1) { 1743dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos bestResolve = matches.get(0); 1744dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos } else if (size > 1) { 17456bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell bestResolve = ResolveCache.getInstance(context).getBestResolve(intent, matches); 1746dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos } 1747dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos 1748dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos if (bestResolve == null) { 1749dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos return null; 1750dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos } 1751dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos 17526bb01347eab60f95deafdfe523b0c368707210f3Brian Attwell return String.valueOf(bestResolve.loadLabel(context.getPackageManager())); 1753dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos } 1754dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos 1755edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann /** 175631b2d42fb0889e61515d27314aa5a245147100daBrian Attwell * Asynchronously extract the most vibrant color from the PhotoView. Once extracted, 175731b2d42fb0889e61515d27314aa5a245147100daBrian Attwell * apply this tint to {@link MultiShrinkScroller}. This operation takes about 20-30ms 175831b2d42fb0889e61515d27314aa5a245147100daBrian Attwell * on a Nexus 5. 175931b2d42fb0889e61515d27314aa5a245147100daBrian Attwell */ 176031b2d42fb0889e61515d27314aa5a245147100daBrian Attwell private void extractAndApplyTintFromPhotoViewAsynchronously() { 176131b2d42fb0889e61515d27314aa5a245147100daBrian Attwell if (mScroller == null) { 176231b2d42fb0889e61515d27314aa5a245147100daBrian Attwell return; 176331b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } 176431b2d42fb0889e61515d27314aa5a245147100daBrian Attwell final Drawable imageViewDrawable = mPhotoView.getDrawable(); 1765faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell new AsyncTask<Void, Void, MaterialPalette>() { 176631b2d42fb0889e61515d27314aa5a245147100daBrian Attwell @Override 1767faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell protected MaterialPalette doInBackground(Void... params) { 1768faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell 176995c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell if (imageViewDrawable instanceof BitmapDrawable 177095c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell && mContactData.getThumbnailPhotoBinaryData() != null 177195c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell && mContactData.getThumbnailPhotoBinaryData().length > 0) { 177295c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell // Perform the color analysis on the thumbnail instead of the full sized 177395c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell // image, so that our results will be as similar as possible to the Bugle 177495c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell // app. 177595c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell final Bitmap bitmap = BitmapFactory.decodeByteArray( 177695c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell mContactData.getThumbnailPhotoBinaryData(), 0, 177795c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell mContactData.getThumbnailPhotoBinaryData().length); 177895c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell try { 177995c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell final int primaryColor = colorFromBitmap(bitmap); 178095c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell if (primaryColor != 0) { 178195c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell return mMaterialColorMapUtils.calculatePrimaryAndSecondaryColor( 178295c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell primaryColor); 178395c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell } 178495c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell } finally { 178595c268e8dae6ed6b3bf6a205b02eadd995dec2c0Brian Attwell bitmap.recycle(); 1786faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell } 17878a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 17888a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (imageViewDrawable instanceof LetterTileDrawable) { 1789faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell final int primaryColor = ((LetterTileDrawable) imageViewDrawable).getColor(); 1790a3859ed9ff9f315d492e199620a08ae35ab8569fBrian Attwell return mMaterialColorMapUtils.calculatePrimaryAndSecondaryColor(primaryColor); 179131b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } 1792a3859ed9ff9f315d492e199620a08ae35ab8569fBrian Attwell return MaterialColorMapUtils.getDefaultPrimaryAndSecondaryColors(getResources()); 179331b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } 179431b2d42fb0889e61515d27314aa5a245147100daBrian Attwell 179531b2d42fb0889e61515d27314aa5a245147100daBrian Attwell @Override 1796faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell protected void onPostExecute(MaterialPalette palette) { 1797faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell super.onPostExecute(palette); 17988571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell if (mHasComputedThemeColor) { 17998571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell // If we had previously computed a theme color from the contact photo, 18008571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell // then do not update the theme color. Changing the theme color several 18018571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell // seconds after QC has started, as a result of an updated/upgraded photo, 18028571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell // is a jarring experience. On the other hand, changing the theme color after 18038571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell // a rotation or onNewIntent() is perfectly fine. 18048571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell return; 18058571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell } 18068571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell // Check that the Photo has not changed. If it has changed, the new tint 18078571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell // color needs to be extracted 18088571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell if (imageViewDrawable == mPhotoView.getDrawable()) { 18098571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell mHasComputedThemeColor = true; 1810faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell setThemeColor(palette); 181131b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } 181231b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } 181331b2d42fb0889e61515d27314aa5a245147100daBrian Attwell }.execute(); 181431b2d42fb0889e61515d27314aa5a245147100daBrian Attwell } 181531b2d42fb0889e61515d27314aa5a245147100daBrian Attwell 18164936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell /** 18174936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell * Examine how many white pixels are in the bitmap in order to determine whether or not 18184936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell * we need gradient overlays on top of the image. 18194936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell */ 18204936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell private void analyzeWhitenessOfPhotoAsynchronously() { 18214936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell final Drawable imageViewDrawable = mPhotoView.getDrawable(); 18224936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell new AsyncTask<Void, Void, Boolean>() { 18234936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell @Override 18244936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell protected Boolean doInBackground(Void... params) { 18254936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell if (imageViewDrawable instanceof BitmapDrawable) { 18264936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell final Bitmap bitmap = ((BitmapDrawable) imageViewDrawable).getBitmap(); 18274936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell return WhitenessUtils.isBitmapWhiteAtTopOrBottom(bitmap); 18284936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell } 18294936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell return !(imageViewDrawable instanceof LetterTileDrawable); 18304936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell } 18314936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell 18324936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell @Override 18334936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell protected void onPostExecute(Boolean isWhite) { 18344936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell super.onPostExecute(isWhite); 18354936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell mScroller.setUseGradient(isWhite); 18364936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell } 18374936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell }.execute(); 18384936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell } 18394936a92aeef739ae6b57dad00f385307d1b1c5b8Brian Attwell 1840faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell private void setThemeColor(MaterialPalette palette) { 18419b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell // If the color is invalid, use the predefined default 1842faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell final int primaryColor = palette.mPrimaryColor; 1843faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell mScroller.setHeaderTintColor(primaryColor); 1844faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell mStatusBarColor = palette.mSecondaryColor; 18459b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell updateStatusBarColor(); 18468571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell 18479b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell mColorFilter = 1848faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell new PorterDuffColorFilter(primaryColor, PorterDuff.Mode.SRC_ATOP); 1849faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell mContactCard.setColorAndFilter(primaryColor, mColorFilter); 1850faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell mRecentCard.setColorAndFilter(primaryColor, mColorFilter); 1851faf973989af7ac3b735c2aee1bec22ef6608b123Brian Attwell mAboutCard.setColorAndFilter(primaryColor, mColorFilter); 18529b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell } 18539b889e6ef4534db6925e3f915bed281733ea8bc3Brian Attwell 18548a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private void updateStatusBarColor() { 18558a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (mScroller == null) { 18568a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell return; 18578a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 18588a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell final int desiredStatusBarColor; 18598a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // Only use a custom status bar color if QuickContacts touches the top of the viewport. 18608a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (mScroller.getScrollNeededToBeFullScreen() <= 0) { 18618a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell desiredStatusBarColor = mStatusBarColor; 18628a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } else { 18638a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell desiredStatusBarColor = Color.TRANSPARENT; 18648a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 18658a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // Animate to the new color. 1866847bf2cd3946b1801c83c745d7183aed5143b44cBrian Attwell final ObjectAnimator animation = ObjectAnimator.ofInt(getWindow(), "statusBarColor", 1867847bf2cd3946b1801c83c745d7183aed5143b44cBrian Attwell getWindow().getStatusBarColor(), desiredStatusBarColor); 1868847bf2cd3946b1801c83c745d7183aed5143b44cBrian Attwell animation.setDuration(ANIMATION_STATUS_BAR_COLOR_CHANGE_DURATION); 1869847bf2cd3946b1801c83c745d7183aed5143b44cBrian Attwell animation.setEvaluator(new ArgbEvaluator()); 1870847bf2cd3946b1801c83c745d7183aed5143b44cBrian Attwell animation.start(); 18718a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 18728a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 18738a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell private int colorFromBitmap(Bitmap bitmap) { 18748a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // Author of Palette recommends using 24 colors when analyzing profile photos. 18758a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell final int NUMBER_OF_PALETTE_COLORS = 24; 18768a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell final Palette palette = Palette.generate(bitmap, NUMBER_OF_PALETTE_COLORS); 1877a0f20f77e1b4f6cde5934d8b3348d93b58fd6362Brian Attwell if (palette != null && palette.getVibrantSwatch() != null) { 1878a0f20f77e1b4f6cde5934d8b3348d93b58fd6362Brian Attwell return palette.getVibrantSwatch().getRgb(); 18798a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 18808a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell return 0; 18818a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 18828a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 1883b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos private List<Entry> contactInteractionsToEntries(List<ContactInteraction> interactions) { 1884eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final List<Entry> entries = new ArrayList<>(); 1885b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos for (ContactInteraction interaction : interactions) { 1886ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos entries.add(new Entry(/* id = */ -1, 1887ea5e0b715030f1b0e8015defd10842127a8a4121Paul Soulos interaction.getIcon(this), 1888b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos interaction.getViewHeader(this), 1889b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos interaction.getViewBody(this), 1890b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos interaction.getBodyIcon(this), 1891b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos interaction.getViewFooter(this), 1892b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos interaction.getFooterIcon(this), 189323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos interaction.getContentDescription(this), 1894b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos interaction.getIntent(), 1895dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos /* alternateIcon = */ null, 1896dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos /* alternateIntent = */ null, 1897dd7419d90cda5c52e81491bea3cf3c3f4e0535c7Paul Soulos /* alternateContentDescription = */ null, 189848ebbaafcf467c072e4477c98ef2faba1c65af7ePaul Soulos /* shouldApplyColor = */ true, 18992a4207fb39330e840436215c896cde911489e111Paul Soulos /* isEditable = */ false, 190048fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos /* EntryContextMenuInfo = */ null, 190148fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos /* thirdIcon = */ null, 190248fc91217042fd854f0e96c2028c188e50a5e21dPaul Soulos /* thirdIntent = */ null, 190348290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos /* thirdContentDescription = */ null, 190448290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos interaction.getIconResourceId())); 1905b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 1906b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos return entries; 1907b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 1908b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 1909eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos private final LoaderCallbacks<Contact> mLoaderContactCallbacks = 1910851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu new LoaderCallbacks<Contact>() { 1911cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann @Override 1912851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu public void onLoaderReset(Loader<Contact> loader) { 1913405ae406379ad9c47770783afc76a660f6c55fcaPaul Soulos mContactData = null; 1914cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann } 1915cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann 1916cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann @Override 1917851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu public void onLoadFinished(Loader<Contact> loader, Contact data) { 19188a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Trace.beginSection("onLoadFinished()"); 1919930da3ae6e392777986ed0722c5480caf1bd9e7eBrian Attwell try { 19208a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 1921930da3ae6e392777986ed0722c5480caf1bd9e7eBrian Attwell if (isFinishing()) { 1922930da3ae6e392777986ed0722c5480caf1bd9e7eBrian Attwell return; 1923930da3ae6e392777986ed0722c5480caf1bd9e7eBrian Attwell } 1924930da3ae6e392777986ed0722c5480caf1bd9e7eBrian Attwell if (data.isError()) { 1925930da3ae6e392777986ed0722c5480caf1bd9e7eBrian Attwell // This shouldn't ever happen, so throw an exception. The {@link ContactLoader} 1926930da3ae6e392777986ed0722c5480caf1bd9e7eBrian Attwell // should log the actual exception. 1927930da3ae6e392777986ed0722c5480caf1bd9e7eBrian Attwell throw new IllegalStateException("Failed to load contact", data.getException()); 1928930da3ae6e392777986ed0722c5480caf1bd9e7eBrian Attwell } 1929930da3ae6e392777986ed0722c5480caf1bd9e7eBrian Attwell if (data.isNotFound()) { 19308a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Log.i(TAG, "No contact found: " + ((ContactLoader)loader).getLookupUri()); 19318a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Toast.makeText(QuickContactActivity.this, R.string.invalidContactMessage, 19328a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell Toast.LENGTH_LONG).show(); 1933930da3ae6e392777986ed0722c5480caf1bd9e7eBrian Attwell finish(); 1934930da3ae6e392777986ed0722c5480caf1bd9e7eBrian Attwell return; 19358a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 1936cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann 1937930da3ae6e392777986ed0722c5480caf1bd9e7eBrian Attwell bindContactData(data); 1938cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann 1939930da3ae6e392777986ed0722c5480caf1bd9e7eBrian Attwell } finally { 1940930da3ae6e392777986ed0722c5480caf1bd9e7eBrian Attwell Trace.endSection(); 1941930da3ae6e392777986ed0722c5480caf1bd9e7eBrian Attwell } 1942cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann } 1943cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann 1944cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann @Override 1945851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu public Loader<Contact> onCreateLoader(int id, Bundle args) { 1946cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann if (mLookupUri == null) { 1947cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann Log.wtf(TAG, "Lookup uri wasn't initialized. Loader was started too early"); 1948cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann } 1949d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // Load all contact data. We need loadGroupMetaData=true to determine whether the 1950d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // contact is invisible. If it is, we need to display an "Add to Contacts" MenuItem. 1951b2b435a944947fbf1965c3bb7c202a97f0273259Yorke Lee return new ContactLoader(getApplicationContext(), mLookupUri, 1952d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell true /*loadGroupMetaData*/, false /*loadInvitableAccountTypes*/, 19538571dd3953ddf2cf8442335657a1945487d665a1Brian Attwell true /*postViewNotification*/, true /*computeFormattedPhoneNumber*/); 1954cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann } 1955cb8d73fc8ea538d0b63dd77210c05c5b8de32f03Daniel Lehmann }; 1956b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 1957b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell @Override 1958b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell public void onBackPressed() { 1959b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell if (mScroller != null) { 19608477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell if (!mIsExitAnimationInProgress) { 19618477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell mScroller.scrollOffBottom(); 19628477eafe57bca7b6b72da6e2e419ebeaf4de9674Brian Attwell } 1963b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell } else { 1964b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell super.onBackPressed(); 1965b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell } 1966b7e4364d6536449271ac4534dbeb7430134c096bBrian Attwell } 1967b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 19688a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell @Override 19698a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell public void finish() { 19708a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell super.finish(); 19718a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 19728a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // override transitions to skip the standard window animations 19738a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell overridePendingTransition(0, 0); 19748a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 19758a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 1976eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos private final LoaderCallbacks<List<ContactInteraction>> mLoaderInteractionsCallbacks = 1977b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos new LoaderCallbacks<List<ContactInteraction>>() { 1978b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 1979b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos @Override 1980b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos public Loader<List<ContactInteraction>> onCreateLoader(int id, Bundle args) { 1981b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos Loader<List<ContactInteraction>> loader = null; 1982b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos switch (id) { 1983b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos case LOADER_SMS_ID: 1984b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos loader = new SmsInteractionsLoader( 1985b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos QuickContactActivity.this, 1986ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos args.getStringArray(KEY_LOADER_EXTRA_PHONES), 1987b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos MAX_SMS_RETRIEVE); 1988b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos break; 1989899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos case LOADER_CALENDAR_ID: 1990ae4cafed699b7cd6c5d4dad855bc0d4948452983Paul Soulos final String[] emailsArray = args.getStringArray(KEY_LOADER_EXTRA_EMAILS); 1991ae4cafed699b7cd6c5d4dad855bc0d4948452983Paul Soulos List<String> emailsList = null; 1992ae4cafed699b7cd6c5d4dad855bc0d4948452983Paul Soulos if (emailsArray != null) { 1993ae4cafed699b7cd6c5d4dad855bc0d4948452983Paul Soulos emailsList = Arrays.asList(args.getStringArray(KEY_LOADER_EXTRA_EMAILS)); 1994ae4cafed699b7cd6c5d4dad855bc0d4948452983Paul Soulos } 1995899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos loader = new CalendarInteractionsLoader( 1996899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos QuickContactActivity.this, 1997ae4cafed699b7cd6c5d4dad855bc0d4948452983Paul Soulos emailsList, 1998899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos MAX_FUTURE_CALENDAR_RETRIEVE, 1999899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos MAX_PAST_CALENDAR_RETRIEVE, 2000899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos FUTURE_MILLISECOND_TO_SEARCH_LOCAL_CALENDAR, 2001899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos PAST_MILLISECOND_TO_SEARCH_LOCAL_CALENDAR); 2002899aa21e911ee7170beab228d44d7fed68c414e4Paul Soulos break; 2003ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos case LOADER_CALL_LOG_ID: 2004ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos loader = new CallLogInteractionsLoader( 2005ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos QuickContactActivity.this, 2006ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos args.getStringArray(KEY_LOADER_EXTRA_PHONES), 2007ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos MAX_CALL_LOG_RETRIEVE); 2008b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 2009b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos return loader; 2010b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 2011b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 2012b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos @Override 2013b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos public void onLoadFinished(Loader<List<ContactInteraction>> loader, 2014b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos List<ContactInteraction> data) { 2015b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos mRecentLoaderResults.put(loader.getId(), data); 2016b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 2017b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos if (isAllRecentDataLoaded()) { 2018b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos bindRecentData(); 2019b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 2020b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 2021b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 2022b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos @Override 2023b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos public void onLoaderReset(Loader<List<ContactInteraction>> loader) { 2024b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos mRecentLoaderResults.remove(loader.getId()); 2025b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 2026b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos }; 2027b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 2028b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos private boolean isAllRecentDataLoaded() { 2029b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos return mRecentLoaderResults.size() == mRecentLoaderIds.length; 2030b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 2031b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 2032b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos private void bindRecentData() { 2033eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final List<ContactInteraction> allInteractions = new ArrayList<>(); 203430e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell final List<List<Entry>> interactionsWrapper = new ArrayList<>(); 2035b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos 203630e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell mRecentDataTask = new AsyncTask<Void, Void, Void>() { 2037b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos @Override 203830e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell protected Void doInBackground(Void... params) { 203930e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell Trace.beginSection("sort recent loader results"); 204030e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell 204130e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell for (List<ContactInteraction> loaderInteractions : mRecentLoaderResults.values()) { 204230e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell allInteractions.addAll(loaderInteractions); 204330e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell } 204430e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell 204530e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell // Sort the interactions by most recent 204630e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell Collections.sort(allInteractions, new Comparator<ContactInteraction>() { 204730e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell @Override 204830e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell public int compare(ContactInteraction a, ContactInteraction b) { 204930e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell return a.getInteractionDate() >= b.getInteractionDate() ? -1 : 1; 205030e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell } 205130e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell }); 205230e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell 205330e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell Trace.endSection(); 205430e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell Trace.beginSection("contactInteractionsToEntries"); 205530e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell 205630e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell // Wrap each interaction in its own list so that an icon is displayed for each entry 205730e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell for (Entry contactInteraction : contactInteractionsToEntries(allInteractions)) { 205830e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell List<Entry> entryListWrapper = new ArrayList<>(1); 205930e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell entryListWrapper.add(contactInteraction); 206030e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell interactionsWrapper.add(entryListWrapper); 206130e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell } 206230e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell 206330e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell Trace.endSection(); 206430e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell return null; 2065b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 206630e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell 206730e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell @Override 206830e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell protected void onPostExecute(Void aVoid) { 206930e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell super.onPostExecute(aVoid); 207030e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell Trace.beginSection("initialize recents card"); 207130e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell 207230e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell if (allInteractions.size() > 0) { 207330e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell mRecentCard.initialize(interactionsWrapper, 2074b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos /* numInitialVisibleEntries = */ MIN_NUM_COLLAPSED_RECENT_ENTRIES_SHOWN, 2075c8e2a91807b581194566eb45019fa16e2268b462Paul Soulos /* isExpanded = */ mRecentCard.isExpanded(), /* isAlwaysExpanded = */ false, 207630e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell mExpandingEntryCardViewListener, mScroller); 207730e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell mRecentCard.setVisibility(View.VISIBLE); 207830e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell } 2079eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos 208030e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell Trace.endSection(); 208130e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell 208230e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell // About card is initialized along with the contact card, but since it appears after 208330e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell // the recent card in the UI, we hold off until making it visible until the recent 208430e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell // card is also ready to avoid stuttering. 208530e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell if (mAboutCard.shouldShow()) { 208630e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell mAboutCard.setVisibility(View.VISIBLE); 208730e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell } else { 208830e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell mAboutCard.setVisibility(View.GONE); 208930e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell } 209030e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell mRecentDataTask = null; 209130e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell } 209230e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell }; 209330e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell mRecentDataTask.execute(); 2094b3054e551173887029c55cb10b83f1afb7f8a6fePaul Soulos } 20958a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 20968a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell @Override 20978a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell protected void onStop() { 20988a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell super.onStop(); 20998a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell 21008a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell if (mEntriesAndActionsTask != null) { 21018a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // Once the activity is stopped, we will no longer want to bind mEntriesAndActionsTask's 21028a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // results on the UI thread. In some circumstances Activities are killed without 21038a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // onStop() being called. This is not a problem, because in these circumstances 21048a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell // the entire process will be killed. 21058a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell mEntriesAndActionsTask.cancel(/* mayInterruptIfRunning = */ false); 21068a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 210730e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell if (mRecentDataTask != null) { 210830e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell mRecentDataTask.cancel(/* mayInterruptIfRunning = */ false); 210930e1ef1927a1a21370b6b5dedd73540152062475Brian Attwell } 21108a6f4ade05e5a8a89d91078ef9c22944450ac8baBrian Attwell } 211123889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos 211223889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos /** 2113d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell * Returns true if it is possible to edit the current contact. 2114d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell */ 2115d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell private boolean isContactEditable() { 2116d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell return mContactData != null && !mContactData.isDirectoryEntry(); 2117d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 2118d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 2119a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell /** 2120a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell * Returns true if it is possible to share the current contact. 2121a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell */ 2122a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell private boolean isContactShareable() { 2123a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell return mContactData != null && !mContactData.isDirectoryEntry(); 2124a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell } 2125a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell 21266095369885edcca566a812b551886e29c7ff8039Brian Attwell private Intent getEditContactIntent() { 212763176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell final Intent intent = new Intent(Intent.ACTION_EDIT, mContactData.getLookupUri()); 2128d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 21296095369885edcca566a812b551886e29c7ff8039Brian Attwell return intent; 21306095369885edcca566a812b551886e29c7ff8039Brian Attwell } 21316095369885edcca566a812b551886e29c7ff8039Brian Attwell 21326095369885edcca566a812b551886e29c7ff8039Brian Attwell private void editContact() { 2133a42ef76251778161d27bc07db214b8c81720e476Paul Soulos mHasIntentLaunched = true; 2134c00a0b5370f0714f6af1ea9b3e29b10f25e91af0Zheng Fu mContactLoader.cacheResult(); 21356095369885edcca566a812b551886e29c7ff8039Brian Attwell startActivityForResult(getEditContactIntent(), REQUEST_CODE_CONTACT_EDITOR_ACTIVITY); 2136d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 2137d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 2138d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell private void toggleStar(MenuItem starredMenuItem) { 2139d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // Make sure there is a contact 214063176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell if (mContactData != null) { 2141d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // Read the current starred value from the UI instead of using the last 2142d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // loaded state. This allows rapid tapping without writing the same 2143d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // value several times 2144d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell final boolean isStarred = starredMenuItem.isChecked(); 2145d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 2146d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // To improve responsiveness, swap out the picture (and tag) in the UI already 2147333091ae754ddfc25714c14b9b89534be24379f9Paul Soulos ContactDisplayUtils.configureStarredMenuItem(starredMenuItem, 2148d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mContactData.isDirectoryEntry(), mContactData.isUserProfile(), 2149d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell !isStarred); 2150d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 2151d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // Now perform the real save 2152eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final Intent intent = ContactSaveService.createSetStarredIntent( 215363176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell QuickContactActivity.this, mContactData.getLookupUri(), !isStarred); 2154d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell startService(intent); 215535ccdba7b8b2270204f7f96d824d258e408fe6efBrian Attwell 215635ccdba7b8b2270204f7f96d824d258e408fe6efBrian Attwell final CharSequence accessibilityText = !isStarred 215735ccdba7b8b2270204f7f96d824d258e408fe6efBrian Attwell ? getResources().getText(R.string.description_action_menu_add_star) 215835ccdba7b8b2270204f7f96d824d258e408fe6efBrian Attwell : getResources().getText(R.string.description_action_menu_remove_star); 215935ccdba7b8b2270204f7f96d824d258e408fe6efBrian Attwell // Accessibility actions need to have an associated view. We can't access the MenuItem's 216035ccdba7b8b2270204f7f96d824d258e408fe6efBrian Attwell // underlying view, so put this accessibility action on the root view. 216135ccdba7b8b2270204f7f96d824d258e408fe6efBrian Attwell mScroller.announceForAccessibility(accessibilityText); 2162d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 2163d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 2164d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 2165752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell /** 2166752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell * Calls into the contacts provider to get a pre-authorized version of the given URI. 2167752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell */ 2168752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell private Uri getPreAuthorizedUri(Uri uri) { 2169752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell final Bundle uriBundle = new Bundle(); 2170752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell uriBundle.putParcelable(ContactsContract.Authorization.KEY_URI_TO_AUTHORIZE, uri); 2171752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell final Bundle authResponse = getContentResolver().call( 2172752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell ContactsContract.AUTHORITY_URI, 2173752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell ContactsContract.Authorization.AUTHORIZATION_METHOD, 2174752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell null, 2175752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell uriBundle); 2176752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell if (authResponse != null) { 2177752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell return (Uri) authResponse.getParcelable( 2178752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell ContactsContract.Authorization.KEY_AUTHORIZED_URI); 2179752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell } else { 2180752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell return uri; 2181752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell } 2182752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell } 21832d150da246632b1649999cfabed776133b097775Brian Attwell 2184752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell private void shareContact() { 2185752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell final String lookupKey = mContactData.getLookupKey(); 2186752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell Uri shareUri = Uri.withAppendedPath(Contacts.CONTENT_VCARD_URI, lookupKey); 2187752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell if (mContactData.isUserProfile()) { 2188752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell // User is sharing the profile. We don't want to force the receiver to have 2189752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell // the highly-privileged READ_PROFILE permission, so we need to request a 2190752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell // pre-authorized URI from the provider. 2191752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell shareUri = getPreAuthorizedUri(shareUri); 2192752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell } 2193752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell 2194752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell final Intent intent = new Intent(Intent.ACTION_SEND); 2195752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell intent.setType(Contacts.CONTENT_VCARD_TYPE); 2196752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell intent.putExtra(Intent.EXTRA_STREAM, shareUri); 2197752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell 2198752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell // Launch chooser to share contact via 2199752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell final CharSequence chooseTitle = getText(R.string.share_via); 2200752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell final Intent chooseIntent = Intent.createChooser(intent, chooseTitle); 2201752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell 2202752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell try { 2203a42ef76251778161d27bc07db214b8c81720e476Paul Soulos mHasIntentLaunched = true; 2204752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell this.startActivity(chooseIntent); 2205eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos } catch (final ActivityNotFoundException ex) { 2206752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell Toast.makeText(this, R.string.share_error, Toast.LENGTH_SHORT).show(); 2207752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell } 2208752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell } 2209752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell 2210752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell /** 2211752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell * Creates a launcher shortcut with the current contact. 2212752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell */ 2213752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell private void createLauncherShortcutWithContact() { 2214752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell final ShortcutIntentBuilder builder = new ShortcutIntentBuilder(this, 2215752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell new OnShortcutIntentCreatedListener() { 2216752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell 2217752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell @Override 2218752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell public void onShortcutIntentCreated(Uri uri, Intent shortcutIntent) { 2219752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell // Broadcast the shortcutIntent to the launcher to create a 2220752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell // shortcut to this contact 2221752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell shortcutIntent.setAction(ACTION_INSTALL_SHORTCUT); 2222752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell QuickContactActivity.this.sendBroadcast(shortcutIntent); 2223752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell 2224752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell // Send a toast to give feedback to the user that a shortcut to this 2225752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell // contact was added to the launcher. 2226752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell Toast.makeText(QuickContactActivity.this, 2227752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell R.string.createContactShortcutSuccessful, 2228752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell Toast.LENGTH_SHORT).show(); 2229752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell } 2230752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell 2231752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell }); 223263176c96f33b5a0bcb25816c80889bb11e5c7152Brian Attwell builder.createContactShortcutIntent(mContactData.getLookupUri()); 2233752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell } 2234752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell 223566965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell private boolean isShortcutCreatable() { 223666965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell final Intent createShortcutIntent = new Intent(); 223766965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell createShortcutIntent.setAction(ACTION_INSTALL_SHORTCUT); 223866965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell final List<ResolveInfo> receivers = getPackageManager() 223966965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell .queryBroadcastReceivers(createShortcutIntent, 0); 224066965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell return receivers != null && receivers.size() > 0; 224166965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell } 224266965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell 2243d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell @Override 2244d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell public boolean onCreateOptionsMenu(Menu menu) { 2245eb64a4b5c51b39fe56ba4ef97dfff73fdcdf8c75Paul Soulos final MenuInflater inflater = getMenuInflater(); 2246d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell inflater.inflate(R.menu.quickcontact, menu); 2247d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell return true; 2248d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 2249d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 2250d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell @Override 2251d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell public boolean onPrepareOptionsMenu(Menu menu) { 2252d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell if (mContactData != null) { 2253d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell final MenuItem starredMenuItem = menu.findItem(R.id.menu_star); 2254333091ae754ddfc25714c14b9b89534be24379f9Paul Soulos ContactDisplayUtils.configureStarredMenuItem(starredMenuItem, 2255d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mContactData.isDirectoryEntry(), mContactData.isUserProfile(), 2256d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell mContactData.getStarred()); 2257a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell 2258d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell // Configure edit MenuItem 2259d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell final MenuItem editMenuItem = menu.findItem(R.id.menu_edit); 2260d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell editMenuItem.setVisible(true); 2261d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell if (DirectoryContactUtil.isDirectoryContact(mContactData) || InvisibleContactUtil 2262d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell .isInvisibleAndAddable(mContactData, this)) { 226330cfd121ad8c8adb83cf417ff1d40a8ba1e3761dBrian Attwell editMenuItem.setIcon(R.drawable.ic_person_add_tinted_24dp); 22642e4214c79170cdb6c1b8b6ff0408925d3f512becBrian Attwell editMenuItem.setTitle(R.string.menu_add_contact); 2265d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } else if (isContactEditable()) { 2266d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell editMenuItem.setIcon(R.drawable.ic_create_24dp); 22672e4214c79170cdb6c1b8b6ff0408925d3f512becBrian Attwell editMenuItem.setTitle(R.string.menu_editContact); 2268d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } else { 2269d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell editMenuItem.setVisible(false); 2270d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 2271a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell 2272a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell final MenuItem shareMenuItem = menu.findItem(R.id.menu_share); 2273a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell shareMenuItem.setVisible(isContactShareable()); 2274a41d6d1c9d87fe81630426f537bdb864c1ee6db4Brian Attwell 227566965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell final MenuItem shortcutMenuItem = menu.findItem(R.id.menu_create_contact_shortcut); 227666965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell shortcutMenuItem.setVisible(isShortcutCreatable()); 227766965e14e741be40f3f5ad6aa21a75795f9a1eb1Brian Attwell 22788a6d0022b07640d4a1fb8b264c8822bbab2981adPaul Soulos return true; 2279d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 22808a6d0022b07640d4a1fb8b264c8822bbab2981adPaul Soulos return false; 2281d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 2282d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell 2283d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell @Override 2284d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell public boolean onOptionsItemSelected(MenuItem item) { 2285d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell switch (item.getItemId()) { 2286d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell case R.id.menu_star: 2287d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell toggleStar(item); 2288d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell return true; 2289d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell case R.id.menu_edit: 2290d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell if (DirectoryContactUtil.isDirectoryContact(mContactData)) { 2291ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos // This action is used to launch the contact selector, with the option of 2292ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos // creating a new contact. Creating a new contact is an INSERT, while selecting 2293ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos // an exisiting one is an edit. The fields in the edit screen will be 2294ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos // prepopulated with data. 2295ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos 2296ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos final Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT); 2297ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos intent.setType(Contacts.CONTENT_ITEM_TYPE); 2298ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos 2299fc423b4040a0ec1728ee32ff40ef430f3e16e9dcBrian Attwell ArrayList<ContentValues> values = mContactData.getContentValues(); 2300fc423b4040a0ec1728ee32ff40ef430f3e16e9dcBrian Attwell 2301fc423b4040a0ec1728ee32ff40ef430f3e16e9dcBrian Attwell // Only pre-fill the name field if the provided display name is an nickname 2302fc423b4040a0ec1728ee32ff40ef430f3e16e9dcBrian Attwell // or better (e.g. structured name, nickname) 2303fc423b4040a0ec1728ee32ff40ef430f3e16e9dcBrian Attwell if (mContactData.getDisplayNameSource() >= DisplayNameSources.NICKNAME) { 2304ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos intent.putExtra(Intents.Insert.NAME, mContactData.getDisplayName()); 2305fc423b4040a0ec1728ee32ff40ef430f3e16e9dcBrian Attwell } else if (mContactData.getDisplayNameSource() 2306fc423b4040a0ec1728ee32ff40ef430f3e16e9dcBrian Attwell == DisplayNameSources.ORGANIZATION) { 2307fc423b4040a0ec1728ee32ff40ef430f3e16e9dcBrian Attwell // This is probably an organization. Instead of copying the organization 2308fc423b4040a0ec1728ee32ff40ef430f3e16e9dcBrian Attwell // name into a name entry, copy it into the organization entry. This 2309fc423b4040a0ec1728ee32ff40ef430f3e16e9dcBrian Attwell // way we will still consider the contact an organization. 2310fc423b4040a0ec1728ee32ff40ef430f3e16e9dcBrian Attwell final ContentValues organization = new ContentValues(); 2311fc423b4040a0ec1728ee32ff40ef430f3e16e9dcBrian Attwell organization.put(Organization.COMPANY, mContactData.getDisplayName()); 2312fc423b4040a0ec1728ee32ff40ef430f3e16e9dcBrian Attwell organization.put(Data.MIMETYPE, Organization.CONTENT_ITEM_TYPE); 2313fc423b4040a0ec1728ee32ff40ef430f3e16e9dcBrian Attwell values.add(organization); 2314ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos } 2315fc423b4040a0ec1728ee32ff40ef430f3e16e9dcBrian Attwell 2316ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos // Last time used and times used are aggregated values from the usage stat 2317ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos // table. They need to be removed from data values so the SQL table can insert 2318ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos // properly 2319ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos for (ContentValues value : values) { 2320ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos value.remove(Data.LAST_TIME_USED); 2321ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos value.remove(Data.TIMES_USED); 2322ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos } 2323ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos intent.putExtra(Intents.Insert.DATA, values); 2324ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos 2325ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos // If the contact can only export to the same account, add it to the intent. 2326ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos // Otherwise the ContactEditorFragment will show a dialog for selecting an 2327ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos // account. 2328ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos if (mContactData.getDirectoryExportSupport() == 2329ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY) { 2330ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos intent.putExtra(Intents.Insert.ACCOUNT, 2331ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos new Account(mContactData.getDirectoryAccountName(), 2332ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos mContactData.getDirectoryAccountType())); 2333ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos intent.putExtra(Intents.Insert.DATA_SET, 2334ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos mContactData.getRawContacts().get(0).getDataSet()); 2335ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos } 2336ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos 2337f19dda97bfdef84e3f39ba069a981004a5c797b1Paul Soulos // Add this flag to disable the delete menu option on directory contact joins 2338f19dda97bfdef84e3f39ba069a981004a5c797b1Paul Soulos // with local contacts. The delete option is ambiguous when joining contacts. 2339f19dda97bfdef84e3f39ba069a981004a5c797b1Paul Soulos intent.putExtra(ContactEditorFragment.INTENT_EXTRA_DISABLE_DELETE_MENU_OPTION, 2340f19dda97bfdef84e3f39ba069a981004a5c797b1Paul Soulos true); 2341f19dda97bfdef84e3f39ba069a981004a5c797b1Paul Soulos 2342ab54ea15274dd3975c82a6aac29ba268aaed0799Paul Soulos startActivityForResult(intent, REQUEST_CODE_CONTACT_SELECTION_ACTIVITY); 2343d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } else if (InvisibleContactUtil.isInvisibleAndAddable(mContactData, this)) { 2344d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell InvisibleContactUtil.addToDefaultGroup(mContactData, this); 2345d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } else if (isContactEditable()) { 2346d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell editContact(); 2347d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 2348d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell return true; 2349752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell case R.id.menu_share: 2350752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell shareContact(); 2351752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell return true; 2352752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell case R.id.menu_create_contact_shortcut: 2353752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell createLauncherShortcutWithContact(); 2354752cccf954bd6070c5fb623875314951c8e9849dBrian Attwell return true; 2355d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell default: 2356d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell return super.onOptionsItemSelected(item); 2357d28851f436c39a83f02d3b405fd91f0fb4833b2aBrian Attwell } 235823889ba7ca18ed4ea56248355438a734511bc0b7Paul Soulos } 2359edb576aab33efff623691a89ace3c76cb2ff12d1Daniel Lehmann} 2360