Restrict fields supported by SimAccountType

Test:
Manual test
* Create new contact using FAB
* Select SIM account
* Verify that only name and phone number are editable
* flip to landscape
* verify that name and phone number are still editable

Bug 30868406
Change-Id: Ifd067db57f64208a71191000bdee6fab1aa99767
diff --git a/res/layout-land/compact_contact_editor_fragment.xml b/res/layout-land/compact_contact_editor_fragment.xml
index 4f333bd..7855fcb 100644
--- a/res/layout-land/compact_contact_editor_fragment.xml
+++ b/res/layout-land/compact_contact_editor_fragment.xml
@@ -19,7 +19,7 @@
         xmlns:android="http://schemas.android.com/apk/res/android"
         android:id="@+id/raw_contacts_editor_view"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
+        android:layout_height="match_parent"
         android:background="@color/background_primary"
         android:orientation="horizontal"
         android:visibility="invisible">
@@ -39,14 +39,16 @@
             android:fadingEdge="none"
             android:fillViewport="true">
 
-        <LinearLayout android:layout_width="match_parent"
-                android:layout_height="match_parent"
+        <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
                 android:orientation="vertical">
 
             <include layout="@layout/editor_all_rawcontacts_accounts_selector" />
+
             <include layout="@layout/editor_account_header" />
 
-            <include layout="@layout/compact_contact_editor_fields"/>
+            <include layout="@layout/compact_contact_editor_fields" />
 
         </LinearLayout>
 
diff --git a/src/com/android/contacts/common/model/RawContactModifier.java b/src/com/android/contacts/common/model/RawContactModifier.java
index fd028e3..3cd200c 100644
--- a/src/com/android/contacts/common/model/RawContactModifier.java
+++ b/src/com/android/contacts/common/model/RawContactModifier.java
@@ -217,7 +217,7 @@
      * displayed for users to pick.
      */
     public static boolean hasEditTypes(DataKind kind) {
-        return kind.typeList != null && kind.typeList.size() > 0;
+        return kind != null && kind.typeList != null && kind.typeList.size() > 0;
     }
 
     /**
diff --git a/src/com/android/contacts/common/model/account/SimAccountType.java b/src/com/android/contacts/common/model/account/SimAccountType.java
index a2219cc..5d2e52d 100644
--- a/src/com/android/contacts/common/model/account/SimAccountType.java
+++ b/src/com/android/contacts/common/model/account/SimAccountType.java
@@ -15,28 +15,56 @@
  */
 package com.android.contacts.common.model.account;
 
+import android.accounts.AuthenticatorDescription;
 import android.content.Context;
-import android.graphics.drawable.Drawable;
 
 import com.android.contacts.R;
+import com.android.contacts.common.model.dataitem.DataKind;
+
+import java.util.Collections;
 
 /**
  * Account type for SIM card contacts
- *
- * TODO: Right now this is the same as FallbackAccountType with a different icon and label.
- * Instead it should setup it's own DataKinds that are known to work on SIM card.
  */
