Block oversize attachments from being sent

* Attachments that come in with a file:// URI do not support the complete
  set of OpenableColumns columns.  To handle this better:
  1. Obtain the openable values in two separate queries, in case one or
      the other is supported (but not both).
  2. If the size is not reported but it is a file:// URI, attempt to
     measure it directly.
  3. If the size cannot be obtained, do not upload the attachment

Bug: 2948965
Change-Id: Ic5160d39efd65eaca40ceba0dd93c3b035d2871e
diff --git a/src/com/android/email/activity/MessageCompose.java b/src/com/android/email/activity/MessageCompose.java
index e35864a..eb1d311 100644
--- a/src/com/android/email/activity/MessageCompose.java
+++ b/src/com/android/email/activity/MessageCompose.java
@@ -60,9 +60,9 @@
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
-import android.view.Window;
 import android.view.View.OnClickListener;
 import android.view.View.OnFocusChangeListener;
+import android.view.Window;
 import android.webkit.WebView;
 import android.widget.Button;
 import android.widget.EditText;
@@ -72,6 +72,7 @@
 import android.widget.TextView;
 import android.widget.Toast;
 
+import java.io.File;
 import java.io.UnsupportedEncodingException;
 import java.net.URLDecoder;
 import java.util.ArrayList;
@@ -103,10 +104,15 @@
 
     private static final int ACTIVITY_REQUEST_PICK_ATTACHMENT = 1;
 
-    private static final String[] ATTACHMENT_META_COLUMNS = {
-        OpenableColumns.DISPLAY_NAME,
+    private static final String[] ATTACHMENT_META_NAME_PROJECTION = {
+        OpenableColumns.DISPLAY_NAME
+    };
+    private static final int ATTACHMENT_META_NAME_COLUMN_DISPLAY_NAME = 0;
+
+    private static final String[] ATTACHMENT_META_SIZE_PROJECTION = {
         OpenableColumns.SIZE
     };
+    private static final int ATTACHMENT_META_SIZE_COLUMN_SIZE = 0;
 
     // Is set while the draft is saved by a background thread.
     // Is static in order to be shared between the two activity instances
@@ -1008,24 +1014,55 @@
     }
 
     private Attachment loadAttachmentInfo(Uri uri) {
-        int size = -1;
+        long size = -1;
         String name = null;
         ContentResolver contentResolver = getContentResolver();
-        Cursor metadataCursor = contentResolver.query(uri,
-                ATTACHMENT_META_COLUMNS, null, null, null);
+
+        // Load name & size independently, because not all providers support both
+        Cursor metadataCursor = contentResolver.query(uri, ATTACHMENT_META_NAME_PROJECTION,
+                null, null, null);
         if (metadataCursor != null) {
             try {
                 if (metadataCursor.moveToFirst()) {
-                    name = metadataCursor.getString(0);
-                    size = metadataCursor.getInt(1);
+                    name = metadataCursor.getString(ATTACHMENT_META_NAME_COLUMN_DISPLAY_NAME);
                 }
             } finally {
                 metadataCursor.close();
             }
         }
+        metadataCursor = contentResolver.query(uri, ATTACHMENT_META_SIZE_PROJECTION,
+                null, null, null);
+        if (metadataCursor != null) {
+            try {
+                if (metadataCursor.moveToFirst()) {
+                    size = metadataCursor.getLong(ATTACHMENT_META_SIZE_COLUMN_SIZE);
+                }
+            } finally {
+                metadataCursor.close();
+            }
+        }
+
+        // When the name or size are not provided, we need to generate them locally.
         if (name == null) {
             name = uri.getLastPathSegment();
         }
+        if (size < 0) {
+            // if the URI is a file: URI, ask file system for its size
+            if ("file".equalsIgnoreCase(uri.getScheme())) {
+                String path = uri.getPath();
+                if (path != null) {
+                    File file = new File(path);
+                    size = file.length();  // Returns 0 for file not found
+                }
+            }
+
+            if (size <= 0) {
+                // The size was not measurable;  This attachment is not safe to use.
+                // Quick hack to force a relevant error into the UI
+                // TODO: A proper announcement of the problem
+                size = Email.MAX_ATTACHMENT_UPLOAD_SIZE + 1;
+            }
+        }
 
         String contentType = contentResolver.getType(uri);
         if (contentType == null) {