Update Emergency Dialer to match Dialer (5/5).

Emergency dialer style updated to match style in Dialer and
InCallUI.
Moved all dialpad resources to PhoneCommon.

Change-Id: I9137a6114dad628309659b5381d501d7db2f455f
diff --git a/Android.mk b/Android.mk
index f01263e..3d1bb08 100644
--- a/Android.mk
+++ b/Android.mk
@@ -13,11 +13,12 @@
 # limitations under the License.
 
 LOCAL_PATH:= $(call my-dir)
-
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_RESOURCE_FILES := $(addprefix $(LOCAL_PATH)/, res)
 
-LOCAL_MODULE := com.android.phone.shared
+LOCAL_PACKAGE_NAME := com.android.phone.common
 
-include $(BUILD_STATIC_JAVA_LIBRARY)
+include $(BUILD_PACKAGE)
+include $(CLEAR_VARS)
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
new file mode 100644
index 0000000..ff2935f
--- /dev/null
+++ b/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 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
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.phone.common">
+</manifest>
+
diff --git a/res/anim/dialpad_slide_in_bottom.xml b/res/anim/dialpad_slide_in_bottom.xml
new file mode 100644
index 0000000..07748b5
--- /dev/null
+++ b/res/anim/dialpad_slide_in_bottom.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<translate xmlns:android="http://schemas.android.com/apk/res/android"
+    android:interpolator="@android:interpolator/fast_out_slow_in"
+    android:duration="@integer/dialpad_slide_in_duration"
+    android:fromYDelta="67%p"
+    android:toYDelta="0" />
diff --git a/res/anim/dialpad_slide_in_right.xml b/res/anim/dialpad_slide_in_right.xml
new file mode 100644
index 0000000..d87e82a
--- /dev/null
+++ b/res/anim/dialpad_slide_in_right.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (c) 2014, 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.
+-->
+
+<translate xmlns:android="http://schemas.android.com/apk/res/android"
+    android:fromXDelta="100%p"
+    android:toXDelta="0"
+    android:interpolator="@android:anim/decelerate_interpolator"
+    android:duration="@integer/dialpad_slide_in_duration"/>
diff --git a/res/anim/dialpad_slide_out_bottom.xml b/res/anim/dialpad_slide_out_bottom.xml
new file mode 100644
index 0000000..c80c8ed
--- /dev/null
+++ b/res/anim/dialpad_slide_out_bottom.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<translate xmlns:android="http://schemas.android.com/apk/res/android"
+    android:interpolator="@android:interpolator/fast_out_linear_in"
+    android:duration="@integer/dialpad_slide_out_duration"
+    android:fromYDelta="0"
+    android:toYDelta="80%p" />
diff --git a/res/anim/dialpad_slide_out_right.xml b/res/anim/dialpad_slide_out_right.xml
new file mode 100644
index 0000000..a29c1a0
--- /dev/null
+++ b/res/anim/dialpad_slide_out_right.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (c) 2014, 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.
+-->
+
+<translate xmlns:android="http://schemas.android.com/apk/res/android"
+    android:fromXDelta="0"
+    android:toXDelta="100%"
+    android:interpolator="@android:anim/decelerate_interpolator"
+    android:duration="@integer/dialpad_slide_out_duration"/>
diff --git a/res/drawable-hdpi/ic_dialpad_delete.png b/res/drawable-hdpi/ic_dialpad_delete.png
new file mode 100644
index 0000000..e588d90
--- /dev/null
+++ b/res/drawable-hdpi/ic_dialpad_delete.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_dialpad_vm.png b/res/drawable-hdpi/ic_dialpad_vm.png
new file mode 100644
index 0000000..9501300
--- /dev/null
+++ b/res/drawable-hdpi/ic_dialpad_vm.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_overflow_menu.png b/res/drawable-hdpi/ic_overflow_menu.png
new file mode 100644
index 0000000..262e9df
--- /dev/null
+++ b/res/drawable-hdpi/ic_overflow_menu.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_dialpad_delete.png b/res/drawable-mdpi/ic_dialpad_delete.png
new file mode 100644
index 0000000..64a52d0
--- /dev/null
+++ b/res/drawable-mdpi/ic_dialpad_delete.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_dialpad_vm.png b/res/drawable-mdpi/ic_dialpad_vm.png
new file mode 100644
index 0000000..f32d8bf
--- /dev/null
+++ b/res/drawable-mdpi/ic_dialpad_vm.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_overflow_menu.png b/res/drawable-mdpi/ic_overflow_menu.png
new file mode 100644
index 0000000..0e720dd
--- /dev/null
+++ b/res/drawable-mdpi/ic_overflow_menu.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_dialpad_delete.png b/res/drawable-xhdpi/ic_dialpad_delete.png
new file mode 100644
index 0000000..87bc113
--- /dev/null
+++ b/res/drawable-xhdpi/ic_dialpad_delete.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_dialpad_vm.png b/res/drawable-xhdpi/ic_dialpad_vm.png
new file mode 100644
index 0000000..5d87c50
--- /dev/null
+++ b/res/drawable-xhdpi/ic_dialpad_vm.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_overflow_menu.png b/res/drawable-xhdpi/ic_overflow_menu.png
new file mode 100644
index 0000000..9156076
--- /dev/null
+++ b/res/drawable-xhdpi/ic_overflow_menu.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_dialpad_delete.png b/res/drawable-xxhdpi/ic_dialpad_delete.png
new file mode 100644
index 0000000..186508a
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_dialpad_delete.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_dialpad_vm.png b/res/drawable-xxhdpi/ic_dialpad_vm.png
new file mode 100644
index 0000000..ac20fab
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_dialpad_vm.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_overflow_menu.png b/res/drawable-xxhdpi/ic_overflow_menu.png
new file mode 100644
index 0000000..92526f5
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_overflow_menu.png
Binary files differ
diff --git a/res/drawable/btn_dialpad_key.xml b/res/drawable/btn_dialpad_key.xml
new file mode 100644
index 0000000..a4cb088
--- /dev/null
+++ b/res/drawable/btn_dialpad_key.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="?android:attr/colorControlHighlight" />
\ No newline at end of file
diff --git a/res/layout-land/dialpad_key.xml b/res/layout-land/dialpad_key.xml
new file mode 100644
index 0000000..29e6bf1
--- /dev/null
+++ b/res/layout-land/dialpad_key.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- A layout representing a single key in the dialpad -->
+<com.android.phone.common.dialpad.DialpadKeyButton
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/DialpadKeyButtonStyle" >
+
+    <LinearLayout style="@style/DialpadKeyInternalLayoutStyle"
+        android:orientation="horizontal"
+        android:baselineAligned="false"
+        android:layout_gravity="right|center_vertical" >
+
+        <!-- Note in the referenced styles that we assign hard widths to these components
+             because we want them to line up vertically when we arrange them in an MxN grid -->
+
+        <com.android.phone.common.dialpad.DialpadTextView
+            android:id="@+id/dialpad_key_number"
+            style="@style/DialpadKeyNumberStyle"
+            android:layout_gravity="right"
+            android:layout_marginBottom="0dp"
+            android:layout_marginRight="@dimen/dialpad_key_margin_right" />
+
+        <TextView
+            android:id="@+id/dialpad_key_letters"
+            style="@style/DialpadKeyLettersStyle"
+            android:layout_width="@dimen/dialpad_key_text_width"
+            android:layout_gravity="right|bottom" />
+    </LinearLayout>
+</com.android.phone.common.dialpad.DialpadKeyButton>
diff --git a/res/layout-land/dialpad_key_one.xml b/res/layout-land/dialpad_key_one.xml
new file mode 100644
index 0000000..2890fd1
--- /dev/null
+++ b/res/layout-land/dialpad_key_one.xml
@@ -0,0 +1,48 @@
+<?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.
+-->
+<com.android.phone.common.dialpad.DialpadKeyButton
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/one"
+    style="@style/DialpadKeyButtonStyle">
+    <LinearLayout
+        style="@style/DialpadKeyInternalLayoutStyle"
+        android:orientation="horizontal"
+        android:baselineAligned="false"
+        android:layout_gravity="right|center_vertical" >
+        <com.android.phone.common.dialpad.DialpadTextView
+            android:id="@+id/dialpad_key_number"
+            style="@style/DialpadKeyNumberStyle"
+            android:layout_gravity="right"
+            android:layout_marginBottom="0dp"
+            android:layout_marginRight="@dimen/dialpad_key_margin_right" />
+        <RelativeLayout
+            android:layout_width="@dimen/dialpad_key_text_width"
+            android:layout_height="wrap_content"
+            android:layout_gravity="right|bottom" >
+            <ImageView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:paddingTop="@dimen/dialpad_voicemail_icon_padding_top"
+                android:id="@+id/dialpad_key_voicemail"
+                android:src="@drawable/ic_dialpad_vm"
+                android:scaleType="fitCenter"
+                android:layout_centerInParent="true"
+                android:tint="@color/dialpad_secondary_text_color" />
+            <!-- Place empty text view so vertical height is same as other dialpad keys. -->
+            <TextView style="@style/DialpadKeyLettersStyle" />
+        </RelativeLayout>
+    </LinearLayout>
+</com.android.phone.common.dialpad.DialpadKeyButton>
diff --git a/res/layout/dialpad.xml b/res/layout/dialpad.xml
new file mode 100644
index 0000000..1fc1f6c
--- /dev/null
+++ b/res/layout/dialpad.xml
@@ -0,0 +1,111 @@
+<?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.
+-->
+
+<!-- Dialpad in the Phone app. -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/dialpad"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:clipChildren="false">
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        android:orientation="horizontal">
+        <Space style="@style/DialpadSpaceStyle" />
+        <include layout="@layout/dialpad_key_one" />
+        <include layout="@layout/dialpad_key"
+            android:id="@+id/two"
+            style="@style/DialpadKeyButtonStyle" />
+        <include layout="@layout/dialpad_key"
+            android:id="@+id/three"
+            style="@style/DialpadKeyButtonStyle" />
+        <Space style="@style/DialpadSpaceStyle" />
+    </LinearLayout>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        android:orientation="horizontal">
+        <Space style="@style/DialpadSpaceStyle" />
+        <include layout="@layout/dialpad_key"
+            android:id="@+id/four"
+            style="@style/DialpadKeyButtonStyle" />
+        <include layout="@layout/dialpad_key"
+            android:id="@+id/five"
+            style="@style/DialpadKeyButtonStyle" />
+        <include layout="@layout/dialpad_key"
+            android:id="@+id/six"
+            style="@style/DialpadKeyButtonStyle" />
+        <Space style="@style/DialpadSpaceStyle" />
+    </LinearLayout>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        android:orientation="horizontal">
+        <Space style="@style/DialpadSpaceStyle" />
+        <include layout="@layout/dialpad_key"
+            android:id="@+id/seven"
+            style="@style/DialpadKeyButtonStyle" />
+        <include layout="@layout/dialpad_key"
+            android:id="@+id/eight"
+            style="@style/DialpadKeyButtonStyle" />
+        <include layout="@layout/dialpad_key"
+            android:id="@+id/nine"
+            style="@style/DialpadKeyButtonStyle" />
+        <Space style="@style/DialpadSpaceStyle" />
+    </LinearLayout>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        android:orientation="horizontal">
+        <Space style="@style/DialpadSpaceStyle" />
+        <com.android.phone.common.dialpad.DialpadKeyButton
+            android:id="@+id/star"
+            style="@style/DialpadKeyButtonStyle">
+            <LinearLayout
+                style="@style/DialpadKeyInternalLayoutStyle">
+                <com.android.phone.common.dialpad.DialpadTextView
+                    android:id="@+id/dialpad_key_number"
+                    style="@style/DialpadKeyStarStyle" />
+            </LinearLayout>
+        </com.android.phone.common.dialpad.DialpadKeyButton>
+        <include layout="@layout/dialpad_key"
+            android:id="@+id/zero"
+            style="@style/DialpadKeyButtonStyle" />
+        <com.android.phone.common.dialpad.DialpadKeyButton
+            android:id="@+id/pound"
+            style="@style/DialpadKeyButtonStyle">
+            <LinearLayout
+                style="@style/DialpadKeyInternalLayoutStyle">
+                <com.android.phone.common.dialpad.DialpadTextView
+                    android:id="@id/dialpad_key_number"
+                    style="@style/DialpadKeyPoundStyle" />
+            </LinearLayout>
+        </com.android.phone.common.dialpad.DialpadKeyButton>
+        <Space style="@style/DialpadSpaceStyle" />
+    </LinearLayout>
+    <Space
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/dialpad_bottom_key_height" />
+</LinearLayout>
diff --git a/res/layout/dialpad_key.xml b/res/layout/dialpad_key.xml
new file mode 100644
index 0000000..d5f47a4
--- /dev/null
+++ b/res/layout/dialpad_key.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- A layout representing a single key in the dialpad -->
+<com.android.phone.common.dialpad.DialpadKeyButton
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/DialpadKeyButtonStyle" >
+
+    <LinearLayout style="@style/DialpadKeyInternalLayoutStyle">
+
+        <!-- Note in the referenced styles that we assign hard widths to these components
+             because we want them to line up vertically when we arrange them in an MxN grid -->
+
+        <com.android.phone.common.dialpad.DialpadTextView
+            android:id="@+id/dialpad_key_number"
+            style="@style/DialpadKeyNumberStyle" />
+
+        <TextView
+            android:id="@+id/dialpad_key_letters"
+            style="@style/DialpadKeyLettersStyle" />
+    </LinearLayout>
+</com.android.phone.common.dialpad.DialpadKeyButton>
diff --git a/res/layout/dialpad_key_one.xml b/res/layout/dialpad_key_one.xml
new file mode 100644
index 0000000..dfb444a
--- /dev/null
+++ b/res/layout/dialpad_key_one.xml
@@ -0,0 +1,41 @@
+<?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.
+-->
+<com.android.phone.common.dialpad.DialpadKeyButton
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/one"
+    style="@style/DialpadKeyButtonStyle">
+    <LinearLayout
+        style="@style/DialpadKeyInternalLayoutStyle">
+        <com.android.phone.common.dialpad.DialpadTextView
+            android:id="@+id/dialpad_key_number"
+            style="@style/DialpadKeyNumberStyle" />
+        <RelativeLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" >
+            <ImageView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:paddingTop="@dimen/dialpad_voicemail_icon_padding_top"
+                android:id="@+id/dialpad_key_voicemail"
+                android:src="@drawable/ic_dialpad_vm"
+                android:scaleType="fitCenter"
+                android:layout_centerInParent="true"
+                android:tint="@color/dialpad_secondary_text_color" />
+            <!-- Place empty text view so vertical height is same as other dialpad keys. -->
+            <TextView style="@style/DialpadKeyLettersStyle" />
+        </RelativeLayout>
+    </LinearLayout>
+</com.android.phone.common.dialpad.DialpadKeyButton>
diff --git a/res/layout/dialpad_view.xml b/res/layout/dialpad_view.xml
new file mode 100644
index 0000000..68de527
--- /dev/null
+++ b/res/layout/dialpad_view.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+<view class="com.android.phone.common.dialpad.DialpadView"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/dialpad_view"
+    android:layout_height="match_parent"
+    android:layout_width="match_parent"
+    android:layout_gravity="bottom"
+    android:orientation="vertical"
+    android:layoutDirection="ltr"
+    android:background="@color/background_dialpad"
+    android:clickable="true" >
+
+    <!-- Text field and possibly soft menu button above the keypad where
+     the digits are displayed. -->
+    <LinearLayout
+        android:id="@+id/digits_container"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/dialpad_digits_height"
+        android:orientation="horizontal">
+
+        <ImageButton android:id="@+id/dialpad_overflow"
+            android:background="@drawable/btn_dialpad_key"
+            android:src="@drawable/ic_overflow_menu"
+            android:tint="@color/dialpad_icon_tint"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:paddingLeft="@dimen/dialpad_digits_padding"
+            android:paddingRight="@dimen/dialpad_digits_menu_right_padding"
+            android:contentDescription="@string/description_dialpad_overflow"
+            android:gravity="center"
+            android:visibility="gone" />
+
+        <view class="com.android.phone.common.dialpad.DigitsEditText"
+            android:id="@+id/digits"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:scrollHorizontally="true"
+            android:singleLine="true"
+            android:layout_weight="1"
+            android:gravity="center"
+            android:background="@android:color/transparent"
+            android:maxLines="1"
+            android:textSize="@dimen/dialpad_digits_text_size"
+            android:freezesText="true"
+            android:focusableInTouchMode="true"
+            android:cursorVisible="false"
+            android:textColor="@color/dialpad_digits_text_color"
+            android:textCursorDrawable="@null"
+            android:fontFamily="sans-serif-light"
+            android:textStyle="normal" />
+
+        <ImageButton
+            android:id="@+id/deleteButton"
+            android:background="@drawable/btn_dialpad_key"
+            android:tint="@color/dialpad_icon_tint"
+            android:paddingLeft="@dimen/dialpad_digits_padding"
+            android:paddingRight="@dimen/dialpad_digits_padding"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:state_enabled="false"
+            android:contentDescription="@string/description_delete_button"
+            android:src="@drawable/ic_dialpad_delete" />
+    </LinearLayout>
+
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="1dp"
+        android:background="#e3e3e3" />
+
+    <Space
+        android:layout_width="match_parent"
+        android:layout_height="14dp" />
+
+    <include layout="@layout/dialpad" />
+
+    <Space
+        android:layout_width="match_parent"
+        android:layout_height="8dp" />
+
+</view>
diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml
new file mode 100644
index 0000000..96547f0
--- /dev/null
+++ b/res/values-land/dimens.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2014 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.
+  -->
+<resources>
+    <dimen name="dialpad_key_margin_right">10dp</dimen>
+    <dimen name="dialpad_key_text_width">25dp</dimen>
+</resources>
diff --git a/res/values/animation_constants.xml b/res/values/animation_constants.xml
new file mode 100644
index 0000000..f8523e3
--- /dev/null
+++ b/res/values/animation_constants.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 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
+  -->
+<resources>
+    <integer name="floating_action_button_animation_duration">250</integer>
+    <integer name="dialpad_slide_in_duration">532</integer>
+    <integer name="dialpad_slide_out_duration">257</integer>
+</resources>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
new file mode 100644
index 0000000..09620a8
--- /dev/null
+++ b/res/values/attrs.xml
@@ -0,0 +1,21 @@
+<!--
+  ~ Copyright (C) 2012 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.
+  -->
+
+<resources>
+    <declare-styleable name="Dialpad">
+        <attr name="dialpad_key_button_touch_tint" format="color"/>
+    </declare-styleable>
+</resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
new file mode 100644
index 0000000..d38428c
--- /dev/null
+++ b/res/values/colors.xml
@@ -0,0 +1,26 @@
+<!--
+  ~ Copyright (C) 2012 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
+  -->
+
+<resources>
+    <!-- Colors for the dialpad -->
+    <color name="background_dialpad">#fcfcfc</color>
+    <color name="background_dialpad_pressed">#ececec</color>
+    <color name="dialpad_primary_text_color">#26c6da</color>
+    <color name="dialpad_secondary_text_color">#999999</color>
+    <color name="dialpad_digits_text_color">#666666</color>
+    <color name="dialpad_separator_line_color">#dadada</color>
+    <color name="dialpad_icon_tint">#b3b3b3</color>
+</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
new file mode 100644
index 0000000..d681d9d
--- /dev/null
+++ b/res/values/dimens.xml
@@ -0,0 +1,55 @@
+<!--
+  ~ Copyright (C) 2012 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
+  -->
+
+<resources>
+    <!-- Text dimensions for dialpad keys -->
+    <dimen name="dialpad_key_numbers_size">36sp</dimen>
+    <dimen name="dialpad_key_letters_size">8sp</dimen>
+    <dimen name="dialpad_key_pound_size">23sp</dimen>
+    <dimen name="dialpad_key_star_size">28sp</dimen>
+    <dimen name="dialpad_key_height">64dp</dimen>
+    <dimen name="dialpad_key_number_margin_bottom">2dp</dimen>
+    <dimen name="dialpad_symbol_margin_bottom">13dp</dimen>
+    <!-- The bottom row of the dialpad is slightly taller to account for the dial button -->
+    <dimen name="dialpad_bottom_key_height">65dp</dimen>
+    <dimen name="dialpad_key_plus_size">18sp</dimen>
+    <dimen name="dialpad_horizontal_padding">5dp</dimen>
+    <dimen name="dialpad_digits_text_size">36dp</dimen>
+    <dimen name="dialpad_digits_height">64dp</dimen>
+    <dimen name="dialpad_digits_padding">16dp</dimen>
+    <dimen name="dialpad_digits_menu_right_padding">10dp</dimen>
+    <dimen name="dialpad_center_margin">3dp</dimen>
+    <dimen name="dialpad_button_margin">2dp</dimen>
+    <dimen name="dialpad_voicemail_icon_padding_top">2dp</dimen>
+    <dimen name="dialpad_key_button_translate_y">100dp</dimen>
+    <!-- Height of the floating action button -->
+    <dimen name="floating_action_button_height">56dp</dimen>
+    <!-- Width of the floating action button -->
+    <dimen name="floating_action_button_width">56dp</dimen>
+    <!-- Corner radius of the floating action button -->
+    <dimen name="floating_action_button_radius">28dp</dimen>
+    <!-- Z translation of the floating action button -->
+    <dimen name="floating_action_button_translation_z">3dp</dimen>
+    <!-- Padding to be applied to the bottom of lists to make space for the floating action
+         button -->
+    <dimen name="floating_action_button_list_bottom_padding">88dp</dimen>
+    <!-- Right margin of the floating action button -->
+    <dimen name="floating_action_button_margin_right">16dp</dimen>
+    <!-- Bottom margin of the floating action button -->
+    <dimen name="floating_action_button_margin_bottom">16dp</dimen>
+    <!-- Offset of bottom margin of the floating action button used when dialpad is up -->
+    <dimen name="floating_action_button_dialpad_margin_bottom_offset">4dp</dimen>
+</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
new file mode 100644
index 0000000..bfa63a9
--- /dev/null
+++ b/res/values/strings.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2012 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
+  -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- The digit to be displayed on the 0 key of the dialpad [CHAR LIMIT=1]-->
+    <string name="dialpad_0_number">0</string>
+    <!-- The digit to be displayed on the 1 key of the dialpad [CHAR LIMIT=1]-->
+    <string name="dialpad_1_number">1</string>
+    <!-- The digit to be displayed on the 2 key of the dialpad [CHAR LIMIT=1]-->
+    <string name="dialpad_2_number">2</string>
+    <!-- The digit to be displayed on the 3 key of the dialpad [CHAR LIMIT=1]-->
+    <string name="dialpad_3_number">3</string>
+    <!-- The digit to be displayed on the 4 key of the dialpad [CHAR LIMIT=1]-->
+    <string name="dialpad_4_number">4</string>
+    <!-- The digit to be displayed on the 5 key of the dialpad [CHAR LIMIT=1]-->
+    <string name="dialpad_5_number">5</string>
+    <!-- The digit to be displayed on the 6 key of the dialpad [CHAR LIMIT=1]-->
+    <string name="dialpad_6_number">6</string>
+    <!-- The digit to be displayed on the 7 key of the dialpad [CHAR LIMIT=1]-->
+    <string name="dialpad_7_number">7</string>
+    <!-- The digit to be displayed on the 8 key of the dialpad [CHAR LIMIT=1]-->
+    <string name="dialpad_8_number">8</string>
+    <!-- The digit to be displayed on the 9 key of the dialpad [CHAR LIMIT=1]-->
+    <string name="dialpad_9_number">9</string>
+    <!--  Do not translate. -->
+    <string name="dialpad_star_number">*</string>
+    <!--  Do not translate. -->
+    <string name="dialpad_pound_number">#</string>
+
+    <!--  Do not translate. -->
+    <string name="dialpad_0_letters">+</string>
+    <!--  Do not translate. -->
+    <string name="dialpad_1_letters"></string>
+    <!--  Do not translate. -->
+    <string name="dialpad_2_letters">ABC</string>
+    <!--  Do not translate. -->
+    <string name="dialpad_3_letters">DEF</string>
+    <!--  Do not translate. -->
+    <string name="dialpad_4_letters">GHI</string>
+    <!--  Do not translate. -->
+    <string name="dialpad_5_letters">JKL</string>
+    <!--  Do not translate. -->
+    <string name="dialpad_6_letters">MNO</string>
+    <!--  Do not translate. -->
+    <string name="dialpad_7_letters">PQRS</string>
+    <!--  Do not translate. -->
+    <string name="dialpad_8_letters">TUV</string>
+    <!--  Do not translate. -->
+    <string name="dialpad_9_letters">WXYZ</string>
+    <!--  Do not translate. -->
+    <string name="dialpad_star_letters"></string>
+    <!--  Do not translate. -->
+    <string name="dialpad_pound_letters"></string>
+
+    <!-- String describing the overflow menu button in the dialpad. -->
+    <string name="description_dialpad_overflow">More options</string>
+
+    <!-- String describing the Delete/Backspace ImageButton.
+         Used by AccessibilityService to announce the purpose of the button.
+    -->
+    <string name="description_delete_button">backspace</string>
+
+     <!--  String describing the button used to add a plus (+) symbol to the dialpad -->
+     <string name="description_image_button_plus">plus</string>
+
+     <!-- String describing the Voicemail ImageButton.
+          Used by AccessibilityService to announce the purpose of the button.
+     -->
+     <string name="description_voicemail_button">voicemail</string>
+
+</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
new file mode 100644
index 0000000..5297aa1
--- /dev/null
+++ b/res/values/styles.xml
@@ -0,0 +1,83 @@
+<!--
+  ~ Copyright (C) 2012 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
+  -->
+
+<resources>
+    <style name="DialpadSpaceStyle">
+        <item name="android:layout_width">0dp</item>
+        <item name="android:layout_height">match_parent</item>
+        <item name="android:layout_weight">3</item>
+    </style>
+
+    <style name="DialpadKeyNumberStyle">
+        <item name="android:textColor">@color/dialpad_primary_text_color</item>
+        <item name="android:textSize">@dimen/dialpad_key_numbers_size</item>
+        <item name="android:fontFamily">sans-serif-light</item>
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:layout_marginBottom">@dimen/dialpad_key_number_margin_bottom</item>
+        <item name="android:gravity">center</item>
+    </style>
+
+    <style name="DialpadKeyStarStyle">
+        <item name="android:textColor">@color/dialpad_secondary_text_color</item>
+        <item name="android:textSize">@dimen/dialpad_key_star_size</item>
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:layout_marginBottom">@dimen/dialpad_symbol_margin_bottom</item>
+        <item name="android:gravity">center</item>
+    </style>
+
+    <style name="DialpadKeyPoundStyle">
+        <item name="android:textColor">@color/dialpad_secondary_text_color</item>
+        <item name="android:textSize">@dimen/dialpad_key_pound_size</item>
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:layout_marginBottom">@dimen/dialpad_symbol_margin_bottom</item>
+        <item name="android:gravity">center</item>
+    </style>
+
+    <style name="DialpadKeyLettersStyle">
+        <item name="android:textColor">@color/dialpad_secondary_text_color</item>
+        <item name="android:textSize">@dimen/dialpad_key_letters_size</item>
+        <item name="android:fontFamily">sans-serif-medium</item>
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:gravity">center_horizontal</item>
+    </style>
+
+    <style name="DialpadKeyButtonStyle">
+        <item name="android:soundEffectsEnabled">false</item>
+        <item name="android:clickable">true</item>
+        <item name="android:layout_width">0dp</item>
+        <item name="android:layout_height">match_parent</item>
+        <item name="android:layout_weight">13</item>
+        <item name="android:minHeight">@dimen/dialpad_key_height</item>
+        <item name="android:background">@drawable/btn_dialpad_key</item>
+        <item name="android:focusable">true</item>
+    </style>
+
+    <style name="DialpadBottomKeyButtonStyle" parent="DialpadKeyButtonStyle">
+        <item name="android:layout_height">@dimen/dialpad_bottom_key_height</item>
+    </style>
+
+    <style name="DialpadKeyInternalLayoutStyle">
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:layout_gravity">center</item>
+        <item name="android:gravity">center</item>
+        <item name="android:orientation">vertical</item>
+    </style>
+</resources>
diff --git a/src/com/android/phone/common/animation/AnimUtils.java b/src/com/android/phone/common/animation/AnimUtils.java
new file mode 100644
index 0000000..35ac107
--- /dev/null
+++ b/src/com/android/phone/common/animation/AnimUtils.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2014 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.phone.common.animation;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.view.View;
+import android.view.ViewPropertyAnimator;
+import android.view.animation.Interpolator;
+import android.view.animation.PathInterpolator;
+
+public class AnimUtils {
+    public static final int DEFAULT_DURATION = -1;
+    public static final Interpolator EASE_IN = new PathInterpolator(0.0f, 0.0f, 0.2f, 1.0f);
+    public static final Interpolator EASE_OUT = new PathInterpolator(0.4f, 0.0f, 1.0f, 1.0f);
+    public static final Interpolator EASE_OUT_EASE_IN = new PathInterpolator(0.4f, 0, 0.2f, 1);
+
+    public static class AnimationCallback {
+        public void onAnimationEnd() {}
+        public void onAnimationCancel() {}
+    }
+
+    public static void crossFadeViews(View fadeIn, View fadeOut, int duration) {
+        fadeIn(fadeIn, duration);
+        fadeOut(fadeOut, duration);
+    }
+
+    public static void fadeOut(View fadeOut, int duration) {
+        fadeOut(fadeOut, duration, null);
+    }
+
+    public static void fadeOut(final View fadeOut, int duration, final AnimationCallback callback) {
+        fadeOut.setAlpha(1);
+        final ViewPropertyAnimator animator = fadeOut.animate();
+        animator.cancel();
+        animator.alpha(0).withLayer().setListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                fadeOut.setVisibility(View.GONE);
+                if (callback != null) {
+                    callback.onAnimationEnd();
+                }
+            }
+
+            @Override
+            public void onAnimationCancel(Animator animation) {
+                fadeOut.setVisibility(View.GONE);
+                fadeOut.setAlpha(0);
+                if (callback != null) {
+                    callback.onAnimationCancel();
+                }
+            }
+        });
+        if (duration != DEFAULT_DURATION) {
+            animator.setDuration(duration);
+        }
+        animator.start();
+    }
+
+    public static void fadeIn(View fadeIn, int duration) {
+        fadeIn(fadeIn, duration, null);
+    }
+
+    public static void fadeIn(final View fadeIn, int duration, final AnimationCallback callback) {
+        fadeIn.setAlpha(0);
+        final ViewPropertyAnimator animator = fadeIn.animate();
+        animator.cancel();
+        animator.alpha(1).withLayer().setListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationStart(Animator animation) {
+                fadeIn.setVisibility(View.VISIBLE);
+            }
+
+            @Override
+            public void onAnimationCancel(Animator animation) {
+                fadeIn.setAlpha(1);
+                if (callback != null) {
+                    callback.onAnimationCancel();
+                }
+            }
+
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                if (callback != null) {
+                    callback.onAnimationEnd();
+                }
+            }
+        });
+        if (duration != DEFAULT_DURATION) {
+            animator.setDuration(duration);
+        }
+        animator.start();
+    }
+}
diff --git a/src/com/android/phone/common/animation/AnimationListenerAdapter.java b/src/com/android/phone/common/animation/AnimationListenerAdapter.java
new file mode 100644
index 0000000..d8f3fa6
--- /dev/null
+++ b/src/com/android/phone/common/animation/AnimationListenerAdapter.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2014 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.phone.common.animation;
+
+import android.view.animation.Animation;
+import android.view.animation.Animation.AnimationListener;
+
+/**
+ * Provides empty implementations of the methods in {@link AnimationListener}
+ * for convenience reasons.
+ */
+public class AnimationListenerAdapter implements AnimationListener {
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onAnimationStart(Animation animation) {
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onAnimationEnd(Animation animation) {
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onAnimationRepeat(Animation animation) {
+    }
+}
diff --git a/src/com/android/phone/common/dialpad/DialpadKeyButton.java b/src/com/android/phone/common/dialpad/DialpadKeyButton.java
new file mode 100644
index 0000000..4e3781c
--- /dev/null
+++ b/src/com/android/phone/common/dialpad/DialpadKeyButton.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2012 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.phone.common.dialpad;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.widget.FrameLayout;
+
+/**
+ * Custom class for dialpad buttons.
+ * <p>
+ * When touch exploration mode is enabled for accessibility, this class
+ * implements the lift-to-type interaction model:
+ * <ul>
+ * <li>Hovering over the button will cause it to gain accessibility focus
+ * <li>Removing the hover pointer while inside the bounds of the button will
+ * perform a click action
+ * <li>If long-click is supported, hovering over the button for a longer period
+ * of time will switch to the long-click action
+ * <li>Moving the hover pointer outside of the bounds of the button will restore
+ * to the normal click action
+ * <ul>
+ */
+public class DialpadKeyButton extends FrameLayout {
+    /** Timeout before switching to long-click accessibility mode. */
+    private static final int LONG_HOVER_TIMEOUT = ViewConfiguration.getLongPressTimeout() * 2;
+
+    /** Accessibility manager instance used to check touch exploration state. */
+    private AccessibilityManager mAccessibilityManager;
+
+    /** Bounds used to filter HOVER_EXIT events. */
+    private Rect mHoverBounds = new Rect();
+
+    /** Whether this view is currently in the long-hover state. */
+    private boolean mLongHovered;
+
+    /** Alternate content description for long-hover state. */
+    private CharSequence mLongHoverContentDesc;
+
+    /** Backup of standard content description. Used for accessibility. */
+    private CharSequence mBackupContentDesc;
+
+    /** Backup of clickable property. Used for accessibility. */
+    private boolean mWasClickable;
+
+    /** Backup of long-clickable property. Used for accessibility. */
+    private boolean mWasLongClickable;
+
+    /** Runnable used to trigger long-click mode for accessibility. */
+    private Runnable mLongHoverRunnable;
+
+    public interface OnPressedListener {
+        public void onPressed(View view, boolean pressed);
+    }
+
+    private OnPressedListener mOnPressedListener;
+
+    public void setOnPressedListener(OnPressedListener onPressedListener) {
+        mOnPressedListener = onPressedListener;
+    }
+
+    public DialpadKeyButton(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        initForAccessibility(context);
+    }
+
+    public DialpadKeyButton(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        initForAccessibility(context);
+    }
+
+    private void initForAccessibility(Context context) {
+        mAccessibilityManager = (AccessibilityManager) context.getSystemService(
+                Context.ACCESSIBILITY_SERVICE);
+    }
+
+    public void setLongHoverContentDescription(CharSequence contentDescription) {
+        mLongHoverContentDesc = contentDescription;
+
+        if (mLongHovered) {
+            super.setContentDescription(mLongHoverContentDesc);
+        }
+    }
+
+    @Override
+    public void setContentDescription(CharSequence contentDescription) {
+        if (mLongHovered) {
+            mBackupContentDesc = contentDescription;
+        } else {
+            super.setContentDescription(contentDescription);
+        }
+    }
+
+    @Override
+    public void setPressed(boolean pressed) {
+        super.setPressed(pressed);
+        if (mOnPressedListener != null) {
+            mOnPressedListener.onPressed(this, pressed);
+        }
+    }
+
+    @Override
+    public void onSizeChanged(int w, int h, int oldw, int oldh) {
+        super.onSizeChanged(w, h, oldw, oldh);
+
+        mHoverBounds.left = getPaddingLeft();
+        mHoverBounds.right = w - getPaddingRight();
+        mHoverBounds.top = getPaddingTop();
+        mHoverBounds.bottom = h - getPaddingBottom();
+    }
+
+    @Override
+    public boolean performAccessibilityAction(int action, Bundle arguments) {
+        if (action == AccessibilityNodeInfo.ACTION_CLICK) {
+            simulateClickForAccessibility();
+            return true;
+        }
+
+        return super.performAccessibilityAction(action, arguments);
+    }
+
+    @Override
+    public boolean onHoverEvent(MotionEvent event) {
+        // When touch exploration is turned on, lifting a finger while inside
+        // the button's hover target bounds should perform a click action.
+        if (mAccessibilityManager.isEnabled()
+                && mAccessibilityManager.isTouchExplorationEnabled()) {
+            switch (event.getActionMasked()) {
+                case MotionEvent.ACTION_HOVER_ENTER:
+                    // Lift-to-type temporarily disables double-tap activation.
+                    mWasClickable = isClickable();
+                    mWasLongClickable = isLongClickable();
+                    if (mWasLongClickable && mLongHoverContentDesc != null) {
+                        if (mLongHoverRunnable == null) {
+                            mLongHoverRunnable = new Runnable() {
+                                @Override
+                                public void run() {
+                                    setLongHovered(true);
+                                    announceForAccessibility(mLongHoverContentDesc);
+                                }
+                            };
+                        }
+                        postDelayed(mLongHoverRunnable, LONG_HOVER_TIMEOUT);
+                    }
+
+                    setClickable(false);
+                    setLongClickable(false);
+                    break;
+                case MotionEvent.ACTION_HOVER_EXIT:
+                    if (mHoverBounds.contains((int) event.getX(), (int) event.getY())) {
+                        if (mLongHovered) {
+                            performLongClick();
+                        } else {
+                            simulateClickForAccessibility();
+                        }
+                    }
+
+                    cancelLongHover();
+                    setClickable(mWasClickable);
+                    setLongClickable(mWasLongClickable);
+                    break;
+            }
+        }
+
+        return super.onHoverEvent(event);
+    }
+
+    /**
+     * When accessibility is on, simulate press and release to preserve the
+     * semantic meaning of performClick(). Required for Braille support.
+     */
+    private void simulateClickForAccessibility() {
+        // Checking the press state prevents double activation.
+        if (isPressed()) {
+            return;
+        }
+
+        setPressed(true);
+
+        // Stay consistent with performClick() by sending the event after
+        // setting the pressed state but before performing the action.
+        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
+
+        setPressed(false);
+    }
+
+    private void setLongHovered(boolean enabled) {
+        if (mLongHovered != enabled) {
+            mLongHovered = enabled;
+
+            // Switch between normal and alternate description, if available.
+            if (enabled) {
+                mBackupContentDesc = getContentDescription();
+                super.setContentDescription(mLongHoverContentDesc);
+            } else {
+                super.setContentDescription(mBackupContentDesc);
+            }
+        }
+    }
+
+    private void cancelLongHover() {
+        if (mLongHoverRunnable != null) {
+            removeCallbacks(mLongHoverRunnable);
+        }
+        setLongHovered(false);
+    }
+}
diff --git a/src/com/android/phone/common/dialpad/DialpadTextView.java b/src/com/android/phone/common/dialpad/DialpadTextView.java
new file mode 100644
index 0000000..2802b32
--- /dev/null
+++ b/src/com/android/phone/common/dialpad/DialpadTextView.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2014 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.phone.common.dialpad;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+/**
+ * This is a custom text view intended only for rendering the numerals (and star and pound) on the
+ * dialpad. TextView has built in top/bottom padding to help account for ascenders/descenders.
+ *
+ * Since vertical space is at a premium on the dialpad, particularly if the font size is scaled to
+ * a larger default, for the dialpad we use this class to more precisely render characters according
+ * to the precise amount of space they need.
+ */
+public class DialpadTextView extends TextView {
+    private Rect mTextBounds = new Rect();
+    private String mTextStr;
+
+    public DialpadTextView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    /**
+     * Draw the text to fit within the height/width which have been specified during measurement.
+     */
+    @Override
+    public void draw(Canvas canvas) {
+        Paint paint = getPaint();
+
+        // Without this, the draw does not respect the style's specified text color.
+        paint.setColor(getCurrentTextColor());
+
+        // The text bounds values are relative and can be negative,, so rather than specifying a
+        // standard origin such as 0, 0, we need to use negative of the left/top bounds.
+        // For example, the bounds may be: Left: 11, Right: 37, Top: -77, Bottom: 0
+        canvas.drawText(mTextStr, -mTextBounds.left, -mTextBounds.top, paint);
+    }
+
+    /**
+     * Calculate the pixel-accurate bounds of the text when rendered, and use that to specify the
+     * height and width.
+     */
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        mTextStr = getText().toString();
+        getPaint().getTextBounds(mTextStr, 0, mTextStr.length(), mTextBounds);
+
+        int width = resolveSize(mTextBounds.width(), widthMeasureSpec);
+        int height = resolveSize(mTextBounds.height(), heightMeasureSpec);
+        setMeasuredDimension(width, height);
+    }
+}
diff --git a/src/com/android/phone/common/dialpad/DialpadView.java b/src/com/android/phone/common/dialpad/DialpadView.java
new file mode 100644
index 0000000..6f9dd41
--- /dev/null
+++ b/src/com/android/phone/common/dialpad/DialpadView.java
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2014 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.phone.common.dialpad;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.RippleDrawable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.EditText;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.phone.common.R;
+import com.android.phone.common.animation.AnimUtils;
+
+/**
+ * View that displays a twelve-key phone dialpad.
+ */
+public class DialpadView extends LinearLayout {
+    private static final String TAG = DialpadView.class.getSimpleName();
+
+    private static final double DELAY_MULTIPLIER = 0.66;
+    private static final double DURATION_MULTIPLIER = 0.8;
+
+    private EditText mDigits;
+    private ImageButton mDelete;
+    private View mOverflowMenuButton;
+    private ColorStateList mRippleColor;
+
+    private boolean mCanDigitsBeEdited;
+
+    private final int[] mButtonIds = new int[] {R.id.zero, R.id.one, R.id.two, R.id.three,
+            R.id.four, R.id.five, R.id.six, R.id.seven, R.id.eight, R.id.nine, R.id.star,
+            R.id.pound};
+
+    // For animation.
+    private static final int KEY_FRAME_DURATION = 33;
+
+    private int mTranslateDistance;
+
+    public DialpadView(Context context) {
+        this(context, null);
+    }
+
+    public DialpadView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public DialpadView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Dialpad);
+        mRippleColor = a.getColorStateList(R.styleable.Dialpad_dialpad_key_button_touch_tint);
+        a.recycle();
+
+        mTranslateDistance = getResources().getDimensionPixelSize(
+                R.dimen.dialpad_key_button_translate_y);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        setupKeypad();
+        mDigits = (EditText) findViewById(R.id.digits);
+        mDelete = (ImageButton) findViewById(R.id.deleteButton);
+        mOverflowMenuButton = findViewById(R.id.dialpad_overflow);
+    }
+
+    private void setupKeypad() {
+        final int[] numberIds = new int[] {R.string.dialpad_0_number, R.string.dialpad_1_number,
+                R.string.dialpad_2_number, R.string.dialpad_3_number, R.string.dialpad_4_number,
+                R.string.dialpad_5_number, R.string.dialpad_6_number, R.string.dialpad_7_number,
+                R.string.dialpad_8_number, R.string.dialpad_9_number, R.string.dialpad_star_number,
+                R.string.dialpad_pound_number};
+
+        final int[] letterIds = new int[] {R.string.dialpad_0_letters, R.string.dialpad_1_letters,
+                R.string.dialpad_2_letters, R.string.dialpad_3_letters, R.string.dialpad_4_letters,
+                R.string.dialpad_5_letters, R.string.dialpad_6_letters, R.string.dialpad_7_letters,
+                R.string.dialpad_8_letters, R.string.dialpad_9_letters,
+                R.string.dialpad_star_letters, R.string.dialpad_pound_letters};
+
+        final Resources resources = getContext().getResources();
+
+        DialpadKeyButton dialpadKey;
+        TextView numberView;
+        TextView lettersView;
+
+        for (int i = 0; i < mButtonIds.length; i++) {
+            dialpadKey = (DialpadKeyButton) findViewById(mButtonIds[i]);
+            numberView = (TextView) dialpadKey.findViewById(R.id.dialpad_key_number);
+            lettersView = (TextView) dialpadKey.findViewById(R.id.dialpad_key_letters);
+            final String numberString = resources.getString(numberIds[i]);
+            final RippleDrawable rippleBackground =
+                    (RippleDrawable) resources.getDrawable(R.drawable.btn_dialpad_key);
+            if (mRippleColor != null) {
+                rippleBackground.setColor(mRippleColor);
+            }
+
+            numberView.setText(numberString);
+            numberView.setElegantTextHeight(false);
+            dialpadKey.setContentDescription(numberString);
+            dialpadKey.setBackground(rippleBackground);
+
+            if (lettersView != null) {
+                lettersView.setText(resources.getString(letterIds[i]));
+            }
+        }
+
+        final DialpadKeyButton one = (DialpadKeyButton) findViewById(R.id.one);
+        one.setLongHoverContentDescription(
+                resources.getText(R.string.description_voicemail_button));
+
+        final DialpadKeyButton zero = (DialpadKeyButton) findViewById(R.id.zero);
+        zero.setLongHoverContentDescription(
+                resources.getText(R.string.description_image_button_plus));
+
+    }
+
+    public void setShowVoicemailButton(boolean show) {
+        View view = findViewById(R.id.dialpad_key_voicemail);
+        if (view != null) {
+            view.setVisibility(show ? View.VISIBLE : View.INVISIBLE);
+        }
+    }
+
+    /**
+     * Whether or not the digits above the dialer can be edited.
+     *
+     * @param canBeEdited If true, the backspace button will be shown and the digits EditText
+     *         will be configured to allow text manipulation.
+     */
+    public void setCanDigitsBeEdited(boolean canBeEdited) {
+        View deleteButton = findViewById(R.id.deleteButton);
+        deleteButton.setVisibility(canBeEdited ? View.VISIBLE : View.GONE);
+        View overflowMenuButton = findViewById(R.id.dialpad_overflow);
+        overflowMenuButton.setVisibility(canBeEdited ? View.VISIBLE : View.GONE);
+
+        EditText digits = (EditText) findViewById(R.id.digits);
+        digits.setClickable(canBeEdited);
+        digits.setLongClickable(canBeEdited);
+        digits.setFocusableInTouchMode(canBeEdited);
+        digits.setCursorVisible(false);
+
+        mCanDigitsBeEdited = canBeEdited;
+    }
+
+    public boolean canDigitsBeEdited() {
+        return mCanDigitsBeEdited;
+    }
+
+    /**
+     * Always returns true for onHoverEvent callbacks, to fix problems with accessibility due to
+     * the dialpad overlaying other fragments.
+     */
+    @Override
+    public boolean onHoverEvent(MotionEvent event) {
+        return true;
+    }
+
+    public void animateShow() {
+        // This is a hack; without this, the setTranslationY is delayed in being applied, and the
+        // numbers appear at their original position (0) momentarily before animating.
+        final AnimatorListenerAdapter showListener = new AnimatorListenerAdapter() {};
+
+        for (int i = 0; i < mButtonIds.length; i++) {
+            int delay = (int)(getKeyButtonAnimationDelay(mButtonIds[i]) * DELAY_MULTIPLIER);
+            int duration =
+                    (int)(getKeyButtonAnimationDuration(mButtonIds[i]) * DURATION_MULTIPLIER);
+            final DialpadKeyButton dialpadKey = (DialpadKeyButton) findViewById(mButtonIds[i]);
+
+            dialpadKey.setTranslationY(mTranslateDistance);
+            dialpadKey.animate()
+                    .translationY(0)
+                    .setInterpolator(AnimUtils.EASE_OUT_EASE_IN)
+                    .setStartDelay(delay)
+                    .setDuration(duration)
+                    .setListener(showListener)
+                    .start();
+        }
+    }
+
+    public EditText getDigits() {
+        return mDigits;
+    }
+
+    public ImageButton getDeleteButton() {
+        return mDelete;
+    }
+
+    public View getOverflowMenuButton() {
+        return mOverflowMenuButton;
+    }
+
+    private int getKeyButtonAnimationDelay(int buttonId) {
+        switch(buttonId) {
+            case R.id.one: return KEY_FRAME_DURATION * 1;
+            case R.id.two: return KEY_FRAME_DURATION * 2;
+            case R.id.three: return KEY_FRAME_DURATION * 3;
+            case R.id.four: return KEY_FRAME_DURATION * 4;
+            case R.id.five: return KEY_FRAME_DURATION * 5;
+            case R.id.six: return KEY_FRAME_DURATION * 6;
+            case R.id.seven: return KEY_FRAME_DURATION * 7;
+            case R.id.eight: return KEY_FRAME_DURATION * 8;
+            case R.id.nine: return KEY_FRAME_DURATION * 9;
+            case R.id.star: return KEY_FRAME_DURATION * 10;
+            case R.id.zero:
+            case R.id.pound:
+                return KEY_FRAME_DURATION * 11;
+        }
+
+        Log.wtf(TAG, "Attempted to get animation delay for invalid key button id.");
+        return 0;
+    }
+
+    private int getKeyButtonAnimationDuration(int buttonId) {
+        switch(buttonId) {
+            case R.id.one:
+            case R.id.two:
+            case R.id.three:
+            case R.id.four:
+            case R.id.five:
+            case R.id.six:
+                return KEY_FRAME_DURATION * 10;
+            case R.id.seven:
+            case R.id.eight:
+            case R.id.nine:
+                return KEY_FRAME_DURATION * 9;
+            case R.id.star:
+            case R.id.zero:
+            case R.id.pound:
+                return KEY_FRAME_DURATION * 8;
+        }
+
+        Log.wtf(TAG, "Attempted to get animation duration for invalid key button id.");
+        return 0;
+    }
+}
diff --git a/src/com/android/phone/common/dialpad/DigitsEditText.java b/src/com/android/phone/common/dialpad/DigitsEditText.java
new file mode 100644
index 0000000..b2022aa
--- /dev/null
+++ b/src/com/android/phone/common/dialpad/DigitsEditText.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2011 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.phone.common.dialpad;
+
+import android.content.Context;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.text.InputType;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.view.MotionEvent;
+import android.view.ViewGroup;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+
+import com.android.phone.common.R;
+
+/**
+ * EditText which suppresses IME show up.
+ */
+public class DigitsEditText extends EditText {
+    // Only scale the text down to 66% smaller at most.
+    private static final float MIN_TEXT_RESIZE_RATIO = 0.66f;
+    private final float mOriginalTextSize;
+
+    public DigitsEditText(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mOriginalTextSize = getTextSize();
+        setInputType(getInputType() | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
+        setShowSoftInputOnFocus(false);
+    }
+
+    @Override
+    protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
+        super.onFocusChanged(focused, direction, previouslyFocusedRect);
+        final InputMethodManager imm = ((InputMethodManager) getContext()
+                .getSystemService(Context.INPUT_METHOD_SERVICE));
+        if (imm != null && imm.isActive(this)) {
+            imm.hideSoftInputFromWindow(getApplicationWindowToken(), 0);
+        }
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        final boolean ret = super.onTouchEvent(event);
+        // Must be done after super.onTouchEvent()
+        final InputMethodManager imm = ((InputMethodManager) getContext()
+                .getSystemService(Context.INPUT_METHOD_SERVICE));
+        if (imm != null && imm.isActive(this)) {
+            imm.hideSoftInputFromWindow(getApplicationWindowToken(), 0);
+        }
+        return ret;
+    }
+
+    @Override
+    protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
+        super.onTextChanged(text, start, lengthBefore, lengthAfter);
+        resizeText(getWidth());
+    }
+
+    @Override
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        super.onSizeChanged(w, h, oldw, oldh);
+        resizeText(w);
+    }
+
+    private void resizeText(int width) {
+        if (width == 0) {
+            return;
+        }
+        final Paint paint = getPaint();
+        setTextSize(TypedValue.COMPLEX_UNIT_PX, mOriginalTextSize);
+
+        float ratio = width / paint.measureText(getText().toString());
+        if (ratio <= 1.0f) {
+            setTextSize(TypedValue.COMPLEX_UNIT_PX,
+                    mOriginalTextSize * Math.max(MIN_TEXT_RESIZE_RATIO, ratio));
+        }
+    }
+}
diff --git a/src/com/android/phone/common/util/ViewUtil.java b/src/com/android/phone/common/util/ViewUtil.java
new file mode 100644
index 0000000..171eee0
--- /dev/null
+++ b/src/com/android/phone/common/util/ViewUtil.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2012 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.phone.common.util;
+
+import android.content.res.Resources;
+import android.graphics.Outline;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ListView;
+
+import com.android.phone.common.R;
+
+/**
+ * Provides static functions to work with views
+ */
+public class ViewUtil {
+    private ViewUtil() {}
+
+    /**
+     * Returns the width as specified in the LayoutParams
+     * @throws IllegalStateException Thrown if the view's width is unknown before a layout pass
+     * s
+     */
+    public static int getConstantPreLayoutWidth(View view) {
+        // We haven't been layed out yet, so get the size from the LayoutParams
+        final ViewGroup.LayoutParams p = view.getLayoutParams();
+        if (p.width < 0) {
+            throw new IllegalStateException("Expecting view's width to be a constant rather " +
+                    "than a result of the layout pass");
+        }
+        return p.width;
+    }
+
+    /**
+     * Returns a boolean indicating whether or not the view's layout direction is RTL
+     *
+     * @param view - A valid view
+     * @return True if the view's layout direction is RTL
+     */
+    public static boolean isViewLayoutRtl(View view) {
+        return view.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
+    }
+
+    /**
+     * Configures the floating action button, clipping it to a circle and setting its translation z.
+     * @param view The float action button's view.
+     * @param res The resources file.
+     */
+    public static void setupFloatingActionButton(View view, Resources res) {
+        // Once layout is complete and the floating action button has been assigned a width and
+        // height, assign the outline.
+        view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
+            @Override
+            public void onLayoutChange(View v, int left, int top, int right, int bottom,
+                    int oldLeft, int oldTop, int oldRight, int oldBottom) {
+                final Outline outline = new Outline();
+                final int minDimension = Math.min(right - left, bottom - top);
+                if (minDimension <= 0) {
+                    return;
+                }
+                outline.setRoundRect(0, 0, right - left, bottom - top, minDimension / 2);
+                v.setOutline(outline);
+            }
+        });
+        view.setTranslationZ(
+                res.getDimensionPixelSize(R.dimen.floating_action_button_translation_z));
+    }
+
+    /**
+     * Adds padding to the bottom of the given {@link ListView} so that the floating action button
+     * does not obscure any content.
+     *
+     * @param listView to add the padding to
+     * @param res valid resources object
+     */
+    public static void addBottomPaddingToListViewForFab(ListView listView, Resources res) {
+        final int fabPadding = res.getDimensionPixelSize(
+                R.dimen.floating_action_button_list_bottom_padding);
+        listView.setPaddingRelative(listView.getPaddingStart(), listView.getPaddingTop(),
+                listView.getPaddingEnd(), listView.getPaddingBottom() + fabPadding);
+        listView.setClipToPadding(false);
+    }
+}