Load contact in CallDetailActivity and add it to Add contact intent

Use a ContactLoader to load the contact data stored in the json-encoded
URI asynchronously, and prepopulate the add contact intent with the
contact data when the contact data is loaded.

This fixes the problem of contact details (i.e. name, photo, address)
not being pre-populated when adding a contact via a call log entry that
was created by calling a contact from nearby places search.

Bug: 11294679
Change-Id: I39a0d8ae40e80b350687a43be8ece6b32c88062a
diff --git a/src/com/android/dialer/CallDetailActivity.java b/src/com/android/dialer/CallDetailActivity.java
index b0c8e68..2b16a98 100644
--- a/src/com/android/dialer/CallDetailActivity.java
+++ b/src/com/android/dialer/CallDetailActivity.java
@@ -17,11 +17,13 @@
 package com.android.dialer;
 
 import android.app.Activity;
+import android.app.LoaderManager.LoaderCallbacks;
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
+import android.content.Loader;
 import android.content.res.Resources;
 import android.database.Cursor;
 import android.graphics.drawable.Drawable;
@@ -30,9 +32,10 @@
 import android.os.Bundle;
 import android.provider.CallLog;
 import android.provider.CallLog.Calls;
-import android.provider.Contacts.Intents.Insert;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
 import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.DisplayNameSources;
+import android.provider.ContactsContract.Intents.Insert;
 import android.provider.VoicemailContract.Voicemails;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.TelephonyManager;
@@ -54,6 +57,8 @@
 import com.android.contacts.common.CallUtil;
 import com.android.contacts.common.ClipboardUtils;
 import com.android.contacts.common.GeoUtil;
+import com.android.contacts.common.model.Contact;
+import com.android.contacts.common.model.ContactLoader;
 import com.android.contacts.common.util.UriUtils;
 import com.android.dialer.BackScrollManager.ScrollableHeader;
 import com.android.dialer.calllog.CallDetailHistoryAdapter;
@@ -80,6 +85,9 @@
 public class CallDetailActivity extends Activity implements ProximitySensorAware {
     private static final String TAG = "CallDetail";
 
+    private static final int LOADER_ID = 0;
+    private static final String BUNDLE_CONTACT_URI_EXTRA = "contact_uri_extra";
+
     private static final char LEFT_TO_RIGHT_EMBEDDING = '\u202A';
     private static final char POP_DIRECTIONAL_FORMATTING = '\u202C';
 
@@ -252,6 +260,35 @@
         }
     };
 
+    private final LoaderCallbacks<Contact> mLoaderCallbacks = new LoaderCallbacks<Contact>() {
+        @Override
+        public void onLoaderReset(Loader<Contact> loader) {
+        }
+
+        @Override
+        public void onLoadFinished(Loader<Contact> loader, Contact data) {
+            final Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
+            intent.setType(Contacts.CONTENT_ITEM_TYPE);
+            if (data.getDisplayNameSource() >= DisplayNameSources.ORGANIZATION) {
+                intent.putExtra(Insert.NAME, data.getDisplayName());
+            }
+            intent.putExtra(Insert.DATA, data.getContentValues());
+            bindContactPhotoAction(intent, R.drawable.ic_add_contact_holo_dark,
+                    getString(R.string.description_add_contact));
+        }
+
+        @Override
+        public Loader<Contact> onCreateLoader(int id, Bundle args) {
+            final Uri contactUri = args.getParcelable(BUNDLE_CONTACT_URI_EXTRA);
+            if (contactUri == null) {
+                Log.wtf(TAG, "No contact lookup uri provided.");
+            }
+            return new ContactLoader(CallDetailActivity.this, contactUri,
+                    false /* loadGroupMetaData */, false /* loadInvitableAccountTypes */,
+                    false /* postViewNotification */, true /* computeFormattedPhoneNumber */);
+        }
+    };
+
     @Override
     protected void onCreate(Bundle icicle) {
         super.onCreate(icicle);
@@ -461,6 +498,13 @@
                     mainActionIcon = R.drawable.ic_contacts_holo_dark;
                     mainActionDescription =
                             getString(R.string.description_view_contact, nameOrNumber);
+                } else if (UriUtils.isEncodedContactUri(contactUri)) {
+                    final Bundle bundle = new Bundle(1);
+                    bundle.putParcelable(BUNDLE_CONTACT_URI_EXTRA, contactUri);
+                    getLoaderManager().initLoader(LOADER_ID, bundle, mLoaderCallbacks);
+                    mainActionIntent = null;
+                    mainActionIcon = R.drawable.ic_add_contact_holo_dark;
+                    mainActionDescription = getString(R.string.description_add_contact);
                 } else if (isVoicemailNumber) {
                     mainActionIntent = null;
                     mainActionIcon = 0;
@@ -485,32 +529,14 @@
                     mainActionIcon = R.drawable.ic_add_contact_holo_dark;
                     mainActionDescription = getString(R.string.description_add_contact);
                 } else {
-                    // If we cannot call the number, when we probably cannot add it as a contact either.
-                    // This is usually the case of private, unknown, or payphone numbers.
+                    // If we cannot call the number, when we probably cannot add it as a contact
+                    // either. This is usually the case of private, unknown, or payphone numbers.
                     mainActionIntent = null;
                     mainActionIcon = 0;
                     mainActionDescription = null;
                 }
 
