Allow EditContactActivity to use a picker

Few fixes... when creating a contact, it returns to the List.  The list converts
the raw_contact into a contact and returns that (same as if you selected a contact).

Then changed AttachImage to use the new style of contacts.

Bug: 2092559
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 68e66ba..6f6e3cd 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -4,9 +4,9 @@
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
      You may obtain a copy of the License at
-  
+
           http://www.apache.org/licenses/LICENSE-2.0
-  
+
      Unless required by applicable law or agreed to in writing, software
      distributed under the License is distributed on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -349,6 +349,7 @@
                 <data android:mimeType="vnd.android.cursor.dir/contact" />
                 <data android:mimeType="vnd.android.cursor.dir/raw_contact" />
             </intent-filter>
+
         </activity>
 
         <!-- Stub service used to keep our process alive long enough for
@@ -360,7 +361,7 @@
         <!-- Views the details of a single contact -->
         <activity android:name="ContactOptionsActivity"
             android:label="@string/contactOptionsTitle"
-        >   
+        >
             <intent-filter>
                 <action android:name="android.intent.action.EDIT" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -377,10 +378,10 @@
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
             />
-        </activity>        
+        </activity>
 
         <!-- Makes .ContactsListActivity the search target for any activity in Contacts -->
-        <meta-data android:name="android.app.default_searchable" 
+        <meta-data android:name="android.app.default_searchable"
                    android:value=".ContactsListActivity" />
 
 
diff --git a/res/values/strings.xml b/res/values/strings.xml
index fcb6d1e..43c1c82 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -344,6 +344,9 @@
     <!-- The group type that displays "Starred in Android" contacts -->
     <string name="starredInAndroid">Starred in Android</string>
 
+    <!-- Displayed in a spinner dialog after the user creates a contact and it's being saved to the database -->
+    <string name="savingContact">Saving contact...</string>
+
     <!-- Toast displayed when a contact is created -->
     <string name="contactCreatedToast">Contact created.</string>
 
diff --git a/src/com/android/contacts/AttachImage.java b/src/com/android/contacts/AttachImage.java
index 8c91722..fd820e2 100644
--- a/src/com/android/contacts/AttachImage.java
+++ b/src/com/android/contacts/AttachImage.java
@@ -17,12 +17,16 @@
 package com.android.contacts;
 
 import android.app.Activity;
+import android.content.ContentUris;
+import android.content.ContentValues;
 import android.content.Intent;
 import android.graphics.Bitmap;
 import android.net.Uri;
 import android.os.Bundle;
-import android.provider.Contacts;
-import android.provider.Contacts.People;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.RawContacts;
+import android.provider.ContactsContract.CommonDataKinds.Photo;
+import android.widget.Toast;
 
 import java.io.ByteArrayOutputStream;
 
@@ -42,6 +46,9 @@
 
     }
 
+    /**
+     * Is the raw_contact uri for the contact the user selected
+     */
     Uri mContactUri;
 
     @Override
@@ -52,7 +59,7 @@
             mContactUri = icicle.getParcelable(CONTACT_URI_KEY);
         } else {
             Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
-            intent.setType(People.CONTENT_ITEM_TYPE);
+            intent.setType(Contacts.CONTENT_ITEM_TYPE);
             startActivityForResult(intent, REQUEST_PICK_CONTACT);
         }
     }
