Add faster emergency call button UI

Faster emergency dialer list a shortcut button of no location status.
The location information would not displayed, and the call button is for
112 using. Clicking to the button, it would show a confirm view for
seeking the second click to place an emergency call.

Test: Manually
Bug: 80406570
Change-Id: I61e2deed6372bb7207cd9efc003ccb48bac611d2
Merged-In: I61e2deed6372bb7207cd9efc003ccb48bac611d2
diff --git a/res/drawable-hdpi/ic_emergency_number_24.png b/res/drawable-hdpi/ic_emergency_number_24.png
new file mode 100644
index 0000000..d5c0b28
--- /dev/null
+++ b/res/drawable-hdpi/ic_emergency_number_24.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_location_on_white_18.png b/res/drawable-hdpi/ic_location_on_white_18.png
new file mode 100644
index 0000000..8f93ec9
--- /dev/null
+++ b/res/drawable-hdpi/ic_location_on_white_18.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_emergency_number_24.png b/res/drawable-mdpi/ic_emergency_number_24.png
new file mode 100644
index 0000000..3db2d19
--- /dev/null
+++ b/res/drawable-mdpi/ic_emergency_number_24.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_location_on_white_18.png b/res/drawable-mdpi/ic_location_on_white_18.png
new file mode 100644
index 0000000..5c5b0fb
--- /dev/null
+++ b/res/drawable-mdpi/ic_location_on_white_18.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_emergency_number_24.png b/res/drawable-xhdpi/ic_emergency_number_24.png
new file mode 100644
index 0000000..b538c02
--- /dev/null
+++ b/res/drawable-xhdpi/ic_emergency_number_24.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_location_on_white_18.png b/res/drawable-xhdpi/ic_location_on_white_18.png
new file mode 100644
index 0000000..7c281c3
--- /dev/null
+++ b/res/drawable-xhdpi/ic_location_on_white_18.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_emergency_number_24.png b/res/drawable-xxhdpi/ic_emergency_number_24.png
new file mode 100644
index 0000000..13f253b
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_emergency_number_24.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_location_on_white_18.png b/res/drawable-xxhdpi/ic_location_on_white_18.png
new file mode 100644
index 0000000..b345cff
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_location_on_white_18.png
Binary files differ
diff --git a/res/drawable/phone_type_icon_background.xml b/res/drawable/phone_type_icon_background.xml
new file mode 100644
index 0000000..b51c3b2
--- /dev/null
+++ b/res/drawable/phone_type_icon_background.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="oval">
+    <solid android:color="@color/emergency_shortcut_confirm_button_background_color"/>
+</shape>
\ No newline at end of file
diff --git a/res/layout/emergency_dialer.xml b/res/layout/emergency_dialer.xml
index 41da3b1..b98b5c4 100644
--- a/res/layout/emergency_dialer.xml
+++ b/res/layout/emergency_dialer.xml
@@ -33,6 +33,7 @@
             android:layout_height="match_parent"
             android:orientation="vertical">
             <include layout="@layout/emergency_information"/>
+            <include layout="@layout/emergency_shortcut_buttons_group"/>
         </LinearLayout>
 
         <FrameLayout
