Merge "Import translations. DO NOT MERGE ANYWHERE" into main
diff --git a/res/layout/contact_editor_fields.xml b/res/layout/contact_editor_fields.xml
index b9bda16..dd4e499 100644
--- a/res/layout/contact_editor_fields.xml
+++ b/res/layout/contact_editor_fields.xml
@@ -48,4 +48,29 @@
 
     </LinearLayout>
 
+    <LinearLayout
+        android:id="@+id/legacy_fields_container"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="8dp"
+        android:orientation="vertical"
+        android:visibility="gone">
+        <TextView
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:textAllCaps="true"
+            android:layout_marginStart="16dp"
+            android:textAppearance="?attr/textAppearanceOverline"
+            android:singleLine="true"
+            android:layout_marginBottom="24dp"
+            android:textSize="11sp"
+            android:text="@string/editor_uneditable_section_title" />
+
+        <LinearLayout
+            android:id="@+id/legacy_section_views"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical" />
+    </LinearLayout>
+
 </merge>
\ No newline at end of file
diff --git a/res/values/ids.xml b/res/values/ids.xml
index a4b8b4b..f22eaba 100644
--- a/res/values/ids.xml
+++ b/res/values/ids.xml
@@ -44,6 +44,9 @@
     <!-- An ID to be used for contents of a custom dialog so that its state be preserved -->
     <item type="id" name="custom_dialog_content" />
 
+    <!-- An ID to be used for tagging text for copy in legacy fields. -->
+    <item name="text_to_copy" type="id"/>
+
     <!-- Menu group ID for settings and help & feedback  -->
     <item type="id" name="nav_misc" />
 
diff --git a/res/values/strings.xml b/res/values/strings.xml
index b608e12..fc24b10 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -425,6 +425,9 @@
     <!-- The button to add an label field to a contact in the Raw Contact Editor [CHAR LIMIT=15] -->
     <string name="group_edit_field_hint_text">Label</string>
 
+    <!-- Editor section title to show below shown editor fields are not editable. Users are only allowed to delete them. [CHAR LIMIT=NONE] -->
+    <string name="editor_uneditable_section_title">Can’t update this info</string>
+
     <!-- Content description for a cancel button. [CHAR LIMIT=NONE] -->
     <string name="cancel_button_content_description">Cancel</string>
 
diff --git a/src/com/android/contacts/editor/Editor.java b/src/com/android/contacts/editor/Editor.java
index c02816a..6ab06bd 100644
--- a/src/com/android/contacts/editor/Editor.java
+++ b/src/com/android/contacts/editor/Editor.java
@@ -114,4 +114,10 @@
      */
     public void editNewlyAddedField();
 
+    /**
+     * Marks the Editor field as a legacy field. Legacy fields are deprecated MIME types
+     * which are not fully supported in the editor.
+     * Adding or editing legacy field are not supported.
+     */
+    void setLegacyField(boolean isLegacyField);
 }
diff --git a/src/com/android/contacts/editor/EditorUiUtils.java b/src/com/android/contacts/editor/EditorUiUtils.java
index 35f107e..3dac5bb 100644
--- a/src/com/android/contacts/editor/EditorUiUtils.java
+++ b/src/com/android/contacts/editor/EditorUiUtils.java
@@ -57,6 +57,7 @@
 import com.android.contacts.util.MaterialColorMapUtils.MaterialPalette;
 import com.android.contacts.widget.QuickContactImageView;
 
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Maps;
 
 import java.io.FileNotFoundException;
@@ -95,6 +96,9 @@
         mimetypeLayoutMap.put(Event.CONTENT_ITEM_TYPE, R.layout.event_field_editor_view);
     }
 
