Make AccountWithDataSet null safe
Don't crash on null account names. Change AccountWithDataSet so that it
does not inherit from Account and allow name and type to be null.
Bug: 18959158
Change-Id: I6da8aa52d9c408288b2c85ac2c5a507ff42dc985
diff --git a/src/com/android/contacts/common/model/AccountTypeManager.java b/src/com/android/contacts/common/model/AccountTypeManager.java
index 6efe819..6677c84 100644
--- a/src/com/android/contacts/common/model/AccountTypeManager.java
+++ b/src/com/android/contacts/common/model/AccountTypeManager.java
@@ -126,7 +126,10 @@
}
public final AccountType getAccountTypeForAccount(AccountWithDataSet account) {
- return getAccountType(account.getAccountTypeWithDataSet());
+ if (account != null) {
+ return getAccountType(account.getAccountTypeWithDataSet());
+ }
+ return getAccountType(null, null);
}
/**
@@ -243,20 +246,12 @@
/* A latch that ensures that asynchronous initialization completes before data is used */
private volatile CountDownLatch mInitializationLatch = new CountDownLatch(1);
- private static final Comparator<Account> ACCOUNT_COMPARATOR = new Comparator<Account>() {
+ private static final Comparator<AccountWithDataSet> ACCOUNT_COMPARATOR =
+ new Comparator<AccountWithDataSet>() {
@Override
- public int compare(Account a, Account b) {
- String aDataSet = null;
- String bDataSet = null;
- if (a instanceof AccountWithDataSet) {
- aDataSet = ((AccountWithDataSet) a).dataSet;
- }
- if (b instanceof AccountWithDataSet) {
- bDataSet = ((AccountWithDataSet) b).dataSet;
- }
-
+ public int compare(AccountWithDataSet a, AccountWithDataSet b) {
if (Objects.equal(a.name, b.name) && Objects.equal(a.type, b.type)
- && Objects.equal(aDataSet, bDataSet)) {
+ && Objects.equal(a.dataSet, b.dataSet)) {
return 0;
} else if (b.name == null || b.type == null) {
return -1;
@@ -273,8 +268,8 @@
}
// Accounts without data sets get sorted before those that have them.
- if (aDataSet != null) {
- return bDataSet == null ? 1 : aDataSet.compareTo(bDataSet);
+ if (a.dataSet != null) {
+ return b.dataSet == null ? 1 : a.dataSet.compareTo(b.dataSet);
} else {
return -1;
}
diff --git a/src/com/android/contacts/common/model/RawContact.java b/src/com/android/contacts/common/model/RawContact.java
index ab30f64..3d8db85 100644
--- a/src/com/android/contacts/common/model/RawContact.java
+++ b/src/com/android/contacts/common/model/RawContact.java
@@ -296,7 +296,12 @@
}
public void setAccount(AccountWithDataSet accountWithDataSet) {
- setAccount(accountWithDataSet.name, accountWithDataSet.type, accountWithDataSet.dataSet);
+ if (accountWithDataSet != null) {
+ setAccount(accountWithDataSet.name, accountWithDataSet.type,
+ accountWithDataSet.dataSet);
+ } else {
+ setAccount(null, null, null);
+ }
}
public void setAccountToLocal() {
diff --git a/src/com/android/contacts/common/model/account/AccountWithDataSet.java b/src/com/android/contacts/common/model/account/AccountWithDataSet.java
index dd31dbc..634b5d6 100644
--- a/src/com/android/contacts/common/model/account/AccountWithDataSet.java
+++ b/src/com/android/contacts/common/model/account/AccountWithDataSet.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
+import android.os.Parcelable;
import android.os.Parcel;
import android.provider.BaseColumns;
import android.provider.ContactsContract;
@@ -36,7 +37,7 @@
/**
* Wrapper for an account that includes a data set (which may be null).
*/
-public class AccountWithDataSet extends Account {
+public class AccountWithDataSet implements Parcelable {
private static final String STRINGIFY_SEPARATOR = "\u0001";
private static final String ARRAY_STRINGIFY_SEPARATOR = "\u0002";
@@ -45,6 +46,8 @@
private static final Pattern ARRAY_STRINGIFY_SEPARATOR_PAT =
Pattern.compile(Pattern.quote(ARRAY_STRINGIFY_SEPARATOR));
+ public final String name;
+ public final String type;
public final String dataSet;
private final AccountTypeWithDataSet mAccountTypeWithDataSet;
@@ -54,20 +57,41 @@
public AccountWithDataSet(String name, String type, String dataSet) {
- super(name, type);
- this.dataSet = dataSet;
+ this.name = emptyToNull(name);
+ this.type = emptyToNull(type);
+ this.dataSet = emptyToNull(dataSet);
mAccountTypeWithDataSet = AccountTypeWithDataSet.get(type, dataSet);
}
+ private static final String emptyToNull(String text) {
+ return TextUtils.isEmpty(text) ? null : text;
+ }
+
public AccountWithDataSet(Parcel in) {
- super(in);
+ this.name = in.readString();
+ this.type = in.readString();
this.dataSet = in.readString();
mAccountTypeWithDataSet = AccountTypeWithDataSet.get(type, dataSet);
}
- @Override
+ public boolean isLocalAccount() {
+ return name == null && type == null;
+ }
+
+ public Account getAccountOrNull() {
+ if (name != null && type != null) {
+ return new Account(name, type);
+ }
+ return null;
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
public void writeToParcel(Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
+ dest.writeString(name);
+ dest.writeString(type);
dest.writeString(dataSet);
}
@@ -113,27 +137,32 @@
}
}
- @Override
- public boolean equals(Object o) {
- return (o instanceof AccountWithDataSet) && super.equals(o)
- && Objects.equal(((AccountWithDataSet) o).dataSet, dataSet);
+ public boolean equals(Object obj) {
+ if (obj instanceof AccountWithDataSet) {
+ AccountWithDataSet other = (AccountWithDataSet) obj;
+ return Objects.equal(name, other.name)
+ && Objects.equal(type, other.type)
+ && Objects.equal(dataSet, other.dataSet);
+ }
+ return false;
}
- @Override
public int hashCode() {
- return 31 * super.hashCode()
- + (dataSet == null ? 0 : dataSet.hashCode());
+ int result = 17;
+ result = 31 * result + (name != null ? name.hashCode() : 0);
+ result = 31 * result + (type != null ? type.hashCode() : 0);
+ result = 31 * result + (dataSet != null ? dataSet.hashCode() : 0);
+ return result;
}
- @Override
public String toString() {
return "AccountWithDataSet {name=" + name + ", type=" + type + ", dataSet=" + dataSet + "}";
}
private static StringBuilder addStringified(StringBuilder sb, AccountWithDataSet account) {
- sb.append(account.name);
+ if (!TextUtils.isEmpty(account.name)) sb.append(account.name);
sb.append(STRINGIFY_SEPARATOR);
- sb.append(account.type);
+ if (!TextUtils.isEmpty(account.type)) sb.append(account.type);
sb.append(STRINGIFY_SEPARATOR);
if (!TextUtils.isEmpty(account.dataSet)) sb.append(account.dataSet);
diff --git a/src/com/android/contacts/common/vcard/ImportRequest.java b/src/com/android/contacts/common/vcard/ImportRequest.java
index 0fab8f5..32efb99 100644
--- a/src/com/android/contacts/common/vcard/ImportRequest.java
+++ b/src/com/android/contacts/common/vcard/ImportRequest.java
@@ -18,6 +18,7 @@
import android.accounts.Account;
import android.net.Uri;
+import com.android.contacts.common.model.account.AccountWithDataSet;
import com.android.vcard.VCardSourceDetector;
/**
@@ -95,10 +96,10 @@
*/
public final int entryCount;
- public ImportRequest(Account account,
+ public ImportRequest(AccountWithDataSet account,
byte[] data, Uri uri, String displayName, int estimatedType, String estimatedCharset,
int vcardVersion, int entryCount) {
- this.account = account;
+ this.account = account != null ? account.getAccountOrNull() : null;
this.data = data;
this.uri = uri;
this.displayName = displayName;