Dialpad Ui elements for InCallUi

Change-Id: I7b230cc46993493459923c436a643910026cf6a6
diff --git a/InCallUI/res/drawable-hdpi/dial_num_0_no_plus_wht.png b/InCallUI/res/drawable-hdpi/dial_num_0_no_plus_wht.png
new file mode 100644
index 0000000..69849ec
--- /dev/null
+++ b/InCallUI/res/drawable-hdpi/dial_num_0_no_plus_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-hdpi/dial_num_1_no_vm_wht.png b/InCallUI/res/drawable-hdpi/dial_num_1_no_vm_wht.png
new file mode 100644
index 0000000..af7ec42
--- /dev/null
+++ b/InCallUI/res/drawable-hdpi/dial_num_1_no_vm_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-hdpi/dial_num_2_wht.png b/InCallUI/res/drawable-hdpi/dial_num_2_wht.png
new file mode 100644
index 0000000..2ae20ab
--- /dev/null
+++ b/InCallUI/res/drawable-hdpi/dial_num_2_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-hdpi/dial_num_3_wht.png b/InCallUI/res/drawable-hdpi/dial_num_3_wht.png
new file mode 100644
index 0000000..991d5f3
--- /dev/null
+++ b/InCallUI/res/drawable-hdpi/dial_num_3_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-hdpi/dial_num_4_wht.png b/InCallUI/res/drawable-hdpi/dial_num_4_wht.png
new file mode 100644
index 0000000..7aad3ef
--- /dev/null
+++ b/InCallUI/res/drawable-hdpi/dial_num_4_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-hdpi/dial_num_5_wht.png b/InCallUI/res/drawable-hdpi/dial_num_5_wht.png
new file mode 100644
index 0000000..42a1d0b
--- /dev/null
+++ b/InCallUI/res/drawable-hdpi/dial_num_5_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-hdpi/dial_num_6_wht.png b/InCallUI/res/drawable-hdpi/dial_num_6_wht.png
new file mode 100644
index 0000000..b03e019
--- /dev/null
+++ b/InCallUI/res/drawable-hdpi/dial_num_6_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-hdpi/dial_num_7_wht.png b/InCallUI/res/drawable-hdpi/dial_num_7_wht.png
new file mode 100644
index 0000000..8b72fff
--- /dev/null
+++ b/InCallUI/res/drawable-hdpi/dial_num_7_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-hdpi/dial_num_8_wht.png b/InCallUI/res/drawable-hdpi/dial_num_8_wht.png
new file mode 100644
index 0000000..822f21a
--- /dev/null
+++ b/InCallUI/res/drawable-hdpi/dial_num_8_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-hdpi/dial_num_9_wht.png b/InCallUI/res/drawable-hdpi/dial_num_9_wht.png
new file mode 100644
index 0000000..2ee944b
--- /dev/null
+++ b/InCallUI/res/drawable-hdpi/dial_num_9_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-hdpi/dial_num_pound_wht.png b/InCallUI/res/drawable-hdpi/dial_num_pound_wht.png
new file mode 100644
index 0000000..e10e57d
--- /dev/null
+++ b/InCallUI/res/drawable-hdpi/dial_num_pound_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-hdpi/dial_num_star_wht.png b/InCallUI/res/drawable-hdpi/dial_num_star_wht.png
new file mode 100644
index 0000000..1dfc111
--- /dev/null
+++ b/InCallUI/res/drawable-hdpi/dial_num_star_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-mdpi/dial_num_0_no_plus_wht.png b/InCallUI/res/drawable-mdpi/dial_num_0_no_plus_wht.png
new file mode 100644
index 0000000..1d8b0e3
--- /dev/null
+++ b/InCallUI/res/drawable-mdpi/dial_num_0_no_plus_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-mdpi/dial_num_1_no_vm_wht.png b/InCallUI/res/drawable-mdpi/dial_num_1_no_vm_wht.png
new file mode 100644
index 0000000..e253724
--- /dev/null
+++ b/InCallUI/res/drawable-mdpi/dial_num_1_no_vm_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-mdpi/dial_num_2_wht.png b/InCallUI/res/drawable-mdpi/dial_num_2_wht.png
new file mode 100644
index 0000000..e311f4f
--- /dev/null
+++ b/InCallUI/res/drawable-mdpi/dial_num_2_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-mdpi/dial_num_3_wht.png b/InCallUI/res/drawable-mdpi/dial_num_3_wht.png
new file mode 100644
index 0000000..f07324a
--- /dev/null
+++ b/InCallUI/res/drawable-mdpi/dial_num_3_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-mdpi/dial_num_4_wht.png b/InCallUI/res/drawable-mdpi/dial_num_4_wht.png
new file mode 100644
index 0000000..cd8d33c
--- /dev/null
+++ b/InCallUI/res/drawable-mdpi/dial_num_4_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-mdpi/dial_num_5_wht.png b/InCallUI/res/drawable-mdpi/dial_num_5_wht.png
new file mode 100644
index 0000000..a9f27dc
--- /dev/null
+++ b/InCallUI/res/drawable-mdpi/dial_num_5_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-mdpi/dial_num_6_wht.png b/InCallUI/res/drawable-mdpi/dial_num_6_wht.png
new file mode 100644
index 0000000..2bdf08e
--- /dev/null
+++ b/InCallUI/res/drawable-mdpi/dial_num_6_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-mdpi/dial_num_7_wht.png b/InCallUI/res/drawable-mdpi/dial_num_7_wht.png
new file mode 100644
index 0000000..6c1c599
--- /dev/null
+++ b/InCallUI/res/drawable-mdpi/dial_num_7_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-mdpi/dial_num_8_wht.png b/InCallUI/res/drawable-mdpi/dial_num_8_wht.png
new file mode 100644
index 0000000..db0694c
--- /dev/null
+++ b/InCallUI/res/drawable-mdpi/dial_num_8_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-mdpi/dial_num_9_wht.png b/InCallUI/res/drawable-mdpi/dial_num_9_wht.png
new file mode 100644
index 0000000..692fdb0
--- /dev/null
+++ b/InCallUI/res/drawable-mdpi/dial_num_9_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-mdpi/dial_num_pound_wht.png b/InCallUI/res/drawable-mdpi/dial_num_pound_wht.png
new file mode 100644
index 0000000..f216d05
--- /dev/null
+++ b/InCallUI/res/drawable-mdpi/dial_num_pound_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-mdpi/dial_num_star_wht.png b/InCallUI/res/drawable-mdpi/dial_num_star_wht.png
new file mode 100644
index 0000000..f7e8e9f
--- /dev/null
+++ b/InCallUI/res/drawable-mdpi/dial_num_star_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-xhdpi/dial_num_0_no_plus_wht.png b/InCallUI/res/drawable-xhdpi/dial_num_0_no_plus_wht.png
new file mode 100644
index 0000000..11ca993
--- /dev/null
+++ b/InCallUI/res/drawable-xhdpi/dial_num_0_no_plus_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-xhdpi/dial_num_1_no_vm_wht.png b/InCallUI/res/drawable-xhdpi/dial_num_1_no_vm_wht.png
new file mode 100644
index 0000000..8d2ac70
--- /dev/null
+++ b/InCallUI/res/drawable-xhdpi/dial_num_1_no_vm_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-xhdpi/dial_num_2_wht.png b/InCallUI/res/drawable-xhdpi/dial_num_2_wht.png
new file mode 100644
index 0000000..12c4ab9
--- /dev/null
+++ b/InCallUI/res/drawable-xhdpi/dial_num_2_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-xhdpi/dial_num_3_wht.png b/InCallUI/res/drawable-xhdpi/dial_num_3_wht.png
new file mode 100644
index 0000000..4353e8a
--- /dev/null
+++ b/InCallUI/res/drawable-xhdpi/dial_num_3_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-xhdpi/dial_num_4_wht.png b/InCallUI/res/drawable-xhdpi/dial_num_4_wht.png
new file mode 100644
index 0000000..ccee5cc
--- /dev/null
+++ b/InCallUI/res/drawable-xhdpi/dial_num_4_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-xhdpi/dial_num_5_wht.png b/InCallUI/res/drawable-xhdpi/dial_num_5_wht.png
new file mode 100644
index 0000000..f27f153
--- /dev/null
+++ b/InCallUI/res/drawable-xhdpi/dial_num_5_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-xhdpi/dial_num_6_wht.png b/InCallUI/res/drawable-xhdpi/dial_num_6_wht.png
new file mode 100644
index 0000000..8966d13
--- /dev/null
+++ b/InCallUI/res/drawable-xhdpi/dial_num_6_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-xhdpi/dial_num_7_wht.png b/InCallUI/res/drawable-xhdpi/dial_num_7_wht.png
new file mode 100644
index 0000000..b018810
--- /dev/null
+++ b/InCallUI/res/drawable-xhdpi/dial_num_7_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-xhdpi/dial_num_8_wht.png b/InCallUI/res/drawable-xhdpi/dial_num_8_wht.png
new file mode 100644
index 0000000..7c7b4f8
--- /dev/null
+++ b/InCallUI/res/drawable-xhdpi/dial_num_8_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-xhdpi/dial_num_9_wht.png b/InCallUI/res/drawable-xhdpi/dial_num_9_wht.png
new file mode 100644
index 0000000..23984f0
--- /dev/null
+++ b/InCallUI/res/drawable-xhdpi/dial_num_9_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-xhdpi/dial_num_pound_wht.png b/InCallUI/res/drawable-xhdpi/dial_num_pound_wht.png
new file mode 100644
index 0000000..be21af8
--- /dev/null
+++ b/InCallUI/res/drawable-xhdpi/dial_num_pound_wht.png
Binary files differ
diff --git a/InCallUI/res/drawable-xhdpi/dial_num_star_wht.png b/InCallUI/res/drawable-xhdpi/dial_num_star_wht.png
new file mode 100644
index 0000000..061a494
--- /dev/null
+++ b/InCallUI/res/drawable-xhdpi/dial_num_star_wht.png
Binary files differ
diff --git a/InCallUI/res/layout/dtmf_twelve_key_dialer_view.xml b/InCallUI/res/layout/dtmf_twelve_key_dialer_view.xml
new file mode 100644
index 0000000..c4fecf3
--- /dev/null
+++ b/InCallUI/res/layout/dtmf_twelve_key_dialer_view.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2006 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.
+-->
+
+<!-- The grid of buttons used in the onscreen DTMF dialpad;
+     see dtmf_twelve_key_dialer_view.xml. -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/dtmf_twelve_key_dialer_view"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:layout_marginTop="1dip" >
+
+    <!-- Display of the digits you've typed so far.
+         This widget appears completely non-interactive to the user: you
+         can't edit or "hit backspace" since these are DTMF tones you've
+         already sent over the network.  But it's still an EditText rather
+         than a TextView because it needs to receive key events from a
+         hard keyboard, if present (see mDialerKeyListener). -->
+    <EditText
+        android:id="@+id/dtmfDialerField"
+        android:layout_width="match_parent"
+        android:layout_height="32dp"
+        android:layout_marginTop="10dp"
+        android:layout_marginBottom="5dp"
+        android:layout_marginStart="32dp"
+        android:layout_marginEnd="32dp"
+        android:paddingEnd="16dp"
+        android:paddingStart="16dp"
+        android:singleLine="true"
+        android:scrollHorizontally="true"
+        android:textSize="24sp"
+        android:gravity="center"
+        android:freezesText="true"
+        android:background="@null"
+        android:textColor="@color/dtmf_dialer_display_text"
+        android:focusableInTouchMode="false"
+        android:clickable="false"/>
+
+    <TableLayout
+        android:id="@+id/dialpad"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_weight="@integer/dialpad_layout_weight_dialpad"
+        android:layout_gravity="center_horizontal"
+        android:layout_marginTop="@dimen/dialpad_vertical_margin"
+        android:paddingStart="5dip"
+        android:paddingEnd="5dip"
+        android:paddingBottom="10dip"
+        android:background="@drawable/dialpad_background"
+        android:layoutDirection="ltr">
+
+        <TableRow
+             android:layout_height="0px"
+             android:layout_weight="1">
+            <ImageButton android:id="@+id/one" style="@style/DialpadButtonStyle"
+                android:src="@drawable/dial_num_1_no_vm_wht"
+                android:contentDescription="@string/description_image_button_one" />
+            <ImageButton android:id="@+id/two" style="@style/DialpadButtonStyle"
+                android:src="@drawable/dial_num_2_wht"
+                android:contentDescription="@string/description_image_button_two" />
+            <ImageButton android:id="@+id/three" style="@style/DialpadButtonStyle"
+                android:src="@drawable/dial_num_3_wht"
+                android:contentDescription="@string/description_image_button_three" />
+        </TableRow>
+
+        <TableRow
+             android:layout_height="0px"
+             android:layout_weight="1">
+            <ImageButton android:id="@+id/four" style="@style/DialpadButtonStyle"
+                android:src="@drawable/dial_num_4_wht"
+                android:contentDescription="@string/description_image_button_four" />
+            <ImageButton android:id="@+id/five" style="@style/DialpadButtonStyle"
+                android:src="@drawable/dial_num_5_wht"
+                android:contentDescription="@string/description_image_button_five" />
+            <ImageButton android:id="@+id/six" style="@style/DialpadButtonStyle"
+                android:src="@drawable/dial_num_6_wht"
+                android:contentDescription="@string/description_image_button_six" />
+        </TableRow>
+
+        <TableRow
+             android:layout_height="0px"
+             android:layout_weight="1">
+            <ImageButton android:id="@+id/seven" style="@style/DialpadButtonStyle"
+                android:src="@drawable/dial_num_7_wht"
+                android:contentDescription="@string/description_image_button_seven" />
+            <ImageButton android:id="@+id/eight" style="@style/DialpadButtonStyle"
+                android:src="@drawable/dial_num_8_wht"
+                android:contentDescription="@string/description_image_button_eight" />
+            <ImageButton android:id="@+id/nine" style="@style/DialpadButtonStyle"
+                android:src="@drawable/dial_num_9_wht"
+                android:contentDescription="@string/description_image_button_nine" />
+        </TableRow>
+
+        <TableRow
+             android:layout_height="0px"
+             android:layout_weight="1">
+            <ImageButton android:id="@+id/star" style="@style/DialpadButtonStyle"
+                android:src="@drawable/dial_num_star_wht"
+                android:contentDescription="@string/description_image_button_star" />
+            <ImageButton android:id="@+id/zero" style="@style/DialpadButtonStyle"
+                android:src="@drawable/dial_num_0_no_plus_wht"
+                android:contentDescription="@string/description_image_button_zero" />
+            <ImageButton android:id="@+id/pound" style="@style/DialpadButtonStyle"
+                android:src="@drawable/dial_num_pound_wht"
+                android:contentDescription="@string/description_image_button_pound" />
+        </TableRow>
+    </TableLayout>
+</LinearLayout>
diff --git a/InCallUI/res/layout/incall_screen.xml b/InCallUI/res/layout/incall_screen.xml
index 9c364ed..25241ba 100644
--- a/InCallUI/res/layout/incall_screen.xml
+++ b/InCallUI/res/layout/incall_screen.xml
@@ -15,21 +15,39 @@
 -->
 
 <!-- In-call Phone UI; see InCallActivity.java. -->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:id="@+id/main">
