1afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda/*
2afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda * Copyright (C) 2011 The Android Open Source Project
3afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda *
4afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda * Licensed under the Apache License, Version 2.0 (the "License");
5afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda * you may not use this file except in compliance with the License.
6afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda * You may obtain a copy of the License at
7afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda *
8afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda *      http://www.apache.org/licenses/LICENSE-2.0
9afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda *
10afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda * Unless required by applicable law or agreed to in writing, software
11afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda * distributed under the License is distributed on an "AS IS" BASIS,
12afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda * See the License for the specific language governing permissions and
14afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda * limitations under the License.
15afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda */
16afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda
17afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerdapackage com.android.contacts;
18afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda
19afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerdaimport android.content.res.Resources;
20afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerdaimport android.graphics.Typeface;
21afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerdaimport android.provider.ContactsContract.CommonDataKinds.Phone;
22afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerdaimport android.telephony.PhoneNumberUtils;
23fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerdaimport android.text.SpannableString;
24afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerdaimport android.text.Spanned;
25afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerdaimport android.text.TextUtils;
26afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerdaimport android.text.format.DateUtils;
27fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerdaimport android.text.style.ForegroundColorSpan;
28fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerdaimport android.text.style.StyleSpan;
29afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerdaimport android.view.View;
30b88abaaf3e733a9daf681277b7e5e8e58c015462Flavio Lerdaimport android.widget.TextView;
31afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda
32e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.calllog.CallTypeHelper;
33e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.calllog.PhoneNumberHelper;
34e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.test.NeededForTesting;
35e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Cheng
36afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda/**
37afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda * Helper class to fill in the views in {@link PhoneCallDetailsViews}.
38afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda */
39afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerdapublic class PhoneCallDetailsHelper {
408e39c71705261fa97adf1b6f39336a7fbd2a2c65Flavio Lerda    /** The maximum number of icons will be shown to represent the call types in a group. */
418e39c71705261fa97adf1b6f39336a7fbd2a2c65Flavio Lerda    private static final int MAX_CALL_TYPE_ICONS = 3;
428e39c71705261fa97adf1b6f39336a7fbd2a2c65Flavio Lerda
43d72bf8a27d12efd492df7333f1f8590a9eb6f097Flavio Lerda    private final Resources mResources;
447d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda    /** The injected current time in milliseconds since the epoch. Used only by tests. */
457d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda    private Long mCurrentTimeMillisForTest;
46178eeebac88b352c131bd0315a99da16162c986eFlavio Lerda    // Helper classes.
479a208cc08567a3d86c7968d7a4f13f5714b9b657Flavio Lerda    private final CallTypeHelper mCallTypeHelper;
48178eeebac88b352c131bd0315a99da16162c986eFlavio Lerda    private final PhoneNumberHelper mPhoneNumberHelper;
49d72bf8a27d12efd492df7333f1f8590a9eb6f097Flavio Lerda
50afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda    /**
51d72bf8a27d12efd492df7333f1f8590a9eb6f097Flavio Lerda     * Creates a new instance of the helper.
52d72bf8a27d12efd492df7333f1f8590a9eb6f097Flavio Lerda     * <p>
53d72bf8a27d12efd492df7333f1f8590a9eb6f097Flavio Lerda     * Generally you should have a single instance of this helper in any context.
54afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda     *
55afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda     * @param resources used to look up strings
56d72bf8a27d12efd492df7333f1f8590a9eb6f097Flavio Lerda     */
57405695664582b4989cffcf054bf1aceb83dec437Flavio Lerda    public PhoneCallDetailsHelper(Resources resources, CallTypeHelper callTypeHelper,
58405695664582b4989cffcf054bf1aceb83dec437Flavio Lerda            PhoneNumberHelper phoneNumberHelper) {
59d72bf8a27d12efd492df7333f1f8590a9eb6f097Flavio Lerda        mResources = resources;
609a208cc08567a3d86c7968d7a4f13f5714b9b657Flavio Lerda        mCallTypeHelper = callTypeHelper;
61178eeebac88b352c131bd0315a99da16162c986eFlavio Lerda        mPhoneNumberHelper = phoneNumberHelper;
62d72bf8a27d12efd492df7333f1f8590a9eb6f097Flavio Lerda    }
63d72bf8a27d12efd492df7333f1f8590a9eb6f097Flavio Lerda
649de38681c1d037100a978a5820c09cb74c0d6feeFlavio Lerda    /** Fills the call details views with content. */
654586febe3637303ab6f1b24fc5a23750aa3a6259Flavio Lerda    public void setPhoneCallDetails(PhoneCallDetailsViews views, PhoneCallDetails details,
66fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda            boolean isHighlighted) {
67fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda        // Display up to a given number of icons.
68fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda        views.callTypeIcons.clear();
69fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda        int count = details.callTypes.length;
70fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda        for (int index = 0; index < count && index < MAX_CALL_TYPE_ICONS; ++index) {
71fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda            views.callTypeIcons.add(details.callTypes[index]);
72fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda        }
73fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda        views.callTypeIcons.setVisibility(View.VISIBLE);
74fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda
75fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda        // Show the total call count only if there are more than the maximum number of icons.
76fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda        final Integer callCount;
77fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda        if (count > MAX_CALL_TYPE_ICONS) {
78fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda            callCount = count;
794586febe3637303ab6f1b24fc5a23750aa3a6259Flavio Lerda        } else {
80fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda            callCount = null;
817d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda        }
82fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda        // The color to highlight the count and date in, if any. This is based on the first call.
83fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda        Integer highlightColor =
84fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda                isHighlighted ? mCallTypeHelper.getHighlightedColor(details.callTypes[0]) : null;
854586febe3637303ab6f1b24fc5a23750aa3a6259Flavio Lerda
86fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda        // The date of this call, relative to the current time.
87fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda        CharSequence dateText =
889de38681c1d037100a978a5820c09cb74c0d6feeFlavio Lerda            DateUtils.getRelativeTimeSpanString(details.date,
897d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda                    getCurrentTimeMillis(),
90afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda                    DateUtils.MINUTE_IN_MILLIS,
91afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda                    DateUtils.FORMAT_ABBREV_RELATIVE);
92afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda
93fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda        // Set the call count and date.
94fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda        setCallCountAndDate(views, callCount, dateText, highlightColor);
95fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda
96afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda        CharSequence numberFormattedLabel = null;
97afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda        // Only show a label if the number is shown and it is not a SIP address.
989de38681c1d037100a978a5820c09cb74c0d6feeFlavio Lerda        if (!TextUtils.isEmpty(details.number)
999de38681c1d037100a978a5820c09cb74c0d6feeFlavio Lerda                && !PhoneNumberUtils.isUriNumber(details.number.toString())) {
1009de38681c1d037100a978a5820c09cb74c0d6feeFlavio Lerda            numberFormattedLabel = Phone.getTypeLabel(mResources, details.numberType,
1019de38681c1d037100a978a5820c09cb74c0d6feeFlavio Lerda                    details.numberLabel);
102afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda        }
103afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda
104b9256f81c0c65da98fb53b7d1879d71183d852b8Flavio Lerda        final CharSequence nameText;
105b9256f81c0c65da98fb53b7d1879d71183d852b8Flavio Lerda        final CharSequence numberText;
10688be53d18fc3ac194eabda8d811eaab68c3e40c8Flavio Lerda        final CharSequence labelText;
107178eeebac88b352c131bd0315a99da16162c986eFlavio Lerda        final CharSequence displayNumber =
108178eeebac88b352c131bd0315a99da16162c986eFlavio Lerda            mPhoneNumberHelper.getDisplayNumber(details.number, details.formattedNumber);
1099de38681c1d037100a978a5820c09cb74c0d6feeFlavio Lerda        if (TextUtils.isEmpty(details.name)) {
110178eeebac88b352c131bd0315a99da16162c986eFlavio Lerda            nameText = displayNumber;
111e4b156d0d3b69e8c8b32c8f601b051d7750a5f84Flavio Lerda            if (TextUtils.isEmpty(details.geocode)
112e4b156d0d3b69e8c8b32c8f601b051d7750a5f84Flavio Lerda                    || mPhoneNumberHelper.isVoicemailNumber(details.number)) {
113be45e0f3d9ba9b0f842174d857a99edeadc0136eFlavio Lerda                numberText = mResources.getString(R.string.call_log_empty_gecode);
114be45e0f3d9ba9b0f842174d857a99edeadc0136eFlavio Lerda            } else {
11571fc6ec6598aeb8dcad797c05816bab91762e2b3Flavio Lerda                numberText = details.geocode;
116be45e0f3d9ba9b0f842174d857a99edeadc0136eFlavio Lerda            }
11788be53d18fc3ac194eabda8d811eaab68c3e40c8Flavio Lerda            labelText = null;
118afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda        } else {
1199de38681c1d037100a978a5820c09cb74c0d6feeFlavio Lerda            nameText = details.name;
12088be53d18fc3ac194eabda8d811eaab68c3e40c8Flavio Lerda            numberText = displayNumber;
12188be53d18fc3ac194eabda8d811eaab68c3e40c8Flavio Lerda            labelText = numberFormattedLabel;
122afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda        }
123afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda
1247d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda        views.nameView.setText(nameText);
125b88abaaf3e733a9daf681277b7e5e8e58c015462Flavio Lerda        views.numberView.setText(numberText);
12688be53d18fc3ac194eabda8d811eaab68c3e40c8Flavio Lerda        views.labelView.setText(labelText);
12788be53d18fc3ac194eabda8d811eaab68c3e40c8Flavio Lerda        views.labelView.setVisibility(TextUtils.isEmpty(labelText) ? View.GONE : View.VISIBLE);
128b88abaaf3e733a9daf681277b7e5e8e58c015462Flavio Lerda    }
129b88abaaf3e733a9daf681277b7e5e8e58c015462Flavio Lerda
130d5678d3c22b7ab82b3840000704ce10162534d5dFlavio Lerda    /** Sets the text of the header view for the details page of a phone call. */
131d5678d3c22b7ab82b3840000704ce10162534d5dFlavio Lerda    public void setCallDetailsHeader(TextView nameView, PhoneCallDetails details) {
132b88abaaf3e733a9daf681277b7e5e8e58c015462Flavio Lerda        final CharSequence nameText;
133b88abaaf3e733a9daf681277b7e5e8e58c015462Flavio Lerda        final CharSequence displayNumber =
134d5678d3c22b7ab82b3840000704ce10162534d5dFlavio Lerda                mPhoneNumberHelper.getDisplayNumber(details.number,
135d5678d3c22b7ab82b3840000704ce10162534d5dFlavio Lerda                        mResources.getString(R.string.recentCalls_addToContact));
136b88abaaf3e733a9daf681277b7e5e8e58c015462Flavio Lerda        if (TextUtils.isEmpty(details.name)) {
137b88abaaf3e733a9daf681277b7e5e8e58c015462Flavio Lerda            nameText = displayNumber;
138afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda        } else {
139b88abaaf3e733a9daf681277b7e5e8e58c015462Flavio Lerda            nameText = details.name;
140afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda        }
141405695664582b4989cffcf054bf1aceb83dec437Flavio Lerda
142b88abaaf3e733a9daf681277b7e5e8e58c015462Flavio Lerda        nameView.setText(nameText);
143afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda    }
144696e8132c3cc9dd8ef2060a83c9d15f35c2b316bFlavio Lerda
145a0290a4baab4297303cab3664c7abfd548f2e301Makoto Onuki    @NeededForTesting
1467d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda    public void setCurrentTimeForTest(long currentTimeMillis) {
1477d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda        mCurrentTimeMillisForTest = currentTimeMillis;
1487d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda    }
1497d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda
1507d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda    /**
1517d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda     * Returns the current time in milliseconds since the epoch.
1527d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda     * <p>
1537d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda     * It can be injected in tests using {@link #setCurrentTimeForTest(long)}.
1547d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda     */
1557d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda    private long getCurrentTimeMillis() {
1567d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda        if (mCurrentTimeMillisForTest == null) {
1577d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda            return System.currentTimeMillis();
1587d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda        } else {
1597d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda            return mCurrentTimeMillisForTest;
1607d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda        }
1617d7473a1efca1fa02b52d54e5b71003c948ba49bFlavio Lerda    }
162fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda
163fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda    /** Sets the call count and date. */
164fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda    private void setCallCountAndDate(PhoneCallDetailsViews views, Integer callCount,
165fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda            CharSequence dateText, Integer highlightColor) {
166fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda        // Combine the count (if present) and the date.
167fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda        final CharSequence text;
168fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda        if (callCount != null) {
169fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda            text = mResources.getString(
170fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda                    R.string.call_log_item_count_and_date, callCount.intValue(), dateText);
171fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda        } else {
172fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda            text = dateText;
173fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda        }
174fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda
175fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda        // Apply the highlight color if present.
176fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda        final CharSequence formattedText;
177fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda        if (highlightColor != null) {
178fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda            formattedText = addBoldAndColor(text, highlightColor);
179fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda        } else {
180fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda            formattedText = text;
181fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda        }
182fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda
183fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda        views.callTypeAndDate.setText(formattedText);
184fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda    }
185fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda
186fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda    /** Creates a SpannableString for the given text which is bold and in the given color. */
187fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda    private CharSequence addBoldAndColor(CharSequence text, int color) {
188fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda        int flags = Spanned.SPAN_INCLUSIVE_INCLUSIVE;
189fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda        SpannableString result = new SpannableString(text);
190fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda        result.setSpan(new StyleSpan(Typeface.BOLD), 0, text.length(), flags);
191fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda        result.setSpan(new ForegroundColorSpan(color), 0, text.length(), flags);
192fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda        return result;
193fe17026100674b204f3b4fc6cb5a61f51ac99ec6Flavio Lerda    }
194afb93bb5893c7c64be3f32598b383fdf589c29d8Flavio Lerda}
195