1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.contacts.activities;
18
19import android.app.Fragment;
20import android.content.ActivityNotFoundException;
21import android.content.Intent;
22import android.graphics.PorterDuff;
23import android.graphics.drawable.Drawable;
24import android.net.Uri;
25import android.os.Bundle;
26import android.provider.ContactsContract.Contacts;
27import android.support.v4.content.ContextCompat;
28import android.support.v7.widget.Toolbar;
29import android.text.TextUtils;
30import android.util.Log;
31import android.view.Menu;
32import android.view.MenuInflater;
33import android.view.MenuItem;
34import android.view.View;
35import android.view.View.OnClickListener;
36import android.view.View.OnFocusChangeListener;
37import android.widget.TextView;
38import android.widget.Toast;
39
40import com.android.contacts.AppCompatContactsActivity;
41import com.android.contacts.R;
42import com.android.contacts.editor.EditorIntents;
43import com.android.contacts.list.ContactEntryListFragment;
44import com.android.contacts.list.ContactPickerFragment;
45import com.android.contacts.list.ContactsIntentResolver;
46import com.android.contacts.list.ContactsRequest;
47import com.android.contacts.list.DirectoryListLoader;
48import com.android.contacts.list.EmailAddressPickerFragment;
49import com.android.contacts.list.GroupMemberPickerFragment;
50import com.android.contacts.list.JoinContactListFragment;
51import com.android.contacts.list.LegacyPhoneNumberPickerFragment;
52import com.android.contacts.list.MultiSelectContactsListFragment;
53import com.android.contacts.list.MultiSelectContactsListFragment.OnCheckBoxListActionListener;
54import com.android.contacts.list.MultiSelectEmailAddressesListFragment;
55import com.android.contacts.list.MultiSelectPhoneNumbersListFragment;
56import com.android.contacts.list.OnContactPickerActionListener;
57import com.android.contacts.list.OnEmailAddressPickerActionListener;
58import com.android.contacts.list.OnPhoneNumberPickerActionListener;
59import com.android.contacts.list.OnPostalAddressPickerActionListener;
60import com.android.contacts.list.PhoneNumberPickerFragment;
61import com.android.contacts.list.PostalAddressPickerFragment;
62import com.android.contacts.list.UiIntentActions;
63import com.android.contacts.logging.ListEvent;
64import com.android.contacts.util.ImplicitIntentsUtil;
65import com.android.contacts.util.ViewUtil;
66
67import java.util.ArrayList;
68
69/**
70 * Displays a list of contacts (or phone numbers or postal addresses) for the
71 * purposes of selecting one.
72 */
73public class ContactSelectionActivity extends AppCompatContactsActivity implements
74        View.OnCreateContextMenuListener, ActionBarAdapter.Listener, OnClickListener,
75        OnFocusChangeListener, OnCheckBoxListActionListener {
76    private static final String TAG = "ContactSelection";
77
78    private static final String KEY_ACTION_CODE = "actionCode";
79    private static final String KEY_SEARCH_MODE = "searchMode";
80    private static final int DEFAULT_DIRECTORY_RESULT_LIMIT = 20;
81
82    private ContactsIntentResolver mIntentResolver;
83    protected ContactEntryListFragment<?> mListFragment;
84
85    private int mActionCode = -1;
86    private boolean mIsSearchMode;
87    private boolean mIsSearchSupported;
88
89    private ContactsRequest mRequest;
90
91    private ActionBarAdapter mActionBarAdapter;
92    private Toolbar mToolbar;
93
94    public ContactSelectionActivity() {
95        mIntentResolver = new ContactsIntentResolver(this);
96    }
97
98    @Override
99    public void onAttachFragment(Fragment fragment) {
100        if (fragment instanceof ContactEntryListFragment<?>) {
101            mListFragment = (ContactEntryListFragment<?>) fragment;
102            setupActionListener();
103        }
104    }
105
106    @Override
107    protected void onCreate(Bundle savedState) {
108        super.onCreate(savedState);
109
110        RequestPermissionsActivity.startPermissionActivityIfNeeded(this);
111
112        if (savedState != null) {
113            mActionCode = savedState.getInt(KEY_ACTION_CODE);
114            mIsSearchMode = savedState.getBoolean(KEY_SEARCH_MODE);
115        }
116
117        // Extract relevant information from the intent
118        mRequest = mIntentResolver.resolveIntent(getIntent());
119        if (!mRequest.isValid()) {
120            setResult(RESULT_CANCELED);
121            finish();
122            return;
123        }
124
125        setContentView(R.layout.contact_picker);
126
127        if (mActionCode != mRequest.getActionCode()) {
128            mActionCode = mRequest.getActionCode();
129            configureListFragment();
130        }
131
132        prepareSearchViewAndActionBar(savedState);
133        configureActivityTitle();
134    }
135
136    public boolean isSelectionMode() {
137        return mActionBarAdapter.isSelectionMode();
138    }
139
140    public boolean isSearchMode() {
141        return mActionBarAdapter.isSearchMode();
142    }
143
144    private void prepareSearchViewAndActionBar(Bundle savedState) {
145        mToolbar = getView(R.id.toolbar);
146        setSupportActionBar(mToolbar);
147
148        // Add a shadow under the toolbar.
149        ViewUtil.addRectangularOutlineProvider(findViewById(R.id.toolbar_parent), getResources());
150
151        mActionBarAdapter = new ActionBarAdapter(this, this, getSupportActionBar(), mToolbar,
152                R.string.enter_contact_name);
153        mActionBarAdapter.setShowHomeIcon(true);
154        mActionBarAdapter.setShowHomeAsUp(true);
155        mActionBarAdapter.initialize(savedState, mRequest);
156
157        // Postal address pickers (and legacy pickers) don't support search, so just show
158        // "HomeAsUp" button and title.
159        mIsSearchSupported = mRequest.getActionCode() != ContactsRequest.ACTION_PICK_POSTAL
160                && mRequest.getActionCode() != ContactsRequest.ACTION_PICK_EMAILS
161                && mRequest.getActionCode() != ContactsRequest.ACTION_PICK_PHONES
162                && !mRequest.isLegacyCompatibilityMode();
163        configureSearchMode();
164    }
165
166    private void configureSearchMode() {
167        mActionBarAdapter.setSearchMode(mIsSearchMode);
168        invalidateOptionsMenu();
169    }
170
171    @Override
172    public boolean onOptionsItemSelected(MenuItem item) {
173        final int id = item.getItemId();
174        if (id == android.R.id.home) {// Go back to previous screen, intending "cancel"
175            setResult(RESULT_CANCELED);
176            onBackPressed();
177        } else if (id == R.id.menu_search) {
178            mIsSearchMode = !mIsSearchMode;
179            configureSearchMode();
180        } else {
181            return super.onOptionsItemSelected(item);
182        }
183        return true;
184    }
185
186    @Override
187    protected void onSaveInstanceState(Bundle outState) {
188        super.onSaveInstanceState(outState);
189        outState.putInt(KEY_ACTION_CODE, mActionCode);
190        outState.putBoolean(KEY_SEARCH_MODE, mIsSearchMode);
191        if (mActionBarAdapter != null) {
192            mActionBarAdapter.onSaveInstanceState(outState);
193        }
194    }
195
196    private void configureActivityTitle() {
197        if (!TextUtils.isEmpty(mRequest.getActivityTitle())) {
198            getSupportActionBar().setTitle(mRequest.getActivityTitle());
199            return;
200        }
201        int titleResId = -1;
202        int actionCode = mRequest.getActionCode();
203        switch (actionCode) {
204            case ContactsRequest.ACTION_INSERT_OR_EDIT_CONTACT: {
205                titleResId = R.string.contactInsertOrEditActivityTitle;
206                break;
207            }
208            case ContactsRequest.ACTION_PICK_CONTACT: {
209                titleResId = R.string.contactPickerActivityTitle;
210                break;
211            }
212            case ContactsRequest.ACTION_PICK_OR_CREATE_CONTACT: {
213                titleResId = R.string.contactPickerActivityTitle;
214                break;
215            }
216            case ContactsRequest.ACTION_CREATE_SHORTCUT_CONTACT: {
217                titleResId = R.string.shortcutActivityTitle;
218                break;
219            }
220            case ContactsRequest.ACTION_PICK_PHONE: {
221                titleResId = R.string.contactPickerActivityTitle;
222                break;
223            }
224            case ContactsRequest.ACTION_PICK_EMAIL: {
225                titleResId = R.string.contactPickerActivityTitle;
226                break;
227            }
228            case ContactsRequest.ACTION_PICK_PHONES: {
229                titleResId = R.string.pickerSelectContactsActivityTitle;
230                break;
231            }
232            case ContactsRequest.ACTION_PICK_EMAILS: {
233                titleResId = R.string.pickerSelectContactsActivityTitle;
234                break;
235            }
236            case ContactsRequest.ACTION_CREATE_SHORTCUT_CALL: {
237                titleResId = R.string.shortcutActivityTitle;
238                break;
239            }
240            case ContactsRequest.ACTION_CREATE_SHORTCUT_SMS: {
241                titleResId = R.string.shortcutActivityTitle;
242                break;
243            }
244            case ContactsRequest.ACTION_PICK_POSTAL: {
245                titleResId = R.string.contactPickerActivityTitle;
246                break;
247            }
248            case ContactsRequest.ACTION_PICK_JOIN: {
249                titleResId = R.string.titleJoinContactDataWith;
250                break;
251            }
252            case ContactsRequest.ACTION_PICK_GROUP_MEMBERS: {
253                titleResId = R.string.groupMemberPickerActivityTitle;
254                break;
255            }
256        }
257        if (titleResId > 0) {
258            getSupportActionBar().setTitle(titleResId);
259        }
260    }
261
262    /**
263     * Creates the fragment based on the current request.
264     */
265    public void configureListFragment() {
266        switch (mActionCode) {
267            case ContactsRequest.ACTION_INSERT_OR_EDIT_CONTACT: {
268                ContactPickerFragment fragment = new ContactPickerFragment();
269                fragment.setEditMode(true);
270                fragment.setDirectorySearchMode(DirectoryListLoader.SEARCH_MODE_NONE);
271                fragment.setCreateContactEnabled(!mRequest.isSearchMode());
272                fragment.setListType(ListEvent.ListType.PICK_CONTACT);
273                mListFragment = fragment;
274                break;
275            }
276
277            case ContactsRequest.ACTION_DEFAULT:
278            case ContactsRequest.ACTION_PICK_CONTACT: {
279                ContactPickerFragment fragment = new ContactPickerFragment();
280                fragment.setIncludeFavorites(mRequest.shouldIncludeFavorites());
281                fragment.setListType(ListEvent.ListType.PICK_CONTACT);
282                mListFragment = fragment;
283                break;
284            }
285
286            case ContactsRequest.ACTION_PICK_OR_CREATE_CONTACT: {
287                ContactPickerFragment fragment = new ContactPickerFragment();
288                fragment.setCreateContactEnabled(!mRequest.isSearchMode());
289                fragment.setListType(ListEvent.ListType.PICK_CONTACT);
290                mListFragment = fragment;
291                break;
292            }
293
294            case ContactsRequest.ACTION_CREATE_SHORTCUT_CONTACT: {
295                ContactPickerFragment fragment = new ContactPickerFragment();
296                fragment.setShortcutRequested(true);
297                fragment.setListType(ListEvent.ListType.PICK_CONTACT_FOR_SHORTCUT);
298                mListFragment = fragment;
299                break;
300            }
301
302            case ContactsRequest.ACTION_PICK_PHONE: {
303                PhoneNumberPickerFragment fragment = getPhoneNumberPickerFragment(mRequest);
304                fragment.setListType(ListEvent.ListType.PICK_PHONE);
305                mListFragment = fragment;
306                break;
307            }
308
309            case ContactsRequest.ACTION_PICK_EMAIL: {
310                mListFragment = new EmailAddressPickerFragment();
311                mListFragment.setListType(ListEvent.ListType.PICK_EMAIL);
312                break;
313            }
314
315            case ContactsRequest.ACTION_PICK_PHONES: {
316                mListFragment = new MultiSelectPhoneNumbersListFragment();
317                mListFragment.setArguments(getIntent().getExtras());
318                break;
319            }
320
321            case ContactsRequest.ACTION_PICK_EMAILS: {
322                mListFragment = new MultiSelectEmailAddressesListFragment();
323                mListFragment.setArguments(getIntent().getExtras());
324                break;
325            }
326            case ContactsRequest.ACTION_CREATE_SHORTCUT_CALL: {
327                PhoneNumberPickerFragment fragment = getPhoneNumberPickerFragment(mRequest);
328                fragment.setShortcutAction(Intent.ACTION_CALL);
329                fragment.setListType(ListEvent.ListType.PICK_CONTACT_FOR_SHORTCUT);
330                mListFragment = fragment;
331                break;
332            }
333
334            case ContactsRequest.ACTION_CREATE_SHORTCUT_SMS: {
335                PhoneNumberPickerFragment fragment = getPhoneNumberPickerFragment(mRequest);
336                fragment.setShortcutAction(Intent.ACTION_SENDTO);
337                fragment.setListType(ListEvent.ListType.PICK_CONTACT_FOR_SHORTCUT);
338                mListFragment = fragment;
339                break;
340            }
341
342            case ContactsRequest.ACTION_PICK_POSTAL: {
343                PostalAddressPickerFragment fragment = new PostalAddressPickerFragment();
344                fragment.setListType(ListEvent.ListType.PICK_POSTAL);
345                mListFragment = fragment;
346                break;
347            }
348
349            case ContactsRequest.ACTION_PICK_JOIN: {
350                JoinContactListFragment joinFragment = new JoinContactListFragment();
351                joinFragment.setTargetContactId(getTargetContactId());
352                joinFragment.setListType(ListEvent.ListType.PICK_JOIN);
353                mListFragment = joinFragment;
354                break;
355            }
356
357            case ContactsRequest.ACTION_PICK_GROUP_MEMBERS: {
358                final String accountName = getIntent().getStringExtra(
359                        UiIntentActions.GROUP_ACCOUNT_NAME);
360                final String accountType = getIntent().getStringExtra(
361                        UiIntentActions.GROUP_ACCOUNT_TYPE);
362                final String accountDataSet = getIntent().getStringExtra(
363                        UiIntentActions.GROUP_ACCOUNT_DATA_SET);
364                final ArrayList<String> contactIds = getIntent().getStringArrayListExtra(
365                        UiIntentActions.GROUP_CONTACT_IDS);
366                mListFragment = GroupMemberPickerFragment.newInstance(
367                        accountName, accountType, accountDataSet, contactIds);
368                mListFragment.setListType(ListEvent.ListType.PICK_GROUP_MEMBERS);
369                break;
370            }
371
372            default:
373                throw new IllegalStateException("Invalid action code: " + mActionCode);
374        }
375
376        // Setting compatibility is no longer needed for PhoneNumberPickerFragment since that logic
377        // has been separated into LegacyPhoneNumberPickerFragment.  But we still need to set
378        // compatibility for other fragments.
379        mListFragment.setLegacyCompatibilityMode(mRequest.isLegacyCompatibilityMode());
380        mListFragment.setDirectoryResultLimit(DEFAULT_DIRECTORY_RESULT_LIMIT);
381
382        getFragmentManager().beginTransaction()
383                .replace(R.id.list_container, mListFragment)
384                .commitAllowingStateLoss();
385    }
386
387    private PhoneNumberPickerFragment getPhoneNumberPickerFragment(ContactsRequest request) {
388        if (mRequest.isLegacyCompatibilityMode()) {
389            return new LegacyPhoneNumberPickerFragment();
390        } else {
391            return new PhoneNumberPickerFragment();
392        }
393    }
394
395    public void setupActionListener() {
396        if (mListFragment instanceof ContactPickerFragment) {
397            ((ContactPickerFragment) mListFragment).setOnContactPickerActionListener(
398                    new ContactPickerActionListener());
399        } else if (mListFragment instanceof PhoneNumberPickerFragment) {
400            ((PhoneNumberPickerFragment) mListFragment).setOnPhoneNumberPickerActionListener(
401                    new PhoneNumberPickerActionListener());
402        } else if (mListFragment instanceof PostalAddressPickerFragment) {
403            ((PostalAddressPickerFragment) mListFragment).setOnPostalAddressPickerActionListener(
404                    new PostalAddressPickerActionListener());
405        } else if (mListFragment instanceof EmailAddressPickerFragment) {
406            ((EmailAddressPickerFragment) mListFragment).setOnEmailAddressPickerActionListener(
407                    new EmailAddressPickerActionListener());
408        } else if (mListFragment instanceof MultiSelectEmailAddressesListFragment) {
409            ((MultiSelectEmailAddressesListFragment) mListFragment).setCheckBoxListListener(this);
410        } else if (mListFragment instanceof MultiSelectPhoneNumbersListFragment) {
411            ((MultiSelectPhoneNumbersListFragment) mListFragment).setCheckBoxListListener(this);
412        } else if (mListFragment instanceof JoinContactListFragment) {
413            ((JoinContactListFragment) mListFragment).setOnContactPickerActionListener(
414                    new JoinContactActionListener());
415        } else if (mListFragment instanceof GroupMemberPickerFragment) {
416            ((GroupMemberPickerFragment) mListFragment).setListener(
417                    new GroupMemberPickerListener());
418            getMultiSelectListFragment().setCheckBoxListListener(this);
419        } else {
420            throw new IllegalStateException("Unsupported list fragment type: " + mListFragment);
421        }
422    }
423
424    private MultiSelectContactsListFragment getMultiSelectListFragment() {
425        if (mListFragment instanceof MultiSelectContactsListFragment) {
426            return (MultiSelectContactsListFragment) mListFragment;
427        }
428        return null;
429    }
430
431    @Override
432    public void onAction(int action) {
433        switch (action) {
434            case ActionBarAdapter.Listener.Action.START_SEARCH_MODE:
435                mIsSearchMode = true;
436                configureSearchMode();
437                break;
438            case ActionBarAdapter.Listener.Action.CHANGE_SEARCH_QUERY:
439                final String queryString = mActionBarAdapter.getQueryString();
440                mListFragment.setQueryString(queryString, /* delaySelection */ false);
441                break;
442            case ActionBarAdapter.Listener.Action.START_SELECTION_MODE:
443                if (getMultiSelectListFragment() != null) {
444                    getMultiSelectListFragment().displayCheckBoxes(true);
445                }
446                invalidateOptionsMenu();
447                break;
448            case ActionBarAdapter.Listener.Action.STOP_SEARCH_AND_SELECTION_MODE:
449                mListFragment.setQueryString("", /* delaySelection */ false);
450                mActionBarAdapter.setSearchMode(false);
451                if (getMultiSelectListFragment() != null) {
452                    getMultiSelectListFragment().displayCheckBoxes(false);
453                }
454                invalidateOptionsMenu();
455                break;
456        }
457    }
458
459    @Override
460    public void onUpButtonPressed() {
461        onBackPressed();
462    }
463
464    @Override
465    public void onStartDisplayingCheckBoxes() {
466        mActionBarAdapter.setSelectionMode(true);
467    }
468
469    @Override
470    public void onSelectedContactIdsChanged() {
471        if (mListFragment instanceof MultiSelectContactsListFragment) {
472            final int count = getMultiSelectListFragment().getSelectedContactIds().size();
473            mActionBarAdapter.setSelectionCount(count);
474            updateAddContactsButton(count);
475
476            // Show or hide the multi select "Done" button
477            invalidateOptionsMenu();
478        }
479    }
480
481    private void updateAddContactsButton(int count) {
482        final TextView textView = (TextView) mActionBarAdapter.getSelectionContainer()
483                .findViewById(R.id.add_contacts);
484        if (count > 0) {
485            textView.setVisibility(View.VISIBLE);
486            textView.setAllCaps(true);
487            textView.setOnClickListener(new OnClickListener() {
488                @Override
489                public void onClick(View v) {
490                    final long[] contactIds =
491                            getMultiSelectListFragment().getSelectedContactIdsArray();
492                    returnSelectedContacts(contactIds);
493                }
494            });
495        } else {
496            textView.setVisibility(View.GONE);
497        }
498    }
499
500    @Override
501    public void onStopDisplayingCheckBoxes() {
502        mActionBarAdapter.setSelectionMode(false);
503    }
504
505    private final class ContactPickerActionListener implements OnContactPickerActionListener {
506        @Override
507        public void onCreateNewContactAction() {
508            startCreateNewContactActivity();
509        }
510
511        @Override
512        public void onEditContactAction(Uri contactLookupUri) {
513            startActivityAndForwardResult(EditorIntents.createEditContactIntent(
514                    ContactSelectionActivity.this, contactLookupUri, /* materialPalette =*/ null,
515                    /* photoId =*/ -1));
516        }
517
518        @Override
519        public void onPickContactAction(Uri contactUri) {
520            returnPickerResult(contactUri);
521        }
522
523        @Override
524        public void onShortcutIntentCreated(Intent intent) {
525            returnPickerResult(intent);
526        }
527    }
528
529    private final class PhoneNumberPickerActionListener implements
530            OnPhoneNumberPickerActionListener {
531        @Override
532        public void onPickDataUri(Uri dataUri, boolean isVideoCall, int callInitiationType) {
533            returnPickerResult(dataUri);
534        }
535
536        @Override
537        public void onPickPhoneNumber(String phoneNumber, boolean isVideoCall,
538                                      int callInitiationType) {
539            Log.w(TAG, "Unsupported call.");
540        }
541
542        @Override
543        public void onShortcutIntentCreated(Intent intent) {
544            returnPickerResult(intent);
545        }
546
547        @Override
548        public void onHomeInActionBarSelected() {
549            ContactSelectionActivity.this.onBackPressed();
550        }
551    }
552
553    private final class JoinContactActionListener implements OnContactPickerActionListener {
554        @Override
555        public void onPickContactAction(Uri contactUri) {
556            Intent intent = new Intent(null, contactUri);
557            setResult(RESULT_OK, intent);
558            finish();
559        }
560
561        @Override
562        public void onShortcutIntentCreated(Intent intent) {
563        }
564
565        @Override
566        public void onCreateNewContactAction() {
567        }
568
569        @Override
570        public void onEditContactAction(Uri contactLookupUri) {
571        }
572    }
573
574    private final class GroupMemberPickerListener implements GroupMemberPickerFragment.Listener {
575
576        @Override
577        public void onGroupMemberClicked(long contactId) {
578            final Intent intent = new Intent();
579            intent.putExtra(UiIntentActions.TARGET_CONTACT_ID_EXTRA_KEY, contactId);
580            returnPickerResult(intent);
581        }
582
583        @Override
584        public void onSelectGroupMembers() {
585            mActionBarAdapter.setSelectionMode(true);
586        }
587    }
588
589    private void returnSelectedContacts(long[] contactIds) {
590        final Intent intent = new Intent();
591        intent.putExtra(UiIntentActions.TARGET_CONTACT_IDS_EXTRA_KEY, contactIds);
592        returnPickerResult(intent);
593    }
594
595    private final class PostalAddressPickerActionListener implements
596            OnPostalAddressPickerActionListener {
597        @Override
598        public void onPickPostalAddressAction(Uri dataUri) {
599            returnPickerResult(dataUri);
600        }
601    }
602
603    private final class EmailAddressPickerActionListener implements
604            OnEmailAddressPickerActionListener {
605        @Override
606        public void onPickEmailAddressAction(Uri dataUri) {
607            returnPickerResult(dataUri);
608        }
609    }
610
611    public void startActivityAndForwardResult(final Intent intent) {
612        intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
613
614        // Forward extras to the new activity
615        Bundle extras = getIntent().getExtras();
616        if (extras != null) {
617            intent.putExtras(extras);
618        }
619        try {
620            ImplicitIntentsUtil.startActivityInApp(ContactSelectionActivity.this, intent);
621        } catch (ActivityNotFoundException e) {
622            Log.e(TAG, "startActivity() failed: " + e);
623            Toast.makeText(ContactSelectionActivity.this, R.string.missing_app,
624                    Toast.LENGTH_SHORT).show();
625        }
626        finish();
627    }
628
629    @Override
630    public void onFocusChange(View view, boolean hasFocus) {
631        if (view.getId() == R.id.search_view) {
632            if (hasFocus) {
633                mActionBarAdapter.setFocusOnSearchView();
634            }
635        }
636    }
637
638    public void returnPickerResult(Uri data) {
639        Intent intent = new Intent();
640        intent.setData(data);
641        returnPickerResult(intent);
642    }
643
644    public void returnPickerResult(Intent intent) {
645        intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
646        setResult(RESULT_OK, intent);
647        finish();
648    }
649
650    @Override
651    public void onClick(View view) {
652        if (view.getId() == R.id.floating_action_button) {
653            startCreateNewContactActivity();
654        }
655    }
656
657    private long getTargetContactId() {
658        Intent intent = getIntent();
659        final long targetContactId = intent.getLongExtra(
660                UiIntentActions.TARGET_CONTACT_ID_EXTRA_KEY, -1);
661        if (targetContactId == -1) {
662            Log.e(TAG, "Intent " + intent.getAction() + " is missing required extra: "
663                    + UiIntentActions.TARGET_CONTACT_ID_EXTRA_KEY);
664            setResult(RESULT_CANCELED);
665            finish();
666            return -1;
667        }
668        return targetContactId;
669    }
670
671    private void startCreateNewContactActivity() {
672        Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI);
673        intent.putExtra(ContactEditorActivity.
674                INTENT_KEY_FINISH_ACTIVITY_ON_SAVE_COMPLETED, true);
675        startActivityAndForwardResult(intent);
676    }
677
678    @Override
679    public boolean onCreateOptionsMenu(Menu menu) {
680        super.onCreateOptionsMenu(menu);
681
682        final MenuInflater inflater = getMenuInflater();
683        inflater.inflate(R.menu.search_menu, menu);
684
685        final MenuItem searchItem = menu.findItem(R.id.menu_search);
686        searchItem.setVisible(!mIsSearchMode && mIsSearchSupported);
687
688        final Drawable searchIcon = searchItem.getIcon();
689        if (searchIcon != null) {
690            searchIcon.mutate().setColorFilter(ContextCompat.getColor(this,
691                    R.color.actionbar_icon_color), PorterDuff.Mode.SRC_ATOP);
692        }
693        return true;
694    }
695
696    @Override
697    public void onBackPressed() {
698        if (!isSafeToCommitTransactions()) {
699            return;
700        }
701
702        if (isSelectionMode()) {
703            mActionBarAdapter.setSelectionMode(false);
704            if (getMultiSelectListFragment() != null) {
705                getMultiSelectListFragment().displayCheckBoxes(false);
706            }
707        } else if (mIsSearchMode) {
708            mIsSearchMode = false;
709            configureSearchMode();
710        } else {
711            super.onBackPressed();
712        }
713    }
714}
715