Merge "Fixed crash Unable to add window"
diff --git a/src/com/android/contacts/ContactPresenceIconUtil.java b/src/com/android/contacts/ContactPresenceIconUtil.java
new file mode 100644
index 0000000..1a2d58e
--- /dev/null
+++ b/src/com/android/contacts/ContactPresenceIconUtil.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.provider.ContactsContract.StatusUpdates;
+
+/**
+ * Define the contact present show policy in Contacts
+ */
+public class ContactPresenceIconUtil {
+    /**
+     * Get the presence icon resource according the status.
+     * 
+     * @return null means don't show the status icon.
+     */
+    public static Drawable getPresenceIcon (Context context, int status) {
+        // We don't show the offline status in Contacts
+        switch(status) {
+            case StatusUpdates.AVAILABLE:
+            case StatusUpdates.IDLE:
+            case StatusUpdates.AWAY:
+            case StatusUpdates.DO_NOT_DISTURB:
+            case StatusUpdates.INVISIBLE:
+                return context.getResources().getDrawable(
+                        StatusUpdates.getPresenceIconResourceId(status));
+            case StatusUpdates.OFFLINE:
+            // The undefined status is treated as OFFLINE in getPresenceIconResourceId();
+            default:
+                return null;
+        }
+    }
+}
diff --git a/src/com/android/contacts/ContactsListActivity.java b/src/com/android/contacts/ContactsListActivity.java
index d0b064b..c7d158d 100644
--- a/src/com/android/contacts/ContactsListActivity.java
+++ b/src/com/android/contacts/ContactsListActivity.java
@@ -3067,9 +3067,13 @@
                 int serverStatus;
                 if (!cursor.isNull(SUMMARY_PRESENCE_STATUS_COLUMN_INDEX)) {
                     serverStatus = cursor.getInt(SUMMARY_PRESENCE_STATUS_COLUMN_INDEX);
-                    presenceView.setImageResource(
-                            Presence.getPresenceIconResourceId(serverStatus));
-                    presenceView.setVisibility(View.VISIBLE);
+                    Drawable icon = ContactPresenceIconUtil.getPresenceIcon(mContext, serverStatus);
+                    if (icon != null) {
+                        presenceView.setImageDrawable(icon);
+                        presenceView.setVisibility(View.VISIBLE);
+                    } else {
+                        presenceView.setVisibility(View.GONE);
+                    }
                 } else {
                     presenceView.setVisibility(View.GONE);
                 }
diff --git a/src/com/android/contacts/ViewContactActivity.java b/src/com/android/contacts/ViewContactActivity.java
index 168da46..ee86ef9 100644
--- a/src/com/android/contacts/ViewContactActivity.java
+++ b/src/com/android/contacts/ViewContactActivity.java
@@ -978,7 +978,6 @@
         public int collapseCount = 0;
 
         public int presence = -1;
-        public int presenceIcon = -1;
 
         public CharSequence footerLine = null;
 
