summaryrefslogtreecommitdiff
path: root/src/com/android/dialer/dialpad/DialpadFragment.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/dialer/dialpad/DialpadFragment.java')
-rw-r--r--src/com/android/dialer/dialpad/DialpadFragment.java181
1 files changed, 137 insertions, 44 deletions
diff --git a/src/com/android/dialer/dialpad/DialpadFragment.java b/src/com/android/dialer/dialpad/DialpadFragment.java
index 2b77b4619..f7a9056f5 100644
--- a/src/com/android/dialer/dialpad/DialpadFragment.java
+++ b/src/com/android/dialer/dialpad/DialpadFragment.java
@@ -31,6 +31,7 @@ import android.graphics.BitmapFactory;
import android.media.AudioManager;
import android.media.ToneGenerator;
import android.net.Uri;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -39,6 +40,7 @@ import android.provider.Contacts.Intents.Insert;
import android.provider.Contacts.People;
import android.provider.Contacts.Phones;
import android.provider.Contacts.PhonesColumns;
+import android.provider.ContactsContract.Contacts;
import android.provider.Settings;
import android.telephony.PhoneNumberUtils;
import android.telephony.PhoneStateListener;
@@ -59,6 +61,7 @@ import android.view.MenuItem;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
+import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.EditText;
@@ -68,9 +71,12 @@ import android.widget.PopupMenu;
import android.widget.TextView;
import com.android.contacts.common.CallUtil;
+import com.android.contacts.common.activity.TransactionSafeActivity;
+import com.android.dialer.interactions.PhoneNumberInteraction;
import com.android.contacts.common.GeoUtil;
import com.android.contacts.common.util.PhoneNumberFormatter;
import com.android.contacts.common.util.StopWatch;
+import com.android.contacts.common.preference.ContactsPreferences;
import com.android.dialer.DialtactsActivity;
import com.android.dialer.R;
import com.android.dialer.SpecialCharSequenceMgr;
@@ -79,6 +85,9 @@ import com.android.internal.telephony.ITelephony;
import com.android.phone.common.CallLogAsync;
import com.android.phone.common.HapticFeedback;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Fragment that displays a twelve-key phone dialpad.
*/
@@ -87,7 +96,8 @@ public class DialpadFragment extends Fragment
View.OnLongClickListener, View.OnKeyListener,
AdapterView.OnItemClickListener, TextWatcher,
PopupMenu.OnMenuItemClickListener,
- DialpadImageButton.OnPressedListener {
+ DialpadImageButton.OnPressedListener,
+ SmartDialLoaderTask.SmartDialLoaderCallback {
private static final String TAG = DialpadFragment.class.getSimpleName();
private static final boolean DEBUG = DialtactsActivity.DEBUG;
@@ -104,6 +114,8 @@ public class DialpadFragment extends Fragment
/** Stream type used to play the DTMF tones off call, and mapped to the volume control keys */
private static final int DIAL_TONE_STREAM_TYPE = AudioManager.STREAM_DTMF;
+ private ContactsPreferences mContactsPrefs;
+
/**
* View (usually FrameLayout) containing mDigits field. This can be null, in which mDigits
* isn't enclosed by the container.
@@ -131,6 +143,15 @@ public class DialpadFragment extends Fragment
private ListView mDialpadChooser;
private DialpadChooserAdapter mDialpadChooserAdapter;
+ /** Will be set only if the view has the smart dialing section. */
+ private AbsListView mSmartDialList;
+
+ /**
+ * Adapter for {@link #mSmartDialList}.
+ * Will be set only if the view has the smart dialing section.
+ */
+ private SmartDialAdapter mSmartDialAdapter;
+
/**
* Regular expression prohibiting manual phone call. Can be empty, which means "no rule".
*/
@@ -149,6 +170,7 @@ public class DialpadFragment extends Fragment
// Vibration (haptic feedback) for dialer key presses.
private final HapticFeedback mHaptic = new HapticFeedback();
+ private boolean mNeedToCacheSmartDial = false;
/** Identifier for the "Add Call" intent extra. */
private static final String ADD_CALL_MODE_KEY = "add_call_mode";
@@ -199,6 +221,8 @@ public class DialpadFragment extends Fragment
*/
private boolean mDigitsFilledByIntent;
+ private boolean mStartedFromNewIntent = false;
+
private static final String PREF_DIGITS_FILLED_BY_INTENT = "pref_digits_filled_by_intent";
/**
@@ -246,14 +270,16 @@ public class DialpadFragment extends Fragment
}
updateDialAndDeleteButtonEnabledState();
+ loadSmartDialEntries();
}
@Override
public void onCreate(Bundle state) {
super.onCreate(state);
+ mContactsPrefs = new ContactsPreferences(getActivity());
mCurrentCountryIso = GeoUtil.getCurrentCountryIso(getActivity());
-
+ mNeedToCacheSmartDial = true;
try {
mHaptic.init(getActivity(),
getResources().getBoolean(R.bool.config_enable_dialer_key_vibration));
@@ -269,6 +295,13 @@ public class DialpadFragment extends Fragment
if (state != null) {
mDigitsFilledByIntent = state.getBoolean(PREF_DIGITS_FILLED_BY_INTENT);
}
+
+ // Start caching contacts to use for smart dialling only if the dialpad fragment is visible
+ if (getUserVisibleHint()) {
+ SmartDialLoaderTask.startCacheContactsTaskIfNeeded(
+ getActivity(), mContactsPrefs.getDisplayOrder());
+ mNeedToCacheSmartDial = false;
+ }
}
@Override
@@ -334,7 +367,13 @@ public class DialpadFragment extends Fragment
mDialpadChooser = (ListView) fragmentView.findViewById(R.id.dialpadChooser);
mDialpadChooser.setOnItemClickListener(this);
- configureScreenFromIntent(getActivity().getIntent());
+ // Smart dial
+ mSmartDialList = (AbsListView) fragmentView.findViewById(R.id.dialpad_smartdial_list);
+ if (mSmartDialList != null) {
+ mSmartDialAdapter = new SmartDialAdapter(getActivity());
+ mSmartDialList.setAdapter(mSmartDialAdapter);
+ mSmartDialList.setOnItemClickListener(new OnSmartDialItemClick());
+ }
return fragmentView;
}
@@ -392,45 +431,11 @@ public class DialpadFragment extends Fragment
}
/**
- * @see #showDialpadChooser(boolean)
+ * Determines whether an add call operation is requested.
+ *
+ * @param intent The intent.
+ * @return {@literal true} if add call operation was requested. {@literal false} otherwise.
*/
- private static boolean needToShowDialpadChooser(Intent intent, boolean isAddCallMode) {
- final String action = intent.getAction();
-
- boolean needToShowDialpadChooser = false;
-
- if (Intent.ACTION_DIAL.equals(action) || Intent.ACTION_VIEW.equals(action)) {
- Uri uri = intent.getData();
- if (uri == null) {
- // ACTION_DIAL or ACTION_VIEW with no data.
- // This behaves basically like ACTION_MAIN: If there's
- // already an active call, bring up an intermediate UI to
- // make the user confirm what they really want to do.
- // Be sure *not* to show the dialpad chooser if this is an
- // explicit "Add call" action, though.
- if (!isAddCallMode && phoneIsInUse()) {
- needToShowDialpadChooser = true;
- }
- }
- } else if (Intent.ACTION_MAIN.equals(action)) {
- // The MAIN action means we're bringing up a blank dialer
- // (e.g. by selecting the Home shortcut, or tabbing over from
- // Contacts or Call log.)
- //
- // At this point, IF there's already an active call, there's a
- // good chance that the user got here accidentally (but really
- // wanted the in-call dialpad instead). So we bring up an
- // intermediate UI to make the user confirm what they really
- // want to do.
- if (phoneIsInUse()) {
- // Log.i(TAG, "resolveIntent(): phone is in use; showing dialpad chooser!");
- needToShowDialpadChooser = true;
- }
- }
-
- return needToShowDialpadChooser;
- }
-
private static boolean isAddCallMode(Intent intent) {
final String action = intent.getAction();
if (Intent.ACTION_DIAL.equals(action) || Intent.ACTION_VIEW.equals(action)) {
@@ -445,7 +450,7 @@ public class DialpadFragment extends Fragment
* Checks the given Intent and changes dialpad's UI state. For example, if the Intent requires
* the screen to enter "Add Call" mode, this method will show correct UI for the mode.
*/
- public void configureScreenFromIntent(Intent intent) {
+ private void configureScreenFromIntent(Intent intent) {
if (!isLayoutReady()) {
// This happens typically when parent's Activity#onNewIntent() is called while
// Fragment#onCreateView() isn't called yet, and thus we cannot configure Views at
@@ -458,16 +463,37 @@ public class DialpadFragment extends Fragment
boolean needToShowDialpadChooser = false;
+ // Be sure *not* to show the dialpad chooser if this is an
+ // explicit "Add call" action, though.
final boolean isAddCallMode = isAddCallMode(intent);
if (!isAddCallMode) {
+
+ // Don't show the chooser when called via onNewIntent() and phone number is present.
+ // i.e. User clicks a telephone link from gmail for example.
+ // In this case, we want to show the dialpad with the phone number.
final boolean digitsFilled = fillDigitsIfNecessary(intent);
- if (!digitsFilled) {
- needToShowDialpadChooser = needToShowDialpadChooser(intent, isAddCallMode);
+ if (!(mStartedFromNewIntent && digitsFilled)) {
+
+ final String action = intent.getAction();
+ if (Intent.ACTION_DIAL.equals(action) || Intent.ACTION_VIEW.equals(action)
+ || Intent.ACTION_MAIN.equals(action)) {
+ // If there's already an active call, bring up an intermediate UI to
+ // make the user confirm what they really want to do.
+ if (phoneIsInUse()) {
+ needToShowDialpadChooser = true;
+ }
+ }
+
}
}
+
showDialpadChooser(needToShowDialpadChooser);
}
+ public void setStartedFromNewIntent(boolean value) {
+ mStartedFromNewIntent = value;
+ }
+
/**
* Sets formatted digits to digits field.
*/
@@ -501,6 +527,13 @@ public class DialpadFragment extends Fragment
}
@Override
+ public void onStart() {
+ super.onStart();
+ configureScreenFromIntent(getActivity().getIntent());
+ setStartedFromNewIntent(false);
+ }
+
+ @Override
public void onResume() {
super.onResume();
@@ -1115,6 +1148,11 @@ public class DialpadFragment extends Fragment
}
}
+ private String getCallOrigin() {
+ return (getActivity() instanceof DialtactsActivity) ?
+ ((DialtactsActivity) getActivity()).getCallOrigin() : null;
+ }
+
private void handleDialButtonClickWithEmptyDigits() {
if (phoneIsCdma() && phoneIsOffhook()) {
// This is really CDMA specific. On GSM is it possible
@@ -1637,4 +1675,59 @@ public class DialpadFragment extends Fragment
intent.putExtra(EXTRA_SEND_EMPTY_FLASH, true);
return intent;
}
+
+ @Override
+ public void setUserVisibleHint(boolean isVisibleToUser) {
+ super.setUserVisibleHint(isVisibleToUser);
+ if (isVisibleToUser && mNeedToCacheSmartDial) {
+ SmartDialLoaderTask.startCacheContactsTaskIfNeeded(
+ getActivity(), mContactsPrefs.getDisplayOrder());
+ mNeedToCacheSmartDial = false;
+ }
+ }
+
+ private String mLastDigitsForSmartDial;
+
+ private void loadSmartDialEntries() {
+ if (mSmartDialAdapter == null) {
+ // No smart dial views. Landscape?
+ return;
+ }
+
+ // Update only when the digits have changed.
+ final String digits = SmartDialNameMatcher.normalizeNumber(mDigits.getText().toString());
+ if (TextUtils.equals(digits, mLastDigitsForSmartDial)) {
+ return;
+ }
+ mLastDigitsForSmartDial = digits;
+
+ if (digits.length() < 2) {
+ mSmartDialAdapter.clear();
+ } else {
+ final SmartDialLoaderTask task = new SmartDialLoaderTask(this, digits);
+ // don't execute this in serial, otherwise we have to wait too long for results
+ task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, new String[] {});
+ }
+ }
+
+ @Override
+ public void setSmartDialAdapterEntries(List<SmartDialEntry> data) {
+ if (data == null || data.isEmpty()) {
+ // No results found. Keep the last results.
+ return;
+ }
+ mSmartDialAdapter.setEntries(data);
+ }
+
+ private class OnSmartDialItemClick implements AdapterView.OnItemClickListener {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ final SmartDialEntry entry = (SmartDialEntry) view.getTag();
+ if (entry == null) return; // just in case.
+
+ mClearDigitsOnStop = true;
+ PhoneNumberInteraction.startInteractionForPhoneCall(
+ (TransactionSafeActivity) getActivity(), entry.contactUri, getCallOrigin());
+ }
+ }
}