1 package com.android.dialer.list; 2 3 import android.content.Context; 4 import android.content.res.Resources; 5 import android.database.Cursor; 6 import android.telephony.PhoneNumberUtils; 7 import android.text.BidiFormatter; 8 import android.text.TextDirectionHeuristics; 9 import android.util.Log; 10 import android.view.View; 11 import android.view.ViewGroup; 12 13 import com.android.contacts.common.CallUtil; 14 import com.android.contacts.common.GeoUtil; 15 import com.android.contacts.common.list.ContactListItemView; 16 import com.android.contacts.common.list.PhoneNumberListAdapter; 17 import com.android.contacts.common.util.ContactDisplayUtils; 18 import com.android.dialer.R; 19 20 /** 21 * {@link PhoneNumberListAdapter} with the following added shortcuts, that are displayed as list 22 * items: 23 * 1) Directly calling the phone number query 24 * 2) Adding the phone number query to a contact 25 * 26 * These shortcuts can be enabled or disabled to toggle whether or not they show up in the 27 * list. 28 */ 29 public class DialerPhoneNumberListAdapter extends PhoneNumberListAdapter { 30 31 private String mFormattedQueryString; 32 private String mCountryIso; 33 34 public final static int SHORTCUT_INVALID = -1; 35 public final static int SHORTCUT_DIRECT_CALL = 0; 36 public final static int SHORTCUT_CREATE_NEW_CONTACT = 1; 37 public final static int SHORTCUT_ADD_TO_EXISTING_CONTACT = 2; 38 public final static int SHORTCUT_SEND_SMS_MESSAGE = 3; 39 public final static int SHORTCUT_MAKE_VIDEO_CALL = 4; 40 public final static int SHORTCUT_BLOCK_NUMBER = 5; 41 42 public final static int SHORTCUT_COUNT = 6; 43 44 private final boolean[] mShortcutEnabled = new boolean[SHORTCUT_COUNT]; 45 46 private final BidiFormatter mBidiFormatter = BidiFormatter.getInstance(); 47 private boolean mVideoCallingEnabled = false; 48 DialerPhoneNumberListAdapter(Context context)49 public DialerPhoneNumberListAdapter(Context context) { 50 super(context); 51 52 mCountryIso = GeoUtil.getCurrentCountryIso(context); 53 mVideoCallingEnabled = CallUtil.isVideoEnabled(context); 54 } 55 56 @Override getCount()57 public int getCount() { 58 return super.getCount() + getShortcutCount(); 59 } 60 61 /** 62 * @return The number of enabled shortcuts. Ranges from 0 to a maximum of SHORTCUT_COUNT 63 */ getShortcutCount()64 public int getShortcutCount() { 65 int count = 0; 66 for (int i = 0; i < mShortcutEnabled.length; i++) { 67 if (mShortcutEnabled[i]) count++; 68 } 69 return count; 70 } 71 disableAllShortcuts()72 public void disableAllShortcuts() { 73 for (int i = 0; i < mShortcutEnabled.length; i++) { 74 mShortcutEnabled[i] = false; 75 } 76 } 77 78 @Override getItemViewType(int position)79 public int getItemViewType(int position) { 80 final int shortcut = getShortcutTypeFromPosition(position); 81 if (shortcut >= 0) { 82 // shortcutPos should always range from 1 to SHORTCUT_COUNT 83 return super.getViewTypeCount() + shortcut; 84 } else { 85 return super.getItemViewType(position); 86 } 87 } 88 89 @Override getViewTypeCount()90 public int getViewTypeCount() { 91 // Number of item view types in the super implementation + 2 for the 2 new shortcuts 92 return super.getViewTypeCount() + SHORTCUT_COUNT; 93 } 94 95 @Override getView(int position, View convertView, ViewGroup parent)96 public View getView(int position, View convertView, ViewGroup parent) { 97 final int shortcutType = getShortcutTypeFromPosition(position); 98 if (shortcutType >= 0) { 99 if (convertView != null) { 100 assignShortcutToView((ContactListItemView) convertView, shortcutType); 101 return convertView; 102 } else { 103 final ContactListItemView v = new ContactListItemView(getContext(), null, 104 mVideoCallingEnabled); 105 assignShortcutToView(v, shortcutType); 106 return v; 107 } 108 } else { 109 return super.getView(position, convertView, parent); 110 } 111 } 112 113 @Override newView( Context context, int partition, Cursor cursor, int position, ViewGroup parent)114 protected ContactListItemView newView( 115 Context context, int partition, Cursor cursor, int position, ViewGroup parent) { 116 final ContactListItemView view = super.newView(context, partition, cursor, position, 117 parent); 118 119 view.setSupportVideoCallIcon(mVideoCallingEnabled); 120 return view; 121 } 122 123 /** 124 * @param position The position of the item 125 * @return The enabled shortcut type matching the given position if the item is a 126 * shortcut, -1 otherwise 127 */ getShortcutTypeFromPosition(int position)128 public int getShortcutTypeFromPosition(int position) { 129 int shortcutCount = position - super.getCount(); 130 if (shortcutCount >= 0) { 131 // Iterate through the array of shortcuts, looking only for shortcuts where 132 // mShortcutEnabled[i] is true 133 for (int i = 0; shortcutCount >= 0 && i < mShortcutEnabled.length; i++) { 134 if (mShortcutEnabled[i]) { 135 shortcutCount--; 136 if (shortcutCount < 0) return i; 137 } 138 } 139 throw new IllegalArgumentException("Invalid position - greater than cursor count " 140 + " but not a shortcut."); 141 } 142 return SHORTCUT_INVALID; 143 } 144 145 @Override isEmpty()146 public boolean isEmpty() { 147 return getShortcutCount() == 0 && super.isEmpty(); 148 } 149 150 @Override isEnabled(int position)151 public boolean isEnabled(int position) { 152 final int shortcutType = getShortcutTypeFromPosition(position); 153 if (shortcutType >= 0) { 154 return true; 155 } else { 156 return super.isEnabled(position); 157 } 158 } 159 assignShortcutToView(ContactListItemView v, int shortcutType)160 private void assignShortcutToView(ContactListItemView v, int shortcutType) { 161 final CharSequence text; 162 final int drawableId; 163 final Resources resources = getContext().getResources(); 164 final String number = getFormattedQueryString(); 165 switch (shortcutType) { 166 case SHORTCUT_DIRECT_CALL: 167 text = ContactDisplayUtils.getTtsSpannedPhoneNumber(resources, 168 R.string.search_shortcut_call_number, 169 mBidiFormatter.unicodeWrap(number, TextDirectionHeuristics.LTR)); 170 drawableId = R.drawable.ic_search_phone; 171 break; 172 case SHORTCUT_CREATE_NEW_CONTACT: 173 text = resources.getString(R.string.search_shortcut_create_new_contact); 174 drawableId = R.drawable.ic_search_add_contact; 175 break; 176 case SHORTCUT_ADD_TO_EXISTING_CONTACT: 177 text = resources.getString(R.string.search_shortcut_add_to_contact); 178 drawableId = R.drawable.ic_person_24dp; 179 break; 180 case SHORTCUT_SEND_SMS_MESSAGE: 181 text = resources.getString(R.string.search_shortcut_send_sms_message); 182 drawableId = R.drawable.ic_message_24dp; 183 break; 184 case SHORTCUT_MAKE_VIDEO_CALL: 185 text = resources.getString(R.string.search_shortcut_make_video_call); 186 drawableId = R.drawable.ic_videocam; 187 break; 188 case SHORTCUT_BLOCK_NUMBER: 189 text = resources.getString(R.string.search_shortcut_block_number); 190 drawableId = R.drawable.ic_not_interested_googblue_24dp; 191 break; 192 default: 193 throw new IllegalArgumentException("Invalid shortcut type"); 194 } 195 v.setDrawableResource(drawableId); 196 v.setDisplayName(text); 197 v.setPhotoPosition(super.getPhotoPosition()); 198 v.setAdjustSelectionBoundsEnabled(false); 199 } 200 201 /** 202 * @return True if the shortcut state (disabled vs enabled) was changed by this operation 203 */ setShortcutEnabled(int shortcutType, boolean visible)204 public boolean setShortcutEnabled(int shortcutType, boolean visible) { 205 final boolean changed = mShortcutEnabled[shortcutType] != visible; 206 mShortcutEnabled[shortcutType] = visible; 207 return changed; 208 } 209 getFormattedQueryString()210 public String getFormattedQueryString() { 211 return mFormattedQueryString; 212 } 213 214 @Override setQueryString(String queryString)215 public void setQueryString(String queryString) { 216 mFormattedQueryString = PhoneNumberUtils.formatNumber( 217 PhoneNumberUtils.normalizeNumber(queryString), mCountryIso); 218 super.setQueryString(queryString); 219 } 220 } 221