diff --git a/res/layout/emergency_shortcut_button.xml b/res/layout/emergency_shortcut_button.xml
new file mode 100644
index 0000000..5e30d4e5
--- /dev/null
+++ b/res/layout/emergency_shortcut_button.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.EmergencyShortcutButton
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_height="64dp"
+    android:layout_width="match_parent">
+    <!-- Normal emergency call button view -->
+    <FrameLayout
+        android:id="@+id/emergency_call_number_info_view"
+        android:layout_height="match_parent"
+        android:layout_width="match_parent"
+        android:focusable="true"
+        android:clickable="true">
+        <LinearLayout
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:layout_gravity="center_vertical|start"
+            android:gravity="center_vertical"
+            android:orientation="horizontal">
+            <FrameLayout
+                android:layout_height="40dp"
+                android:layout_width="40dp"
+                android:layout_marginLeft="16dp"
+                android:layout_marginRight="16dp"
+                android:background="@drawable/phone_type_icon_background">
+                <ImageView
+                    android:id="@+id/phone_type_icon"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center"/>
+            </FrameLayout>
+            <LinearLayout
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:gravity="center_vertical|start"
+                android:orientation="vertical">
+                <TextView
+                    android:id="@+id/phone_number"
+                    android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    android:autoSizeTextType="uniform"
+                    android:maxLines="1"
+                    android:textStyle="bold"
+                    android:textAppearance="?android:attr/textAppearanceLarge"/>
+                <TextView
+                    android:id="@+id/phone_number_description"
+                    android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    android:autoSizeTextType="uniform"
+                    android:maxLines="1"/>
+            </LinearLayout>
+        </LinearLayout>
+        <ImageView
+            android:id="@+id/microphone_icon"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:layout_gravity="center_vertical|end"
+            android:src="@drawable/fab_ic_call"/>
+    </FrameLayout>
+
+    <!-- "Tap again to call" view -->
+    <FrameLayout
+        android:id="@+id/emergency_call_confirm_view"
+        android:layout_height="match_parent"
+        android:layout_width="match_parent"
+        android:background="@color/emergency_shortcut_confirm_button_background_color"
+        android:focusable="true"
+        android:clickable="true"
+        android:visibility="invisible">
+        <LinearLayout
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:layout_gravity="center_vertical|start"
+            android:gravity="center_vertical"
+            android:orientation="horizontal">
+            <FrameLayout
+                android:layout_height="40dp"
+                android:layout_width="40dp"
+                android:layout_marginLeft="16dp"
+                android:layout_marginRight="16dp"
+                android:background="@drawable/phone_type_icon_background">
+                <ImageView
+                    android:id="@+id/confirmed_phone_type_icon"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center"/>
+            </FrameLayout>
+            <FrameLayout
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:gravity="center_vertical|start"
+                android:orientation="vertical">
+                <TextView
+                    android:id="@+id/phone_call_hint"
+                    android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    android:autoSizeTextType="uniform"
+                    android:maxLines="1"
+                    android:textColor="@android:color/white"
+                    android:textStyle="italic|bold"/>
+            </FrameLayout>
+        </LinearLayout>
+        <ImageView
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:layout_gravity="center_vertical|end"
+            android:src="@drawable/fab_ic_call"/>
+    </FrameLayout>
+</com.android.phone.EmergencyShortcutButton>
\ No newline at end of file
diff --git a/res/layout/emergency_shortcut_buttons_group.xml b/res/layout/emergency_shortcut_buttons_group.xml
new file mode 100644
index 0000000..5ba0533
--- /dev/null
+++ b/res/layout/emergency_shortcut_buttons_group.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/emergency_shortcut_buttons_group"
+    android:layout_height="wrap_content"
+    android:layout_width="match_parent"
+    android:layout_marginTop="58dp"
+    android:orientation="vertical">
+    <FrameLayout
+        android:layout_height="wrap_content"
+        android:layout_width="match_parent"
+        android:paddingBottom="12dp">
+        <TextView
+            android:id="@+id/emergency_number_title"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:layout_gravity="center_vertical|start"
+            android:textStyle="bold"
+            android:maxLines="1"
+            android:text="@string/single_emergency_number_title"/>
+        <LinearLayout
+            android:id="@+id/location_info"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:layout_gravity="center_vertical|end"
+            android:gravity="center_vertical"
+            android:orientation="horizontal">
+            <ImageView
+                android:id="@+id/location_icon"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:src="@drawable/ic_location_on_white_18"/>
+            <TextView
+                android:id="@+id/location_text"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:maxLines="1"
+                android:textStyle="italic"/>
+        </LinearLayout>
+    </FrameLayout>
+    <LinearLayout
+        android:id="@+id/emergency_shortcut_buttons_container"
+        android:layout_height="wrap_content"
+        android:layout_width="match_parent"
+        android:gravity="center"
+        android:orientation="vertical"
+        android:background="@drawable/btn_emergency_shortcuts">
+    </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 870d692..98ffff7 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -54,4 +54,5 @@
 
     <color name="dialer_dialpad_touch_tint">#330288d1</color>
     <color name="floating_action_button_touch_tint">#80ffffff</color>