@@ -1019,9 +1018,6 @@
          */
         public ViewEntry applyStatus(DataStatus status, boolean fillData) {
             presence = status.getPresence();
-            presenceIcon = (presence == -1) ? -1 :
-                    StatusUpdates.getPresenceIconResourceId(this.presence);
-
             if (fillData && status.isValid()) {
                 this.data = status.getStatus().toString();
                 this.footerLine = status.getTimestampLabel(context);
@@ -1208,13 +1204,8 @@
             }
 
             // Set the presence icon
-            Drawable presenceIcon = null;
-            if (entry.presenceIcon != -1) {
-                presenceIcon = resources.getDrawable(entry.presenceIcon);
-            } else if (entry.presence != -1) {
-                presenceIcon = resources.getDrawable(
-                        StatusUpdates.getPresenceIconResourceId(entry.presence));
-            }
+            Drawable presenceIcon = ContactPresenceIconUtil.getPresenceIcon(
+                    mContext, entry.presence);
             ImageView presenceIconView = views.presenceIcon;
             if (presenceIcon != null) {
                 presenceIconView.setImageDrawable(presenceIcon);
diff --git a/src/com/android/contacts/ui/EditContactActivity.java b/src/com/android/contacts/ui/EditContactActivity.java
index d1e6328..74d2f3e 100644
--- a/src/com/android/contacts/ui/EditContactActivity.java
+++ b/src/com/android/contacts/ui/EditContactActivity.java
@@ -136,6 +136,13 @@
     String mQuerySelection;
 
     private long mContactIdForJoin;
+
+    private static final int STATUS_LOADING = 0;
+    private static final int STATUS_EDITING = 1;
+    private static final int STATUS_SAVING = 2;
+
+    private int mStatus;
+
     EntitySet mState;
 
     /** The linear layout holding the ContactEditorViews */
@@ -165,10 +172,13 @@
 
         if (Intent.ACTION_EDIT.equals(action) && !hasIncomingState) {
             setTitle(R.string.editContact_title_edit);
+            mStatus = STATUS_LOADING;
+
             // Read initial state from database
             new QueryEntitiesTask(this).execute(intent);
         } else if (Intent.ACTION_INSERT.equals(action) && !hasIncomingState) {
             setTitle(R.string.editContact_title_insert);
+            mStatus = STATUS_EDITING;
             // Trigger dialog to pick account type
             doAddAction();
         }
@@ -180,49 +190,56 @@
     }
 
     private static class QueryEntitiesTask extends
-            WeakAsyncTask<Intent, Void, Void, EditContactActivity> {
+            WeakAsyncTask<Intent, Void, EntitySet, EditContactActivity> {
+
+        private String mSelection;
 
         public QueryEntitiesTask(EditContactActivity target) {
             super(target);
         }
 
         @Override
-        protected Void doInBackground(EditContactActivity target, Intent... params) {
-            // Load edit details in background
-            final Context context = target;
-            final Sources sources = Sources.getInstance(context);
+        protected EntitySet doInBackground(EditContactActivity target, Intent... params) {
             final Intent intent = params[0];
 
-            final ContentResolver resolver = context.getContentResolver();
+            final ContentResolver resolver = target.getContentResolver();
 
             // Handle both legacy and new authorities
             final Uri data = intent.getData();
             final String authority = data.getAuthority();
             final String mimeType = intent.resolveType(resolver);
 
-            String selection = "0";
+            mSelection = "0";
             if (ContactsContract.AUTHORITY.equals(authority)) {
                 if (Contacts.CONTENT_ITEM_TYPE.equals(mimeType)) {
                     // Handle selected aggregate
                     final long contactId = ContentUris.parseId(data);
-                    selection = RawContacts.CONTACT_ID + "=" + contactId;
+                    mSelection = RawContacts.CONTACT_ID + "=" + contactId;
                 } else if (RawContacts.CONTENT_ITEM_TYPE.equals(mimeType)) {
                     final long rawContactId = ContentUris.parseId(data);
                     final long contactId = ContactsUtils.queryForContactId(resolver, rawContactId);
-                    selection = RawContacts.CONTACT_ID + "=" + contactId;
+                    mSelection = RawContacts.CONTACT_ID + "=" + contactId;
                 }
             } else if (android.provider.Contacts.AUTHORITY.equals(authority)) {
                 final long rawContactId = ContentUris.parseId(data);
-                selection = Data.RAW_CONTACT_ID + "=" + rawContactId;
+                mSelection = Data.RAW_CONTACT_ID + "=" + rawContactId;
             }
 
-            target.mQuerySelection = selection;
-            target.mState = EntitySet.fromQuery(resolver, selection, null, null);
+            return EntitySet.fromQuery(target.getContentResolver(), mSelection, null, null);
+        }
+
+        @Override
+        protected void onPostExecute(EditContactActivity target, EntitySet entitySet) {
+            target.mQuerySelection = mSelection;
+
+            // Load edit details in background
+            final Context context = target;
+            final Sources sources = Sources.getInstance(context);
 
             // Handle any incoming values that should be inserted
-            final Bundle extras = intent.getExtras();
+            final Bundle extras = target.getIntent().getExtras();
             final boolean hasExtras = extras != null && extras.size() > 0;
-            final boolean hasState = target.mState.size() > 0;
+            final boolean hasState = entitySet.size() > 0;
             if (hasExtras && hasState) {
                 // Find source defining the first RawContact found
                 final EntityDelta state = target.mState.get(0);
@@ -232,18 +249,13 @@
                 EntityModifier.parseExtras(context, source, state, extras);
             }
 
-            return null;
-        }
+            target.mState = entitySet;
 
-        @Override
-        protected void onPostExecute(EditContactActivity target, Void result) {
             // Bind UI to new background state
             target.bindEditors();
         }
     }
 
-
-
     @Override
     protected void onSaveInstanceState(Bundle outState) {
         if (hasValidState()) {
@@ -278,7 +290,7 @@
     }
 
     @Override
-    protected Dialog onCreateDialog(int id) {
+    protected Dialog onCreateDialog(int id, Bundle bundle) {
         switch (id) {
             case DIALOG_CONFIRM_DELETE:
                 return new AlertDialog.Builder(this)
@@ -355,7 +367,7 @@
      * performing user actions.
      */
     protected boolean hasValidState() {
-        return mState != null && mState.size() > 0;
+        return mStatus == STATUS_EDITING && mState != null && mState.size() > 0;
     }
 
     /**
@@ -364,7 +376,9 @@
      * {@link RawContacts}.
      */
     protected void bindEditors() {
-        if (!hasValidState()) return;
+        if (mState == null) {
+            return;
+        }
 
         final LayoutInflater inflater = (LayoutInflater) getSystemService(
                 Context.LAYOUT_INFLATER_SERVICE);
@@ -405,6 +419,7 @@
 
         // Show editor now that we've loaded state
         mContent.setVisibility(View.VISIBLE);
+        mStatus = STATUS_EDITING;
     }
 
     /**
@@ -744,8 +759,11 @@
      * finishes the activity.
      */
     boolean doSaveAction(int saveMode) {
-        if (!hasValidState()) return false;
+        if (!hasValidState()) {
+            return false;
+        }
 
+        mStatus = STATUS_SAVING;
         final PersistTask task = new PersistTask(this, saveMode);
         task.execute(mState);
 
@@ -805,6 +823,7 @@
                 break;
 
             case SAVE_MODE_JOIN:
+                mStatus = STATUS_EDITING;
                 if (success) {
                     showJoinAggregateActivity(contactLookupUri);
                 }
@@ -938,6 +957,10 @@
      * {@link EntityDelta} under the currently edited {@link Contacts}.
      */
     private boolean doAddAction() {
+        if (mStatus != STATUS_EDITING) {
+            return false;
+        }
+
         // Adding is okay when missing state
         new AddContactTask(this).execute();
         return true;
@@ -948,12 +971,13 @@
      * user confirmation before continuing.
      */
     private boolean doDeleteAction() {
-        if (!hasValidState()) return false;
+        if (!hasValidState())
+            return false;
         int readOnlySourcesCnt = 0;
-	int writableSourcesCnt = 0;
+        int writableSourcesCnt = 0;
         Sources sources = Sources.getInstance(EditContactActivity.this);
         for (EntityDelta delta : mState) {
-	    final String accountType = delta.getValues().getAsString(RawContacts.ACCOUNT_TYPE);
+            final String accountType = delta.getValues().getAsString(RawContacts.ACCOUNT_TYPE);
             final ContactsSource contactsSource = sources.getInflatedSource(accountType,
                     ContactsSource.LEVEL_CONSTRAINTS);
             if (contactsSource != null && contactsSource.readOnly) {
@@ -961,18 +985,18 @@
             } else {
                 writableSourcesCnt += 1;
             }
-	}
+        }
 
         if (readOnlySourcesCnt > 0 && writableSourcesCnt > 0) {
-	    showDialog(DIALOG_CONFIRM_READONLY_DELETE);
-	} else if (readOnlySourcesCnt > 0 && writableSourcesCnt == 0) {
-	    showDialog(DIALOG_CONFIRM_READONLY_HIDE);
-	} else if (readOnlySourcesCnt == 0 && writableSourcesCnt > 1) {
-	    showDialog(DIALOG_CONFIRM_MULTIPLE_DELETE);
+            showDialog(DIALOG_CONFIRM_READONLY_DELETE);
+        } else if (readOnlySourcesCnt > 0 && writableSourcesCnt == 0) {
+            showDialog(DIALOG_CONFIRM_READONLY_HIDE);
+        } else if (readOnlySourcesCnt == 0 && writableSourcesCnt > 1) {
+            showDialog(DIALOG_CONFIRM_MULTIPLE_DELETE);
         } else {
-	    showDialog(DIALOG_CONFIRM_DELETE);
-	}
-	return true;
+            showDialog(DIALOG_CONFIRM_DELETE);
+        }
+        return true;
     }
 
     /**
diff --git a/src/com/android/contacts/ui/QuickContactWindow.java b/src/com/android/contacts/ui/QuickContactWindow.java
index 0d1eb2c..4ac787c 100644
--- a/src/com/android/contacts/ui/QuickContactWindow.java
+++ b/src/com/android/contacts/ui/QuickContactWindow.java
@@ -17,6 +17,7 @@
 package com.android.contacts.ui;
 
 import com.android.contacts.Collapser;
+import com.android.contacts.ContactPresenceIconUtil;
 import com.android.contacts.ContactsUtils;
 import com.android.contacts.R;
 import com.android.contacts.model.ContactsSource;
@@ -617,30 +618,6 @@
     }
 
     /**
-     * Find the presence icon for showing in summary header.
-     */
-    private Drawable getPresenceIcon(int status) {
-        int resId = -1;
-        switch (status) {
-            case StatusUpdates.AVAILABLE:
-                resId = android.R.drawable.presence_online;
-                break;
-            case StatusUpdates.IDLE:
-            case StatusUpdates.AWAY:
-                resId = android.R.drawable.presence_away;
-                break;
-            case StatusUpdates.DO_NOT_DISTURB:
-                resId = android.R.drawable.presence_busy;
-                break;
-        }
-        if (resId != -1) {
-            return mContext.getResources().getDrawable(resId);
-        } else {
-            return null;
-        }
-    }
-
-    /**
      * Find the QuickContact-specific presence icon for showing in chiclets.
      */
     private Drawable getTrackPresenceIcon(int status) {
@@ -1215,7 +1192,7 @@
             // Read contact information from last data row
             final String name = cursor.getString(DataQuery.DISPLAY_NAME);
             final int presence = cursor.getInt(DataQuery.CONTACT_PRESENCE);
-            final Drawable statusIcon = getPresenceIcon(presence);
+            final Drawable statusIcon = ContactPresenceIconUtil.getPresenceIcon(mContext, presence);
 
             setHeaderText(R.id.name, name);
             setHeaderImage(R.id.presence, statusIcon);