Adding listener thats notified when chips checks permission.
am: 4b01e3b

* commit '4b01e3b35a9634336e5de163ba7c4110785bf221':
  Adding listener thats notified when chips checks permission.
diff --git a/src/com/android/ex/chips/BaseRecipientAdapter.java b/src/com/android/ex/chips/BaseRecipientAdapter.java
index 38b4b5b..2c394f8 100644
--- a/src/com/android/ex/chips/BaseRecipientAdapter.java
+++ b/src/com/android/ex/chips/BaseRecipientAdapter.java
@@ -30,6 +30,7 @@
 import android.os.Message;
 import android.provider.ContactsContract;
 import android.provider.ContactsContract.Directory;
+import android.support.annotation.Nullable;
 import android.text.TextUtils;
 import android.text.util.Rfc822Token;
 import android.util.Log;
@@ -40,6 +41,7 @@
 import android.widget.Filter;
 import android.widget.Filterable;
 
+import com.android.ex.chips.ChipsUtil.PermissionsCheckListener;
 import com.android.ex.chips.DropdownChipLayouter.AdapterType;
 
 import java.util.ArrayList;
@@ -238,7 +240,7 @@
                 return results;
             }
 
-            if (!ChipsUtil.hasPermissions(mContext)) {
+            if (!ChipsUtil.hasPermissions(mContext, mPermissionsCheckListener)) {
                 if (DEBUG) {
                     Log.d(TAG, "No Contacts permission. mShowRequestPermissionsItem: "
                             + mShowRequestPermissionsItem);
@@ -351,7 +353,7 @@
      * {@code null} when we don't need or can't search other directories.
      */
     protected List<DirectorySearchParams> searchOtherDirectories(Set<String> existingDestinations) {
-        if (!ChipsUtil.hasPermissions(mContext)) {
+        if (!ChipsUtil.hasPermissions(mContext, mPermissionsCheckListener)) {
             // If we don't have permissions we can't search other directories.
             if (DEBUG) {
                 Log.d(TAG, "Not searching other directories because we don't have required "
@@ -541,6 +543,8 @@
 
     protected boolean mShowRequestPermissionsItem;
 
+    private PermissionsCheckListener mPermissionsCheckListener;
+
     /**
      * Handler specific for maintaining "Waiting for more contacts" message, which will be shown
      * when:
@@ -622,6 +626,15 @@
         return mDropdownChipLayouter;
     }
 
+    public void setPermissionsCheckListener(PermissionsCheckListener permissionsCheckListener) {
+        mPermissionsCheckListener = permissionsCheckListener;
+    }
+
+    @Nullable
+    public PermissionsCheckListener getPermissionsCheckListener() {
+        return mPermissionsCheckListener;
+    }
+
     /**
      * Enables overriding the default photo manager that is used.
      */
@@ -653,7 +666,7 @@
     public void getMatchingRecipients(ArrayList<String> inAddresses,
             RecipientAlternatesAdapter.RecipientMatchCallback callback) {
         RecipientAlternatesAdapter.getMatchingRecipients(
-                getContext(), this, inAddresses, getAccount(), callback);
+                getContext(), this, inAddresses, getAccount(), callback, mPermissionsCheckListener);
     }
 
     /**
@@ -916,7 +929,7 @@
     }
 
     private Cursor doQuery(CharSequence constraint, int limit, Long directoryId) {
-        if (!ChipsUtil.hasPermissions(mContext)) {
+        if (!ChipsUtil.hasPermissions(mContext, mPermissionsCheckListener)) {
             if (DEBUG) {
                 Log.d(TAG, "Not doing query because we don't have required permissions.");
             }
diff --git a/src/com/android/ex/chips/ChipsUtil.java b/src/com/android/ex/chips/ChipsUtil.java
index e0471dc..3509f0e 100644
--- a/src/com/android/ex/chips/ChipsUtil.java
+++ b/src/com/android/ex/chips/ChipsUtil.java
@@ -21,10 +21,18 @@
 import android.content.pm.PackageManager;
 import android.os.Build;
 import android.os.Process;
+import android.support.annotation.Nullable;
 
 public class ChipsUtil {
 
     /**
+     * Listener that gets notified when we check whether we have permission.
+     */
+    public interface PermissionsCheckListener {
+        void onPermissionCheck(String permission, boolean granted);
+    }
+
+    /**
      * Permissions required by Chips library.
      */
     public static final String[] REQUIRED_PERMISSIONS =
@@ -64,10 +72,19 @@
 
     /**
      * Returns true if all permissions in {@link #REQUIRED_PERMISSIONS} are granted.
+     *
+     * <p>If {@link PermissionsCheckListener} is specified it will be called for every
+     * {@link #checkPermission} call.
      */
-    public static boolean hasPermissions(Context context) {
+    public static boolean hasPermissions(Context context,
+            @Nullable PermissionsCheckListener permissionsCheckListener) {
         for (String permission : REQUIRED_PERMISSIONS) {
-            if (checkPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
+            final boolean granted =
+                    checkPermission(context, permission) == PackageManager.PERMISSION_GRANTED;
+            if (permissionsCheckListener != null) {
+                permissionsCheckListener.onPermissionCheck(permission, granted);
+            }
+            if (!granted) {
                 return false;
             }
         }
diff --git a/src/com/android/ex/chips/RecipientAlternatesAdapter.java b/src/com/android/ex/chips/RecipientAlternatesAdapter.java
index 69564bc..cc19700 100644
--- a/src/com/android/ex/chips/RecipientAlternatesAdapter.java
+++ b/src/com/android/ex/chips/RecipientAlternatesAdapter.java
@@ -76,8 +76,10 @@
     }
 
     public static void getMatchingRecipients(Context context, BaseRecipientAdapter adapter,
-            ArrayList<String> inAddresses, Account account, RecipientMatchCallback callback) {
-        getMatchingRecipients(context, adapter, inAddresses, QUERY_TYPE_EMAIL, account, callback);
+            ArrayList<String> inAddresses, Account account, RecipientMatchCallback callback,
+            ChipsUtil.PermissionsCheckListener permissionsCheckListener) {
+        getMatchingRecipients(context, adapter, inAddresses, QUERY_TYPE_EMAIL, account, callback,
+                permissionsCheckListener);
     }
 
     /**
@@ -91,7 +93,8 @@
      */
     public static void getMatchingRecipients(Context context, BaseRecipientAdapter adapter,
             ArrayList<String> inAddresses, int addressType, Account account,
-            RecipientMatchCallback callback) {
+            RecipientMatchCallback callback,
+            ChipsUtil.PermissionsCheckListener permissionsCheckListener) {
         Queries.Query query;
         if (addressType == QUERY_TYPE_EMAIL) {
             query = Queries.EMAIL;
@@ -121,7 +124,7 @@
         Cursor c = null;
 
         try {
-            if (ChipsUtil.hasPermissions(context)) {
+            if (ChipsUtil.hasPermissions(context, permissionsCheckListener)) {
                 c = context.getContentResolver().query(
                         query.getContentUri(),
                         query.getProjection(),
@@ -139,7 +142,7 @@
         final Set<String> matchesNotFound = new HashSet<String>();
 
         getMatchingRecipientsFromDirectoryQueries(context, recipientEntries,
-                addresses, account, matchesNotFound, query, callback);
+                addresses, account, matchesNotFound, query, callback, permissionsCheckListener);
 
         getMatchingRecipientsFromExtensionMatcher(adapter, matchesNotFound, callback);
     }
@@ -147,16 +150,18 @@
     public static void getMatchingRecipientsFromDirectoryQueries(Context context,
             Map<String, RecipientEntry> recipientEntries, Set<String> addresses,
             Account account, Set<String> matchesNotFound,
-            RecipientMatchCallback callback) {
+            RecipientMatchCallback callback,
+            ChipsUtil.PermissionsCheckListener permissionsCheckListener) {
         getMatchingRecipientsFromDirectoryQueries(
                 context, recipientEntries, addresses, account,
-                matchesNotFound, Queries.EMAIL, callback);
+                matchesNotFound, Queries.EMAIL, callback, permissionsCheckListener);
     }
 
     private static void getMatchingRecipientsFromDirectoryQueries(Context context,
             Map<String, RecipientEntry> recipientEntries, Set<String> addresses,
             Account account, Set<String> matchesNotFound, Queries.Query query,
-            RecipientMatchCallback callback) {
+            RecipientMatchCallback callback,
+            ChipsUtil.PermissionsCheckListener permissionsCheckListener) {
         // See if any entries did not resolve; if so, we need to check other
         // directories
 
@@ -173,7 +178,7 @@
             final List<DirectorySearchParams> paramsList;
             Cursor directoryCursor = null;
             try {
-                if (ChipsUtil.hasPermissions(context)) {
+                if (ChipsUtil.hasPermissions(context, permissionsCheckListener)) {
                     directoryCursor = context.getContentResolver().query(
                             DirectoryListQuery.URI, DirectoryListQuery.PROJECTION,
                             null, null, null);
@@ -196,7 +201,7 @@
                         final long directoryId = paramsList.get(i).directoryId;
                         try {
                             directoryContactsCursor = doQuery(unresolvedAddress, 1 /* limit */,
-                                    directoryId, account, context, query);
+                                    directoryId, account, context, query, permissionsCheckListener);
                             if (directoryContactsCursor != null
                                     && directoryContactsCursor.getCount() != 0) {
                                 // We found the directory with at least one contact
@@ -335,8 +340,9 @@
     }
 
     private static Cursor doQuery(CharSequence constraint, int limit, Long directoryId,
-            Account account, Context context, Query query) {
-        if (!ChipsUtil.hasPermissions(context)) {
+            Account account, Context context, Query query,
+            ChipsUtil.PermissionsCheckListener permissionsCheckListener) {
+        if (!ChipsUtil.hasPermissions(context, permissionsCheckListener)) {
             if (Log.isLoggable(TAG, Log.DEBUG)) {
                 Log.d(TAG, "Not doing query because we don't have required permissions.");
             }
@@ -362,16 +368,20 @@
 
     public RecipientAlternatesAdapter(Context context, long contactId, Long directoryId,
             String lookupKey, long currentId, int queryMode, OnCheckedItemChangedListener listener,
-            DropdownChipLayouter dropdownChipLayouter) {
+            DropdownChipLayouter dropdownChipLayouter,
+            ChipsUtil.PermissionsCheckListener permissionsCheckListener) {
         this(context, contactId, directoryId, lookupKey, currentId, queryMode, listener,
-                dropdownChipLayouter, null);
+                dropdownChipLayouter, null, permissionsCheckListener);
     }
 
     public RecipientAlternatesAdapter(Context context, long contactId, Long directoryId,
             String lookupKey, long currentId, int queryMode, OnCheckedItemChangedListener listener,
-            DropdownChipLayouter dropdownChipLayouter, StateListDrawable deleteDrawable) {
+            DropdownChipLayouter dropdownChipLayouter, StateListDrawable deleteDrawable,
+            ChipsUtil.PermissionsCheckListener permissionsCheckListener) {
         super(context,
-                getCursorForConstruction(context, contactId, directoryId, lookupKey, queryMode), 0);
+                getCursorForConstruction(context, contactId, directoryId, lookupKey, queryMode,
+                        permissionsCheckListener),
+                0);
         mCurrentId = currentId;
         mDirectoryId = directoryId;
         mCheckedItemChangedListener = listener;
@@ -381,7 +391,8 @@
     }
 
     private static Cursor getCursorForConstruction(Context context, long contactId,
-            Long directoryId, String lookupKey, int queryType) {
+            Long directoryId, String lookupKey, int queryType,
+            ChipsUtil.PermissionsCheckListener permissionsCheckListener) {
         final Uri uri;
         final String desiredMimeType;
         final String[] projection;
@@ -423,7 +434,7 @@
                 .append(" = ?")
                 .toString();
         final Cursor cursor;
-        if (ChipsUtil.hasPermissions(context)) {
+        if (ChipsUtil.hasPermissions(context, permissionsCheckListener)) {
             cursor = context.getContentResolver().query(
                     uri, projection, selection, new String[] {String.valueOf(contactId)}, null);
         } else {
diff --git a/src/com/android/ex/chips/RecipientEditTextView.java b/src/com/android/ex/chips/RecipientEditTextView.java
index 5b06ca1..c0f37ad 100644
--- a/src/com/android/ex/chips/RecipientEditTextView.java
+++ b/src/com/android/ex/chips/RecipientEditTextView.java
@@ -960,19 +960,6 @@
     }
 
     /**
-     * Calculate the bottom of the line the chip will be located on using:
-     * 1) which line the chip appears on
-     * 2) the height of a chip
-     * 3) padding built into the edit text view
-     */
-    private int calculateOffsetFromBottom(int line) {
-        // Line offsets start at zero.
-        int actualLine = getLineCount() - (line + 1);
-        return -((actualLine * ((int) mChipHeight) + getPaddingBottom()) + getPaddingTop())
-                + getDropDownVerticalOffset();
-    }
-
-    /**
      * Calculate the offset from bottom of the EditText to top of the provided line.
      */
     private int calculateOffsetFromBottomToTop(int line) {
@@ -1776,7 +1763,7 @@
         return new RecipientAlternatesAdapter(getContext(), chip.getContactId(),
                 chip.getDirectoryId(), chip.getLookupKey(), chip.getDataId(),
                 getAdapter().getQueryType(), this, mDropdownChipLayouter,
-                constructStateListDeleteDrawable());
+                constructStateListDeleteDrawable(), getAdapter().getPermissionsCheckListener());
     }
 
     private ListAdapter createSingleAddressAdapter(DrawableRecipientChip currentChip) {