+
+    <LinearLayout
+        android:id="@+id/in_call_and_button_container"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical">
+
+        <RelativeLayout
+             android:id="@+id/in_call_card_container"
              android:layout_width="match_parent"
-             android:layout_height="match_parent"
-             android:id="@+id/main">
+             android:layout_height="0dp"
+             android:layout_weight="1">
 
-    <LinearLayout android:id="@+id/in_call_and_button_container"
-                  android:layout_width="match_parent"
-                  android:layout_height="match_parent"
-                  android:orientation="vertical">
-
-        <fragment android:name="com.android.incallui.CallCardFragment"
-                  android:id="@+id/callCardFragment"
-                  android:layout_width="match_parent"
-                  android:layout_height="0dp"
-                  android:layout_weight="1"/>
+            <fragment
+                android:name="com.android.incallui.CallCardFragment"
+                android:id="@+id/callCardFragment"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_alignParentTop="true"
+                android:layout_alignParentStart="true" />
+            <fragment
+                android:name="com.android.incallui.DialpadFragment"
+                android:id="@+id/dialpadFragment"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_alignParentTop="true"
+                android:layout_alignParentStart="true" />
+        </RelativeLayout>
 
         <fragment android:name="com.android.incallui.CallButtonFragment"
                   android:id="@+id/callButtonFragment"
