1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.contacts.interactions;
17
18import com.android.contacts.R;
19import com.android.contacts.common.util.BitmapUtil;
20import com.android.contacts.common.util.ContactDisplayUtils;
21
22import android.content.ContentValues;
23import android.content.Context;
24import android.content.Intent;
25import android.content.res.Resources;
26import android.graphics.PorterDuff;
27import android.graphics.drawable.Drawable;
28import android.net.Uri;
29import android.provider.CallLog.Calls;
30import android.provider.ContactsContract.CommonDataKinds.Phone;
31import android.text.BidiFormatter;
32import android.text.Spannable;
33import android.text.TextDirectionHeuristics;
34
35/**
36 * Represents a call log event interaction, wrapping the columns in
37 * {@link android.provider.CallLog.Calls}.
38 *
39 * This class does not return log entries related to voicemail or SIP calls. Additionally,
40 * this class ignores number presentation. Number presentation affects how to identify phone
41 * numbers. Since, we already know the identity of the phone number owner we can ignore number
42 * presentation.
43 *
44 * As a result of ignoring voicemail and number presentation, we don't need to worry about API
45 * version.
46 */
47public class CallLogInteraction implements ContactInteraction {
48
49    private static final String URI_TARGET_PREFIX = "tel:";
50    private static final int CALL_LOG_ICON_RES = R.drawable.ic_phone_24dp;
51    private static final int CALL_ARROW_ICON_RES = R.drawable.ic_call_arrow;
52    private static BidiFormatter sBidiFormatter = BidiFormatter.getInstance();
53
54    private ContentValues mValues;
55
56    public CallLogInteraction(ContentValues values) {
57        mValues = values;
58    }
59
60    @Override
61    public Intent getIntent() {
62        String number = getNumber();
63        return number == null ? null : new Intent(Intent.ACTION_CALL).setData(
64                Uri.parse(URI_TARGET_PREFIX + number));
65    }
66
67    @Override
68    public String getViewHeader(Context context) {
69        return getNumber();
70    }
71
72    @Override
73    public long getInteractionDate() {
74        Long date = getDate();
75        return date == null ? -1 : date;
76    }
77
78    @Override
79    public String getViewBody(Context context) {
80        Integer numberType = getCachedNumberType();
81        if (numberType == null) {
82            return null;
83        }
84        return Phone.getTypeLabel(context.getResources(), getCachedNumberType(),
85                getCachedNumberLabel()).toString();
86    }
87
88    @Override
89    public String getViewFooter(Context context) {
90        Long date = getDate();
91        return date == null ? null : ContactInteractionUtil.formatDateStringFromTimestamp(
92                date, context);
93    }
94
95    @Override
96    public Drawable getIcon(Context context) {
97        return context.getResources().getDrawable(CALL_LOG_ICON_RES);
98    }
99
100    @Override
101    public Drawable getBodyIcon(Context context) {
102        return null;
103    }
104
105    @Override
106    public Drawable getFooterIcon(Context context) {
107        Drawable callArrow = null;
108        Resources res = context.getResources();
109        Integer type = getType();
110        if (type == null) {
111            return null;
112        }
113        switch (type) {
114            case Calls.INCOMING_TYPE:
115                callArrow = res.getDrawable(CALL_ARROW_ICON_RES);
116                callArrow.setColorFilter(res.getColor(R.color.call_arrow_green),
117                        PorterDuff.Mode.MULTIPLY);
118                break;
119            case Calls.MISSED_TYPE:
120                callArrow = res.getDrawable(CALL_ARROW_ICON_RES);
121                callArrow.setColorFilter(res.getColor(R.color.call_arrow_red),
122                        PorterDuff.Mode.MULTIPLY);
123                break;
124            case Calls.OUTGOING_TYPE:
125                callArrow = BitmapUtil.getRotatedDrawable(res, CALL_ARROW_ICON_RES, 180f);
126                callArrow.setColorFilter(res.getColor(R.color.call_arrow_green),
127                        PorterDuff.Mode.MULTIPLY);
128                break;
129        }
130        return callArrow;
131    }
132
133    public String getCachedName() {
134        return mValues.getAsString(Calls.CACHED_NAME);
135    }
136
137    public String getCachedNumberLabel() {
138        return mValues.getAsString(Calls.CACHED_NUMBER_LABEL);
139    }
140
141    public Integer getCachedNumberType() {
142        return mValues.getAsInteger(Calls.CACHED_NUMBER_TYPE);
143    }
144
145    public Long getDate() {
146        return mValues.getAsLong(Calls.DATE);
147    }
148
149    public Long getDuration() {
150        return mValues.getAsLong(Calls.DURATION);
151    }
152
153    public Boolean getIsRead() {
154        return mValues.getAsBoolean(Calls.IS_READ);
155    }
156
157    public Integer getLimitParamKey() {
158        return mValues.getAsInteger(Calls.LIMIT_PARAM_KEY);
159    }
160
161    public Boolean getNew() {
162        return mValues.getAsBoolean(Calls.NEW);
163    }
164
165    public String getNumber() {
166        final String number = mValues.getAsString(Calls.NUMBER);
167        return number == null ? null :
168            sBidiFormatter.unicodeWrap(number, TextDirectionHeuristics.LTR);
169    }
170
171    public Integer getNumberPresentation() {
172        return mValues.getAsInteger(Calls.NUMBER_PRESENTATION);
173    }
174
175    public Integer getOffsetParamKey() {
176        return mValues.getAsInteger(Calls.OFFSET_PARAM_KEY);
177    }
178
179    public Integer getType() {
180        return mValues.getAsInteger(Calls.TYPE);
181    }
182
183    @Override
184    public Spannable getContentDescription(Context context) {
185        final String phoneNumber = getViewHeader(context);
186        final String contentDescription = context.getResources().getString(
187                R.string.content_description_recent_call,
188                getCallTypeString(context), phoneNumber, getViewFooter(context));
189        return ContactDisplayUtils.getTelephoneTtsSpannable(contentDescription, phoneNumber);
190    }
191
192    private String getCallTypeString(Context context) {
193        String callType = "";
194        Resources res = context.getResources();
195        Integer type = getType();
196        if (type == null) {
197            return callType;
198        }
199        switch (type) {
200            case Calls.INCOMING_TYPE:
201                callType = res.getString(R.string.content_description_recent_call_type_incoming);
202                break;
203            case Calls.MISSED_TYPE:
204                callType = res.getString(R.string.content_description_recent_call_type_missed);
205                break;
206            case Calls.OUTGOING_TYPE:
207                callType = res.getString(R.string.content_description_recent_call_type_outgoing);
208                break;
209        }
210        return callType;
211    }
212
213    @Override
214    public int getIconResourceId() {
215        return CALL_LOG_ICON_RES;
216    }
217}
218