[automerger] Filter Attachment file name of forward slashes for .eml attachments. am: 53b40fd185 am: eb8ae2ec17 am: be56f65931 am: 6f463bac17 am: 015cde5a2b am: 1827d56264 am: 31ea2c26ff am: 3cb03481aa am: f16fc49b6a am: 4c2fb949c1 am: c59403a72e
Change-Id: Ib830bc94450ac3c1c89c73036614dcb9a4aa22f2
diff --git a/proguard-test.flags b/proguard-test.flags
index 2eb8cfa..b735814 100644
--- a/proguard-test.flags
+++ b/proguard-test.flags
@@ -29,10 +29,6 @@
public static boolean updateMessageFields(...);
}
--keep class com.android.mail.utils.Utils {
- public static android.text.Spanned insertStringWithStyle(...);
-}
-
-keepclasseswithmembers class * {
*** findProviderForDomain(...);
}
diff --git a/res/values-az-rAZ-sw600dp/strings.xml b/res/values-az-sw600dp/strings.xml
similarity index 100%
rename from res/values-az-rAZ-sw600dp/strings.xml
rename to res/values-az-sw600dp/strings.xml
diff --git a/res/values-az-rAZ/strings.xml b/res/values-az/strings.xml
similarity index 100%
rename from res/values-az-rAZ/strings.xml
rename to res/values-az/strings.xml
diff --git a/res/values-bn-rBD-sw600dp/strings.xml b/res/values-bn-sw600dp/strings.xml
similarity index 100%
rename from res/values-bn-rBD-sw600dp/strings.xml
rename to res/values-bn-sw600dp/strings.xml
diff --git a/res/values-bn-rBD/strings.xml b/res/values-bn/strings.xml
similarity index 100%
rename from res/values-bn-rBD/strings.xml
rename to res/values-bn/strings.xml
diff --git a/res/values-et-rEE-sw600dp/strings.xml b/res/values-et-sw600dp/strings.xml
similarity index 100%
rename from res/values-et-rEE-sw600dp/strings.xml
rename to res/values-et-sw600dp/strings.xml
diff --git a/res/values-et-rEE/strings.xml b/res/values-et/strings.xml
similarity index 100%
rename from res/values-et-rEE/strings.xml
rename to res/values-et/strings.xml
diff --git a/res/values-eu-rES-sw600dp/strings.xml b/res/values-eu-sw600dp/strings.xml
similarity index 100%
rename from res/values-eu-rES-sw600dp/strings.xml
rename to res/values-eu-sw600dp/strings.xml
diff --git a/res/values-eu-rES/strings.xml b/res/values-eu/strings.xml
similarity index 100%
rename from res/values-eu-rES/strings.xml
rename to res/values-eu/strings.xml
diff --git a/res/values-gl-rES-sw600dp/strings.xml b/res/values-gl-sw600dp/strings.xml
similarity index 100%
rename from res/values-gl-rES-sw600dp/strings.xml
rename to res/values-gl-sw600dp/strings.xml
diff --git a/res/values-gl-rES/strings.xml b/res/values-gl/strings.xml
similarity index 100%
rename from res/values-gl-rES/strings.xml
rename to res/values-gl/strings.xml
diff --git a/res/values-gu-rIN-sw600dp/strings.xml b/res/values-gu-sw600dp/strings.xml
similarity index 100%
rename from res/values-gu-rIN-sw600dp/strings.xml
rename to res/values-gu-sw600dp/strings.xml
diff --git a/res/values-gu-rIN/strings.xml b/res/values-gu/strings.xml
similarity index 100%
rename from res/values-gu-rIN/strings.xml
rename to res/values-gu/strings.xml
diff --git a/res/values-hy-rAM-sw600dp/strings.xml b/res/values-hy-sw600dp/strings.xml
similarity index 100%
rename from res/values-hy-rAM-sw600dp/strings.xml
rename to res/values-hy-sw600dp/strings.xml
diff --git a/res/values-hy-rAM/strings.xml b/res/values-hy/strings.xml
similarity index 100%
rename from res/values-hy-rAM/strings.xml
rename to res/values-hy/strings.xml
diff --git a/res/values-is-rIS-sw600dp/strings.xml b/res/values-is-sw600dp/strings.xml
similarity index 100%
rename from res/values-is-rIS-sw600dp/strings.xml
rename to res/values-is-sw600dp/strings.xml
diff --git a/res/values-is-rIS/strings.xml b/res/values-is/strings.xml
similarity index 100%
rename from res/values-is-rIS/strings.xml
rename to res/values-is/strings.xml
diff --git a/res/values-ka-rGE-sw600dp/strings.xml b/res/values-ka-sw600dp/strings.xml
similarity index 100%
rename from res/values-ka-rGE-sw600dp/strings.xml
rename to res/values-ka-sw600dp/strings.xml
diff --git a/res/values-ka-rGE/strings.xml b/res/values-ka/strings.xml
similarity index 100%
rename from res/values-ka-rGE/strings.xml
rename to res/values-ka/strings.xml
diff --git a/res/values-kk-rKZ-sw600dp/strings.xml b/res/values-kk-sw600dp/strings.xml
similarity index 100%
rename from res/values-kk-rKZ-sw600dp/strings.xml
rename to res/values-kk-sw600dp/strings.xml
diff --git a/res/values-kk-rKZ/strings.xml b/res/values-kk/strings.xml
similarity index 100%
rename from res/values-kk-rKZ/strings.xml
rename to res/values-kk/strings.xml
diff --git a/res/values-km-rKH-sw600dp/strings.xml b/res/values-km-sw600dp/strings.xml
similarity index 100%
rename from res/values-km-rKH-sw600dp/strings.xml
rename to res/values-km-sw600dp/strings.xml
diff --git a/res/values-km-rKH/strings.xml b/res/values-km/strings.xml
similarity index 100%
rename from res/values-km-rKH/strings.xml
rename to res/values-km/strings.xml
diff --git a/res/values-kn-rIN-sw600dp/strings.xml b/res/values-kn-sw600dp/strings.xml
similarity index 100%
rename from res/values-kn-rIN-sw600dp/strings.xml
rename to res/values-kn-sw600dp/strings.xml
diff --git a/res/values-kn-rIN/strings.xml b/res/values-kn/strings.xml
similarity index 100%
rename from res/values-kn-rIN/strings.xml
rename to res/values-kn/strings.xml
diff --git a/res/values-ky-rKG-sw600dp/strings.xml b/res/values-ky-sw600dp/strings.xml
similarity index 100%
rename from res/values-ky-rKG-sw600dp/strings.xml
rename to res/values-ky-sw600dp/strings.xml
diff --git a/res/values-ky-rKG/strings.xml b/res/values-ky/strings.xml
similarity index 100%
rename from res/values-ky-rKG/strings.xml
rename to res/values-ky/strings.xml
diff --git a/res/values-lo-rLA-sw600dp/strings.xml b/res/values-lo-sw600dp/strings.xml
similarity index 100%
rename from res/values-lo-rLA-sw600dp/strings.xml
rename to res/values-lo-sw600dp/strings.xml
diff --git a/res/values-lo-rLA/strings.xml b/res/values-lo/strings.xml
similarity index 100%
rename from res/values-lo-rLA/strings.xml
rename to res/values-lo/strings.xml
diff --git a/res/values-mk-rMK-sw600dp/strings.xml b/res/values-mk-sw600dp/strings.xml
similarity index 100%
rename from res/values-mk-rMK-sw600dp/strings.xml
rename to res/values-mk-sw600dp/strings.xml
diff --git a/res/values-mk-rMK/strings.xml b/res/values-mk/strings.xml
similarity index 100%
rename from res/values-mk-rMK/strings.xml
rename to res/values-mk/strings.xml
diff --git a/res/values-ml-rIN-sw600dp/strings.xml b/res/values-ml-sw600dp/strings.xml
similarity index 100%
rename from res/values-ml-rIN-sw600dp/strings.xml
rename to res/values-ml-sw600dp/strings.xml
diff --git a/res/values-ml-rIN/strings.xml b/res/values-ml/strings.xml
similarity index 100%
rename from res/values-ml-rIN/strings.xml
rename to res/values-ml/strings.xml
diff --git a/res/values-mn-rMN-sw600dp/strings.xml b/res/values-mn-sw600dp/strings.xml
similarity index 100%
rename from res/values-mn-rMN-sw600dp/strings.xml
rename to res/values-mn-sw600dp/strings.xml
diff --git a/res/values-mn-rMN/strings.xml b/res/values-mn/strings.xml
similarity index 100%
rename from res/values-mn-rMN/strings.xml
rename to res/values-mn/strings.xml
diff --git a/res/values-mr-rIN-sw600dp/strings.xml b/res/values-mr-sw600dp/strings.xml
similarity index 100%
rename from res/values-mr-rIN-sw600dp/strings.xml
rename to res/values-mr-sw600dp/strings.xml
diff --git a/res/values-mr-rIN/strings.xml b/res/values-mr/strings.xml
similarity index 100%
rename from res/values-mr-rIN/strings.xml
rename to res/values-mr/strings.xml
diff --git a/res/values-ms-rMY-sw600dp/strings.xml b/res/values-ms-sw600dp/strings.xml
similarity index 100%
rename from res/values-ms-rMY-sw600dp/strings.xml
rename to res/values-ms-sw600dp/strings.xml
diff --git a/res/values-ms-rMY/strings.xml b/res/values-ms/strings.xml
similarity index 100%
rename from res/values-ms-rMY/strings.xml
rename to res/values-ms/strings.xml
diff --git a/res/values-my-rMM-sw600dp/strings.xml b/res/values-my-sw600dp/strings.xml
similarity index 100%
rename from res/values-my-rMM-sw600dp/strings.xml
rename to res/values-my-sw600dp/strings.xml
diff --git a/res/values-my-rMM/strings.xml b/res/values-my/strings.xml
similarity index 100%
rename from res/values-my-rMM/strings.xml
rename to res/values-my/strings.xml
diff --git a/res/values-ne-rNP-sw600dp/strings.xml b/res/values-ne-sw600dp/strings.xml
similarity index 100%
rename from res/values-ne-rNP-sw600dp/strings.xml
rename to res/values-ne-sw600dp/strings.xml
diff --git a/res/values-ne-rNP/strings.xml b/res/values-ne/strings.xml
similarity index 100%
rename from res/values-ne-rNP/strings.xml
rename to res/values-ne/strings.xml
diff --git a/res/values-si-rLK-sw600dp/strings.xml b/res/values-si-sw600dp/strings.xml
similarity index 100%
rename from res/values-si-rLK-sw600dp/strings.xml
rename to res/values-si-sw600dp/strings.xml
diff --git a/res/values-si-rLK/strings.xml b/res/values-si/strings.xml
similarity index 100%
rename from res/values-si-rLK/strings.xml
rename to res/values-si/strings.xml
diff --git a/res/values-ta-rIN-sw600dp/strings.xml b/res/values-ta-sw600dp/strings.xml
similarity index 100%
rename from res/values-ta-rIN-sw600dp/strings.xml
rename to res/values-ta-sw600dp/strings.xml
diff --git a/res/values-ta-rIN/strings.xml b/res/values-ta/strings.xml
similarity index 100%
rename from res/values-ta-rIN/strings.xml
rename to res/values-ta/strings.xml
diff --git a/res/values-te-rIN-sw600dp/strings.xml b/res/values-te-sw600dp/strings.xml
similarity index 100%
rename from res/values-te-rIN-sw600dp/strings.xml
rename to res/values-te-sw600dp/strings.xml
diff --git a/res/values-te-rIN/strings.xml b/res/values-te/strings.xml
similarity index 100%
rename from res/values-te-rIN/strings.xml
rename to res/values-te/strings.xml
diff --git a/res/values-ur-rPK-sw600dp/strings.xml b/res/values-ur-sw600dp/strings.xml
similarity index 100%
rename from res/values-ur-rPK-sw600dp/strings.xml
rename to res/values-ur-sw600dp/strings.xml
diff --git a/res/values-ur-rPK/strings.xml b/res/values-ur/strings.xml
similarity index 100%
rename from res/values-ur-rPK/strings.xml
rename to res/values-ur/strings.xml
diff --git a/res/values-uz-rUZ-sw600dp/strings.xml b/res/values-uz-sw600dp/strings.xml
similarity index 100%
rename from res/values-uz-rUZ-sw600dp/strings.xml
rename to res/values-uz-sw600dp/strings.xml
diff --git a/res/values-uz-rUZ/strings.xml b/res/values-uz/strings.xml
similarity index 100%
rename from res/values-uz-rUZ/strings.xml
rename to res/values-uz/strings.xml
diff --git a/src/com/android/mail/browse/EmlMessageViewFragment.java b/src/com/android/mail/browse/EmlMessageViewFragment.java
index 306c138..2fbbb72 100644
--- a/src/com/android/mail/browse/EmlMessageViewFragment.java
+++ b/src/com/android/mail/browse/EmlMessageViewFragment.java
@@ -27,7 +27,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.provider.OpenableColumns;
-import android.support.v7.app.ActionBarActivity;
+import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@@ -337,7 +337,7 @@
return;
}
- ((ActionBarActivity) getActivity()).getSupportActionBar().setTitle(
+ ((AppCompatActivity) getActivity()).getSupportActionBar().setTitle(
data.getString(data.getColumnIndex(OpenableColumns.DISPLAY_NAME)));
}
diff --git a/src/com/android/mail/compose/AttachmentComposeView.java b/src/com/android/mail/compose/AttachmentComposeView.java
index 89216e1..6f099c5 100644
--- a/src/com/android/mail/compose/AttachmentComposeView.java
+++ b/src/com/android/mail/compose/AttachmentComposeView.java
@@ -69,7 +69,8 @@
private void populateAttachmentData(Context context) {
((TextView) findViewById(R.id.attachment_name)).setText(mAttachment.getName());
- if (mAttachment.size > 0) {
+ // If size is -1, then it's size is unknown, hence do not show it.
+ if (mAttachment.size != -1) {
((TextView) findViewById(R.id.attachment_size)).
setText(AttachmentUtils.convertToHumanReadableSize(context, mAttachment.size));
} else {
diff --git a/src/com/android/mail/compose/AttachmentsView.java b/src/com/android/mail/compose/AttachmentsView.java
index 5edac8a..285a437 100644
--- a/src/com/android/mail/compose/AttachmentsView.java
+++ b/src/com/android/mail/compose/AttachmentsView.java
@@ -15,18 +15,21 @@
*/
package com.android.mail.compose;
+import android.annotation.TargetApi;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteException;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
+import android.provider.DocumentsContract;
import android.provider.OpenableColumns;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
+import android.webkit.MimeTypeMap;
import android.widget.LinearLayout;
import com.android.mail.R;
@@ -37,6 +40,7 @@
import com.android.mail.ui.AttachmentTileGrid;
import com.android.mail.utils.LogTag;
import com.android.mail.utils.LogUtils;
+import com.android.mail.utils.Utils;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
@@ -206,6 +210,39 @@
}
/**
+ * Checks if the passed Uri is a virtual document.
+ *
+ * @param contentUri
+ * @return true if virtual, false if regular.
+ */
+ @TargetApi(24)
+ private boolean isVirtualDocument(Uri contentUri) {
+ // For SAF files, check if it's a virtual document.
+ if (!DocumentsContract.isDocumentUri(getContext(), contentUri)) {
+ return false;
+ }
+
+ final ContentResolver contentResolver = getContext().getContentResolver();
+ final Cursor metadataCursor = contentResolver.query(contentUri,
+ new String[] { DocumentsContract.Document.COLUMN_FLAGS }, null, null, null);
+ if (metadataCursor != null) {
+ try {
+ int flags = 0;
+ if (metadataCursor.moveToNext()) {
+ flags = metadataCursor.getInt(0);
+ }
+ if ((flags & DocumentsContract.Document.FLAG_VIRTUAL_DOCUMENT) != 0) {
+ return true;
+ }
+ } finally {
+ metadataCursor.close();
+ }
+ }
+
+ return false;
+ }
+
+ /**
* Generate an {@link Attachment} object for a given local content URI. Attempts to populate
* the {@link Attachment#name}, {@link Attachment#size}, and {@link Attachment#contentType}
* fields using a {@link ContentResolver}.
@@ -226,13 +263,26 @@
if (contentType == null) contentType = "";
final Attachment attachment = new Attachment();
- attachment.uri = null; // URI will be assigned by the provider upon send/save
- attachment.setName(null);
- attachment.size = 0;
+ attachment.uri = null; // URI will be assigned by the provider upon send/save
attachment.contentUri = contentUri;
attachment.thumbnailUri = contentUri;
Cursor metadataCursor = null;
+ String name = null;
+ int size = -1; // Unknown, will be determined either now or in the service
+ final boolean isVirtual = Utils.isRunningNOrLater()
+ ? isVirtualDocument(contentUri) : false;
+
+ if (isVirtual) {
+ final String[] mimeTypes = contentResolver.getStreamTypes(contentUri, "*/*");
+ if (mimeTypes != null && mimeTypes.length > 0) {
+ attachment.virtualMimeType = mimeTypes[0];
+ } else{
+ throw new AttachmentFailureException(
+ "Cannot attach a virtual document without any streamable format.");
+ }
+ }
+
try {
metadataCursor = contentResolver.query(
contentUri, new String[]{OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE},
@@ -240,8 +290,12 @@
if (metadataCursor != null) {
try {
if (metadataCursor.moveToNext()) {
- attachment.setName(metadataCursor.getString(0));
- attachment.size = metadataCursor.getInt(1);
+ name = metadataCursor.getString(0);
+ // For virtual document this size is not the one which will be attached,
+ // so ignore it.
+ if (!isVirtual) {
+ size = metadataCursor.getInt(1);
+ }
}
} finally {
metadataCursor.close();
@@ -259,38 +313,55 @@
metadataCursor = getOptionalColumn(contentResolver, contentUri,
OpenableColumns.DISPLAY_NAME);
if (metadataCursor != null && metadataCursor.moveToNext()) {
- attachment.setName(metadataCursor.getString(0));
+ name = metadataCursor.getString(0);
}
} finally {
if (metadataCursor != null) metadataCursor.close();
}
// Let's try to get SIZE
- try {
- metadataCursor =
- getOptionalColumn(contentResolver, contentUri, OpenableColumns.SIZE);
- if (metadataCursor != null && metadataCursor.moveToNext()) {
- attachment.size = metadataCursor.getInt(0);
- } else {
- // Unable to get the size from the metadata cursor. Open the file and seek.
- attachment.size = getSizeFromFile(contentUri, contentResolver);
+ if (!isVirtual) {
+ try {
+ metadataCursor =
+ getOptionalColumn(contentResolver, contentUri, OpenableColumns.SIZE);
+ if (metadataCursor != null && metadataCursor.moveToNext()) {
+ size = metadataCursor.getInt(0);
+ } else {
+ // Unable to get the size from the metadata cursor. Open the file and seek.
+ size = getSizeFromFile(contentUri, contentResolver);
+ }
+ } finally {
+ if (metadataCursor != null) metadataCursor.close();
}
- } finally {
- if (metadataCursor != null) metadataCursor.close();
}
} catch (SecurityException e) {
throw new AttachmentFailureException("Security Exception from attachment uri", e);
}
- if (attachment.getName() == null) {
- attachment.setName(contentUri.getLastPathSegment());
- }
- if (attachment.size == 0) {
- // if the attachment is not a content:// for example, a file:// URI
- attachment.size = getSizeFromFile(contentUri, contentResolver);
+ if (name == null) {
+ name = contentUri.getLastPathSegment();
}
+ // For virtual files append the inferred extension name.
+ if (isVirtual) {
+ String extension = MimeTypeMap.getSingleton()
+ .getExtensionFromMimeType(attachment.virtualMimeType);
+ if (extension != null) {
+ name += "." + extension;
+ }
+ }
+
+ // TODO: This can't work with pipes. Fix it.
+ if (size == -1 && !isVirtual) {
+ // if the attachment is not a content:// for example, a file:// URI
+ size = getSizeFromFile(contentUri, contentResolver);
+ }
+
+ // Save the computed values into the attachment.
+ attachment.size = size;
+ attachment.setName(name);
attachment.setContentType(contentType);
+
return attachment;
}
@@ -300,28 +371,28 @@
* @param account
* @param attachment the attachment to be added.
*
- * @return size of the attachment added.
* @throws AttachmentFailureException if an error occurs adding the attachment.
*/
- public long addAttachment(Account account, Attachment attachment)
+ public void addAttachment(Account account, Attachment attachment)
throws AttachmentFailureException {
final int maxSize = account.settings.getMaxAttachmentSize();
- // Error getting the size or the size was too big.
- if (attachment.size == -1 || attachment.size > maxSize) {
+ // The attachment size is known and it's too big.
+ if (attachment.size > maxSize) {
throw new AttachmentFailureException(
"Attachment too large to attach", R.string.too_large_to_attach_single);
- } else if ((getTotalAttachmentsSize()
+ } else if (attachment.size != -1 && (getTotalAttachmentsSize()
+ attachment.size) > maxSize) {
throw new AttachmentFailureException(
"Attachment too large to attach", R.string.too_large_to_attach_additional);
} else {
addAttachment(attachment);
}
-
- return attachment.size;
}
+ /**
+ * @return size of the file or -1 if unknown.
+ */
private static int getSizeFromFile(Uri uri, ContentResolver contentResolver) {
int size = -1;
ParcelFileDescriptor file = null;
@@ -339,9 +410,7 @@
LogUtils.w(LOG_TAG, "Error closing file opened to obtain size.");
}
}
- // We only want to return a non-negative value. (ParcelFileDescriptor#getStatSize() will
- // return -1 if the fd is not a file
- return Math.max(size, 0);
+ return size;
}
/**
diff --git a/src/com/android/mail/compose/ComposeActivity.java b/src/com/android/mail/compose/ComposeActivity.java
index 489f6d8..3dd9e87 100644
--- a/src/com/android/mail/compose/ComposeActivity.java
+++ b/src/com/android/mail/compose/ComposeActivity.java
@@ -36,6 +36,7 @@
import android.content.Intent;
import android.content.Loader;
import android.content.pm.ActivityInfo;
+import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Rect;
@@ -50,7 +51,7 @@
import android.provider.BaseColumns;
import android.support.v4.app.RemoteInput;
import android.support.v7.app.ActionBar;
-import android.support.v7.app.ActionBarActivity;
+import android.support.v7.app.AppCompatActivity;
import android.support.v7.view.ActionMode;
import android.text.Editable;
import android.text.Html;
@@ -137,7 +138,7 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
-public class ComposeActivity extends ActionBarActivity
+public class ComposeActivity extends AppCompatActivity
implements OnClickListener, ActionBar.OnNavigationListener,
RespondInlineListener, TextWatcher,
AttachmentAddedOrDeletedListener, OnAccountChangedListener,
@@ -1834,12 +1835,16 @@
addAttachments(refMessage.getAttachments());
}
- public long addAttachments(List<Attachment> attachments) {
- long size = 0;
+ /**
+ * @return true if at least one file is attached.
+ */
+ public boolean addAttachments(List<Attachment> attachments) {
+ boolean attached = false;
AttachmentFailureException error = null;
for (Attachment a : attachments) {
try {
- size += mAttachmentsView.addAttachment(mAccount, a);
+ mAttachmentsView.addAttachment(mAccount, a);
+ attached = true;
} catch (AttachmentFailureException e) {
error = e;
}
@@ -1852,7 +1857,7 @@
showAttachmentTooBigToast(error.getErrorRes());
}
}
- return size;
+ return attached;
}
/**
@@ -1881,33 +1886,30 @@
}
final String action = intent.getAction();
if (!mAttachmentsChanged) {
- long totalSize = 0;
+ boolean attached = false;
if (extras.containsKey(EXTRA_ATTACHMENTS)) {
final String[] uris = (String[]) extras.getSerializable(EXTRA_ATTACHMENTS);
final ArrayList<Uri> parsedUris = Lists.newArrayListWithCapacity(uris.length);
for (String uri : uris) {
parsedUris.add(Uri.parse(uri));
}
- totalSize += handleAttachmentUrisFromIntent(parsedUris);
+ attached |= handleAttachmentUrisFromIntent(parsedUris);
}
if (extras.containsKey(Intent.EXTRA_STREAM)) {
if (Intent.ACTION_SEND_MULTIPLE.equals(action)) {
final ArrayList<Uri> uris = extras
.getParcelableArrayList(Intent.EXTRA_STREAM);
- totalSize += handleAttachmentUrisFromIntent(uris);
+ attached |= handleAttachmentUrisFromIntent(uris);
} else {
final Uri uri = extras.getParcelable(Intent.EXTRA_STREAM);
final ArrayList<Uri> uris = Lists.newArrayList(uri);
- totalSize += handleAttachmentUrisFromIntent(uris);
+ attached |= handleAttachmentUrisFromIntent(uris);
}
}
- if (totalSize > 0) {
+ if (attached) {
mAttachmentsChanged = true;
updateSaveUi();
-
- Analytics.getInstance().sendEvent("send_intent_with_attachments",
- Integer.toString(getAttachments().size()), null, totalSize);
}
}
}
@@ -1932,9 +1934,9 @@
/**
* Helper function to handle a list of uris to attach.
- * @return the total size of all successfully attached files.
+ * @return true if anything has been attached.
*/
- private long handleAttachmentUrisFromIntent(List<Uri> uris) {
+ private boolean handleAttachmentUrisFromIntent(List<Uri> uris) {
ArrayList<Attachment> attachments = Lists.newArrayList();
for (Uri uri : uris) {
try {
@@ -2034,8 +2036,8 @@
return;
}
- final long size = handleAttachmentUrisFromIntent(Arrays.asList(contentUri));
- if (size > 0) {
+ final boolean attached = handleAttachmentUrisFromIntent(Arrays.asList(contentUri));
+ if (attached) {
mAttachmentsChanged = true;
updateSaveUi();
}
@@ -2053,11 +2055,9 @@
private void addAttachmentAndUpdateView(Attachment attachment) {
try {
- long size = mAttachmentsView.addAttachment(mAccount, attachment);
- if (size > 0) {
- mAttachmentsChanged = true;
- updateSaveUi();
- }
+ mAttachmentsView.addAttachment(mAccount, attachment);
+ mAttachmentsChanged = true;
+ updateSaveUi();
} catch (AttachmentFailureException e) {
LogUtils.e(LOG_TAG, e, "Error adding attachment");
showAttachmentTooBigToast(e.getErrorRes());
@@ -2616,7 +2616,7 @@
if (openedFds != null) {
final Set<String> keys = openedFds.keySet();
for (final String key : keys) {
- final ParcelFileDescriptor fd = openedFds.getParcelable(key);
+ final AssetFileDescriptor fd = openedFds.getParcelable(key);
if (fd != null) {
try {
fd.close();
@@ -2726,9 +2726,16 @@
continue;
}
- ParcelFileDescriptor fileDescriptor;
+ AssetFileDescriptor fileDescriptor;
try {
- fileDescriptor = resolver.openFileDescriptor(attachment.contentUri, "r");
+ if (attachment.virtualMimeType == null) {
+ fileDescriptor = new AssetFileDescriptor(
+ resolver.openFileDescriptor(attachment.contentUri, "r"), 0,
+ AssetFileDescriptor.UNKNOWN_LENGTH);
+ } else {
+ fileDescriptor = resolver.openTypedAssetFileDescriptor(
+ attachment.contentUri, attachment.virtualMimeType, null, null);
+ }
} catch (FileNotFoundException e) {
LogUtils.e(LOG_TAG, e, "Exception attempting to open attachment");
fileDescriptor = null;
@@ -3435,7 +3442,6 @@
@SuppressLint("NewApi")
private void doAttach(String type) {
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
- i.addCategory(Intent.CATEGORY_OPENABLE);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
i.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
i.setType(type);
diff --git a/src/com/android/mail/providers/Attachment.java b/src/com/android/mail/providers/Attachment.java
index af4b3e3..7f56d1d 100644
--- a/src/com/android/mail/providers/Attachment.java
+++ b/src/com/android/mail/providers/Attachment.java
@@ -160,6 +160,14 @@
*/
public String providerData;
+ /**
+ * Streamable mime type of the attachment in case it's a virtual file.
+ *
+ * Might be null. If null, then the default type (contentType) is assumed
+ * to be streamable.
+ */
+ public String virtualMimeType;
+
private transient Uri mIdentifierUri;
/**
@@ -186,6 +194,7 @@
supportsDownloadAgain = in.readInt() == 1;
type = in.readInt();
flags = in.readInt();
+ virtualMimeType = in.readString();
}
public Attachment(Cursor cursor) {
@@ -211,6 +220,7 @@
cursor.getColumnIndex(AttachmentColumns.SUPPORTS_DOWNLOAD_AGAIN)) == 1;
type = cursor.getInt(cursor.getColumnIndex(AttachmentColumns.TYPE));
flags = cursor.getInt(cursor.getColumnIndex(AttachmentColumns.FLAGS));
+ virtualMimeType = cursor.getString(cursor.getColumnIndex(AttachmentColumns.VIRTUAL_MIME_TYPE));
}
public Attachment(JSONObject srcJson) {
@@ -228,6 +238,7 @@
supportsDownloadAgain = srcJson.optBoolean(AttachmentColumns.SUPPORTS_DOWNLOAD_AGAIN, true);
type = srcJson.optInt(AttachmentColumns.TYPE);
flags = srcJson.optInt(AttachmentColumns.FLAGS);
+ virtualMimeType = srcJson.optString(AttachmentColumns.VIRTUAL_MIME_TYPE, null);
}
/**
@@ -262,6 +273,7 @@
type = inline ? AttachmentType.INLINE_CURRENT_MESSAGE : AttachmentType.STANDARD;
partId = cid;
flags = 0;
+ virtualMimeType = null;
// insert attachment into content provider so that we can open the file
final ContentResolver resolver = context.getContentResolver();
@@ -308,6 +320,7 @@
type = values.getAsInteger(AttachmentColumns.TYPE);
flags = values.getAsInteger(AttachmentColumns.FLAGS);
partId = values.getAsString(AttachmentColumns.CONTENT_ID);
+ virtualMimeType = values.getAsString(AttachmentColumns.VIRTUAL_MIME_TYPE);
}
/**
@@ -333,6 +346,7 @@
values.put(AttachmentColumns.TYPE, type);
values.put(AttachmentColumns.FLAGS, flags);
values.put(AttachmentColumns.CONTENT_ID, partId);
+ values.put(AttachmentColumns.VIRTUAL_MIME_TYPE, virtualMimeType);
return values;
}
@@ -353,6 +367,7 @@
dest.writeInt(supportsDownloadAgain ? 1 : 0);
dest.writeInt(type);
dest.writeInt(flags);
+ dest.writeString(virtualMimeType);
}
public JSONObject toJSON() throws JSONException {
@@ -372,6 +387,7 @@
result.put(AttachmentColumns.SUPPORTS_DOWNLOAD_AGAIN, supportsDownloadAgain);
result.put(AttachmentColumns.TYPE, type);
result.put(AttachmentColumns.FLAGS, flags);
+ result.put(AttachmentColumns.VIRTUAL_MIME_TYPE, virtualMimeType);
return result;
}
diff --git a/src/com/android/mail/providers/UIProvider.java b/src/com/android/mail/providers/UIProvider.java
index 783e4f3..3bb6da5 100644
--- a/src/com/android/mail/providers/UIProvider.java
+++ b/src/com/android/mail/providers/UIProvider.java
@@ -1958,7 +1958,8 @@
AttachmentColumns.SUPPORTS_DOWNLOAD_AGAIN,
AttachmentColumns.TYPE,
AttachmentColumns.FLAGS,
- AttachmentColumns.CONTENT_ID
+ AttachmentColumns.CONTENT_ID,
+ AttachmentColumns.VIRTUAL_MIME_TYPE
};
public static final int ATTACHMENT_NAME_COLUMN = 0;
public static final int ATTACHMENT_SIZE_COLUMN = 1;
@@ -1974,6 +1975,7 @@
public static final int ATTACHMENT_TYPE_COLUMN = 11;
public static final int ATTACHMENT_FLAGS_COLUMN = 12;
public static final int ATTACHMENT_CONTENT_ID_COLUMN = 13;
+ public static final int ATTACHMENT_VIRTUAL_MIME_TYPE_COLUMN = 14;
/** Separates attachment info parts in strings in the database. */
public static final String ATTACHMENT_INFO_SEPARATOR = "\n"; // use to join
@@ -2160,6 +2162,11 @@
*/
public static final String CONTENT_ID = "contentId";
+ /**
+ * Holds a streamable mime type for this attachment if it's a virtual file.
+ */
+ public static final String VIRTUAL_MIME_TYPE = "streamableMimeType";
+
private AttachmentColumns() {}
}
diff --git a/src/com/android/mail/ui/AbstractMailActivity.java b/src/com/android/mail/ui/AbstractMailActivity.java
index 00d2f5f..5cf4128 100644
--- a/src/com/android/mail/ui/AbstractMailActivity.java
+++ b/src/com/android/mail/ui/AbstractMailActivity.java
@@ -20,7 +20,7 @@
import android.content.Context;
import android.os.Bundle;
import android.os.StrictMode;
-import android.support.v7.app.ActionBarActivity;
+import android.support.v7.app.AppCompatActivity;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -37,7 +37,7 @@
* <p>In the Gmail codebase, this was called GmailBaseActivity</p>
*
*/
-public abstract class AbstractMailActivity extends ActionBarActivity implements RestrictedActivity {
+public abstract class AbstractMailActivity extends AppCompatActivity implements RestrictedActivity {
private final UiHandler mUiHandler = new UiHandler();
diff --git a/src/com/android/mail/ui/AccountFeedbackActivity.java b/src/com/android/mail/ui/AccountFeedbackActivity.java
index 89a736d..e3cb592 100644
--- a/src/com/android/mail/ui/AccountFeedbackActivity.java
+++ b/src/com/android/mail/ui/AccountFeedbackActivity.java
@@ -21,7 +21,7 @@
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
-import android.support.v7.app.ActionBarActivity;
+import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
@@ -37,7 +37,7 @@
* as well as showing settings/help/send feedback in the action
* overflow menu.
*/
-public abstract class AccountFeedbackActivity extends ActionBarActivity
+public abstract class AccountFeedbackActivity extends AppCompatActivity
implements ConversationAccountController, AccountLoadCallbacks.AccountLoadCallbackListener {
public static final String EXTRA_ACCOUNT_URI = "extra-account-uri";
diff --git a/src/com/android/mail/ui/ActionableToastBar.java b/src/com/android/mail/ui/ActionableToastBar.java
index 8ad9828..c6bf990 100644
--- a/src/com/android/mail/ui/ActionableToastBar.java
+++ b/src/com/android/mail/ui/ActionableToastBar.java
@@ -459,4 +459,4 @@
public interface ActionClickedListener {
public void onActionClicked(Context context);
}
-}
\ No newline at end of file
+}
diff --git a/src/com/android/mail/ui/FolderSelectionActivity.java b/src/com/android/mail/ui/FolderSelectionActivity.java
index 53e3539..09dae1a 100644
--- a/src/com/android/mail/ui/FolderSelectionActivity.java
+++ b/src/com/android/mail/ui/FolderSelectionActivity.java
@@ -26,7 +26,7 @@
import android.database.DataSetObservable;
import android.database.DataSetObserver;
import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
+import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
@@ -50,7 +50,7 @@
/**
* This activity displays the list of available folders for the current account.
*/
-public class FolderSelectionActivity extends ActionBarActivity implements OnClickListener,
+public class FolderSelectionActivity extends AppCompatActivity implements OnClickListener,
DialogInterface.OnClickListener, ControllableActivity,
FolderSelector {
public static final String EXTRA_ACCOUNT_SHORTCUT = "account-shortcut";
diff --git a/src/com/android/mail/ui/MailboxSelectionActivity.java b/src/com/android/mail/ui/MailboxSelectionActivity.java
index e524083..9605f09 100644
--- a/src/com/android/mail/ui/MailboxSelectionActivity.java
+++ b/src/com/android/mail/ui/MailboxSelectionActivity.java
@@ -36,7 +36,7 @@
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
-import android.support.v7.app.ActionBarActivity;
+import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
@@ -49,7 +49,7 @@
* An activity that shows the list of all the available accounts and return the
* one selected in onResult().
*/
-public class MailboxSelectionActivity extends ActionBarActivity implements OnClickListener,
+public class MailboxSelectionActivity extends AppCompatActivity implements OnClickListener,
LoaderManager.LoaderCallbacks<Cursor>, AdapterView.OnItemClickListener {
// Used to save our instance state
diff --git a/src/com/android/mail/ui/RestrictedActivity.java b/src/com/android/mail/ui/RestrictedActivity.java
index ed91b7b..364f677 100644
--- a/src/com/android/mail/ui/RestrictedActivity.java
+++ b/src/com/android/mail/ui/RestrictedActivity.java
@@ -36,9 +36,9 @@
/**
* {@link RestrictedActivity} gives access to a subset of
- * {@link android.support.v7.app.ActionBarActivity} methods.
+ * {@link android.support.v7.app.AppCompatActivity} methods.
* These methods match the signatures from
- * {@link android.support.v7.app.ActionBarActivity}.
+ * {@link android.support.v7.app.AppCompatActivity}.
*/
public interface RestrictedActivity {
/*
@@ -49,7 +49,7 @@
/**
* @see android.app.Activity#findViewById(int)
*/
- View findViewById(int id);
+ <T extends View> T findViewById(int id);
/**
* @see android.app.Activity#finish()
@@ -57,7 +57,7 @@
void finish();
/**
- * @see android.support.v7.app.ActionBarActivity#getSupportActionBar()
+ * @see android.support.v7.app.AppCompatActivity#getSupportActionBar()
*/
ActionBar getSupportActionBar();
@@ -102,7 +102,7 @@
Window getWindow();
/**
- * @see android.support.v7.app.ActionBarActivity#supportInvalidateOptionsMenu()
+ * @see android.support.v7.app.AppCompatActivity#supportInvalidateOptionsMenu()
*/
void supportInvalidateOptionsMenu();
@@ -147,7 +147,7 @@
void showDialog(int id);
/**
- * @see android.support.v7.app.ActionBarActivity#startSupportActionMode(ActionMode.Callback)
+ * @see android.support.v7.app.AppCompatActivity#startSupportActionMode(ActionMode.Callback)
*/
ActionMode startSupportActionMode(ActionMode.Callback callback);
diff --git a/src/com/android/mail/utils/AttachmentUtils.java b/src/com/android/mail/utils/AttachmentUtils.java
index 4837f7a..8cdaef8 100644
--- a/src/com/android/mail/utils/AttachmentUtils.java
+++ b/src/com/android/mail/utils/AttachmentUtils.java
@@ -17,6 +17,8 @@
import android.app.DownloadManager;
import android.content.Context;
+import android.content.res.AssetFileDescriptor;
+import android.content.res.AssetFileDescriptor.AutoCloseInputStream;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
@@ -187,13 +189,13 @@
try {
final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-kk:mm:ss");
file = File.createTempFile(dateFormat.format(new Date()), ".attachment", cacheDir);
- final ParcelFileDescriptor fileDescriptor = attachmentFds != null
- && attachment.contentUri != null ? (ParcelFileDescriptor) attachmentFds
+ final AssetFileDescriptor fileDescriptor = attachmentFds != null
+ && attachment.contentUri != null ? (AssetFileDescriptor) attachmentFds
.getParcelable(attachment.contentUri.toString())
: null;
if (fileDescriptor != null) {
// Get the input stream from the file descriptor
- inputStream = new FileInputStream(fileDescriptor.getFileDescriptor());
+ inputStream = new AutoCloseInputStream(fileDescriptor);
} else {
if (attachment.contentUri == null) {
// The contentUri of the attachment is null. This can happen when sending a
@@ -203,7 +205,15 @@
throw new FileNotFoundException("Missing contentUri in attachment");
}
// Attempt to open the file
- inputStream = context.getContentResolver().openInputStream(attachment.contentUri);
+ if (attachment.virtualMimeType == null) {
+ inputStream = context.getContentResolver().openInputStream(attachment.contentUri);
+ } else {
+ AssetFileDescriptor fd = context.getContentResolver().openTypedAssetFileDescriptor(
+ attachment.contentUri, attachment.virtualMimeType, null, null);
+ if (fd != null) {
+ inputStream = new AutoCloseInputStream(fd);
+ }
+ }
}
outputStream = new FileOutputStream(file);
final long now = SystemClock.elapsedRealtime();
diff --git a/src/com/android/mail/utils/Utils.java b/src/com/android/mail/utils/Utils.java
index a9c93bf..4efbccc 100644
--- a/src/com/android/mail/utils/Utils.java
+++ b/src/com/android/mail/utils/Utils.java
@@ -36,6 +36,7 @@
import android.os.Bundle;
import android.provider.Browser;
import android.support.annotation.Nullable;
+import android.support.annotation.VisibleForTesting;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
@@ -144,6 +145,10 @@
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
}
+ public static boolean isRunningNOrLater() {
+ return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N;
+ }
+
/**
* @return Whether we are running on a low memory device. This is used to disable certain
* memory intensive features in the app.
@@ -1069,6 +1074,7 @@
* Applies the given appearance on the given subString, and inserts that as a parameter in the
* given parentString.
*/
+ @VisibleForTesting
public static Spanned insertStringWithStyle(Context context,
String entireString, String subString, int appearance) {
final int index = entireString.indexOf(subString);
diff --git a/tests/Android.mk b/tests/Android.mk
index 902d31f..4762862 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -31,7 +31,7 @@
LOCAL_SRC_FILES := $(call all-java-files-under, $(src_dirs))
LOCAL_AAPT_FLAGS := --auto-add-overlay
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test legacy-android-test
include $(BUILD_PACKAGE)
diff --git a/tests/src/com/android/mail/browse/ConversationCursorTests.java b/tests/src/com/android/mail/browse/ConversationCursorTests.java
index bd8c928..5034526 100644
--- a/tests/src/com/android/mail/browse/ConversationCursorTests.java
+++ b/tests/src/com/android/mail/browse/ConversationCursorTests.java
@@ -25,6 +25,7 @@
import android.content.Context;
import android.content.OperationApplicationException;
import android.net.Uri;
+import android.os.Looper;
import android.os.RemoteException;
import android.test.ProviderTestCase2;
import android.test.mock.MockContentResolver;
@@ -47,6 +48,7 @@
public ConversationCursorTests() {
super(TestProvider.class, TestProvider.AUTHORITY);
+ Looper.prepare();
mActivity = new Activity() {
@Override
public ContentResolver getContentResolver() {
@@ -60,7 +62,6 @@
super.setUp();
mMockContext = getMockContext();
mMockResolver = (MockContentResolver)mMockContext.getContentResolver();
- mMockResolver.addProvider(TestProvider.AUTHORITY, new TestProvider(mMockContext));
}
@Override
diff --git a/tests/src/com/android/mail/browse/EmlMessageLoaderTest.java b/tests/src/com/android/mail/browse/EmlMessageLoaderTest.java
index 8e4b803..54f1a25 100644
--- a/tests/src/com/android/mail/browse/EmlMessageLoaderTest.java
+++ b/tests/src/com/android/mail/browse/EmlMessageLoaderTest.java
@@ -54,8 +54,8 @@
@SmallTest
public void testLoadingBlankEml() throws Exception {
- final Uri emptyEmlUri = TestProvider.uri(
- new Uri.Builder().scheme("content").authority("empty").path("empty").build());
+ final Uri emptyEmlUri = new Uri.Builder().scheme("content").authority(
+ TestProvider.AUTHORITY).path("empty").build();
final ContentValues cv = new ContentValues(2);
cv.put(OpenableColumns.DISPLAY_NAME, "Empty.eml");
cv.put(OpenableColumns.SIZE, 0);
diff --git a/tests/src/com/android/mail/browse/TestProvider.java b/tests/src/com/android/mail/browse/TestProvider.java
index df305b5..19d5ec3 100644
--- a/tests/src/com/android/mail/browse/TestProvider.java
+++ b/tests/src/com/android/mail/browse/TestProvider.java
@@ -21,6 +21,7 @@
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
+import android.content.pm.ProviderInfo;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.net.Uri;
@@ -54,9 +55,6 @@
* delete() and update() do not allow non-null selection or selectionArgs arguments; the presence
* of these will result in an UnsupportedOperationException
*
- * NOTE: When using any operation other than applyBatch, the Uri to be used must be created with
- * MockProvider.uri(yourUri). This guarantees that the operation is sent to MockProvider
- *
* NOTE: MockProvider only simulates direct storage/retrieval of rows; it does not (and can not)
* simulate other actions (e.g. creation of ancillary data) that the actual provider might perform
*
@@ -64,6 +62,7 @@
**/
public class TestProvider extends ContentProvider {
public static final String AUTHORITY = "com.android.mail.mock.provider";
+
/* package */static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
/* package */static final int TABLE = 100;
@@ -77,7 +76,9 @@
public TestProvider(Context context) {
this();
- attachInfo(context, null);
+ ProviderInfo info = new ProviderInfo();
+ info.authority = AUTHORITY;
+ attachInfo(context, info);
}
// We'll store our values here
@@ -85,17 +86,6 @@
// And we'll generate new id's from here
long mMockId = 1;
- /**
- * Create a Uri for MockProvider from a given Uri
- *
- * @param uri the Uri from which the MockProvider Uri will be created
- * @return a Uri that can be used with MockProvider
- */
- public static Uri uri(Uri uri) {
- return new Uri.Builder().scheme("content").authority(AUTHORITY)
- .path(uri.getPath().substring(1)).build();
- }
-
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
if (selection != null || selectionArgs != null) {
@@ -144,7 +134,7 @@
if (selection != null || selectionArgs != null || sortOrder != null || projection == null) {
throw new UnsupportedOperationException();
}
- final int match = sURIMatcher.match(uri(uri));
+ final int match = sURIMatcher.match(uri);
ArrayList<ContentValues> valuesList = new ArrayList<ContentValues>();
switch (match) {
case TABLE:
@@ -182,7 +172,7 @@
if (selection != null || selectionArgs != null) {
throw new UnsupportedOperationException();
}
- final int match = sURIMatcher.match(uri(uri));
+ final int match = sURIMatcher.match(uri);
ArrayList<ContentValues> updateValuesList = new ArrayList<ContentValues>();
String path = uri.getPath();
switch (match) {
diff --git a/tests/src/com/android/mail/browse/TestProviderTests.java b/tests/src/com/android/mail/browse/TestProviderTests.java
index 0e26980..be45655 100644
--- a/tests/src/com/android/mail/browse/TestProviderTests.java
+++ b/tests/src/com/android/mail/browse/TestProviderTests.java
@@ -37,7 +37,6 @@
Context mMockContext;
MockContentResolver mMockResolver;
- private static final String CANHAZ_AUTHORITY = "com.android.canhaz";
private static final String PONY_TABLE = "pony";
private static final String PONY_COLUMN_NAME = "name";
private static final String PONY_COLUMN_TYPE = "type";
@@ -60,7 +59,6 @@
super.setUp();
mMockContext = getMockContext();
mMockResolver = (MockContentResolver)mMockContext.getContentResolver();
- mMockResolver.addProvider(CANHAZ_AUTHORITY, new TestProvider(mMockContext));
}
@Override
@@ -79,8 +77,7 @@
private ContentProviderResult[] setupPonies() throws RemoteException,
OperationApplicationException {
- // The Uri is content://com.android.canhaz/pony
- Uri uri = new Uri.Builder().scheme("content").authority(CANHAZ_AUTHORITY)
+ Uri uri = new Uri.Builder().scheme("content").authority(TestProvider.AUTHORITY)
.path(PONY_TABLE).build();
// Our array of CPO's to be used with applyBatch
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
@@ -95,12 +92,11 @@
}
private static Uri getPonyUri() {
- return new Uri.Builder().scheme("content").authority(CANHAZ_AUTHORITY)
+ return new Uri.Builder().scheme("content").authority(TestProvider.AUTHORITY)
.path(PONY_TABLE).build();
}
public void testInsertQueryandDelete() throws RemoteException, OperationApplicationException {
- // The Uri is content://com.android.canhaz/pony
ContentProviderResult[] results = setupPonies();
Uri uri = getPonyUri();
@@ -108,10 +104,9 @@
assertNotNull(results);
assertEquals(2, results.length);
// Make sure that we've created matcher entries for pony and pony/#
- assertEquals(TestProvider.TABLE, TestProvider.sURIMatcher.match(TestProvider.uri(uri)));
- assertEquals(TestProvider.RECORD,
- TestProvider.sURIMatcher.match(TestProvider.uri(results[0].uri)));
- Cursor c = mMockResolver.query(TestProvider.uri(uri), PONY_PROJECTION, null, null, null);
+ assertEquals(TestProvider.TABLE, TestProvider.sURIMatcher.match(uri));
+ assertEquals(TestProvider.RECORD, TestProvider.sURIMatcher.match(results[0].uri));
+ Cursor c = mMockResolver.query(uri, PONY_PROJECTION, null, null, null);
assertNotNull(c);
assertEquals(2, c.getCount());
long eliseId = -1;
@@ -138,9 +133,9 @@
assertNotSame(-1, eliseId);
assertNotSame(-1, flickaId);
// Delete the elise record
- assertEquals(1, mMockResolver.delete(ContentUris.withAppendedId(TestProvider.uri(uri),
+ assertEquals(1, mMockResolver.delete(ContentUris.withAppendedId(uri,
eliseId), null, null));
- c = mMockResolver.query(TestProvider.uri(uri), PONY_PROJECTION, null, null, null);
+ c = mMockResolver.query(uri, PONY_PROJECTION, null, null, null);
assertNotNull(c);
// There should be one left (Flicka)
assertEquals(1, c.getCount());
@@ -149,17 +144,16 @@
}
public void testUpdate() throws RemoteException, OperationApplicationException {
- // The Uri is content://com.android.canhaz/pony
Uri uri = getPonyUri();
setupPonies();
- Cursor c = mMockResolver.query(TestProvider.uri(uri), PONY_PROJECTION, null, null, null);
+ Cursor c = mMockResolver.query(uri, PONY_PROJECTION, null, null, null);
assertNotNull(c);
assertEquals(2, c.getCount());
// Give all the ponies 5 legs
ContentValues cv = new ContentValues();
cv.put(PONY_COLUMN_LEGS, 5);
- assertEquals(2, mMockResolver.update(TestProvider.uri(uri), cv, null, null));
- c = mMockResolver.query(TestProvider.uri(uri), PONY_PROJECTION, null, null, null);
+ assertEquals(2, mMockResolver.update(uri, cv, null, null));
+ c = mMockResolver.query(uri, PONY_PROJECTION, null, null, null);
assertNotNull(c);
// We should still have two records, and each should have 5 legs, but otherwise be the same
assertEquals(2, c.getCount());