diff --git a/InCallUI/src/com/android/incallui/AnswerFragment.java b/InCallUI/src/com/android/incallui/AnswerFragment.java
index 0995ed6..a20fdb9 100644
--- a/InCallUI/src/com/android/incallui/AnswerFragment.java
+++ b/InCallUI/src/com/android/incallui/AnswerFragment.java
@@ -16,10 +16,6 @@
 
 package com.android.incallui;
 
-import com.google.common.base.Preconditions;
-
-import android.app.Fragment;
-import android.app.FragmentTransaction;
 import android.os.Bundle;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -53,7 +49,7 @@
 
     @Override
     public void showAnswerUi(boolean show) {
-        getView().setVisibility(show ? View.VISIBLE : View.INVISIBLE);
+        getView().setVisibility(show ? View.VISIBLE : View.GONE);
     }
 
     @Override
diff --git a/InCallUI/src/com/android/incallui/CallButtonFragment.java b/InCallUI/src/com/android/incallui/CallButtonFragment.java
index 3ccc1d1..772251d 100644
--- a/InCallUI/src/com/android/incallui/CallButtonFragment.java
+++ b/InCallUI/src/com/android/incallui/CallButtonFragment.java
@@ -34,6 +34,8 @@
     private ToggleButton mMuteButton;
     private ToggleButton mAudioButton;
     private ToggleButton mHoldButton;