@@ -74,7 +81,6 @@
         }
 
         if (requestCode == REQUEST_PICK_CONTACT) {
-            mContactUri = result.getData();
             // A contact was picked. Launch the cropper to get face detection, the right size, etc.
             // TODO: get these values from constants somewhere
             Intent myIntent = getIntent();
@@ -89,6 +95,20 @@
             intent.putExtra("outputY", 96);
             intent.putExtra("return-data", true);
             startActivityForResult(intent, REQUEST_CROP_PHOTO);
+
+            // while they're cropping, convert the contact into a raw_contact
+            final long contactId = ContentUris.parseId(result.getData());
+            final long rawContactId = ContactsUtils.queryForRawContactId(getContentResolver(),
+                    contactId);
+
+            if (rawContactId == -1) {
+                Toast.makeText(this, R.string.contactSavedErrorToast, Toast.LENGTH_LONG).show();
+            }
+
+            mContactUri = Uri.withAppendedPath(
+                    ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId),
+                    RawContacts.Data.CONTENT_DIRECTORY);
+
         } else if (requestCode == REQUEST_CROP_PHOTO) {
             final Bundle extras = result.getExtras();
             if (extras != null) {
@@ -96,8 +116,12 @@
                 if (photo != null) {
                     ByteArrayOutputStream stream = new ByteArrayOutputStream();
                     photo.compress(Bitmap.CompressFormat.JPEG, 75, stream);
-                    Contacts.People.setPhotoData(getContentResolver(), mContactUri,
-                            stream.toByteArray());
+
+                    final ContentValues imageValues = new ContentValues();
+                    imageValues.put(Photo.MIMETYPE, Photo.CONTENT_ITEM_TYPE);
+                    imageValues.put(Photo.PHOTO, stream.toByteArray());
+                    imageValues.put(RawContacts.Data.IS_SUPER_PRIMARY, 1);
+                    getContentResolver().insert(mContactUri, imageValues);
                 }
             }
             finish();
diff --git a/src/com/android/contacts/ContactsListActivity.java b/src/com/android/contacts/ContactsListActivity.java
index 5e8519e..52470a3 100644
--- a/src/com/android/contacts/ContactsListActivity.java
+++ b/src/com/android/contacts/ContactsListActivity.java
@@ -294,6 +294,8 @@
 
     private static final int QUERY_TOKEN = 42;
 
+    static final String KEY_PICKER_MODE = "picker_mode";
+
     private ContactItemListAdapter mAdapter;
 
     int mMode = MODE_DEFAULT;
@@ -878,7 +880,6 @@
         switch (requestCode) {
             case SUBACTIVITY_NEW_CONTACT:
                 if (resultCode == RESULT_OK) {
-                    // Contact was created, pass it back
                     returnPickerResult(null, data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME),
                             data.getData(), 0);
                 }
@@ -1040,7 +1041,6 @@
         if (mMode == MODE_INSERT_OR_EDIT_CONTACT) {
             Intent intent;
             if (position == 0) {
-                // Insert
                 intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI);
             } else {
                 // Edit
@@ -1048,10 +1048,14 @@
                 intent = new Intent(Intent.ACTION_EDIT, uri);
             }
             intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
-            final Bundle extras = getIntent().getExtras();
-            if (extras != null) {
-                intent.putExtras(extras);
+            Bundle extras = getIntent().getExtras();
+
+            if (extras == null) {
+                extras = new Bundle();
             }
+            intent.putExtras(extras);
+            extras.putBoolean(KEY_PICKER_MODE, (mMode & MODE_MASK_PICKER) == MODE_MASK_PICKER);
+
             startActivity(intent);
             finish();
         } else if (id != -1) {
@@ -1094,9 +1098,8 @@
             }
         } else if ((mMode & MODE_MASK_CREATE_NEW) == MODE_MASK_CREATE_NEW
                 && position == 0) {
-            // TODO: Hook this up to new edit contact activity (bug 2092559)
-            /*Intent newContact = new Intent(Intents.Insert.ACTION, People.CONTENT_URI);
-            startActivityForResult(newContact, SUBACTIVITY_NEW_CONTACT);*/
+            Intent newContact = new Intent(Intents.Insert.ACTION, Contacts.CONTENT_URI);
+            startActivityForResult(newContact, SUBACTIVITY_NEW_CONTACT);
         } else {
             signalError();
         }
