DO NOT MERGE Make third party sync adapters editable
Bug:3093621
Change-Id: If3bb34f7d29bea4bd873342232bea3c1a77bcd2a
diff --git a/res/layout/external_raw_contact_editor_view.xml b/res/layout/raw_contact_readonly_editor_view.xml
similarity index 94%
rename from res/layout/external_raw_contact_editor_view.xml
rename to res/layout/raw_contact_readonly_editor_view.xml
index f1ba198..b34028a 100644
--- a/res/layout/external_raw_contact_editor_view.xml
+++ b/res/layout/raw_contact_readonly_editor_view.xml
@@ -14,8 +14,7 @@
limitations under the License.
-->
-<!-- placed inside act_edit as tabcontent -->
-<com.android.contacts.editor.ExternalRawContactEditorView
+<com.android.contacts.editor.RawContactReadOnlyEditorView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -77,4 +76,4 @@
android:layout_height="wrap_content"
android:orientation="vertical"/>
-</com.android.contacts.editor.ExternalRawContactEditorView>
+</com.android.contacts.editor.RawContactReadOnlyEditorView>
diff --git a/src/com/android/contacts/activities/ConfirmAddDetailActivity.java b/src/com/android/contacts/activities/ConfirmAddDetailActivity.java
index 95a39e7..4b297d9 100644
--- a/src/com/android/contacts/activities/ConfirmAddDetailActivity.java
+++ b/src/com/android/contacts/activities/ConfirmAddDetailActivity.java
@@ -560,8 +560,7 @@
final String dataSet = state.getValues().getAsString(RawContacts.DATA_SET);
final AccountType type = mAccountTypeManager.getAccountType(accountType, dataSet);
- // Raw contacts that are not from external sources should be editable.
- if (!type.isExternal()) {
+ if (type.areContactsWritable()) {
mEditableAccountType = type;
mState = state;
return;
diff --git a/src/com/android/contacts/detail/ContactDetailFragment.java b/src/com/android/contacts/detail/ContactDetailFragment.java
index 9659c01..d4bff5c 100644
--- a/src/com/android/contacts/detail/ContactDetailFragment.java
+++ b/src/com/android/contacts/detail/ContactDetailFragment.java
@@ -23,7 +23,6 @@
import com.android.contacts.ContactSaveService;
import com.android.contacts.ContactsUtils;
import com.android.contacts.GroupMetaData;
-import com.android.contacts.NfcHandler;
import com.android.contacts.R;
import com.android.contacts.TypePrecedence;
import com.android.contacts.activities.ContactDetailActivity.FragmentKeyListener;
@@ -154,7 +153,6 @@
private Button mQuickFixButton;
private QuickFix mQuickFix;
- private final ArrayList<Long> mWritableRawContactIds = new ArrayList<Long>();
private int mNumPhoneNumbers = 0;
private String mDefaultCountryIso;
private boolean mContactHasSocialUpdates;
@@ -531,8 +529,6 @@
mPrimaryPhoneUri = null;
mNumPhoneNumbers = 0;
- mWritableRawContactIds.clear();
-
final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
// Build up method entries
@@ -550,10 +546,8 @@
if (!mRawContactIds.contains(rawContactId)) {
mRawContactIds.add(rawContactId);
}
+
AccountType type = accountTypes.getAccountType(accountType, dataSet);
- if (type == null || type.areContactsWritable()) {
- mWritableRawContactIds.add(rawContactId);
- }
for (NamedContentValues subValue : entity.getSubValues()) {
final ContentValues entryValues = subValue.values;
diff --git a/src/com/android/contacts/editor/ContactEditorFragment.java b/src/com/android/contacts/editor/ContactEditorFragment.java
index 22fc3fc..a8c0b36 100644
--- a/src/com/android/contacts/editor/ContactEditorFragment.java
+++ b/src/com/android/contacts/editor/ContactEditorFragment.java
@@ -95,7 +95,7 @@
public class ContactEditorFragment extends Fragment implements
SplitContactConfirmationDialogFragment.Listener,
AggregationSuggestionEngine.Listener, AggregationSuggestionView.Listener,
- ExternalRawContactEditorView.Listener {
+ RawContactReadOnlyEditorView.Listener {
private static final String TAG = ContactEditorFragment.class.getSimpleName();
@@ -449,7 +449,8 @@
String dataSet = entityValues.getAsString(RawContacts.DATA_SET);
AccountType accountType = AccountTypeManager.getInstance(mContext).getAccountType(
type, dataSet);
- if (accountType.getEditContactActivityClassName() != null) {
+ if (accountType.getEditContactActivityClassName() != null &&
+ !accountType.areContactsWritable()) {
if (mListener != null) {
String name = entityValues.getAsString(RawContacts.ACCOUNT_NAME);
long rawContactId = entityValues.getAsLong(RawContacts.Entity._ID);
@@ -671,10 +672,10 @@
final long rawContactId = values.getAsLong(RawContacts._ID);
final BaseRawContactEditorView editor;
- if (type.isExternal()) {
+ if (!type.areContactsWritable()) {
editor = (BaseRawContactEditorView) inflater.inflate(
- R.layout.external_raw_contact_editor_view, mContent, false);
- ((ExternalRawContactEditorView) editor).setListener(this);
+ R.layout.raw_contact_readonly_editor_view, mContent, false);
+ ((RawContactReadOnlyEditorView) editor).setListener(this);
} else {
editor = (RawContactEditorView) inflater.inflate(R.layout.raw_contact_editor_view,
mContent, false);
diff --git a/src/com/android/contacts/editor/ExternalRawContactEditorView.java b/src/com/android/contacts/editor/RawContactReadOnlyEditorView.java
similarity index 97%
rename from src/com/android/contacts/editor/ExternalRawContactEditorView.java
rename to src/com/android/contacts/editor/RawContactReadOnlyEditorView.java
index 21517ed..9e1085d 100644
--- a/src/com/android/contacts/editor/ExternalRawContactEditorView.java
+++ b/src/com/android/contacts/editor/RawContactReadOnlyEditorView.java
@@ -51,7 +51,7 @@
/**
* Custom view that displays external contacts in the edit screen.
*/
-public class ExternalRawContactEditorView extends BaseRawContactEditorView
+public class RawContactReadOnlyEditorView extends BaseRawContactEditorView
implements OnClickListener {
private LayoutInflater mInflater;
@@ -76,11 +76,11 @@
void onExternalEditorRequest(AccountWithDataSet account, Uri uri);
}
- public ExternalRawContactEditorView(Context context) {
+ public RawContactReadOnlyEditorView(Context context) {
super(context);
}
- public ExternalRawContactEditorView(Context context, AttributeSet attrs) {
+ public RawContactReadOnlyEditorView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@@ -187,7 +187,7 @@
mName.setText(primary != null ? primary.getAsString(StructuredName.DISPLAY_NAME) :
mContext.getString(R.string.missing_name));
- if (type.areContactsWritable()) {
+ if (type.getEditContactActivityClassName() != null) {
mAccountContainer.setBackgroundDrawable(null);
mAccountContainer.setEnabled(false);
mEditExternallyButton.setVisibility(View.VISIBLE);
@@ -237,7 +237,8 @@
} else {
emailType = null;
}
- bindData(mContext.getText(R.string.emailLabelsGroup), emailAddress, null, i == 0);
+ bindData(mContext.getText(R.string.emailLabelsGroup), emailAddress, emailType,
+ i == 0);
}
}
diff --git a/src/com/android/contacts/model/AccountType.java b/src/com/android/contacts/model/AccountType.java
index eef8049..21e17bd 100644
--- a/src/com/android/contacts/model/AccountType.java
+++ b/src/com/android/contacts/model/AccountType.java
@@ -81,16 +81,14 @@
*/
private HashMap<String, DataKind> mMimeKinds = Maps.newHashMap();
- public boolean isExternal() {
- return false;
- }
-
public boolean isExtension() {
return false;
}
/**
- * @return True if contacts can be created and edited using this app
+ * @return True if contacts can be created and edited using this app. If false,
+ * there could still be an external editor as provided by
+ * {@link #getEditContactActivityClassName()} or {@link #getCreateContactActivityClassName()}
*/
public abstract boolean areContactsWritable();
diff --git a/src/com/android/contacts/model/EntityModifier.java b/src/com/android/contacts/model/EntityModifier.java
index fdac645..8582ed8 100644
--- a/src/com/android/contacts/model/EntityModifier.java
+++ b/src/com/android/contacts/model/EntityModifier.java
@@ -961,12 +961,11 @@
// Migrate data supported by the new account type.
// All the other data inside oldState are silently dropped.
for (DataKind kind : newAccountType.getSortedDataKinds()) {
+ if (!kind.editable) continue;
final String mimeType = kind.mimeType;
- final int fieldCount = kind.fieldList.size();
- final Set<String> allowedColumns = new HashSet<String>();
if (DataKind.PSEUDO_MIME_TYPE_DISPLAY_NAME.equals(mimeType)
|| DataKind.PSEUDO_MIME_TYPE_PHONETIC_NAME.equals(mimeType)) {
- // Ignore pseude data.
+ // Ignore pseudo data.
continue;
} else if (StructuredName.CONTENT_ITEM_TYPE.equals(mimeType)) {
migrateStructuredName(context, oldState, newState, kind);
@@ -976,8 +975,10 @@
migrateEvent(oldState, newState, kind, null /* default Year */);
} else if (sGenericMimeTypesWithoutTypeSupport.contains(mimeType)) {
migrateGenericWithoutTypeColumn(oldState, newState, kind);
- } else {
+ } else if (sGenericMimeTypesWithTypeSupport.contains(mimeType)) {
migrateGenericWithTypeColumn(oldState, newState, kind);
+ } else {
+ throw new IllegalStateException("Unexpected editable mime-type: " + mimeType);
}
}
}
@@ -1296,10 +1297,6 @@
/** @hide Public only for testing. */
public static void migrateGenericWithTypeColumn(
EntityDelta oldState, EntityDelta newState, DataKind newDataKind) {
- if (!sGenericMimeTypesWithTypeSupport.contains(newDataKind.mimeType)) {
- throw new RuntimeException("not supported: " + newDataKind.mimeType);
- }
-
final ArrayList<ValuesDelta> mimeEntries = oldState.getMimeEntries(newDataKind.mimeType);
if (mimeEntries == null || mimeEntries.isEmpty()) {
return;
diff --git a/src/com/android/contacts/model/ExternalAccountType.java b/src/com/android/contacts/model/ExternalAccountType.java
index 9718ce2..ca064c7 100644
--- a/src/com/android/contacts/model/ExternalAccountType.java
+++ b/src/com/android/contacts/model/ExternalAccountType.java
@@ -49,6 +49,7 @@
private static final String TAG_CONTACTS_SOURCE_LEGACY = "ContactsSource";
private static final String TAG_CONTACTS_ACCOUNT_TYPE = "ContactsAccountType";
private static final String TAG_CONTACTS_DATA_KIND = "ContactsDataKind";
+ private static final String TAG_EDIT_SCHEMA = "EditSchema";
private static final String ATTR_EDIT_CONTACT_ACTIVITY = "editContactActivity";
private static final String ATTR_CREATE_CONTACT_ACTIVITY = "createContactActivity";
@@ -84,6 +85,7 @@
private String mAccountTypeIconAttribute;
private boolean mInitSuccessful;
private boolean mHasContactsMetadata;
+ private boolean mHasEditSchema;
public ExternalAccountType(Context context, String resPackageName, boolean isExtension) {
this.mIsExtension = isExtension;
@@ -125,11 +127,6 @@
}
@Override
- public boolean isExternal() {
- return true;
- }
-
- @Override
public boolean isExtension() {
return mIsExtension;
}
@@ -144,7 +141,7 @@
@Override
public boolean areContactsWritable() {
- return getCreateContactActivityClassName() != null;
+ return mHasEditSchema;
}
/**
@@ -269,44 +266,45 @@
while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
&& type != XmlPullParser.END_DOCUMENT) {
String tag = parser.getName();
- if (type == XmlPullParser.END_TAG || !TAG_CONTACTS_DATA_KIND.equals(tag)) {
- continue;
+ if (TAG_EDIT_SCHEMA.equals(tag)) {
+ parseEditSchema(context, parser);
+ } else if (TAG_CONTACTS_DATA_KIND.equals(tag)) {
+ final TypedArray a = context.obtainStyledAttributes(attrs,
+ android.R.styleable.ContactsDataKind);
+ final DataKind kind = new DataKind();
+
+ kind.mimeType = a
+ .getString(com.android.internal.R.styleable.ContactsDataKind_mimeType);
+ kind.iconRes = a.getResourceId(
+ com.android.internal.R.styleable.ContactsDataKind_icon, -1);
+
+ final String summaryColumn = a.getString(
+ com.android.internal.R.styleable.ContactsDataKind_summaryColumn);
+ if (summaryColumn != null) {
+ // Inflate a specific column as summary when requested
+ kind.actionHeader = new SimpleInflater(summaryColumn);
+ }
+
+ final String detailColumn = a.getString(
+ com.android.internal.R.styleable.ContactsDataKind_detailColumn);
+ final boolean detailSocialSummary = a.getBoolean(
+ com.android.internal.R.styleable.ContactsDataKind_detailSocialSummary,
+ false);
+
+ if (detailSocialSummary) {
+ // Inflate social summary when requested
+ kind.actionBodySocial = true;
+ }
+
+ if (detailColumn != null) {
+ // Inflate specific column as summary
+ kind.actionBody = new SimpleInflater(detailColumn);
+ }
+
+ a.recycle();
+
+ addKind(kind);
}
-
- final TypedArray a = context.obtainStyledAttributes(attrs,
- android.R.styleable.ContactsDataKind);
- final DataKind kind = new DataKind();
-
- kind.mimeType = a
- .getString(com.android.internal.R.styleable.ContactsDataKind_mimeType);
- kind.iconRes = a.getResourceId(
- com.android.internal.R.styleable.ContactsDataKind_icon, -1);
-
- final String summaryColumn = a
- .getString(com.android.internal.R.styleable.ContactsDataKind_summaryColumn);
- if (summaryColumn != null) {
- // Inflate a specific column as summary when requested
- kind.actionHeader = new FallbackAccountType.SimpleInflater(summaryColumn);
- }
-
- final String detailColumn = a
- .getString(com.android.internal.R.styleable.ContactsDataKind_detailColumn);
- final boolean detailSocialSummary = a.getBoolean(
- com.android.internal.R.styleable.ContactsDataKind_detailSocialSummary,
- false);
-
- if (detailSocialSummary) {
- // Inflate social summary when requested
- kind.actionBodySocial = true;
- }
-
- if (detailColumn != null) {
- // Inflate specific column as summary
- kind.actionBody = new FallbackAccountType.SimpleInflater(detailColumn);
- }
-
- addKind(kind);
- a.recycle();
}
} catch (XmlPullParserException e) {
throw new IllegalStateException("Problem reading XML", e);
@@ -315,6 +313,36 @@
}
}
+ /**
+ * Has to be started while the parser is on the EditSchema tag. Will finish on the end tag
+ */
+ private void parseEditSchema(Context context, XmlPullParser parser)
+ throws XmlPullParserException, IOException {
+ // Loop until we left this tag
+ final int startingDepth = parser.getDepth();
+ int type;
+ do {
+ type = parser.next();
+ } while (!(parser.getDepth() == startingDepth && type == XmlPullParser.END_TAG));
+
+ // Just add all defaults for now
+ addDataKindStructuredName(context);
+ addDataKindDisplayName(context);
+ addDataKindPhoneticName(context);
+ addDataKindNickname(context);
+ addDataKindPhone(context);
+ addDataKindEmail(context);
+ addDataKindStructuredPostal(context);
+ addDataKindIm(context);
+ addDataKindOrganization(context);
+ addDataKindPhoto(context);
+ addDataKindNote(context);
+ addDataKindWebsite(context);
+ addDataKindSipAddress(context);
+
+ mHasEditSchema = true;
+ }
+
@Override
public int getHeaderColor(Context context) {
return 0xff6d86b4;