Implementing "app up" behavior

Bug: 3237656
Change-Id: Ief60f257ea59a1da8ad9e3fcabf292ee4f7506c3
diff --git a/src/com/android/contacts/activities/ContactEditorActivity.java b/src/com/android/contacts/activities/ContactEditorActivity.java
index 2f9a514..f68782a 100644
--- a/src/com/android/contacts/activities/ContactEditorActivity.java
+++ b/src/com/android/contacts/activities/ContactEditorActivity.java
@@ -21,7 +21,9 @@
 import com.android.contacts.interactions.ContactDeletionInteraction;
 import com.android.contacts.util.DialogManager;
 import com.android.contacts.views.editor.ContactEditorFragment;
+import com.android.contacts.views.editor.ContactEditorFragment.SaveMode;
 
+import android.app.ActionBar;
 import android.app.Activity;
 import android.app.Dialog;
 import android.content.ContentValues;
@@ -30,6 +32,7 @@
 import android.os.Bundle;
 import android.provider.ContactsContract;
 import android.util.Log;
+import android.view.MenuItem;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.widget.Button;
@@ -54,6 +57,13 @@
 
         setContentView(R.layout.contact_editor_activity);
 
+        // This Activity will always fall back to the "top" Contacts screen when touched on the
+        // app up icon, regardless of launch context.
+        ActionBar actionBar = getActionBar();
+        if (actionBar != null) {
+            actionBar.setDisplayOptions(ActionBar.DISPLAY_HOME_AS_UP, ActionBar.DISPLAY_HOME_AS_UP);
+        }
+
         mFragment = (ContactEditorFragment) getFragmentManager().findFragmentById(
                 R.id.contact_editor_fragment);
         mFragment.setListener(mFragmentListener);
@@ -67,7 +77,7 @@
         if (mDoneButton != null) mDoneButton.setOnClickListener(new OnClickListener() {
             @Override
             public void onClick(View v) {
-                mFragment.save(true);
+                mFragment.save(SaveMode.CLOSE);
             }
         });
         if (mRevertButton != null) mRevertButton.setOnClickListener(new OnClickListener() {
@@ -115,7 +125,18 @@
 
     @Override
     public void onBackPressed() {
-        mFragment.save(true);
+        mFragment.save(SaveMode.CLOSE);
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch (item.getItemId()) {
+            case android.R.id.home: {
+                mFragment.save(SaveMode.HOME);
+                return true;
+            }
+        }
+        return false;
     }
 
     private final ContactEditorFragment.Listener mFragmentListener =
@@ -126,8 +147,14 @@
         }
 
         @Override
-        public void onSaveFinished(int resultCode, Intent resultIntent) {
+        public void onSaveFinished(int resultCode, Intent resultIntent, boolean navigateHome) {
             setResult(resultCode, resultIntent);
+            if (navigateHome) {
+                Intent intent = new Intent(ContactEditorActivity.this,
+                        ContactBrowserActivity.class);
+                intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+                startActivity(intent);
+            }
             finish();
         }
 
diff --git a/src/com/android/contacts/preference/ContactsPreferenceActivity.java b/src/com/android/contacts/preference/ContactsPreferenceActivity.java
index d4b0ab0..7f7b750 100644
--- a/src/com/android/contacts/preference/ContactsPreferenceActivity.java
+++ b/src/com/android/contacts/preference/ContactsPreferenceActivity.java
@@ -17,9 +17,14 @@
 package com.android.contacts.preference;
 
 import com.android.contacts.R;
+import com.android.contacts.activities.ContactBrowserActivity;
 
+import android.app.ActionBar;
 import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
 import android.preference.PreferenceActivity;
+import android.view.MenuItem;
 
 import java.util.List;
 
@@ -28,6 +33,18 @@
  */
 public final class ContactsPreferenceActivity extends PreferenceActivity {
 
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        // This Activity will always fall back to the "top" Contacts screen when touched on the
+        // app up icon, regardless of launch context.
+        ActionBar actionBar = getActionBar();
+        if (actionBar != null) {
+            actionBar.setDisplayOptions(ActionBar.DISPLAY_HOME_AS_UP, ActionBar.DISPLAY_HOME_AS_UP);
+        }
+    }
+
     /**
      * Populate the activity with the top-level headers.
      */
@@ -44,4 +61,18 @@
         return !context.getResources().getBoolean(R.bool.config_sort_order_user_changeable)
                 && !context.getResources().getBoolean(R.bool.config_display_order_user_changeable);
     }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch (item.getItemId()) {
+            case android.R.id.home: {
+                Intent intent = new Intent(this, ContactBrowserActivity.class);
+                intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+                startActivity(intent);
+                finish();
+                return true;
+            }
+        }
+        return false;
+    }
 }