diff --git a/src/com/android/contacts/model/EntitySet.java b/src/com/android/contacts/model/EntitySet.java
index 18afd2b..75c9dc3 100644
--- a/src/com/android/contacts/model/EntitySet.java
+++ b/src/com/android/contacts/model/EntitySet.java
@@ -160,7 +160,7 @@
      * existing {@link RawContacts#_ID} value. Usually used when creating
      * {@link AggregationExceptions} during an update.
      */
-    protected long findRawContactId() {
+    public long findRawContactId() {
         for (EntityDelta delta : this) {
             final Long rawContactId = delta.getValues().getAsLong(RawContacts._ID);
             if (rawContactId != null && rawContactId >= 0) {
diff --git a/src/com/android/contacts/ui/EditContactActivity.java b/src/com/android/contacts/ui/EditContactActivity.java
index d9ae717..843615a 100644
--- a/src/com/android/contacts/ui/EditContactActivity.java
+++ b/src/com/android/contacts/ui/EditContactActivity.java
@@ -16,31 +16,14 @@
 
 package com.android.contacts.ui;
 
-import com.android.contacts.ContactsUtils;
-import com.android.contacts.R;
-import com.android.contacts.ScrollingTabWidget;
-import com.android.contacts.ViewContactActivity;
-import com.android.contacts.model.ContactsSource;
-import com.android.contacts.model.Editor;
-import com.android.contacts.model.EntityDelta;
-import com.android.contacts.model.EntityModifier;
-import com.android.contacts.model.EntitySet;
-import com.android.contacts.model.HardCodedSources;
-import com.android.contacts.model.Sources;
-import com.android.contacts.model.Editor.EditorListener;
-import com.android.contacts.model.EntityDelta.ValuesDelta;
-import com.android.contacts.ui.widget.ContactEditorView;
-import com.android.contacts.util.EmptyService;
-import com.android.contacts.util.WeakAsyncTask;
-import com.android.internal.widget.ContactHeaderWidget;
-import com.google.android.collect.Lists;
-
 import android.accounts.Account;
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.Dialog;
+import android.app.ProgressDialog;
 import android.content.ActivityNotFoundException;
 import android.content.ContentProviderOperation;
+import android.content.ContentProviderResult;
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.ContentValues;
@@ -74,10 +57,27 @@
 import android.widget.TextView;
 import android.widget.Toast;
 
+import com.google.android.collect.Lists;
+
+import com.android.contacts.ContactsUtils;
+import com.android.contacts.R;
+import com.android.contacts.ScrollingTabWidget;
+import com.android.contacts.model.ContactsSource;
+import com.android.contacts.model.Editor;
+import com.android.contacts.model.EntityDelta;
+import com.android.contacts.model.EntityModifier;
+import com.android.contacts.model.EntitySet;
+import com.android.contacts.model.HardCodedSources;
+import com.android.contacts.model.Sources;
+import com.android.contacts.model.Editor.EditorListener;
+import com.android.contacts.model.EntityDelta.ValuesDelta;
+import com.android.contacts.ui.widget.ContactEditorView;
+import com.android.contacts.util.EmptyService;
+import com.android.contacts.util.WeakAsyncTask;
+import com.android.internal.widget.ContactHeaderWidget;
+
+import java.lang.ref.WeakReference;
 import java.util.ArrayList;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
 
 /**
  * Activity for editing or inserting a contact.
@@ -493,19 +493,6 @@
         return false;
     }
 
-
-
-
-
-
-
-
-
-
-
-
-
-
     /**
      * Background task for persisting edited contact data, using the changes
      * defined by a set of {@link EntityDelta}. This task starts
@@ -520,6 +507,10 @@
         private static final int RESULT_SUCCESS = 1;
         private static final int RESULT_FAILURE = 2;
 
+        private long mSavedId;
+
+        private WeakReference<ProgressDialog> progress;
+
         public PersistTask(EditContactActivity target) {
             super(target);
         }
@@ -527,6 +518,9 @@
         /** {@inheritDoc} */
         @Override
         protected void onPreExecute(EditContactActivity target) {
+            this.progress = new WeakReference<ProgressDialog>(ProgressDialog.show(target, null,
+                    target.getText(R.string.savingContact)));
+
             // Before starting this task, start an empty service to protect our
             // process from being reclaimed by the system.
             final Context context = target;
@@ -552,7 +546,21 @@
                 try {
                     // Build operations and try applying
                     final ArrayList<ContentProviderOperation> diff = state.buildDiff();
-                    resolver.applyBatch(ContactsContract.AUTHORITY, diff);
+                    ContentProviderResult[] results;
+                    if (!diff.isEmpty()) {
+                         results = resolver.applyBatch(ContactsContract.AUTHORITY, diff);
+                         Intent intent = new Intent();
+                         final long rawContactId = getRawContactId(state, diff, results);
+                         final Uri rawContactUri = ContentUris.withAppendedId(
+                                 RawContacts.CONTENT_URI, rawContactId);
+
+                         // convert the raw contact URI to a contact URI
+                         final Uri contactLookupUri = RawContacts.getContactLookupUri(resolver,
+                                 rawContactUri);
+                         intent.setData(contactLookupUri);
+                         target.setResult(RESULT_OK, intent);
+                         target.finish();
+                    }
                     result = (diff.size() > 0) ? RESULT_SUCCESS : RESULT_UNCHANGED;
                     break;
 
@@ -574,6 +582,27 @@
             return result;
         }
 
+        private long getRawContactId(EntitySet state,
+                final ArrayList<ContentProviderOperation> diff,
+                final ContentProviderResult[] results) {
+            long rawContactId = state.findRawContactId();
+            if (rawContactId != -1) {
+                return rawContactId;
+            }
+
+            // we gotta do some searching for the id
+            final int diffSize = diff.size();
+            for (int i = 0; i < diffSize; i++) {
+                ContentProviderOperation operation = diff.get(i);
+                if (operation.getType() == ContentProviderOperation.TYPE_INSERT
+                        && operation.getUri().getEncodedPath().contains(
+                                RawContacts.CONTENT_URI.getEncodedPath())) {
+                    return ContentUris.parseId(results[i].uri);
+                }
+            }
+            return -1;
+        }
+
         /** {@inheritDoc} */
         @Override
         protected void onPostExecute(EditContactActivity target, Integer result) {
@@ -585,48 +614,23 @@
                 Toast.makeText(context, R.string.contactSavedErrorToast, Toast.LENGTH_LONG).show();
             }
 
+            progress.get().dismiss();
+            target.finish();
             // Stop the service that was protecting us
             context.stopService(new Intent(context, EmptyService.class));
         }
     }
 
     /**
-     * Timeout for a {@link PersistTask} running on a background thread. This is
-     * just shorter than the ANR timeout, so that we hold off user interaction
-     * as long as possible.
-     */
-    private static final long TIMEOUT_PERSIST = 4000;
-
-    /**
      * Saves or creates the contact based on the mode, and if successful
      * finishes the activity.
      */
     private boolean doSaveAction() {
         if (!hasValidState()) return false;
 
-        // Pass back last-selected contact
-        final Long rawContactId = this.getSelectedRawContactId();
-        if (rawContactId != null) {
-            final Intent intent = new Intent();
-            intent.putExtra(ViewContactActivity.RAW_CONTACT_ID_EXTRA, (long)rawContactId);
-            setResult(RESULT_OK, intent);
-        }
+        final PersistTask task = new PersistTask(this);
+        task.execute(mState);
 
-        try {
-            final PersistTask task = new PersistTask(this);
-            task.execute(mState);
-            task.get(TIMEOUT_PERSIST, TimeUnit.MILLISECONDS);
-        } catch (InterruptedException e) {
-            // Ignore when someone cancels the operation
-        } catch (TimeoutException e) {
-            // Ignore when task is taking too long
-        } catch (ExecutionException e) {
-            // Important exceptions are handled on remote thread
-        }
-
-        // Persisting finished, or we timed out waiting on it. Either way,
-        // finish this activity, the background task will keep running.
-        this.finish();
         return true;
     }