DialtactsActivity.java revision bd762dc826d85e5b7db634ef14a0dbb70c42eaab
1032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov/*
2032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * Copyright (C) 2008 The Android Open Source Project
3032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov *
4032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * Licensed under the Apache License, Version 2.0 (the "License");
5032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * you may not use this file except in compliance with the License.
6032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * You may obtain a copy of the License at
7032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov *
8032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov *      http://www.apache.org/licenses/LICENSE-2.0
9032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov *
10032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * Unless required by applicable law or agreed to in writing, software
11032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * distributed under the License is distributed on an "AS IS" BASIS,
12032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * See the License for the specific language governing permissions and
14032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov * limitations under the License.
15032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov */
16032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov
1709fba0a6d82a7f88ce3c8cbb74eddd4bb96eb7e4Daniel Lehmannpackage com.android.contacts.activities;
18032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov
1909fba0a6d82a7f88ce3c8cbb74eddd4bb96eb7e4Daniel Lehmannimport com.android.contacts.R;
20c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmannimport com.android.contacts.calllog.CallLogFragment;
21c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmannimport com.android.contacts.dialpad.DialpadFragment;
22aae838c5a7ef38f4f2778cff6dfaa1f650a44522Daniel Lehmannimport com.android.contacts.interactions.PhoneNumberInteraction;
23b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawaimport com.android.contacts.list.OnPhoneNumberPickerActionListener;
24b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawaimport com.android.contacts.list.PhoneNumberPickerFragment;
25aae838c5a7ef38f4f2778cff6dfaa1f650a44522Daniel Lehmannimport com.android.contacts.list.StrequentContactListFragment;
26b25c13ec8b060cc74f91285929c4535adf4260f0Jeff Hamiltonimport com.android.internal.telephony.ITelephony;
27b25c13ec8b060cc74f91285929c4535adf4260f0Jeff Hamilton
28c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmannimport android.app.ActionBar;
29b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawaimport android.app.ActionBar.LayoutParams;
30c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmannimport android.app.ActionBar.Tab;
31c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmannimport android.app.ActionBar.TabListener;
32032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikovimport android.app.Activity;
33c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmannimport android.app.Fragment;
34c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmannimport android.app.FragmentManager;
35c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmannimport android.app.FragmentTransaction;
36c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasaniimport android.content.Context;
37032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikovimport android.content.Intent;
38903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamiltonimport android.content.SharedPreferences;
39032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikovimport android.net.Uri;
40032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikovimport android.os.Bundle;
41032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikovimport android.os.RemoteException;
42032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikovimport android.os.ServiceManager;
43032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikovimport android.provider.CallLog.Calls;
44b25c13ec8b060cc74f91285929c4535adf4260f0Jeff Hamiltonimport android.provider.ContactsContract.Intents.UI;
45438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawaimport android.support.v13.app.FragmentPagerAdapter;
46438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawaimport android.support.v4.view.ViewPager;
47438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawaimport android.support.v4.view.ViewPager.OnPageChangeListener;
48b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawaimport android.text.TextUtils;
49032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikovimport android.util.Log;
50c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmannimport android.view.Menu;
51c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmannimport android.view.MenuInflater;
52c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmannimport android.view.MenuItem;
53aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawaimport android.view.MenuItem.OnMenuItemClickListener;
54b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawaimport android.view.View;
55c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasaniimport android.view.View.OnAttachStateChangeListener;
56c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasaniimport android.view.inputmethod.InputMethodManager;
57b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawaimport android.widget.SearchView;
58b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawaimport android.widget.SearchView.OnCloseListener;
59b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawaimport android.widget.SearchView.OnQueryTextListener;
60032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov
61032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov/**
6208832404d96360ac386a98fd977e45fde936ec30Nicolas Catania * The dialer activity that has one tab with the virtual 12key
6308832404d96360ac386a98fd977e45fde936ec30Nicolas Catania * dialer, a tab with recent calls in it, a tab with the contacts and
6408832404d96360ac386a98fd977e45fde936ec30Nicolas Catania * a tab with the favorite. This is the container and the tabs are
6508832404d96360ac386a98fd977e45fde936ec30Nicolas Catania * embedded using intents.
6608832404d96360ac386a98fd977e45fde936ec30Nicolas Catania * The dialer tab's title is 'phone', a more common name (see strings.xml).
67032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov */
68c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmannpublic class DialtactsActivity extends Activity {
6909fba0a6d82a7f88ce3c8cbb74eddd4bb96eb7e4Daniel Lehmann    private static final String TAG = "DialtactsActivity";
707675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann
7143105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa    /** Used to open Call Setting */
7243105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa    private static final String PHONE_PACKAGE = "com.android.phone";
7343105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa    private static final String CALL_SETTINGS_CLASS_NAME =
7443105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            "com.android.phone.CallFeaturesSetting";
7543105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa
76438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa    /** Used both by {@link ActionBar} and {@link ViewPagerAdapter} */
77032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    private static final int TAB_INDEX_DIALER = 0;
78032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    private static final int TAB_INDEX_CALL_LOG = 1;
7920962611bd54c64c206351d53b51686081d89e53Daisuke Miyakawa    private static final int TAB_INDEX_FAVORITES = 2;
8020962611bd54c64c206351d53b51686081d89e53Daisuke Miyakawa
8120962611bd54c64c206351d53b51686081d89e53Daisuke Miyakawa    private static final int TAB_INDEX_COUNT = 3;
8208832404d96360ac386a98fd977e45fde936ec30Nicolas Catania
83903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton    /** Name of the dialtacts shared preferences */
84903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton    static final String PREFS_DIALTACTS = "dialtacts";
85903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton    static final boolean PREF_FAVORITES_AS_CONTACTS_DEFAULT = false;
86903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton
877675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann    /** Last manually selected tab index */
887675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann    private static final String PREF_LAST_MANUALLY_SELECTED_TAB = "last_manually_selected_tab";
897675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann    private static final int PREF_LAST_MANUALLY_SELECTED_TAB_DEFAULT = TAB_INDEX_DIALER;
907675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann
91438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa    /**
92438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa     * Listener interface for Fragments accommodated in {@link ViewPager} enabling them to know
93438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa     * when it becomes visible or invisible inside the ViewPager.
94438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa     */
95438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa    public interface ViewPagerVisibilityListener {
96aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa        public void onVisibilityChanged(boolean visible);
97438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa    }
98438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa
99438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa    public class ViewPagerAdapter extends FragmentPagerAdapter {
100438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa        public ViewPagerAdapter(FragmentManager fm) {
101438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa            super(fm);
102438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa        }
103438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa
104438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa        @Override
105438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa        public Fragment getItem(int position) {
106438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa            switch (position) {
107438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa                case TAB_INDEX_DIALER:
10843105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa                    return new DialpadFragment();
109438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa                case TAB_INDEX_CALL_LOG:
11043105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa                    return new CallLogFragment();
111438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa                case TAB_INDEX_FAVORITES:
11243105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa                    return new StrequentContactListFragment();
113438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa            }
114438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa            throw new IllegalStateException("No fragment at position " + position);
115438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa        }
116438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa
117438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa        @Override
118438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa        public int getCount() {
119438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa            return TAB_INDEX_COUNT;
120438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa        }
121438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa    }
122438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa
123438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa    private class PageChangeListener implements OnPageChangeListener {
124aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa        private int mPreviousPosition = -1;  // Invalid at first
125aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa
126438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa        @Override
127438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa        public void onPageScrolled(
128438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa                int position, float positionOffset, int positionOffsetPixels) {
129438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa        }
130438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa
131438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa        @Override
132438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa        public void onPageSelected(int position) {
133438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa            final ActionBar actionBar = getActionBar();
134aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa            if (mPreviousPosition == position) {
135aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa                Log.w(TAG, "Previous position and next position became same (" + position + ")");
136aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa            }
137aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa
138aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa            if (mPreviousPosition >= 0) {
13943105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa                sendFragmentVisibilityChange(mPreviousPosition, false);
140aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa            }
14143105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            sendFragmentVisibilityChange(position, true);
142aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa
143438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa            actionBar.selectTab(actionBar.getTabAt(position));
144aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa
145aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa            // Activity#onPrepareOptionsMenu() may not be called when Fragment has it's own
146aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa            // options menu. We force this Activity to call it to hide/show bottom bar. Also
147aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa            // we don't want to do so when it is unnecessary (buttons may flicker).
148aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa            if (mPreviousPosition == TAB_INDEX_DIALER || position == TAB_INDEX_DIALER) {
149aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa                // Force this Activity to prepare Menu again.
150aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa                invalidateOptionsMenu();
151aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa            }
152aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa
153aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa            mPreviousPosition = position;
154438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa        }
155438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa
15643105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        public void setCurrentPosition(int position) {
15743105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            mPreviousPosition = position;
15843105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        }
15943105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa
160438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa        @Override
161438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa        public void onPageScrollStateChanged(int state) {
162438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa        }
163438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa    }
164438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa
16508832404d96360ac386a98fd977e45fde936ec30Nicolas Catania    private String mFilterText;
166032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    private Uri mDialUri;
167438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa
168438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa    /** Enables horizontal swipe between Fragments. */
169438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa    private ViewPager mViewPager;
17043105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa    private final PageChangeListener mPageChangeListener = new PageChangeListener();
171c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann    private DialpadFragment mDialpadFragment;
172c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann    private CallLogFragment mCallLogFragment;
173aae838c5a7ef38f4f2778cff6dfaa1f650a44522Daniel Lehmann    private StrequentContactListFragment mStrequentFragment;
174032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov
1752c1f7878d72184a56e9c2b0d9f4d74be439979c2Daisuke Miyakawa    private final TabListener mTabListener = new TabListener() {
17643105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        @Override
17743105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        public void onTabUnselected(Tab tab, FragmentTransaction ft) {
17843105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        }
17943105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa
18043105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        @Override
18143105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        public void onTabSelected(Tab tab, FragmentTransaction ft) {
18243105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            if (mViewPager.getCurrentItem() != tab.getPosition()) {
18343105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa                mViewPager.setCurrentItem(tab.getPosition(), false /* smoothScroll */);
18443105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            }
18543105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa
18643105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            // During the call, we don't remember the tab position.
18743105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            if (!DialpadFragment.phoneIsInUse()) {
18843105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa                // Remember this tab index. This function is also called, if the tab is set
18943105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa                // automatically in which case the setter (setCurrentTab) has to set this to its old
19043105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa                // value afterwards
19143105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa                mLastManuallySelectedFragment = tab.getPosition();
19243105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            }
19343105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        }
19443105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa
19543105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        @Override
19643105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        public void onTabReselected(Tab tab, FragmentTransaction ft) {
19743105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        }
19843105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa    };
19943105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa
2007675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann    /**
201b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa     * Fragment for searching phone numbers. Unlike the other Fragments, this doesn't correspond
202b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa     * to tab but is shown by a search action.
203b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa     */
204aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa    private PhoneNumberPickerFragment mSearchFragment;
205b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa    /**
206b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa     * True when this Activity is in its search UI (with a {@link SearchView} and
207b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa     * {@link PhoneNumberPickerFragment}).
208b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa     */
209b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa    private boolean mInSearchUi;
210aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa    private SearchView mSearchView;
211b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa
212b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa    /**
213aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa     * The index of the Fragment (or, the tab) that has last been manually selected.
214cfcd0764a1ec53c6014df9ce3e7d3a3da511599fDaisuke Miyakawa     * This value does not keep track of programmatically set Tabs (e.g. Call Log after a Call)
215cfcd0764a1ec53c6014df9ce3e7d3a3da511599fDaisuke Miyakawa     */
216aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa    private int mLastManuallySelectedFragment;
217cfcd0764a1ec53c6014df9ce3e7d3a3da511599fDaisuke Miyakawa
218cfcd0764a1ec53c6014df9ce3e7d3a3da511599fDaisuke Miyakawa    /**
219b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa     * Listener used when one of phone numbers in search UI is selected. This will initiate a
220b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa     * phone call using the phone number.
221b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa     */
222b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa    private final OnPhoneNumberPickerActionListener mPhoneNumberPickerActionListener =
223b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa            new OnPhoneNumberPickerActionListener() {
224b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa                @Override
225b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa                public void onPickPhoneNumberAction(Uri dataUri) {
226b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa                    PhoneNumberInteraction.startInteractionForPhoneCall(
227b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa                            DialtactsActivity.this, dataUri);
228b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa                }
229b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa
230b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa                @Override
231b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa                public void onShortcutIntentCreated(Intent intent) {
232b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa                    Log.w(TAG, "Unsupported intent has come (" + intent + "). Ignoring.");
233b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa                }
23488f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa
23588f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa                @Override
23688f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa                public void onHomeInActionBarSelected() {
23788f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa                    exitSearchUi();
23888f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa                }
239b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa    };
240b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa
241b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa    /**
242b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa     * Listener used to send search queries to the phone search fragment.
243b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa     */
244b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa    private final OnQueryTextListener mPhoneSearchQueryTextListener =
245b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa            new OnQueryTextListener() {
246b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa                @Override
247b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa                public boolean onQueryTextSubmit(String query) {
248b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa                    // Ignore.
249b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa                    return true;
250b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa                }
251b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa
252b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa                @Override
253b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa                public boolean onQueryTextChange(String newText) {
254b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa                    // Show search result with non-empty text. Show a bare list otherwise.
255aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa                    mSearchFragment.setQueryString(newText, true);
256aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa                    mSearchFragment.setSearchMode(!TextUtils.isEmpty(newText));
257b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa                    return true;
258b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa                }
259b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa    };
260b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa
261b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa    /**
262b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa     * Listener used to handle the "close" button on the right side of {@link SearchView}.
263b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa     * If some text is in the search view, this will clean it up. Otherwise this will exit
264b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa     * the search UI and let users go back to usual Phone UI.
265b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa     *
266b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa     * This does _not_ handle back button.
267b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa     *
268b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa     * TODO: need "up" button instead of close button
269b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa     */
270b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa    private final OnCloseListener mPhoneSearchCloseListener =
271b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa            new OnCloseListener() {
272b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa                @Override
273b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa                public boolean onClose() {
274b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa                    if (TextUtils.isEmpty(mSearchView.getQuery())) {
275b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa                        exitSearchUi();
276b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa                    } else {
277b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa                        mSearchView.setQuery(null, true);
278b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa                    }
279b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa                    return true;
280b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa                }
281b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa    };
282b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa
283032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    @Override
284032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    protected void onCreate(Bundle icicle) {
285032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        super.onCreate(icicle);
286032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov
287032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        final Intent intent = getIntent();
288032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        fixIntent(intent);
28908832404d96360ac386a98fd977e45fde936ec30Nicolas Catania
29009fba0a6d82a7f88ce3c8cbb74eddd4bb96eb7e4Daniel Lehmann        setContentView(R.layout.dialtacts_activity);
291032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov
292438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa        mViewPager = (ViewPager) findViewById(R.id.pager);
293438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa        mViewPager.setAdapter(new ViewPagerAdapter(getFragmentManager()));
29443105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        mViewPager.setOnPageChangeListener(mPageChangeListener);
295c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann
296c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        // Setup the ActionBar tabs (the order matches the tab-index contants TAB_INDEX_*)
297c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        setupDialer();
298c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        setupCallLog();
299c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        setupFavorites();
300c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
301c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        getActionBar().setDisplayShowTitleEnabled(false);
302c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        getActionBar().setDisplayShowHomeEnabled(false);
303032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov
3047675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann        // Load the last manually loaded tab
3057675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann        final SharedPreferences prefs = getSharedPreferences(PREFS_DIALTACTS, MODE_PRIVATE);
306aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa        mLastManuallySelectedFragment = prefs.getInt(PREF_LAST_MANUALLY_SELECTED_TAB,
3077675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann                PREF_LAST_MANUALLY_SELECTED_TAB_DEFAULT);
308aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa        if (mLastManuallySelectedFragment >= TAB_INDEX_COUNT) {
30920962611bd54c64c206351d53b51686081d89e53Daisuke Miyakawa            // Stored value may have exceeded the number of current tabs. Reset it.
310aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa            mLastManuallySelectedFragment = PREF_LAST_MANUALLY_SELECTED_TAB_DEFAULT;
31120962611bd54c64c206351d53b51686081d89e53Daisuke Miyakawa        }
3127675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann
313032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        setCurrentTab(intent);
314903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton
3157fa3cd652fdaa5284fdf5fa9c306f2ca89227c1aJeff Hamilton        if (UI.FILTER_CONTACTS_ACTION.equals(intent.getAction())
316903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton                && icicle == null) {
317903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton            setupFilterText(intent);
318903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton        }
319032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    }
320032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov
321903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton    @Override
32243105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa    public void onAttachFragment(Fragment fragment) {
32343105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        // This method can be called before onCreate(), at which point we cannot rely on ViewPager.
32443105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        // In that case, we will setup the "current position" soon after the ViewPager is ready.
32543105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        final int currentPosition = mViewPager != null ? mViewPager.getCurrentItem() : -1;
32643105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa
32743105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        if (fragment instanceof DialpadFragment) {
32843105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            mDialpadFragment = (DialpadFragment) fragment;
32943105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            mDialpadFragment.setListener(mDialpadListener);
33043105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            mDialpadFragment.onVisibilityChanged(currentPosition == TAB_INDEX_DIALER);
33143105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        } else if (fragment instanceof CallLogFragment) {
33243105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            mCallLogFragment = (CallLogFragment) fragment;
33343105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            mCallLogFragment.onVisibilityChanged(currentPosition == TAB_INDEX_CALL_LOG);
33443105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        } else if (fragment instanceof StrequentContactListFragment) {
33543105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            mStrequentFragment = (StrequentContactListFragment) fragment;
33643105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            mStrequentFragment.setListener(mStrequentListener);
33743105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        } else if (fragment instanceof PhoneNumberPickerFragment) {
33843105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            mSearchFragment = (PhoneNumberPickerFragment) fragment;
33943105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            mSearchFragment.setOnPhoneNumberPickerActionListener(mPhoneNumberPickerActionListener);
34043105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            mSearchFragment.setNameHighlightingEnabled(true);
34143105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            mSearchFragment.setQuickContactEnabled(true);
34243105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            final FragmentTransaction transaction = getFragmentManager().beginTransaction();
34343105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            if (mInSearchUi) {
34443105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa                transaction.show(mSearchFragment);
34543105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            } else {
34643105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa                transaction.hide(mSearchFragment);
34743105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            }
34843105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            transaction.commit();
34943105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        }
35043105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa    }
35143105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa
35243105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa    @Override
353903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton    protected void onPause() {
354903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton        super.onPause();
35508832404d96360ac386a98fd977e45fde936ec30Nicolas Catania
3567675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann        final SharedPreferences.Editor editor =
3577675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann                getSharedPreferences(PREFS_DIALTACTS, MODE_PRIVATE).edit();
358aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa        editor.putInt(PREF_LAST_MANUALLY_SELECTED_TAB, mLastManuallySelectedFragment);
3597675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann
360909271c9b60f755a5298c611400502e7418d161bBrad Fitzpatrick        editor.apply();
361903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton    }
36208832404d96360ac386a98fd977e45fde936ec30Nicolas Catania
363032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    private void fixIntent(Intent intent) {
364032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        // This should be cleaned up: the call key used to send an Intent
365032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        // that just said to go to the recent calls list.  It now sends this
366032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        // abstract action, but this class hasn't been rewritten to deal with it.
367032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        if (Intent.ACTION_CALL_BUTTON.equals(intent.getAction())) {
368032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            intent.setDataAndType(Calls.CONTENT_URI, Calls.CONTENT_TYPE);
369032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            intent.putExtra("call_key", true);
370032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            setIntent(intent);
371032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        }
372032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    }
37308832404d96360ac386a98fd977e45fde936ec30Nicolas Catania
374c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann    private void setupDialer() {
375c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        final Tab tab = getActionBar().newTab();
37600848d5b0cd3199fb91171936eb59db7c5e4b6afDavid Brown        // TODO: Temporarily disable tab text labels (in all 4 tabs in this
37700848d5b0cd3199fb91171936eb59db7c5e4b6afDavid Brown        //   activity) so that the current tabs will all fit onscreen in
37800848d5b0cd3199fb91171936eb59db7c5e4b6afDavid Brown        //   portrait (bug 4520620).  (Also note we do setText("") rather
37900848d5b0cd3199fb91171936eb59db7c5e4b6afDavid Brown        //   leaving the text null, to work around bug 4521549.)
38000848d5b0cd3199fb91171936eb59db7c5e4b6afDavid Brown        tab.setText("");  // R.string.dialerIconLabel
38143105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        tab.setTabListener(mTabListener);
382c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        tab.setIcon(R.drawable.ic_tab_dialer);
383c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        getActionBar().addTab(tab);
384032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    }
385032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov
386c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann    private void setupCallLog() {
387c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        final Tab tab = getActionBar().newTab();
38800848d5b0cd3199fb91171936eb59db7c5e4b6afDavid Brown        tab.setText("");  // R.string.recentCallsIconLabel
389c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        tab.setIcon(R.drawable.ic_tab_recent);
39043105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        tab.setTabListener(mTabListener);
391c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        getActionBar().addTab(tab);
392032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    }
393032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov
394c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann    private void setupFavorites() {
395c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        final Tab tab = getActionBar().newTab();
39600848d5b0cd3199fb91171936eb59db7c5e4b6afDavid Brown        tab.setText("");  // R.string.contactsFavoritesLabel
397c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        tab.setIcon(R.drawable.ic_tab_starred);
39843105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        tab.setTabListener(mTabListener);
399c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        getActionBar().addTab(tab);
4009add0e5ef2a267acbe104e04f4cf6ab24cb8ba3eKatherine Kuan    }
4019add0e5ef2a267acbe104e04f4cf6ab24cb8ba3eKatherine Kuan
402032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    /**
403032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov     * Returns true if the intent is due to hitting the green send key while in a call.
40408832404d96360ac386a98fd977e45fde936ec30Nicolas Catania     *
405032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov     * @param intent the intent that launched this activity
406032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov     * @param recentCallsRequest true if the intent is requesting to view recent calls
40708832404d96360ac386a98fd977e45fde936ec30Nicolas Catania     * @return true if the intent is due to hitting the green send key while in a call
408032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov     */
409aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa    private boolean isSendKeyWhileInCall(final Intent intent,
410aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa            final boolean recentCallsRequest) {
411032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        // If there is a call in progress go to the call screen
412032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        if (recentCallsRequest) {
413032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            final boolean callKey = intent.getBooleanExtra("call_key", false);
414032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov
415032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            try {
416032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov                ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone"));
417032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov                if (callKey && phone != null && phone.showCallScreen()) {
418032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov                    return true;
419032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov                }
420032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            } catch (RemoteException e) {
421032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov                Log.e(TAG, "Failed to handle send while in call", e);
422032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            }
423032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        }
424032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov
425032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        return false;
426032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    }
427032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov
428032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    /**
429032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov     * Sets the current tab based on the intent's request type
43008832404d96360ac386a98fd977e45fde936ec30Nicolas Catania     *
4317675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann     * @param intent Intent that contains information about which tab should be selected
432032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov     */
433032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    private void setCurrentTab(Intent intent) {
434032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        // If we got here by hitting send and we're in call forward along to the in-call activity
435032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        final boolean recentCallsRequest = Calls.CONTENT_TYPE.equals(intent.getType());
436032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        if (isSendKeyWhileInCall(intent, recentCallsRequest)) {
437032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            finish();
438032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            return;
439032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        }
44008832404d96360ac386a98fd977e45fde936ec30Nicolas Catania
4417675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann        // Remember the old manually selected tab index so that it can be restored if it is
4427675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann        // overwritten by one of the programmatic tab selections
443aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa        final int savedTabIndex = mLastManuallySelectedFragment;
4447675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann
445438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa        final int tabIndex;
446438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa        if (DialpadFragment.phoneIsInUse() || isDialIntent(intent)) {
447438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa            tabIndex = TAB_INDEX_DIALER;
448c18f9b7cb0846d0c10fe0398224b53530a2194ecDaisuke Miyakawa        } else if (recentCallsRequest) {
449438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa            tabIndex = TAB_INDEX_CALL_LOG;
450903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton        } else {
451aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa            tabIndex = mLastManuallySelectedFragment;
452032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        }
453aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa        mViewPager.setCurrentItem(tabIndex, false /* smoothScroll */);
45443105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        if (mViewPager.getCurrentItem() == tabIndex) {
45543105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            mPageChangeListener.setCurrentPosition(tabIndex);
45643105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            sendFragmentVisibilityChange(tabIndex, true);
45743105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        } else {
45843105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            getActionBar().selectTab(getActionBar().getTabAt(tabIndex));
45943105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        }
460032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov
4617675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann        // Restore to the previous manual selection
462aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa        mLastManuallySelectedFragment = savedTabIndex;
463032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    }
464032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov
465032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    @Override
466032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    public void onNewIntent(Intent newIntent) {
467032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        setIntent(newIntent);
468032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        fixIntent(newIntent);
469032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        setCurrentTab(newIntent);
470903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton        final String action = newIntent.getAction();
4717fa3cd652fdaa5284fdf5fa9c306f2ca89227c1aJeff Hamilton        if (UI.FILTER_CONTACTS_ACTION.equals(action)) {
472903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton            setupFilterText(newIntent);
473903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton        } else if (isDialIntent(newIntent)) {
474032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            setupDialUri(newIntent);
475032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        }
47643105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        if (mInSearchUi || mSearchFragment.isVisible()) {
477438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa            exitSearchUi();
478438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa        }
479032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    }
480032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov
481032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    /** Returns true if the given intent contains a phone number to populate the dialer with */
482032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    private boolean isDialIntent(Intent intent) {
483032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        final String action = intent.getAction();
484032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        if (Intent.ACTION_DIAL.equals(action)) {
485032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            return true;
486032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        }
487032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        if (Intent.ACTION_VIEW.equals(action)) {
488032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            final Uri data = intent.getData();
489032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            if (data != null && "tel".equals(data.getScheme())) {
490032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov                return true;
491032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            }
492032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        }
493032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        return false;
494032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    }
49508832404d96360ac386a98fd977e45fde936ec30Nicolas Catania
496903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton    /**
497903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton     * Retrieves the filter text stored in {@link #setupFilterText(Intent)}.
498903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton     * This text originally came from a FILTER_CONTACTS_ACTION intent received
499903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton     * by this activity. The stored text will then be cleared after after this
500903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton     * method returns.
50108832404d96360ac386a98fd977e45fde936ec30Nicolas Catania     *
502903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton     * @return The stored filter text
503903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton     */
504903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton    public String getAndClearFilterText() {
505903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton        String filterText = mFilterText;
506903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton        mFilterText = null;
507903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton        return filterText;
508903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton    }
509903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton
510903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton    /**
511903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton     * Stores the filter text associated with a FILTER_CONTACTS_ACTION intent.
512903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton     * This is so child activities can check if they are supposed to display a filter.
51308832404d96360ac386a98fd977e45fde936ec30Nicolas Catania     *
514903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton     * @param intent The intent received in {@link #onNewIntent(Intent)}
515903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton     */
516903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton    private void setupFilterText(Intent intent) {
517903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton        // If the intent was relaunched from history, don't apply the filter text.
518903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton        if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) {
519903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton            return;
520903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton        }
521b25c13ec8b060cc74f91285929c4535adf4260f0Jeff Hamilton        String filter = intent.getStringExtra(UI.FILTER_TEXT_EXTRA_KEY);
522903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton        if (filter != null && filter.length() > 0) {
523903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton            mFilterText = filter;
524903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton        }
525903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton    }
526032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov
527032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    /**
528032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov     * Retrieves the uri stored in {@link #setupDialUri(Intent)}. This uri
529032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov     * originally came from a dial intent received by this activity. The stored
530032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov     * uri will then be cleared after after this method returns.
53108832404d96360ac386a98fd977e45fde936ec30Nicolas Catania     *
532032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov     * @return The stored uri
533032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov     */
534032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    public Uri getAndClearDialUri() {
535032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        Uri dialUri = mDialUri;
536032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        mDialUri = null;
537032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        return dialUri;
538032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    }
539032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov
540032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    /**
541032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov     * Stores the uri associated with a dial intent. This is so child activities can
542032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov     * check if they are supposed to display new dial info.
54308832404d96360ac386a98fd977e45fde936ec30Nicolas Catania     *
544032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov     * @param intent The intent received in {@link #onNewIntent(Intent)}
545032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov     */
546032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    private void setupDialUri(Intent intent) {
547032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        // If the intent was relaunched from history, don't reapply the intent.
548032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) {
549032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            return;
550032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        }
551032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        mDialUri = intent.getData();
552032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    }
553032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov
554032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    @Override
555242599a0f1ab23e2a46eff963484a70ec7981befDianne Hackborn    public void onBackPressed() {
556b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        if (mInSearchUi) {
557b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa            // We should let the user go back to usual screens with tabs.
558b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa            exitSearchUi();
559b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        } else if (isTaskRoot()) {
560032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            // Instead of stopping, simply push this to the back of the stack.
561032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            // This is only done when running at the top of the stack;
562032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            // otherwise, we have been launched by someone else so need to
563032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            // allow the user to go back to the caller.
564032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            moveTaskToBack(false);
565242599a0f1ab23e2a46eff963484a70ec7981befDianne Hackborn        } else {
566242599a0f1ab23e2a46eff963484a70ec7981befDianne Hackborn            super.onBackPressed();
567032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        }
568032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    }
569032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov
57043105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa    private DialpadFragment.Listener mDialpadListener = new DialpadFragment.Listener() {
571c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        @Override
57243105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        public void onSearchButtonPressed() {
57343105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            enterSearchUi();
574c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        }
57543105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa    };
576c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann
57732f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro    private StrequentContactListFragment.Listener mStrequentListener =
57832f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro            new StrequentContactListFragment.Listener() {
57932f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro        @Override
58032f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro        public void onContactSelected(Uri contactUri) {
581b1f0e5e8a4de69bd80276742900441e930fa4c86Daisuke Miyakawa            PhoneNumberInteraction.startInteractionForPhoneCall(
582b1f0e5e8a4de69bd80276742900441e930fa4c86Daisuke Miyakawa                    DialtactsActivity.this, contactUri);
58332f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro        }
58432f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro    };
58532f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro
586c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann    @Override
587c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann    public boolean onCreateOptionsMenu(Menu menu) {
588c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        MenuInflater inflater = getMenuInflater();
589aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa        inflater.inflate(R.menu.dialtacts_options, menu);
590c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        return true;
591c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann    }
592c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann
593c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann    @Override
594aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa    public boolean onPrepareOptionsMenu(Menu menu) {
595aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa        final MenuItem searchMenuItem = menu.findItem(R.id.search_on_action_bar);
596aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa        if (mInSearchUi || getActionBar().getSelectedTab().getPosition() == TAB_INDEX_DIALER) {
597aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa            searchMenuItem.setVisible(false);
598aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa        } else {
599aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa            searchMenuItem.setVisible(true);
600aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa            searchMenuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() {
601aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa                @Override
602aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa                public boolean onMenuItemClick(MenuItem item) {
603aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa                    enterSearchUi();
604aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa                    return true;
605aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa                }
606c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann            });
607c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        }
608aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa
609aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa        return true;
610c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann    }
611b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa
612b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa    @Override
613b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa    public void startSearch(String initialQuery, boolean selectInitialQuery,
614b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa            Bundle appSearchData, boolean globalSearch) {
61543105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        if (mSearchFragment != null && mSearchFragment.isAdded() && !globalSearch) {
616b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa            enterSearchUi();
617b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        } else {
618b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa            super.startSearch(initialQuery, selectInitialQuery, appSearchData, globalSearch);
619b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        }
620b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa    }
621b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa
622b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa    /**
623b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa     * Hides every tab and shows search UI for phone lookup.
624b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa     */
625b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa    private void enterSearchUi() {
626b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        final ActionBar actionBar = getActionBar();
627b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa
628b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        final Tab tab = actionBar.getSelectedTab();
629c18f9b7cb0846d0c10fe0398224b53530a2194ecDaisuke Miyakawa
630c18f9b7cb0846d0c10fe0398224b53530a2194ecDaisuke Miyakawa        // User can search during the call, but we don't want to remember the status.
631c18f9b7cb0846d0c10fe0398224b53530a2194ecDaisuke Miyakawa        if (tab != null && !DialpadFragment.phoneIsInUse()) {
632aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa            mLastManuallySelectedFragment = tab.getPosition();
633b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        }
634b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa
635b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        // Instantiate or reset SearchView in ActionBar.
636b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        if (mSearchView == null) {
637b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa            // TODO: layout is not what we want. Need "up" button instead of "close" button, etc.
638b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa            final View searchViewLayout =
639b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa                    getLayoutInflater().inflate(R.layout.custom_action_bar, null);
640b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa            mSearchView = (SearchView) searchViewLayout.findViewById(R.id.search_view);
641b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa            mSearchView.setQueryHint(getString(R.string.hint_findContacts));
642b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa            mSearchView.setOnQueryTextListener(mPhoneSearchQueryTextListener);
643b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa            mSearchView.setOnCloseListener(mPhoneSearchCloseListener);
644b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa            mSearchView.requestFocus();
64536c33609482ae5c961ac5f3b67c581a0bb430f38Daisuke Miyakawa            // Show soft keyboard when SearchView has a focus. Need to delay the request in order
64636c33609482ae5c961ac5f3b67c581a0bb430f38Daisuke Miyakawa            // to let InputMethodManager handle it correctly.
647c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani            mSearchView.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
648c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani                @Override
649c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani                public void onViewDetachedFromWindow(View v) {
650c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani                }
651c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani
652c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani                @Override
653c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani                public void onViewAttachedToWindow(View v) {
654c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani                    if (mSearchView.hasFocus()) {
655c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani                        mSearchView.postDelayed(new Runnable() {
656c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani                            public void run() {
657c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani                                showInputMethod(mSearchView.findFocus());
658c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani                            }
659c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani                        }, 0);
660c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani                    }
661c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani                }
662c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani            });
663b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa            actionBar.setCustomView(searchViewLayout,
664b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa                    new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
665b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        } else {
666b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa            mSearchView.setQuery(null, true);
667b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        }
668b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa
669b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        actionBar.setDisplayShowCustomEnabled(true);
670b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
67188f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa        actionBar.setDisplayShowHomeEnabled(true);
67288f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa        actionBar.setDisplayHomeAsUpEnabled(true);
673b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa
67443105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        sendFragmentVisibilityChange(mViewPager.getCurrentItem(), false);
67543105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa
676b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        // Show the search fragment and hide everything else.
677b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        final FragmentTransaction transaction = getFragmentManager().beginTransaction();
678aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa        transaction.show(mSearchFragment);
679b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        transaction.commit();
680438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa        mViewPager.setVisibility(View.GONE);
681b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa
682b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        mInSearchUi = true;
683b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa    }
684b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa
685c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani    private void showInputMethod(View view) {
686c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani        InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
687c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani        if (imm != null) {
688c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani            imm.showSoftInput(view, 0);
689c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani        }
690c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani    }
691c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani
69288f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa    private void hideInputMethod(View view) {
69388f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa        InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
69488f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa        if (imm != null) {
69588f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa            imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
69688f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa        }
69788f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa    }
69888f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa
699b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa    /**
700b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa     * Goes back to usual Phone UI with tags. Previously selected Tag and associated Fragment
701b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa     * should be automatically focused again.
702b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa     */
703b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa    private void exitSearchUi() {
704b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        final ActionBar actionBar = getActionBar();
705b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa
706b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        // We want to hide SearchView and show Tabs. Also focus on previously selected one.
707b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        actionBar.setDisplayShowCustomEnabled(false);
70888f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa        actionBar.setDisplayShowHomeEnabled(false);
709b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
710b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa
71143105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        sendFragmentVisibilityChange(mViewPager.getCurrentItem(), true);
71243105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa
713438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa        final FragmentTransaction transaction = getFragmentManager().beginTransaction();
714aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa        transaction.hide(mSearchFragment);
715438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa        transaction.commit();
716438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa
717438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa        mViewPager.setVisibility(View.VISIBLE);
718438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa
71988f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa        hideInputMethod(getCurrentFocus());
72088f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa
721350e8d53a135e0bb62308a93dd09777364c08a58Daisuke Miyakawa        // Request to update option menu.
722350e8d53a135e0bb62308a93dd09777364c08a58Daisuke Miyakawa        invalidateOptionsMenu();
723350e8d53a135e0bb62308a93dd09777364c08a58Daisuke Miyakawa
724b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        mInSearchUi = false;
725b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa    }
726aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa
727aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa    private Fragment getFragmentAt(int position) {
728aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa        switch (position) {
729aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa            case TAB_INDEX_DIALER:
730aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa                return mDialpadFragment;
731aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa            case TAB_INDEX_CALL_LOG:
732aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa                return mCallLogFragment;
733aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa            case TAB_INDEX_FAVORITES:
734aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa                return mStrequentFragment;
735aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa            default:
736aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa                throw new IllegalStateException("Unknown fragment index: " + position);
737aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa        }
738aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa    }
73943105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa
74043105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa    private void sendFragmentVisibilityChange(int position, boolean visibility) {
74143105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        final Fragment fragment = getFragmentAt(position);
74243105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        if (fragment instanceof ViewPagerVisibilityListener) {
74343105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            ((ViewPagerVisibilityListener) fragment).onVisibilityChanged(visibility);
74443105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        }
74543105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa    }
746bd762dc826d85e5b7db634ef14a0dbb70c42eaabDaisuke Miyakawa
747bd762dc826d85e5b7db634ef14a0dbb70c42eaabDaisuke Miyakawa    /** Returns an Intent to launch Call Settings screen */
748bd762dc826d85e5b7db634ef14a0dbb70c42eaabDaisuke Miyakawa    public static Intent getCallSettingsIntent() {
749bd762dc826d85e5b7db634ef14a0dbb70c42eaabDaisuke Miyakawa        final Intent intent = new Intent(Intent.ACTION_MAIN);
750bd762dc826d85e5b7db634ef14a0dbb70c42eaabDaisuke Miyakawa        intent.setClassName(PHONE_PACKAGE, CALL_SETTINGS_CLASS_NAME);
751bd762dc826d85e5b7db634ef14a0dbb70c42eaabDaisuke Miyakawa        return intent;
752bd762dc826d85e5b7db634ef14a0dbb70c42eaabDaisuke Miyakawa    }
753032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov}
754