-                if (mainActionIntent == null) {
-                    mMainActionView.setVisibility(View.INVISIBLE);
-                    mMainActionPushLayerView.setVisibility(View.GONE);
-                    mHeaderTextView.setVisibility(View.INVISIBLE);
-                    mHeaderOverlayView.setVisibility(View.INVISIBLE);
-                } else {
-                    mMainActionView.setVisibility(View.VISIBLE);
-                    mMainActionView.setImageResource(mainActionIcon);
-                    mMainActionPushLayerView.setVisibility(View.VISIBLE);
-                    mMainActionPushLayerView.setOnClickListener(new View.OnClickListener() {
-                        @Override
-                        public void onClick(View v) {
-                            startActivity(mainActionIntent);
-                        }
-                    });
-                    mMainActionPushLayerView.setContentDescription(mainActionDescription);
-                    mHeaderTextView.setVisibility(View.VISIBLE);
-                    mHeaderOverlayView.setVisibility(View.VISIBLE);
-                }
+                bindContactPhotoAction(mainActionIntent, mainActionIcon, mainActionDescription);
 
                 // This action allows to call the number that places the call.
                 if (canPlaceCallsTo) {
@@ -597,6 +623,29 @@
         mAsyncTaskExecutor.submit(Tasks.UPDATE_PHONE_CALL_DETAILS, new UpdateContactDetailsTask());
     }
 
+    private void bindContactPhotoAction(final Intent actionIntent, int actionIcon,
+            String actionDescription) {
+        if (actionIntent == null) {
+            mMainActionView.setVisibility(View.INVISIBLE);
+            mMainActionPushLayerView.setVisibility(View.GONE);
+            mHeaderTextView.setVisibility(View.INVISIBLE);
+            mHeaderOverlayView.setVisibility(View.INVISIBLE);
+        } else {
+            mMainActionView.setVisibility(View.VISIBLE);
+            mMainActionView.setImageResource(actionIcon);
+            mMainActionPushLayerView.setVisibility(View.VISIBLE);
+            mMainActionPushLayerView.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    startActivity(actionIntent);
+                }
+            });
+            mMainActionPushLayerView.setContentDescription(actionDescription);
+            mHeaderTextView.setVisibility(View.VISIBLE);
+            mHeaderOverlayView.setVisibility(View.VISIBLE);
+        }
+    }
+
     /** Return the phone call details for a given call log URI. */
     private PhoneCallDetails getPhoneCallDetailsForUri(Uri callUri) {
         ContentResolver resolver = getContentResolver();