summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--java/com/android/incallui/DialpadFragment.java178
-rw-r--r--java/com/android/incallui/DtmfKeyListener.java156
2 files changed, 166 insertions, 168 deletions
diff --git a/java/com/android/incallui/DialpadFragment.java b/java/com/android/incallui/DialpadFragment.java
index fbcd4078e..2f3a68cda 100644
--- a/java/com/android/incallui/DialpadFragment.java
+++ b/java/com/android/incallui/DialpadFragment.java
@@ -18,8 +18,6 @@ package com.android.incallui;
import android.content.Context;
import android.os.Bundle;
-import android.text.Editable;
-import android.text.method.DialerKeyListener;
import android.util.ArrayMap;
import android.util.AttributeSet;
import android.view.KeyEvent;
@@ -32,6 +30,7 @@ import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.contacts.common.compat.PhoneNumberUtilsCompat;
+import com.android.dialer.common.LogUtil;
import com.android.dialer.dialpadview.DialpadKeyButton;
import com.android.dialer.dialpadview.DialpadKeyButton.OnPressedListener;
import com.android.dialer.dialpadview.DialpadView;
@@ -82,7 +81,7 @@ public class DialpadFragment extends BaseFragment<DialpadPresenter, DialpadUi>
};
private EditText mDtmfDialerField;
// KeyListener used with the "dialpad digits" EditText widget.
- private DTMFKeyListener mDialerKeyListener;
+ private DtmfKeyListener mDtmfKeyListener;
private DialpadView mDialpadView;
private int mCurrentTextColor;
@@ -141,8 +140,9 @@ public class DialpadFragment extends BaseFragment<DialpadPresenter, DialpadUi>
mDialpadView.setBackgroundResource(R.color.incall_dialpad_background);
mDtmfDialerField = (EditText) parent.findViewById(R.id.digits);
if (mDtmfDialerField != null) {
- mDialerKeyListener = new DTMFKeyListener();
- mDtmfDialerField.setKeyListener(mDialerKeyListener);
+ LogUtil.i("DialpadFragment.onCreateView", "creating dtmfKeyListener");
+ mDtmfKeyListener = new DtmfKeyListener(getPresenter());
+ mDtmfDialerField.setKeyListener(mDtmfKeyListener);
// remove the long-press context menus that support
// the edit (copy / paste / select) functions.
mDtmfDialerField.setLongClickable(false);
@@ -180,7 +180,7 @@ public class DialpadFragment extends BaseFragment<DialpadPresenter, DialpadUi>
@Override
public void onDestroyView() {
- mDialerKeyListener = null;
+ mDtmfKeyListener = null;
super.onDestroyView();
}
@@ -236,8 +236,8 @@ public class DialpadFragment extends BaseFragment<DialpadPresenter, DialpadUi>
/** Called externally (from InCallScreen) to play a DTMF Tone. */
/* package */ boolean onDialerKeyDown(KeyEvent event) {
Log.d(this, "Notifying dtmf key down.");
- if (mDialerKeyListener != null) {
- return mDialerKeyListener.onKeyDown(event);
+ if (mDtmfKeyListener != null) {
+ return mDtmfKeyListener.onKeyDown(event);
} else {
return false;
}
@@ -246,8 +246,8 @@ public class DialpadFragment extends BaseFragment<DialpadPresenter, DialpadUi>
/** Called externally (from InCallScreen) to cancel the last DTMF Tone played. */
public boolean onDialerKeyUp(KeyEvent event) {
Log.d(this, "Notifying dtmf key up.");
- if (mDialerKeyListener != null) {
- return mDialerKeyListener.onKeyUp(event);
+ if (mDtmfKeyListener != null) {
+ return mDtmfKeyListener.onKeyUp(event);
} else {
return false;
}
@@ -307,162 +307,4 @@ public class DialpadFragment extends BaseFragment<DialpadPresenter, DialpadUi>
setTranslationY(yFraction * getHeight());
}
}
-
- /**
- * Our own key listener, specialized for dealing with DTMF codes. 1. Ignore the backspace since it
- * is irrelevant. 2. Allow ONLY valid DTMF characters to generate a tone and be sent as a DTMF
- * code. 3. All other remaining characters are handled by the superclass.
- *
- * <p>This code is purely here to handle events from the hardware keyboard while the DTMF dialpad
- * is up.
- */
- private class DTMFKeyListener extends DialerKeyListener {
-
- /**
- * Overrides the characters used in {@link DialerKeyListener#CHARACTERS} These are the valid
- * dtmf characters.
- */
- public final char[] dtmfCharacters =
- new char[] {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '#', '*'};
-
- private DTMFKeyListener() {
- super();
- }
-
- /** Overriden to return correct DTMF-dialable characters. */
- @Override
- protected char[] getAcceptedChars() {
- return dtmfCharacters;
- }
-
- /** special key listener ignores backspace. */
- @Override
- public boolean backspace(View view, Editable content, int keyCode, KeyEvent event) {
- return false;
- }
-
- /**
- * Overriden so that with each valid button press, we start sending a dtmf code and play a local
- * dtmf tone.
- */
- @Override
- public boolean onKeyDown(View view, Editable content, int keyCode, KeyEvent event) {
- // if (DBG) log("DTMFKeyListener.onKeyDown, keyCode " + keyCode + ", view " + view);
-
- // find the character
- char c = (char) lookup(event, content);
-
- // if not a long press, and parent onKeyDown accepts the input
- if (event.getRepeatCount() == 0 && super.onKeyDown(view, content, keyCode, event)) {
-
- boolean keyOK = ok(getAcceptedChars(), c);
-
- // if the character is a valid dtmf code, start playing the tone and send the
- // code.
- if (keyOK) {
- Log.d(this, "DTMFKeyListener reading '" + c + "' from input.");
- getPresenter().processDtmf(c);
- } else {
- Log.d(this, "DTMFKeyListener rejecting '" + c + "' from input.");
- }
- return true;
- }
- return false;
- }
-
- /**
- * Overriden so that with each valid button up, we stop sending a dtmf code and the dtmf tone.
- */
- @Override
- public boolean onKeyUp(View view, Editable content, int keyCode, KeyEvent event) {
- // if (DBG) log("DTMFKeyListener.onKeyUp, keyCode " + keyCode + ", view " + view);
-
- super.onKeyUp(view, content, keyCode, event);
-
- // find the character
- char c = (char) lookup(event, content);
-
- boolean keyOK = ok(getAcceptedChars(), c);
-
- if (keyOK) {
- Log.d(this, "Stopping the tone for '" + c + "'");
- getPresenter().stopDtmf();
- return true;
- }
-
- return false;
- }
-
- /** Handle individual keydown events when we DO NOT have an Editable handy. */
- public boolean onKeyDown(KeyEvent event) {
- char c = lookup(event);
- Log.d(this, "DTMFKeyListener.onKeyDown: event '" + c + "'");
-
- // if not a long press, and parent onKeyDown accepts the input
- if (event.getRepeatCount() == 0 && c != 0) {
- // if the character is a valid dtmf code, start playing the tone and send the
- // code.
- if (ok(getAcceptedChars(), c)) {
- Log.d(this, "DTMFKeyListener reading '" + c + "' from input.");
- getPresenter().processDtmf(c);
- return true;
- } else {
- Log.d(this, "DTMFKeyListener rejecting '" + c + "' from input.");
- }
- }
- return false;
- }
-
- /**
- * Handle individual keyup events.
- *
- * @param event is the event we are trying to stop. If this is null, then we just force-stop the
- * last tone without checking if the event is an acceptable dialer event.
- */
- public boolean onKeyUp(KeyEvent event) {
- if (event == null) {
- //the below piece of code sends stopDTMF event unnecessarily even when a null event
- //is received, hence commenting it.
- /*if (DBG) log("Stopping the last played tone.");
- stopTone();*/
- return true;
- }
-
- char c = lookup(event);
- Log.d(this, "DTMFKeyListener.onKeyUp: event '" + c + "'");
-
- // TODO: stopTone does not take in character input, we may want to
- // consider checking for this ourselves.
- if (ok(getAcceptedChars(), c)) {
- Log.d(this, "Stopping the tone for '" + c + "'");
- getPresenter().stopDtmf();
- return true;
- }
-
- return false;
- }
-
- /**
- * Find the Dialer Key mapped to this event.
- *
- * @return The char value of the input event, otherwise 0 if no matching character was found.
- */
- private char lookup(KeyEvent event) {
- // This code is similar to {@link DialerKeyListener#lookup(KeyEvent, Spannable) lookup}
- int meta = event.getMetaState();
- int number = event.getNumber();
-
- if (!((meta & (KeyEvent.META_ALT_ON | KeyEvent.META_SHIFT_ON)) == 0) || (number == 0)) {
- int match = event.getMatch(getAcceptedChars(), meta);
- number = (match != 0) ? match : number;
- }
-
- return (char) number;
- }
-
- /** Check to see if the keyEvent is dialable. */
- boolean isKeyEventAcceptable(KeyEvent event) {
- return (ok(getAcceptedChars(), lookup(event)));
- }
- }
}
diff --git a/java/com/android/incallui/DtmfKeyListener.java b/java/com/android/incallui/DtmfKeyListener.java
new file mode 100644
index 000000000..a2a0de09e
--- /dev/null
+++ b/java/com/android/incallui/DtmfKeyListener.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.incallui;
+
+import android.support.annotation.NonNull;
+import android.text.Editable;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.method.DialerKeyListener;
+import android.view.KeyEvent;
+import android.view.View;
+import com.android.dialer.common.LogUtil;
+
+/**
+ * Key listener specialized to deal with Dtmf codes.
+ *
+ * <p>This listener will listen for valid Dtmf characters, and in response will inform the
+ * associated presenter of the character. As an implementation of {@link DialerKeyListener}, this
+ * class will listen for <b>hardware keyboard</b> events.
+ *
+ * <p>From legacy documentation:
+ *
+ * <ul>
+ * <li>Ignores the backspace since it is irrelevant.
+ * <li>Allow ONLY valid DTMF characters to generate a tone and be sent as a DTMF code.
+ * <li>All other remaining characters are handled by the superclass.
+ * <li>This code is purely here to handle events from the hardware keyboard while the DTMF dialpad
+ * is up.
+ * </ul>
+ */
+final class DtmfKeyListener extends DialerKeyListener {
+ /**
+ * Overrides the characters used in {@link DialerKeyListener#CHARACTERS} These are the valid dtmf
+ * characters.
+ */
+ private static final char[] VALID_DTMF_CHARACTERS =
+ new char[] {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '#', '*'};
+
+ /**
+ * Spannable used to call {@link DialerKeyListener#lookup(KeyEvent, Spannable)}, so it's not
+ * necessary to copy the implementation.
+ *
+ * <p>The Spannable is only used to determine which meta keys are pressed, e.g. shift, alt, see
+ * {@link android.text.method.MetaKeyKeyListener#getMetaState(CharSequence)}, so using a dummy
+ * value is fine here.
+ */
+ private static final Spannable EMPTY_SPANNABLE = new SpannableString("");
+
+ private final DialpadPresenter presenter;
+
+ DtmfKeyListener(@NonNull DialpadPresenter presenter) {
+ this.presenter = presenter;
+ }
+
+ @Override
+ protected char[] getAcceptedChars() {
+ return VALID_DTMF_CHARACTERS;
+ }
+
+ @Override
+ public boolean backspace(View view, Editable content, int keyCode, KeyEvent event) {
+ return false;
+ }
+
+ /**
+ * Responds to keyDown events by firing a Dtmf tone, if the given event corresponds is a {@link
+ * #VALID_DTMF_CHARACTERS}.
+ *
+ * @return {@code true} if the event was handled.
+ */
+ @Override
+ public boolean onKeyDown(View view, Editable content, int keyCode, KeyEvent event) {
+ LogUtil.i("DtmfKeyListener.onKeyDown", "overload");
+ if (!super.onKeyDown(view, content, keyCode, event)) {
+ LogUtil.i("DtmfKeyListener.onKeyDown", "parent type didn't support event");
+ return false;
+ }
+
+ return onKeyDown(event);
+ }
+
+ /**
+ * Version of {@link #onKeyDown(View, Editable, int, KeyEvent)} used when a View/Editable isn't
+ * available.
+ */
+ boolean onKeyDown(KeyEvent event) {
+ LogUtil.enterBlock("DtmfKeyListener.onKeyDown");
+ if (event.getRepeatCount() != 0) {
+ LogUtil.i("DtmfKeyListener.onKeyDown", "long press, ignoring");
+ return false;
+ }
+
+ char c = (char) lookup(event, EMPTY_SPANNABLE);
+
+ if (!ok(getAcceptedChars(), c)) {
+ LogUtil.i("DtmfKeyListener.onKeyDown", "not an accepted character");
+ return false;
+ }
+
+ presenter.processDtmf(c);
+ return true;
+ }
+
+ /**
+ * Responds to keyUp events by stopping any playing Dtmf tone if the given event corresponds is a
+ * {@link #VALID_DTMF_CHARACTERS}.
+ *
+ * <p>Null events also stop the Dtmf tone.
+ *
+ * @return {@code true} if the event was handled
+ */
+ @Override
+ public boolean onKeyUp(View view, Editable content, int keyCode, KeyEvent event) {
+ LogUtil.i("DtmfKeyListener.onKeyUp", "overload");
+ super.onKeyUp(view, content, keyCode, event);
+
+ return onKeyUp(event);
+ }
+
+ /**
+ * Handle individual keyup events.
+ *
+ * @param event is the event we are trying to stop. If this is null, then we just force-stop the
+ * last tone without checking if the event is an acceptable dialer event.
+ */
+ boolean onKeyUp(KeyEvent event) {
+ LogUtil.enterBlock("DtmfKeyListener.onKeyUp");
+ if (event == null) {
+ return true;
+ }
+
+ char c = (char) lookup(event, EMPTY_SPANNABLE);
+
+ if (!ok(getAcceptedChars(), c)) {
+ LogUtil.i("DtmfKeyListener.onKeyUp", "not an accepted character");
+ return false;
+ }
+
+ presenter.stopDtmf();
+ return true;
+ }
+}