blob: dc69194bb91aa5024989784baf6cfd7abe061616 [file] [log] [blame]
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.contacts;
18
Jeff Hamiltondf4b1462010-06-28 10:40:26 -050019import com.android.contacts.activities.ContactsFrontDoor;
Dmitri Plotnikovcfa39002010-07-09 18:05:17 -070020import com.android.contacts.activities.ContactBrowserActivity;
Jeff Hamiltonb25c13e2009-09-21 09:22:16 -050021import com.android.internal.telephony.ITelephony;
22
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080023import android.app.Activity;
24import android.app.TabActivity;
25import android.content.Intent;
Jeff Hamilton90313772009-07-28 10:20:31 -050026import android.content.SharedPreferences;
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080027import android.net.Uri;
28import android.os.Bundle;
29import android.os.RemoteException;
30import android.os.ServiceManager;
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080031import android.provider.CallLog.Calls;
Jeff Hamiltonb25c13e2009-09-21 09:22:16 -050032import android.provider.ContactsContract.Intents.UI;
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080033import android.util.Log;
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080034import android.view.Window;
35import android.widget.TabHost;
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080036
37/**
Nicolas Catania08832402009-09-24 09:52:50 -070038 * The dialer activity that has one tab with the virtual 12key
39 * dialer, a tab with recent calls in it, a tab with the contacts and
40 * a tab with the favorite. This is the container and the tabs are
41 * embedded using intents.
42 * The dialer tab's title is 'phone', a more common name (see strings.xml).
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080043 */
Jeff Hamilton90313772009-07-28 10:20:31 -050044public class DialtactsActivity extends TabActivity implements TabHost.OnTabChangeListener {
45 private static final String TAG = "Dailtacts";
Daniel Lehmann7675e122010-04-21 17:31:11 -070046
The Android Open Source Project1f620962009-03-09 11:52:14 -070047 private static final int TAB_INDEX_DIALER = 0;
48 private static final int TAB_INDEX_CALL_LOG = 1;
Jeff Hamilton90313772009-07-28 10:20:31 -050049 private static final int TAB_INDEX_CONTACTS = 2;
50 private static final int TAB_INDEX_FAVORITES = 3;
Nicolas Catania08832402009-09-24 09:52:50 -070051
The Android Open Source Project1f620962009-03-09 11:52:14 -070052 static final String EXTRA_IGNORE_STATE = "ignore-state";
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080053
Jeff Hamilton90313772009-07-28 10:20:31 -050054 /** Name of the dialtacts shared preferences */
55 static final String PREFS_DIALTACTS = "dialtacts";
56 /** If true, when handling the contacts intent the favorites tab will be shown instead */
57 static final String PREF_FAVORITES_AS_CONTACTS = "favorites_as_contacts";
58 static final boolean PREF_FAVORITES_AS_CONTACTS_DEFAULT = false;
59
Daniel Lehmann7675e122010-04-21 17:31:11 -070060 /** Last manually selected tab index */
61 private static final String PREF_LAST_MANUALLY_SELECTED_TAB = "last_manually_selected_tab";
62 private static final int PREF_LAST_MANUALLY_SELECTED_TAB_DEFAULT = TAB_INDEX_DIALER;
63
The Android Open Source Project1f620962009-03-09 11:52:14 -070064 private TabHost mTabHost;
Nicolas Catania08832402009-09-24 09:52:50 -070065 private String mFilterText;
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080066 private Uri mDialUri;
67
Daniel Lehmann7675e122010-04-21 17:31:11 -070068 /**
69 * The index of the tab that has last been manually selected (the user clicked on a tab).
70 * This value does not keep track of programmatically set Tabs (e.g. Call Log after a Call)
71 */
72 private int mLastManuallySelectedTab;
73
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080074 @Override
75 protected void onCreate(Bundle icicle) {
76 super.onCreate(icicle);
77
78 final Intent intent = getIntent();
79 fixIntent(intent);
Nicolas Catania08832402009-09-24 09:52:50 -070080
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080081 requestWindowFeature(Window.FEATURE_NO_TITLE);
82 setContentView(R.layout.dialer_activity);
83
84 mTabHost = getTabHost();
85 mTabHost.setOnTabChangedListener(this);
86
87 // Setup the tabs
88 setupDialerTab();
89 setupCallLogTab();
Jeff Hamilton90313772009-07-28 10:20:31 -050090 setupContactsTab();
91 setupFavoritesTab();
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080092
Daniel Lehmann7675e122010-04-21 17:31:11 -070093 // Load the last manually loaded tab
94 final SharedPreferences prefs = getSharedPreferences(PREFS_DIALTACTS, MODE_PRIVATE);
95 mLastManuallySelectedTab = prefs.getInt(PREF_LAST_MANUALLY_SELECTED_TAB,
96 PREF_LAST_MANUALLY_SELECTED_TAB_DEFAULT);
97
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -080098 setCurrentTab(intent);
Jeff Hamilton90313772009-07-28 10:20:31 -050099
Jeff Hamilton7fa3cd62010-06-30 11:36:58 -0500100 if (UI.FILTER_CONTACTS_ACTION.equals(intent.getAction())
Jeff Hamilton90313772009-07-28 10:20:31 -0500101 && icicle == null) {
102 setupFilterText(intent);
103 }
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800104 }
105
Jeff Hamilton90313772009-07-28 10:20:31 -0500106 @Override
107 protected void onPause() {
108 super.onPause();
Nicolas Catania08832402009-09-24 09:52:50 -0700109
Daniel Lehmann7675e122010-04-21 17:31:11 -0700110 final int currentTabIndex = mTabHost.getCurrentTab();
111 final SharedPreferences.Editor editor =
112 getSharedPreferences(PREFS_DIALTACTS, MODE_PRIVATE).edit();
Jeff Hamilton90313772009-07-28 10:20:31 -0500113 if (currentTabIndex == TAB_INDEX_CONTACTS || currentTabIndex == TAB_INDEX_FAVORITES) {
Jeff Hamilton90313772009-07-28 10:20:31 -0500114 editor.putBoolean(PREF_FAVORITES_AS_CONTACTS, currentTabIndex == TAB_INDEX_FAVORITES);
Jeff Hamilton90313772009-07-28 10:20:31 -0500115 }
Daniel Lehmann7675e122010-04-21 17:31:11 -0700116 editor.putInt(PREF_LAST_MANUALLY_SELECTED_TAB, mLastManuallySelectedTab);
117
Brad Fitzpatrick909271c2010-09-10 09:50:13 -0700118 editor.apply();
Jeff Hamilton90313772009-07-28 10:20:31 -0500119 }
Nicolas Catania08832402009-09-24 09:52:50 -0700120
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800121 private void fixIntent(Intent intent) {
122 // This should be cleaned up: the call key used to send an Intent
123 // that just said to go to the recent calls list. It now sends this
124 // abstract action, but this class hasn't been rewritten to deal with it.
125 if (Intent.ACTION_CALL_BUTTON.equals(intent.getAction())) {
126 intent.setDataAndType(Calls.CONTENT_URI, Calls.CONTENT_TYPE);
127 intent.putExtra("call_key", true);
128 setIntent(intent);
129 }
130 }
Nicolas Catania08832402009-09-24 09:52:50 -0700131
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800132 private void setupCallLogTab() {
The Android Open Source Project1f620962009-03-09 11:52:14 -0700133 // Force the class since overriding tab entries doesn't work
134 Intent intent = new Intent("com.android.phone.action.RECENT_CALLS");
135 intent.setClass(this, RecentCallsListActivity.class);
136
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800137 mTabHost.addTab(mTabHost.newTabSpec("call_log")
138 .setIndicator(getString(R.string.recentCallsIconLabel),
139 getResources().getDrawable(R.drawable.ic_tab_recent))
The Android Open Source Project1f620962009-03-09 11:52:14 -0700140 .setContent(intent));
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800141 }
142
143 private void setupDialerTab() {
The Android Open Source Project1f620962009-03-09 11:52:14 -0700144 Intent intent = new Intent("com.android.phone.action.TOUCH_DIALER");
145 intent.setClass(this, TwelveKeyDialer.class);
146
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800147 mTabHost.addTab(mTabHost.newTabSpec("dialer")
148 .setIndicator(getString(R.string.dialerIconLabel),
149 getResources().getDrawable(R.drawable.ic_tab_dialer))
The Android Open Source Project1f620962009-03-09 11:52:14 -0700150 .setContent(intent));
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800151 }
152
Jeff Hamilton90313772009-07-28 10:20:31 -0500153 private void setupContactsTab() {
154 Intent intent = new Intent(UI.LIST_DEFAULT);
Dmitri Plotnikovcfa39002010-07-09 18:05:17 -0700155 intent.setClass(this, ContactBrowserActivity.class);
Jeff Hamilton90313772009-07-28 10:20:31 -0500156
157 mTabHost.addTab(mTabHost.newTabSpec("contacts")
158 .setIndicator(getText(R.string.contactsIconLabel),
159 getResources().getDrawable(R.drawable.ic_tab_contacts))
160 .setContent(intent));
161 }
162
163 private void setupFavoritesTab() {
164 Intent intent = new Intent(UI.LIST_STREQUENT_ACTION);
Dmitri Plotnikovcfa39002010-07-09 18:05:17 -0700165 intent.setClass(this, ContactBrowserActivity.class);
Jeff Hamilton90313772009-07-28 10:20:31 -0500166
167 mTabHost.addTab(mTabHost.newTabSpec("favorites")
168 .setIndicator(getString(R.string.contactsFavoritesLabel),
169 getResources().getDrawable(R.drawable.ic_tab_starred))
170 .setContent(intent));
171 }
172
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800173 /**
174 * Returns true if the intent is due to hitting the green send key while in a call.
Nicolas Catania08832402009-09-24 09:52:50 -0700175 *
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800176 * @param intent the intent that launched this activity
177 * @param recentCallsRequest true if the intent is requesting to view recent calls
Nicolas Catania08832402009-09-24 09:52:50 -0700178 * @return true if the intent is due to hitting the green send key while in a call
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800179 */
180 private boolean isSendKeyWhileInCall(final Intent intent, final boolean recentCallsRequest) {
181 // If there is a call in progress go to the call screen
182 if (recentCallsRequest) {
183 final boolean callKey = intent.getBooleanExtra("call_key", false);
184
185 try {
186 ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone"));
187 if (callKey && phone != null && phone.showCallScreen()) {
188 return true;
189 }
190 } catch (RemoteException e) {
191 Log.e(TAG, "Failed to handle send while in call", e);
192 }
193 }
194
195 return false;
196 }
197
198 /**
199 * Sets the current tab based on the intent's request type
Nicolas Catania08832402009-09-24 09:52:50 -0700200 *
Daniel Lehmann7675e122010-04-21 17:31:11 -0700201 * @param intent Intent that contains information about which tab should be selected
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800202 */
203 private void setCurrentTab(Intent intent) {
The Android Open Source Project1f620962009-03-09 11:52:14 -0700204 // If we got here by hitting send and we're in call forward along to the in-call activity
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800205 final boolean recentCallsRequest = Calls.CONTENT_TYPE.equals(intent.getType());
206 if (isSendKeyWhileInCall(intent, recentCallsRequest)) {
207 finish();
208 return;
209 }
Nicolas Catania08832402009-09-24 09:52:50 -0700210
The Android Open Source Project1f620962009-03-09 11:52:14 -0700211 // Dismiss menu provided by any children activities
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800212 Activity activity = getLocalActivityManager().
213 getActivity(mTabHost.getCurrentTabTag());
214 if (activity != null) {
215 activity.closeOptionsMenu();
216 }
217
The Android Open Source Project1f620962009-03-09 11:52:14 -0700218 // Tell the children activities that they should ignore any possible saved
219 // state and instead reload their state from the parent's intent
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800220 intent.putExtra(EXTRA_IGNORE_STATE, true);
The Android Open Source Project1f620962009-03-09 11:52:14 -0700221
Daniel Lehmann7675e122010-04-21 17:31:11 -0700222 // Remember the old manually selected tab index so that it can be restored if it is
223 // overwritten by one of the programmatic tab selections
224 final int savedTabIndex = mLastManuallySelectedTab;
225
The Android Open Source Project1f620962009-03-09 11:52:14 -0700226 // Choose the tab based on the inbound intent
Jeff Hamiltondf4b1462010-06-28 10:40:26 -0500227 if (intent.getBooleanExtra(ContactsFrontDoor.EXTRA_FRONT_DOOR, false)) {
Daniel Lehmanne9b196e2010-10-26 12:17:39 -0700228 // Launched through the contacts front door, set the proper contacts tab (sticky
229 // between favorites and contacts)
230 SharedPreferences prefs = getSharedPreferences(PREFS_DIALTACTS, MODE_PRIVATE);
231 boolean favoritesAsContacts = prefs.getBoolean(PREF_FAVORITES_AS_CONTACTS,
232 PREF_FAVORITES_AS_CONTACTS_DEFAULT);
233 if (favoritesAsContacts) {
234 mTabHost.setCurrentTab(TAB_INDEX_FAVORITES);
235 } else {
236 mTabHost.setCurrentTab(TAB_INDEX_CONTACTS);
237 }
Jeff Hamilton90313772009-07-28 10:20:31 -0500238 } else {
Jeff Hamiltondf4b1462010-06-28 10:40:26 -0500239 // Not launched through the front door, look at the component to determine the tab
240 String componentName = intent.getComponent().getClassName();
241 if (getClass().getName().equals(componentName)) {
242 if (recentCallsRequest) {
243 mTabHost.setCurrentTab(TAB_INDEX_CALL_LOG);
244 } else {
245 mTabHost.setCurrentTab(TAB_INDEX_DIALER);
246 }
Jeff Hamilton90313772009-07-28 10:20:31 -0500247 } else {
Daniel Lehmanne9b196e2010-10-26 12:17:39 -0700248 mTabHost.setCurrentTab(mLastManuallySelectedTab);
Jeff Hamilton90313772009-07-28 10:20:31 -0500249 }
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800250 }
The Android Open Source Project1f620962009-03-09 11:52:14 -0700251
Daniel Lehmann7675e122010-04-21 17:31:11 -0700252 // Restore to the previous manual selection
253 mLastManuallySelectedTab = savedTabIndex;
254
The Android Open Source Project1f620962009-03-09 11:52:14 -0700255 // Tell the children activities that they should honor their saved states
256 // instead of the state from the parent's intent
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800257 intent.putExtra(EXTRA_IGNORE_STATE, false);
258 }
259
260 @Override
261 public void onNewIntent(Intent newIntent) {
262 setIntent(newIntent);
263 fixIntent(newIntent);
264 setCurrentTab(newIntent);
Jeff Hamilton90313772009-07-28 10:20:31 -0500265 final String action = newIntent.getAction();
Jeff Hamilton7fa3cd62010-06-30 11:36:58 -0500266 if (UI.FILTER_CONTACTS_ACTION.equals(action)) {
Jeff Hamilton90313772009-07-28 10:20:31 -0500267 setupFilterText(newIntent);
268 } else if (isDialIntent(newIntent)) {
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800269 setupDialUri(newIntent);
270 }
271 }
The Android Open Source Project1f620962009-03-09 11:52:14 -0700272
273 /** Returns true if the given intent contains a phone number to populate the dialer with */
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800274 private boolean isDialIntent(Intent intent) {
275 final String action = intent.getAction();
276 if (Intent.ACTION_DIAL.equals(action)) {
277 return true;
278 }
279 if (Intent.ACTION_VIEW.equals(action)) {
280 final Uri data = intent.getData();
281 if (data != null && "tel".equals(data.getScheme())) {
282 return true;
283 }
284 }
285 return false;
286 }
Nicolas Catania08832402009-09-24 09:52:50 -0700287
Jeff Hamilton90313772009-07-28 10:20:31 -0500288 /**
289 * Retrieves the filter text stored in {@link #setupFilterText(Intent)}.
290 * This text originally came from a FILTER_CONTACTS_ACTION intent received
291 * by this activity. The stored text will then be cleared after after this
292 * method returns.
Nicolas Catania08832402009-09-24 09:52:50 -0700293 *
Jeff Hamilton90313772009-07-28 10:20:31 -0500294 * @return The stored filter text
295 */
296 public String getAndClearFilterText() {
297 String filterText = mFilterText;
298 mFilterText = null;
299 return filterText;
300 }
301
302 /**
303 * Stores the filter text associated with a FILTER_CONTACTS_ACTION intent.
304 * This is so child activities can check if they are supposed to display a filter.
Nicolas Catania08832402009-09-24 09:52:50 -0700305 *
Jeff Hamilton90313772009-07-28 10:20:31 -0500306 * @param intent The intent received in {@link #onNewIntent(Intent)}
307 */
308 private void setupFilterText(Intent intent) {
309 // If the intent was relaunched from history, don't apply the filter text.
310 if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) {
311 return;
312 }
Jeff Hamiltonb25c13e2009-09-21 09:22:16 -0500313 String filter = intent.getStringExtra(UI.FILTER_TEXT_EXTRA_KEY);
Jeff Hamilton90313772009-07-28 10:20:31 -0500314 if (filter != null && filter.length() > 0) {
315 mFilterText = filter;
316 }
317 }
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800318
319 /**
320 * Retrieves the uri stored in {@link #setupDialUri(Intent)}. This uri
321 * originally came from a dial intent received by this activity. The stored
322 * uri will then be cleared after after this method returns.
Nicolas Catania08832402009-09-24 09:52:50 -0700323 *
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800324 * @return The stored uri
325 */
326 public Uri getAndClearDialUri() {
327 Uri dialUri = mDialUri;
328 mDialUri = null;
329 return dialUri;
330 }
331
332 /**
333 * Stores the uri associated with a dial intent. This is so child activities can
334 * check if they are supposed to display new dial info.
Nicolas Catania08832402009-09-24 09:52:50 -0700335 *
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800336 * @param intent The intent received in {@link #onNewIntent(Intent)}
337 */
338 private void setupDialUri(Intent intent) {
339 // If the intent was relaunched from history, don't reapply the intent.
340 if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) {
341 return;
342 }
343 mDialUri = intent.getData();
344 }
345
346 @Override
Dianne Hackborn242599a2009-09-14 21:33:24 -0700347 public void onBackPressed() {
348 if (isTaskRoot()) {
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800349 // Instead of stopping, simply push this to the back of the stack.
350 // This is only done when running at the top of the stack;
351 // otherwise, we have been launched by someone else so need to
352 // allow the user to go back to the caller.
353 moveTaskToBack(false);
Dianne Hackborn242599a2009-09-14 21:33:24 -0700354 } else {
355 super.onBackPressed();
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800356 }
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800357 }
358
359 /** {@inheritDoc} */
360 public void onTabChanged(String tabId) {
361 // Because we're using Activities as our tab children, we trigger
362 // onWindowFocusChanged() to let them know when they're active. This may
363 // seem to duplicate the purpose of onResume(), but it's needed because
364 // onResume() can't reliably check if a keyguard is active.
365 Activity activity = getLocalActivityManager().getActivity(tabId);
366 if (activity != null) {
367 activity.onWindowFocusChanged(true);
368 }
Daniel Lehmann7675e122010-04-21 17:31:11 -0700369
370 // Remember this tab index. This function is also called, if the tab is set automatically
371 // in which case the setter (setCurrentTab) has to set this to its old value afterwards
372 mLastManuallySelectedTab = mTabHost.getCurrentTab();
The Android Open Source Project7aa0e4c2009-03-03 19:32:21 -0800373 }
374}