CallLogAdapter.java revision cdd20a38dd669fea7de380fdc58fb526cb8d6581
194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng/* 294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * Copyright (C) 2011 The Android Open Source Project 394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * 494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * Licensed under the Apache License, Version 2.0 (the "License"); 594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * you may not use this file except in compliance with the License. 694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * You may obtain a copy of the License at 794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * 894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * http://www.apache.org/licenses/LICENSE-2.0 994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * 1094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * Unless required by applicable law or agreed to in writing, software 1194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * distributed under the License is distributed on an "AS IS" BASIS, 1294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * See the License for the specific language governing permissions and 1494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * limitations under the License. 1594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng */ 1694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng 1794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Chengpackage com.android.dialer.calllog; 1894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng 195f1c7dbf86603f534fbacdc96bab30d683913f4fBrandon Maxwellimport com.google.common.annotations.VisibleForTesting; 205f1c7dbf86603f534fbacdc96bab30d683913f4fBrandon Maxwell 2194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Chengimport android.content.Context; 22c5b6a693d4773214ff8d3fcfa43d0a29581bb886Chiao Chengimport android.content.Intent; 23bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chenimport android.content.SharedPreferences; 2494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Chengimport android.content.res.Resources; 2594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Chengimport android.database.Cursor; 2694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Chengimport android.net.Uri; 27267e9ebd056ec4973c4b37c38f949e863de4f24cAndrew Leeimport android.os.Bundle; 2849efd91e50a11dc7bdef8382a0ceac01bc060f77Andrew Leeimport android.os.Trace; 29bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chenimport android.preference.PreferenceManager; 3003aaf3894d8af53f241d1189c504e44c538100d4Nancy Chenimport android.provider.CallLog; 315f1c7dbf86603f534fbacdc96bab30d683913f4fBrandon Maxwellimport android.provider.ContactsContract.CommonDataKinds.Phone; 325f1c7dbf86603f534fbacdc96bab30d683913f4fBrandon Maxwellimport android.support.v7.widget.RecyclerView; 33492cd7371c6d8fddc4de85887a4ed9a89d602767Andrew Leeimport android.support.v7.widget.RecyclerView.ViewHolder; 349dc924c8bcc0bc8d996452e9ce3215b5f064962eTyler Gunnimport android.telecom.PhoneAccountHandle; 351e5325f43c98a92f8bfec1dbd9db3d32a91835e9Ihab Awadimport android.telephony.PhoneNumberUtils; 36bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chenimport android.telephony.TelephonyManager; 3794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Chengimport android.text.TextUtils; 3894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Chengimport android.view.LayoutInflater; 3994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Chengimport android.view.View; 40b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Leeimport android.view.View.AccessibilityDelegate; 4194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Chengimport android.view.ViewGroup; 42b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Leeimport android.view.accessibility.AccessibilityEvent; 4394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng 445f1c7dbf86603f534fbacdc96bab30d683913f4fBrandon Maxwellimport com.android.contacts.common.preference.ContactsPreferences; 45c16ea5ad67bf454158b364dec2f26c95a879c350Yorke Leeimport com.android.contacts.common.util.PermissionsUtil; 4694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Chengimport com.android.dialer.PhoneCallDetails; 479554500572ba82fbd7adb0a1637206ef870ef09eChiao Chengimport com.android.dialer.R; 4874479d448bc39c3534585a627fba603aa89e93caAndrew Leeimport com.android.dialer.contactinfo.ContactInfoCache; 4974479d448bc39c3534585a627fba603aa89e93caAndrew Leeimport com.android.dialer.contactinfo.ContactInfoCache.OnContactInfoChangedListener; 5070bb286f79696fc3a3ee8a57a038a9f56087d902Andrew Leeimport com.android.dialer.contactinfo.NumberWithCountryIso; 519bd094118e920b732394c29657f26b062f3e916bAnne Rongimport com.android.dialer.database.FilteredNumberAsyncQueryHandler; 5270bb286f79696fc3a3ee8a57a038a9f56087d902Andrew Leeimport com.android.dialer.database.FilteredNumberAsyncQueryHandler.OnCheckBlockedListener; 538d0847ca13ca46730756e1d3a3dff3d7d27fd18bAndrew Leeimport com.android.dialer.filterednumber.FilterNumberDialogFragment; 54d3f6a6c56dec7d47bae1121ed1030f67c26736feAndrew Leeimport com.android.dialer.util.PhoneNumberUtil; 55267e9ebd056ec4973c4b37c38f949e863de4f24cAndrew Leeimport com.android.dialer.voicemail.VoicemailPlaybackPresenter; 5656cb0efa5eda1670077e66fc0e8c79478d0c1c67Yorke Lee 57146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunnimport java.util.HashMap; 5870bb286f79696fc3a3ee8a57a038a9f56087d902Andrew Leeimport java.util.Map; 5994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng 6094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng/** 6194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * Adapter class to fill in data for the Call Log. 6294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng */ 63fb585079cc4c522c27f6dd6bf03fd296535960f3Yorke Leepublic class CallLogAdapter extends GroupingListAdapter 64601eadd8518b2a3683c50850af2a6db8147ec61aYorke Lee implements CallLogGroupBuilder.GroupCreator, 658d0847ca13ca46730756e1d3a3dff3d7d27fd18bAndrew Lee VoicemailPlaybackPresenter.OnVoicemailDeletedListener, 668d0847ca13ca46730756e1d3a3dff3d7d27fd18bAndrew Lee FilterNumberDialogFragment.Callback { 67c5b6a693d4773214ff8d3fcfa43d0a29581bb886Chiao Cheng 6894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng /** Interface used to initiate a refresh of the content. */ 6994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng public interface CallFetcher { 7094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng public void fetchCalls(); 7194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng } 7294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng 73affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee private static final int NO_EXPANDED_LIST_ITEM = -1; 748ef8020b8b792026a8dd15e029055f7d5e2d48f6Tyler Gunn 75bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen private static final int VOICEMAIL_PROMO_CARD_POSITION = 0; 76ab90a18e2f05c7ae4158b770a9fbe9cbe4544597Andrew Lee 77ab90a18e2f05c7ae4158b770a9fbe9cbe4544597Andrew Lee protected static final int VIEW_TYPE_NORMAL = 0; 78ab90a18e2f05c7ae4158b770a9fbe9cbe4544597Andrew Lee private static final int VIEW_TYPE_VOICEMAIL_PROMO_CARD = 1; 79bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen 80bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen /** 81bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen * The key for the show voicemail promo card preference which will determine whether the promo 82bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen * card was permanently dismissed or not. 83bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen */ 84bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen private static final String SHOW_VOICEMAIL_PROMO_CARD = "show_voicemail_promo_card"; 85bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen private static final boolean SHOW_VOICEMAIL_PROMO_CARD_DEFAULT = true; 86bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen 87704acc087ce359295475a46695c2821c55778344Chiao Cheng protected final Context mContext; 8894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng private final ContactInfoHelper mContactInfoHelper; 89a4adb2c035690a1c9600a20c2485886d9d5991d0Andrew Lee protected final VoicemailPlaybackPresenter mVoicemailPlaybackPresenter; 9094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng private final CallFetcher mCallFetcher; 919bd094118e920b732394c29657f26b062f3e916bAnne Rong private final FilteredNumberAsyncQueryHandler mFilteredNumberAsyncQueryHandler; 9294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng 9374479d448bc39c3534585a627fba603aa89e93caAndrew Lee protected ContactInfoCache mContactInfoCache; 9470bb286f79696fc3a3ee8a57a038a9f56087d902Andrew Lee protected final Map<NumberWithCountryIso, Integer> mBlockedIdCache; 9594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng 96a4adb2c035690a1c9600a20c2485886d9d5991d0Andrew Lee private boolean mIsCallLogActivity; 9769705be50fc4c84b35df88c879dd9a4b4de655b3Andrew Lee 98267e9ebd056ec4973c4b37c38f949e863de4f24cAndrew Lee private static final String KEY_EXPANDED_POSITION = "expanded_position"; 99267e9ebd056ec4973c4b37c38f949e863de4f24cAndrew Lee private static final String KEY_EXPANDED_ROW_ID = "expanded_row_id"; 100267e9ebd056ec4973c4b37c38f949e863de4f24cAndrew Lee 101affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee // Tracks the position of the currently expanded list item. 102affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee private int mCurrentlyExpandedPosition = RecyclerView.NO_POSITION; 103affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee // Tracks the rowId of the currently expanded list item, so the position can be updated if there 104affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee // are any changes to the call log entries, such as additions or removals. 105affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee private long mCurrentlyExpandedRowId = NO_EXPANDED_LIST_ITEM; 1062d588b857347fda465a963742c4f61e4014f3441Nancy Chen private int mHiddenPosition = RecyclerView.NO_POSITION; 1072d588b857347fda465a963742c4f61e4014f3441Nancy Chen private Uri mHiddenItemUri = null; 1082d588b857347fda465a963742c4f61e4014f3441Nancy Chen private boolean mPendingHide = false; 109146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn 11094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng /** 1114dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn * Hashmap, keyed by call Id, used to track the day group for a call. As call log entries are 1124dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn * put into the primary call groups in {@link com.android.dialer.calllog.CallLogGroupBuilder}, 1134dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn * they are also assigned a secondary "day group". This hashmap tracks the day group assigned 1144dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn * to all calls in the call log. This information is used to trigger the display of a day 1154dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn * group header above the call log entry at the start of a day group. 1164dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn * Note: Multiple calls are grouped into a single primary "call group" in the call log, and 1174dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn * the cursor used to bind rows includes all of these calls. When determining if a day group 1184dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn * change has occurred it is necessary to look at the last entry in the call log to determine 1194dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn * its day group. This hashmap provides a means of determining the previous day group without 1204dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn * having to reverse the cursor to the start of the previous day call log entry. 1214dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn */ 1225f1c7dbf86603f534fbacdc96bab30d683913f4fBrandon Maxwell private HashMap<Long, Integer> mDayGroups = new HashMap<>(); 1234dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn 12494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng private boolean mLoading = true; 12594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng 126bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen private SharedPreferences mPrefs; 127bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen 1285f1c7dbf86603f534fbacdc96bab30d683913f4fBrandon Maxwell private ContactsPreferences mContactsPreferences; 1295f1c7dbf86603f534fbacdc96bab30d683913f4fBrandon Maxwell 1300599e880630892becf1a1991e6712e0e6d9df3c8Andrew Lee protected boolean mShowVoicemailPromoCard = false; 131bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen 13294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng /** Instance of helper class for managing views. */ 133d3f6a6c56dec7d47bae1121ed1030f67c26736feAndrew Lee private final CallLogListItemHelper mCallLogListItemHelper; 134d3f6a6c56dec7d47bae1121ed1030f67c26736feAndrew Lee 135d3f6a6c56dec7d47bae1121ed1030f67c26736feAndrew Lee /** Cache for repeated requests to TelecomManager. */ 136d3f6a6c56dec7d47bae1121ed1030f67c26736feAndrew Lee protected final TelecomCallLogCache mTelecomCallLogCache; 13794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng 13894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng /** Helper to group call log entries. */ 13994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng private final CallLogGroupBuilder mCallLogGroupBuilder; 14094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng 141146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn /** 142affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee * The OnClickListener used to expand or collapse the action buttons of a call log entry. 143146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn */ 144146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn private final View.OnClickListener mExpandCollapseListener = new View.OnClickListener() { 145146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn @Override 146146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn public void onClick(View v) { 147affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee CallLogListItemViewHolder viewHolder = (CallLogListItemViewHolder) v.getTag(); 148affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee if (viewHolder == null) { 149affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee return; 150affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee } 151affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee 152053b9c7a4b2662588706211fd8aa1f8a03ec2901Andrew Lee if (mVoicemailPlaybackPresenter != null) { 153053b9c7a4b2662588706211fd8aa1f8a03ec2901Andrew Lee // Always reset the voicemail playback state on expand or collapse. 15485647649a10d680faeb2e73a3d191191058b7d66Nancy Chen mVoicemailPlaybackPresenter.resetAll(); 155053b9c7a4b2662588706211fd8aa1f8a03ec2901Andrew Lee } 156bae7b937b6cf6e7eb26d07bec95de38083923614Andrew Lee 157affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee if (viewHolder.getAdapterPosition() == mCurrentlyExpandedPosition) { 158affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee // Hide actions, if the clicked item is the expanded item. 1592f05af35af03de67c1c474cd148719b24fac3552Andrew Lee viewHolder.showActions(false); 160bae7b937b6cf6e7eb26d07bec95de38083923614Andrew Lee 161affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee mCurrentlyExpandedPosition = RecyclerView.NO_POSITION; 162affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee mCurrentlyExpandedRowId = NO_EXPANDED_LIST_ITEM; 163affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee } else { 164affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee expandViewHolderActions(viewHolder); 165affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee } 166affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee 167b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee } 168b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee }; 16968e771378889a479a80aac29a9ec2136b7ef27b6Tyler Gunn 170bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen /** 171bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen * Click handler used to dismiss the promo card when the user taps the "ok" button. 172bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen */ 173bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen private final View.OnClickListener mOkActionListener = new View.OnClickListener() { 174bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen @Override 175bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen public void onClick(View view) { 176bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen dismissVoicemailPromoCard(); 177bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen } 178bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen }; 179bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen 180bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen /** 181bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen * Click handler used to send the user to the voicemail settings screen and then dismiss the 182bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen * promo card. 183bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen */ 184bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen private final View.OnClickListener mVoicemailSettingsActionListener = 185bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen new View.OnClickListener() { 186bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen @Override 187bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen public void onClick(View view) { 188bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen Intent intent = new Intent(TelephonyManager.ACTION_CONFIGURE_VOICEMAIL); 189bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen mContext.startActivity(intent); 190bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen dismissVoicemailPromoCard(); 191bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen } 192bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen }; 193bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen 194affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee private void expandViewHolderActions(CallLogListItemViewHolder viewHolder) { 195affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee // If another item is expanded, notify it that it has changed. Its actions will be 196affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee // hidden when it is re-binded because we change mCurrentlyExpandedPosition below. 197affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee if (mCurrentlyExpandedPosition != RecyclerView.NO_POSITION) { 198affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee notifyItemChanged(mCurrentlyExpandedPosition); 199affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee } 200affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee // Show the actions for the clicked list item. 2012f05af35af03de67c1c474cd148719b24fac3552Andrew Lee viewHolder.showActions(true); 202affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee mCurrentlyExpandedPosition = viewHolder.getAdapterPosition(); 203affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee mCurrentlyExpandedRowId = viewHolder.rowId; 204affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee } 20574479d448bc39c3534585a627fba603aa89e93caAndrew Lee 206affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee /** 207affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee * Expand the actions on a list item when focused in Talkback mode, to aid discoverability. 208affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee */ 209b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee private AccessibilityDelegate mAccessibilityDelegate = new AccessibilityDelegate() { 210b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee @Override 211c940eada912f952a95d693ae6aab48ef08ef7319Andrew Lee public boolean onRequestSendAccessibilityEvent( 212c940eada912f952a95d693ae6aab48ef08ef7319Andrew Lee ViewGroup host, View child, AccessibilityEvent event) { 213b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED) { 214c940eada912f952a95d693ae6aab48ef08ef7319Andrew Lee // Only expand if actions are not already expanded, because triggering the expand 215c940eada912f952a95d693ae6aab48ef08ef7319Andrew Lee // function on clicks causes the action views to lose the focus indicator. 216c940eada912f952a95d693ae6aab48ef08ef7319Andrew Lee CallLogListItemViewHolder viewHolder = (CallLogListItemViewHolder) host.getTag(); 217cdd20a38dd669fea7de380fdc58fb526cb8d6581Nancy Chen if (mCurrentlyExpandedPosition != viewHolder.getAdapterPosition()) { 218c940eada912f952a95d693ae6aab48ef08ef7319Andrew Lee expandViewHolderActions((CallLogListItemViewHolder) host.getTag()); 219c940eada912f952a95d693ae6aab48ef08ef7319Andrew Lee } 22068e771378889a479a80aac29a9ec2136b7ef27b6Tyler Gunn } 221b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee return super.onRequestSendAccessibilityEvent(host, child, event); 222146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn } 223146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn }; 224146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn 225affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee protected final OnContactInfoChangedListener mOnContactInfoChangedListener = 226affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee new OnContactInfoChangedListener() { 227affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee @Override 228affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee public void onContactInfoChanged() { 229affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee notifyDataSetChanged(); 230affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee } 231affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee }; 232affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee 233c6fde8d1b9a4e586ca65b82e9911089a9da14508Andrew Lee public CallLogAdapter( 234c6fde8d1b9a4e586ca65b82e9911089a9da14508Andrew Lee Context context, 235c6fde8d1b9a4e586ca65b82e9911089a9da14508Andrew Lee CallFetcher callFetcher, 236c6fde8d1b9a4e586ca65b82e9911089a9da14508Andrew Lee ContactInfoHelper contactInfoHelper, 237267e9ebd056ec4973c4b37c38f949e863de4f24cAndrew Lee VoicemailPlaybackPresenter voicemailPlaybackPresenter, 238a4adb2c035690a1c9600a20c2485886d9d5991d0Andrew Lee boolean isCallLogActivity) { 23994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng super(context); 24094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng 24194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng mContext = context; 24294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng mCallFetcher = callFetcher; 24394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng mContactInfoHelper = contactInfoHelper; 244267e9ebd056ec4973c4b37c38f949e863de4f24cAndrew Lee mVoicemailPlaybackPresenter = voicemailPlaybackPresenter; 2450bb059d61f1e6648dee6f0a4cf8f02a6a7c26ce7Yorke Lee if (mVoicemailPlaybackPresenter != null) { 2460bb059d61f1e6648dee6f0a4cf8f02a6a7c26ce7Yorke Lee mVoicemailPlaybackPresenter.setOnVoicemailDeletedListener(this); 2470bb059d61f1e6648dee6f0a4cf8f02a6a7c26ce7Yorke Lee } 248a4adb2c035690a1c9600a20c2485886d9d5991d0Andrew Lee mIsCallLogActivity = isCallLogActivity; 249b77bf5df2b866dd40e330b7c2dedee4a1d51fc78Sai Cheemalapati 25074479d448bc39c3534585a627fba603aa89e93caAndrew Lee mContactInfoCache = new ContactInfoCache( 25174479d448bc39c3534585a627fba603aa89e93caAndrew Lee mContactInfoHelper, mOnContactInfoChangedListener); 252c16ea5ad67bf454158b364dec2f26c95a879c350Yorke Lee if (!PermissionsUtil.hasContactsPermissions(context)) { 253c16ea5ad67bf454158b364dec2f26c95a879c350Yorke Lee mContactInfoCache.disableRequestProcessing(); 254c16ea5ad67bf454158b364dec2f26c95a879c350Yorke Lee } 25594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng 25694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng Resources resources = mContext.getResources(); 25794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng CallTypeHelper callTypeHelper = new CallTypeHelper(resources); 25894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng 259d3f6a6c56dec7d47bae1121ed1030f67c26736feAndrew Lee mTelecomCallLogCache = new TelecomCallLogCache(mContext); 2605f1c7dbf86603f534fbacdc96bab30d683913f4fBrandon Maxwell mBlockedIdCache = new HashMap<>(); 261e80d62229bb11a92f0db8d4e4bac6533bbed9b66Nancy Chen PhoneCallDetailsHelper phoneCallDetailsHelper = 262d3f6a6c56dec7d47bae1121ed1030f67c26736feAndrew Lee new PhoneCallDetailsHelper(mContext, resources, mTelecomCallLogCache); 263d3f6a6c56dec7d47bae1121ed1030f67c26736feAndrew Lee mCallLogListItemHelper = 264d3f6a6c56dec7d47bae1121ed1030f67c26736feAndrew Lee new CallLogListItemHelper(phoneCallDetailsHelper, resources, mTelecomCallLogCache); 26594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng mCallLogGroupBuilder = new CallLogGroupBuilder(this); 2669bd094118e920b732394c29657f26b062f3e916bAnne Rong mFilteredNumberAsyncQueryHandler = 2679bd094118e920b732394c29657f26b062f3e916bAnne Rong new FilteredNumberAsyncQueryHandler(mContext.getContentResolver()); 268b980fc4386cdc24a605fc682d0fef0c5dc54c327Andrew Lee 269b980fc4386cdc24a605fc682d0fef0c5dc54c327Andrew Lee mPrefs = PreferenceManager.getDefaultSharedPreferences(context); 2705f1c7dbf86603f534fbacdc96bab30d683913f4fBrandon Maxwell mContactsPreferences = new ContactsPreferences(mContext); 271b980fc4386cdc24a605fc682d0fef0c5dc54c327Andrew Lee maybeShowVoicemailPromoCard(); 27294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng } 27394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng 274267e9ebd056ec4973c4b37c38f949e863de4f24cAndrew Lee public void onSaveInstanceState(Bundle outState) { 275267e9ebd056ec4973c4b37c38f949e863de4f24cAndrew Lee outState.putInt(KEY_EXPANDED_POSITION, mCurrentlyExpandedPosition); 276267e9ebd056ec4973c4b37c38f949e863de4f24cAndrew Lee outState.putLong(KEY_EXPANDED_ROW_ID, mCurrentlyExpandedRowId); 277267e9ebd056ec4973c4b37c38f949e863de4f24cAndrew Lee } 278267e9ebd056ec4973c4b37c38f949e863de4f24cAndrew Lee 279267e9ebd056ec4973c4b37c38f949e863de4f24cAndrew Lee public void onRestoreInstanceState(Bundle savedInstanceState) { 280267e9ebd056ec4973c4b37c38f949e863de4f24cAndrew Lee if (savedInstanceState != null) { 281267e9ebd056ec4973c4b37c38f949e863de4f24cAndrew Lee mCurrentlyExpandedPosition = 282267e9ebd056ec4973c4b37c38f949e863de4f24cAndrew Lee savedInstanceState.getInt(KEY_EXPANDED_POSITION, RecyclerView.NO_POSITION); 283267e9ebd056ec4973c4b37c38f949e863de4f24cAndrew Lee mCurrentlyExpandedRowId = 284267e9ebd056ec4973c4b37c38f949e863de4f24cAndrew Lee savedInstanceState.getLong(KEY_EXPANDED_ROW_ID, NO_EXPANDED_LIST_ITEM); 285267e9ebd056ec4973c4b37c38f949e863de4f24cAndrew Lee } 286267e9ebd056ec4973c4b37c38f949e863de4f24cAndrew Lee } 287267e9ebd056ec4973c4b37c38f949e863de4f24cAndrew Lee 28894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng /** 28994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * Requery on background thread when {@link Cursor} changes. 29094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng */ 29194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng @Override 29294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng protected void onContentChanged() { 29394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng mCallFetcher.fetchCalls(); 29494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng } 29594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng 296fb585079cc4c522c27f6dd6bf03fd296535960f3Yorke Lee public void setLoading(boolean loading) { 29794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng mLoading = loading; 29894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng } 29994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng 30094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng public boolean isEmpty() { 30194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng if (mLoading) { 30294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng // We don't want the empty state to show when loading. 30394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng return false; 30494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng } else { 305492cd7371c6d8fddc4de85887a4ed9a89d602767Andrew Lee return getItemCount() == 0; 30694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng } 30794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng } 30894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng 30994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng public void invalidateCache() { 31074479d448bc39c3534585a627fba603aa89e93caAndrew Lee mContactInfoCache.invalidate(); 31170bb286f79696fc3a3ee8a57a038a9f56087d902Andrew Lee mBlockedIdCache.clear(); 31294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng } 31394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng 314b980fc4386cdc24a605fc682d0fef0c5dc54c327Andrew Lee public void onResume() { 315142362f8253e7456640c14d6acaf1969afc4b68dYorke Lee if (PermissionsUtil.hasPermission(mContext, android.Manifest.permission.READ_CONTACTS)) { 316142362f8253e7456640c14d6acaf1969afc4b68dYorke Lee mContactInfoCache.start(); 317142362f8253e7456640c14d6acaf1969afc4b68dYorke Lee } 3185f1c7dbf86603f534fbacdc96bab30d683913f4fBrandon Maxwell mContactsPreferences.refreshValue(ContactsPreferences.DISPLAY_ORDER_KEY); 319142362f8253e7456640c14d6acaf1969afc4b68dYorke Lee } 320142362f8253e7456640c14d6acaf1969afc4b68dYorke Lee 3212d588b857347fda465a963742c4f61e4014f3441Nancy Chen public void onPause() { 3222d588b857347fda465a963742c4f61e4014f3441Nancy Chen pauseCache(); 323b67294e72e074ee5b67c692f6674cee296fe8927Andrew Lee 324b67294e72e074ee5b67c692f6674cee296fe8927Andrew Lee // Clear blocked id cache so that changes in blocked status will be reflected in the UI. 325b67294e72e074ee5b67c692f6674cee296fe8927Andrew Lee mBlockedIdCache.clear(); 326b67294e72e074ee5b67c692f6674cee296fe8927Andrew Lee 3272d588b857347fda465a963742c4f61e4014f3441Nancy Chen if (mHiddenItemUri != null) { 3282d588b857347fda465a963742c4f61e4014f3441Nancy Chen CallLogAsyncTaskUtil.deleteVoicemail(mContext, mHiddenItemUri, null); 3292d588b857347fda465a963742c4f61e4014f3441Nancy Chen } 3302d588b857347fda465a963742c4f61e4014f3441Nancy Chen } 3312d588b857347fda465a963742c4f61e4014f3441Nancy Chen 3322d588b857347fda465a963742c4f61e4014f3441Nancy Chen @VisibleForTesting 3332d588b857347fda465a963742c4f61e4014f3441Nancy Chen /* package */ void pauseCache() { 33474479d448bc39c3534585a627fba603aa89e93caAndrew Lee mContactInfoCache.stop(); 335d3f6a6c56dec7d47bae1121ed1030f67c26736feAndrew Lee mTelecomCallLogCache.reset(); 33694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng } 33794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng 33894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng @Override 33994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng protected void addGroups(Cursor cursor) { 34094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng mCallLogGroupBuilder.addGroups(cursor); 34194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng } 34294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng 34394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng @Override 344492cd7371c6d8fddc4de85887a4ed9a89d602767Andrew Lee public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 345a4adb2c035690a1c9600a20c2485886d9d5991d0Andrew Lee if (viewType == VIEW_TYPE_VOICEMAIL_PROMO_CARD) { 346bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen return createVoicemailPromoCardViewHolder(parent); 34769705be50fc4c84b35df88c879dd9a4b4de655b3Andrew Lee } 3489afa723dcebf18759c63dc1c976b05050e348d2aTyler Gunn return createCallLogEntryViewHolder(parent); 3499afa723dcebf18759c63dc1c976b05050e348d2aTyler Gunn } 3509afa723dcebf18759c63dc1c976b05050e348d2aTyler Gunn 3519afa723dcebf18759c63dc1c976b05050e348d2aTyler Gunn /** 3529afa723dcebf18759c63dc1c976b05050e348d2aTyler Gunn * Creates a new call log entry {@link ViewHolder}. 3539afa723dcebf18759c63dc1c976b05050e348d2aTyler Gunn * 3549afa723dcebf18759c63dc1c976b05050e348d2aTyler Gunn * @param parent the parent view. 3559afa723dcebf18759c63dc1c976b05050e348d2aTyler Gunn * @return The {@link ViewHolder}. 3569afa723dcebf18759c63dc1c976b05050e348d2aTyler Gunn */ 3579afa723dcebf18759c63dc1c976b05050e348d2aTyler Gunn private ViewHolder createCallLogEntryViewHolder(ViewGroup parent) { 358492cd7371c6d8fddc4de85887a4ed9a89d602767Andrew Lee LayoutInflater inflater = LayoutInflater.from(mContext); 3592ff08a8f8d4762ab5d0aebb0b69079f0b8d20b3eYorke Lee View view = inflater.inflate(R.layout.call_log_list_item, parent, false); 360c1b7d0ae8cdfc0f0dddb5c2bb45c8239ffc6a264Andrew Lee CallLogListItemViewHolder viewHolder = CallLogListItemViewHolder.create( 361c1b7d0ae8cdfc0f0dddb5c2bb45c8239ffc6a264Andrew Lee view, 362c1b7d0ae8cdfc0f0dddb5c2bb45c8239ffc6a264Andrew Lee mContext, 363bae7b937b6cf6e7eb26d07bec95de38083923614Andrew Lee mExpandCollapseListener, 364d3f6a6c56dec7d47bae1121ed1030f67c26736feAndrew Lee mTelecomCallLogCache, 365d3f6a6c56dec7d47bae1121ed1030f67c26736feAndrew Lee mCallLogListItemHelper, 3669bd094118e920b732394c29657f26b062f3e916bAnne Rong mVoicemailPlaybackPresenter, 3678d0847ca13ca46730756e1d3a3dff3d7d27fd18bAndrew Lee mFilteredNumberAsyncQueryHandler, 3688d0847ca13ca46730756e1d3a3dff3d7d27fd18bAndrew Lee this); 369affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee 370affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee viewHolder.callLogEntryView.setTag(viewHolder); 371affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee viewHolder.callLogEntryView.setAccessibilityDelegate(mAccessibilityDelegate); 372affe8b7947dd58edc3d9f4685a3bdde53f46762bAndrew Lee 373c1b7d0ae8cdfc0f0dddb5c2bb45c8239ffc6a264Andrew Lee viewHolder.primaryActionView.setTag(viewHolder); 374c987e00fa84f8997c07e8cb2d413897ae1d41b14Andrew Lee 375c1b7d0ae8cdfc0f0dddb5c2bb45c8239ffc6a264Andrew Lee return viewHolder; 37694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng } 37794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng 37894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng /** 37994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * Binds the views in the entry to the data in the call log. 380a9a82f52cbcadd0b9a4aafa0c785c0d6af629f1cSantos Cordon * TODO: This gets called 20-30 times when Dialer starts up for a single call log entry and 381a9a82f52cbcadd0b9a4aafa0c785c0d6af629f1cSantos Cordon * should not. It invokes cross-process methods and the repeat execution can get costly. 38294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * 383a482522fb8fe4e9959c749f4ec616ae59cf06b28Brandon Maxwell * @param viewHolder The view corresponding to this entry. 384bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen * @param position The position of the entry. 38594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng */ 386492cd7371c6d8fddc4de85887a4ed9a89d602767Andrew Lee public void onBindViewHolder(ViewHolder viewHolder, int position) { 38749efd91e50a11dc7bdef8382a0ceac01bc060f77Andrew Lee Trace.beginSection("onBindViewHolder: " + position); 388bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen 389bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen switch (getItemViewType(position)) { 390bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen case VIEW_TYPE_VOICEMAIL_PROMO_CARD: 391bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen bindVoicemailPromoCardViewHolder(viewHolder); 392bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen break; 393bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen default: 394bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen bindCallLogListViewHolder(viewHolder, position); 395bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen break; 396bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen } 397bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen 398bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen Trace.endSection(); 399bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen } 400bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen 401bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen /** 402bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen * Binds the promo card view holder. 403bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen * 404bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen * @param viewHolder The promo card view holder. 405bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen */ 406bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen protected void bindVoicemailPromoCardViewHolder(ViewHolder viewHolder) { 407bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen PromoCardViewHolder promoCardViewHolder = (PromoCardViewHolder) viewHolder; 408bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen 409ab90a18e2f05c7ae4158b770a9fbe9cbe4544597Andrew Lee promoCardViewHolder.getSecondaryActionView() 410ab90a18e2f05c7ae4158b770a9fbe9cbe4544597Andrew Lee .setOnClickListener(mVoicemailSettingsActionListener); 411ab90a18e2f05c7ae4158b770a9fbe9cbe4544597Andrew Lee promoCardViewHolder.getPrimaryActionView().setOnClickListener(mOkActionListener); 412bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen } 413bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen 414bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen /** 415bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen * Binds the view holder for the call log list item view. 416bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen * 417bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen * @param viewHolder The call log list item view holder. 418bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen * @param position The position of the list item. 419bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen */ 420bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen 421bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen private void bindCallLogListViewHolder(ViewHolder viewHolder, int position) { 422492cd7371c6d8fddc4de85887a4ed9a89d602767Andrew Lee Cursor c = (Cursor) getItem(position); 423492cd7371c6d8fddc4de85887a4ed9a89d602767Andrew Lee if (c == null) { 424492cd7371c6d8fddc4de85887a4ed9a89d602767Andrew Lee return; 425492cd7371c6d8fddc4de85887a4ed9a89d602767Andrew Lee } 426bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen 427492cd7371c6d8fddc4de85887a4ed9a89d602767Andrew Lee int count = getGroupSize(position); 428492cd7371c6d8fddc4de85887a4ed9a89d602767Andrew Lee 42994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng final String number = c.getString(CallLogQuery.NUMBER); 430719a7adde25e0a717816b00668c16c3a1e3c5518Jay Shrauner final int numberPresentation = c.getInt(CallLogQuery.NUMBER_PRESENTATION); 431b2eebafbc1f1e26b5178b2858ca335467b4bc341Nancy Chen final PhoneAccountHandle accountHandle = PhoneAccountUtils.getAccount( 432b2eebafbc1f1e26b5178b2858ca335467b4bc341Nancy Chen c.getString(CallLogQuery.ACCOUNT_COMPONENT_NAME), 433b2eebafbc1f1e26b5178b2858ca335467b4bc341Nancy Chen c.getString(CallLogQuery.ACCOUNT_ID)); 43494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng final String countryIso = c.getString(CallLogQuery.COUNTRY_ISO); 435a482522fb8fe4e9959c749f4ec616ae59cf06b28Brandon Maxwell final ContactInfo cachedContactInfo = ContactInfoHelper.getContactInfo(c); 43656cb0efa5eda1670077e66fc0e8c79478d0c1c67Yorke Lee final boolean isVoicemailNumber = 437d3f6a6c56dec7d47bae1121ed1030f67c26736feAndrew Lee mTelecomCallLogCache.isVoicemailNumber(accountHandle, number); 43856cb0efa5eda1670077e66fc0e8c79478d0c1c67Yorke Lee 43914cfa66d6df53303c280194d661c0b32838aa417Andrew Lee // Note: Binding of the action buttons is done as required in configureActionViews when the 44014cfa66d6df53303c280194d661c0b32838aa417Andrew Lee // user expands the actions ViewStub. 441146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn 44274479d448bc39c3534585a627fba603aa89e93caAndrew Lee ContactInfo info = ContactInfo.EMPTY; 443d3f6a6c56dec7d47bae1121ed1030f67c26736feAndrew Lee if (PhoneNumberUtil.canPlaceCallsTo(number, numberPresentation) && !isVoicemailNumber) { 44474479d448bc39c3534585a627fba603aa89e93caAndrew Lee // Lookup contacts with this number 44574479d448bc39c3534585a627fba603aa89e93caAndrew Lee info = mContactInfoCache.getValue(number, countryIso, cachedContactInfo); 44694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng } 4471e5325f43c98a92f8bfec1dbd9db3d32a91835e9Ihab Awad CharSequence formattedNumber = info.formattedNumber == null 4484f8c39ab99b575cf6e2eb8ea3a9847d51603e244Brian Attwell ? null : PhoneNumberUtils.createTtsSpannable(info.formattedNumber); 449edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee 450edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee final PhoneCallDetails details = new PhoneCallDetails( 451edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee mContext, number, numberPresentation, formattedNumber, isVoicemailNumber); 452edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee details.accountHandle = accountHandle; 453edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee details.callTypes = getCallTypes(c, count); 454edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee details.countryIso = countryIso; 455edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee details.date = c.getLong(CallLogQuery.DATE); 456edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee details.duration = c.getLong(CallLogQuery.DURATION); 457edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee details.features = getCallFeatures(c, count); 458edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee details.geocode = c.getString(CallLogQuery.GEOCODED_LOCATION); 459edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee details.transcription = c.getString(CallLogQuery.TRANSCRIPTION); 46003aaf3894d8af53f241d1189c504e44c538100d4Nancy Chen if (details.callTypes[0] == CallLog.Calls.VOICEMAIL_TYPE) { 46103aaf3894d8af53f241d1189c504e44c538100d4Nancy Chen details.isRead = c.getInt(CallLogQuery.IS_READ) == 1; 46203aaf3894d8af53f241d1189c504e44c538100d4Nancy Chen } 463edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee 4648b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn if (!c.isNull(CallLogQuery.DATA_USAGE)) { 465edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee details.dataUsage = c.getLong(CallLogQuery.DATA_USAGE); 4668b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn } 4678b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn 46836aeec91ed927b7fe3a27bcd5e224443899117f1Brandon Maxwell if (!TextUtils.isEmpty(info.name) || !TextUtils.isEmpty(info.nameAlternative)) { 469edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee details.contactUri = info.lookupUri; 47036aeec91ed927b7fe3a27bcd5e224443899117f1Brandon Maxwell details.namePrimary = info.name; 47136aeec91ed927b7fe3a27bcd5e224443899117f1Brandon Maxwell details.nameAlternative = info.nameAlternative; 47236aeec91ed927b7fe3a27bcd5e224443899117f1Brandon Maxwell details.nameDisplayOrder = mContactsPreferences.getDisplayOrder(); 473edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee details.numberType = info.type; 474edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee details.numberLabel = info.label; 475edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee details.photoUri = info.photoUri; 476edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee details.sourceType = info.sourceType; 4772f05af35af03de67c1c474cd148719b24fac3552Andrew Lee details.objectId = info.objectId; 478edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee } 479704acc087ce359295475a46695c2821c55778344Chiao Cheng 48070bb286f79696fc3a3ee8a57a038a9f56087d902Andrew Lee final CallLogListItemViewHolder views = (CallLogListItemViewHolder) viewHolder; 4815a9cd71b8ea670cd7c9aebd3dba27ea8cbe769dfAndrew Lee views.info = info; 482edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee views.rowId = c.getLong(CallLogQuery.ID); 483edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee // Store values used when the actions ViewStub is inflated on expansion. 484edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee views.number = number; 48518b4a2e3b8d60df39b3489c76bf4edffb81e15a5Tyler Gunn views.displayNumber = details.displayNumber; 486edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee views.numberPresentation = numberPresentation; 487edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee views.callType = c.getInt(CallLogQuery.CALL_TYPE); 488edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee views.accountHandle = accountHandle; 489edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee views.voicemailUri = c.getString(CallLogQuery.VOICEMAIL_URI); 490edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee // Stash away the Ids of the calls so that we can support deleting a row in the call log. 491edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee views.callIds = getCallIds(c, count); 49218b4a2e3b8d60df39b3489c76bf4edffb81e15a5Tyler Gunn views.isBusiness = mContactInfoHelper.isBusiness(info.sourceType); 49318b4a2e3b8d60df39b3489c76bf4edffb81e15a5Tyler Gunn views.numberType = (String) Phone.getTypeLabel(mContext.getResources(), details.numberType, 49418b4a2e3b8d60df39b3489c76bf4edffb81e15a5Tyler Gunn details.numberLabel); 495edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee // Default case: an item in the call log. 496edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee views.primaryActionView.setVisibility(View.VISIBLE); 4979686330691f1216edff0ffa779138bda43388c47Sai Cheemalapati 498edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee // Check if the day group has changed and display a header if necessary. 499edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee int currentGroup = getDayGroupForCall(views.rowId); 500edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee int previousGroup = getPreviousDayGroup(c); 501edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee if (currentGroup != previousGroup) { 502edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee views.dayGroupHeader.setVisibility(View.VISIBLE); 503edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee views.dayGroupHeader.setText(getGroupDescription(currentGroup)); 50494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng } else { 505edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee views.dayGroupHeader.setVisibility(View.GONE); 50694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng } 50794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng 508d3f6a6c56dec7d47bae1121ed1030f67c26736feAndrew Lee mCallLogListItemHelper.setPhoneCallDetails(views, details); 509b0b57a10fbb9bec5c80d7adad8f65750a2f96e1bAndrew Lee 510edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee if (mCurrentlyExpandedRowId == views.rowId) { 511158dfa2dcb89db772f61af6f1f6775fcf5695e60Andrew Lee // In case ViewHolders were added/removed, update the expanded position if the rowIds 512158dfa2dcb89db772f61af6f1f6775fcf5695e60Andrew Lee // match so that we can restore the correct expanded state on rebind. 513158dfa2dcb89db772f61af6f1f6775fcf5695e60Andrew Lee mCurrentlyExpandedPosition = position; 514edb22da2b40549631a08150cbfc205e6ad243c20Andrew Lee } 515049203f6f27e66581133e7c1550bfe73e2ca50cfYorke Lee 51670bb286f79696fc3a3ee8a57a038a9f56087d902Andrew Lee // Update the photo, once we know whether the user's number is blocked or not. 51770bb286f79696fc3a3ee8a57a038a9f56087d902Andrew Lee final NumberWithCountryIso blockedIdKey = new NumberWithCountryIso(number, countryIso); 51870bb286f79696fc3a3ee8a57a038a9f56087d902Andrew Lee if (mBlockedIdCache.containsKey(blockedIdKey)) { 51970bb286f79696fc3a3ee8a57a038a9f56087d902Andrew Lee views.blockId = mBlockedIdCache.get(blockedIdKey); 52070bb286f79696fc3a3ee8a57a038a9f56087d902Andrew Lee views.updatePhoto(); 52170bb286f79696fc3a3ee8a57a038a9f56087d902Andrew Lee } else { 52270bb286f79696fc3a3ee8a57a038a9f56087d902Andrew Lee views.blockId = null; 52370bb286f79696fc3a3ee8a57a038a9f56087d902Andrew Lee boolean failed = mFilteredNumberAsyncQueryHandler.startBlockedQuery( 52470bb286f79696fc3a3ee8a57a038a9f56087d902Andrew Lee new OnCheckBlockedListener() { 52570bb286f79696fc3a3ee8a57a038a9f56087d902Andrew Lee @Override 52670bb286f79696fc3a3ee8a57a038a9f56087d902Andrew Lee public void onCheckComplete(Integer id) { 52770bb286f79696fc3a3ee8a57a038a9f56087d902Andrew Lee mBlockedIdCache.put(blockedIdKey, id); 52870bb286f79696fc3a3ee8a57a038a9f56087d902Andrew Lee views.blockId = id; 52970bb286f79696fc3a3ee8a57a038a9f56087d902Andrew Lee views.updatePhoto(); 53070bb286f79696fc3a3ee8a57a038a9f56087d902Andrew Lee } 53170bb286f79696fc3a3ee8a57a038a9f56087d902Andrew Lee }, null, number, countryIso); 53270bb286f79696fc3a3ee8a57a038a9f56087d902Andrew Lee if (failed) { 53370bb286f79696fc3a3ee8a57a038a9f56087d902Andrew Lee views.updatePhoto(); 53470bb286f79696fc3a3ee8a57a038a9f56087d902Andrew Lee } 53570bb286f79696fc3a3ee8a57a038a9f56087d902Andrew Lee } 53670bb286f79696fc3a3ee8a57a038a9f56087d902Andrew Lee 5372f05af35af03de67c1c474cd148719b24fac3552Andrew Lee views.showActions(mCurrentlyExpandedPosition == position); 53856cb0efa5eda1670077e66fc0e8c79478d0c1c67Yorke Lee 539d3f6a6c56dec7d47bae1121ed1030f67c26736feAndrew Lee mCallLogListItemHelper.setPhoneCallDetails(views, details); 540c5b6a693d4773214ff8d3fcfa43d0a29581bb886Chiao Cheng } 541c5b6a693d4773214ff8d3fcfa43d0a29581bb886Chiao Cheng 5425f1c7dbf86603f534fbacdc96bab30d683913f4fBrandon Maxwell private String getPreferredDisplayName(ContactInfo contactInfo) { 5435f1c7dbf86603f534fbacdc96bab30d683913f4fBrandon Maxwell if (mContactsPreferences.getDisplayOrder() == ContactsPreferences.DISPLAY_ORDER_PRIMARY || 5445f1c7dbf86603f534fbacdc96bab30d683913f4fBrandon Maxwell TextUtils.isEmpty(contactInfo.nameAlternative)) { 5455f1c7dbf86603f534fbacdc96bab30d683913f4fBrandon Maxwell return contactInfo.name; 5465f1c7dbf86603f534fbacdc96bab30d683913f4fBrandon Maxwell } 5475f1c7dbf86603f534fbacdc96bab30d683913f4fBrandon Maxwell return contactInfo.nameAlternative; 5485f1c7dbf86603f534fbacdc96bab30d683913f4fBrandon Maxwell } 5495f1c7dbf86603f534fbacdc96bab30d683913f4fBrandon Maxwell 55069705be50fc4c84b35df88c879dd9a4b4de655b3Andrew Lee @Override 55169705be50fc4c84b35df88c879dd9a4b4de655b3Andrew Lee public int getItemCount() { 5522d588b857347fda465a963742c4f61e4014f3441Nancy Chen return super.getItemCount() + (mShowVoicemailPromoCard ? 1 : 0) 5532d588b857347fda465a963742c4f61e4014f3441Nancy Chen - (mHiddenPosition != RecyclerView.NO_POSITION ? 1 : 0); 55469705be50fc4c84b35df88c879dd9a4b4de655b3Andrew Lee } 55569705be50fc4c84b35df88c879dd9a4b4de655b3Andrew Lee 55669705be50fc4c84b35df88c879dd9a4b4de655b3Andrew Lee @Override 55769705be50fc4c84b35df88c879dd9a4b4de655b3Andrew Lee public int getItemViewType(int position) { 558a4adb2c035690a1c9600a20c2485886d9d5991d0Andrew Lee if (position == VOICEMAIL_PROMO_CARD_POSITION && mShowVoicemailPromoCard) { 559bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen return VIEW_TYPE_VOICEMAIL_PROMO_CARD; 56069705be50fc4c84b35df88c879dd9a4b4de655b3Andrew Lee } 56169705be50fc4c84b35df88c879dd9a4b4de655b3Andrew Lee return super.getItemViewType(position); 56269705be50fc4c84b35df88c879dd9a4b4de655b3Andrew Lee } 56369705be50fc4c84b35df88c879dd9a4b4de655b3Andrew Lee 564bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen /** 565bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen * Retrieves an item at the specified position, taking into account the presence of a promo 566bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen * card. 567bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen * 568bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen * @param position The position to retrieve. 569bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen * @return The item at that position. 570bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen */ 571bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen @Override 572bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen public Object getItem(int position) { 5732d588b857347fda465a963742c4f61e4014f3441Nancy Chen return super.getItem(position - (mShowVoicemailPromoCard ? 1 : 0) 5742d588b857347fda465a963742c4f61e4014f3441Nancy Chen + ((mHiddenPosition != RecyclerView.NO_POSITION && position >= mHiddenPosition) 5752d588b857347fda465a963742c4f61e4014f3441Nancy Chen ? 1 : 0)); 576bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen } 577bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen 5780599e880630892becf1a1991e6712e0e6d9df3c8Andrew Lee @Override 5790599e880630892becf1a1991e6712e0e6d9df3c8Andrew Lee public int getGroupSize(int position) { 5800599e880630892becf1a1991e6712e0e6d9df3c8Andrew Lee return super.getGroupSize(position - (mShowVoicemailPromoCard ? 1 : 0)); 5810599e880630892becf1a1991e6712e0e6d9df3c8Andrew Lee } 5820599e880630892becf1a1991e6712e0e6d9df3c8Andrew Lee 583a4adb2c035690a1c9600a20c2485886d9d5991d0Andrew Lee protected boolean isCallLogActivity() { 584a4adb2c035690a1c9600a20c2485886d9d5991d0Andrew Lee return mIsCallLogActivity; 58569705be50fc4c84b35df88c879dd9a4b4de655b3Andrew Lee } 58669705be50fc4c84b35df88c879dd9a4b4de655b3Andrew Lee 5872d588b857347fda465a963742c4f61e4014f3441Nancy Chen /** 5882d588b857347fda465a963742c4f61e4014f3441Nancy Chen * In order to implement the "undo" function, when a voicemail is "deleted" i.e. when the user 5892d588b857347fda465a963742c4f61e4014f3441Nancy Chen * clicks the delete button, the deleted item is temporarily hidden from the list. If a user 5902d588b857347fda465a963742c4f61e4014f3441Nancy Chen * clicks delete on a second item before the first item's undo option has expired, the first 5912d588b857347fda465a963742c4f61e4014f3441Nancy Chen * item is immediately deleted so that only one item can be "undoed" at a time. 5922d588b857347fda465a963742c4f61e4014f3441Nancy Chen */ 5930bb059d61f1e6648dee6f0a4cf8f02a6a7c26ce7Yorke Lee @Override 5940bb059d61f1e6648dee6f0a4cf8f02a6a7c26ce7Yorke Lee public void onVoicemailDeleted(Uri uri) { 5952d588b857347fda465a963742c4f61e4014f3441Nancy Chen if (mHiddenItemUri == null) { 5962d588b857347fda465a963742c4f61e4014f3441Nancy Chen // Immediately hide the currently expanded card. 5972d588b857347fda465a963742c4f61e4014f3441Nancy Chen mHiddenPosition = mCurrentlyExpandedPosition; 5982d588b857347fda465a963742c4f61e4014f3441Nancy Chen notifyDataSetChanged(); 5992d588b857347fda465a963742c4f61e4014f3441Nancy Chen } else { 6002d588b857347fda465a963742c4f61e4014f3441Nancy Chen // This means that there was a previous item that was hidden in the UI but not 6012d588b857347fda465a963742c4f61e4014f3441Nancy Chen // yet deleted from the database (call it a "pending delete"). Delete this previous item 6022d588b857347fda465a963742c4f61e4014f3441Nancy Chen // now since it is only possible to do one "undo" at a time. 6032d588b857347fda465a963742c4f61e4014f3441Nancy Chen CallLogAsyncTaskUtil.deleteVoicemail(mContext, mHiddenItemUri, null); 6042d588b857347fda465a963742c4f61e4014f3441Nancy Chen 6052d588b857347fda465a963742c4f61e4014f3441Nancy Chen // Set pending hide action so that the current item is hidden only after the previous 6062d588b857347fda465a963742c4f61e4014f3441Nancy Chen // item is permanently deleted. 6072d588b857347fda465a963742c4f61e4014f3441Nancy Chen mPendingHide = true; 6082d588b857347fda465a963742c4f61e4014f3441Nancy Chen } 6092d588b857347fda465a963742c4f61e4014f3441Nancy Chen 6102d588b857347fda465a963742c4f61e4014f3441Nancy Chen collapseExpandedCard(); 6112d588b857347fda465a963742c4f61e4014f3441Nancy Chen 6122d588b857347fda465a963742c4f61e4014f3441Nancy Chen // Save the new hidden item uri in case it needs to be deleted from the database when 6132d588b857347fda465a963742c4f61e4014f3441Nancy Chen // a user attempts to delete another item. 6142d588b857347fda465a963742c4f61e4014f3441Nancy Chen mHiddenItemUri = uri; 6152d588b857347fda465a963742c4f61e4014f3441Nancy Chen } 6162d588b857347fda465a963742c4f61e4014f3441Nancy Chen 6172d588b857347fda465a963742c4f61e4014f3441Nancy Chen private void collapseExpandedCard() { 6180bb059d61f1e6648dee6f0a4cf8f02a6a7c26ce7Yorke Lee mCurrentlyExpandedRowId = NO_EXPANDED_LIST_ITEM; 6190bb059d61f1e6648dee6f0a4cf8f02a6a7c26ce7Yorke Lee mCurrentlyExpandedPosition = RecyclerView.NO_POSITION; 6200bb059d61f1e6648dee6f0a4cf8f02a6a7c26ce7Yorke Lee } 6210bb059d61f1e6648dee6f0a4cf8f02a6a7c26ce7Yorke Lee 622146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn /** 6232d588b857347fda465a963742c4f61e4014f3441Nancy Chen * When the user clicks "undo", the hidden item is unhidden. 6242d588b857347fda465a963742c4f61e4014f3441Nancy Chen */ 6252d588b857347fda465a963742c4f61e4014f3441Nancy Chen @Override 6262d588b857347fda465a963742c4f61e4014f3441Nancy Chen public void onVoicemailDeleteUndo() { 6272d588b857347fda465a963742c4f61e4014f3441Nancy Chen mHiddenPosition = RecyclerView.NO_POSITION; 6282d588b857347fda465a963742c4f61e4014f3441Nancy Chen mHiddenItemUri = null; 6292d588b857347fda465a963742c4f61e4014f3441Nancy Chen 6302d588b857347fda465a963742c4f61e4014f3441Nancy Chen mPendingHide = false; 6312d588b857347fda465a963742c4f61e4014f3441Nancy Chen notifyDataSetChanged(); 6322d588b857347fda465a963742c4f61e4014f3441Nancy Chen } 6332d588b857347fda465a963742c4f61e4014f3441Nancy Chen 6342d588b857347fda465a963742c4f61e4014f3441Nancy Chen /** 6352d588b857347fda465a963742c4f61e4014f3441Nancy Chen * This callback signifies that a database deletion has completed. This means that if there is 6362d588b857347fda465a963742c4f61e4014f3441Nancy Chen * an item pending deletion, it will be hidden because the previous item that was in "undo" mode 6372d588b857347fda465a963742c4f61e4014f3441Nancy Chen * has been removed from the database. Otherwise it simply resets the hidden state because there 6382d588b857347fda465a963742c4f61e4014f3441Nancy Chen * are no pending deletes and thus no hidden items. 6392d588b857347fda465a963742c4f61e4014f3441Nancy Chen */ 6402d588b857347fda465a963742c4f61e4014f3441Nancy Chen @Override 6412d588b857347fda465a963742c4f61e4014f3441Nancy Chen public void onVoicemailDeletedInDatabase() { 6422d588b857347fda465a963742c4f61e4014f3441Nancy Chen if (mPendingHide) { 6432d588b857347fda465a963742c4f61e4014f3441Nancy Chen mHiddenPosition = mCurrentlyExpandedPosition; 6442d588b857347fda465a963742c4f61e4014f3441Nancy Chen mPendingHide = false; 6452d588b857347fda465a963742c4f61e4014f3441Nancy Chen } else { 6462d588b857347fda465a963742c4f61e4014f3441Nancy Chen // There should no longer be any hidden item because it has been deleted from the 6472d588b857347fda465a963742c4f61e4014f3441Nancy Chen // database. 6482d588b857347fda465a963742c4f61e4014f3441Nancy Chen mHiddenPosition = RecyclerView.NO_POSITION; 6492d588b857347fda465a963742c4f61e4014f3441Nancy Chen mHiddenItemUri = null; 6502d588b857347fda465a963742c4f61e4014f3441Nancy Chen } 6512d588b857347fda465a963742c4f61e4014f3441Nancy Chen } 6522d588b857347fda465a963742c4f61e4014f3441Nancy Chen 6538d0847ca13ca46730756e1d3a3dff3d7d27fd18bAndrew Lee @Override 6548d0847ca13ca46730756e1d3a3dff3d7d27fd18bAndrew Lee public void onChangeFilteredNumberSuccess() { 6558d0847ca13ca46730756e1d3a3dff3d7d27fd18bAndrew Lee mBlockedIdCache.clear(); 6568d0847ca13ca46730756e1d3a3dff3d7d27fd18bAndrew Lee notifyDataSetChanged(); 6578d0847ca13ca46730756e1d3a3dff3d7d27fd18bAndrew Lee } 6588d0847ca13ca46730756e1d3a3dff3d7d27fd18bAndrew Lee 6598d0847ca13ca46730756e1d3a3dff3d7d27fd18bAndrew Lee @Override 6608d0847ca13ca46730756e1d3a3dff3d7d27fd18bAndrew Lee public void onChangeFilteredNumberUndo() { 6618d0847ca13ca46730756e1d3a3dff3d7d27fd18bAndrew Lee mBlockedIdCache.clear(); 6628d0847ca13ca46730756e1d3a3dff3d7d27fd18bAndrew Lee notifyDataSetChanged(); 6638d0847ca13ca46730756e1d3a3dff3d7d27fd18bAndrew Lee } 6648d0847ca13ca46730756e1d3a3dff3d7d27fd18bAndrew Lee 6652d588b857347fda465a963742c4f61e4014f3441Nancy Chen /** 6664dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn * Retrieves the day group of the previous call in the call log. Used to determine if the day 6674dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn * group has changed and to trigger display of the day group text. 6684dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn * 6694dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn * @param cursor The call log cursor. 6704dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn * @return The previous day group, or DAY_GROUP_NONE if this is the first call. 6714dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn */ 6724dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn private int getPreviousDayGroup(Cursor cursor) { 6734dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn // We want to restore the position in the cursor at the end. 6744dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn int startingPosition = cursor.getPosition(); 6754dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn int dayGroup = CallLogGroupBuilder.DAY_GROUP_NONE; 6764dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn if (cursor.moveToPrevious()) { 6772d588b857347fda465a963742c4f61e4014f3441Nancy Chen // If the previous entry is hidden (deleted in the UI but not in the database), skip it 6782d588b857347fda465a963742c4f61e4014f3441Nancy Chen // and check the card above it. A list with the voicemail promo card at the top will be 6792d588b857347fda465a963742c4f61e4014f3441Nancy Chen // 1-indexed because the 0th index is the promo card iteself. 6802d588b857347fda465a963742c4f61e4014f3441Nancy Chen int previousViewPosition = mShowVoicemailPromoCard ? startingPosition : 6812d588b857347fda465a963742c4f61e4014f3441Nancy Chen startingPosition - 1; 6822d588b857347fda465a963742c4f61e4014f3441Nancy Chen if (previousViewPosition != mHiddenPosition || 6832d588b857347fda465a963742c4f61e4014f3441Nancy Chen (previousViewPosition == mHiddenPosition && cursor.moveToPrevious())) { 6842d588b857347fda465a963742c4f61e4014f3441Nancy Chen long previousRowId = cursor.getLong(CallLogQuery.ID); 6852d588b857347fda465a963742c4f61e4014f3441Nancy Chen dayGroup = getDayGroupForCall(previousRowId); 6862d588b857347fda465a963742c4f61e4014f3441Nancy Chen } 6874dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn } 6884dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn cursor.moveToPosition(startingPosition); 6894dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn return dayGroup; 6904dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn } 6914dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn 6924dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn /** 6934dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn * Given a call Id, look up the day group that the call belongs to. The day group data is 6944dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn * populated in {@link com.android.dialer.calllog.CallLogGroupBuilder}. 6954dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn * 6964dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn * @param callId The call to retrieve the day group for. 6974dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn * @return The day group for the call. 6984dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn */ 6994dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn private int getDayGroupForCall(long callId) { 7004dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn if (mDayGroups.containsKey(callId)) { 7014dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn return mDayGroups.get(callId); 7024dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn } 7034dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn return CallLogGroupBuilder.DAY_GROUP_NONE; 7044dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn } 70581c3829f8a9377cb2e93c1fa6d223d223b78f371Andrew Lee 7064dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn /** 70794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * Returns the call types for the given number of items in the cursor. 70894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * <p> 70994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * It uses the next {@code count} rows in the cursor to extract the types. 71094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * <p> 71194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * It position in the cursor is unchanged by this function. 71294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng */ 71394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng private int[] getCallTypes(Cursor cursor, int count) { 71494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng int position = cursor.getPosition(); 71594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng int[] callTypes = new int[count]; 71694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng for (int index = 0; index < count; ++index) { 71794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng callTypes[index] = cursor.getInt(CallLogQuery.CALL_TYPE); 71894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng cursor.moveToNext(); 71994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng } 72094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng cursor.moveToPosition(position); 72194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng return callTypes; 72294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng } 72394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng 7248b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn /** 7258b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn * Determine the features which were enabled for any of the calls that make up a call log 7268b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn * entry. 7278b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn * 7288b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn * @param cursor The cursor. 7298b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn * @param count The number of calls for the current call log entry. 7308b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn * @return The features. 7318b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn */ 7328b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn private int getCallFeatures(Cursor cursor, int count) { 73303610993bf2adf12a6962c32851095551ffd0043Yorke Lee int features = 0; 7348b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn int position = cursor.getPosition(); 7358b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn for (int index = 0; index < count; ++index) { 7368b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn features |= cursor.getInt(CallLogQuery.FEATURES); 7378b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn cursor.moveToNext(); 7388b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn } 7398b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn cursor.moveToPosition(position); 7408b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn return features; 7418b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn } 7428b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn 743d0715acdfc1aee0c20950741dc15d30abd18d2f2Tyler Gunn /** 74494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * Sets whether processing of requests for contact details should be enabled. 74574479d448bc39c3534585a627fba603aa89e93caAndrew Lee * 74694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * This method should be called in tests to disable such processing of requests when not 74794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * needed. 74894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng */ 74994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng @VisibleForTesting 75094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng void disableRequestProcessingForTest() { 75174479d448bc39c3534585a627fba603aa89e93caAndrew Lee // TODO: Remove this and test the cache directly. 752c16ea5ad67bf454158b364dec2f26c95a879c350Yorke Lee mContactInfoCache.disableRequestProcessing(); 75394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng } 75494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng 75594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng @VisibleForTesting 75694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng void injectContactInfoForTest(String number, String countryIso, ContactInfo contactInfo) { 75774479d448bc39c3534585a627fba603aa89e93caAndrew Lee // TODO: Remove this and test the cache directly. 75874479d448bc39c3534585a627fba603aa89e93caAndrew Lee mContactInfoCache.injectContactInfoForTest(number, countryIso, contactInfo); 75994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng } 76094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng 7614dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn /** 7624dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn * Stores the day group associated with a call in the call log. 7634dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn * 7644dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn * @param rowId The row Id of the current call. 7654dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn * @param dayGroup The day group the call belongs in. 7664dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn */ 7674dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn @Override 7684dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn public void setDayGroup(long rowId, int dayGroup) { 7694dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn if (!mDayGroups.containsKey(rowId)) { 7704dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn mDayGroups.put(rowId, dayGroup); 7714dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn } 7724dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn } 7734dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn 7744dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn /** 7754dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn * Clears the day group associations on re-bind of the call log. 7764dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn */ 7774dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn @Override 7784dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn public void clearDayGroups() { 7794dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn mDayGroups.clear(); 7804dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn } 7814dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn 782146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn /** 783146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn * Retrieves the call Ids represented by the current call log row. 784146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn * 785146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn * @param cursor Call log cursor to retrieve call Ids from. 786146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn * @param groupSize Number of calls associated with the current call log row. 787146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn * @return Array of call Ids. 788146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn */ 789cf5e001120916deb770ea65ae55730e456f92137Tyler Gunn private long[] getCallIds(final Cursor cursor, final int groupSize) { 790146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn // We want to restore the position in the cursor at the end. 791146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn int startingPosition = cursor.getPosition(); 792146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn long[] ids = new long[groupSize]; 793146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn // Copy the ids of the rows in the group. 794146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn for (int index = 0; index < groupSize; ++index) { 795146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn ids[index] = cursor.getLong(CallLogQuery.ID); 796146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn cursor.moveToNext(); 797146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn } 798146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn cursor.moveToPosition(startingPosition); 799146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn return ids; 800146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn } 801146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn 802146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn /** 8034dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn * Determines the description for a day group. 8044dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn * 8054dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn * @param group The day group to retrieve the description for. 8064dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn * @return The day group description. 8074dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn */ 8084dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn private CharSequence getGroupDescription(int group) { 8094dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn if (group == CallLogGroupBuilder.DAY_GROUP_TODAY) { 8101e273313ff938ba0c7294dade433736d3fc5876bTyler Gunn return mContext.getResources().getString(R.string.call_log_header_today); 8114dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn } else if (group == CallLogGroupBuilder.DAY_GROUP_YESTERDAY) { 8121e273313ff938ba0c7294dade433736d3fc5876bTyler Gunn return mContext.getResources().getString(R.string.call_log_header_yesterday); 8134dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn } else { 8144dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn return mContext.getResources().getString(R.string.call_log_header_other); 8154dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn } 8164dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn } 817bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen 818bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen /** 819bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen * Determines if the voicemail promo card should be shown or not. The voicemail promo card will 820bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen * be shown as the first item in the voicemail tab. 821bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen */ 822bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen private void maybeShowVoicemailPromoCard() { 823bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen boolean showPromoCard = mPrefs.getBoolean(SHOW_VOICEMAIL_PROMO_CARD, 824bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen SHOW_VOICEMAIL_PROMO_CARD_DEFAULT); 825a4adb2c035690a1c9600a20c2485886d9d5991d0Andrew Lee mShowVoicemailPromoCard = (mVoicemailPlaybackPresenter != null) && showPromoCard; 826bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen } 827bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen 828bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen /** 829bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen * Dismisses the voicemail promo card and refreshes the call log. 830bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen */ 831bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen private void dismissVoicemailPromoCard() { 832bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen mPrefs.edit().putBoolean(SHOW_VOICEMAIL_PROMO_CARD, false).apply(); 833a4adb2c035690a1c9600a20c2485886d9d5991d0Andrew Lee mShowVoicemailPromoCard = false; 834bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen notifyItemRemoved(VOICEMAIL_PROMO_CARD_POSITION); 835bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen } 836bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen 837bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen /** 838bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen * Creates the view holder for the voicemail promo card. 839bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen * 840bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen * @param parent The parent view. 841bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen * @return The {@link ViewHolder}. 842bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen */ 843bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen protected ViewHolder createVoicemailPromoCardViewHolder(ViewGroup parent) { 844bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen LayoutInflater inflater = LayoutInflater.from(mContext); 845bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen View view = inflater.inflate(R.layout.voicemail_promo_card, parent, false); 846bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen 847bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen PromoCardViewHolder viewHolder = PromoCardViewHolder.create(view); 848bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen return viewHolder; 849bdd2bc2efe22dc5b14cd2d3f5eb20350b69da875Nancy Chen } 85094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng} 851