Faster Emergency Dialer new UI design

- Change the layout parameter to match UI guideline.
- Emergency info button need double tap to launch Emergency information.
- Emergency info button vertical margin will changed when emergency
shortcut button more than 2.

Test: Manually
Bug: 111967652
Change-Id: Ibdd105e6da9f4c9b548b83420ba1b27ef88c82b9
diff --git a/src/com/android/phone/EccShortcutAdapter.java b/src/com/android/phone/EccShortcutAdapter.java
index deeb82f..e14b90a 100644
--- a/src/com/android/phone/EccShortcutAdapter.java
+++ b/src/com/android/phone/EccShortcutAdapter.java
@@ -186,15 +186,15 @@
             switch (type) {
                 case POLICE:
                     description = mPoliceDescription;
-                    material.iconRes = R.drawable.ic_shield_white_24;
+                    material.iconRes = R.drawable.ic_local_police_gm2_24px;
                     break;
                 case AMBULANCE:
                     description = mAmbulanceDescription;
-                    material.iconRes = R.drawable.ic_emergency_number_24;
+                    material.iconRes = R.drawable.ic_local_hospital_gm2_24px;
                     break;
                 case FIRE:
                     description = mFireDescription;
-                    material.iconRes = R.drawable.ic_fire_white_24;
+                    material.iconRes = R.drawable.ic_local_fire_department_gm2_24px;
                     break;
                 default:
                     // ignore unknown types
@@ -204,7 +204,7 @@
                 material.description = description;
             } else {
                 // concatenate multiple types
-                material.iconRes = R.drawable.ic_emergency_number_24;
+                material.iconRes = R.drawable.ic_local_hospital_gm2_24px;
                 material.description = context.getString(R.string.description_concat_format,
                         material.description, description);
             }
diff --git a/src/com/android/phone/EmergencyDialer.java b/src/com/android/phone/EmergencyDialer.java
index 66701d5..1fbbd33 100644
--- a/src/com/android/phone/EmergencyDialer.java
+++ b/src/com/android/phone/EmergencyDialer.java
@@ -108,17 +108,12 @@
  * moved into a shared base class that would live in the framework?
  * Or could we figure out some way to move *this* class into apps/Contacts
  * also?
- *
- * TODO: Implement emergency dialer shortcut.
- *  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.integrate emergency phone number table.
  */
 public class EmergencyDialer extends Activity implements View.OnClickListener,
         View.OnLongClickListener, View.OnKeyListener, TextWatcher,
         DialpadKeyButton.OnPressedListener, ColorExtractor.OnColorsChangedListener,