+    public static final ImmutableList<String> LEGACY_MIME_TYPE =
+        ImmutableList.of(Im.CONTENT_ITEM_TYPE, SipAddress.CONTENT_ITEM_TYPE);
+
     /**
      * Fetches a layout for a given mimetype.
      *
diff --git a/src/com/android/contacts/editor/KindSectionView.java b/src/com/android/contacts/editor/KindSectionView.java
index 5d49064..28eeaf2 100644
--- a/src/com/android/contacts/editor/KindSectionView.java
+++ b/src/com/android/contacts/editor/KindSectionView.java
@@ -48,6 +48,13 @@
  */
 public class KindSectionView extends LinearLayout {
 
+    /** Callbacks for hosts of {@link KindSectionView}s. */
+    public interface Listener {
+
+        /** Invoked when all fields in a legacy {@link KindSectionView} are removed. */
+        void onEmptyLegacyKindSectionView();
+    }
+
     /**
      * Marks a name as super primary when it is changed.
      *
@@ -58,21 +65,21 @@
 
         private final ValuesDelta mValuesDelta;
         private final long mRawContactId;
-        private final RawContactEditorView.Listener mListener;
+        private final RawContactEditorView.Listener mEditorViewListener;
 
         public StructuredNameEditorListener(ValuesDelta valuesDelta, long rawContactId,
-                RawContactEditorView.Listener listener) {
+            RawContactEditorView.Listener editorViewListener) {
             mValuesDelta = valuesDelta;
             mRawContactId = rawContactId;
-            mListener = listener;
+            mEditorViewListener = editorViewListener;
         }
 
         @Override
         public void onRequest(int request) {
             if (request == Editor.EditorListener.FIELD_CHANGED) {
                 mValuesDelta.setSuperPrimary(true);
-                if (mListener != null) {
-                    mListener.onNameFieldChanged(mRawContactId, mValuesDelta);
+                if (mEditorViewListener != null) {
+                    mEditorViewListener.onNameFieldChanged(mRawContactId, mValuesDelta);
                 }
             } else if (request == Editor.EditorListener.FIELD_TURNED_EMPTY) {
                 mValuesDelta.setSuperPrimary(false);
@@ -119,6 +126,11 @@
 
         @Override
         public void onDeleteRequested(Editor editor) {
+            if (mIsLegacyField && mEditors.getChildCount() == 1) {
+                editor.deleteEditor();
+                mListener.onEmptyLegacyKindSectionView();
+                return;
+            }
             if (mShowOneEmptyEditor && mEditors.getChildCount() == 1) {
                 // If there is only 1 editor in the section, then don't allow the user to
                 // delete it.  Just clear the fields in the editor.
@@ -152,11 +164,13 @@
 
     private KindSectionData mKindSectionData;
     private ViewIdGenerator mViewIdGenerator;
-    private RawContactEditorView.Listener mListener;
+    private RawContactEditorView.Listener mEditorViewListener;
+    private Listener mListener;
 
     private boolean mIsUserProfile;
     private boolean mShowOneEmptyEditor = false;
     private boolean mHideIfEmpty = true;
+    private boolean mIsLegacyField = false;
 
     private LayoutInflater mLayoutInflater;
     private ViewGroup mEditors;
@@ -227,6 +241,13 @@
     }
 
     /**
+     * When {@code isLegacyField} is true, prevent users from editing the field.
+     */
+    void setLegacyField(boolean isLegacyField) {
+        this.mIsLegacyField = isLegacyField;
+    }
+
+    /**
      * Whether this is a name kind section view and all name fields (structured, phonetic,
      * and nicknames) are empty.
      */
@@ -277,10 +298,14 @@
      * Empty name editors are never added and at least one structured name editor is always
      * displayed, even if it is empty.
      */
-    public void setState(KindSectionData kindSectionData,
-            ViewIdGenerator viewIdGenerator, RawContactEditorView.Listener listener) {
+    public void setState(
+        KindSectionData kindSectionData,
+        ViewIdGenerator viewIdGenerator,
+        RawContactEditorView.Listener editorViewListener,
+        Listener listener) {
         mKindSectionData = kindSectionData;
         mViewIdGenerator = viewIdGenerator;
+        mEditorViewListener = editorViewListener;
         mListener = listener;
 
         // Set the icon using the DataKind
@@ -292,6 +317,9 @@
                 mIcon.setContentDescription(dataKind.titleRes == -1 || dataKind.titleRes == 0
                         ? "" : getResources().getString(dataKind.titleRes));
             }
+            if (mIsLegacyField) {
+                mIcon.setEnabled(false);
+            }
         }
 
         rebuildFromState();
@@ -359,7 +387,7 @@
         if (!mIsUserProfile) {
             // Don't set super primary for the me contact
             nameView.setEditorListener(new StructuredNameEditorListener(
-                    nameValuesDelta, rawContactDelta.getRawContactId(), mListener));
+                    nameValuesDelta, rawContactDelta.getRawContactId(), mEditorViewListener));
         }
         nameView.setDeletable(false);
         nameView.setValues(accountType.getKindForMimetype(DataKind.PSEUDO_MIME_TYPE_NAME),
@@ -414,6 +442,7 @@
         view.setEnabled(isEnabled());
         if (view instanceof Editor) {
             final Editor editor = (Editor) view;
+            editor.setLegacyField(mIsLegacyField);
             editor.setDeletable(true);
             editor.setEditorListener(editorListener);
             editor.setValues(dataKind, valuesDelta, rawContactDelta, !dataKind.editable,
@@ -593,4 +622,8 @@
         }
         return emptyEditors;
     }
+
+    public boolean isEditorEmpty() {
+        return mKindSectionData.getVisibleValuesDeltas().isEmpty();
+    }
 }
