diff options
Diffstat (limited to 'java/com')
-rw-r--r-- | java/com/android/incallui/DialpadFragment.java | 178 | ||||
-rw-r--r-- | java/com/android/incallui/DtmfKeyListener.java | 156 |
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; + } +} |