-        EmergencyShortcutButton.OnConfirmClickListener, SensorEventListener {
+        EmergencyShortcutButton.OnConfirmClickListener, SensorEventListener,
+        EmergencyInfoGroup.OnConfirmClickListener {
 
     private class MetricsWriter {
         // Metrics constants indicating the entry type that user opened emergency dialer.
@@ -244,6 +239,8 @@
 
     private EmergencyActionGroup mEmergencyActionGroup;
 
+    private EmergencyInfoGroup mEmergencyInfoGroup;
+
     // close activity when screen turns off
     private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
@@ -451,6 +448,8 @@
 
         mEmergencyActionGroup = (EmergencyActionGroup) findViewById(R.id.emergency_action_group);
 
+        mEmergencyInfoGroup = (EmergencyInfoGroup) findViewById(R.id.emergency_info_button);
+
         if (mAreEmergencyDialerShortcutsEnabled) {
             mEccInfoHelper = new EccInfoHelper(new IsoToEccProtobufRepository());
             setupEmergencyShortcutsView();
@@ -606,6 +605,17 @@
     }
 
     @Override
+    public void onConfirmClick(EmergencyInfoGroup button) {
+        if (button == null) return;
+
+        mUserActions |= MetricsWriter.USER_ACTION_OPEN_EMERGENCY_INFO;
+        Intent intent = (Intent) button.getTag(R.id.tag_intent);
+        if (intent != null) {
+            startActivity(intent);
+        }
+    }
+
+    @Override
     public void onClick(View view) {
         switch (view.getId()) {
             case R.id.deleteButton: {
@@ -629,14 +639,6 @@
                 switchView(mDialpadView, mEmergencyShortcutView, true);
                 return;
             }
-            case R.id.emergency_info_button: {
-                mUserActions |= MetricsWriter.USER_ACTION_OPEN_EMERGENCY_INFO;
-                Intent intent = (Intent) view.getTag(R.id.tag_intent);
-                if (intent != null) {
-                    startActivity(intent);
-                }
-                return;
-            }
         }
     }
 
@@ -1099,8 +1101,7 @@
         final View dialpadButton = findViewById(R.id.floating_action_button_dialpad);
         dialpadButton.setOnClickListener(this);
 
-        final View emergencyInfoButton = findViewById(R.id.emergency_info_button);
-        emergencyInfoButton.setOnClickListener(this);
+        mEmergencyInfoGroup.setOnConfirmClickListener(this);
 
         // EmergencyActionGroup is replaced by EmergencyInfoGroup.
         mEmergencyActionGroup.setVisibility(View.GONE);
@@ -1179,10 +1180,15 @@
                     shortcutButtonContainer.addView(button);
                 }
 
-                // update emergency numbers title for numerous buttons.
+                // Update emergency numbers title for numerous buttons.
                 if (mEmergencyShortcutButtonList.size() > 1) {
                     emergencyNumberTitle.setText(getString(
                             R.string.numerous_emergency_numbers_title));
+                    // Update mEmergencyInfoGroup margin to avoid UI overlay when
+                    // emergency shortcut button more than 2.
+                    if (mEmergencyShortcutButtonList.size() > 2) {
+                        mEmergencyInfoGroup.updateLayoutMargin();
+                    }
                 } else {
                     emergencyNumberTitle.setText(getText(R.string.single_emergency_number_title));
                 }
@@ -1205,6 +1211,7 @@
      */
     private void onPreTouchEvent(MotionEvent event) {
         mEmergencyActionGroup.onPreTouchEvent(event);
+        mEmergencyInfoGroup.onPreTouchEvent(event);
 
         if (mEmergencyShortcutButtonList != null) {
             for (EmergencyShortcutButton button : mEmergencyShortcutButtonList) {
@@ -1218,6 +1225,7 @@
      */
     private void onPostTouchEvent(MotionEvent event) {
         mEmergencyActionGroup.onPostTouchEvent(event);
+        mEmergencyInfoGroup.onPostTouchEvent(event);
 
         if (mEmergencyShortcutButtonList != null) {
             for (EmergencyShortcutButton button : mEmergencyShortcutButtonList) {
diff --git a/src/com/android/phone/EmergencyInfoGroup.java b/src/com/android/phone/EmergencyInfoGroup.java
index d0dc322..5c01834 100644
--- a/src/com/android/phone/EmergencyInfoGroup.java
+++ b/src/com/android/phone/EmergencyInfoGroup.java
@@ -16,6 +16,8 @@
 
 package com.android.phone;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.Intent;
@@ -27,7 +29,10 @@
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 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.LinearLayout;
@@ -44,23 +49,60 @@
  * EmergencyInfoGroup display user icon and user name. And it is an entry point to
  * Emergency Information.
  */
-public class EmergencyInfoGroup extends FrameLayout {
-    private ImageView mEmergencyInfoImage;
+public class EmergencyInfoGroup extends FrameLayout implements View.OnClickListener {
+    // Time to hide view of confirmation.
+    private static final long HIDE_DELAY_MS = 3000;
+    private static final int[] ICON_VIEWS =
+            {R.id.emergency_info_image, R.id.confirmed_emergency_info_image};
+
     private TextView mEmergencyInfoName;
-    private TextView mEmergencyInfoHint;
     private View mEmergencyInfoButton;
+    private View mEmergencyInfoConfirmButton;
+
+    private MotionEvent mPendingTouchEvent;
+    private OnConfirmClickListener mOnConfirmClickListener;
+
+    private boolean mConfirmViewHiding;
 
     public EmergencyInfoGroup(Context context, @Nullable AttributeSet attrs) {
         super(context, attrs);
     }
 
+    /**
+     * Interface definition for a callback to be invoked when the view of confirmation on emergency
+     * info button is clicked.
+     */
+    public interface OnConfirmClickListener {
+        /**
+         * Called when the view of confirmation on emergency info button has been clicked.
+         *
+         * @param button The shortcut button that was clicked.
+         */
+        void onConfirmClick(EmergencyInfoGroup 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;
+    }
+
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        mEmergencyInfoButton = findViewById(R.id.emergency_info_button);
-        mEmergencyInfoImage = (ImageView) findViewById(R.id.emergency_info_image);
+        mEmergencyInfoButton = findViewById(R.id.emergency_info_view);
         mEmergencyInfoName = (TextView) findViewById(R.id.emergency_info_name);
-        mEmergencyInfoHint = (TextView) findViewById(R.id.emergency_info_hint);
+
+        mEmergencyInfoConfirmButton = findViewById(R.id.emergency_info_confirm_view);
+
+        mEmergencyInfoButton.setOnClickListener(this);
+        mEmergencyInfoConfirmButton.setOnClickListener(this);
+
+        mConfirmViewHiding = true;
     }
 
     @Override
@@ -71,12 +113,6 @@
         }
     }
 
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        super.onLayout(changed, left, top, right, bottom);
-        updateLayoutHeight();
-    }
-
     private void setupButtonInfo() {
         List<ResolveInfo> infos;
 
@@ -92,8 +128,8 @@
             final String packageName = infos.get(0).activityInfo.packageName;
             final Intent intent = new Intent(TelephonyManager.ACTION_EMERGENCY_ASSISTANCE)
                     .setPackage(packageName);
-            mEmergencyInfoButton.setTag(R.id.tag_intent, intent);
-            mEmergencyInfoImage.setImageDrawable(getCircularUserIcon());
+            setTag(R.id.tag_intent, intent);
+            setUserIcon();
 
             visible = true;
         }
@@ -102,6 +138,13 @@
         setVisibility(visible ? View.VISIBLE : View.GONE);
     }
 
+    private void setUserIcon() {
+        for (int iconView : ICON_VIEWS) {
+            ImageView userIcon = findViewById(iconView);
+            userIcon.setImageDrawable(getCircularUserIcon());
+        }
+    }
+
     /**
      * Get user icon.
      *
@@ -134,15 +177,124 @@
                 R.string.emergency_information_owner_hint) : userName;
     }
 
-    private void updateLayoutHeight() {
+    /**
+     * Called by the activity before a touch event is dispatched to the view hierarchy.
+     */
+    public void onPreTouchEvent(MotionEvent event) {
+        mPendingTouchEvent = event;
+    }
+
+    /**
+     * 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
+    public boolean dispatchTouchEvent(MotionEvent event) {
+        boolean handled = super.dispatchTouchEvent(event);
+        if (mPendingTouchEvent == event && handled) {
+            mPendingTouchEvent = null;
+        }
+        return handled;
+    }
+
+    @Override
+    public void onClick(View view) {
+        switch (view.getId()) {
+            case R.id.emergency_info_view:
+                if (AccessibilityManager.getInstance(mContext).isTouchExplorationEnabled()) {
+                    if (mOnConfirmClickListener != null) {
+                        mOnConfirmClickListener.onConfirmClick(this);
+                    }
+                } else {
+                    revealSelectedButton();
+                }
+                break;
+            case R.id.emergency_info_confirm_view:
+                if (mOnConfirmClickListener != null) {
+                    mOnConfirmClickListener.onConfirmClick(this);
+                }
+                break;
+            default:
+                break;
+        }
+    }
+
+    private void revealSelectedButton() {
+        mConfirmViewHiding = false;
+
+        mEmergencyInfoConfirmButton.setVisibility(View.VISIBLE);
+        int centerX = mEmergencyInfoButton.getLeft() + mEmergencyInfoButton.getWidth() / 2;
+        int centerY = mEmergencyInfoButton.getTop() + mEmergencyInfoButton.getHeight() / 2;
+        Animator reveal = ViewAnimationUtils.createCircularReveal(
+                mEmergencyInfoConfirmButton,
+                centerX,
+                centerY,
+                0,
+                Math.max(centerX, mEmergencyInfoConfirmButton.getWidth() - centerX)
+                        + Math.max(centerY, mEmergencyInfoConfirmButton.getHeight() - centerY));
+        reveal.start();
+
+        postDelayed(mCancelSelectedButtonRunnable, HIDE_DELAY_MS);
+        mEmergencyInfoConfirmButton.requestFocus();
+    }
+
+    private void hideSelectedButton() {
+        if (mConfirmViewHiding || mEmergencyInfoConfirmButton.getVisibility() != VISIBLE) {
+            return;
+        }
+
+        mConfirmViewHiding = true;
+
+        removeCallbacks(mCancelSelectedButtonRunnable);
+        int centerX =
+                mEmergencyInfoConfirmButton.getLeft() + mEmergencyInfoConfirmButton.getWidth() / 2;
+        int centerY =
+                mEmergencyInfoConfirmButton.getTop() + mEmergencyInfoConfirmButton.getHeight() / 2;
+        Animator reveal = ViewAnimationUtils.createCircularReveal(
+                mEmergencyInfoConfirmButton,
+                centerX,
+                centerY,
+                Math.max(centerX, mEmergencyInfoButton.getWidth() - centerX)
+                        + Math.max(centerY, mEmergencyInfoButton.getHeight() - centerY),
+                0);
+        reveal.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mEmergencyInfoConfirmButton.setVisibility(INVISIBLE);
+            }
+        });
+        reveal.start();
+
+        mEmergencyInfoButton.requestFocus();
+    }
+
+    private final Runnable mCancelSelectedButtonRunnable = new Runnable() {
+        @Override
+        public void run() {
+            if (!isAttachedToWindow()) return;
+            hideSelectedButton();
+        }
+    };
+
+    /**
+     * Update layout margin when emergency shortcut button more than 2.
+     */
+    public void updateLayoutMargin() {
         LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) getLayoutParams();
-        // Update height if mEmergencyInfoHint text line more than 1.
-        // EmergencyInfoGroup max line is 2, eclipse type "end" will be adopt if string too long.
-        params.height =
-                mEmergencyInfoHint.getLineCount() > 1 ? getResources().getDimensionPixelSize(
-                        R.dimen.emergency_info_button_multiline_height)
-                        : getResources().getDimensionPixelSize(
-                                R.dimen.emergency_info_button_singleline_height);
+
+        params.topMargin = getResources().getDimensionPixelSize(
+                R.dimen.emergency_info_button_fix_margin_vertical);
+        params.bottomMargin = getResources().getDimensionPixelSize(
+                R.dimen.emergency_info_button_fix_margin_vertical);
+
         setLayoutParams(params);
     }
 }
\ No newline at end of file