Propagate original exception when throwing load exception
Bug 5198078
Change-Id: I941dc9b96d6c58eb1912d446c3c27ec4c4c2ffef
diff --git a/src/com/android/contacts/ContactLoader.java b/src/com/android/contacts/ContactLoader.java
index 1107530..a28b1db 100644
--- a/src/com/android/contacts/ContactLoader.java
+++ b/src/com/android/contacts/ContactLoader.java
@@ -93,14 +93,7 @@
/**
* Singleton instance that represents "No Contact Found"
*/
- public static final Result NOT_FOUND = new Result();
-
- /**
- * Singleton instance that represents an error, e.g. because of an invalid Uri
- * TODO: We should come up with something nicer here. Maybe use an Either type so
- * that we can capture the Exception?
- */
- public static final Result ERROR = new Result();
+ public static final Result NOT_FOUND = new Result((Exception) null);
private final Uri mLookupUri;
private final Uri mUri;
@@ -135,11 +128,12 @@
private final String mCustomRingtone;
private final boolean mIsUserProfile;
+ private final Exception mException;
+
/**
- * Constructor for case "no contact found". This must only be used for the
- * final {@link Result#NOT_FOUND} singleton
+ * Constructor for special results, namely "no contact found" and "error".
*/
- private Result() {
+ private Result(Exception exception) {
mLookupUri = null;
mUri = null;
mDirectoryId = -1;
@@ -161,7 +155,11 @@
mSendToVoicemail = false;
mCustomRingtone = null;
mIsUserProfile = false;
+ mException = exception;
+ }
+ private static Result forError(Exception exception) {
+ return new Result(exception);
}
/**
@@ -172,6 +170,7 @@
String displayName, String altDisplayName, String phoneticName, boolean starred,
Integer presence, boolean sendToVoicemail, String customRingtone,
boolean isUserProfile) {
+ mException = null;
mLookupUri = lookupUri;
mUri = uri;
mDirectoryId = directoryId;
@@ -196,6 +195,7 @@
}
private Result(Result from) {
+ mException = from.mException;
mLookupUri = from.mLookupUri;
mUri = from.mUri;
mDirectoryId = from.mDirectoryId;
@@ -267,6 +267,18 @@
return mId;
}
+ /**
+ * @return true when an exception happened during loading, in which case
+ * {@link #getException} returns the actual exception object.
+ */
+ public boolean isError() {
+ return mException != null;
+ }
+
+ public Exception getException() {
+ return mException;
+ }
+
public long getNameRawContactId() {
return mNameRawContactId;
}
@@ -631,7 +643,7 @@
return result;
} catch (Exception e) {
Log.e(TAG, "Error loading the contact: " + mLookupUri, e);
- return Result.ERROR;
+ return Result.forError(e);
}
}
@@ -1087,7 +1099,7 @@
mContact = result;
- if (result != Result.ERROR && result != Result.NOT_FOUND) {
+ if (!result.isError() && result != Result.NOT_FOUND) {
mLookupUri = result.getLookupUri();
if (!result.isDirectoryEntry()) {
diff --git a/src/com/android/contacts/detail/ContactLoaderFragment.java b/src/com/android/contacts/detail/ContactLoaderFragment.java
index c82d735..f3c6158 100644
--- a/src/com/android/contacts/detail/ContactLoaderFragment.java
+++ b/src/com/android/contacts/detail/ContactLoaderFragment.java
@@ -187,13 +187,10 @@
return;
}
- if (data == ContactLoader.Result.ERROR) {
+ if (data.isError()) {
// This shouldn't ever happen, so throw an exception. The {@link ContactLoader}
// should log the actual exception.
- // TODO: Make the {@link ContactLoader.Result} pass the exception so we can include
- // the original stack trace when this error is thrown.
- throw new IllegalStateException("The result of the ContactLoader is "
- + "ContactLoader.Result.ERROR");
+ throw new IllegalStateException("Failed to load contact", data.getException());
} else if (data == ContactLoader.Result.NOT_FOUND) {
Log.i(TAG, "No contact found: " + ((ContactLoader)loader).getLookupUri());
mContactData = null;
diff --git a/src/com/android/contacts/editor/ContactEditorFragment.java b/src/com/android/contacts/editor/ContactEditorFragment.java
index 5a96e7f..046b1ed 100644
--- a/src/com/android/contacts/editor/ContactEditorFragment.java
+++ b/src/com/android/contacts/editor/ContactEditorFragment.java
@@ -1610,7 +1610,7 @@
public void onLoadFinished(Loader<ContactLoader.Result> loader, ContactLoader.Result data) {
final long loaderCurrentTime = SystemClock.elapsedRealtime();
Log.v(TAG, "Time needed for loading: " + (loaderCurrentTime-mLoaderStartTime));
- if (data == ContactLoader.Result.NOT_FOUND || data == ContactLoader.Result.ERROR) {
+ if (data == ContactLoader.Result.NOT_FOUND || data.isError()) {
// Item has been deleted
Log.i(TAG, "No contact found. Closing activity");
if (mListener != null) mListener.onContactNotFound();
diff --git a/src/com/android/contacts/socialwidget/SocialWidgetProvider.java b/src/com/android/contacts/socialwidget/SocialWidgetProvider.java
index b29a9cd..cd6a494 100644
--- a/src/com/android/contacts/socialwidget/SocialWidgetProvider.java
+++ b/src/com/android/contacts/socialwidget/SocialWidgetProvider.java
@@ -133,8 +133,7 @@
final RemoteViews views = new RemoteViews(context.getPackageName(),
R.layout.social_widget);
- if (contactData == ContactLoader.Result.ERROR ||
- contactData == ContactLoader.Result.NOT_FOUND) {
+ if (contactData.isError() || contactData == ContactLoader.Result.NOT_FOUND) {
setDisplayNameAndSnippet(context, views,
context.getString(R.string.invalidContactMessage), null, null, null);
setPhoto(views, ContactBadgeUtil.loadPlaceholderPhoto(context));
diff --git a/tests/src/com/android/contacts/ContactLoaderTest.java b/tests/src/com/android/contacts/ContactLoaderTest.java
index 3560ce1..5d44cf1 100644
--- a/tests/src/com/android/contacts/ContactLoaderTest.java
+++ b/tests/src/com/android/contacts/ContactLoaderTest.java
@@ -76,17 +76,17 @@
public void testNullUri() {
ContactLoader.Result result = assertLoadContact(null);
- assertEquals(ContactLoader.Result.ERROR, result);
+ assertTrue(result.isError());
}
public void testEmptyUri() {
ContactLoader.Result result = assertLoadContact(Uri.EMPTY);
- assertEquals(ContactLoader.Result.ERROR, result);
+ assertTrue(result.isError());
}
public void testInvalidUri() {
ContactLoader.Result result = assertLoadContact(Uri.parse("content://wtf"));
- assertEquals(ContactLoader.Result.ERROR, result);
+ assertTrue(result.isError());
}
public void testLoadContactWithContactIdUri() {