+    private ToggleButton mShowDialpadButton;
+
     private View mEndCallButton;
 
     @Override
@@ -87,6 +89,14 @@
             }
         });
 
+        mShowDialpadButton = (ToggleButton) parent.findViewById(R.id.dialpadButton);
+        mShowDialpadButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+            @Override
+            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+                getPresenter().showDialpadClicked(isChecked);
+            }
+        });
+
         return parent;
     }
 
@@ -121,4 +131,12 @@
     public void setHold(boolean value) {
         mHoldButton.setChecked(value);
     }
+
+    @Override
+    public void displayDialpad(boolean value) {
+        mShowDialpadButton.setChecked(value);
+        if (getActivity() != null && getActivity() instanceof InCallActivity) {
+            ((InCallActivity) getActivity()).displayDialpad(value);
+        }
+    }
 }
diff --git a/InCallUI/src/com/android/incallui/CallButtonPresenter.java b/InCallUI/src/com/android/incallui/CallButtonPresenter.java
index 60ab7bb..35e6ab7 100644
--- a/InCallUI/src/com/android/incallui/CallButtonPresenter.java
+++ b/InCallUI/src/com/android/incallui/CallButtonPresenter.java
@@ -98,10 +98,16 @@
         getUi().setHold(checked);
     }
 
