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