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 */ 16 package com.android.contacts.interactions; 17 18 import com.android.contacts.R; 19 import com.android.contacts.common.util.BitmapUtil; 20 import com.android.contacts.common.util.ContactDisplayUtils; 21 22 import android.content.ContentValues; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.res.Resources; 26 import android.graphics.PorterDuff; 27 import android.graphics.drawable.Drawable; 28 import android.net.Uri; 29 import android.provider.CallLog.Calls; 30 import android.provider.ContactsContract.CommonDataKinds.Phone; 31 import android.text.BidiFormatter; 32 import android.text.Spannable; 33 import 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 */ 47 public 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