+    public void showDialpadClicked(boolean checked) {
+        Logger.v(this, "Show dialpad " + String.valueOf(checked));
+        getUi().displayDialpad(checked);
+    }
+
     public interface CallButtonUi extends Ui {
         void setVisible(boolean on);
         void setMute(boolean on);
         void setSpeaker(boolean on);
         void setHold(boolean on);
+        void displayDialpad(boolean on);
     }
 }
diff --git a/InCallUI/src/com/android/incallui/CallCardFragment.java b/InCallUI/src/com/android/incallui/CallCardFragment.java
index 3f46bb5..76bdd11 100644
--- a/InCallUI/src/com/android/incallui/CallCardFragment.java
+++ b/InCallUI/src/com/android/incallui/CallCardFragment.java
@@ -56,6 +56,15 @@
     }
 
     @Override
+    public void setVisible(boolean on) {
+        if (on) {
+            getView().setVisibility(View.VISIBLE);
+        } else {
+            getView().setVisibility(View.INVISIBLE);
+        }
+    }
+
+    @Override
     public void setSecondaryCallInfo(boolean show, String number) {
         if (show) {
             showAndInitializeSecondaryCallInfo();
diff --git a/InCallUI/src/com/android/incallui/CallCardPresenter.java b/InCallUI/src/com/android/incallui/CallCardPresenter.java
index 04a43ea..bea89ef 100644
--- a/InCallUI/src/com/android/incallui/CallCardPresenter.java
+++ b/InCallUI/src/com/android/incallui/CallCardPresenter.java
@@ -72,8 +72,9 @@
     public interface CallCardUi extends Ui {
         // TODO(klp): Consider passing in the Call object directly in these methods.
 
-        public void setNumber(String number);
-        public void setName(String name);
-        public void setSecondaryCallInfo(boolean show, String number);
+        void setVisible(boolean on);
+        void setNumber(String number);
+        void setName(String name);
+        void setSecondaryCallInfo(boolean show, String number);
     }
 }
diff --git a/InCallUI/src/com/android/incallui/CallCommandClient.java b/InCallUI/src/com/android/incallui/CallCommandClient.java
index ae3be92..381d8d3 100644
--- a/InCallUI/src/com/android/incallui/CallCommandClient.java
+++ b/InCallUI/src/com/android/incallui/CallCommandClient.java
@@ -95,4 +95,23 @@
             Logger.e(this, "Error setting speaker.", e);
         }
     }
