Always show email and phone fields

* This fixes showing an almost blank screen when
  writing the "me" profile also when adding a new contact.
* Also fixed a bug when writing the "me" profile --
  we weren't calling the RawContact.setAccountToLocal
  in createNewRawContactDelta in the base editor fragment.

Bug 19124091

Change-Id: I93422047796189b4df060bfa39aa3c84ce47fa25
diff --git a/src/com/android/contacts/editor/CompactContactEditorFragment.java b/src/com/android/contacts/editor/CompactContactEditorFragment.java
index 89c7521..8294365 100644
--- a/src/com/android/contacts/editor/CompactContactEditorFragment.java
+++ b/src/com/android/contacts/editor/CompactContactEditorFragment.java
@@ -95,9 +95,6 @@
 
     @Override
     protected boolean doSaveAction(int saveMode) {
-        // Store account as default account, only if this is a new contact
-        saveDefaultAccountIfNecessary();
-
         // Save contact
         final Intent intent = ContactSaveService.createSaveContactIntent(mContext, mState,
                 SAVE_MODE_EXTRA_KEY, saveMode, isEditingUserProfile(),
diff --git a/src/com/android/contacts/editor/CompactRawContactsEditorView.java b/src/com/android/contacts/editor/CompactRawContactsEditorView.java
index cbe2ee4..d8dea60 100644
--- a/src/com/android/contacts/editor/CompactRawContactsEditorView.java
+++ b/src/com/android/contacts/editor/CompactRawContactsEditorView.java
@@ -20,6 +20,7 @@
 import com.android.contacts.common.model.AccountTypeManager;
 import com.android.contacts.common.model.RawContactDelta;
 import com.android.contacts.common.model.RawContactDeltaList;
+import com.android.contacts.common.model.RawContactModifier;
 import com.android.contacts.common.model.ValuesDelta;
 import com.android.contacts.common.model.account.AccountType;
 import com.android.contacts.common.model.account.AccountType.EditField;
@@ -119,20 +120,30 @@
         }
 
         mViewIdGenerator = viewIdGenerator;
-
         setId(mViewIdGenerator.getId(rawContactDeltas.get(0), /* dataKind =*/ null,
                 /* valuesDelta =*/ null, ViewIdGenerator.NO_VIEW_INDEX));
 
-        addEditorViews(rawContactDeltas);
-        removeExtraEmptyStructuredNames();
+        addEditorViews(rawContactDeltas, viewIdGenerator);
+        removeExtraEmptyTextFields(mNames);
+        removeExtraEmptyTextFields(mPhoneNumbers);
+        removeExtraEmptyTextFields(mEmails);
     }
 
-    private void addEditorViews(RawContactDeltaList rawContactDeltas) {
+    private void addEditorViews(RawContactDeltaList rawContactDeltas,
+            ViewIdGenerator viewIdGenerator) {
         for (RawContactDelta rawContactDelta : rawContactDeltas) {
             if (!rawContactDelta.isVisible()) {
                 continue;
             }
+            setId(viewIdGenerator.getId(
+                    rawContactDelta, null, null, ViewIdGenerator.NO_VIEW_INDEX));
+
             final AccountType accountType = rawContactDelta.getAccountType(mAccountTypeManager);
+
+            // Make sure we have a StructuredName
+            RawContactModifier.ensureKindExists(
+                    rawContactDelta, accountType, StructuredName.CONTENT_ITEM_TYPE);
+
             for (DataKind dataKind : accountType.getSortedDataKinds()) {
                 if (!dataKind.editable) {
                     continue;
@@ -164,15 +175,11 @@
                                 mNicknames, dataKind, rawContactDelta));
                     }
                 } else if (Phone.CONTENT_ITEM_TYPE.equals(mimeType)) {
-                    if (hasNonEmptyValuesDelta(rawContactDelta, mimeType, dataKind)) {
-                        mPhoneNumbers.addView(inflateKindSectionView(
-                                mPhoneNumbers, dataKind, rawContactDelta));
-                    }
+                    mPhoneNumbers.addView(inflateKindSectionView(
+                            mPhoneNumbers, dataKind, rawContactDelta));
                 } else if (Email.CONTENT_ITEM_TYPE.equals(mimeType)) {
-                    if (hasNonEmptyValuesDelta(rawContactDelta, mimeType, dataKind)) {
-                        mEmails.addView(inflateKindSectionView(
-                                mEmails, dataKind, rawContactDelta));
-                    }
+                    mEmails.addView(inflateKindSectionView(
+                            mEmails, dataKind, rawContactDelta));
                 } else if (hasNonEmptyValuesDelta(rawContactDelta, mimeType, dataKind)) {
                     mOther.addView(inflateKindSectionView(
                             mOther, dataKind, rawContactDelta));
@@ -181,40 +188,48 @@
         }
     }
 
