Merge tag 'android-11.0.0_r48' into int/11/fp3

Android 11.0.0 Release 48 (RD2A.211001.002)

* tag 'android-11.0.0_r48':

Change-Id: Ic809761c60911a7ecfc7b43864d8b46938137c05
diff --git a/src/com/android/ex/chips/RecipientAlternatesAdapter.java b/src/com/android/ex/chips/RecipientAlternatesAdapter.java
old mode 100644
new mode 100755
index cc19700..992055c
--- a/src/com/android/ex/chips/RecipientAlternatesAdapter.java
+++ b/src/com/android/ex/chips/RecipientAlternatesAdapter.java
@@ -415,7 +415,7 @@
         } else {
             projection = Queries.PHONE.getProjection();
 
-            if (lookupKey == null) {
+            if (directoryId == null || lookupKey == null) {
                 uri = Queries.PHONE.getContentUri();
                 desiredMimeType = null;
             } else {
@@ -441,10 +441,14 @@
             cursor = new MatrixCursor(projection);
         }
 
-        final Cursor resultCursor = removeUndesiredDestinations(cursor, desiredMimeType, lookupKey);
-        cursor.close();
+        if (cursor != null) {
+            final Cursor resultCursor = removeUndesiredDestinations(cursor,
+                    desiredMimeType, lookupKey);
+            cursor.close();
+            return resultCursor;
+        }
 
-        return resultCursor;
+        return cursor;
     }
 
     /**
diff --git a/src/com/android/ex/chips/RecipientEditTextView.java b/src/com/android/ex/chips/RecipientEditTextView.java
old mode 100644
new mode 100755
index 1fc7ec0..bd8b211
--- a/src/com/android/ex/chips/RecipientEditTextView.java
+++ b/src/com/android/ex/chips/RecipientEditTextView.java
@@ -213,6 +213,23 @@
 
     private boolean mAttachedToWindow;
 
+    public enum ScreenOrientation {
+        PORTRAIT,
+        LANDSCAPE,
+    }
+
+    private ScreenOrientation mOrientation = ScreenOrientation.PORTRAIT;
+
+    public ScreenOrientation getOrientation() {
+        return mOrientation;
+    }
+
+    public void setOrientation(ScreenOrientation orientation) {
+        mOrientation = orientation;
+    }
+
+    private boolean mAllSelected = false;
+
     private final Runnable mAddTextWatcher = new Runnable() {
         @Override
         public void run() {
@@ -540,6 +557,11 @@
         // When selection changes, see if it is inside the chips area.
         // If so, move the cursor back after the chips again.
         // Only exception is when we change the selection due to a selected chip.
+        if (getOrientation() == ScreenOrientation.LANDSCAPE) {
+            if ((getText().length() != 0) && (getText().length() == (end - start))) {
+                mAllSelected = true;
+            }
+        }
         DrawableRecipientChip last = getLastChip();
         if (mSelectedChip == null && last != null && start < getSpannable().getSpanEnd(last)) {
             // Grab the last chip and set the cursor to after it.
@@ -2284,6 +2306,41 @@
         return end - start;
     }
 
+    /**
+     * @hide
+     */
+    public void onGroupItemClick(int position, RecipientEntry entry) {
+        if (position < 0) {
+            return;
+        }
+
+        final int charactersTyped = submitGroupMemberAtPosition(entry);
+        if (charactersTyped > -1 && mRecipientEntryItemClickedListener != null) {
+            mRecipientEntryItemClickedListener
+                    .onRecipientEntryItemClicked(charactersTyped, position);
+        }
+    }
+
+    private int submitGroupMemberAtPosition(RecipientEntry entry) {
+        if (entry == null) {
+            return -1;
+        }
+        clearComposingText();
+
+        int end = getSelectionEnd();
+        int start = mTokenizer.findTokenStart(getText(), end);
+
+        Editable editable = getText();
+        QwertyKeyListener.markAsReplaced(editable, start, end, "");
+        CharSequence chip = createChip(entry);
+        if (chip != null && start >= 0 && end >= 0) {
+            editable.replace(start, end, chip);
+        }
+        sanitizeBetween();
+
+        return end - start;
+    }
+
     private RecipientEntry createValidatedEntry(RecipientEntry item) {
         if (item == null) {
             return null;
@@ -2859,6 +2916,7 @@
                 // If the item deleted is a space, and the thing before the
                 // space is a chip, delete the entire span.
                 int selStart = getSelectionStart();
+                if (getOrientation() == ScreenOrientation.PORTRAIT) {
                 DrawableRecipientChip[] repl = getSpannable().getSpans(selStart, selStart,
                         DrawableRecipientChip.class);
                 if (repl.length > 0) {
@@ -2872,11 +2930,57 @@
                         deleteEnd = editable.length();
                     }
                     if (!mNoChipMode && mRecipientChipDeletedListener != null) {
-                        mRecipientChipDeletedListener.onRecipientChipDeleted(toDelete.getEntry());
+                            mRecipientChipDeletedListener
+                                    .onRecipientChipDeleted(toDelete.getEntry());
                     }
                     editable.removeSpan(toDelete);
                     editable.delete(deleteStart, deleteEnd);
                 }
+                } else {
+                    if (mAllSelected) {
+                        DrawableRecipientChip[] repl = getSpannable().getSpans(0,
+                                getText().length(),
+                                DrawableRecipientChip.class);
+                        for (int i = 0; i < repl.length; i++) {
+                            DrawableRecipientChip toDelete = repl[i];
+                            Editable editable = getText();
+                            // Add the separator token.
+                            int deleteStart = editable.getSpanStart(toDelete);
+                            int deleteEnd = editable.getSpanEnd(toDelete) + 1;
+                            deleteStart = (deleteStart < 0) ? 0 : deleteStart;
+                            if (deleteEnd > editable.length()) {
+                                deleteEnd = editable.length();
+                            }
+                            if (!mNoChipMode && mRecipientChipDeletedListener != null) {
+                                mRecipientChipDeletedListener
+                                        .onRecipientChipDeleted(toDelete.getEntry());
+                            }
+                            editable.removeSpan(toDelete);
+                            editable.delete(deleteStart, deleteEnd);
+                        }
+                        mAllSelected = false;
+                    } else {
+                        DrawableRecipientChip[] repl = getSpannable().getSpans(selStart, selStart,
+                                DrawableRecipientChip.class);
+                        if (repl.length > 0) {
+                            // There is a chip there! Just remove it.
+                            DrawableRecipientChip toDelete = repl[0];
+                            Editable editable = getText();
+                            // Add the separator token.
+                            int deleteStart = editable.getSpanStart(toDelete);
+                            int deleteEnd = editable.getSpanEnd(toDelete) + 1;
+                            if (deleteEnd > editable.length()) {
+                                deleteEnd = editable.length();
+                            }
+                            if (!mNoChipMode && mRecipientChipDeletedListener != null) {
+                                mRecipientChipDeletedListener
+                                        .onRecipientChipDeleted(toDelete.getEntry());
+                            }
+                            editable.removeSpan(toDelete);
+                            editable.delete(deleteStart, deleteEnd);
+                        }
+                    }
+                }
             } else if (count > before) {
                 if (mSelectedChip != null
                     && isGeneratedContact(mSelectedChip)) {
diff --git a/src/com/android/ex/chips/RecipientEntry.java b/src/com/android/ex/chips/RecipientEntry.java
old mode 100644
new mode 100755
index a42794f..7765775
--- a/src/com/android/ex/chips/RecipientEntry.java
+++ b/src/com/android/ex/chips/RecipientEntry.java
@@ -48,7 +48,12 @@
      */
     public static final int ENTRY_TYPE_PERMISSION_REQUEST = 1;
 
-    public static final int ENTRY_TYPE_SIZE = 2;
+    /**
+     * @hide
+     */
+    public static final int ENTRY_TYPE_GROUP = 2;
+
+    public static final int ENTRY_TYPE_SIZE = 3;
 
     private final int mEntryType;
 
@@ -247,6 +252,19 @@
         return (displayNameSource > DisplayNameSources.PHONE) ? displayName : destination;
     }
 
+    /**
+     * @hide
+     */
+    public static RecipientEntry constructTopLevelEntryForGroup(int entryType, String displayName,
+            int displayNameSource, String destination, int destinationType, String destinationLabel,
+            long contactId, Long directoryId, long dataId, String thumbnailUriAsString,
+            boolean isValid, String lookupKey) {
+        return new RecipientEntry(entryType, pickDisplayName(displayNameSource,
+                displayName, destination), destination, destinationType, destinationLabel,
+                contactId, directoryId, dataId, (thumbnailUriAsString != null
+                ? Uri.parse(thumbnailUriAsString) : null), true, isValid, lookupKey);
+    }
+
     public int getEntryType() {
         return mEntryType;
     }
@@ -315,7 +333,8 @@
     }
 
     public boolean isSelectable() {
-        return mEntryType == ENTRY_TYPE_PERSON || mEntryType == ENTRY_TYPE_PERMISSION_REQUEST;
+        return mEntryType == ENTRY_TYPE_PERSON || mEntryType == ENTRY_TYPE_PERMISSION_REQUEST
+                || mEntryType == ENTRY_TYPE_GROUP;
     }
 
     @Override