diff --git a/src/com/android/contacts/editor/LabeledEditorView.java b/src/com/android/contacts/editor/LabeledEditorView.java
index df4c5f9..3df3222 100644
--- a/src/com/android/contacts/editor/LabeledEditorView.java
+++ b/src/com/android/contacts/editor/LabeledEditorView.java
@@ -81,6 +81,8 @@
     private boolean mIsDeletable = true;
     private boolean mIsAttachedToWindow;
 
+    protected boolean mIsLegacyField;
+
     private EditType mType;
 
     private ViewIdGenerator mViewIdGenerator;
@@ -264,8 +266,8 @@
     @Override
     public void setEnabled(boolean enabled) {
         super.setEnabled(enabled);
-        mLabel.setEnabled(!mReadOnly && enabled);
-        mDelete.setEnabled(!mReadOnly && enabled);
+        mLabel.setEnabled(!mReadOnly && enabled && !mIsLegacyField);
+        mDelete.setEnabled((!mReadOnly && enabled) || mIsLegacyField);
     }
 
     public Spinner getLabel() {
@@ -342,6 +344,10 @@
         return "";
     }
 
+    public void setLegacyField(boolean mIsLegacyField) {
+        this.mIsLegacyField = mIsLegacyField;
+    }
+
     protected void saveValue(String column, String value) {
         mEntry.put(column, value);
     }
diff --git a/src/com/android/contacts/editor/RawContactEditorView.java b/src/com/android/contacts/editor/RawContactEditorView.java
index 19da5bc..755800a 100644
--- a/src/com/android/contacts/editor/RawContactEditorView.java
+++ b/src/com/android/contacts/editor/RawContactEditorView.java
@@ -50,6 +50,7 @@
 import android.widget.ListPopupWindow;
 import android.widget.TextView;
 
+import com.android.contacts.editor.KindSectionView;
 import com.android.contacts.GeoUtil;
 import com.android.contacts.R;
 import com.android.contacts.compat.PhoneNumberUtilsCompat;
@@ -80,7 +81,8 @@
 /**
  * View to display information from multiple {@link RawContactDelta}s grouped together.
  */
