DialtactsActivity.java revision 7979ea27c046dfc2d9305b3282233046acef6ec4
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;
257979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaroimport com.android.contacts.list.ContactTileListFragment;
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:
1127979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro                    return new ContactTileListFragment();
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;
1737979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro    private ContactTileListFragment 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);
3347979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro        } else if (fragment instanceof ContactTileListFragment) {
3357979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro            mStrequentFragment = (ContactTileListFragment) fragment;
3367979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro            mStrequentFragment.enableQuickContact(false);
3377979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro            mStrequentFragment.enableSecondaryTarget(true);
33843105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            mStrequentFragment.setListener(mStrequentListener);
33943105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        } else if (fragment instanceof PhoneNumberPickerFragment) {
34043105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            mSearchFragment = (PhoneNumberPickerFragment) fragment;
34143105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            mSearchFragment.setOnPhoneNumberPickerActionListener(mPhoneNumberPickerActionListener);
34243105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            mSearchFragment.setQuickContactEnabled(true);
34343105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            final FragmentTransaction transaction = getFragmentManager().beginTransaction();
34443105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            if (mInSearchUi) {
34543105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa                transaction.show(mSearchFragment);
34643105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            } else {
34743105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa                transaction.hide(mSearchFragment);
34843105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            }
34943105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            transaction.commit();
35043105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        }
35143105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa    }
35243105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa
35343105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa    @Override
354903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton    protected void onPause() {
355903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton        super.onPause();
35608832404d96360ac386a98fd977e45fde936ec30Nicolas Catania
3577675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann        final SharedPreferences.Editor editor =
3587675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann                getSharedPreferences(PREFS_DIALTACTS, MODE_PRIVATE).edit();
359aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa        editor.putInt(PREF_LAST_MANUALLY_SELECTED_TAB, mLastManuallySelectedFragment);
3607675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann
361909271c9b60f755a5298c611400502e7418d161bBrad Fitzpatrick        editor.apply();
362903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton    }
36308832404d96360ac386a98fd977e45fde936ec30Nicolas Catania
364032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    private void fixIntent(Intent intent) {
365032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        // This should be cleaned up: the call key used to send an Intent
366032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        // that just said to go to the recent calls list.  It now sends this
367032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        // abstract action, but this class hasn't been rewritten to deal with it.
368032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        if (Intent.ACTION_CALL_BUTTON.equals(intent.getAction())) {
369032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            intent.setDataAndType(Calls.CONTENT_URI, Calls.CONTENT_TYPE);
370032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            intent.putExtra("call_key", true);
371032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            setIntent(intent);
372032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        }
373032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    }
37408832404d96360ac386a98fd977e45fde936ec30Nicolas Catania
375c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann    private void setupDialer() {
376c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        final Tab tab = getActionBar().newTab();
37700848d5b0cd3199fb91171936eb59db7c5e4b6afDavid Brown        // TODO: Temporarily disable tab text labels (in all 4 tabs in this
37800848d5b0cd3199fb91171936eb59db7c5e4b6afDavid Brown        //   activity) so that the current tabs will all fit onscreen in
37900848d5b0cd3199fb91171936eb59db7c5e4b6afDavid Brown        //   portrait (bug 4520620).  (Also note we do setText("") rather
38000848d5b0cd3199fb91171936eb59db7c5e4b6afDavid Brown        //   leaving the text null, to work around bug 4521549.)
38100848d5b0cd3199fb91171936eb59db7c5e4b6afDavid Brown        tab.setText("");  // R.string.dialerIconLabel
38243105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        tab.setTabListener(mTabListener);
383c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        tab.setIcon(R.drawable.ic_tab_dialer);
384c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        getActionBar().addTab(tab);
385032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    }
386032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov
387c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann    private void setupCallLog() {
388c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        final Tab tab = getActionBar().newTab();
38900848d5b0cd3199fb91171936eb59db7c5e4b6afDavid Brown        tab.setText("");  // R.string.recentCallsIconLabel
390c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        tab.setIcon(R.drawable.ic_tab_recent);
39143105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        tab.setTabListener(mTabListener);
392c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        getActionBar().addTab(tab);
393032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    }
394032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov
395c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann    private void setupFavorites() {
396c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        final Tab tab = getActionBar().newTab();
39700848d5b0cd3199fb91171936eb59db7c5e4b6afDavid Brown        tab.setText("");  // R.string.contactsFavoritesLabel
398c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        tab.setIcon(R.drawable.ic_tab_starred);
39943105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        tab.setTabListener(mTabListener);
400c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        getActionBar().addTab(tab);
4019add0e5ef2a267acbe104e04f4cf6ab24cb8ba3eKatherine Kuan    }
4029add0e5ef2a267acbe104e04f4cf6ab24cb8ba3eKatherine Kuan
403032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    /**
404032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov     * Returns true if the intent is due to hitting the green send key while in a call.
40508832404d96360ac386a98fd977e45fde936ec30Nicolas Catania     *
406032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov     * @param intent the intent that launched this activity
407032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov     * @param recentCallsRequest true if the intent is requesting to view recent calls
40808832404d96360ac386a98fd977e45fde936ec30Nicolas Catania     * @return true if the intent is due to hitting the green send key while in a call
409032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov     */
410aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa    private boolean isSendKeyWhileInCall(final Intent intent,
411aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa            final boolean recentCallsRequest) {
412032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        // If there is a call in progress go to the call screen
413032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        if (recentCallsRequest) {
414032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            final boolean callKey = intent.getBooleanExtra("call_key", false);
415032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov
416032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            try {
417032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov                ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone"));
418032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov                if (callKey && phone != null && phone.showCallScreen()) {
419032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov                    return true;
420032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov                }
421032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            } catch (RemoteException e) {
422032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov                Log.e(TAG, "Failed to handle send while in call", e);
423032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            }
424032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        }
425032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov
426032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        return false;
427032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    }
428032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov
429032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    /**
430032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov     * Sets the current tab based on the intent's request type
43108832404d96360ac386a98fd977e45fde936ec30Nicolas Catania     *
4327675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann     * @param intent Intent that contains information about which tab should be selected
433032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov     */
434032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    private void setCurrentTab(Intent intent) {
435032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        // If we got here by hitting send and we're in call forward along to the in-call activity
436032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        final boolean recentCallsRequest = Calls.CONTENT_TYPE.equals(intent.getType());
437032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        if (isSendKeyWhileInCall(intent, recentCallsRequest)) {
438032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            finish();
439032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            return;
440032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        }
44108832404d96360ac386a98fd977e45fde936ec30Nicolas Catania
4427675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann        // Remember the old manually selected tab index so that it can be restored if it is
4437675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann        // overwritten by one of the programmatic tab selections
444aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa        final int savedTabIndex = mLastManuallySelectedFragment;
4457675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann
446438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa        final int tabIndex;
447438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa        if (DialpadFragment.phoneIsInUse() || isDialIntent(intent)) {
448438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa            tabIndex = TAB_INDEX_DIALER;
449c18f9b7cb0846d0c10fe0398224b53530a2194ecDaisuke Miyakawa        } else if (recentCallsRequest) {
450438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa            tabIndex = TAB_INDEX_CALL_LOG;
451903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton        } else {
452aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa            tabIndex = mLastManuallySelectedFragment;
453032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        }
454aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa        mViewPager.setCurrentItem(tabIndex, false /* smoothScroll */);
45543105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        if (mViewPager.getCurrentItem() == tabIndex) {
45643105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            mPageChangeListener.setCurrentPosition(tabIndex);
45743105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            sendFragmentVisibilityChange(tabIndex, true);
45843105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        } else {
45943105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            getActionBar().selectTab(getActionBar().getTabAt(tabIndex));
46043105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        }
461032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov
4627675e12b55f9492bf0f6062811f2a0ed030dc1cfDaniel Lehmann        // Restore to the previous manual selection
463aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa        mLastManuallySelectedFragment = savedTabIndex;
464032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    }
465032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov
466032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    @Override
467032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    public void onNewIntent(Intent newIntent) {
468032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        setIntent(newIntent);
469032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        fixIntent(newIntent);
470032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        setCurrentTab(newIntent);
471903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton        final String action = newIntent.getAction();
4727fa3cd652fdaa5284fdf5fa9c306f2ca89227c1aJeff Hamilton        if (UI.FILTER_CONTACTS_ACTION.equals(action)) {
473903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton            setupFilterText(newIntent);
474903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton        } else if (isDialIntent(newIntent)) {
475032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            setupDialUri(newIntent);
476032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        }
47743105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        if (mInSearchUi || mSearchFragment.isVisible()) {
478438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa            exitSearchUi();
479438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa        }
480032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    }
481032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov
482032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    /** Returns true if the given intent contains a phone number to populate the dialer with */
483032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    private boolean isDialIntent(Intent intent) {
484032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        final String action = intent.getAction();
485032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        if (Intent.ACTION_DIAL.equals(action)) {
486032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            return true;
487032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        }
488032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        if (Intent.ACTION_VIEW.equals(action)) {
489032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            final Uri data = intent.getData();
490032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            if (data != null && "tel".equals(data.getScheme())) {
491032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov                return true;
492032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            }
493032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        }
494032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        return false;
495032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    }
49608832404d96360ac386a98fd977e45fde936ec30Nicolas Catania
497903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton    /**
498903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton     * Retrieves the filter text stored in {@link #setupFilterText(Intent)}.
499903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton     * This text originally came from a FILTER_CONTACTS_ACTION intent received
500903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton     * by this activity. The stored text will then be cleared after after this
501903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton     * method returns.
50208832404d96360ac386a98fd977e45fde936ec30Nicolas Catania     *
503903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton     * @return The stored filter text
504903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton     */
505903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton    public String getAndClearFilterText() {
506903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton        String filterText = mFilterText;
507903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton        mFilterText = null;
508903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton        return filterText;
509903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton    }
510903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton
511903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton    /**
512903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton     * Stores the filter text associated with a FILTER_CONTACTS_ACTION intent.
513903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton     * This is so child activities can check if they are supposed to display a filter.
51408832404d96360ac386a98fd977e45fde936ec30Nicolas Catania     *
515903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton     * @param intent The intent received in {@link #onNewIntent(Intent)}
516903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton     */
517903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton    private void setupFilterText(Intent intent) {
518903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton        // If the intent was relaunched from history, don't apply the filter text.
519903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton        if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) {
520903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton            return;
521903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton        }
522b25c13ec8b060cc74f91285929c4535adf4260f0Jeff Hamilton        String filter = intent.getStringExtra(UI.FILTER_TEXT_EXTRA_KEY);
523903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton        if (filter != null && filter.length() > 0) {
524903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton            mFilterText = filter;
525903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton        }
526903137768d56ca85d026c2f4b92e4ace6e068d3bJeff Hamilton    }
527032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov
528032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    /**
529032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov     * Retrieves the uri stored in {@link #setupDialUri(Intent)}. This uri
530032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov     * originally came from a dial intent received by this activity. The stored
531032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov     * uri will then be cleared after after this method returns.
53208832404d96360ac386a98fd977e45fde936ec30Nicolas Catania     *
533032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov     * @return The stored uri
534032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov     */
535032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    public Uri getAndClearDialUri() {
536032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        Uri dialUri = mDialUri;
537032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        mDialUri = null;
538032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        return dialUri;
539032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    }
540032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov
541032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    /**
542032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov     * Stores the uri associated with a dial intent. This is so child activities can
543032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov     * check if they are supposed to display new dial info.
54408832404d96360ac386a98fd977e45fde936ec30Nicolas Catania     *
545032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov     * @param intent The intent received in {@link #onNewIntent(Intent)}
546032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov     */
547032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    private void setupDialUri(Intent intent) {
548032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        // If the intent was relaunched from history, don't reapply the intent.
549032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) {
550032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            return;
551032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        }
552032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        mDialUri = intent.getData();
553032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    }
554032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov
555032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    @Override
556242599a0f1ab23e2a46eff963484a70ec7981befDianne Hackborn    public void onBackPressed() {
557b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        if (mInSearchUi) {
558b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa            // We should let the user go back to usual screens with tabs.
559b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa            exitSearchUi();
560b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        } else if (isTaskRoot()) {
561032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            // Instead of stopping, simply push this to the back of the stack.
562032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            // This is only done when running at the top of the stack;
563032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            // otherwise, we have been launched by someone else so need to
564032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            // allow the user to go back to the caller.
565032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov            moveTaskToBack(false);
566242599a0f1ab23e2a46eff963484a70ec7981befDianne Hackborn        } else {
567242599a0f1ab23e2a46eff963484a70ec7981befDianne Hackborn            super.onBackPressed();
568032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov        }
569032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov    }
570032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov
57143105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa    private DialpadFragment.Listener mDialpadListener = new DialpadFragment.Listener() {
572c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        @Override
57343105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        public void onSearchButtonPressed() {
57443105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            enterSearchUi();
575c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        }
57643105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa    };
577c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann
5787979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro    private ContactTileListFragment.Listener mStrequentListener =
5797979ea27c046dfc2d9305b3282233046acef6ec4Frank Sposaro            new ContactTileListFragment.Listener() {
58032f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro        @Override
58132f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro        public void onContactSelected(Uri contactUri) {
582b1f0e5e8a4de69bd80276742900441e930fa4c86Daisuke Miyakawa            PhoneNumberInteraction.startInteractionForPhoneCall(
583b1f0e5e8a4de69bd80276742900441e930fa4c86Daisuke Miyakawa                    DialtactsActivity.this, contactUri);
58432f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro        }
58532f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro    };
58632f395567c9d103e9101c2549f76945c9dee20b5Frank Sposaro
587c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann    @Override
588c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann    public boolean onCreateOptionsMenu(Menu menu) {
589c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        MenuInflater inflater = getMenuInflater();
590aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa        inflater.inflate(R.menu.dialtacts_options, menu);
591c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        return true;
592c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann    }
593c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann
594c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann    @Override
595aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa    public boolean onPrepareOptionsMenu(Menu menu) {
596aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa        final MenuItem searchMenuItem = menu.findItem(R.id.search_on_action_bar);
597aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa        if (mInSearchUi || getActionBar().getSelectedTab().getPosition() == TAB_INDEX_DIALER) {
598aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa            searchMenuItem.setVisible(false);
599aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa        } else {
600aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa            searchMenuItem.setVisible(true);
601aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa            searchMenuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() {
602aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa                @Override
603aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa                public boolean onMenuItemClick(MenuItem item) {
604aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa                    enterSearchUi();
605aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa                    return true;
606aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa                }
607c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann            });
608c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann        }
609aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa
610aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa        return true;
611c15062754af08cadc50b4b8ec89c2175a4bec1feDaniel Lehmann    }
612b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa
613b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa    @Override
614b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa    public void startSearch(String initialQuery, boolean selectInitialQuery,
615b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa            Bundle appSearchData, boolean globalSearch) {
61643105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        if (mSearchFragment != null && mSearchFragment.isAdded() && !globalSearch) {
617b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa            enterSearchUi();
618b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        } else {
619b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa            super.startSearch(initialQuery, selectInitialQuery, appSearchData, globalSearch);
620b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        }
621b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa    }
622b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa
623b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa    /**
624b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa     * Hides every tab and shows search UI for phone lookup.
625b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa     */
626b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa    private void enterSearchUi() {
627b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        final ActionBar actionBar = getActionBar();
628b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa
629b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        final Tab tab = actionBar.getSelectedTab();
630c18f9b7cb0846d0c10fe0398224b53530a2194ecDaisuke Miyakawa
631c18f9b7cb0846d0c10fe0398224b53530a2194ecDaisuke Miyakawa        // User can search during the call, but we don't want to remember the status.
632c18f9b7cb0846d0c10fe0398224b53530a2194ecDaisuke Miyakawa        if (tab != null && !DialpadFragment.phoneIsInUse()) {
633aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa            mLastManuallySelectedFragment = tab.getPosition();
634b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        }
635b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa
636b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        // Instantiate or reset SearchView in ActionBar.
637b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        if (mSearchView == null) {
638b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa            // TODO: layout is not what we want. Need "up" button instead of "close" button, etc.
639b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa            final View searchViewLayout =
640b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa                    getLayoutInflater().inflate(R.layout.custom_action_bar, null);
641b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa            mSearchView = (SearchView) searchViewLayout.findViewById(R.id.search_view);
642b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa            mSearchView.setQueryHint(getString(R.string.hint_findContacts));
643b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa            mSearchView.setOnQueryTextListener(mPhoneSearchQueryTextListener);
644b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa            mSearchView.setOnCloseListener(mPhoneSearchCloseListener);
645b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa            mSearchView.requestFocus();
64636c33609482ae5c961ac5f3b67c581a0bb430f38Daisuke Miyakawa            // Show soft keyboard when SearchView has a focus. Need to delay the request in order
64736c33609482ae5c961ac5f3b67c581a0bb430f38Daisuke Miyakawa            // to let InputMethodManager handle it correctly.
648c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani            mSearchView.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
649c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani                @Override
650c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani                public void onViewDetachedFromWindow(View v) {
651c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani                }
652c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani
653c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani                @Override
654c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani                public void onViewAttachedToWindow(View v) {
655c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani                    if (mSearchView.hasFocus()) {
656c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani                        mSearchView.postDelayed(new Runnable() {
657c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani                            public void run() {
658c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani                                showInputMethod(mSearchView.findFocus());
659c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani                            }
660c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani                        }, 0);
661c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani                    }
662c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani                }
663c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani            });
664b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa            actionBar.setCustomView(searchViewLayout,
665b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa                    new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
666b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        } else {
667b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa            mSearchView.setQuery(null, true);
668b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        }
669b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa
670b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        actionBar.setDisplayShowCustomEnabled(true);
671b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
67288f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa        actionBar.setDisplayShowHomeEnabled(true);
67388f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa        actionBar.setDisplayHomeAsUpEnabled(true);
674b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa
67543105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        sendFragmentVisibilityChange(mViewPager.getCurrentItem(), false);
67643105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa
677b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        // Show the search fragment and hide everything else.
678b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        final FragmentTransaction transaction = getFragmentManager().beginTransaction();
679aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa        transaction.show(mSearchFragment);
680b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        transaction.commit();
681438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa        mViewPager.setVisibility(View.GONE);
682b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa
683b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        mInSearchUi = true;
684b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa    }
685b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa
686c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani    private void showInputMethod(View view) {
687c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani        InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
688c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani        if (imm != null) {
689c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani            imm.showSoftInput(view, 0);
690c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani        }
691c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani    }
692c5be9585f664a893392486e3f86c67f3e083f271Amith Yamasani
69388f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa    private void hideInputMethod(View view) {
69488f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa        InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
69588f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa        if (imm != null) {
69688f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa            imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
69788f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa        }
69888f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa    }
69988f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa
700b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa    /**
701b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa     * Goes back to usual Phone UI with tags. Previously selected Tag and associated Fragment
702b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa     * should be automatically focused again.
703b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa     */
704b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa    private void exitSearchUi() {
705b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        final ActionBar actionBar = getActionBar();
706b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa
707b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        // We want to hide SearchView and show Tabs. Also focus on previously selected one.
708b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        actionBar.setDisplayShowCustomEnabled(false);
70988f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa        actionBar.setDisplayShowHomeEnabled(false);
710b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
711b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa
71243105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        sendFragmentVisibilityChange(mViewPager.getCurrentItem(), true);
71343105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa
714438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa        final FragmentTransaction transaction = getFragmentManager().beginTransaction();
715aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa        transaction.hide(mSearchFragment);
716438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa        transaction.commit();
717438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa
718438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa        mViewPager.setVisibility(View.VISIBLE);
719438e1f19279ea058e145c84dbe3ba62cc14df645Daisuke Miyakawa
72088f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa        hideInputMethod(getCurrentFocus());
72188f70fc83cdd119e85d9890b2875faf5c981b47dDaisuke Miyakawa
722350e8d53a135e0bb62308a93dd09777364c08a58Daisuke Miyakawa        // Request to update option menu.
723350e8d53a135e0bb62308a93dd09777364c08a58Daisuke Miyakawa        invalidateOptionsMenu();
724350e8d53a135e0bb62308a93dd09777364c08a58Daisuke Miyakawa
725b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa        mInSearchUi = false;
726b2e626ad4fedc0fd726f66b9942d1b2f30d9cfefDaisuke Miyakawa    }
727aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa
728aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa    private Fragment getFragmentAt(int position) {
729aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa        switch (position) {
730aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa            case TAB_INDEX_DIALER:
731aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa                return mDialpadFragment;
732aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa            case TAB_INDEX_CALL_LOG:
733aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa                return mCallLogFragment;
734aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa            case TAB_INDEX_FAVORITES:
735aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa                return mStrequentFragment;
736aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa            default:
737aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa                throw new IllegalStateException("Unknown fragment index: " + position);
738aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa        }
739aa72f08effc0b2bac7c56dd2fed9bbeae3a6f109Daisuke Miyakawa    }
74043105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa
74143105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa    private void sendFragmentVisibilityChange(int position, boolean visibility) {
74243105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        final Fragment fragment = getFragmentAt(position);
74343105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        if (fragment instanceof ViewPagerVisibilityListener) {
74443105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa            ((ViewPagerVisibilityListener) fragment).onVisibilityChanged(visibility);
74543105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa        }
74643105d0b04963ac96acc1fa7f97278f927f48948Daisuke Miyakawa    }
747bd762dc826d85e5b7db634ef14a0dbb70c42eaabDaisuke Miyakawa
748bd762dc826d85e5b7db634ef14a0dbb70c42eaabDaisuke Miyakawa    /** Returns an Intent to launch Call Settings screen */
749bd762dc826d85e5b7db634ef14a0dbb70c42eaabDaisuke Miyakawa    public static Intent getCallSettingsIntent() {
750bd762dc826d85e5b7db634ef14a0dbb70c42eaabDaisuke Miyakawa        final Intent intent = new Intent(Intent.ACTION_MAIN);
751bd762dc826d85e5b7db634ef14a0dbb70c42eaabDaisuke Miyakawa        intent.setClassName(PHONE_PACKAGE, CALL_SETTINGS_CLASS_NAME);
752bd762dc826d85e5b7db634ef14a0dbb70c42eaabDaisuke Miyakawa        return intent;
753bd762dc826d85e5b7db634ef14a0dbb70c42eaabDaisuke Miyakawa    }
754032bb36086d55529b59cbd6ea03d2f9b6cfe36afDmitri Plotnikov}
755