Merge "Fixing tests that did not get updated earlier" into froyo
diff --git a/src/com/android/contacts/ImportVCardActivity.java b/src/com/android/contacts/ImportVCardActivity.java
index a8b3f1e..4dcf5d5 100644
--- a/src/com/android/contacts/ImportVCardActivity.java
+++ b/src/com/android/contacts/ImportVCardActivity.java
@@ -31,6 +31,7 @@
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
+import android.os.FileUtils;
import android.os.Handler;
import android.os.PowerManager;
import android.pim.vcard.VCardConfig;
@@ -53,9 +54,12 @@
import android.text.style.RelativeSizeSpan;
import android.util.Log;
+import java.io.BufferedOutputStream;
import java.io.File;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.OutputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@@ -153,6 +157,7 @@
private boolean mCanceled;
private PowerManager.WakeLock mWakeLock;
private Uri mUri;
+ private File mTempFile;
private List<VCardFile> mSelectedVCardFileList;
private List<String> mErrorFileNameList;
@@ -190,11 +195,18 @@
boolean shouldCallFinish = true;
mWakeLock.acquire();
Uri createdUri = null;
+ mTempFile = null;
// Some malicious vCard data may make this thread broken
// (e.g. OutOfMemoryError).
// Even in such cases, some should be done.
try {
if (mUri != null) { // Read one vCard expressed by mUri
+ final Uri uri = getReopenableUri(mUri);
+ if (uri == null) {
+ shouldCallFinish = false;
+ return;
+ }
+
mProgressDialogForReadVCard.setProgressNumberFormat("");
mProgressDialogForReadVCard.setProgress(0);
@@ -208,16 +220,15 @@
VCardSourceDetector detector = new VCardSourceDetector();
VCardInterpreterCollection builderCollection = new VCardInterpreterCollection(
Arrays.asList(counter, detector));
-
boolean result;
try {
- result = readOneVCardFile(mUri,
+ result = readOneVCardFile(uri,
VCardConfig.DEFAULT_CHARSET, builderCollection, null, true, null);
} catch (VCardNestedException e) {
try {
// Assume that VCardSourceDetector was able to detect the source.
// Try again with the detector.
- result = readOneVCardFile(mUri,
+ result = readOneVCardFile(uri,
VCardConfig.DEFAULT_CHARSET, counter, detector, false, null);
} catch (VCardNestedException e2) {
result = false;
@@ -239,7 +250,7 @@
mProgressDialogForReadVCard.setIndeterminate(false);
mProgressDialogForReadVCard.setMax(counter.getCount());
String charset = detector.getEstimatedCharset();
- createdUri = doActuallyReadOneVCard(mUri, null, charset, true, detector,
+ createdUri = doActuallyReadOneVCard(uri, null, charset, true, detector,
mErrorFileNameList);
} else { // Read multiple files.
mProgressDialogForReadVCard.setProgressNumberFormat(
@@ -251,7 +262,13 @@
if (mCanceled) {
return;
}
- final Uri uri = Uri.parse("file://" + vcardFile.getCanonicalPath());
+ // TODO: detect scheme!
+ final Uri uri = getReopenableUri(
+ Uri.parse("file://" + vcardFile.getCanonicalPath()));
+ if (uri == null) {
+ shouldCallFinish = false;
+ return;
+ }
VCardSourceDetector detector = new VCardSourceDetector();
try {
@@ -271,6 +288,12 @@
} finally {
mWakeLock.release();
mProgressDialogForReadVCard.dismiss();
+ if (mTempFile != null) {
+ if (!mTempFile.delete()) {
+ Log.w(LOG_TAG, "Failed to delete a cache file.");
+ }
+ mTempFile = null;
+ }
// finish() is called via mCancelListener, which is used in DialogDisplayer.
if (shouldCallFinish && !isFinishing()) {
if (mErrorFileNameList == null || mErrorFileNameList.isEmpty()) {
@@ -310,6 +333,49 @@
}
}
+ private Uri getReopenableUri(final Uri uri) {
+ if ("file".equals(uri.getScheme())) {
+ return uri;
+ } else {
+ // We may not be able to scan a given uri more than once when it does not
+ // point to a local file, while it is necessary to scan it more than once
+ // because of vCard limitation. We rely on a local temporary file instead.
+ //
+ // e.g. Email app's AttachmentProvider is able to give us a content Uri
+ // with an attachment file, but we cannot "sometimes" (not always) scan
+ // the Uri more than once because of permission revocation.
+ InputStream is = null;
+ OutputStream os = null;
+ Uri reopenableUri = null;
+ try {
+ is = mResolver.openInputStream(uri);
+ File dir = getDir("tmp", MODE_PRIVATE);
+ mTempFile = dir.createTempFile("vcf", null, dir);
+ FileUtils.copyToFile(is, mTempFile);
+ reopenableUri = Uri.parse("file://" + mTempFile.getCanonicalPath());
+ } catch (IOException e) {
+ mHandler.post(new DialogDisplayer(
+ getString(R.string.fail_reason_io_error) +
+ ": " + e.getLocalizedMessage()));
+ return null;
+ } finally {
+ if (is != null) {
+ try {
+ is.close();
+ } catch (IOException e) {
+ }
+ }
+ if (os != null) {
+ try {
+ os.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ return reopenableUri;
+ }
+ }
+
private Uri doActuallyReadOneVCard(Uri uri, Account account,
String charset, boolean showEntryParseProgress,
VCardSourceDetector detector, List<String> errorFileNameList) {
diff --git a/src/com/android/contacts/ViewContactActivity.java b/src/com/android/contacts/ViewContactActivity.java
index 2b2a8f7..ead6a4a 100644
--- a/src/com/android/contacts/ViewContactActivity.java
+++ b/src/com/android/contacts/ViewContactActivity.java
@@ -402,7 +402,7 @@
// Contains an Id.
final long uriContactId = Long.parseLong(segments.get(3));
- final String uriLookupKey = segments.get(2);
+ final String uriLookupKey = Uri.encode(segments.get(2));
final Uri dataUri = Uri.withAppendedPath(
ContentUris.withAppendedId(Contacts.CONTENT_URI, uriContactId),
Contacts.Data.CONTENT_DIRECTORY);