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;
20
21import android.content.ContentValues;
22import android.content.Context;
23import android.content.Intent;
24import android.content.res.Resources;
25import android.graphics.PorterDuff;
26import android.graphics.drawable.Drawable;
27import android.net.Uri;
28import android.provider.CallLog.Calls;
29import android.provider.ContactsContract.CommonDataKinds.Phone;
30import android.text.BidiFormatter;
31import android.text.TextDirectionHeuristics;
32
33/**
34 * Represents a call log event interaction, wrapping the columns in
35 * {@link android.provider.CallLog.Calls}.
36 *
37 * This class does not return log entries related to voicemail or SIP calls. Additionally,
38 * this class ignores number presentation. Number presentation affects how to identify phone
39 * numbers. Since, we already know the identity of the phone number owner we can ignore number
40 * presentation.
41 *
42 * As a result of ignoring voicemail and number presentation, we don't need to worry about API
43 * version.
44 */
45public class CallLogInteraction implements ContactInteraction {
46
47    private static final String URI_TARGET_PREFIX = "tel:";
48    private static final int CALL_LOG_ICON_RES = R.drawable.ic_phone_24dp;
49    private static final int CALL_ARROW_ICON_RES = R.drawable.ic_call_arrow;
50    private static BidiFormatter sBidiFormatter = BidiFormatter.getInstance();
51
52    private ContentValues mValues;
53
54    public CallLogInteraction(ContentValues values) {
55        mValues = values;
56    }
57
58    @Override
59    public Intent getIntent() {
60        String number = getNumber();
61        return number == null ? null : new Intent(Intent.ACTION_CALL).setData(
62                Uri.parse(URI_TARGET_PREFIX + number));
63    }
64
65    @Override
66    public String getViewHeader(Context context) {
67        return getNumber();
68    }
69
70    @Override
71    public long getInteractionDate() {
72        Long date = getDate();
73        return date == null ? -1 : date;
74    }
75
76    @Override
77    public String getViewBody(Context context) {
78        Integer numberType = getCachedNumberType();
79        if (numberType == null) {
80            return null;
81        }
82        return Phone.getTypeLabel(context.getResources(), getCachedNumberType(),
83                getCachedNumberLabel()).toString();
84    }
85
86    @Override
87    public String getViewFooter(Context context) {
88        Long date = getDate();
89        return date == null ? null : ContactInteractionUtil.formatDateStringFromTimestamp(
90                date, context);
91    }
92
93    @Override
94    public Drawable getIcon(Context context) {
95        return context.getResources().getDrawable(CALL_LOG_ICON_RES);
96    }
97
98    @Override
99    public Drawable getBodyIcon(Context context) {
100        return null;
101    }
102
103    @Override
104    public Drawable getFooterIcon(Context context) {
105        Drawable callArrow = null;
106        Resources res = context.getResources();
107        Integer type = getType();
108        if (type == null) {
109            return null;
110        }
111        switch (type) {
112            case Calls.INCOMING_TYPE:
113                callArrow = res.getDrawable(CALL_ARROW_ICON_RES);
114                callArrow.setColorFilter(res.getColor(R.color.call_arrow_green),
115                        PorterDuff.Mode.MULTIPLY);
116                break;
117            case Calls.MISSED_TYPE:
118                callArrow = res.getDrawable(CALL_ARROW_ICON_RES);
119                callArrow.setColorFilter(res.getColor(R.color.call_arrow_red),
120                        PorterDuff.Mode.MULTIPLY);
121                break;
122            case Calls.OUTGOING_TYPE:
123                callArrow = BitmapUtil.getRotatedDrawable(res, CALL_ARROW_ICON_RES, 180f);
124                callArrow.setColorFilter(res.getColor(R.color.call_arrow_green),
125                        PorterDuff.Mode.MULTIPLY);
126                break;
127        }
128        return callArrow;
129    }
130
131    public String getCachedName() {
132        return mValues.getAsString(Calls.CACHED_NAME);
133    }
134
135    public String getCachedNumberLabel() {
136        return mValues.getAsString(Calls.CACHED_NUMBER_LABEL);
137    }
138
139    public Integer getCachedNumberType() {
140        return mValues.getAsInteger(Calls.CACHED_NUMBER_TYPE);
141    }
142
143    public Long getDate() {
144        return mValues.getAsLong(Calls.DATE);
145    }
146
147    public Long getDuration() {
148        return mValues.getAsLong(Calls.DURATION);
149    }
150
151    public Boolean getIsRead() {
152        return mValues.getAsBoolean(Calls.IS_READ);
153    }
154
155    public Integer getLimitParamKey() {
156        return mValues.getAsInteger(Calls.LIMIT_PARAM_KEY);
157    }
158
159    public Boolean getNew() {
160        return mValues.getAsBoolean(Calls.NEW);
161    }
162
163    public String getNumber() {
164        final String number = mValues.getAsString(Calls.NUMBER);
165        return number == null ? null :
166            sBidiFormatter.unicodeWrap(number, TextDirectionHeuristics.LTR);
167    }
168
169    public Integer getNumberPresentation() {
170        return mValues.getAsInteger(Calls.NUMBER_PRESENTATION);
171    }
172
173    public Integer getOffsetParamKey() {
174        return mValues.getAsInteger(Calls.OFFSET_PARAM_KEY);
175    }
176
177    public Integer getType() {
178        return mValues.getAsInteger(Calls.TYPE);
179    }
180
181    @Override
182    public String getContentDescription(Context context) {
183        String callDetails = getCallTypeString(context) + ". " + getViewFooter(context) + ". " +
184                getViewHeader(context) + ". " + getViewFooter(context);
185        return context.getResources().getString(R.string.content_description_recent_call,
186                callDetails);
187    }
188
189    private String getCallTypeString(Context context) {
190        String callType = "";
191        Resources res = context.getResources();
192        Integer type = getType();
193        if (type == null) {
194            return callType;
195        }
196        switch (type) {
197            case Calls.INCOMING_TYPE:
198                callType = res.getString(R.string.content_description_recent_call_type_incoming);
199                break;
200            case Calls.MISSED_TYPE:
201                callType = res.getString(R.string.content_description_recent_call_type_missed);
202                break;
203            case Calls.OUTGOING_TYPE:
204                callType = res.getString(R.string.content_description_recent_call_type_outgoing);
205                break;
206        }
207        return callType;
208    }
209
210    @Override
211    public int getIconResourceId() {
212        return CALL_LOG_ICON_RES;
213    }
214}
215