14cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann/*
2ef3f8f045ed4150caa64749742227acd0e6b85d8Daniel Lehmann * Copyright (C) 2010 The Android Open Source Project
34cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann *
44cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann * Licensed under the Apache License, Version 2.0 (the "License");
54cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann * you may not use this file except in compliance with the License.
64cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann * You may obtain a copy of the License at
74cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann *
84cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann *      http://www.apache.org/licenses/LICENSE-2.0
94cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann *
104cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann * Unless required by applicable law or agreed to in writing, software
114cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann * distributed under the License is distributed on an "AS IS" BASIS,
124cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann * See the License for the specific language governing permissions and
144cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann * limitations under the License
154cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann */
164cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann
174cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmannpackage com.android.contacts.activities;
184cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann
192eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport android.app.ActionBar;
2079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport android.app.Fragment;
2160be1a1e8639a58d16f58686f8a89747d6079cc7Daniel Lehmannimport android.content.ActivityNotFoundException;
22caf0bc759c4ef96dde5bb0a5256c1dcb51b6ccc4Dmitri Plotnikovimport android.content.ContentValues;
23078d08f5e497231cbe7fb520b5a4e42a398201a6Chiao Chengimport android.content.Context;
2418f104fa8c167a510b2cca3c15a43833c9a54c7cDaniel Lehmannimport android.content.Intent;
25c2687c3c38d8fb5f34ad6d8fb5c33e16f335183cDaniel Lehmannimport android.net.Uri;
264cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmannimport android.os.Bundle;
272eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport android.os.Handler;
28d6272412cdf3fdda90e835ec5b0cd1e15a0c97c9Daisuke Miyakawaimport android.text.TextUtils;
294cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmannimport android.util.Log;
304cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmannimport android.view.KeyEvent;
31942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuanimport android.view.Menu;
32942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuanimport android.view.MenuInflater;
33942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuanimport android.view.MenuItem;
342a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmannimport android.view.MenuItem.OnMenuItemClickListener;
352eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport android.view.View;
36d6272412cdf3fdda90e835ec5b0cd1e15a0c97c9Daisuke Miyakawaimport android.view.accessibility.AccessibilityEvent;
37d6272412cdf3fdda90e835ec5b0cd1e15a0c97c9Daisuke Miyakawaimport android.view.accessibility.AccessibilityManager;
38caf0bc759c4ef96dde5bb0a5256c1dcb51b6ccc4Dmitri Plotnikovimport android.widget.Toast;
39caf0bc759c4ef96dde5bb0a5256c1dcb51b6ccc4Dmitri Plotnikov
40e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.ContactSaveService;
41e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.ContactsActivity;
42e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.R;
43e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.detail.ContactDetailDisplayUtils;
44e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.detail.ContactDetailFragment;
45e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.detail.ContactDetailLayoutController;
46e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.detail.ContactLoaderFragment;
47e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.detail.ContactLoaderFragment.ContactLoaderFragmentListener;
48e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.interactions.ContactDeletionInteraction;
49cd321f65f1e50409812976380ad1f0fdb3fa35cbYorke Leeimport com.android.contacts.common.model.Contact;
50428f008513d1591cc08fcfe2cf0c9237fb313241Chiao Chengimport com.android.contacts.common.model.account.AccountWithDataSet;
51e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.util.PhoneCapabilityTester;
52e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Cheng
53caf0bc759c4ef96dde5bb0a5256c1dcb51b6ccc4Dmitri Plotnikovimport java.util.ArrayList;
544cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann
556f667b55687bf9193323802e8f3234f0ab254388Dmitri Plotnikovpublic class ContactDetailActivity extends ContactsActivity {
564cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann    private static final String TAG = "ContactDetailActivity";
574cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann
58851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu    private Contact mContactData;
59942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan    private Uri mLookupUri;
60942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan
6151f1071a1dc91dace0de73be1c5fbba4f091f054Katherine Kuan    private ContactDetailLayoutController mContactDetailLayoutController;
622eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    private ContactLoaderFragment mLoaderFragment;
632eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
642eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    private Handler mHandler = new Handler();
652eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
664cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann    @Override
676fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    protected void onCreate(Bundle savedState) {
684cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann        super.onCreate(savedState);
69c90c705db8b3665ba9c8d8ce4b8ab3a03e38ddc7Daniel Lehmann        if (PhoneCapabilityTester.isUsingTwoPanes(this)) {
70c90c705db8b3665ba9c8d8ce4b8ab3a03e38ddc7Daniel Lehmann            // This activity must not be shown. We have to select the contact in the
715e684a424e7036ba3d379221d1889b4dd7265021Dave Santoro            // PeopleActivity instead ==> Create a forward intent and finish
72c90c705db8b3665ba9c8d8ce4b8ab3a03e38ddc7Daniel Lehmann            final Intent originalIntent = getIntent();
73c90c705db8b3665ba9c8d8ce4b8ab3a03e38ddc7Daniel Lehmann            Intent intent = new Intent();
74c90c705db8b3665ba9c8d8ce4b8ab3a03e38ddc7Daniel Lehmann            intent.setAction(originalIntent.getAction());
75c90c705db8b3665ba9c8d8ce4b8ab3a03e38ddc7Daniel Lehmann            intent.setDataAndType(originalIntent.getData(), originalIntent.getType());
76d0414e5bd478444a9360c95258c267373f02554bDaniel Lehmann
77d0414e5bd478444a9360c95258c267373f02554bDaniel Lehmann            // If we are launched from the outside, we should create a new task, because the user
78d0414e5bd478444a9360c95258c267373f02554bDaniel Lehmann            // can freely navigate the app (this is different from phones, where only the UP button
79d0414e5bd478444a9360c95258c267373f02554bDaniel Lehmann            // kicks the user into the full app)
80d0414e5bd478444a9360c95258c267373f02554bDaniel Lehmann            if (shouldUpRecreateTask(intent)) {
81f879b9cc53e634caea7837873d8ac4d9ce411448Yorke Lee                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
82d0414e5bd478444a9360c95258c267373f02554bDaniel Lehmann            } else {
83d0414e5bd478444a9360c95258c267373f02554bDaniel Lehmann                intent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
84d0414e5bd478444a9360c95258c267373f02554bDaniel Lehmann                        Intent.FLAG_ACTIVITY_FORWARD_RESULT | Intent.FLAG_ACTIVITY_SINGLE_TOP |
85d0414e5bd478444a9360c95258c267373f02554bDaniel Lehmann                        Intent.FLAG_ACTIVITY_CLEAR_TOP);
86d0414e5bd478444a9360c95258c267373f02554bDaniel Lehmann            }
879856fcee477d04f51bdbcbfdf632876c6b8a1173Katherine Kuan            intent.setClass(this, PeopleActivity.class);
88c90c705db8b3665ba9c8d8ce4b8ab3a03e38ddc7Daniel Lehmann            startActivity(intent);
89c90c705db8b3665ba9c8d8ce4b8ab3a03e38ddc7Daniel Lehmann            finish();
90c90c705db8b3665ba9c8d8ce4b8ab3a03e38ddc7Daniel Lehmann            return;
91c90c705db8b3665ba9c8d8ce4b8ab3a03e38ddc7Daniel Lehmann        }
92c90c705db8b3665ba9c8d8ce4b8ab3a03e38ddc7Daniel Lehmann
9325a0282e968ebcdec6510bdb766ffba79b6fb8c4Daniel Lehmann        setContentView(R.layout.contact_detail_activity);
94db0d8669cd1ffaa45827edb65b2b0eecb27561f5Katherine Kuan
9551f1071a1dc91dace0de73be1c5fbba4f091f054Katherine Kuan        mContactDetailLayoutController = new ContactDetailLayoutController(this, savedState,
962f41fe6bcc8d055bf53ad070425552fad57dff21Daniel Lehmann                getFragmentManager(), null, findViewById(R.id.contact_detail_container),
9751f1071a1dc91dace0de73be1c5fbba4f091f054Katherine Kuan                mContactDetailFragmentListener);
98cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
9913fd2d99efcafa86c117855aafaf9fca445d38dbMakoto Onuki        // We want the UP affordance but no app icon.
10013fd2d99efcafa86c117855aafaf9fca445d38dbMakoto Onuki        // Setting HOME_AS_UP, SHOW_TITLE and clearing SHOW_HOME does the trick.
10113fd2d99efcafa86c117855aafaf9fca445d38dbMakoto Onuki        ActionBar actionBar = getActionBar();
1024ec198790236ab4be6bc5d73441215b684832618Isaac Katzenelson        if (actionBar != null) {
10313fd2d99efcafa86c117855aafaf9fca445d38dbMakoto Onuki            actionBar.setDisplayOptions(ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_TITLE,
10413fd2d99efcafa86c117855aafaf9fca445d38dbMakoto Onuki                    ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_TITLE
10513fd2d99efcafa86c117855aafaf9fca445d38dbMakoto Onuki                    | ActionBar.DISPLAY_SHOW_HOME);
10613fd2d99efcafa86c117855aafaf9fca445d38dbMakoto Onuki            actionBar.setTitle("");
1074ec198790236ab4be6bc5d73441215b684832618Isaac Katzenelson        }
1084ec198790236ab4be6bc5d73441215b684832618Isaac Katzenelson
109cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann        Log.i(TAG, getIntent().getData().toString());
1104cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann    }
1114cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann
11279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan    @Override
11379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan    public void onAttachFragment(Fragment fragment) {
114db0d8669cd1ffaa45827edb65b2b0eecb27561f5Katherine Kuan         if (fragment instanceof ContactLoaderFragment) {
1152eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            mLoaderFragment = (ContactLoaderFragment) fragment;
1162eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            mLoaderFragment.setListener(mLoaderFragmentListener);
1172eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            mLoaderFragment.loadUri(getIntent().getData());
11879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan        }
11979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan    }
12079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan
1214cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann    @Override
122942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan    public boolean onCreateOptionsMenu(Menu menu) {
123942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan        super.onCreateOptionsMenu(menu);
124942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan        MenuInflater inflater = getMenuInflater();
125942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan        inflater.inflate(R.menu.star, menu);
126942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan        return true;
127942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan    }
128942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan
129942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan    @Override
130942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan    public boolean onPrepareOptionsMenu(Menu menu) {
131c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann        final MenuItem starredMenuItem = menu.findItem(R.id.menu_star);
132c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann        starredMenuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() {
133942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan            @Override
134c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann            public boolean onMenuItemClick(MenuItem item) {
135942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan                // Toggle "starred" state
136942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan                // Make sure there is a contact
137942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan                if (mLookupUri != null) {
138c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann                    // Read the current starred value from the UI instead of using the last
139c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann                    // loaded state. This allows rapid tapping without writing the same
140c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann                    // value several times
141c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann                    final boolean isStarred = starredMenuItem.isChecked();
142c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann
143c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann                    // To improve responsiveness, swap out the picture (and tag) in the UI already
144c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann                    ContactDetailDisplayUtils.configureStarredMenuItem(starredMenuItem,
145c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann                            mContactData.isDirectoryEntry(), mContactData.isUserProfile(),
146c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann                            !isStarred);
147c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann
148c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann                    // Now perform the real save
149942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan                    Intent intent = ContactSaveService.createSetStarredIntent(
150c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann                            ContactDetailActivity.this, mLookupUri, !isStarred);
151942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan                    ContactDetailActivity.this.startService(intent);
152942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan                }
153c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann                return true;
154942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan            }
155942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan        });
156942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan        // If there is contact data, update the starred state
157942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan        if (mContactData != null) {
158c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann            ContactDetailDisplayUtils.configureStarredMenuItem(starredMenuItem,
159c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann                    mContactData.isDirectoryEntry(), mContactData.isUserProfile(),
160c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann                    mContactData.getStarred());
161942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan        }
162942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan        return true;
163942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan    }
164942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan
165942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan    @Override
1664cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann    public boolean onKeyDown(int keyCode, KeyEvent event) {
16758fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        // First check if the {@link ContactLoaderFragment} can handle the key
168f6141f1bc0116dd5c9dc399567502d74300326b6Katherine Kuan        if (mLoaderFragment != null && mLoaderFragment.handleKeyDown(keyCode)) return true;
16958fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan
17058fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        // Otherwise find the correct fragment to handle the event
17151f1071a1dc91dace0de73be1c5fbba4f091f054Katherine Kuan        FragmentKeyListener mCurrentFragment = mContactDetailLayoutController.getCurrentPage();
172f6141f1bc0116dd5c9dc399567502d74300326b6Katherine Kuan        if (mCurrentFragment != null && mCurrentFragment.handleKeyDown(keyCode)) return true;
1734cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann
17458fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        // In the last case, give the key event to the superclass.
1754cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann        return super.onKeyDown(keyCode, event);
1764cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann    }
17718f104fa8c167a510b2cca3c15a43833c9a54c7cDaniel Lehmann
1782eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    @Override
1792eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    protected void onSaveInstanceState(Bundle outState) {
1802eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        super.onSaveInstanceState(outState);
18151f1071a1dc91dace0de73be1c5fbba4f091f054Katherine Kuan        if (mContactDetailLayoutController != null) {
18251f1071a1dc91dace0de73be1c5fbba4f091f054Katherine Kuan            mContactDetailLayoutController.onSaveInstanceState(outState);
18351f1071a1dc91dace0de73be1c5fbba4f091f054Katherine Kuan        }
1842eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    }
18518f104fa8c167a510b2cca3c15a43833c9a54c7cDaniel Lehmann
1862eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    private final ContactLoaderFragmentListener mLoaderFragmentListener =
1872eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            new ContactLoaderFragmentListener() {
18869e7fec6dd8a3d24054863c6c648512577fce35cDaniel Lehmann        @Override
18958fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        public void onContactNotFound() {
19058fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan            finish();
19158fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        }
19258fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan
19358fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        @Override
194851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu        public void onDetailsLoaded(final Contact result) {
195942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan            if (result == null) {
196942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan                return;
197942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan            }
1982eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            // Since {@link FragmentTransaction}s cannot be done in the onLoadFinished() of the
1992eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            // {@link LoaderCallbacks}, then post this {@link Runnable} to the {@link Handler}
2002eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            // on the main thread to execute later.
2012eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            mHandler.post(new Runnable() {
2022eb969cc399d87b659a45568fa951d394c216917Katherine Kuan                @Override
2032eb969cc399d87b659a45568fa951d394c216917Katherine Kuan                public void run() {
204bed71bedbaae4d6b26b2b64db476bffa710753e5Makoto Onuki                    // If the activity is destroyed (or will be destroyed soon), don't update the UI
205bed71bedbaae4d6b26b2b64db476bffa710753e5Makoto Onuki                    if (isFinishing()) {
206bed71bedbaae4d6b26b2b64db476bffa710753e5Makoto Onuki                        return;
207bed71bedbaae4d6b26b2b64db476bffa710753e5Makoto Onuki                    }
2082eb969cc399d87b659a45568fa951d394c216917Katherine Kuan                    mContactData = result;
2092eb969cc399d87b659a45568fa951d394c216917Katherine Kuan                    mLookupUri = result.getLookupUri();
2102eb969cc399d87b659a45568fa951d394c216917Katherine Kuan                    invalidateOptionsMenu();
2112eb969cc399d87b659a45568fa951d394c216917Katherine Kuan                    setupTitle();
21251f1071a1dc91dace0de73be1c5fbba4f091f054Katherine Kuan                    mContactDetailLayoutController.setContactData(mContactData);
2132eb969cc399d87b659a45568fa951d394c216917Katherine Kuan                }
2142eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            });
2152eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        }
21658fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan
21758fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        @Override
21858fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        public void onEditRequested(Uri contactLookupUri) {
2195c3a0a1440625fab859aab420cb08bc0276358a0Katherine Kuan            Intent intent = new Intent(Intent.ACTION_EDIT, contactLookupUri);
2205c3a0a1440625fab859aab420cb08bc0276358a0Katherine Kuan            intent.putExtra(
2215c3a0a1440625fab859aab420cb08bc0276358a0Katherine Kuan                    ContactEditorActivity.INTENT_KEY_FINISH_ACTIVITY_ON_SAVE_COMPLETED, true);
2225c3a0a1440625fab859aab420cb08bc0276358a0Katherine Kuan            // Don't finish the detail activity after launching the editor because when the
2235c3a0a1440625fab859aab420cb08bc0276358a0Katherine Kuan            // editor is done, we will still want to show the updated contact details using
2245c3a0a1440625fab859aab420cb08bc0276358a0Katherine Kuan            // this activity.
2255c3a0a1440625fab859aab420cb08bc0276358a0Katherine Kuan            startActivity(intent);
22658fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        }
22758fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan
22858fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        @Override
22958fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        public void onDeleteRequested(Uri contactUri) {
23058fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan            ContactDeletionInteraction.start(ContactDetailActivity.this, contactUri, true);
23158fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        }
2322eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    };
2332eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
2342eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    /**
2352eb969cc399d87b659a45568fa951d394c216917Katherine Kuan     * Setup the activity title and subtitle with contact name and company.
2362eb969cc399d87b659a45568fa951d394c216917Katherine Kuan     */
2372eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    private void setupTitle() {
2382eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        CharSequence displayName = ContactDetailDisplayUtils.getDisplayName(this, mContactData);
2392eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        String company =  ContactDetailDisplayUtils.getCompany(this, mContactData);
2402eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
2412eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        ActionBar actionBar = getActionBar();
2422eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        actionBar.setTitle(displayName);
2432eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        actionBar.setSubtitle(company);
244d6272412cdf3fdda90e835ec5b0cd1e15a0c97c9Daisuke Miyakawa
245e38ac4f95f032e065594109b14c9c196704437bdChiao Cheng        final StringBuilder talkback = new StringBuilder();
246078d08f5e497231cbe7fb520b5a4e42a398201a6Chiao Cheng        if (!TextUtils.isEmpty(displayName)) {
247e38ac4f95f032e065594109b14c9c196704437bdChiao Cheng            talkback.append(displayName);
248e38ac4f95f032e065594109b14c9c196704437bdChiao Cheng        }
249e38ac4f95f032e065594109b14c9c196704437bdChiao Cheng        if (!TextUtils.isEmpty(company)) {
250e38ac4f95f032e065594109b14c9c196704437bdChiao Cheng            if (talkback.length() != 0) {
251e38ac4f95f032e065594109b14c9c196704437bdChiao Cheng                talkback.append(", ");
252e38ac4f95f032e065594109b14c9c196704437bdChiao Cheng            }
253e38ac4f95f032e065594109b14c9c196704437bdChiao Cheng            talkback.append(company);
254e38ac4f95f032e065594109b14c9c196704437bdChiao Cheng        }
255e38ac4f95f032e065594109b14c9c196704437bdChiao Cheng
256e38ac4f95f032e065594109b14c9c196704437bdChiao Cheng        if (talkback.length() != 0) {
257078d08f5e497231cbe7fb520b5a4e42a398201a6Chiao Cheng            AccessibilityManager accessibilityManager =
258078d08f5e497231cbe7fb520b5a4e42a398201a6Chiao Cheng                    (AccessibilityManager) this.getSystemService(Context.ACCESSIBILITY_SERVICE);
259078d08f5e497231cbe7fb520b5a4e42a398201a6Chiao Cheng            if (accessibilityManager.isEnabled()) {
260078d08f5e497231cbe7fb520b5a4e42a398201a6Chiao Cheng                View decorView = getWindow().getDecorView();
261e38ac4f95f032e065594109b14c9c196704437bdChiao Cheng                decorView.setContentDescription(talkback);
262078d08f5e497231cbe7fb520b5a4e42a398201a6Chiao Cheng                decorView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
263078d08f5e497231cbe7fb520b5a4e42a398201a6Chiao Cheng            }
264d6272412cdf3fdda90e835ec5b0cd1e15a0c97c9Daisuke Miyakawa        }
2652eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    }
2662eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
26751f1071a1dc91dace0de73be1c5fbba4f091f054Katherine Kuan    private final ContactDetailFragment.Listener mContactDetailFragmentListener =
2682eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            new ContactDetailFragment.Listener() {
2692eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        @Override
270cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann        public void onItemClicked(Intent intent) {
27108bcf715d5ea7f07ce18a282d9850ac70552ca9dKatherine Kuan            if (intent == null) {
27208bcf715d5ea7f07ce18a282d9850ac70552ca9dKatherine Kuan                return;
27308bcf715d5ea7f07ce18a282d9850ac70552ca9dKatherine Kuan            }
27460be1a1e8639a58d16f58686f8a89747d6079cc7Daniel Lehmann            try {
27560be1a1e8639a58d16f58686f8a89747d6079cc7Daniel Lehmann                startActivity(intent);
27660be1a1e8639a58d16f58686f8a89747d6079cc7Daniel Lehmann            } catch (ActivityNotFoundException e) {
27760be1a1e8639a58d16f58686f8a89747d6079cc7Daniel Lehmann                Log.e(TAG, "No activity found for intent: " + intent);
27860be1a1e8639a58d16f58686f8a89747d6079cc7Daniel Lehmann            }
27918f104fa8c167a510b2cca3c15a43833c9a54c7cDaniel Lehmann        }
280cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
28169e7fec6dd8a3d24054863c6c648512577fce35cDaniel Lehmann        @Override
282caf0bc759c4ef96dde5bb0a5256c1dcb51b6ccc4Dmitri Plotnikov        public void onCreateRawContactRequested(
2832b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro                ArrayList<ContentValues> values, AccountWithDataSet account) {
284caf0bc759c4ef96dde5bb0a5256c1dcb51b6ccc4Dmitri Plotnikov            Toast.makeText(ContactDetailActivity.this, R.string.toast_making_personal_copy,
285caf0bc759c4ef96dde5bb0a5256c1dcb51b6ccc4Dmitri Plotnikov                    Toast.LENGTH_LONG).show();
286caf0bc759c4ef96dde5bb0a5256c1dcb51b6ccc4Dmitri Plotnikov            Intent serviceIntent = ContactSaveService.createNewRawContactIntent(
2879d730dd9d9efe125c9102b298f897577157ffecdDmitri Plotnikov                    ContactDetailActivity.this, values, account,
2889d730dd9d9efe125c9102b298f897577157ffecdDmitri Plotnikov                    ContactDetailActivity.class, Intent.ACTION_VIEW);
289caf0bc759c4ef96dde5bb0a5256c1dcb51b6ccc4Dmitri Plotnikov            startService(serviceIntent);
290caf0bc759c4ef96dde5bb0a5256c1dcb51b6ccc4Dmitri Plotnikov
291caf0bc759c4ef96dde5bb0a5256c1dcb51b6ccc4Dmitri Plotnikov        }
292cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann    };
29379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan
29479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan    /**
29579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan     * This interface should be implemented by {@link Fragment}s within this
29679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan     * activity so that the activity can determine whether the currently
29779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan     * displayed view is handling the key event or not.
29879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan     */
29979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan    public interface FragmentKeyListener {
30079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan        /**
30179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan         * Returns true if the key down event will be handled by the implementing class, or false
30279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan         * otherwise.
30379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan         */
30479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan        public boolean handleKeyDown(int keyCode);
30579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan    }
3064cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann}
307