-public class SimAccountType extends FallbackAccountType {
+public class SimAccountType extends BaseAccountType {
 
     public SimAccountType(Context context) {
-        super(context);
         this.titleRes = R.string.account_sim;
         this.iconRes = R.drawable.ic_sim_card_tinted_24dp;
 
+        try {
+            addDataKindDisplayName(context);
+            // SIM cards probably don't natively support full structured name data (separate
+            // first and last names) but restricting to just a single field in
+            // StructuredNameEditorView will require more significant changes.
+            addDataKindStructuredName(context);
+
+            final DataKind phoneKind = addDataKindPhone(context);
+            phoneKind.typeOverallMax = 1;
+            // SIM card contacts don't necessarily support separate types (based on data exposed
+            // in Samsung and LG Contacts Apps.
+            phoneKind.typeList = Collections.emptyList();
+
+            mIsInitialized = true;
+        } catch (DefinitionException e) {
+            // Just fail fast. Because we're explicitly adding the fields in this class this
+            // exception should only happen in case of a bug.
+            throw new IllegalStateException(e);
+        }
+    }
+
+    @Override
+    public boolean areContactsWritable() {
+        return true;
     }
 
     @Override
     public boolean isGroupMembershipEditable() {
         return false;
     }
+
+    @Override
+    public void initializeFieldsFromAuthenticator(AuthenticatorDescription authenticator) {
+        // Do nothing. We want to use our local icon and title
+    }
 }
diff --git a/src/com/android/contacts/editor/CompactKindSectionView.java b/src/com/android/contacts/editor/CompactKindSectionView.java
index 7e5ff11..f550c6d 100644
--- a/src/com/android/contacts/editor/CompactKindSectionView.java
+++ b/src/com/android/contacts/editor/CompactKindSectionView.java
@@ -382,6 +382,11 @@
         mEditors.addView(nameView);
 
         // Phonetic name
+        final DataKind phoneticNameKind = accountType
+                .getKindForMimetype(DataKind.PSEUDO_MIME_TYPE_PHONETIC_NAME);
+        // The account type doesn't support phonetic name.
+        if (phoneticNameKind == null) return;
+
         final PhoneticNameEditorView phoneticNameView = (PhoneticNameEditorView) mLayoutInflater
                 .inflate(R.layout.phonetic_name_editor_view, mEditors, /* attachToRoot =*/ false);
         phoneticNameView.setEditorListener(new OtherNameKindEditorListener());
diff --git a/src/com/android/contacts/editor/CompactRawContactsEditorView.java b/src/com/android/contacts/editor/CompactRawContactsEditorView.java
index 884cc51..f465167 100644
--- a/src/com/android/contacts/editor/CompactRawContactsEditorView.java
+++ b/src/com/android/contacts/editor/CompactRawContactsEditorView.java
@@ -31,6 +31,7 @@
 import com.android.contacts.common.util.MaterialColorMapUtils;
 import com.android.contacts.util.UiClosables;
 
+import android.animation.LayoutTransition;
 import android.content.ContentUris;
 import android.content.Context;
 import android.database.Cursor;
@@ -616,7 +617,13 @@
             MaterialColorMapUtils.MaterialPalette materialPalette, ViewIdGenerator viewIdGenerator,
             long photoId, boolean hasNewContact, boolean isUserProfile,
             AccountWithDataSet primaryAccount) {
+        // Enable layout animations for new contacts. This looks nicer when switching to and from
+        // an account that doesn't support profile photos (e.g. SIM accounts).
+        if (hasNewContact && getLayoutTransition() == null) {
+            setLayoutTransition(new LayoutTransition());
+        }
         mKindSectionDataMap.clear();
+        mKindSectionViewsMap.clear();
         mKindSectionViews.removeAllViews();
         mMoreFields.setVisibility(View.VISIBLE);
 
@@ -645,9 +652,11 @@
             return;
         }
 
+
         // Get the primary name kind section data
-        mPrimaryNameKindSectionData = mKindSectionDataMap.get(StructuredName.CONTENT_ITEM_TYPE)
-                .getEntryToWrite(/* id =*/ -1, mPrimaryAccount, mIsUserProfile);
+        mPrimaryNameKindSectionData =
+                getOrCreateKindSectionDataList(StructuredName.CONTENT_ITEM_TYPE)
+                        .getEntryToWrite(/* id =*/ -1, mPrimaryAccount, mIsUserProfile);
         if (mPrimaryNameKindSectionData != null) {
             // Ensure that a structured name and photo exists
             final RawContactDelta rawContactDelta =
@@ -667,6 +676,8 @@
         addPhotoView();
         addKindSectionViews();
 
+        mMoreFields.setVisibility(hasMoreFields() ? View.VISIBLE : View.GONE);
+
         if (mIsExpanded) showAllFields();
 
         if (mListener != null) mListener.onEditorsBound();
@@ -913,13 +924,15 @@
     private void addPhotoView() {
         // Get the kind section data and values delta that we will display in the photo view
         final KindSectionDataList kindSectionDataList =
-                mKindSectionDataMap.get(Photo.CONTENT_ITEM_TYPE);
+                getOrCreateKindSectionDataList(Photo.CONTENT_ITEM_TYPE);
         final Pair<KindSectionData,ValuesDelta> photoToDisplay =
                 kindSectionDataList.getEntryToDisplay(mPhotoId);
         if (photoToDisplay == null) {
             wlog("photo: no kind section data parsed");
             mPhotoView.setVisibility(View.GONE);
             return;
+        } else {
+            mPhotoView.setVisibility(View.VISIBLE);
         }
 
         // Set the photo view
@@ -1067,6 +1080,17 @@
         mMoreFields.setVisibility(View.GONE);
     }
 
+    private boolean hasMoreFields() {
+        for (List<CompactKindSectionView> sections : mKindSectionViewsMap.values()) {
+            for (CompactKindSectionView section : sections) {
+                if (section.getVisibility() != View.VISIBLE) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
     private static void vlog(String message) {
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
             Log.v(TAG, message);