am 30d26326: Add directory photo support

* commit '30d26326568cb888430468370df6f6ab2ec12767':
  Add directory photo support
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 8734bc5..edea133 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -19,5 +19,5 @@
     <string name="more_string" msgid="8495478259330621990">"+<xliff:g id="COUNT">%1$s</xliff:g>"</string>
     <string name="copy_email" msgid="7869435992461603532">"Nakili anwani ya barua pepe"</string>
     <string name="copy_number" msgid="530057841276106843">"Nakili namba ya simu"</string>
-    <string name="done" msgid="2356320650733788862">"Leta"</string>
+    <string name="done" msgid="2356320650733788862">"Inayofuata"</string>
 </resources>
diff --git a/src/com/android/ex/chips/BaseRecipientAdapter.java b/src/com/android/ex/chips/BaseRecipientAdapter.java
index 28127cc..8ad4a94 100644
--- a/src/com/android/ex/chips/BaseRecipientAdapter.java
+++ b/src/com/android/ex/chips/BaseRecipientAdapter.java
@@ -144,7 +144,7 @@
     }
 
     /** Used to temporarily hold results in Cursor objects. */
-    private static class TemporaryEntry {
+    protected static class TemporaryEntry {
         public final String displayName;
         public final String destination;
         public final int destinationType;
@@ -154,6 +154,25 @@
         public final String thumbnailUriString;
         public final int displayNameSource;
 
+        public TemporaryEntry(
+                String displayName,
+                String destination,
+                int destinationType,
+                String destinationLabel,
+                long contactId,
+                long dataId,
+                String thumbnailUriString,
+                int displayNameSource) {
+            this.displayName = displayName;
+            this.destination = destination;
+            this.destinationType = destinationType;
+            this.destinationLabel = destinationLabel;
+            this.contactId = contactId;
+            this.dataId = dataId;
+            this.thumbnailUriString = thumbnailUriString;
+            this.displayNameSource = displayNameSource;
+        }
+
         public TemporaryEntry(Cursor cursor) {
             this.displayName = cursor.getString(Queries.Query.NAME);
             this.destination = cursor.getString(Queries.Query.DESTINATION);
@@ -326,7 +345,7 @@
     /**
      * An asynchronous filter that performs search in a particular directory.
      */
-    private final class DirectoryFilter extends Filter {
+    protected class DirectoryFilter extends Filter {
         private final DirectorySearchParams mParams;
         private int mLimit;
 
@@ -540,6 +559,10 @@
         }
     }
 
+    public Context getContext() {
+        return mContext;
+    }
+
     public int getQueryType() {
         return mQueryType;
     }
@@ -558,6 +581,16 @@
         return new DefaultFilter();
     }
 
+    /**
+     * An extesion to {@link RecipientAlternatesAdapter#getMatchingRecipients} that allows
+     * additional sources of contacts to be considered as matching recipients.
+     * @param addresses A set of addresses to be matched
+     * @return A list of matches or null if none found
+     */
+    public Map<String, RecipientEntry> getMatchingRecipients(Set<String> addresses) {
+        return null;
+    }
+
     public static List<DirectorySearchParams> setupOtherDirectories(Context context,
             Cursor directoryCursor, Account account) {
         final PackageManager packageManager = context.getPackageManager();
@@ -616,7 +649,7 @@
      * Starts search in other directories using {@link Filter}. Results will be handled in
      * {@link DirectoryFilter}.
      */
-    private void startSearchOtherDirectories(
+    protected void startSearchOtherDirectories(
             CharSequence constraint, List<DirectorySearchParams> paramsList, int limit) {
         final int count = paramsList.size();
         // Note: skipping the default partition (index 0), which has already been loaded
@@ -733,7 +766,7 @@
         mTempEntries = null;
     }
 
-    private List<RecipientEntry> getEntries() {
+    protected List<RecipientEntry> getEntries() {
         return mTempEntries != null ? mTempEntries : mEntries;
     }
 
diff --git a/src/com/android/ex/chips/RecipientAlternatesAdapter.java b/src/com/android/ex/chips/RecipientAlternatesAdapter.java
index ef34379..f64c166 100644
--- a/src/com/android/ex/chips/RecipientAlternatesAdapter.java
+++ b/src/com/android/ex/chips/RecipientAlternatesAdapter.java
@@ -73,9 +73,9 @@
         public void matchesNotFound(Set<String> unfoundAddresses);
     }
 
-    public static void getMatchingRecipients(Context context, ArrayList<String> inAddresses,
-            Account account, RecipientMatchCallback callback) {
-        getMatchingRecipients(context, inAddresses, QUERY_TYPE_EMAIL, account, callback);
+    public static void getMatchingRecipients(Context context, BaseRecipientAdapter adapter,
+            ArrayList<String> inAddresses, Account account, RecipientMatchCallback callback) {
+        getMatchingRecipients(context, adapter, inAddresses, QUERY_TYPE_EMAIL, account, callback);
     }
 
     /**
@@ -88,8 +88,9 @@
      * @param callback RecipientMatchCallback called when a match or matches are found.
      * @return HashMap<String,RecipientEntry>
      */
-    public static void getMatchingRecipients(Context context, ArrayList<String> inAddresses,
-            int addressType, Account account, RecipientMatchCallback callback) {
+    public static void getMatchingRecipients(Context context, BaseRecipientAdapter adapter,
+            ArrayList<String> inAddresses, int addressType, Account account,
+            RecipientMatchCallback callback) {
         Queries.Query query;
         if (addressType == QUERY_TYPE_EMAIL) {
             query = Queries.EMAIL;
@@ -197,6 +198,19 @@
             }
         }
 
+        // If no matches found in contact provider or the directories, try the extension
+        // matcher.
+        // todo (aalbert): This whole method needs to be in the adapter?
+        if (adapter != null) {
+            final Map<String, RecipientEntry> entries =
+                    adapter.getMatchingRecipients(matchesNotFound);
+            if (entries != null && entries.size() > 0) {
+                callback.matchesFound(entries);
+                for (final String address : entries.keySet()) {
+                    matchesNotFound.remove(address);
+                }
+            }
+        }
         callback.matchesNotFound(matchesNotFound);
     }
 
diff --git a/src/com/android/ex/chips/RecipientEditTextView.java b/src/com/android/ex/chips/RecipientEditTextView.java
index fefd273..e300354 100644
--- a/src/com/android/ex/chips/RecipientEditTextView.java
+++ b/src/com/android/ex/chips/RecipientEditTextView.java
@@ -17,18 +17,6 @@
 
 package com.android.ex.chips;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
 import android.app.Dialog;
 import android.content.ClipData;
 import android.content.ClipDescription;
@@ -100,6 +88,18 @@
 import com.android.ex.chips.recipientchip.InvisibleRecipientChip;
 import com.android.ex.chips.recipientchip.VisibleRecipientChip;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
 /**
  * RecipientEditTextView is an auto complete text view for use with applications
  * that use the new Chips UI for addressing a message to recipients.
@@ -2506,7 +2506,7 @@
                 }
             }
             final BaseRecipientAdapter adapter = (BaseRecipientAdapter) getAdapter();
-            RecipientAlternatesAdapter.getMatchingRecipients(getContext(), addresses,
+            RecipientAlternatesAdapter.getMatchingRecipients(getContext(), adapter, addresses,
                     adapter.getAccount(), new RecipientMatchCallback() {
                         @Override
                         public void matchesFound(Map<String, RecipientEntry> entries) {
@@ -2633,7 +2633,8 @@
                     addresses.add(createAddressText(chip.getEntry()));
                 }
             }
-            RecipientAlternatesAdapter.getMatchingRecipients(getContext(), addresses,
+            final BaseRecipientAdapter adapter = (BaseRecipientAdapter) getAdapter();
+            RecipientAlternatesAdapter.getMatchingRecipients(getContext(), adapter, addresses,
                     ((BaseRecipientAdapter) getAdapter()).getAccount(),
                     new RecipientMatchCallback() {
 
@@ -2644,21 +2645,14 @@
                                         .getContactId())
                                         && getSpannable().getSpanStart(temp) != -1) {
                                     // Replace this.
-                                    RecipientEntry entry = createValidatedEntry(entries
+                                    final RecipientEntry entry = createValidatedEntry(entries
                                             .get(tokenizeAddress(temp.getEntry().getDestination())
                                                     .toLowerCase()));
-                                    // If we don't have a validated contact
-                                    // match, just use the
-                                    // entry as it existed before.
-                                    if (entry == null && !isPhoneQuery()) {
-                                        entry = temp.getEntry();
-                                    }
-                                    final RecipientEntry tempEntry = entry;
-                                    if (tempEntry != null) {
+                                    if (entry != null) {
                                         mHandler.post(new Runnable() {
                                             @Override
                                             public void run() {
-                                                replaceChip(temp, tempEntry);
+                                                replaceChip(temp, entry);
                                             }
                                         });
                                     }