Merge "Adding content description for photo overlay."
diff --git a/src/com/android/contacts/detail/ContactDetailFragment.java b/src/com/android/contacts/detail/ContactDetailFragment.java
index c47040d..f836139 100644
--- a/src/com/android/contacts/detail/ContactDetailFragment.java
+++ b/src/com/android/contacts/detail/ContactDetailFragment.java
@@ -999,25 +999,35 @@
             }
         } else {
             // Build an IM Intent
-            String host = im.getCustomProtocol();
-
-            if (protocol != Im.PROTOCOL_CUSTOM) {
-                // Try bringing in a well-known host for specific protocols
-                host = ContactsUtils.lookupProviderNameFromId(protocol);
-            }
-
-            if (!TextUtils.isEmpty(host)) {
-                final String authority = host.toLowerCase();
-                final Uri imUri = new Uri.Builder().scheme(CallUtil.SCHEME_IMTO).authority(
-                        authority).appendPath(data).build();
-                final Intent intent = new Intent(Intent.ACTION_SENDTO, imUri);
-                if (PhoneCapabilityTester.isIntentRegistered(context, intent)) {
-                    entry.intent = intent;
-                }
+            final Intent imIntent = getCustomIMIntent(im, protocol);
+            if (imIntent != null &&
+                    PhoneCapabilityTester.isIntentRegistered(context, imIntent)) {
+                entry.intent = imIntent;
             }
         }
     }
 
+    @VisibleForTesting
+    public static Intent getCustomIMIntent(ImDataItem im, int protocol) {
+        String host = im.getCustomProtocol();
+        final String data = im.getData();
+        if (TextUtils.isEmpty(data)) {
+            return null;
+        }
+        if (protocol != Im.PROTOCOL_CUSTOM) {
+            // Try bringing in a well-known host for specific protocols
+            host = ContactsUtils.lookupProviderNameFromId(protocol);
+        }
+        if (TextUtils.isEmpty(host)) {
+            return null;
+        }
+        final String authority = host.toLowerCase();
+        final Uri imUri = new Uri.Builder().scheme(CallUtil.SCHEME_IMTO).authority(
+                authority).appendPath(data).build();
+        final Intent intent = new Intent(Intent.ACTION_SENDTO, imUri);
+        return intent;
+    }
+
     /**
      * Show a list popup.  Used for "popup-able" entry, such as "More networks".
      */
diff --git a/src/com/android/contacts/editor/ContactEditorFragment.java b/src/com/android/contacts/editor/ContactEditorFragment.java
index 916ae70..da0d91e 100644
--- a/src/com/android/contacts/editor/ContactEditorFragment.java
+++ b/src/com/android/contacts/editor/ContactEditorFragment.java
@@ -67,26 +67,27 @@
 import com.android.contacts.activities.ContactEditorAccountsChangedActivity;
 import com.android.contacts.activities.ContactEditorActivity;
 import com.android.contacts.activities.JoinContactActivity;
-import com.android.contacts.detail.PhotoSelectionHandler;
-import com.android.contacts.editor.AggregationSuggestionEngine.Suggestion;
-import com.android.contacts.editor.Editor.EditorListener;
 import com.android.contacts.common.model.AccountTypeManager;
-import com.android.contacts.model.Contact;
-import com.android.contacts.model.ContactLoader;
-import com.android.contacts.model.RawContact;
-import com.android.contacts.model.RawContactDelta;
 import com.android.contacts.common.model.ValuesDelta;
-import com.android.contacts.model.RawContactDeltaList;
-import com.android.contacts.model.RawContactModifier;
 import com.android.contacts.common.model.account.AccountType;
 import com.android.contacts.common.model.account.AccountWithDataSet;
 import com.android.contacts.common.model.account.GoogleAccountType;
 import com.android.contacts.common.util.AccountsListAdapter;
 import com.android.contacts.common.util.AccountsListAdapter.AccountListFilter;
+import com.android.contacts.detail.PhotoSelectionHandler;
+import com.android.contacts.editor.AggregationSuggestionEngine.Suggestion;
+import com.android.contacts.editor.Editor.EditorListener;
+import com.android.contacts.model.Contact;
+import com.android.contacts.model.ContactLoader;
+import com.android.contacts.model.RawContact;
+import com.android.contacts.model.RawContactDelta;
+import com.android.contacts.model.RawContactDeltaList;
+import com.android.contacts.model.RawContactModifier;
 import com.android.contacts.util.ContactPhotoUtils;
 import com.android.contacts.util.HelpUtils;
 import com.android.contacts.util.UiClosables;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
 
 import java.io.File;
 import java.util.ArrayList;