+
+    public void playDtmfTone(char digit, boolean timedShortTone) {
+        try {
+            Logger.v(this, "Sending dtmf tone " + digit);
+            mCommandService.playDtmfTone(digit, timedShortTone);
+        } catch (RemoteException e) {
+            Logger.e(this, "Error setting speaker.", e);
+        }
+
+    }
+
+    public void stopDtmfTone() {
+        try {
+            Logger.v(this, "Stop dtmf tone ");
+            mCommandService.stopDtmfTone();
+        } catch (RemoteException e) {
+            Logger.e(this, "Error setting speaker.", e);
+        }
+    }
 }
diff --git a/InCallUI/src/com/android/incallui/DialpadFragment.java b/InCallUI/src/com/android/incallui/DialpadFragment.java
new file mode 100644
index 0000000..6be923c
--- /dev/null
+++ b/InCallUI/src/com/android/incallui/DialpadFragment.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2013 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.content.Context;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityManager;
+import android.widget.EditText;
+
+import java.util.HashMap;
+
+/**
+ * Fragment for call control buttons
+ */
+public class DialpadFragment extends BaseFragment<DialpadPresenter>
+        implements DialpadPresenter.DialpadUi, View.OnTouchListener, View.OnKeyListener,
+        View.OnHoverListener, View.OnClickListener {
+
+    private EditText mDtmfDialerField;
+
+    /** Hash Map to map a view id to a character*/
+    private static final HashMap<Integer, Character> mDisplayMap =
+        new HashMap<Integer, Character>();
+
+    /** Set up the static maps*/
+    static {
+        // Map the buttons to the display characters
+        mDisplayMap.put(R.id.one, '1');
+        mDisplayMap.put(R.id.two, '2');
+        mDisplayMap.put(R.id.three, '3');
+        mDisplayMap.put(R.id.four, '4');
+        mDisplayMap.put(R.id.five, '5');
+        mDisplayMap.put(R.id.six, '6');
+        mDisplayMap.put(R.id.seven, '7');
+        mDisplayMap.put(R.id.eight, '8');
+        mDisplayMap.put(R.id.nine, '9');
+        mDisplayMap.put(R.id.zero, '0');
+        mDisplayMap.put(R.id.pound, '#');
+        mDisplayMap.put(R.id.star, '*');
+    }
+
+    @Override
+    public void onClick(View v) {
+        Logger.d(this, "onClick");
+        final AccessibilityManager accessibilityManager = (AccessibilityManager)
+            getActivity().getSystemService(Context.ACCESSIBILITY_SERVICE);
+        // When accessibility is on, simulate press and release to preserve the
+        // semantic meaning of performClick(). Required for Braille support.
+        if (accessibilityManager.isEnabled()) {
+            final int id = v.getId();
+            // Checking the press state prevents double activation.
+            if (!v.isPressed() && mDisplayMap.containsKey(id)) {
+                getPresenter().processDtmf(mDisplayMap.get(id), true /* timedShortTone */);
+            }
+        }
+    }
+
+    @Override
+    public boolean onHover(View v, MotionEvent event) {
+        // When touch exploration is turned on, lifting a finger while inside
+        // the button's hover target bounds should perform a click action.
+        final AccessibilityManager accessibilityManager = (AccessibilityManager)
+            getActivity().getSystemService(Context.ACCESSIBILITY_SERVICE);
+
+        if (accessibilityManager.isEnabled()
+                && accessibilityManager.isTouchExplorationEnabled()) {
+            final int left = v.getPaddingLeft();
+            final int right = (v.getWidth() - v.getPaddingRight());
+            final int top = v.getPaddingTop();
+            final int bottom = (v.getHeight() - v.getPaddingBottom());
+
+            switch (event.getActionMasked()) {
+                case MotionEvent.ACTION_HOVER_ENTER:
+                    // Lift-to-type temporarily disables double-tap activation.
+                    v.setClickable(false);
+                    break;
+                case MotionEvent.ACTION_HOVER_EXIT:
+                    final int x = (int) event.getX();
+                    final int y = (int) event.getY();
+                    if ((x > left) && (x < right) && (y > top) && (y < bottom)) {
+                        v.performClick();
+                    }
+                    v.setClickable(true);
+                    break;
+            }
+        }
+
+        return false;
+    }
+
+    @Override
+    public boolean onKey(View v, int keyCode, KeyEvent event) {
+        Logger.d(this, "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) {
+                        getPresenter().processDtmf(mDisplayMap.get(viewId));
+                    }
+                    break;
+                case KeyEvent.ACTION_UP:
+                    getPresenter().stopTone();
+                    break;
+                }
+                // do not return true [handled] here, since we want the
+                // press / click animation to be handled by the framework.
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public boolean onTouch(View v, MotionEvent event) {
+        Logger.d(this, "onTouch");
+        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
+                    getPresenter().processDtmf(mDisplayMap.get(viewId));
+                    break;
+                case MotionEvent.ACTION_UP:
+                case MotionEvent.ACTION_CANCEL:
+                    // stop the tone on ANY other event, except for MOVE.
+                    getPresenter().stopTone();
+                    break;
+            }
+            // do not return true [handled] here, since we want the
+            // press / click animation to be handled by the framework.
+        }
+        return false;
+    }
+
+    // TODO(klp) Adds hardware keyboard listener
+
+    @Override
+    DialpadPresenter createPresenter() {
+        return new DialpadPresenter();
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        final View parent = inflater.inflate(
+                com.android.incallui.R.layout.dtmf_twelve_key_dialer_view, container, false);
+        mDtmfDialerField = (EditText) parent.findViewById(R.id.dtmfDialerField);
+        if (mDtmfDialerField != null) {
+            // remove the long-press context menus that support
+            // the edit (copy / paste / select) functions.
+            mDtmfDialerField.setLongClickable(false);
+
+            setupKeypad(parent);
+        }
+        getPresenter().onUiReady(this);
+        return parent;
+    }
+
+    @Override
+    public void setVisible(boolean on) {
+        if (on) {
+            getView().setVisibility(View.VISIBLE);
+        } else {
+            getView().setVisibility(View.INVISIBLE);
+        }
+    }
+
+    @Override
+    public void appendDigitsToField(char digit) {
+        if (mDtmfDialerField != null) {
+            // TODO: maybe *don't* manually append this digit if
+            // mDialpadDigits is focused and this key came from the HW
+            // keyboard, since in that case the EditText field will
+            // get the key event directly and automatically appends
+            // whetever the user types.
+            // (Or, a cleaner fix would be to just make mDialpadDigits
+            // *not* handle HW key presses.  That seems to be more
+            // complicated than just setting focusable="false" on it,
+            // though.)
+            mDtmfDialerField.getText().append(digit);
+        }
+    }
+
+    /**
+     * setup the keys on the dialer activity, using the keymaps.
+     */
+    private void setupKeypad(View parent) {
+        // for each view id listed in the displaymap
+        View button;
+        for (int viewId : mDisplayMap.keySet()) {
+            // locate the view
+            button = parent.findViewById(viewId);
+            // Setup the listeners for the buttons
+            button.setOnTouchListener(this);
+            button.setClickable(true);
+            button.setOnKeyListener(this);
+            button.setOnHoverListener(this);
+            button.setOnClickListener(this);
+        }
+    }
+}
diff --git a/InCallUI/src/com/android/incallui/DialpadPresenter.java b/InCallUI/src/com/android/incallui/DialpadPresenter.java
new file mode 100644
index 0000000..727c90d
--- /dev/null
+++ b/InCallUI/src/com/android/incallui/DialpadPresenter.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2013 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.telephony.PhoneNumberUtils;
+
+/**
+ * Logic for call buttons.
+ */
+public class DialpadPresenter extends Presenter<DialpadPresenter.DialpadUi>
+        implements InCallPresenter.InCallStateListener {
+
+    @Override
+    public void onUiReady(DialpadUi ui) {
+        super.onUiReady(ui);
+    }
+
+    @Override
+    public void onStateChange(InCallPresenter.InCallState state, CallList callList) {
+
+    }
+
+    /**
+     * 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.
+     *
+     * @see #processDtmf(char, boolean)
+     */
+    public final void processDtmf(char c) {
+        processDtmf(c, false);
+    }
+
+    /**
+     * Processes the specified digit as a DTMF key, by playing the appropriate
+     * DTMF tone (or short tone if requested), and appending the digit to the
+     * EditText field that displays the DTMF digits sent so far.
+     */
+    // TODO(klp) Add timedShortTone==true handling for accessibility cases.
+    public final void processDtmf(char c, boolean timedShortTone) {
+        Logger.d(this, "Processing dtmf key " + c);
+        // if it is a valid key, then update the display and send the dtmf tone.
+        if (PhoneNumberUtils.is12Key(c)) {
+            Logger.d(this, "updating display and sending dtmf tone for '" + c + "'");
+
+            // Append this key to the "digits" widget.
+            getUi().appendDigitsToField(c);
+            // Plays the tone through CallCommandService
+            CallCommandClient.getInstance().playDtmfTone(c, timedShortTone);
+        } else {
+            Logger.d(this, "ignoring dtmf request for '" + c + "'");
+        }
+    }
+
+    /**
+     * Stops the local tone based on the phone type.
+     */
+    public void stopTone() {
+        Logger.d(this, "stopping remote tone");
+        CallCommandClient.getInstance().stopDtmfTone();
+    }
+
+    public interface DialpadUi extends Ui {
+        void setVisible(boolean on);
+        void appendDigitsToField(char digit);
+    }
+}
diff --git a/InCallUI/src/com/android/incallui/InCallActivity.java b/InCallUI/src/com/android/incallui/InCallActivity.java
index 9eb54ee..28e02b3 100644
--- a/InCallUI/src/com/android/incallui/InCallActivity.java
+++ b/InCallUI/src/com/android/incallui/InCallActivity.java
@@ -33,6 +33,7 @@
     private CallButtonFragment mCallButtonFragment;
     private CallCardFragment mCallCardFragment;
     private AnswerFragment mAnswerFragment;