-public class RawContactEditorView extends LinearLayout implements View.OnClickListener {
+public class RawContactEditorView extends LinearLayout implements View.OnClickListener,
+    KindSectionView.Listener {
 
     static final String TAG = "RawContactEditorView";
 
@@ -218,6 +220,8 @@
 
     private PhotoEditorView mPhotoView;
     private ViewGroup mKindSectionViews;
+    private LinearLayout mLegacySectionLinearLayout;
+    private ViewGroup mLegacyKindSectionViews;
     private Map<String, KindSectionView> mKindSectionViewMap = new HashMap<>();
     private View mMoreFields;
 
@@ -259,6 +263,8 @@
 
         mPhotoView = (PhotoEditorView) findViewById(R.id.photo_editor);
         mKindSectionViews = (LinearLayout) findViewById(R.id.kind_section_views);
+        mLegacySectionLinearLayout = (LinearLayout) findViewById(R.id.legacy_fields_container);
+        mLegacyKindSectionViews = (LinearLayout) findViewById(R.id.legacy_section_views);
         mMoreFields = findViewById(R.id.more_fields);
         mMoreFields.setOnClickListener(this);
     }
@@ -277,6 +283,10 @@
         for (int i = 0; i < childCount; i++) {
             mKindSectionViews.getChildAt(i).setEnabled(enabled);
         }
+        final int legacyChildCount = mLegacyKindSectionViews.getChildCount();
+        for (int i = 0; i < legacyChildCount; i++) {
+            mLegacyKindSectionViews.getChildAt(i).setEnabled(false);
+        }
     }
 
     @Override
@@ -447,6 +457,8 @@
 
         mKindSectionViewMap.clear();
         mKindSectionViews.removeAllViews();
+        mLegacySectionLinearLayout.setVisibility(View.GONE);
+        mLegacyKindSectionViews.removeAllViews();
         mMoreFields.setVisibility(View.VISIBLE);
 
         mMaterialPalette = materialPalette;
@@ -531,7 +543,7 @@
         addKindSectionViews();
 
         mMoreFields.setVisibility(hasMoreFields() ? View.VISIBLE : View.GONE);
-
+        addLegacyKindSectionViews();
         if (mIsExpanded) showAllFields();
     }
 
@@ -874,6 +886,9 @@
         int i = -1;
 
         for (String mimeType : mSortedMimetypes) {
+            if(EditorUiUtils.LEGACY_MIME_TYPE.contains(mimeType)) {
+                continue;
+            }
             i++;
             // Ignore mime types that we've already handled
             if (Photo.CONTENT_ITEM_TYPE.equals(mimeType)) {
@@ -910,7 +925,7 @@
         // they will be the only types you add new values to initially for new contacts
         kindSectionView.setShowOneEmptyEditor(true);
 
-        kindSectionView.setState(kindSectionData, mViewIdGenerator, mListener);
+        kindSectionView.setState(kindSectionData, mViewIdGenerator, mListener, this);
 
         return kindSectionView;
     }
@@ -938,6 +953,55 @@
         return false;
     }
 