@@ -118,6 +119,11 @@
     private static final String KEY_NEW_LOCAL_PROFILE = "newLocalProfile";
     private static final String KEY_IS_USER_PROFILE = "isUserProfile";
     private static final String KEY_UPDATED_PHOTOS = "updatedPhotos";
+    private static final String KEY_IS_EDIT = "isEdit";
+    private static final String KEY_HAS_NEW_CONTACT = "hasNewContact";
+    private static final String KEY_NEW_CONTACT_READY = "newContactDataReady";
+    private static final String KEY_EXISTING_CONTACT_READY = "existingContactDataReady";
+    private static final String KEY_RAW_CONTACTS = "rawContacts";
 
     public static final String SAVE_MODE_EXTRA_KEY = "saveMode";
 
@@ -236,6 +242,21 @@
 
     private int mStatus;
 
+    // Whether to show the new contact blank form and if it's corresponding delta is ready.
+    private boolean mHasNewContact = false;
+    private boolean mNewContactDataReady = false;
+
+    // Whether it's an edit of existing contact and if it's corresponding delta is ready.
+    private boolean mIsEdit = false;
+    private boolean mExistingContactDataReady = false;
+
+    // This is used to pre-populate the editor with a display name when a user edits a read-only
+    // contact.
+    private String mDefaultDisplayName;
+
+    // Used to temporarily store existing contact data during a rebind call (i.e. account switch)
+    private ImmutableList<RawContact> mRawContacts;
+
     private AggregationSuggestionEngine mAggregationSuggestionEngine;
     private long mAggregationSuggestionsRawContactId;
     private View mAggregationSuggestionView;
@@ -365,10 +386,7 @@
 
         validateAction(mAction);
 
