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; 207ce5352a70e8aaf120bf4f7bd05d595f46abb080Walter Jangimport com.android.contacts.common.util.ContactDisplayUtils; 21ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 22ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulosimport android.content.ContentValues; 23ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulosimport android.content.Context; 24ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulosimport android.content.Intent; 25ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulosimport android.content.res.Resources; 26ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulosimport android.graphics.PorterDuff; 27ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulosimport android.graphics.drawable.Drawable; 28ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulosimport android.net.Uri; 29ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulosimport android.provider.CallLog.Calls; 30ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulosimport android.provider.ContactsContract.CommonDataKinds.Phone; 31c62cc7931593b4137f8a507689b653e1e15e1260Brian Attwellimport android.text.BidiFormatter; 327ce5352a70e8aaf120bf4f7bd05d595f46abb080Walter Jangimport android.text.Spannable; 33c62cc7931593b4137f8a507689b653e1e15e1260Brian Attwellimport android.text.TextDirectionHeuristics; 34ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 35ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos/** 36ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos * Represents a call log event interaction, wrapping the columns in 37ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos * {@link android.provider.CallLog.Calls}. 38ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos * 39ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos * This class does not return log entries related to voicemail or SIP calls. Additionally, 40ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos * this class ignores number presentation. Number presentation affects how to identify phone 41ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos * numbers. Since, we already know the identity of the phone number owner we can ignore number 42ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos * presentation. 43ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos * 44ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos * As a result of ignoring voicemail and number presentation, we don't need to worry about API 45ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos * version. 46ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos */ 47ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulospublic class CallLogInteraction implements ContactInteraction { 48ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 49ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos private static final String URI_TARGET_PREFIX = "tel:"; 50ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos private static final int CALL_LOG_ICON_RES = R.drawable.ic_phone_24dp; 51ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos private static final int CALL_ARROW_ICON_RES = R.drawable.ic_call_arrow; 52c62cc7931593b4137f8a507689b653e1e15e1260Brian Attwell private static BidiFormatter sBidiFormatter = BidiFormatter.getInstance(); 53ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 54ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos private ContentValues mValues; 55ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 56ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos public CallLogInteraction(ContentValues values) { 57ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos mValues = values; 58ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos } 59ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 60ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos @Override 61ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos public Intent getIntent() { 6275d5a915cb764f610db6141148c57b1c8e080564Paul Soulos String number = getNumber(); 6375d5a915cb764f610db6141148c57b1c8e080564Paul Soulos return number == null ? null : new Intent(Intent.ACTION_CALL).setData( 6475d5a915cb764f610db6141148c57b1c8e080564Paul Soulos Uri.parse(URI_TARGET_PREFIX + number)); 65ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos } 66ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 67ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos @Override 68ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos public String getViewHeader(Context context) { 69ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos return getNumber(); 70ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos } 71ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 72ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos @Override 73ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos public long getInteractionDate() { 7475d5a915cb764f610db6141148c57b1c8e080564Paul Soulos Long date = getDate(); 7575d5a915cb764f610db6141148c57b1c8e080564Paul Soulos return date == null ? -1 : date; 76ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos } 77ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 78ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos @Override 79ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos public String getViewBody(Context context) { 8075d5a915cb764f610db6141148c57b1c8e080564Paul Soulos Integer numberType = getCachedNumberType(); 8175d5a915cb764f610db6141148c57b1c8e080564Paul Soulos if (numberType == null) { 82ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos return null; 83ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos } 84ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos return Phone.getTypeLabel(context.getResources(), getCachedNumberType(), 85ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos getCachedNumberLabel()).toString(); 86ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos } 87ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 88ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos @Override 89ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos public String getViewFooter(Context context) { 9075d5a915cb764f610db6141148c57b1c8e080564Paul Soulos Long date = getDate(); 9175d5a915cb764f610db6141148c57b1c8e080564Paul Soulos return date == null ? null : ContactInteractionUtil.formatDateStringFromTimestamp( 9275d5a915cb764f610db6141148c57b1c8e080564Paul Soulos date, context); 93ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos } 94ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 95ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos @Override 96ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos public Drawable getIcon(Context context) { 97ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos return context.getResources().getDrawable(CALL_LOG_ICON_RES); 98ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos } 99ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 100ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos @Override 101ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos public Drawable getBodyIcon(Context context) { 102ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos return null; 103ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos } 104ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 105ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos @Override 106ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos public Drawable getFooterIcon(Context context) { 107ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos Drawable callArrow = null; 108ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos Resources res = context.getResources(); 10975d5a915cb764f610db6141148c57b1c8e080564Paul Soulos Integer type = getType(); 11075d5a915cb764f610db6141148c57b1c8e080564Paul Soulos if (type == null) { 11175d5a915cb764f610db6141148c57b1c8e080564Paul Soulos return null; 11275d5a915cb764f610db6141148c57b1c8e080564Paul Soulos } 11375d5a915cb764f610db6141148c57b1c8e080564Paul Soulos switch (type) { 114ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos case Calls.INCOMING_TYPE: 115ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos callArrow = res.getDrawable(CALL_ARROW_ICON_RES); 116ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos callArrow.setColorFilter(res.getColor(R.color.call_arrow_green), 117ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos PorterDuff.Mode.MULTIPLY); 118ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos break; 119ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos case Calls.MISSED_TYPE: 120ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos callArrow = res.getDrawable(CALL_ARROW_ICON_RES); 121ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos callArrow.setColorFilter(res.getColor(R.color.call_arrow_red), 122ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos PorterDuff.Mode.MULTIPLY); 123ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos break; 124ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos case Calls.OUTGOING_TYPE: 125ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos callArrow = BitmapUtil.getRotatedDrawable(res, CALL_ARROW_ICON_RES, 180f); 126ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos callArrow.setColorFilter(res.getColor(R.color.call_arrow_green), 127ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos PorterDuff.Mode.MULTIPLY); 128ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos break; 129ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos } 130ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos return callArrow; 131ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos } 132ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 133ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos public String getCachedName() { 134ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos return mValues.getAsString(Calls.CACHED_NAME); 135ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos } 136ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 137ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos public String getCachedNumberLabel() { 138ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos return mValues.getAsString(Calls.CACHED_NUMBER_LABEL); 139ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos } 140ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 14175d5a915cb764f610db6141148c57b1c8e080564Paul Soulos public Integer getCachedNumberType() { 14275d5a915cb764f610db6141148c57b1c8e080564Paul Soulos return mValues.getAsInteger(Calls.CACHED_NUMBER_TYPE); 143ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos } 144ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 14575d5a915cb764f610db6141148c57b1c8e080564Paul Soulos public Long getDate() { 146ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos return mValues.getAsLong(Calls.DATE); 147ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos } 148ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 14975d5a915cb764f610db6141148c57b1c8e080564Paul Soulos public Long getDuration() { 150ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos return mValues.getAsLong(Calls.DURATION); 151ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos } 152ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 15375d5a915cb764f610db6141148c57b1c8e080564Paul Soulos public Boolean getIsRead() { 154ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos return mValues.getAsBoolean(Calls.IS_READ); 155ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos } 156ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 15775d5a915cb764f610db6141148c57b1c8e080564Paul Soulos public Integer getLimitParamKey() { 158ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos return mValues.getAsInteger(Calls.LIMIT_PARAM_KEY); 159ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos } 160ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 16175d5a915cb764f610db6141148c57b1c8e080564Paul Soulos public Boolean getNew() { 162ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos return mValues.getAsBoolean(Calls.NEW); 163ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos } 164ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 165ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos public String getNumber() { 166b2215766433478ac1c53d61c08f4844326dfe4f8Jay Shrauner final String number = mValues.getAsString(Calls.NUMBER); 167b2215766433478ac1c53d61c08f4844326dfe4f8Jay Shrauner return number == null ? null : 168b2215766433478ac1c53d61c08f4844326dfe4f8Jay Shrauner sBidiFormatter.unicodeWrap(number, TextDirectionHeuristics.LTR); 169ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos } 170ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 17175d5a915cb764f610db6141148c57b1c8e080564Paul Soulos public Integer getNumberPresentation() { 172ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos return mValues.getAsInteger(Calls.NUMBER_PRESENTATION); 173ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos } 174ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 17575d5a915cb764f610db6141148c57b1c8e080564Paul Soulos public Integer getOffsetParamKey() { 176ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos return mValues.getAsInteger(Calls.OFFSET_PARAM_KEY); 177ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos } 178ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos 17975d5a915cb764f610db6141148c57b1c8e080564Paul Soulos public Integer getType() { 180ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos return mValues.getAsInteger(Calls.TYPE); 181ab840448dd00ce3f02ec7317df69b24613ade8a9Paul Soulos } 18223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos 18323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos @Override 1847ce5352a70e8aaf120bf4f7bd05d595f46abb080Walter Jang public Spannable getContentDescription(Context context) { 1857ce5352a70e8aaf120bf4f7bd05d595f46abb080Walter Jang final String phoneNumber = getViewHeader(context); 1867ce5352a70e8aaf120bf4f7bd05d595f46abb080Walter Jang final String contentDescription = context.getResources().getString( 1877ce5352a70e8aaf120bf4f7bd05d595f46abb080Walter Jang R.string.content_description_recent_call, 1887ce5352a70e8aaf120bf4f7bd05d595f46abb080Walter Jang getCallTypeString(context), phoneNumber, getViewFooter(context)); 1897ce5352a70e8aaf120bf4f7bd05d595f46abb080Walter Jang return ContactDisplayUtils.getTelephoneTtsSpannable(contentDescription, phoneNumber); 19023e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos } 19123e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos 19223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos private String getCallTypeString(Context context) { 19323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos String callType = ""; 19423e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos Resources res = context.getResources(); 19523e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos Integer type = getType(); 19623e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos if (type == null) { 19723e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos return callType; 19823e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos } 19923e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos switch (type) { 20023e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos case Calls.INCOMING_TYPE: 20123e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos callType = res.getString(R.string.content_description_recent_call_type_incoming); 20223e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos break; 20323e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos case Calls.MISSED_TYPE: 20423e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos callType = res.getString(R.string.content_description_recent_call_type_missed); 20523e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos break; 20623e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos case Calls.OUTGOING_TYPE: 20723e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos callType = res.getString(R.string.content_description_recent_call_type_outgoing); 20823e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos break; 20923e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos } 21023e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos return callType; 21123e2836c1e9cbe8996a1344301e69d67bb617891Paul Soulos } 21248290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos 21348290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos @Override 21448290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos public int getIconResourceId() { 21548290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos return CALL_LOG_ICON_RES; 21648290bed7c6a8bd5e7be8b206dddacf9047a945fPaul Soulos } 217b2215766433478ac1c53d61c08f4844326dfe4f8Jay Shrauner} 218