+    private void addLegacyKindSectionViews() {
+        boolean hasLegacyData = false;
+        for (String mimeType : EditorUiUtils.LEGACY_MIME_TYPE) {
+
+            KindSectionData kindSectionData = mKindSectionDataMap.get(mimeType);
+            if (kindSectionData != null && !kindSectionData.getVisibleValuesDeltas().isEmpty()) {
+                hasLegacyData = true;
+                KindSectionView kindSectionView =
+                    inflateLegacyKindSectionView(mKindSectionViews, kindSectionData);
+                mLegacyKindSectionViews.addView(kindSectionView);
+
+                // Keep a pointer to the KindSectionView for each mimeType
+                mKindSectionViewMap.put(mimeType, kindSectionView);
+            }
+        }
+
+        if (hasLegacyData) {
+            mLegacySectionLinearLayout.setVisibility(View.VISIBLE);
+        }
+    }
+
+    private KindSectionView inflateLegacyKindSectionView(
+        ViewGroup viewGroup, KindSectionData kindSectionData) {
+        KindSectionView kindSectionView =
+            (KindSectionView)
+                mLayoutInflater.inflate(
+                    R.layout.item_kind_section, viewGroup, /* attachToRoot =*/ false);
+        kindSectionView.setLegacyField(true);
+
+        kindSectionView.setState(kindSectionData, mViewIdGenerator, mListener, this);
+
+        return kindSectionView;
+    }
+
+    @Override
+    public void onEmptyLegacyKindSectionView() {
+        for (int i = mLegacyKindSectionViews.getChildCount() - 1; i >= 0; i--) {
+            View childView = mLegacyKindSectionViews.getChildAt(i);
+            if (childView instanceof KindSectionView
+                && ((KindSectionView) childView).isEditorEmpty()) {
+                mLegacyKindSectionViews.removeViewAt(i);
+            }
+        }
+
+        if (mLegacyKindSectionViews.getChildCount() == 0) {
+            mLegacySectionLinearLayout.setVisibility(View.GONE);
+        }
+    }
+
     private static void wlog(String message) {
         if (Log.isLoggable(TAG, Log.WARN)) {
             Log.w(TAG, message);
diff --git a/src/com/android/contacts/editor/TextFieldsEditorView.java b/src/com/android/contacts/editor/TextFieldsEditorView.java
index 28fe87f..d7f9545 100644
--- a/src/com/android/contacts/editor/TextFieldsEditorView.java
+++ b/src/com/android/contacts/editor/TextFieldsEditorView.java
@@ -22,6 +22,8 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.provider.ContactsContract;
+import android.provider.ContactsContract.CommonDataKinds.Im;
+import android.provider.ContactsContract.CommonDataKinds.SipAddress;
 import android.provider.ContactsContract.CommonDataKinds.StructuredName;
 import android.text.Editable;
 import android.text.InputType;
@@ -49,6 +51,7 @@
 import com.android.contacts.model.account.AccountType.EditField;
 import com.android.contacts.model.dataitem.DataKind;
 import com.android.contacts.util.PhoneNumberFormatter;
+import com.android.contacts.ClipboardUtils;
 
 /**
  * Simple editor that handles labels and any {@link EditField} defined for the
@@ -57,7 +60,6 @@
  */
 public class TextFieldsEditorView extends LabeledEditorView {
     private static final String TAG = TextFieldsEditorView.class.getSimpleName();
-
     private EditText[] mFieldEditTexts = null;
     private ViewGroup mFields = null;
     protected View mExpansionViewContainer;
@@ -75,6 +77,12 @@
     private String mFixedDisplayName = "";
     private boolean needInputInitialize;
 
+    private final OnLongClickListener mOnLongClickListener =
+        v -> {
+            ClipboardUtils.copyText(
+                getContext(), /* label= */ null, (CharSequence) v.getTag(R.id.text_to_copy), true);
+            return true;
+        };
 
     public TextFieldsEditorView(Context context) {
         super(context);
@@ -164,7 +172,15 @@
 
         if (mFieldEditTexts != null) {
             for (int index = 0; index < mFieldEditTexts.length; index++) {
-                mFieldEditTexts[index].setEnabled(!isReadOnly() && enabled);
+                mFieldEditTexts[index].setEnabled(!isReadOnly() && enabled && !mIsLegacyField);
+                if (mIsLegacyField) {
+                    mFieldEditTexts[index].setFocusable(false);
+                    mFieldEditTexts[index].setClickable(false);
+                    mFieldEditTexts[index].setLongClickable(false);
+                }
+            }
+            if (mIsLegacyField && mFieldEditTexts.length > 0) {
+                setOnLongClickListenerOnContainer();
             }
         }
         if (mExpansionView != null) {
@@ -172,6 +188,18 @@
         }
     }
 
+    /**
+     * Attaches OnLongClickLister to fields LinearLayout that allow user copy the EditText text on
+     * long press.
+     */
+    private void setOnLongClickListenerOnContainer() {
+      mFields.setFocusable(true);
+      mFields.setLongClickable(true);
+      // Current legacy mimetypes support exactly 1 field
+      mFields.setTag(R.id.text_to_copy, mFieldEditTexts[0].getText().toString());
+      mFields.setOnLongClickListener(mOnLongClickListener);
+    }
+
     private OnFocusChangeListener mTextFocusChangeListener = new OnFocusChangeListener() {
         @Override
         public void onFocusChange(View v, boolean hasFocus) {