-        // Handle initial actions only when existing state missing
-        final boolean hasIncomingState = savedInstanceState != null;
-
-        if (mState == null) {
+        if (mState.isEmpty()) {
             // The delta list may not have finished loading before orientation change happens.
             // In this case, there will be a saved state but deltas will be missing.  Reload from
             // database.
@@ -384,8 +402,12 @@
             bindEditors();
         }
 
-        if (!hasIncomingState) {
-            if (Intent.ACTION_INSERT.equals(mAction)) {
+        // Handle initial actions only when existing state missing
+        if (savedInstanceState == null) {
+            if (Intent.ACTION_EDIT.equals(mAction)) {
+                mIsEdit = true;
+            } else if (Intent.ACTION_INSERT.equals(mAction)) {
+                mHasNewContact = true;
                 final Account account = mIntentExtras == null ? null :
                         (Account) mIntentExtras.getParcelable(Intents.Insert.ACCOUNT);
                 final String dataSet = mIntentExtras == null ? null :
@@ -468,20 +490,34 @@
             mNewLocalProfile = savedState.getBoolean(KEY_NEW_LOCAL_PROFILE);
             mIsUserProfile = savedState.getBoolean(KEY_IS_USER_PROFILE);
             mUpdatedPhotos = savedState.getParcelable(KEY_UPDATED_PHOTOS);
+            mIsEdit = savedState.getBoolean(KEY_IS_EDIT);
+            mHasNewContact = savedState.getBoolean(KEY_HAS_NEW_CONTACT);
+            mNewContactDataReady = savedState.getBoolean(KEY_NEW_CONTACT_READY);
+            mExistingContactDataReady = savedState.getBoolean(KEY_EXISTING_CONTACT_READY);
+            mRawContacts = ImmutableList.copyOf(savedState.<RawContact>getParcelableArrayList(
+                    KEY_RAW_CONTACTS));
+
+        }
+
+        // mState can still be null because it may not have have finished loading before
+        // onSaveInstanceState was called.
+        if (mState == null) {
+            mState = new RawContactDeltaList();
         }
     }
 
-    public void setData(Contact data) {
+    public void setData(Contact contact) {
+
         // If we have already loaded data, we do not want to change it here to not confuse the user
-        if (mState != null) {
+        if (!mState.isEmpty()) {
             Log.v(TAG, "Ignoring background change. This will have to be rebased later");
             return;
         }
 
         // See if this edit operation needs to be redirected to a custom editor
-        ImmutableList<RawContact> rawContacts = data.getRawContacts();
-        if (rawContacts.size() == 1) {
-            RawContact rawContact = rawContacts.get(0);
+        mRawContacts = contact.getRawContacts();
+        if (mRawContacts.size() == 1) {
+            RawContact rawContact = mRawContacts.get(0);
             String type = rawContact.getAccountTypeString();
             String dataSet = rawContact.getDataSet();
             AccountType accountType = rawContact.getAccountType(mContext);
@@ -499,7 +535,18 @@
             }
         }
 
-        bindEditorsForExistingContact(data);
+        // Check for writable raw contacts.  If there are none, then we need to create one so user
+        // can edit.  For the user profile case, there is already an editable contact.
+        if (!contact.isUserProfile() && !contact.isWritableContact(mContext)) {
+            mHasNewContact = true;
+
+            // This is potentially an asynchronous call and will add deltas to list.
+            selectAccountAndCreateContact();
+        }
+
+        // This also adds deltas to list
+        bindEditorsForExistingContact(contact.getDisplayName(), contact.isUserProfile(),
+                mRawContacts);
     }
 
     @Override
@@ -507,15 +554,17 @@
         mListener.onCustomEditContactActivityRequested(account, uri, null, false);
     }
 
-    private void bindEditorsForExistingContact(Contact contact) {
+    private void bindEditorsForExistingContact(String displayName, boolean isUserProfile,
+            ImmutableList<RawContact> rawContacts) {
         setEnabled(true);
+        mDefaultDisplayName = displayName;
 
-        mState = contact.createRawContactDeltaList();
+        mState.addAll(rawContacts.iterator());
         setIntentExtras(mIntentExtras);
         mIntentExtras = null;
 
         // For user profile, change the contacts query URI
-        mIsUserProfile = contact.isUserProfile();
+        mIsUserProfile = isUserProfile;
         boolean localProfileExists = false;
 
         if (mIsUserProfile) {
@@ -539,7 +588,7 @@
             }
         }
         mRequestFocus = true;
-
+        mExistingContactDataReady = true;
         bindEditors();
     }
 
@@ -649,8 +698,13 @@
                 mListener.onCustomCreateContactActivityRequested(newAccount, mIntentExtras);
             }
         } else {
-            mState = null;
+            mExistingContactDataReady = false;
+            mNewContactDataReady = false;
+            mState = new RawContactDeltaList();
             bindEditorsForNewContact(newAccount, newAccountType, oldState, oldAccountType);
+            if (mIsEdit) {
+                bindEditorsForExistingContact(mDefaultDisplayName, mIsUserProfile, mRawContacts);
+            }
         }
     }
 
@@ -671,7 +725,8 @@
             rawContact.setAccountToLocal();
         }
 
-        RawContactDelta insert = new RawContactDelta(ValuesDelta.fromAfter(rawContact.getValues()));
+        final ValuesDelta valuesDelta = ValuesDelta.fromAfter(rawContact.getValues());
+        final RawContactDelta insert = new RawContactDelta(valuesDelta);
         if (oldState == null) {
             // Parse any values from incoming intent
             RawContactModifier.parseExtras(mContext, newAccountType, insert, mIntentExtras);
@@ -694,23 +749,25 @@
             insert.setProfileQueryUri();
         }
 
-        if (mState == null) {
-            // Create state if none exists yet
-            mState = RawContactDeltaList.fromSingle(insert);
-        } else {
-            // Add contact onto end of existing state
-            mState.add(insert);
-        }
+        mState.add(insert);
 
         mRequestFocus = true;
 