+    private DialpadFragment mDialpadFragment;
 
     @Override
     protected void onCreate(Bundle icicle) {
@@ -133,7 +134,16 @@
 
     @Override
     public void onBackPressed() {
-        // TODO(klp): implement
+        // TODO(klp): implement fully
+        Logger.d(this, "onBackPressed()...");
+
+        // BACK is also used to exit out of any "special modes" of the
+        // in-call UI:
+
+        if (mDialpadFragment.isVisible()) {
+            mCallButtonFragment.displayDialpad(false);  // do the "closing" animation
+            return;
+        }
 
         // Nothing special to do.  Fall back to the default behavior.
         super.onBackPressed();
@@ -185,8 +195,7 @@
                 break;
         }
 
-        // TODO(klp): handle dialer key down
-
+        // TODO(klp) Adds hardware keyboard support
         return super.onKeyDown(keyCode, event);
     }
 
@@ -208,6 +217,12 @@
                     .findFragmentById(R.id.answerFragment);
         }
 
+        if (mDialpadFragment == null) {
+            mDialpadFragment = (DialpadFragment) getFragmentManager()
+                    .findFragmentById(R.id.dialpadFragment);
+            mDialpadFragment.getView().setVisibility(View.INVISIBLE);
+        }
+
         setUpPresenters();
     }
 
@@ -235,4 +250,14 @@
 
         toast.show();
     }
+
+    public void displayDialpad(boolean showDialpad) {
+        if (showDialpad) {
+            mDialpadFragment.setVisible(true);
+            mCallCardFragment.setVisible(false);
+        } else {
+            mDialpadFragment.setVisible(false);
+            mCallCardFragment.setVisible(true);
+        }
+    }
 }