+    <color name="emergency_shortcut_confirm_button_background_color">#E25142</color>
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 60778c8..2bce34b 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1128,6 +1128,12 @@
     <string name="emergency_enable_radio_dialog_title">Emergency call</string>
     <!-- Title for the emergency dialpad UI -->
     <string name="emergency_dialpad_title">Emergency calls only</string>
+    <!-- Emergency dialer: Title of single emergency shortcut button -->
+    <string name="single_emergency_number_title">Emergency number</string>
+    <!-- Emergency dialer: Title of numerous emergency shortcut buttons -->
+    <string name="numerous_emergency_numbers_title">Emergency numbers</string>
+    <!-- Emergency dialer: Hint of selected emergency shortcut button -->
+    <string name="emergency_call_shortcut_hint">Tap again to call <xliff:g id="emergency_number">%s</xliff:g></string>
     <!-- Status message for the "radio enable" UI for emergency calls -->
     <string name="emergency_enable_radio_dialog_message">Turning on radio\u2026</string>
     <!-- Status message for the "radio enable" UI for emergency calls -->
diff --git a/src/com/android/phone/EmergencyDialer.java b/src/com/android/phone/EmergencyDialer.java
index 70ee5d6..ea9eae1 100644
--- a/src/com/android/phone/EmergencyDialer.java
+++ b/src/com/android/phone/EmergencyDialer.java
@@ -58,7 +58,9 @@
 import android.view.MenuItem;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.WindowManager;
+import android.widget.TextView;
 
 import com.android.internal.colorextraction.ColorExtractor;
 import com.android.internal.colorextraction.ColorExtractor.GradientColors;
@@ -67,6 +69,9 @@
 import com.android.phone.common.util.ViewUtil;
 import com.android.phone.common.widget.ResizingTextEditText;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * EmergencyDialer is a special dialer that is used ONLY for dialing emergency calls.
  *
@@ -85,15 +90,15 @@
  * also?
  *
  * TODO: Implement emergency dialer shortcut.
- *  emergency dialer shortcut offer a local emergency number list. Directly click a number to
- *  make an emergency phone call without entering numbers from dialpad.
+ *  Emergency dialer shortcut offer a local emergency number list. Directly clicking a call button
+ *  to place an emergency phone call without entering numbers from dialpad.
  *  TODO item:
- *     1.implement emergency shortcut list UI.
- *     2.integrate emergency phone number table.
+ *     1.integrate emergency phone number table.
  */
 public class EmergencyDialer extends Activity implements View.OnClickListener,
         View.OnLongClickListener, View.OnKeyListener, TextWatcher,
