Fields Summary |
---|
private static final String | LOG_TAG |
private static final boolean | DBG |
private static final int | PHONE_DISCONNECT |
private static com.android.internal.telephony.Phone | mPhone |
private android.media.ToneGenerator | mToneGenerator |
private Object | mToneGeneratorLock |
private boolean | mDTMFToneEnabled |
private static final HashMap | mToneMapHash Map to map a character to a tone |
private static final HashMap | mDisplayMapHash Map to map a view id to a character |
private android.widget.EditText | mDialpadDigitsSet up the static maps |
private android.widget.EditText | mInCallDigits |
private InCallScreen | mInCallScreen |
private android.widget.SlidingDrawer | mDialerContainer |
private DTMFTwelveKeyDialerView | mDialerView |
private DTMFKeyListener | mDialerKeyListener |
private android.os.Handler | mHandlerOur own handler to take care of the messages from the phone state changes |
Methods Summary |
---|
public void | clearDigits()Clears out the display of "DTMF digits typed so far" that's kept in
either mDialpadDigits or mInCallDigits (depending on whether we're
in portrait or landscape mode.)
The InCallScreen is responsible for calling this method any time a
new call becomes active (or, more simply, any time a call ends).
This is how we make sure that the "history" of DTMF digits you type
doesn't persist from one call to the next.
TODO: it might be more elegent if the dialpad itself could remember
the call that we're associated with, and clear the digits if the
"current call" has changed since last time. (This would require
some unique identifier that's different for each call. We can't
just use the foreground Call object, since that's a singleton that
lasts the whole life of the phone process. Instead, maybe look at
the Connection object that comes back from getEarliestConnection()?
Or getEarliestConnectTime()?)
Or to be even fancier, we could keep a mapping of *multiple*
"active calls" to DTMF strings. That way you could have two lines
in use and swap calls multiple times, and we'd still remember the
digits for each call. (But that's such an obscure use case that
it's probably not worth the extra complexity.)
if (DBG) log("clearDigits()...");
if (mDialpadDigits != null) {
mDialpadDigits.setText("");
}
if (mInCallDigits != null) {
mInCallDigits.setText("");
}
|
void | clearInCallScreenReference()Null out our reference to the InCallScreen activity.
This indicates that the InCallScreen activity has been destroyed.
At the same time, get rid of listeners since we're not going to
be valid anymore.
mInCallScreen = null;
mDialerKeyListener = null;
if (mDialerContainer != null) {
mDialerContainer.setOnDrawerOpenListener(null);
mDialerContainer.setOnDrawerCloseListener(null);
}
closeDialer(false);
|
public void | closeDialer(boolean animate)Forces the dialer into the "closed" state.
Does nothing if the dialer is already closed.
if (mDialerContainer != null && mDialerContainer.isOpened()) {
if (animate) {
mDialerContainer.animateToggle();
} else {
mDialerContainer.toggle();
}
}
|
public void | hideDTMFDisplay(boolean shouldHide)Called when we want to hide the DTMF Display field immediately.
DTMFKeyListener.DTMFDisplayAnimation animation = mDialerKeyListener.mDTMFDisplayAnimation;
// if the animation is in place
if (animation != null) {
View text = animation.mDTMFDisplay;
// and the display is available
if (text != null) {
// hide the display if necessary
text.setVisibility(shouldHide ? View.GONE : View.VISIBLE);
if (shouldHide) {
// null the animation - this makes the display disappear faster
text.setAnimation(null);
} else {
// otherwise reset the animation to the initial state.
animation.prepareFadeIn();
}
}
}
|
boolean | isKeyEventAcceptable(android.view.KeyEvent event)Check to see if the keyEvent is dialable.
return (mDialerKeyListener != null && mDialerKeyListener.isKeyEventAcceptable(event));
|
public boolean | isOpened()
return mDialerContainer != null && mDialerContainer.isOpened();
|
private static void | log(java.lang.String msg)static logging method
Log.d(LOG_TAG, msg);
|
private void | onDialerClose()Dialer code that runs when the dialer is closed.
This releases resources acquired when we start the dialer.
if (DBG) log("onDialerClose()...");
// reset back to a short delay for the poke lock.
PhoneApp app = PhoneApp.getInstance();
app.updateWakeState();
mPhone.unregisterForDisconnect(mHandler);
stopDialerSession();
// Give the InCallScreen a chance to do any necessary UI updates.
mInCallScreen.onDialerClose();
|
public boolean | onDialerKeyDown(android.view.KeyEvent event)Called externally (from InCallScreen) to play a DTMF Tone.
if (DBG) log("Notifying dtmf key down.");
return mDialerKeyListener.onKeyDown(event);
|
public boolean | onDialerKeyUp(android.view.KeyEvent event)Called externally (from InCallScreen) to cancel the last DTMF Tone played.
if (DBG) log("Notifying dtmf key up.");
return mDialerKeyListener.onKeyUp(event);
|
private void | onDialerOpen()Dialer code that runs when the dialer is brought up.
This includes layout changes, etc, and just prepares the dialer model for use.
if (DBG) log("onDialerOpen()...");
// inflate the view.
mDialerView = (DTMFTwelveKeyDialerView) mInCallScreen.findViewById(R.id.dtmf_dialer);
mDialerView.setDialer(this);
// Have the WindowManager filter out cheek touch events
mInCallScreen.getWindow().addFlags(WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES);
mPhone.registerForDisconnect(mHandler, PHONE_DISCONNECT, null);
// set to a longer delay while the dialer is up.
PhoneApp app = PhoneApp.getInstance();
app.updateWakeState();
// setup the digit display
mDialpadDigits = (EditText) mDialerView.findViewById(R.id.dtmfDialerField);
mDialpadDigits.setKeyListener(new DTMFKeyListener(null));
mDialpadDigits.requestFocus();
// remove the long-press context menus that support
// the edit (copy / paste / select) functions.
mDialpadDigits.setLongClickable(false);
// Check for the presence of the keypad (portrait mode)
View view = mDialerView.findViewById(R.id.one);
if (view != null) {
if (DBG) log("portrait mode setup");
setupKeypad();
} else {
if (DBG) log("landscape mode setup");
// Adding hint text to the field to indicate that keyboard
// is needed while in landscape mode.
mDialpadDigits.setHint(R.string.dialerKeyboardHintText);
}
// setup the local tone generator.
startDialerSession();
// Give the InCallScreen a chance to do any necessary UI updates.
mInCallScreen.onDialerOpen();
|
public void | onDrawerClosed()Implemented for the SlidingDrawer close listener, release the dialer.
onDialerClose();
|
public void | onDrawerOpened()Implemented for the SlidingDrawer open listener, prepare the dialer.
onDialerOpen();
|
public boolean | onKey(android.view.View v, int keyCode, android.view.KeyEvent event)Implements View.OnKeyListener for the DTMF buttons. Enables dialing with trackball/dpad.
// if (DBG) log("onKey: keyCode " + keyCode + ", view " + v);
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
int viewId = v.getId();
if (mDisplayMap.containsKey(viewId)) {
switch (event.getAction()) {
case KeyEvent.ACTION_DOWN:
if (event.getRepeatCount() == 0) {
processDtmf(mDisplayMap.get(viewId));
}
break;
case KeyEvent.ACTION_UP:
stopTone();
break;
}
// do not return true [handled] here, since we want the
// press / click animation to be handled by the framework.
}
}
return false;
|
public boolean | onKeyDown(int keyCode, android.view.KeyEvent event)catch the back and call buttons to return to the in call activity.
// if (DBG) log("onKeyDown: keyCode " + keyCode);
switch (keyCode) {
// finish for these events
case KeyEvent.KEYCODE_BACK:
case KeyEvent.KEYCODE_CALL:
if (DBG) log("exit requested");
closeDialer(true); // do the "closing" animation
return true;
}
return mInCallScreen.onKeyDown(keyCode, event);
|
public boolean | onKeyUp(int keyCode, android.view.KeyEvent event)catch the back and call buttons to return to the in call activity.
// if (DBG) log("onKeyUp: keyCode " + keyCode);
return mInCallScreen.onKeyUp(keyCode, event);
|
public void | onQueryComplete(int token, java.lang.Object cookie, com.android.internal.telephony.CallerInfo ci)upon completion of the query, update the name field in the status.
if (DBG) log("callerinfo query complete, updating ui.");
((TextView) cookie).setText(PhoneUtils.getCompactNameFromCallerInfo(ci, mInCallScreen));
|
public boolean | onTouch(android.view.View v, android.view.MotionEvent event)Implemented for the TouchListener, process the touch events.
int viewId = v.getId();
// if the button is recognized
if (mDisplayMap.containsKey(viewId)) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// Append the character mapped to this button, to the display.
// start the tone
processDtmf(mDisplayMap.get(viewId));
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
// stop the tone on ANY other event, except for MOVE.
stopTone();
break;
}
// do not return true [handled] here, since we want the
// press / click animation to be handled by the framework.
}
return false;
|
public void | openDialer(boolean animate)Forces the dialer into the "open" state.
Does nothing if the dialer is already open.
if (mDialerContainer != null && !mDialerContainer.isOpened()) {
if (animate) {
mDialerContainer.animateToggle();
} else {
mDialerContainer.toggle();
}
}
|
private final void | processDtmf(char c)Processes the specified digit as a DTMF key, by playing the
appropriate DTMF tone, and appending the digit to the EditText
field that displays the DTMF digits sent so far.
// if it is a valid key, then update the display and send the dtmf tone.
if (PhoneNumberUtils.is12Key(c)) {
if (DBG) log("updating display and sending dtmf tone for '" + c + "'");
if (mDialpadDigits != null) {
mDialpadDigits.getText().append(c);
}
// Note we *don't* need to manually append this digit to the
// landscape-mode EditText field (mInCallDigits), since it
// gets key events directly and automatically appends whetever
// the user types.
// Play the tone if it exists.
if (mToneMap.containsKey(c)) {
// begin tone playback.
startTone(c);
}
} else if (DBG) {
log("ignoring dtmf request for '" + c + "'");
}
// Any DTMF keypress counts as explicit "user activity".
PhoneApp.getInstance().pokeUserActivity();
|
private void | setupKeypad()setup the keys on the dialer activity, using the keymaps.
// for each view id listed in the displaymap
View button;
for (int viewId : mDisplayMap.keySet()) {
// locate the view
button = mDialerView.findViewById(viewId);
// Setup the listeners for the buttons
button.setOnTouchListener(this);
button.setClickable(true);
button.setOnKeyListener(this);
}
|
public void | startDialerSession()Setup the local tone generator. Should have corresponding calls to
{@link onDialerPause}.
// see if we need to play local tones.
mDTMFToneEnabled = Settings.System.getInt(mInCallScreen.getContentResolver(),
Settings.System.DTMF_TONE_WHEN_DIALING, 1) == 1;
// create the tone generator
// if the mToneGenerator creation fails, just continue without it. It is
// a local audio signal, and is not as important as the dtmf tone itself.
if (mDTMFToneEnabled) {
synchronized (mToneGeneratorLock) {
if (mToneGenerator == null) {
try {
mToneGenerator = new ToneGenerator(AudioManager.STREAM_VOICE_CALL, 80);
} catch (RuntimeException e) {
if (DBG) log("Exception caught while creating local tone generator: " + e);
mToneGenerator = null;
}
}
}
}
|
private void | startTone(char tone)Starts playing a DTMF tone. Also begins the local tone playback,
if enabled.
if (DBG) log("startTone()...");
PhoneApp.getInstance().phone.startDtmf(tone);
// if local tone playback is enabled, start it.
if (mDTMFToneEnabled) {
synchronized (mToneGeneratorLock) {
if (mToneGenerator == null) {
if (DBG) log("startTone: mToneGenerator == null, tone: " + tone);
} else {
if (DBG) log("starting local tone " + tone);
mToneGenerator.startTone(mToneMap.get(tone));
}
}
}
|
public void | stopDialerSession()Tear down the local tone generator, corresponds to calls to
{@link onDialerResume}
// release the tone generator.
synchronized (mToneGeneratorLock) {
if (mToneGenerator != null) {
mToneGenerator.release();
mToneGenerator = null;
}
}
|
private void | stopTone()Stops playing the current DTMF tone.
The ToneStopper class (similar to that in {@link TwelveKeyDialer#mToneStopper})
has been removed in favor of synchronous start / stop calls since tone duration
is now a function of the input.
if (DBG) log("stopTone()...");
PhoneApp.getInstance().phone.stopDtmf();
// if local tone playback is enabled, stop it.
if (DBG) log("trying to stop local tone...");
if (mDTMFToneEnabled) {
synchronized (mToneGeneratorLock) {
if (mToneGenerator == null) {
if (DBG) log("stopTone: mToneGenerator == null");
} else {
if (DBG) log("stopping local tone.");
mToneGenerator.stopTone();
}
}
}
|