+        mNewContactDataReady = true;
         bindEditors();
     }
 
     private void bindEditors() {
         // bindEditors() can only bind views if there is data in mState, so immediately return
         // if mState is null
-        if (mState == null) {
+        if (mState.isEmpty()) {
+            return;
+        }
+
+        // Check if delta list is ready.  Delta list is populated from existing data and when
+        // editing an read-only contact, it's also populated with newly created data for the
+        // blank form.  When the data is not ready, skip. This method will be called multiple times.
+        if ((mIsEdit && !mExistingContactDataReady) || (mHasNewContact && !mNewContactDataReady)) {
             return;
         }
 
@@ -724,6 +781,7 @@
                 Context.LAYOUT_INFLATER_SERVICE);
         final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
         int numRawContacts = mState.size();
+
         for (int i = 0; i < numRawContacts; i++) {
             // TODO ensure proper ordering of entities in the list
             final RawContactDelta rawContactDelta = mState.get(i);
@@ -741,10 +799,10 @@
                 editor = (RawContactEditorView) inflater.inflate(R.layout.raw_contact_editor_view,
                         mContent, false);
             }
-            if (Intent.ACTION_INSERT.equals(mAction) && numRawContacts == 1) {
+            if (mHasNewContact && !mNewLocalProfile) {
                 final List<AccountWithDataSet> accounts =
                         AccountTypeManager.getInstance(mContext).getAccounts(true);
-                if (accounts.size() > 1 && !mNewLocalProfile) {
+                if (accounts.size() > 1) {
                     addAccountSwitcher(mState.get(0), editor);
                 } else {
                     disableAccountSwitcher(editor);
@@ -787,12 +845,13 @@
                     }
                 };
 
-                final TextFieldsEditorView nameEditor = rawContactEditor.getNameEditor();
+                final StructuredNameEditorView nameEditor = rawContactEditor.getNameEditor();
                 if (mRequestFocus) {
                     nameEditor.requestFocus();
                     mRequestFocus = false;
                 }
                 nameEditor.setEditorListener(listener);
+                nameEditor.setDisplayName(mDefaultDisplayName);
 
                 final TextFieldsEditorView phoneticNameEditor =
                         rawContactEditor.getPhoneticNameEditor();
@@ -959,7 +1018,7 @@
         doneMenu.setVisible(false);
 
         // Split only if more than one raw profile and not a user profile
-        splitMenu.setVisible(mState != null && mState.size() > 1 && !isEditingUserProfile());
+        splitMenu.setVisible(mState.size() > 1 && !isEditingUserProfile());
 
         // Cannot join a user profile
         joinMenu.setVisible(!isEditingUserProfile());
@@ -1032,7 +1091,7 @@
      * performing user actions.
      */
     private boolean hasValidState() {
-        return mState != null && mState.size() > 0;
+        return mState.size() > 0;
     }
 
     /**
@@ -1117,7 +1176,7 @@
     }
 
     private boolean revert() {
-        if (mState == null || !hasPendingChanges()) {
+        if (mState.isEmpty() || !hasPendingChanges()) {
             doRevertAction();
         } else {
             CancelEditDialogFragment.show(this);
@@ -1193,7 +1252,7 @@
 
                     // If this was in INSERT, we are changing into an EDIT now.
                     // If it already was an EDIT, we are changing to the new Uri now
-                    mState = null;
+                    mState = new RawContactDeltaList();
                     load(Intent.ACTION_EDIT, contactLookupUri, null);
                     mStatus = Status.LOADING;
                     getLoaderManager().restartLoader(LOADER_DATA, null, mDataLoaderListener);
@@ -1393,12 +1452,10 @@
      * Returns the contact ID for the currently edited contact or 0 if the contact is new.
      */
     protected long getContactId() {
-        if (mState != null) {
-            for (RawContactDelta rawContact : mState) {
-                Long contactId = rawContact.getValues().getAsLong(RawContacts.CONTACT_ID);
-                if (contactId != null) {
-                    return contactId;
-                }
+        for (RawContactDelta rawContact : mState) {
+            Long contactId = rawContact.getValues().getAsLong(RawContacts.CONTACT_ID);
+            if (contactId != null) {
+                return contactId;
             }
         }
         return 0;
@@ -1435,7 +1492,7 @@
     public void onAggregationSuggestionChange() {
         Activity activity = getActivity();
         if ((activity != null && activity.isFinishing())
-                || !isVisible() || mState == null || mStatus != Status.EDITING) {
+                || !isVisible() ||  mState.isEmpty() || mStatus != Status.EDITING) {
             return;
         }
 
@@ -1600,6 +1657,11 @@
         outState.putBoolean(KEY_IS_USER_PROFILE, mIsUserProfile);
         outState.putInt(KEY_STATUS, mStatus);
         outState.putParcelable(KEY_UPDATED_PHOTOS, mUpdatedPhotos);
+        outState.putBoolean(KEY_HAS_NEW_CONTACT, mHasNewContact);
+        outState.putBoolean(KEY_IS_EDIT, mIsEdit);
+        outState.putBoolean(KEY_NEW_CONTACT_READY, mNewContactDataReady);
+        outState.putBoolean(KEY_EXISTING_CONTACT_READY, mExistingContactDataReady);
+        outState.putParcelableArrayList(KEY_RAW_CONTACTS, Lists.newArrayList(mRawContacts));
 
         super.onSaveInstanceState(outState);
     }
@@ -1778,7 +1840,7 @@
 
     @Override
     public void onSplitContactConfirmed() {
-        if (mState == null) {
+        if (mState.isEmpty()) {
             // This may happen when this Fragment is recreated by the system during users
             // confirming the split action (and thus this method is called just before onCreate()),
             // for example.
diff --git a/src/com/android/contacts/editor/RawContactEditorView.java b/src/com/android/contacts/editor/RawContactEditorView.java
index d069c8d..9099307 100644
--- a/src/com/android/contacts/editor/RawContactEditorView.java
+++ b/src/com/android/contacts/editor/RawContactEditorView.java
@@ -418,7 +418,7 @@
         return -1;
     }
 
-    public TextFieldsEditorView getNameEditor() {
+    public StructuredNameEditorView getNameEditor() {
         return mName;
     }
 
diff --git a/src/com/android/contacts/editor/StructuredNameEditorView.java b/src/com/android/contacts/editor/StructuredNameEditorView.java
index f709021..4d72598 100644
--- a/src/com/android/contacts/editor/StructuredNameEditorView.java
+++ b/src/com/android/contacts/editor/StructuredNameEditorView.java
@@ -200,6 +200,18 @@
         }
     }
 
+    /**
+     * Set the display name onto the text field directly.  This does not affect the underlying
+     * data structure so it is similar to the user typing the value in on the field directly.
+     *
+     * @param name The name to set on the text field.
+     */
+    public void setDisplayName(String name) {
+        // For now, assume the first text field is the name.
+        // TODO: Find a better way to get a hold of the name field.
+        super.setValue(0, name);
+    }
+
     @Override
     protected Parcelable onSaveInstanceState() {
         SavedState state = new SavedState(super.onSaveInstanceState());
diff --git a/src/com/android/contacts/editor/TextFieldsEditorView.java b/src/com/android/contacts/editor/TextFieldsEditorView.java
index 0b47021..95eb0c1 100644
--- a/src/com/android/contacts/editor/TextFieldsEditorView.java
+++ b/src/com/android/contacts/editor/TextFieldsEditorView.java
@@ -174,6 +174,10 @@
         }
     }
 
+    public void setValue(int field, String value) {
+        mFieldEditTexts[field].setText(value);
+    }
+
     @Override
     public void setValues(DataKind kind, ValuesDelta entry, RawContactDelta state, boolean readOnly,
             ViewIdGenerator vig) {
diff --git a/src/com/android/contacts/model/RawContactDeltaList.java b/src/com/android/contacts/model/RawContactDeltaList.java
index 600a751..1a9eb71 100644
--- a/src/com/android/contacts/model/RawContactDeltaList.java
+++ b/src/com/android/contacts/model/RawContactDeltaList.java
@@ -49,17 +49,7 @@
     private boolean mSplitRawContacts;
     private long[] mJoinWithRawContactIds;
 
-    private RawContactDeltaList() {
-    }
-
-    /**
-     * Create an {@link RawContactDeltaList} that contains the given {@link RawContactDelta},
-     * usually when inserting a new {@link Contacts} entry.
-     */
-    public static RawContactDeltaList fromSingle(RawContactDelta delta) {
-        final RawContactDeltaList state = new RawContactDeltaList();
-        state.add(delta);
-        return state;
+    public RawContactDeltaList() {
     }
 
     /**
@@ -85,6 +75,11 @@
      */
     public static RawContactDeltaList fromIterator(Iterator<?> iterator) {
         final RawContactDeltaList state = new RawContactDeltaList();
+        state.addAll(iterator);
+        return state;
+    }
+
+    public void addAll(Iterator<?> iterator) {
         // Perform background query to pull contact details
         while (iterator.hasNext()) {
             // Read all contacts into local deltas to prepare for edits
@@ -93,9 +88,8 @@
                     ? RawContact.createFrom((Entity) nextObject)
                     : (RawContact) nextObject;
             final RawContactDelta rawContactDelta = RawContactDelta.fromBefore(before);
-            state.add(rawContactDelta);
+            add(rawContactDelta);
         }
-        return state;
     }
 
     /**
diff --git a/tests/src/com/android/contacts/RawContactDeltaListTests.java b/tests/src/com/android/contacts/RawContactDeltaListTests.java
index a8c445b..6a75b81 100644
--- a/tests/src/com/android/contacts/RawContactDeltaListTests.java
+++ b/tests/src/com/android/contacts/RawContactDeltaListTests.java
@@ -45,6 +45,7 @@
 
 import java.lang.reflect.Field;
 import java.util.ArrayList;
+import java.util.Collections;
 
 /**
  * Tests for {@link RawContactDeltaList} which focus on "diff" operations that should
@@ -112,10 +113,8 @@
     }
 
     static RawContactDeltaList buildSet(RawContactDelta... deltas) {
-        final RawContactDeltaList set = RawContactDeltaList.fromSingle(deltas[0]);
-        for (int i = 1; i < deltas.length; i++) {
-            set.add(deltas[i]);
-        }
+        final RawContactDeltaList set = new RawContactDeltaList();
+        Collections.addAll(set, deltas);
         return set;
     }
 
diff --git a/tests/src/com/android/contacts/RawContactModifierTests.java b/tests/src/com/android/contacts/RawContactModifierTests.java
index 91358ca..ce69b55 100644
--- a/tests/src/com/android/contacts/RawContactModifierTests.java
+++ b/tests/src/com/android/contacts/RawContactModifierTests.java
@@ -521,7 +521,9 @@
 
         // Try creating a contact without any child entries
         final RawContactDelta state = getRawContact(null);
-        final RawContactDeltaList set = RawContactDeltaList.fromSingle(state);
+        final RawContactDeltaList set = new RawContactDeltaList();
+        set.add(state);
+
 
         // Build diff, expecting single insert
         final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
@@ -549,7 +551,8 @@
         // Try creating a contact with single empty entry
         final RawContactDelta state = getRawContact(null);
         RawContactModifier.insertChild(state, kindPhone, typeHome);
-        final RawContactDeltaList set = RawContactDeltaList.fromSingle(state);
+        final RawContactDeltaList set = new RawContactDeltaList();
+        set.add(state);
 
         // Build diff, expecting two insert operations
         final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
@@ -593,7 +596,8 @@
         second.put(Phone.NUMBER, TEST_PHONE);
 
         final RawContactDelta state = getRawContact(TEST_ID, first, second);
-        final RawContactDeltaList set = RawContactDeltaList.fromSingle(state);
+        final RawContactDeltaList set = new RawContactDeltaList();
+        set.add(state);
 
         // Build diff, expecting no changes
         final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
@@ -658,7 +662,8 @@
         first.put(Phone.NUMBER, TEST_PHONE);
 
         final RawContactDelta state = getRawContact(TEST_ID, first);
-        final RawContactDeltaList set = RawContactDeltaList.fromSingle(state);
+        final RawContactDeltaList set = new RawContactDeltaList();
+        set.add(state);
 
         // Build diff, expecting no changes
         final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
diff --git a/tests/src/com/android/contacts/detail/ContactDetailFragmentTests.java b/tests/src/com/android/contacts/detail/ContactDetailFragmentTests.java
index 0b86912..1747add 100644
--- a/tests/src/com/android/contacts/detail/ContactDetailFragmentTests.java
+++ b/tests/src/com/android/contacts/detail/ContactDetailFragmentTests.java
@@ -105,10 +105,11 @@
         ImDataItem im = (ImDataItem) DataItem.createFrom(values);
 
         DetailViewEntry entry = new ContactDetailFragment.DetailViewEntry();
-        ContactDetailFragment.buildImActions(mContext, entry, im);
-        assertEquals(Intent.ACTION_SENDTO, entry.intent.getAction());
+        final Intent imIntent =
+                ContactDetailFragment.getCustomIMIntent(im, Im.PROTOCOL_CUSTOM);
+        assertEquals(Intent.ACTION_SENDTO, imIntent.getAction());
 
-        final Uri data = entry.intent.getData();
+        final Uri data = imIntent.getData();
         assertEquals("imto", data.getScheme());
         assertEquals(TEST_PROTOCOL, data.getAuthority());
         assertEquals(TEST_ADDRESS, data.getPathSegments().get(0));