-        DialpadKeyButton.OnPressedListener, ColorExtractor.OnColorsChangedListener {
+        DialpadKeyButton.OnPressedListener, ColorExtractor.OnColorsChangedListener,
+        EmergencyShortcutButton.OnConfirmClickListener {
     // Keys used with onSaveInstanceState().
     private static final String LAST_NUMBER = "lastNumber";
 
@@ -131,6 +136,8 @@
     private View mEmergencyShortcutView;
     private View mDialpadView;
 
+    private List<EmergencyShortcutButton> mEmergencyShortcutButtonList;
+
     private ToneGenerator mToneGenerator;
     private Object mToneGeneratorLock = new Object();
 
@@ -408,13 +415,28 @@
 
     @Override
     public boolean dispatchTouchEvent(MotionEvent ev) {
-        mEmergencyActionGroup.onPreTouchEvent(ev);
+        onPreTouchEvent(ev);
         boolean handled = super.dispatchTouchEvent(ev);
-        mEmergencyActionGroup.onPostTouchEvent(ev);
+        onPostTouchEvent(ev);
         return handled;
     }
 
     @Override
+    public void onConfirmClick(EmergencyShortcutButton button) {
+        if (button == null) return;
+
+        String phoneNumber = button.getPhoneNumber();
+
+        if (!TextUtils.isEmpty(phoneNumber)) {
+            Log.d(LOG_TAG, "dial emergency number: " + phoneNumber);
+            TelecomManager tm = (TelecomManager) getSystemService(TELECOM_SERVICE);
+            tm.placeCall(Uri.fromParts(PhoneAccount.SCHEME_TEL, phoneNumber, null), null);
+        } else {
+            Log.d(LOG_TAG, "emergency number is empty");
+        }
+    }
+
+    @Override
     public void onClick(View view) {
         switch (view.getId()) {
             case R.id.deleteButton: {
@@ -854,9 +876,82 @@
         final View emergencyDialpadTitle = findViewById(R.id.emergency_dialpad_title_container);
         emergencyDialpadTitle.setVisibility(View.VISIBLE);
 
+        // TODO: Integrating emergency phone number table will get location information.
+        // Using null to present no location status.
+        setLocationInfo(null);
+
+        mEmergencyShortcutButtonList = new ArrayList<>();
+        setupEmergencyCallShortcutButton();
+
         switchView(mEmergencyShortcutView, mDialpadView, false);
     }
 
+    private void setLocationInfo(String country) {
+        final View locationInfo = findViewById(R.id.location_info);
+
+        if (TextUtils.isEmpty(country)) {
+            locationInfo.setVisibility(View.INVISIBLE);
+        } else {
+            final TextView location = (TextView) locationInfo.findViewById(R.id.location_text);
+            location.setText(country);
+            locationInfo.setVisibility(View.VISIBLE);
+        }
+    }
+
+    // TODO: Integrate emergency phone number table.
+    // Using default layout(no location, phone number is 112, description is Emergency,
+    // and icon is cross shape) until integrating emergency phone number table.
+    private void setupEmergencyCallShortcutButton() {
+        final ViewGroup shortcutButtonContainer = findViewById(
+                R.id.emergency_shortcut_buttons_container);
+        shortcutButtonContainer.setClipToOutline(true);
+
+        final EmergencyShortcutButton button =
+                (EmergencyShortcutButton) getLayoutInflater().inflate(
+                        R.layout.emergency_shortcut_button,
+                        shortcutButtonContainer, false);
+
+        button.setPhoneNumber("112");
+        button.setPhoneDescription("Emergency");
+        button.setPhoneTypeIcon(R.drawable.ic_emergency_number_24);
+        button.setOnConfirmClickListener(this);
+
+        shortcutButtonContainer.addView(button);
+        mEmergencyShortcutButtonList.add(button);
+
+        //Set emergency number title for numerous buttons.
+        if (shortcutButtonContainer.getChildCount() > 1) {
+            final TextView emergencyNumberTitle = findViewById(R.id.emergency_number_title);
+            emergencyNumberTitle.setText(getString(R.string.numerous_emergency_numbers_title));
+        }
+    }
+
+    /**
+     * Called by the activity before a touch event is dispatched to the view hierarchy.
+     */
+    private void onPreTouchEvent(MotionEvent event) {
+        mEmergencyActionGroup.onPreTouchEvent(event);
+
+        if (mEmergencyShortcutButtonList != null) {
+            for (EmergencyShortcutButton button : mEmergencyShortcutButtonList) {
+                button.onPreTouchEvent(event);
+            }
+        }
+    }
+
+    /**
+     * Called by the activity after a touch event is dispatched to the view hierarchy.
+     */
+    private void onPostTouchEvent(MotionEvent event) {
+        mEmergencyActionGroup.onPostTouchEvent(event);
+
+        if (mEmergencyShortcutButtonList != null) {
+            for (EmergencyShortcutButton button : mEmergencyShortcutButtonList) {
+                button.onPostTouchEvent(event);
+            }
+        }
+    }
+
     /**
      * Switch two view.
      *
diff --git a/src/com/android/phone/EmergencyShortcutButton.java b/src/com/android/phone/EmergencyShortcutButton.java
new file mode 100644
index 0000000..92877c7
--- /dev/null
+++ b/src/com/android/phone/EmergencyShortcutButton.java
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2018 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;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewAnimationUtils;
+import android.view.accessibility.AccessibilityManager;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+
+/**
+ * Emergency shortcut button displays a local emergency phone number information(including phone
+ * number, and phone type). To decrease false clicking, it need to click twice to confirm to place
+ * an emergency phone call.
+ *
+ * <p> The button need to be set an {@link OnConfirmClickListener} from activity to handle dial
+ * function.
+ *
+ * <p> First clicking on the button, it would change the view of call number information to
+ * the view of confirmation. And then clicking on the view of confirmation, it will place an
+ * emergency call.
+ *
+ * <p> For screen reader, it changed to click twice on the view of call number information to
+ * place an emergency call. The view of confirmation will not display.
+ */
+public class EmergencyShortcutButton extends FrameLayout implements View.OnClickListener {
+    // Time to hide view of confirmation.
+    private static final long HIDE_DELAY = 3000;
+
+    private static final int[] ICON_VIEWS = {R.id.phone_type_icon, R.id.confirmed_phone_type_icon};
+    private View mCallNumberInfoView;
+    private View mConfirmView;
+
+    private TextView mPhoneNumber;
+    private TextView mPhoneTypeDescription;
+    private TextView mPhoneCallHint;
+    private MotionEvent mPendingTouchEvent;
+    private OnConfirmClickListener mOnConfirmClickListener;
+
+    private boolean mConfirmViewHiding;
+
+    public EmergencyShortcutButton(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    /**
+     * Interface definition for a callback to be invoked when the view of confirmation on shortcut
+     * button is clicked.
+     */
+    public interface OnConfirmClickListener {
+        /**
+         * Called when the view of confirmation on shortcut button has been clicked.
+         *
+         * @param button The shortcut button that was clicked.
+         */
+        void onConfirmClick(EmergencyShortcutButton button);
+    }
+
+    /**
+     * Register a callback {@link OnConfirmClickListener} to be invoked when view of confirmation
+     * is clicked.
+     *
+     * @param onConfirmClickListener The callback that will run.
+     */
+    public void setOnConfirmClickListener(OnConfirmClickListener onConfirmClickListener) {
+        mOnConfirmClickListener = onConfirmClickListener;
+    }
+
+    /**
+     * Set icon for different phone number type.
+     *
+     * @param resId The resource identifier of the drawable.
+     */
+    public void setPhoneTypeIcon(int resId) {
+        for (int iconView : ICON_VIEWS) {
+            ImageView phoneTypeIcon = findViewById(iconView);
+            phoneTypeIcon.setImageResource(resId);
+        }
+    }
+
+    /**
+     * Set emergency phone number description.
+     */
+    public void setPhoneDescription(@NonNull String description) {
+        mPhoneTypeDescription.setText(description);
+    }
+
+    /**
+     * Set emergency phone number.
+     */
+    public void setPhoneNumber(@NonNull String number) {
+        mPhoneNumber.setText(number);
+        mPhoneCallHint.setText(
+                getContext().getString(R.string.emergency_call_shortcut_hint, number));
+
+        // Set content description for phone number.
+        if (number.length() > 1) {
+            StringBuilder stringBuilder = new StringBuilder();
+            for (char c : number.toCharArray()) {
+                stringBuilder.append(c).append(" ");
+            }
+            mPhoneNumber.setContentDescription(stringBuilder.toString().trim());
+        }
+    }
+
+    /**
+     * Get emergency phone number.
+     *
+     * @return phone number, or {@code null} if {@code mPhoneNumber} does not be set.
+     */
+    public String getPhoneNumber() {
+        return mPhoneNumber != null ? mPhoneNumber.getText().toString() : null;
+    }
+
+    /**
+     * Called by the activity before a touch event is dispatched to the view hierarchy.
+     */
+    public void onPreTouchEvent(MotionEvent event) {
+        mPendingTouchEvent = event;
+    }
+
+    @Override
+    public boolean dispatchTouchEvent(MotionEvent event) {
+        boolean handled = super.dispatchTouchEvent(event);
+        if (mPendingTouchEvent == event && handled) {
+            mPendingTouchEvent = null;
+        }
+        return handled;
+    }
+
+    /**
+     * Called by the activity after a touch event is dispatched to the view hierarchy.
+     */
+    public void onPostTouchEvent(MotionEvent event) {
+        // Hide the confirmation button if a touch event was delivered to the activity but not to
+        // this view.
+        if (mPendingTouchEvent != null) {
+            hideSelectedButton();
+        }
+        mPendingTouchEvent = null;
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mCallNumberInfoView = findViewById(R.id.emergency_call_number_info_view);
+        mConfirmView = findViewById(R.id.emergency_call_confirm_view);
+
+        mCallNumberInfoView.setOnClickListener(this);
+        mConfirmView.setOnClickListener(this);
+
+        mPhoneNumber = (TextView) mCallNumberInfoView.findViewById(R.id.phone_number);
+        mPhoneTypeDescription = (TextView) mCallNumberInfoView.findViewById(
+                R.id.phone_number_description);
+
+        mPhoneCallHint = (TextView) mConfirmView.findViewById(R.id.phone_call_hint);
+
+        mConfirmViewHiding = true;
+    }
+
+    @Override
+    public void onClick(View view) {
+        switch (view.getId()) {
+            case R.id.emergency_call_number_info_view:
+                if (AccessibilityManager.getInstance(mContext).isTouchExplorationEnabled()) {
+                    if (mOnConfirmClickListener != null) {
+                        mOnConfirmClickListener.onConfirmClick(this);
+                    }
+                } else {
+                    revealSelectedButton();
+                }
+                break;
+            case R.id.emergency_call_confirm_view:
+                if (mOnConfirmClickListener != null) {
+                    mOnConfirmClickListener.onConfirmClick(this);
+                }
+                break;
+        }
+    }
+
+    private void revealSelectedButton() {
+        mConfirmViewHiding = false;
+
+        mConfirmView.setVisibility(View.VISIBLE);
+        int centerX = mCallNumberInfoView.getLeft() + mCallNumberInfoView.getWidth() / 2;
+        int centerY = mCallNumberInfoView.getTop() + mCallNumberInfoView.getHeight() / 2;
+        Animator reveal = ViewAnimationUtils.createCircularReveal(
+                mConfirmView,
+                centerX,
+                centerY,
+                0,
+                Math.max(centerX, mConfirmView.getWidth() - centerX)
+                        + Math.max(centerY, mConfirmView.getHeight() - centerY));
+        reveal.start();
+
+        postDelayed(mCancelSelectedButtonRunnable, HIDE_DELAY);
+        mConfirmView.requestFocus();
+    }
+
+    private void hideSelectedButton() {
+        if (mConfirmViewHiding || mConfirmView.getVisibility() != VISIBLE) {
+            return;
+        }
+
+        mConfirmViewHiding = true;
+
+        removeCallbacks(mCancelSelectedButtonRunnable);
+        int centerX = mConfirmView.getLeft() + mConfirmView.getWidth() / 2;
+        int centerY = mConfirmView.getTop() + mConfirmView.getHeight() / 2;
+        Animator reveal = ViewAnimationUtils.createCircularReveal(
+                mConfirmView,
+                centerX,
+                centerY,
+                Math.max(centerX, mCallNumberInfoView.getWidth() - centerX)
+                        + Math.max(centerY, mCallNumberInfoView.getHeight() - centerY),
+                0);
+        reveal.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mConfirmView.setVisibility(INVISIBLE);
+            }
+        });
+        reveal.start();
+
+        mCallNumberInfoView.requestFocus();
+    }
+
+    private final Runnable mCancelSelectedButtonRunnable = new Runnable() {
+        @Override
+        public void run() {
+            if (!isAttachedToWindow()) return;
+            hideSelectedButton();
+        }
+    };
+}