Add file count limit when share

When share too many files, it will cause exception then crash.
Add a limit count to avoid this.

Fix: 140515766
Test: manual
Test: atest DocumentsUIGoogleTests
Change-Id: Iff40233da536659e5f83b4454642b9d2ab35fcef
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 042c16f..99db0c8 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -196,6 +196,8 @@
     <string name="toast_view_in_archives_unsupported">Cannot open files in archives</string>
     <!-- Toast shown when some of the selected documents failed to be deleted [CHAR LIMIT=48] -->
     <string name="toast_failed_delete">Unable to delete some documents</string>
+    <!-- Toast shown when user want to share files amount over limit [CHAR LIMIT=48] -->
+    <string name="toast_share_over_limit">Can\u2019t share more than <xliff:g id="count" example="1">%1$d</xliff:g> files</string>
 
     <!-- Title of dialog when prompting user to select an app to share documents with [CHAR LIMIT=32] -->
     <string name="share_via">Share via</string>
diff --git a/src/com/android/documentsui/files/ActionHandler.java b/src/com/android/documentsui/files/ActionHandler.java
index 9fb6e69..052d80e 100644
--- a/src/com/android/documentsui/files/ActionHandler.java
+++ b/src/com/android/documentsui/files/ActionHandler.java
@@ -87,6 +87,7 @@
 public class ActionHandler<T extends FragmentActivity & Addons> extends AbstractActionHandler<T> {
 
     private static final String TAG = "ManagerActionHandler";
+    private static final int SHARE_FILES_COUNT_LIMIT = 100;
 
     private final ActionModeAddons mActionModeAddons;
     private final Features mFeatures;
@@ -356,6 +357,9 @@
         Selection<String> selection = getStableSelection();
         if (selection.isEmpty()) {
             return;
+        } else if (selection.size() > SHARE_FILES_COUNT_LIMIT) {
+            mDialogs.showShareOverLimit(SHARE_FILES_COUNT_LIMIT);
+            return;
         }
 
         // Model must be accessed in UI thread, since underlying cursor is not threadsafe.
diff --git a/src/com/android/documentsui/ui/DialogController.java b/src/com/android/documentsui/ui/DialogController.java
index 10de216..3a74cf9 100644
--- a/src/com/android/documentsui/ui/DialogController.java
+++ b/src/com/android/documentsui/ui/DialogController.java
@@ -47,6 +47,11 @@
     void showViewInArchivesUnsupported();
     void showDocumentsClipped(int size);
 
+    /**
+     * Dialogs used when share file count over limit
+     */
+    void showShareOverLimit(int size);
+
     // Dialogs used in PickActivity
     void confirmAction(FragmentManager fm, DocumentInfo pickTarget, int type);
 
@@ -153,6 +158,12 @@
         }
 
         @Override
+        public void showShareOverLimit(int size) {
+            String message = mActivity.getString(R.string.toast_share_over_limit, size);
+            Snackbars.makeSnackbar(mActivity, message, Snackbar.LENGTH_SHORT).show();
+        }
+
+        @Override
         public void confirmAction(FragmentManager fm, DocumentInfo pickTarget, int type) {
             ConfirmFragment.show(fm, pickTarget, type);
         }
diff --git a/tests/common/com/android/documentsui/testing/TestEnv.java b/tests/common/com/android/documentsui/testing/TestEnv.java
index 6ddd047..06f9dd1 100644
--- a/tests/common/com/android/documentsui/testing/TestEnv.java
+++ b/tests/common/com/android/documentsui/testing/TestEnv.java
@@ -200,6 +200,15 @@
         selectionMgr.setItemsSelected(ids, true);
     }
 
+    public void selectMultipleFiles(int count) {
+        List<String> ids = new ArrayList<>(count);
+        for (int i = 0; i < count; i++) {
+            DocumentInfo info = model.createFile(String.valueOf(i));
+            ids.add(ModelId.build(info.authority, info.documentId));
+        }
+        selectionMgr.setItemsSelected(ids, true);
+    }
+
     // Easily copy docs, so we don't pollute static data across tests.
     public static DocumentInfo clone(DocumentInfo a) {
         DocumentInfo b = new DocumentInfo();
diff --git a/tests/common/com/android/documentsui/ui/TestDialogController.java b/tests/common/com/android/documentsui/ui/TestDialogController.java
index 17916b2..41acee9 100644
--- a/tests/common/com/android/documentsui/ui/TestDialogController.java
+++ b/tests/common/com/android/documentsui/ui/TestDialogController.java
@@ -31,6 +31,7 @@
     private boolean mDocumentsClipped;
     private boolean mViewInArchivesUnsupported;
     private boolean mShowOperationUnsupported;
+    private boolean mShowShareOverLimit;
     private DocumentInfo mTarget;
     private int mConfrimType;
 
@@ -68,6 +69,11 @@
     }
 
     @Override
+    public void showShareOverLimit(int size) {
+        mShowShareOverLimit = true;
+    }
+
+    @Override
     public void confirmAction(FragmentManager fm, DocumentInfo pickTarget, int type) {
         mTarget = pickTarget;
         mConfrimType = type;
@@ -96,6 +102,10 @@
         Assert.assertFalse(mDocumentsClipped);
     }
 
+    public void assertShareOverLimitShown() {
+        Assert.assertTrue(mShowShareOverLimit);
+    }
+
     public void assertOverwriteConfirmed(DocumentInfo expected) {
         Assert.assertEquals(expected, mTarget);
         Assert.assertEquals(ConfirmFragment.TYPE_OVERWRITE, mConfrimType);
diff --git a/tests/unit/com/android/documentsui/files/ActionHandlerTest.java b/tests/unit/com/android/documentsui/files/ActionHandlerTest.java
index 5f1d10c..213e507 100644
--- a/tests/unit/com/android/documentsui/files/ActionHandlerTest.java
+++ b/tests/unit/com/android/documentsui/files/ActionHandlerTest.java
@@ -233,6 +233,17 @@
     }
 
     @Test
+    public void testShareSelectedDocuments_overShareLimit() {
+        mActivity.resources.strings.put(R.string.share_via, "Sharezilla!");
+        mEnv.selectMultipleFiles(500);
+        mHandler.shareSelectedDocuments();
+
+        Intent intent = mActivity.startActivity.getLastValue();
+        assertNull(intent);
+        mDialogs.assertShareOverLimitShown();
+    }
+
+    @Test
     public void testShareSelectedDocuments_VirtualFiles() {
         if (!mEnv.features.isVirtualFilesSharingEnabled()) {
             return;