CallLogAdapter.java revision c6fde8d1b9a4e586ca65b82e9911089a9da14508
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
1994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Chengimport android.content.Context;
20c5b6a693d4773214ff8d3fcfa43d0a29581bb886Chiao Chengimport android.content.Intent;
2194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Chengimport android.content.res.Resources;
2294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Chengimport android.database.Cursor;
2394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Chengimport android.net.Uri;
2474eb4ecc5df272f681b427760d46deafce8ed0b2Brian Attwellimport android.provider.ContactsContract.CommonDataKinds.Phone;
2594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Chengimport android.provider.ContactsContract.PhoneLookup;
269dc924c8bcc0bc8d996452e9ce3215b5f064962eTyler Gunnimport android.telecom.PhoneAccountHandle;
271e5325f43c98a92f8bfec1dbd9db3d32a91835e9Ihab Awadimport android.telephony.PhoneNumberUtils;
2894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Chengimport android.text.TextUtils;
2934b83c9a4d4911615a9822b630a674a8538634f0Jay Shraunerimport android.util.Log;
3094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Chengimport android.view.LayoutInflater;
3194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Chengimport android.view.View;
32b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Leeimport android.view.View.AccessibilityDelegate;
3394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Chengimport android.view.ViewGroup;
3494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Chengimport android.view.ViewTreeObserver;
35b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Leeimport android.view.accessibility.AccessibilityEvent;
36c5b6a693d4773214ff8d3fcfa43d0a29581bb886Chiao Chengimport android.widget.ImageView;
37c5b6a693d4773214ff8d3fcfa43d0a29581bb886Chiao Chengimport android.widget.TextView;
3894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
3994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Chengimport com.android.common.widget.GroupingListAdapter;
4035071c06d1587942f5a66c8f12e6247e8f904d26Chiao Chengimport com.android.contacts.common.util.UriUtils;
4194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Chengimport com.android.dialer.PhoneCallDetails;
4294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Chengimport com.android.dialer.PhoneCallDetailsHelper;
439554500572ba82fbd7adb0a1637206ef870ef09eChiao Chengimport com.android.dialer.R;
4474479d448bc39c3534585a627fba603aa89e93caAndrew Leeimport com.android.dialer.contactinfo.ContactInfoCache;
4574479d448bc39c3534585a627fba603aa89e93caAndrew Leeimport com.android.dialer.contactinfo.ContactInfoCache.OnContactInfoChangedListener;
467d20f8273886411ffc864231d59f780e450de3dbYorke Leeimport com.android.dialer.util.DialerUtils;
4756cb0efa5eda1670077e66fc0e8c79478d0c1c67Yorke Lee
4894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Chengimport com.google.common.annotations.VisibleForTesting;
4994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
50146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunnimport java.util.HashMap;
5194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
5294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng/**
5394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * Adapter class to fill in data for the Call Log.
5494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng */
55fb585079cc4c522c27f6dd6bf03fd296535960f3Yorke Leepublic class CallLogAdapter extends GroupingListAdapter
5694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        implements ViewTreeObserver.OnPreDrawListener, CallLogGroupBuilder.GroupCreator {
5734b83c9a4d4911615a9822b630a674a8538634f0Jay Shrauner    private static final String TAG = CallLogAdapter.class.getSimpleName();
58c5b6a693d4773214ff8d3fcfa43d0a29581bb886Chiao Cheng
59654df8fbbc7703c24aec687de902e2c72ba343ddYorke Lee    /** Interface used to inform a parent UI element that a list item has been expanded. */
60654df8fbbc7703c24aec687de902e2c72ba343ddYorke Lee    public interface CallItemExpandedListener {
61654df8fbbc7703c24aec687de902e2c72ba343ddYorke Lee        /**
622ff08a8f8d4762ab5d0aebb0b69079f0b8d20b3eYorke Lee         * @param view The {@link View} that represents the item that was clicked
63654df8fbbc7703c24aec687de902e2c72ba343ddYorke Lee         *         on.
64654df8fbbc7703c24aec687de902e2c72ba343ddYorke Lee         */
652ff08a8f8d4762ab5d0aebb0b69079f0b8d20b3eYorke Lee        public void onItemExpanded(View view);
668ef8020b8b792026a8dd15e029055f7d5e2d48f6Tyler Gunn
678ef8020b8b792026a8dd15e029055f7d5e2d48f6Tyler Gunn        /**
6868e771378889a479a80aac29a9ec2136b7ef27b6Tyler Gunn         * Retrieves the call log view for the specified call Id.  If the view is not currently
6968e771378889a479a80aac29a9ec2136b7ef27b6Tyler Gunn         * visible, returns null.
708ef8020b8b792026a8dd15e029055f7d5e2d48f6Tyler Gunn         *
7168e771378889a479a80aac29a9ec2136b7ef27b6Tyler Gunn         * @param callId The call Id.
7268e771378889a479a80aac29a9ec2136b7ef27b6Tyler Gunn         * @return The call log view.
738ef8020b8b792026a8dd15e029055f7d5e2d48f6Tyler Gunn         */
742ff08a8f8d4762ab5d0aebb0b69079f0b8d20b3eYorke Lee        public View getViewForCallId(long callId);
75654df8fbbc7703c24aec687de902e2c72ba343ddYorke Lee    }
76654df8fbbc7703c24aec687de902e2c72ba343ddYorke Lee
7794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    /** Interface used to initiate a refresh of the content. */
7894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    public interface CallFetcher {
7994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        public void fetchCalls();
8094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    }
8194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
829686330691f1216edff0ffa779138bda43388c47Sai Cheemalapati    /** Implements onClickListener for the report button. */
839686330691f1216edff0ffa779138bda43388c47Sai Cheemalapati    public interface OnReportButtonClickListener {
849686330691f1216edff0ffa779138bda43388c47Sai Cheemalapati        public void onReportButtonClick(String number);
859686330691f1216edff0ffa779138bda43388c47Sai Cheemalapati    }
869686330691f1216edff0ffa779138bda43388c47Sai Cheemalapati
878ef8020b8b792026a8dd15e029055f7d5e2d48f6Tyler Gunn    /** Constant used to indicate no row is expanded. */
888ef8020b8b792026a8dd15e029055f7d5e2d48f6Tyler Gunn    private static final long NONE_EXPANDED = -1;
898ef8020b8b792026a8dd15e029055f7d5e2d48f6Tyler Gunn
90704acc087ce359295475a46695c2821c55778344Chiao Cheng    protected final Context mContext;
9194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    private final ContactInfoHelper mContactInfoHelper;
9294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    private final CallFetcher mCallFetcher;
939686330691f1216edff0ffa779138bda43388c47Sai Cheemalapati    private final OnReportButtonClickListener mOnReportButtonClickListener;
9494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    private ViewTreeObserver mViewTreeObserver = null;
9594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
9674479d448bc39c3534585a627fba603aa89e93caAndrew Lee    protected ContactInfoCache mContactInfoCache;
9794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
988ef8020b8b792026a8dd15e029055f7d5e2d48f6Tyler Gunn    /**
998ef8020b8b792026a8dd15e029055f7d5e2d48f6Tyler Gunn     * Tracks the currently expanded call log row.
1008ef8020b8b792026a8dd15e029055f7d5e2d48f6Tyler Gunn     */
1018ef8020b8b792026a8dd15e029055f7d5e2d48f6Tyler Gunn    private long mCurrentlyExpanded = NONE_EXPANDED;
102146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn
10394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    /**
1044dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     *  Hashmap, keyed by call Id, used to track the day group for a call.  As call log entries are
1054dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     *  put into the primary call groups in {@link com.android.dialer.calllog.CallLogGroupBuilder},
1064dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     *  they are also assigned a secondary "day group".  This hashmap tracks the day group assigned
1074dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     *  to all calls in the call log.  This information is used to trigger the display of a day
1084dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     *  group header above the call log entry at the start of a day group.
1094dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     *  Note: Multiple calls are grouped into a single primary "call group" in the call log, and
1104dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     *  the cursor used to bind rows includes all of these calls.  When determining if a day group
1114dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     *  change has occurred it is necessary to look at the last entry in the call log to determine
1124dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     *  its day group.  This hashmap provides a means of determining the previous day group without
1134dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     *  having to reverse the cursor to the start of the previous day call log entry.
1144dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     */
1154dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn    private HashMap<Long,Integer> mDayGroups = new HashMap<Long, Integer>();
1164dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn
11794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    private boolean mLoading = true;
11894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
11994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    /** Instance of helper class for managing views. */
12094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    private final CallLogListItemHelper mCallLogViewsHelper;
12194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
12294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    /** Helper to parse and process phone numbers. */
12324ec319f8d410be8a1923c4033f927165876cbabYorke Lee    private PhoneNumberDisplayHelper mPhoneNumberHelper;
124e80d62229bb11a92f0db8d4e4bac6533bbed9b66Nancy Chen    /** Helper to access Telephony phone number utils class */
125e80d62229bb11a92f0db8d4e4bac6533bbed9b66Nancy Chen    protected final PhoneNumberUtilsWrapper mPhoneNumberUtilsWrapper;
12694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    /** Helper to group call log entries. */
12794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    private final CallLogGroupBuilder mCallLogGroupBuilder;
12894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
129654df8fbbc7703c24aec687de902e2c72ba343ddYorke Lee    private CallItemExpandedListener mCallItemExpandedListener;
130654df8fbbc7703c24aec687de902e2c72ba343ddYorke Lee
131643e78532e5d40ca62e6545855f847e26eaffa4eChiao Cheng    /** Listener for the primary or secondary actions in the list.
132643e78532e5d40ca62e6545855f847e26eaffa4eChiao Cheng     *  Primary opens the call details.
133643e78532e5d40ca62e6545855f847e26eaffa4eChiao Cheng     *  Secondary calls or plays.
134643e78532e5d40ca62e6545855f847e26eaffa4eChiao Cheng     **/
135643e78532e5d40ca62e6545855f847e26eaffa4eChiao Cheng    private final View.OnClickListener mActionListener = new View.OnClickListener() {
13694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        @Override
13794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        public void onClick(View view) {
13830355a89526c84e7b9e980c2f805c55ccfb66906Andrew Lee            final IntentProvider intentProvider = (IntentProvider) view.getTag();
13930355a89526c84e7b9e980c2f805c55ccfb66906Andrew Lee            if (intentProvider != null) {
14030355a89526c84e7b9e980c2f805c55ccfb66906Andrew Lee                final Intent intent = intentProvider.getIntent(mContext);
14130355a89526c84e7b9e980c2f805c55ccfb66906Andrew Lee                // See IntentProvider.getCallDetailIntentProvider() for why this may be null.
14230355a89526c84e7b9e980c2f805c55ccfb66906Andrew Lee                if (intent != null) {
14330355a89526c84e7b9e980c2f805c55ccfb66906Andrew Lee                    DialerUtils.startActivityWithErrorToast(mContext, intent);
14430355a89526c84e7b9e980c2f805c55ccfb66906Andrew Lee                }
14530355a89526c84e7b9e980c2f805c55ccfb66906Andrew Lee            }
14694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        }
14794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    };
148643e78532e5d40ca62e6545855f847e26eaffa4eChiao Cheng
149146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn    /**
150146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn     * The onClickListener used to expand or collapse the action buttons section for a call log
151146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn     * entry.
152146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn     */
153146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn    private final View.OnClickListener mExpandCollapseListener = new View.OnClickListener() {
154146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn        @Override
155146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn        public void onClick(View v) {
1562ff08a8f8d4762ab5d0aebb0b69079f0b8d20b3eYorke Lee            final View callLogItem = (View) v.getParent().getParent();
157b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee            handleRowExpanded(callLogItem, true /* animate */, false /* forceExpand */);
158b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee        }
159b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee    };
16068e771378889a479a80aac29a9ec2136b7ef27b6Tyler Gunn
16174479d448bc39c3534585a627fba603aa89e93caAndrew Lee    protected final OnContactInfoChangedListener mOnContactInfoChangedListener =
16274479d448bc39c3534585a627fba603aa89e93caAndrew Lee            new OnContactInfoChangedListener() {
16374479d448bc39c3534585a627fba603aa89e93caAndrew Lee                @Override
16474479d448bc39c3534585a627fba603aa89e93caAndrew Lee                public void onContactInfoChanged() {
16574479d448bc39c3534585a627fba603aa89e93caAndrew Lee                    notifyDataSetChanged();
16674479d448bc39c3534585a627fba603aa89e93caAndrew Lee                }
16774479d448bc39c3534585a627fba603aa89e93caAndrew Lee            };
16874479d448bc39c3534585a627fba603aa89e93caAndrew Lee
169b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee    private AccessibilityDelegate mAccessibilityDelegate = new AccessibilityDelegate() {
170b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee        @Override
171b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
172b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee                AccessibilityEvent event) {
173b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee            if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED) {
1742ff08a8f8d4762ab5d0aebb0b69079f0b8d20b3eYorke Lee                handleRowExpanded(host, false /* animate */,
175b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee                        true /* forceExpand */);
17668e771378889a479a80aac29a9ec2136b7ef27b6Tyler Gunn            }
177b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee            return super.onRequestSendAccessibilityEvent(host, child, event);
178146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn        }
179146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn    };
180146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn
18194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    @Override
18294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    public boolean onPreDraw() {
18394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        // We only wanted to listen for the first draw (and this is it).
18494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        unregisterPreDrawListener();
18594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
18674479d448bc39c3534585a627fba603aa89e93caAndrew Lee        mContactInfoCache.start();
18794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        return true;
18894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    }
18994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
190c6fde8d1b9a4e586ca65b82e9911089a9da14508Andrew Lee    public CallLogAdapter(
191c6fde8d1b9a4e586ca65b82e9911089a9da14508Andrew Lee            Context context,
192c6fde8d1b9a4e586ca65b82e9911089a9da14508Andrew Lee            CallFetcher callFetcher,
193c6fde8d1b9a4e586ca65b82e9911089a9da14508Andrew Lee            ContactInfoHelper contactInfoHelper,
19414cfa66d6df53303c280194d661c0b32838aa417Andrew Lee            OnReportButtonClickListener onReportButtonClickListener) {
19594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        super(context);
19694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
19794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        mContext = context;
19894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        mCallFetcher = callFetcher;
19994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        mContactInfoHelper = contactInfoHelper;
20094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
2019686330691f1216edff0ffa779138bda43388c47Sai Cheemalapati        mOnReportButtonClickListener = onReportButtonClickListener;
202b77bf5df2b866dd40e330b7c2dedee4a1d51fc78Sai Cheemalapati
20374479d448bc39c3534585a627fba603aa89e93caAndrew Lee        mContactInfoCache = new ContactInfoCache(
20474479d448bc39c3534585a627fba603aa89e93caAndrew Lee                mContactInfoHelper, mOnContactInfoChangedListener);
20594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
20694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        Resources resources = mContext.getResources();
20794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        CallTypeHelper callTypeHelper = new CallTypeHelper(resources);
20894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
209e80d62229bb11a92f0db8d4e4bac6533bbed9b66Nancy Chen        mPhoneNumberHelper = new PhoneNumberDisplayHelper(mContext, resources);
210e80d62229bb11a92f0db8d4e4bac6533bbed9b66Nancy Chen        mPhoneNumberUtilsWrapper = new PhoneNumberUtilsWrapper(mContext);
211e80d62229bb11a92f0db8d4e4bac6533bbed9b66Nancy Chen        PhoneCallDetailsHelper phoneCallDetailsHelper =
212e80d62229bb11a92f0db8d4e4bac6533bbed9b66Nancy Chen                new PhoneCallDetailsHelper(mContext, resources, mPhoneNumberUtilsWrapper);
21394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        mCallLogViewsHelper =
21430355a89526c84e7b9e980c2f805c55ccfb66906Andrew Lee                new CallLogListItemHelper(phoneCallDetailsHelper, mPhoneNumberHelper, resources);
21594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        mCallLogGroupBuilder = new CallLogGroupBuilder(this);
21694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    }
21794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
21894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    /**
21994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * Requery on background thread when {@link Cursor} changes.
22094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     */
22194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    @Override
22294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    protected void onContentChanged() {
22394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        mCallFetcher.fetchCalls();
22494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    }
22594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
226fb585079cc4c522c27f6dd6bf03fd296535960f3Yorke Lee    public void setLoading(boolean loading) {
22794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        mLoading = loading;
22894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    }
22994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
23094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    @Override
23194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    public boolean isEmpty() {
23294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        if (mLoading) {
23394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng            // We don't want the empty state to show when loading.
23494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng            return false;
23594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        } else {
23694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng            return super.isEmpty();
23794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        }
23894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    }
23994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
24094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    /**
24194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * Stop receiving onPreDraw() notifications.
24294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     */
24394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    private void unregisterPreDrawListener() {
24494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        if (mViewTreeObserver != null && mViewTreeObserver.isAlive()) {
24594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng            mViewTreeObserver.removeOnPreDrawListener(this);
24694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        }
24794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        mViewTreeObserver = null;
24894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    }
24994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
25094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    public void invalidateCache() {
25174479d448bc39c3534585a627fba603aa89e93caAndrew Lee        mContactInfoCache.invalidate();
25294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
25394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        // Restart the request-processing thread after the next draw.
25494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        unregisterPreDrawListener();
25594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    }
25694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
25774479d448bc39c3534585a627fba603aa89e93caAndrew Lee    public void pauseCache() {
25874479d448bc39c3534585a627fba603aa89e93caAndrew Lee        mContactInfoCache.stop();
25994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    }
26094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
26194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    @Override
26294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    protected void addGroups(Cursor cursor) {
26394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        mCallLogGroupBuilder.addGroups(cursor);
26494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    }
26594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
26694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    @Override
26794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    protected View newStandAloneView(Context context, ViewGroup parent) {
268704acc087ce359295475a46695c2821c55778344Chiao Cheng        return newChildView(context, parent);
26994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    }
27094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
27194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    @Override
272704acc087ce359295475a46695c2821c55778344Chiao Cheng    protected View newGroupView(Context context, ViewGroup parent) {
273704acc087ce359295475a46695c2821c55778344Chiao Cheng        return newChildView(context, parent);
27494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    }
27594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
27694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    @Override
27794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    protected View newChildView(Context context, ViewGroup parent) {
278c329bfb6d47f20237d22e13297d5bbb72e612919Evan Charlton        LayoutInflater inflater = LayoutInflater.from(context);
2792ff08a8f8d4762ab5d0aebb0b69079f0b8d20b3eYorke Lee        View view = inflater.inflate(R.layout.call_log_list_item, parent, false);
280c987e00fa84f8997c07e8cb2d413897ae1d41b14Andrew Lee
281c987e00fa84f8997c07e8cb2d413897ae1d41b14Andrew Lee        // Get the views to bind to and cache them.
28230355a89526c84e7b9e980c2f805c55ccfb66906Andrew Lee        CallLogListItemViews views = CallLogListItemViews.fromView(context, view);
283c987e00fa84f8997c07e8cb2d413897ae1d41b14Andrew Lee        view.setTag(views);
284c987e00fa84f8997c07e8cb2d413897ae1d41b14Andrew Lee
285c987e00fa84f8997c07e8cb2d413897ae1d41b14Andrew Lee        // Set text height to false on the TextViews so they don't have extra padding.
286c987e00fa84f8997c07e8cb2d413897ae1d41b14Andrew Lee        views.phoneCallDetailsViews.nameView.setElegantTextHeight(false);
287c987e00fa84f8997c07e8cb2d413897ae1d41b14Andrew Lee        views.phoneCallDetailsViews.callLocationAndDate.setElegantTextHeight(false);
288c987e00fa84f8997c07e8cb2d413897ae1d41b14Andrew Lee
28994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        return view;
29094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    }
29194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
29294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    @Override
293704acc087ce359295475a46695c2821c55778344Chiao Cheng    protected void bindStandAloneView(View view, Context context, Cursor cursor) {
29494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        bindView(view, cursor, 1);
29594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    }
29694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
29794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    @Override
298704acc087ce359295475a46695c2821c55778344Chiao Cheng    protected void bindChildView(View view, Context context, Cursor cursor) {
299704acc087ce359295475a46695c2821c55778344Chiao Cheng        bindView(view, cursor, 1);
30094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    }
30194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
30294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    @Override
30394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    protected void bindGroupView(View view, Context context, Cursor cursor, int groupSize,
30494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng            boolean expanded) {
30594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        bindView(view, cursor, groupSize);
30694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    }
30794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
30894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    private void findAndCacheViews(View view) {
30994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    }
31094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
31194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    /**
31294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * Binds the views in the entry to the data in the call log.
313a9a82f52cbcadd0b9a4aafa0c785c0d6af629f1cSantos Cordon     * TODO: This gets called 20-30 times when Dialer starts up for a single call log entry and
314a9a82f52cbcadd0b9a4aafa0c785c0d6af629f1cSantos Cordon     * should not. It invokes cross-process methods and the repeat execution can get costly.
31594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     *
3162ff08a8f8d4762ab5d0aebb0b69079f0b8d20b3eYorke Lee     * @param callLogItemView the view corresponding to this entry
31794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * @param c the cursor pointing to the entry in the call log
31894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * @param count the number of entries in the current item, greater than 1 if it is a group
31994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     */
3202ff08a8f8d4762ab5d0aebb0b69079f0b8d20b3eYorke Lee    private void bindView(View callLogItemView, Cursor c, int count) {
3212ff08a8f8d4762ab5d0aebb0b69079f0b8d20b3eYorke Lee        callLogItemView.setAccessibilityDelegate(mAccessibilityDelegate);
3222ff08a8f8d4762ab5d0aebb0b69079f0b8d20b3eYorke Lee        final CallLogListItemViews views = (CallLogListItemViews) callLogItemView.getTag();
323f517e7bb367d1ed749b500959d0a0a1ba8c3d5e5Christine Chen
32494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        // Default case: an item in the call log.
32594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        views.primaryActionView.setVisibility(View.VISIBLE);
32694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
32794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        final String number = c.getString(CallLogQuery.NUMBER);
328719a7adde25e0a717816b00668c16c3a1e3c5518Jay Shrauner        final int numberPresentation = c.getInt(CallLogQuery.NUMBER_PRESENTATION);
32994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        final long date = c.getLong(CallLogQuery.DATE);
33094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        final long duration = c.getLong(CallLogQuery.DURATION);
33194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        final int callType = c.getInt(CallLogQuery.CALL_TYPE);
332b2eebafbc1f1e26b5178b2858ca335467b4bc341Nancy Chen        final PhoneAccountHandle accountHandle = PhoneAccountUtils.getAccount(
333b2eebafbc1f1e26b5178b2858ca335467b4bc341Nancy Chen                c.getString(CallLogQuery.ACCOUNT_COMPONENT_NAME),
334b2eebafbc1f1e26b5178b2858ca335467b4bc341Nancy Chen                c.getString(CallLogQuery.ACCOUNT_ID));
33594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        final String countryIso = c.getString(CallLogQuery.COUNTRY_ISO);
3368cd9423bd04584acbcbf178bf6a1c1953debb8daYorke Lee
337146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn        final long rowId = c.getLong(CallLogQuery.ID);
338146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn        views.rowId = rowId;
339146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn
34014cfa66d6df53303c280194d661c0b32838aa417Andrew Lee        // Check if the day group has changed and display a header if necessary.
34114cfa66d6df53303c280194d661c0b32838aa417Andrew Lee        int currentGroup = getDayGroupForCall(rowId);
34214cfa66d6df53303c280194d661c0b32838aa417Andrew Lee        int previousGroup = getPreviousDayGroup(c);
34314cfa66d6df53303c280194d661c0b32838aa417Andrew Lee        if (currentGroup != previousGroup) {
34414cfa66d6df53303c280194d661c0b32838aa417Andrew Lee            views.dayGroupHeader.setVisibility(View.VISIBLE);
34514cfa66d6df53303c280194d661c0b32838aa417Andrew Lee            views.dayGroupHeader.setText(getGroupDescription(currentGroup));
3464dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn        } else {
3474dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn            views.dayGroupHeader.setVisibility(View.GONE);
3484dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn        }
3494dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn
350146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn        // Store some values used when the actions ViewStub is inflated on expansion of the actions
351146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn        // section.
352146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn        views.number = number;
353146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn        views.numberPresentation = numberPresentation;
354146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn        views.callType = callType;
3558f7c4368817a17727b2132d399d0895e33f67a95Nancy Chen        views.accountHandle = accountHandle;
356146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn        views.voicemailUri = c.getString(CallLogQuery.VOICEMAIL_URI);
357146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn        // Stash away the Ids of the calls so that we can support deleting a row in the call log.
358cf5e001120916deb770ea65ae55730e456f92137Tyler Gunn        views.callIds = getCallIds(c, count);
35994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
360c1fc077754e99bff54bfd7e155ba5c8dd95cf773Andrew Lee        final ContactInfo cachedContactInfo = mContactInfoHelper.getContactInfo(c);
36194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
36256cb0efa5eda1670077e66fc0e8c79478d0c1c67Yorke Lee        final boolean isVoicemailNumber =
363e80d62229bb11a92f0db8d4e4bac6533bbed9b66Nancy Chen                mPhoneNumberUtilsWrapper.isVoicemailNumber(accountHandle, number);
36456cb0efa5eda1670077e66fc0e8c79478d0c1c67Yorke Lee
36514cfa66d6df53303c280194d661c0b32838aa417Andrew Lee        // Expand/collapse an actions section for the call log entry when the primary view is tapped.
36630355a89526c84e7b9e980c2f805c55ccfb66906Andrew Lee        views.primaryActionView.setOnClickListener(mExpandCollapseListener);
367146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn
36814cfa66d6df53303c280194d661c0b32838aa417Andrew Lee        // Note: Binding of the action buttons is done as required in configureActionViews when the
36914cfa66d6df53303c280194d661c0b32838aa417Andrew Lee        // user expands the actions ViewStub.
370146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn
37174479d448bc39c3534585a627fba603aa89e93caAndrew Lee        ContactInfo info = ContactInfo.EMPTY;
37274479d448bc39c3534585a627fba603aa89e93caAndrew Lee        if (PhoneNumberUtilsWrapper.canPlaceCallsTo(number, numberPresentation)
37374479d448bc39c3534585a627fba603aa89e93caAndrew Lee                && !isVoicemailNumber) {
37474479d448bc39c3534585a627fba603aa89e93caAndrew Lee            // Lookup contacts with this number
37574479d448bc39c3534585a627fba603aa89e93caAndrew Lee            info = mContactInfoCache.getValue(number, countryIso, cachedContactInfo);
37694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        }
37794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
37894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        final Uri lookupUri = info.lookupUri;
37994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        final String name = info.name;
38094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        final int ntype = info.type;
38194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        final String label = info.label;
38294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        final long photoId = info.photoId;
383034a2b329e469bf6888fbbcf91992f974015c2a8Yorke Lee        final Uri photoUri = info.photoUri;
3841e5325f43c98a92f8bfec1dbd9db3d32a91835e9Ihab Awad        CharSequence formattedNumber = info.formattedNumber == null
3851e5325f43c98a92f8bfec1dbd9db3d32a91835e9Ihab Awad                ? null : PhoneNumberUtils.ttsSpanAsPhoneNumber(info.formattedNumber);
38694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        final int[] callTypes = getCallTypes(c, count);
38794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        final String geocode = c.getString(CallLogQuery.GEOCODED_LOCATION);
38856cb0efa5eda1670077e66fc0e8c79478d0c1c67Yorke Lee        final int sourceType = info.sourceType;
3898b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn        final int features = getCallFeatures(c, count);
3908cd9423bd04584acbcbf178bf6a1c1953debb8daYorke Lee        final String transcription = c.getString(CallLogQuery.TRANSCRIPTION);
3918b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn        Long dataUsage = null;
3928b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn        if (!c.isNull(CallLogQuery.DATA_USAGE)) {
3938b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn            dataUsage = c.getLong(CallLogQuery.DATA_USAGE);
3948b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn        }
3958b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn
39694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        final PhoneCallDetails details;
397704acc087ce359295475a46695c2821c55778344Chiao Cheng
398b77bf5df2b866dd40e330b7c2dedee4a1d51fc78Sai Cheemalapati        views.reported = info.isBadData;
39955733814f213809baaa8eaa8984ff026bdb08b4eAnthony Lee
40055733814f213809baaa8eaa8984ff026bdb08b4eAnthony Lee        // The entry can only be reported as invalid if it has a valid ID and the source of the
40155733814f213809baaa8eaa8984ff026bdb08b4eAnthony Lee        // entry supports marking entries as invalid.
40255733814f213809baaa8eaa8984ff026bdb08b4eAnthony Lee        views.canBeReportedAsInvalid = mContactInfoHelper.canReportAsInvalid(info.sourceType,
40355733814f213809baaa8eaa8984ff026bdb08b4eAnthony Lee                info.objectId);
404b77bf5df2b866dd40e330b7c2dedee4a1d51fc78Sai Cheemalapati
4059686330691f1216edff0ffa779138bda43388c47Sai Cheemalapati        // Restore expansion state of the row on rebind.  Inflate the actions ViewStub if required,
4069686330691f1216edff0ffa779138bda43388c47Sai Cheemalapati        // and set its visibility state accordingly.
40725e732727f5bf2c38c40cd353b739742278940c1Andrew Lee        views.expandOrCollapseActions(
40825e732727f5bf2c38c40cd353b739742278940c1Andrew Lee                isExpanded(rowId),
40925e732727f5bf2c38c40cd353b739742278940c1Andrew Lee                mOnReportButtonClickListener,
41025e732727f5bf2c38c40cd353b739742278940c1Andrew Lee                mActionListener,
41125e732727f5bf2c38c40cd353b739742278940c1Andrew Lee                mPhoneNumberUtilsWrapper,
41225e732727f5bf2c38c40cd353b739742278940c1Andrew Lee                mCallLogViewsHelper);
4139686330691f1216edff0ffa779138bda43388c47Sai Cheemalapati
41494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        if (TextUtils.isEmpty(name)) {
415e80d62229bb11a92f0db8d4e4bac6533bbed9b66Nancy Chen            details = new PhoneCallDetails(number, numberPresentation, formattedNumber, countryIso,
416e80d62229bb11a92f0db8d4e4bac6533bbed9b66Nancy Chen                    geocode, callTypes, date, duration, accountHandle, features, dataUsage,
417e80d62229bb11a92f0db8d4e4bac6533bbed9b66Nancy Chen                    transcription);
41894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        } else {
419e80d62229bb11a92f0db8d4e4bac6533bbed9b66Nancy Chen            details = new PhoneCallDetails(number, numberPresentation, formattedNumber, countryIso,
420e80d62229bb11a92f0db8d4e4bac6533bbed9b66Nancy Chen                    geocode, callTypes, date, duration, name, ntype, label, lookupUri, photoUri,
421e80d62229bb11a92f0db8d4e4bac6533bbed9b66Nancy Chen                    sourceType, accountHandle, features, dataUsage, transcription);
42294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        }
42394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
4240927dc6ef623bec56415d087885f6d2607da35f7Andrew Lee        mCallLogViewsHelper.setPhoneCallDetails(mContext, views, details);
425034a2b329e469bf6888fbbcf91992f974015c2a8Yorke Lee
42656cb0efa5eda1670077e66fc0e8c79478d0c1c67Yorke Lee        String nameForDefaultImage = null;
42756cb0efa5eda1670077e66fc0e8c79478d0c1c67Yorke Lee        if (TextUtils.isEmpty(name)) {
428e80d62229bb11a92f0db8d4e4bac6533bbed9b66Nancy Chen            nameForDefaultImage = mPhoneNumberHelper.getDisplayNumber(details.accountHandle,
429e80d62229bb11a92f0db8d4e4bac6533bbed9b66Nancy Chen                    details.number, details.numberPresentation, details.formattedNumber).toString();
43056cb0efa5eda1670077e66fc0e8c79478d0c1c67Yorke Lee        } else {
43156cb0efa5eda1670077e66fc0e8c79478d0c1c67Yorke Lee            nameForDefaultImage = name;
43256cb0efa5eda1670077e66fc0e8c79478d0c1c67Yorke Lee        }
43356cb0efa5eda1670077e66fc0e8c79478d0c1c67Yorke Lee
43481c3829f8a9377cb2e93c1fa6d223d223b78f371Andrew Lee        views.setPhoto(photoId, photoUri, lookupUri, nameForDefaultImage, isVoicemailNumber,
43581c3829f8a9377cb2e93c1fa6d223d223b78f371Andrew Lee                mContactInfoHelper.isBusiness(info.sourceType));
43674eb4ecc5df272f681b427760d46deafce8ed0b2Brian Attwell        views.quickContactView.setPrioritizedMimeType(Phone.CONTENT_ITEM_TYPE);
43794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
43894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        // Listen for the first draw
43994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        if (mViewTreeObserver == null) {
4402ff08a8f8d4762ab5d0aebb0b69079f0b8d20b3eYorke Lee            mViewTreeObserver = callLogItemView.getViewTreeObserver();
44194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng            mViewTreeObserver.addOnPreDrawListener(this);
44294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        }
443c5b6a693d4773214ff8d3fcfa43d0a29581bb886Chiao Cheng    }
444c5b6a693d4773214ff8d3fcfa43d0a29581bb886Chiao Cheng
445146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn    /**
4464dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     * Retrieves the day group of the previous call in the call log.  Used to determine if the day
4474dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     * group has changed and to trigger display of the day group text.
4484dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     *
4494dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     * @param cursor The call log cursor.
4504dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     * @return The previous day group, or DAY_GROUP_NONE if this is the first call.
4514dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     */
4524dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn    private int getPreviousDayGroup(Cursor cursor) {
4534dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn        // We want to restore the position in the cursor at the end.
4544dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn        int startingPosition = cursor.getPosition();
4554dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn        int dayGroup = CallLogGroupBuilder.DAY_GROUP_NONE;
4564dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn        if (cursor.moveToPrevious()) {
4574dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn            long previousRowId = cursor.getLong(CallLogQuery.ID);
4584dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn            dayGroup = getDayGroupForCall(previousRowId);
4594dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn        }
4604dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn        cursor.moveToPosition(startingPosition);
4614dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn        return dayGroup;
4624dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn    }
4634dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn
4644dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn    /**
4654dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     * Given a call Id, look up the day group that the call belongs to.  The day group data is
4664dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     * populated in {@link com.android.dialer.calllog.CallLogGroupBuilder}.
4674dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     *
4684dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     * @param callId The call to retrieve the day group for.
4694dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     * @return The day group for the call.
4704dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     */
4714dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn    private int getDayGroupForCall(long callId) {
4724dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn        if (mDayGroups.containsKey(callId)) {
4734dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn            return mDayGroups.get(callId);
4744dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn        }
4754dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn        return CallLogGroupBuilder.DAY_GROUP_NONE;
4764dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn    }
47781c3829f8a9377cb2e93c1fa6d223d223b78f371Andrew Lee
4784dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn    /**
4798ef8020b8b792026a8dd15e029055f7d5e2d48f6Tyler Gunn     * Determines if a call log row with the given Id is expanded.
4808ef8020b8b792026a8dd15e029055f7d5e2d48f6Tyler Gunn     * @param rowId The row Id of the call.
4818ef8020b8b792026a8dd15e029055f7d5e2d48f6Tyler Gunn     * @return True if the row should be expanded.
482146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn     */
483146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn    private boolean isExpanded(long rowId) {
4848ef8020b8b792026a8dd15e029055f7d5e2d48f6Tyler Gunn        return mCurrentlyExpanded == rowId;
485146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn    }
486146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn
487146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn    /**
488146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn     * Toggles the expansion state tracked for the call log row identified by rowId and returns
4898ef8020b8b792026a8dd15e029055f7d5e2d48f6Tyler Gunn     * the new expansion state.  Assumes that only a single call log row will be expanded at any
4908ef8020b8b792026a8dd15e029055f7d5e2d48f6Tyler Gunn     * one point and tracks the current and previous expanded item.
491146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn     *
492146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn     * @param rowId The row Id associated with the call log row to expand/collapse.
493146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn     * @return True where the row is now expanded, false otherwise.
494146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn     */
495146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn    private boolean toggleExpansion(long rowId) {
4968ef8020b8b792026a8dd15e029055f7d5e2d48f6Tyler Gunn        if (rowId == mCurrentlyExpanded) {
4978ef8020b8b792026a8dd15e029055f7d5e2d48f6Tyler Gunn            // Collapsing currently expanded row.
4988ef8020b8b792026a8dd15e029055f7d5e2d48f6Tyler Gunn            mCurrentlyExpanded = NONE_EXPANDED;
4998ef8020b8b792026a8dd15e029055f7d5e2d48f6Tyler Gunn            return false;
5008ef8020b8b792026a8dd15e029055f7d5e2d48f6Tyler Gunn        } else {
5018ef8020b8b792026a8dd15e029055f7d5e2d48f6Tyler Gunn            // Expanding a row (collapsing current expanded one).
5028ef8020b8b792026a8dd15e029055f7d5e2d48f6Tyler Gunn            mCurrentlyExpanded = rowId;
5038ef8020b8b792026a8dd15e029055f7d5e2d48f6Tyler Gunn            return true;
5048ef8020b8b792026a8dd15e029055f7d5e2d48f6Tyler Gunn        }
505146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn    }
506146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn
50794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    /**
50894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * Returns the call types for the given number of items in the cursor.
50994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * <p>
51094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * It uses the next {@code count} rows in the cursor to extract the types.
51194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * <p>
51294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * It position in the cursor is unchanged by this function.
51394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     */
51494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    private int[] getCallTypes(Cursor cursor, int count) {
51594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        int position = cursor.getPosition();
51694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        int[] callTypes = new int[count];
51794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        for (int index = 0; index < count; ++index) {
51894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng            callTypes[index] = cursor.getInt(CallLogQuery.CALL_TYPE);
51994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng            cursor.moveToNext();
52094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        }
52194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        cursor.moveToPosition(position);
52294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        return callTypes;
52394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    }
52494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
5258b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn    /**
5268b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn     * Determine the features which were enabled for any of the calls that make up a call log
5278b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn     * entry.
5288b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn     *
5298b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn     * @param cursor The cursor.
5308b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn     * @param count The number of calls for the current call log entry.
5318b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn     * @return The features.
5328b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn     */
5338b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn    private int getCallFeatures(Cursor cursor, int count) {
53403610993bf2adf12a6962c32851095551ffd0043Yorke Lee        int features = 0;
5358b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn        int position = cursor.getPosition();
5368b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn        for (int index = 0; index < count; ++index) {
5378b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn            features |= cursor.getInt(CallLogQuery.FEATURES);
5388b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn            cursor.moveToNext();
5398b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn        }
5408b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn        cursor.moveToPosition(position);
5418b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn        return features;
5428b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn    }
5438b0e858d5b4c50813dbe2b5c244e7013814b23ecTyler Gunn
544d0715acdfc1aee0c20950741dc15d30abd18d2f2Tyler Gunn    /**
545d0715acdfc1aee0c20950741dc15d30abd18d2f2Tyler Gunn     * Bind a call log entry view for testing purposes.  Also inflates the action view stub so
546d0715acdfc1aee0c20950741dc15d30abd18d2f2Tyler Gunn     * unit tests can access the buttons contained within.
547d0715acdfc1aee0c20950741dc15d30abd18d2f2Tyler Gunn     *
548d0715acdfc1aee0c20950741dc15d30abd18d2f2Tyler Gunn     * @param view The current call log row.
549d0715acdfc1aee0c20950741dc15d30abd18d2f2Tyler Gunn     * @param context The current context.
550d0715acdfc1aee0c20950741dc15d30abd18d2f2Tyler Gunn     * @param cursor The cursor to bind from.
551d0715acdfc1aee0c20950741dc15d30abd18d2f2Tyler Gunn     */
552d0715acdfc1aee0c20950741dc15d30abd18d2f2Tyler Gunn    @VisibleForTesting
553d0715acdfc1aee0c20950741dc15d30abd18d2f2Tyler Gunn    void bindViewForTest(View view, Context context, Cursor cursor) {
554d0715acdfc1aee0c20950741dc15d30abd18d2f2Tyler Gunn        bindStandAloneView(view, context, cursor);
55530355a89526c84e7b9e980c2f805c55ccfb66906Andrew Lee        CallLogListItemViews views = CallLogListItemViews.fromView(context, view);
55625e732727f5bf2c38c40cd353b739742278940c1Andrew Lee        views.inflateActionViewStub(mOnReportButtonClickListener, mActionListener,
55730355a89526c84e7b9e980c2f805c55ccfb66906Andrew Lee                mPhoneNumberUtilsWrapper, mCallLogViewsHelper);
558d0715acdfc1aee0c20950741dc15d30abd18d2f2Tyler Gunn    }
559034a2b329e469bf6888fbbcf91992f974015c2a8Yorke Lee
56094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    /**
56194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * Sets whether processing of requests for contact details should be enabled.
56274479d448bc39c3534585a627fba603aa89e93caAndrew Lee     *
56394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * This method should be called in tests to disable such processing of requests when not
56494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * needed.
56594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     */
56694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    @VisibleForTesting
56794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    void disableRequestProcessingForTest() {
56874479d448bc39c3534585a627fba603aa89e93caAndrew Lee        // TODO: Remove this and test the cache directly.
56974479d448bc39c3534585a627fba603aa89e93caAndrew Lee        mContactInfoCache.disableRequestProcessingForTest();
57094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    }
57194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
57294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    @VisibleForTesting
57394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    void injectContactInfoForTest(String number, String countryIso, ContactInfo contactInfo) {
57474479d448bc39c3534585a627fba603aa89e93caAndrew Lee        // TODO: Remove this and test the cache directly.
57574479d448bc39c3534585a627fba603aa89e93caAndrew Lee        mContactInfoCache.injectContactInfoForTest(number, countryIso, contactInfo);
57694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    }
57794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
57894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    @Override
57994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    public void addGroup(int cursorPosition, int size, boolean expanded) {
58094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        super.addGroup(cursorPosition, size, expanded);
58194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    }
58294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
5834dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn    /**
5844dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     * Stores the day group associated with a call in the call log.
5854dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     *
5864dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     * @param rowId The row Id of the current call.
5874dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     * @param dayGroup The day group the call belongs in.
5884dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     */
5894dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn    @Override
5904dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn    public void setDayGroup(long rowId, int dayGroup) {
5914dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn        if (!mDayGroups.containsKey(rowId)) {
5924dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn            mDayGroups.put(rowId, dayGroup);
5934dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn        }
5944dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn    }
5954dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn
5964dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn    /**
5974dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     * Clears the day group associations on re-bind of the call log.
5984dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     */
5994dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn    @Override
6004dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn    public void clearDayGroups() {
6014dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn        mDayGroups.clear();
6024dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn    }
6034dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn
604146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn    /**
605146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn     * Retrieves the call Ids represented by the current call log row.
606146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn     *
607146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn     * @param cursor Call log cursor to retrieve call Ids from.
608146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn     * @param groupSize Number of calls associated with the current call log row.
609146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn     * @return Array of call Ids.
610146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn     */
611cf5e001120916deb770ea65ae55730e456f92137Tyler Gunn    private long[] getCallIds(final Cursor cursor, final int groupSize) {
612146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn        // We want to restore the position in the cursor at the end.
613146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn        int startingPosition = cursor.getPosition();
614146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn        long[] ids = new long[groupSize];
615146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn        // Copy the ids of the rows in the group.
616146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn        for (int index = 0; index < groupSize; ++index) {
617146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn            ids[index] = cursor.getLong(CallLogQuery.ID);
618146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn            cursor.moveToNext();
619146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn        }
620146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn        cursor.moveToPosition(startingPosition);
621146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn        return ids;
622146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn    }
623146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn
624146a4cdf57f0d4d0cd85e808f1df2bdea639b24cTyler Gunn    /**
6254dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     * Determines the description for a day group.
6264dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     *
6274dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     * @param group The day group to retrieve the description for.
6284dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     * @return The day group description.
6294dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn     */
6304dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn    private CharSequence getGroupDescription(int group) {
6314dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn       if (group == CallLogGroupBuilder.DAY_GROUP_TODAY) {
6321e273313ff938ba0c7294dade433736d3fc5876bTyler Gunn           return mContext.getResources().getString(R.string.call_log_header_today);
6334dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn       } else if (group == CallLogGroupBuilder.DAY_GROUP_YESTERDAY) {
6341e273313ff938ba0c7294dade433736d3fc5876bTyler Gunn           return mContext.getResources().getString(R.string.call_log_header_yesterday);
6354dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn       } else {
6364dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn           return mContext.getResources().getString(R.string.call_log_header_other);
6374dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn       }
6384dfd7129ab04853504fe0c050e982db7b178b643Tyler Gunn    }
6399686330691f1216edff0ffa779138bda43388c47Sai Cheemalapati
640b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee    /**
641b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee     * Manages the state changes for the UI interaction where a call log row is expanded.
642b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee     *
643b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee     * @param view The view that was tapped
644b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee     * @param animate Whether or not to animate the expansion/collapse
645b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee     * @param forceExpand Whether or not to force the call log row into an expanded state regardless
646b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee     *        of its previous state
647b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee     */
6482ff08a8f8d4762ab5d0aebb0b69079f0b8d20b3eYorke Lee    private void handleRowExpanded(View view, boolean animate, boolean forceExpand) {
649b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee        final CallLogListItemViews views = (CallLogListItemViews) view.getTag();
650b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee
651b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee        if (forceExpand && isExpanded(views.rowId)) {
652b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee            return;
653b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee        }
654b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee
655b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee        // Hide or show the actions view.
656b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee        boolean expanded = toggleExpansion(views.rowId);
657b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee
658b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee        // Trigger loading of the viewstub and visual expand or collapse.
65925e732727f5bf2c38c40cd353b739742278940c1Andrew Lee        views.expandOrCollapseActions(
66025e732727f5bf2c38c40cd353b739742278940c1Andrew Lee                expanded,
66125e732727f5bf2c38c40cd353b739742278940c1Andrew Lee                mOnReportButtonClickListener,
66225e732727f5bf2c38c40cd353b739742278940c1Andrew Lee                mActionListener,
66325e732727f5bf2c38c40cd353b739742278940c1Andrew Lee                mPhoneNumberUtilsWrapper,
66425e732727f5bf2c38c40cd353b739742278940c1Andrew Lee                mCallLogViewsHelper);
665b359699a1dd96a4581a47b11ef2a85ec4a8a9433Yorke Lee    }
66694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng}
667