-    private void removeExtraEmptyStructuredNames() {
-        // If there is one (or less) structured names, leave it whether it is empty or not
-        if (mNames.getChildCount() <= 1) {
+    // TODO: avoid inflating extra views and deleting them
+    private void removeExtraEmptyTextFields(ViewGroup viewGroup) {
+        // If there is one (or less) editors, leave it whether it is empty or not
+        if (viewGroup.getChildCount() <= 1) {
             return;
         }
-        // Determine if there are any non-empty names
-        boolean hasAtLeastOneNonEmptyName = false;
-        for (int i = 0; i < mNames.getChildCount(); i++) {
-            final StructuredNameEditorView childView =
-                    (StructuredNameEditorView) mNames.getChildAt(i);
-            if (!childView.isEmpty()) {
-                hasAtLeastOneNonEmptyName = true;
+        // Determine if there are any non-empty editors
+        boolean hasAtLeastOneNonEmptyEditorView = false;
+        for (int i = 0; i < viewGroup.getChildCount(); i++) {
+            if (!isEmptyEditorView(viewGroup.getChildAt(i))) {
+                hasAtLeastOneNonEmptyEditorView = true;
                 break;
             }
         }
-        if (hasAtLeastOneNonEmptyName) {
-            // There is at least one non-empty name, remove all the empty ones
-            for (int i = 0; i < mNames.getChildCount(); i++) {
-                final StructuredNameEditorView childView =
-                        (StructuredNameEditorView) mNames.getChildAt(i);
-                if (childView.isEmpty()) {
-                    childView.setVisibility(View.GONE);
+        if (hasAtLeastOneNonEmptyEditorView) {
+            // There is at least one non-empty editor, remove all the empty ones
+            for (int i = 0; i < viewGroup.getChildCount(); i++) {
+                if (isEmptyEditorView(viewGroup.getChildAt(i))) {
+                    viewGroup.getChildAt(i).setVisibility(View.GONE);
                 }
             }
         } else {
-            // There is no non-empty name, keep the first empty view and remove the rest
-            for (int i = 1; i < mNames.getChildCount(); i++) {
-                final StructuredNameEditorView childView =
-                        (StructuredNameEditorView) mNames.getChildAt(i);
-                childView.setVisibility(View.GONE);
+            // There is no non-empty editor, keep the first empty view and remove the rest
+            for (int i = 1; i < viewGroup.getChildCount(); i++) {
+                viewGroup.getChildAt(i).setVisibility(View.GONE);
             }
         }
     }
 
+    // TODO: remove this after KindSectionView is rewritten
+    private static boolean isEmptyEditorView(View view) {
+        if (view instanceof TextFieldsEditorView) {
+            final TextFieldsEditorView textFieldsEditorView = (TextFieldsEditorView) view;
+            return textFieldsEditorView.isEmpty();
+        }
+        if (view instanceof KindSectionView) {
+            final KindSectionView kindSectionView = (KindSectionView) view;
+            return kindSectionView.hasEmptyEditor();
+        }
+        return false;
+    }
+
     private static boolean hasNonEmptyValuesDelta(RawContactDelta rawContactDelta,
             String mimeType, DataKind dataKind) {
         return !getNonEmptyValuesDeltas(rawContactDelta, mimeType, dataKind).isEmpty();
diff --git a/src/com/android/contacts/editor/ContactEditorBaseFragment.java b/src/com/android/contacts/editor/ContactEditorBaseFragment.java
index 6961c4c..03ac880 100644
--- a/src/com/android/contacts/editor/ContactEditorBaseFragment.java
+++ b/src/com/android/contacts/editor/ContactEditorBaseFragment.java
@@ -876,6 +876,9 @@
 
         setEnabled(false);
 
+        // Store account as default account, only if this is a new contact
+        saveDefaultAccountIfNecessary();
+
         return doSaveAction(saveMode);
     }
 
@@ -1065,14 +1068,56 @@
     protected void setStateForNewContact(AccountWithDataSet account, AccountType accountType,
             RawContactDelta oldState, AccountType oldAccountType) {
         mStatus = Status.EDITING;
-        mState.add(createNewRawContactDelta(mContext, mIntentExtras, account, accountType,
-                mIsUserProfile, oldState, oldAccountType));
+        mState.add(createNewRawContactDelta(account, accountType, oldState, oldAccountType));
         mRequestFocus = true;
         mNewContactDataReady = true;
         bindEditors();
     }
 
     /**
+     * Returns a {@link RawContactDelta} for a new contact suitable for addition into
+     * {@link #mState}.
+     *
+     * If oldState and oldAccountType are specified, the state specified by those parameters
+     * is migrated to the result {@link RawContactDelta}.
+     */
+    private RawContactDelta createNewRawContactDelta(AccountWithDataSet account,
+            AccountType accountType, RawContactDelta oldState, AccountType oldAccountType) {
+        final RawContact rawContact = new RawContact();
+        if (account != null) {
+            rawContact.setAccount(account);
+        } else {
+            rawContact.setAccountToLocal();
+        }
+
+        final RawContactDelta result = new RawContactDelta(
+                ValuesDelta.fromAfter(rawContact.getValues()));
+        if (oldState == null) {
+            // Parse any values from incoming intent
+            RawContactModifier.parseExtras(mContext, accountType, result, mIntentExtras);
+        } else {
+            RawContactModifier.migrateStateForNewContact(
+                    mContext, oldState, result, oldAccountType, accountType);
+        }
+
+        // Ensure we have some default fields (if the account type does not support a field,
+        // ensureKind will not add it, so it is safe to add e.g. Event)
+        RawContactModifier.ensureKindExists(result, accountType, Phone.CONTENT_ITEM_TYPE);
+        RawContactModifier.ensureKindExists(result, accountType, Email.CONTENT_ITEM_TYPE);
+        RawContactModifier.ensureKindExists(result, accountType, Organization.CONTENT_ITEM_TYPE);
+        RawContactModifier.ensureKindExists(result, accountType, Event.CONTENT_ITEM_TYPE);
+        RawContactModifier.ensureKindExists(result, accountType,
+                StructuredPostal.CONTENT_ITEM_TYPE);
+
+        // Set the correct URI for saving the contact as a profile
+        if (mNewLocalProfile) {
+            result.setProfileQueryUri();
+        }
+
+        return result;
+    }
+
+    /**
      * Prepare {@link #mState} for an existing contact.
      */
     protected void setStateForExistingContact(String displayName, boolean isUserProfile,
@@ -1108,6 +1153,21 @@
     }
 
     /**
+     * Returns a {@link RawContactDelta} for a local contact suitable for addition into
+     * {@link #mState}.
+     */
+    private static RawContactDelta createLocalRawContactDelta() {
+        final RawContact rawContact = new RawContact();
+        rawContact.setAccountToLocal();
+
+        final RawContactDelta result = new RawContactDelta(
+                ValuesDelta.fromAfter(rawContact.getValues()));
+        result.setProfileQueryUri();
+
+        return result;
+    }
+
+    /**
      * Sets group metadata on all bound editors.
      */
     abstract protected void setGroupMetaData();
@@ -1215,7 +1275,7 @@
                 if (saveSucceeded && contactLookupUri != null) {
                     final Uri lookupUri = maybeConvertToLegacyLookupUri(
                             mContext, contactLookupUri, mLookupUri);
-                    resultIntent = composeQuickContactsIntent(mContext, lookupUri);
+                    resultIntent = composeQuickContactsIntent(lookupUri);
                 } else {
                     resultIntent = null;
                 }
@@ -1480,7 +1540,7 @@
      * Creates the result Intent for the given contactLookupUri that should started after a
      * successful saving a contact.
      */
-    protected static Intent composeQuickContactsIntent(Context context, Uri contactLookupUri) {
+    protected static Intent composeQuickContactsIntent(Uri contactLookupUri) {
         final Intent intent = new Intent(QuickContact.ACTION_QUICK_CONTACT);
         intent.setData(contactLookupUri);
         intent.putExtra(QuickContact.EXTRA_MODE, QuickContactActivity.MODE_FULLY_EXPANDED);
@@ -1488,59 +1548,4 @@
         intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
         return intent;
     }
-
-    /**
-     * Returns a {@link RawContactDelta} for a new contact suitable for addition into
-     * {@link #mState}.
-     *
-     * If oldState and oldAccountType are specified, the state specified by those parameters
-     * is migrated to the result {@link RawContactDelta}.
-     */
-    private static RawContactDelta createNewRawContactDelta(Context context, Bundle intentExtras,
-            AccountWithDataSet account, AccountType accountType, boolean isNewLocalProfile,
-            RawContactDelta oldState, AccountType oldAccountType) {
-        final RawContact rawContact = new RawContact();
-        rawContact.setAccount(account);
-
-        final RawContactDelta result = new RawContactDelta(
-                ValuesDelta.fromAfter(rawContact.getValues()));
-        if (oldState == null) {
-            // Parse any values from incoming intent
-            RawContactModifier.parseExtras(context, accountType, result, intentExtras);
-        } else {
-            RawContactModifier.migrateStateForNewContact(
-                    context, oldState, result, oldAccountType, accountType);
-        }
-
-        // Ensure we have some default fields (if the account type does not support a field,
-        // ensureKind will not add it, so it is safe to add e.g. Event)
-        RawContactModifier.ensureKindExists(result, accountType, Phone.CONTENT_ITEM_TYPE);
-        RawContactModifier.ensureKindExists(result, accountType, Email.CONTENT_ITEM_TYPE);
-        RawContactModifier.ensureKindExists(result, accountType, Organization.CONTENT_ITEM_TYPE);
-        RawContactModifier.ensureKindExists(result, accountType, Event.CONTENT_ITEM_TYPE);
-        RawContactModifier.ensureKindExists(result, accountType,
-                StructuredPostal.CONTENT_ITEM_TYPE);
-
-        // Set the correct URI for saving the contact as a profile
-        if (isNewLocalProfile) {
-            result.setProfileQueryUri();
-        }
-
-        return result;
-    }
-
-    /**
-     * Returns a {@link RawContactDelta} for a local contact suitable for addition into
-     * {@link #mState}.
-     */
-    private static RawContactDelta createLocalRawContactDelta() {
-        final RawContact rawContact = new RawContact();
-        rawContact.setAccountToLocal();
-
-        final RawContactDelta result = new RawContactDelta(
-                ValuesDelta.fromAfter(rawContact.getValues()));
-        result.setProfileQueryUri();
-
-        return result;
-    }
 }
diff --git a/src/com/android/contacts/editor/ContactEditorFragment.java b/src/com/android/contacts/editor/ContactEditorFragment.java
index 236c977..5bc868a 100644
--- a/src/com/android/contacts/editor/ContactEditorFragment.java
+++ b/src/com/android/contacts/editor/ContactEditorFragment.java
@@ -418,9 +418,6 @@
 
     @Override
     protected boolean doSaveAction(int saveMode) {
-        // Store account as default account, only if this is a new contact
-        saveDefaultAccountIfNecessary();
-
         // Save contact
         Intent intent = ContactSaveService.createSaveContactIntent(mContext, mState,
                 SAVE_MODE_EXTRA_KEY, saveMode, isEditingUserProfile(),
diff --git a/src/com/android/contacts/editor/KindSectionView.java b/src/com/android/contacts/editor/KindSectionView.java
index dbcb9d5..5a5a51d 100644
--- a/src/com/android/contacts/editor/KindSectionView.java
+++ b/src/com/android/contacts/editor/KindSectionView.java
@@ -261,6 +261,13 @@
     }
 
     /**
+     * Whether this section has any empty editors.
+     */
+    public boolean hasEmptyEditor() {
+        return !getEmptyEditors().isEmpty();
+    }
+
+    /**
      * Returns a list of empty editor views in this section.
      */
     private List<View> getEmptyEditors() {