diff --git a/src/com/android/contacts/views/editor/ContactEditorFragment.java b/src/com/android/contacts/views/editor/ContactEditorFragment.java
index 26e1745..e117dc1 100644
--- a/src/com/android/contacts/views/editor/ContactEditorFragment.java
+++ b/src/com/android/contacts/views/editor/ContactEditorFragment.java
@@ -128,7 +128,7 @@
     /**
      * Modes that specify what the AsyncTask has to perform after saving
      */
-    private interface SaveMode {
+    public interface SaveMode {
         /**
          * Close the editor after saving
          */
@@ -148,6 +148,11 @@
          * Join another contact after saving
          */
         public static final int JOIN = 3;
+
+        /**
+         * Navigate to Contacts Home activity after saving.
+         */
+        public static final int HOME = 4;
     }
 
     private interface Status {
@@ -245,7 +250,7 @@
         }
         // If anything was left unsaved, save it now but keep the editor open.
         if (!getActivity().isChangingConfigurations() && mStatus == Status.EDITING) {
-            save(false);
+            save(SaveMode.RELOAD);
         }
     }
 
@@ -553,7 +558,7 @@
     public boolean onOptionsItemSelected(MenuItem item) {
         switch (item.getItemId()) {
             case R.id.menu_done:
-                return doSaveAction(SaveMode.CLOSE);
+                return save(SaveMode.CLOSE);
             case R.id.menu_discard:
                 return doRevertAction();
             case R.id.menu_delete:
@@ -610,7 +615,7 @@
             }
         }
 
-        return doSaveAction(SaveMode.JOIN);
+        return save(SaveMode.JOIN);
     }
 
     /**
@@ -694,7 +699,7 @@
      * Saves or creates the contact based on the mode, and if successful
      * finishes the activity.
      */
-    private boolean doSaveAction(int saveMode) {
+    public boolean save(int saveMode) {
         if (!hasValidState()) {
             return false;
         }
@@ -721,14 +726,6 @@
         return true;
     }
 
-    /**
-     * Asynchronously saves the changes made by the user. This can be called even if nothing
-     * has changed
-     */
-    public void save(boolean closeAfterSave) {
-        doSaveAction(closeAfterSave ? SaveMode.CLOSE : SaveMode.RELOAD);
-    }
-
     private boolean doRevertAction() {
         // When this Fragment is closed we don't want it to auto-save
         mStatus = Status.CLOSING;
@@ -745,6 +742,7 @@
         Log.d(TAG, "onSaveCompleted(" + success + ", " + saveMode + ", " + contactLookupUri);
         switch (saveMode) {
             case SaveMode.CLOSE:
+            case SaveMode.HOME:
                 final Intent resultIntent;
                 final int resultCode;
                 if (success && contactLookupUri != null) {
@@ -774,7 +772,8 @@
                 }
                 // It is already saved, so prevent that it is saved again
                 mStatus = Status.CLOSING;
-                if (mListener != null) mListener.onSaveFinished(resultCode, resultIntent);
+                if (mListener != null) mListener.onSaveFinished(resultCode, resultIntent,
+                        saveMode == SaveMode.HOME);
                 break;
             case SaveMode.RELOAD:
                 if (success && contactLookupUri != null) {
@@ -880,7 +879,7 @@
         /**
          * Contact was saved and the Fragment can now be closed safely.
          */
-        void onSaveFinished(int resultCode, Intent resultIntent);
+        void onSaveFinished(int resultCode, Intent resultIntent, boolean navigateHome);
 
         /**
          * User decided to delete the contact.
@@ -1238,7 +1237,7 @@
      */
     protected void doJoinSuggestedContact(long[] rawContactIds) {
         mState.setJoinWithRawContacts(rawContactIds);
-        doSaveAction(SaveMode.RELOAD);
+        save(SaveMode.RELOAD);
     }
 
     @Override
@@ -1618,7 +1617,7 @@
     @Override
     public void onSplitContactConfirmed() {
         mState.markRawContactsForSplitting();
-        doSaveAction(SaveMode.SPLIT);
+        save(SaveMode.SPLIT);
     }
 
     /**