1ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos/*
2ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos * Copyright (C) 2014 The Android Open Source Project
3ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos *
4ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos * Licensed under the Apache License, Version 2.0 (the "License");
5ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos * you may not use this file except in compliance with the License.
6ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos * You may obtain a copy of the License at
7ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos *
8ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos *      http://www.apache.org/licenses/LICENSE-2.0
9ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos *
10ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos * Unless required by applicable law or agreed to in writing, software
11ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos * distributed under the License is distributed on an "AS IS" BASIS,
12ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos * See the License for the specific language governing permissions and
14ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos * limitations under the License.
15ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos */
16ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulospackage com.android.contacts.interactions;
17ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos
18ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulosimport com.android.contacts.R;
19ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulosimport com.android.contacts.common.util.BitmapUtil;
20ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos
21ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulosimport android.content.ContentValues;
22ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulosimport android.content.Context;
23ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulosimport android.content.Intent;
24ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulosimport android.content.res.Resources;
25ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulosimport android.graphics.PorterDuff;
26ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulosimport android.graphics.drawable.Drawable;
27ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulosimport android.net.Uri;
28ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulosimport android.provider.CallLog.Calls;
29ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulosimport android.provider.ContactsContract.CommonDataKinds.Phone;
30c62cc7931593b4137f8a507689b653e1e15e1260Brian Attwellimport android.text.BidiFormatter;
31c62cc7931593b4137f8a507689b653e1e15e1260Brian Attwellimport android.text.TextDirectionHeuristics;
32ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos
33ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos/**
34ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos * Represents a call log event interaction, wrapping the columns in
35ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos * {@link android.provider.CallLog.Calls}.
36ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos *
37ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos * This class does not return log entries related to voicemail or SIP calls. Additionally,
38ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos * this class ignores number presentation. Number presentation affects how to identify phone
39ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos * numbers. Since, we already know the identity of the phone number owner we can ignore number
40ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos * presentation.
41ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos *
42ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos * As a result of ignoring voicemail and number presentation, we don't need to worry about API
43ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos * version.
44ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos */
45ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulospublic class CallLogInteraction implements ContactInteraction {
46ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos
47ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    private static final String URI_TARGET_PREFIX = "tel:";
48ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    private static final int CALL_LOG_ICON_RES = R.drawable.ic_phone_24dp;
49ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    private static final int CALL_ARROW_ICON_RES = R.drawable.ic_call_arrow;
50c62cc7931593b4137f8a507689b653e1e15e1260Brian Attwell    private static BidiFormatter sBidiFormatter = BidiFormatter.getInstance();
51ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos
52ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    private ContentValues mValues;
53ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos
54ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    public CallLogInteraction(ContentValues values) {
55ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos        mValues = values;
56ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    }
57ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos
58ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    @Override
59ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    public Intent getIntent() {
6075d5a915cb764f610db6141148c57b1c8e080564Paul Soulos        String number = getNumber();
6175d5a915cb764f610db6141148c57b1c8e080564Paul Soulos        return number == null ? null : new Intent(Intent.ACTION_CALL).setData(
6275d5a915cb764f610db6141148c57b1c8e080564Paul Soulos                Uri.parse(URI_TARGET_PREFIX + number));
63ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    }
64ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos
65ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    @Override
66ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    public String getViewHeader(Context context) {
67ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos        return getNumber();
68ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    }
69ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos
70ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    @Override
71ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    public long getInteractionDate() {
7275d5a915cb764f610db6141148c57b1c8e080564Paul Soulos        Long date = getDate();
7375d5a915cb764f610db6141148c57b1c8e080564Paul Soulos        return date == null ? -1 : date;
74ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    }
75ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos
76ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    @Override
77ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    public String getViewBody(Context context) {
7875d5a915cb764f610db6141148c57b1c8e080564Paul Soulos        Integer numberType = getCachedNumberType();
7975d5a915cb764f610db6141148c57b1c8e080564Paul Soulos        if (numberType == null) {
80ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos            return null;
81ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos        }
82ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos        return Phone.getTypeLabel(context.getResources(), getCachedNumberType(),
83ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos                getCachedNumberLabel()).toString();
84ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    }
85ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos
86ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    @Override
87ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    public String getViewFooter(Context context) {
8875d5a915cb764f610db6141148c57b1c8e080564Paul Soulos        Long date = getDate();
8975d5a915cb764f610db6141148c57b1c8e080564Paul Soulos        return date == null ? null : ContactInteractionUtil.formatDateStringFromTimestamp(
9075d5a915cb764f610db6141148c57b1c8e080564Paul Soulos                date, context);
91ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    }
92ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos
93ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    @Override
94ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    public Drawable getIcon(Context context) {
95ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos        return context.getResources().getDrawable(CALL_LOG_ICON_RES);
96ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    }
97ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos
98ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    @Override
99ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    public Drawable getBodyIcon(Context context) {
100ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos        return null;
101ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    }
102ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos
103ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    @Override
104ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    public Drawable getFooterIcon(Context context) {
105ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos        Drawable callArrow = null;
106ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos        Resources res = context.getResources();
10775d5a915cb764f610db6141148c57b1c8e080564Paul Soulos        Integer type = getType();
10875d5a915cb764f610db6141148c57b1c8e080564Paul Soulos        if (type == null) {
10975d5a915cb764f610db6141148c57b1c8e080564Paul Soulos            return null;
11075d5a915cb764f610db6141148c57b1c8e080564Paul Soulos        }
11175d5a915cb764f610db6141148c57b1c8e080564Paul Soulos        switch (type) {
112ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos            case Calls.INCOMING_TYPE:
113ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos                callArrow = res.getDrawable(CALL_ARROW_ICON_RES);
114ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos                callArrow.setColorFilter(res.getColor(R.color.call_arrow_green),
115ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos                        PorterDuff.Mode.MULTIPLY);
116ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos                break;
117ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos            case Calls.MISSED_TYPE:
118ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos                callArrow = res.getDrawable(CALL_ARROW_ICON_RES);
119ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos                callArrow.setColorFilter(res.getColor(R.color.call_arrow_red),
120ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos                        PorterDuff.Mode.MULTIPLY);
121ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos                break;
122ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos            case Calls.OUTGOING_TYPE:
123ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos                callArrow = BitmapUtil.getRotatedDrawable(res, CALL_ARROW_ICON_RES, 180f);
124ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos                callArrow.setColorFilter(res.getColor(R.color.call_arrow_green),
125ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos                        PorterDuff.Mode.MULTIPLY);
126ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos                break;
127ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos        }
128ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos        return callArrow;
129ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    }
130ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos
131ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    public String getCachedName() {
132ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos        return mValues.getAsString(Calls.CACHED_NAME);
133ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    }
134ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos
135ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    public String getCachedNumberLabel() {
136ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos        return mValues.getAsString(Calls.CACHED_NUMBER_LABEL);
137ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    }
138ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos
13975d5a915cb764f610db6141148c57b1c8e080564Paul Soulos    public Integer getCachedNumberType() {
14075d5a915cb764f610db6141148c57b1c8e080564Paul Soulos        return mValues.getAsInteger(Calls.CACHED_NUMBER_TYPE);
141ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    }
142ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos
14375d5a915cb764f610db6141148c57b1c8e080564Paul Soulos    public Long getDate() {
144ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos        return mValues.getAsLong(Calls.DATE);
145ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    }
146ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos
14775d5a915cb764f610db6141148c57b1c8e080564Paul Soulos    public Long getDuration() {
148ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos        return mValues.getAsLong(Calls.DURATION);
149ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    }
150ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos
15175d5a915cb764f610db6141148c57b1c8e080564Paul Soulos    public Boolean getIsRead() {
152ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos        return mValues.getAsBoolean(Calls.IS_READ);
153ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    }
154ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos
15575d5a915cb764f610db6141148c57b1c8e080564Paul Soulos    public Integer getLimitParamKey() {
156ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos        return mValues.getAsInteger(Calls.LIMIT_PARAM_KEY);
157ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    }
158ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos
15975d5a915cb764f610db6141148c57b1c8e080564Paul Soulos    public Boolean getNew() {
160ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos        return mValues.getAsBoolean(Calls.NEW);
161ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    }
162ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos
163ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    public String getNumber() {
1648164603be5a79e5f95ef4d404a07a7f21f25af9aJay Shrauner        final String number = mValues.getAsString(Calls.NUMBER);
1658164603be5a79e5f95ef4d404a07a7f21f25af9aJay Shrauner        return number == null ? null :
1668164603be5a79e5f95ef4d404a07a7f21f25af9aJay Shrauner            sBidiFormatter.unicodeWrap(number, TextDirectionHeuristics.LTR);
167ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    }
168ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos
16975d5a915cb764f610db6141148c57b1c8e080564Paul Soulos    public Integer getNumberPresentation() {
170ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos        return mValues.getAsInteger(Calls.NUMBER_PRESENTATION);
171ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    }
172ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos
17375d5a915cb764f610db6141148c57b1c8e080564Paul Soulos    public Integer getOffsetParamKey() {
174ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos        return mValues.getAsInteger(Calls.OFFSET_PARAM_KEY);
175ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    }
176ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos
17775d5a915cb764f610db6141148c57b1c8e080564Paul Soulos    public Integer getType() {
178ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos        return mValues.getAsInteger(Calls.TYPE);
179ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos    }
18023e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos
18123e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos    @Override
18223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos    public String getContentDescription(Context context) {
18323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos        String callDetails = getCallTypeString(context) + ". " + getViewFooter(context) + ". " +
18423e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                getViewHeader(context) + ". " + getViewFooter(context);
18523e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos        return context.getResources().getString(R.string.content_description_recent_call,
18623e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                callDetails);
18723e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos    }
18823e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos
18923e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos    private String getCallTypeString(Context context) {
19023e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos        String callType = "";
19123e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos        Resources res = context.getResources();
19223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos        Integer type = getType();
19323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos        if (type == null) {
19423e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos            return callType;
19523e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos        }
19623e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos        switch (type) {
19723e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos            case Calls.INCOMING_TYPE:
19823e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                callType = res.getString(R.string.content_description_recent_call_type_incoming);
19923e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                break;
20023e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos            case Calls.MISSED_TYPE:
20123e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                callType = res.getString(R.string.content_description_recent_call_type_missed);
20223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                break;
20323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos            case Calls.OUTGOING_TYPE:
20423e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                callType = res.getString(R.string.content_description_recent_call_type_outgoing);
20523e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos                break;
20623e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos        }
20723e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos        return callType;
20823e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos    }
20948290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos
21048290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos    @Override
21148290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos    public int getIconResourceId() {
21248290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos        return CALL_LOG_ICON_RES;
21348290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos    }
2148164603be5a79e5f95ef4d404a07a7f21f25af9aJay Shrauner}
215