summaryrefslogtreecommitdiff
path: root/src/com/android/dialer/dialpad/DialpadFragment.java
diff options
context:
space:
mode:
authorYorke Lee <yorkelee@google.com>2012-11-07 15:11:44 -0800
committerYorke Lee <yorkelee@google.com>2012-11-07 15:50:04 -0800
commit1be0178a11b1cc3b06867b14446e1e041e97a82c (patch)
tree90d972b1c98ce31fee597ba57461741266c0149f /src/com/android/dialer/dialpad/DialpadFragment.java
parent90a85b2201a3e1132124827714ee34e00091036f (diff)
Add smart dialling capabilities to dialer
Layout changes to dialpad fragment to make space for smart dial suggestions. This feature does not appear in landscape mode. SmartDialTextView automatically resizes text to fit within the bounds of the view. SmartDialAdapter highlights certain portions of the matching name based on match positions provided by SmartDialNameMatcher. SmartDialLoaderTask is an AsyncTask that caches all contacts with a phone number into memory, or matches all contact names against a provided query to return a list of matches (maximum of 3). SmartDialNameMatcher contains utility functions to remove accents from accented characters and normalize a phone number. It also contains the matching logic that determines if a contact's display name matches a numeric query. Added some tests for SmartDialNameMatcher Bug: 6977981 Change-Id: I43e1a70d8d0d46e02fc67fe1caaec9a1769124f5
Diffstat (limited to 'src/com/android/dialer/dialpad/DialpadFragment.java')
-rw-r--r--src/com/android/dialer/dialpad/DialpadFragment.java103
1 files changed, 101 insertions, 2 deletions
diff --git a/src/com/android/dialer/dialpad/DialpadFragment.java b/src/com/android/dialer/dialpad/DialpadFragment.java
index 2b77b4619..3af7f9bec 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";
@@ -246,14 +268,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 +293,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,6 +365,14 @@ public class DialpadFragment extends Fragment
mDialpadChooser = (ListView) fragmentView.findViewById(R.id.dialpadChooser);
mDialpadChooser.setOnItemClickListener(this);
+ // 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());
+ }
+
configureScreenFromIntent(getActivity().getIntent());
return fragmentView;
@@ -1115,6 +1154,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 +1681,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());
+ }
+ }
}