Merge "Import translations. DO NOT MERGE" into lmp-dev
diff --git a/InCallUI/res/drawable-hdpi/business_unknown.png b/InCallUI/res/drawable-hdpi/business_unknown.png
deleted file mode 100644
index b369939..0000000
--- a/InCallUI/res/drawable-hdpi/business_unknown.png
+++ /dev/null
Binary files differ
diff --git a/InCallUI/res/drawable-hdpi/ic_call_white_24dp.png b/InCallUI/res/drawable-hdpi/ic_call_white_24dp.png
new file mode 100644
index 0000000..1902e72
--- /dev/null
+++ b/InCallUI/res/drawable-hdpi/ic_call_white_24dp.png
Binary files differ
diff --git a/InCallUI/res/drawable-hdpi/img_business.png b/InCallUI/res/drawable-hdpi/img_business.png
new file mode 100644
index 0000000..f706342
--- /dev/null
+++ b/InCallUI/res/drawable-hdpi/img_business.png
Binary files differ
diff --git a/InCallUI/res/drawable-hdpi/img_emergency.png b/InCallUI/res/drawable-hdpi/img_emergency.png
new file mode 100644
index 0000000..7e5eff4
--- /dev/null
+++ b/InCallUI/res/drawable-hdpi/img_emergency.png
Binary files differ
diff --git a/InCallUI/res/drawable-hdpi/picture_emergency.png b/InCallUI/res/drawable-hdpi/picture_emergency.png
deleted file mode 100644
index 0e13a43..0000000
--- a/InCallUI/res/drawable-hdpi/picture_emergency.png
+++ /dev/null
Binary files differ
diff --git a/InCallUI/res/drawable-mdpi/business_unknown.png b/InCallUI/res/drawable-mdpi/business_unknown.png
deleted file mode 100644
index eac97a9..0000000
--- a/InCallUI/res/drawable-mdpi/business_unknown.png
+++ /dev/null
Binary files differ
diff --git a/InCallUI/res/drawable-mdpi/ic_call_white_24dp.png b/InCallUI/res/drawable-mdpi/ic_call_white_24dp.png
new file mode 100644
index 0000000..d4e5f5d
--- /dev/null
+++ b/InCallUI/res/drawable-mdpi/ic_call_white_24dp.png
Binary files differ
diff --git a/InCallUI/res/drawable-mdpi/img_business.png b/InCallUI/res/drawable-mdpi/img_business.png
new file mode 100644
index 0000000..90738a7
--- /dev/null
+++ b/InCallUI/res/drawable-mdpi/img_business.png
Binary files differ
diff --git a/InCallUI/res/drawable-mdpi/img_emergency.png b/InCallUI/res/drawable-mdpi/img_emergency.png
new file mode 100644
index 0000000..0209eb9
--- /dev/null
+++ b/InCallUI/res/drawable-mdpi/img_emergency.png
Binary files differ
diff --git a/InCallUI/res/drawable-mdpi/picture_emergency.png b/InCallUI/res/drawable-mdpi/picture_emergency.png
deleted file mode 100644
index a224b80..0000000
--- a/InCallUI/res/drawable-mdpi/picture_emergency.png
+++ /dev/null
Binary files differ
diff --git a/InCallUI/res/drawable-xhdpi/business_unknown.png b/InCallUI/res/drawable-xhdpi/business_unknown.png
deleted file mode 100644
index aa84456..0000000
--- a/InCallUI/res/drawable-xhdpi/business_unknown.png
+++ /dev/null
Binary files differ
diff --git a/InCallUI/res/drawable-xhdpi/ic_call_white_24dp.png b/InCallUI/res/drawable-xhdpi/ic_call_white_24dp.png
new file mode 100644
index 0000000..cde9cea
--- /dev/null
+++ b/InCallUI/res/drawable-xhdpi/ic_call_white_24dp.png
Binary files differ
diff --git a/InCallUI/res/drawable-xhdpi/img_business.png b/InCallUI/res/drawable-xhdpi/img_business.png
new file mode 100644
index 0000000..7b04d95
--- /dev/null
+++ b/InCallUI/res/drawable-xhdpi/img_business.png
Binary files differ
diff --git a/InCallUI/res/drawable-xhdpi/img_emergency.png b/InCallUI/res/drawable-xhdpi/img_emergency.png
new file mode 100644
index 0000000..5c00d9d
--- /dev/null
+++ b/InCallUI/res/drawable-xhdpi/img_emergency.png
Binary files differ
diff --git a/InCallUI/res/drawable-xhdpi/picture_emergency.png b/InCallUI/res/drawable-xhdpi/picture_emergency.png
deleted file mode 100644
index 08b421e..0000000
--- a/InCallUI/res/drawable-xhdpi/picture_emergency.png
+++ /dev/null
Binary files differ
diff --git a/InCallUI/res/drawable-xxhdpi/business_unknown.png b/InCallUI/res/drawable-xxhdpi/business_unknown.png
deleted file mode 100644
index 6273bb3..0000000
--- a/InCallUI/res/drawable-xxhdpi/business_unknown.png
+++ /dev/null
Binary files differ
diff --git a/InCallUI/res/drawable-xxhdpi/ic_call_white_24dp.png b/InCallUI/res/drawable-xxhdpi/ic_call_white_24dp.png
new file mode 100644
index 0000000..b761bc4
--- /dev/null
+++ b/InCallUI/res/drawable-xxhdpi/ic_call_white_24dp.png
Binary files differ
diff --git a/InCallUI/res/drawable-xxhdpi/img_business.png b/InCallUI/res/drawable-xxhdpi/img_business.png
new file mode 100644
index 0000000..c17e4c9
--- /dev/null
+++ b/InCallUI/res/drawable-xxhdpi/img_business.png
Binary files differ
diff --git a/InCallUI/res/drawable-xxhdpi/img_emergency.png b/InCallUI/res/drawable-xxhdpi/img_emergency.png
new file mode 100644
index 0000000..4eaaba5
--- /dev/null
+++ b/InCallUI/res/drawable-xxhdpi/img_emergency.png
Binary files differ
diff --git a/InCallUI/res/drawable/end_call_background.xml b/InCallUI/res/drawable/end_call_background.xml
index b3d877b..8f3926f 100644
--- a/InCallUI/res/drawable/end_call_background.xml
+++ b/InCallUI/res/drawable/end_call_background.xml
@@ -16,6 +16,4 @@
 
 <!-- Background drawable used to render the "end call" button. -->
 <ripple xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="@color/end_call_touch_feedback_tint">
-    <item android:drawable="@drawable/fab_red" />
-</ripple>
+    android:color="@color/end_call_touch_feedback_tint" />
diff --git a/InCallUI/res/layout-land/call_card_content.xml b/InCallUI/res/layout-land/call_card_content.xml
index 7d1db8e..b1b5275 100644
--- a/InCallUI/res/layout-land/call_card_content.xml
+++ b/InCallUI/res/layout-land/call_card_content.xml
@@ -110,17 +110,21 @@
 
     <FrameLayout
         android:id="@+id/floating_end_call_action_button_container"
-        android:layout_width="@dimen/floating_action_button_width"
-        android:layout_height="@dimen/floating_action_button_height"
+        android:layout_width="@dimen/end_call_floating_action_button_diameter"
+        android:layout_height="@dimen/end_call_floating_action_button_diameter"
+        android:background="@drawable/fab_red"
+        android:layout_centerHorizontal="true"
         android:layout_marginBottom="@dimen/end_call_button_margin_bottom"
-        android:layout_alignParentBottom="true"
-        android:layout_centerHorizontal="true" >
+        android:layout_alignParentBottom="true" >
 
         <ImageButton android:id="@+id/floating_end_call_action_button"
-                     android:layout_width="match_parent"
-                     android:layout_height="match_parent"
-                     android:background="@drawable/end_call_background"
-                     android:src="@drawable/fab_ic_end_call"
-                     android:contentDescription="@string/onscreenEndCallText" />
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:background="@drawable/end_call_background"
+            android:src="@drawable/fab_ic_end_call"
+            android:scaleType="center"
+            android:contentDescription="@string/onscreenEndCallText" />
+
     </FrameLayout>
+
 </RelativeLayout>
diff --git a/InCallUI/res/layout/call_card_content.xml b/InCallUI/res/layout/call_card_content.xml
index ec32d98..605d630 100644
--- a/InCallUI/res/layout/call_card_content.xml
+++ b/InCallUI/res/layout/call_card_content.xml
@@ -18,7 +18,7 @@
 
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="match_parent" >
+    android:layout_height="match_parent">
 
     <!-- The main content of the CallCard is either one or two "call info"
          blocks, depending on whether one or two lines are in use.
@@ -39,7 +39,7 @@
         android:background="@color/incall_call_banner_background_color"
         android:paddingTop="@dimen/call_banner_primary_call_container_top_padding"
         android:clipChildren="false"
-        android:clipToPadding="false" >
+        android:clipToPadding="false">
 
         <include layout="@layout/primary_call_info" />
 
@@ -84,7 +84,7 @@
         android:layout_height="fill_parent"
         android:layout_centerHorizontal="true"
         android:layout_centerVertical="true"
-        android:visibility="gone" >
+        android:visibility="gone">
 
         <ProgressBar
             android:id="@+id/progress_bar"
@@ -97,9 +97,9 @@
 
     <!-- Secondary "Call info" block, for the background ("on hold") call. -->
     <include layout="@layout/secondary_call_info"
-         android:layout_below="@id/primary_call_info_container"
-         android:layout_width="match_parent"
-         android:layout_height="wrap_content" />
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true"/>
 
     <!-- Placeholder for the dialpad which is replaced with the dialpad fragment when shown. -->
     <FrameLayout
@@ -121,17 +121,21 @@
 
     <FrameLayout
         android:id="@+id/floating_end_call_action_button_container"
-        android:layout_width="@dimen/floating_action_button_width"
-        android:layout_height="@dimen/floating_action_button_height"
+        android:layout_width="@dimen/end_call_floating_action_button_diameter"
+        android:layout_height="@dimen/end_call_floating_action_button_diameter"
+        android:background="@drawable/fab_red"
+        android:layout_centerHorizontal="true"
         android:layout_marginBottom="@dimen/end_call_button_margin_bottom"
-        android:layout_alignParentBottom="true"
-        android:layout_centerHorizontal="true" >
+        android:layout_alignParentBottom="true" >
 
         <ImageButton android:id="@+id/floating_end_call_action_button"
-                     android:layout_width="match_parent"
-                     android:layout_height="match_parent"
-                     android:background="@drawable/end_call_background"
-                     android:src="@drawable/fab_ic_end_call"
-                     android:contentDescription="@string/onscreenEndCallText" />
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:background="@drawable/end_call_background"
+            android:src="@drawable/fab_ic_end_call"
+            android:scaleType="center"
+            android:contentDescription="@string/onscreenEndCallText" />
+
     </FrameLayout>
+
 </RelativeLayout>
diff --git a/InCallUI/res/layout/dtmf_twelve_key_dialer_view.xml b/InCallUI/res/layout/dtmf_twelve_key_dialer_view.xml
index cd9977e..efd6982 100644
--- a/InCallUI/res/layout/dtmf_twelve_key_dialer_view.xml
+++ b/InCallUI/res/layout/dtmf_twelve_key_dialer_view.xml
@@ -19,8 +19,7 @@
     android:id="@+id/dtmf_twelve_key_dialer_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:orientation="vertical"
-    android:layout_marginTop="1dip" >
+    android:orientation="vertical">
 
     <view class="com.android.incallui.DialpadFragment$HoverIgnoringLinearLayout"
         android:orientation="vertical"
diff --git a/InCallUI/res/layout/primary_call_info.xml b/InCallUI/res/layout/primary_call_info.xml
index 4231922..1f3b954 100644
--- a/InCallUI/res/layout/primary_call_info.xml
+++ b/InCallUI/res/layout/primary_call_info.xml
@@ -47,7 +47,7 @@
             android:layout_marginEnd="4dp"
             android:baselineAlignBottom="true"
             android:tint="@color/incall_accent_color"
-            android:alpha="0.7"
+            android:alpha="0.0"
             android:scaleType="centerInside"
             android:visibility="gone" />
 
diff --git a/InCallUI/res/layout/secondary_call_info.xml b/InCallUI/res/layout/secondary_call_info.xml
index c562ae2..cbe1fa2 100644
--- a/InCallUI/res/layout/secondary_call_info.xml
+++ b/InCallUI/res/layout/secondary_call_info.xml
@@ -20,6 +20,7 @@
     android:id="@+id/secondary_call_info"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
+    android:layout_alignParentBottom="true"
     android:orientation="horizontal"
     android:paddingStart="@dimen/call_banner_side_padding"
     android:paddingEnd="@dimen/secondary_call_banner_right_padding"
diff --git a/InCallUI/res/layout/select_account_list_item.xml b/InCallUI/res/layout/select_account_list_item.xml
index 0b24c9b..1999fce 100644
--- a/InCallUI/res/layout/select_account_list_item.xml
+++ b/InCallUI/res/layout/select_account_list_item.xml
@@ -15,7 +15,8 @@
 -->
 
 <!-- Layout of a single item in the InCallUI Account Chooser Dialog. -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<view class="com.android.contacts.common.widget.ActivityTouchLinearLayout"
+    xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="horizontal"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
@@ -24,6 +25,7 @@
     <ImageView android:id="@+id/icon"
                android:layout_width="48dp"
                android:layout_height="48dp"
+               android:tint="@color/dialtacts_secondary_text_color"
                android:scaleType="center" />
 
     <TextView android:id="@+id/text"
@@ -33,4 +35,4 @@
               android:layout_width="0dp"
               android:layout_weight="1"
               android:layout_height="match_parent" />
-</LinearLayout>
+</view>
diff --git a/InCallUI/res/values/colors.xml b/InCallUI/res/values/colors.xml
index faf27e6..bd2642d 100644
--- a/InCallUI/res/values/colors.xml
+++ b/InCallUI/res/values/colors.xml
@@ -67,6 +67,6 @@
     <color name="glowpad_incoming_widget_tint">#a3a3a3</color>
     <color name="glowpad_incoming_widget_background_tint">#ffffff</color>
 
-    <!-- 30% opacity, accent color. -->
-    <color name="incall_dialpad_touch_tint">#66eeff41</color>
+    <!-- 20% opacity, theme color. -->
+    <color name="incall_dialpad_touch_tint">#330288d1</color>
 </resources>
diff --git a/InCallUI/res/values/dimens.xml b/InCallUI/res/values/dimens.xml
index f35a3f3..6bf80f3 100644
--- a/InCallUI/res/values/dimens.xml
+++ b/InCallUI/res/values/dimens.xml
@@ -59,6 +59,7 @@
     <dimen name="primary_call_elevation">4dp</dimen>
     <dimen name="secondary_call_elevation">4dp</dimen>
 
+    <dimen name="floating_action_bar_vertical_offset">-24dp</dimen>
 
     <!-- Padding at the left and right edges of the incall_touch_ui button
          cluster.  This padding is necessary because we can't allow the
@@ -102,7 +103,6 @@
     <dimen name="translucent_shadow_height">2dp</dimen>
 
     <dimen name="end_call_button_margin_bottom">8dp</dimen>
-    <dimen name="end_call_button_hide_offset">70dp</dimen>
 
     <dimen name="call_card_anim_translate_y_offset">50dp</dimen>
 
@@ -111,4 +111,8 @@
     <dimen name="video_preview_small_dimension">90dp</dimen>
 
     <dimen name="video_preview_margin">20dp</dimen>
+
+    <dimen name="end_call_floating_action_button_diameter">72dp</dimen>
+    <dimen name="end_call_floating_action_button_small_diameter">56dp</dimen>
+
 </resources>
diff --git a/InCallUI/res/values/strings.xml b/InCallUI/res/values/strings.xml
index 964286a..fc2ee20 100644
--- a/InCallUI/res/values/strings.xml
+++ b/InCallUI/res/values/strings.xml
@@ -486,12 +486,30 @@
     -->
     <string name="description_delete_button">backspace</string>
 
-    <!-- Content description of the speakerphone enabled notification icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_speakerphone_enabled">Speakerphone enabled.</string>
+    <!-- String used by AccessibilityService to announce that the speakerphone has been selected for audio output [CHAR LIMIT=NONE]-->
+    <string name="accessibility_speakerphone_selected">Speakerphone selected</string>
 
-    <!-- Content description of the call muted notification icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <!-- String used by AccessibilityService to announce that the phone's earpiece has been selected for audio output [CHAR LIMIT=NONE]-->
+    <string name="accessibility_earpiece_selected">Earpiece selected</string>
+
+    <!-- String used by AccessibilityService to announce that the wired headset has been selected for audio output [CHAR LIMIT=NONE]-->
+    <string name="accessibility_wired_headset_selected">Wired headset selected</string>
+
+    <!-- String used by AccessibilityService to announce that the bluetooth headset has been selected for audio output [CHAR LIMIT=NONE]-->
+    <string name="accessibility_bluetooth_headset_selected">Bluetooth headset selected</string>
+
+    <!-- String used by AccessibilityService to announce that the call has been muted [CHAR LIMIT=NONE]-->
     <string name="accessibility_call_muted">Call muted.</string>
 
+    <!-- String used by AccessibilityService to announce that the call has been unmuted [CHAR LIMIT=NONE]-->
+    <string name="accessibility_call_unmuted">Call unmuted.</string>
+
+    <!-- String used by AccessibilityService to announce that the call has been put on hold [CHAR LIMIT=NONE]-->
+    <string name="accessibility_call_put_on_hold">Call put on hold.</string>
+
+    <!-- String used by AccessibilityService to announce that the call has been removed from hold [CHAR LIMIT=NONE]-->
+    <string name="accessibility_call_removed_from_hold">Call removed from hold.</string>
+
     <!-- Description of the answer target in the Slide unlock screen of Phone. [CHAR LIMIT=NONE] -->
     <string name="description_target_answer">Answer</string>
     <!-- Description of the send_sms target in the Slide unlock screen of Phone. [CHAR LIMIT=NONE] -->
diff --git a/InCallUI/src/com/android/incallui/Call.java b/InCallUI/src/com/android/incallui/Call.java
index 01f2e8b..6bd3d0b 100644
--- a/InCallUI/src/com/android/incallui/Call.java
+++ b/InCallUI/src/com/android/incallui/Call.java
@@ -169,7 +169,6 @@
     private final String mId;
     private int mState = State.INVALID;
     private int mDisconnectCause;
-    private String mParentCallId;
     private int mSessionModificationState;
     private final List<String> mChildCallIds = new ArrayList<>();
 
@@ -202,14 +201,10 @@
     }
 
     private void updateFromTelecommCall() {
+        Log.d(this, "updateFromTelecommCall: " + mTelecommCall);
         setState(translateState(mTelecommCall.getState()));
         setDisconnectCause(mTelecommCall.getDetails().getDisconnectCauseCode());
 
-        if (mTelecommCall.getParent() != null) {
-            mParentCallId = CallList.getInstance().getCallByTelecommCall(
-                    mTelecommCall.getParent()).getId();
-        }
-
         if (mTelecommCall.getVideoCall() != null) {
             if (mVideoCallListener == null) {
                 mVideoCallListener = new InCallVideoCallListener(this);
@@ -264,7 +259,7 @@
     }
 
     public int getState() {
-        if (mParentCallId != null) {
+        if (mTelecommCall.getParent() != null) {
             return State.CONFERENCED;
         } else {
             return mState;
@@ -343,7 +338,11 @@
     }
 
     public String getParentId() {
-        return mParentCallId;
+        android.telecomm.Call parentCall = mTelecommCall.getParent();
+        if (parentCall != null) {
+            return CallList.getInstance().getCallByTelecommCall(parentCall).getId();
+        }
+        return null;
     }
 
     public int getVideoState() {
@@ -382,10 +381,10 @@
     public String toString() {
         return String.format(Locale.US, "[%s, %s, %s, children:%s, parent:%s, videoState:%d]",
                 mId,
-                State.toString(mState),
+                State.toString(getState()),
                 PhoneCapabilities.toString(mTelecommCall.getDetails().getCallCapabilities()),
                 mChildCallIds,
-                mParentCallId,
+                getParentId(),
                 mTelecommCall.getDetails().getVideoState());
     }
 }
diff --git a/InCallUI/src/com/android/incallui/CallButtonFragment.java b/InCallUI/src/com/android/incallui/CallButtonFragment.java
index 9b141da..09a3bc2 100644
--- a/InCallUI/src/com/android/incallui/CallButtonFragment.java
+++ b/InCallUI/src/com/android/incallui/CallButtonFragment.java
@@ -16,9 +16,9 @@
 
 package com.android.incallui;
 
+import android.content.Context;
 import android.graphics.drawable.LayerDrawable;
 import android.os.Bundle;
-
 import android.telecomm.AudioState;
 import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
@@ -26,6 +26,8 @@
 import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
 import android.widget.CompoundButton;
 import android.widget.ImageButton;
 import android.widget.PopupMenu;
@@ -60,6 +62,8 @@
     private View mManageConferenceButton;
     private View mGenericMergeButton;
 
+    private int mPrevAudioMode = 0;
+
     // Constants for Drawable.setAlpha()
     private static final int HIDDEN = 0;
     private static final int VISIBLE = 255;
@@ -224,7 +228,11 @@
 
     @Override
     public void setMute(boolean value) {
-        mMuteButton.setSelected(value);
+        if (mMuteButton.isSelected() != value) {
+            mMuteButton.setSelected(value);
+            maybeSendAccessibilityEvent(mMuteButton, value ? R.string.accessibility_call_muted
+                    : R.string.accessibility_call_unmuted);
+        }
     }
 
     @Override
@@ -249,7 +257,12 @@
 
     @Override
     public void setHold(boolean value) {
-        mHoldButton.setSelected(value);
+        if (mHoldButton.isSelected() != value) {
+            mHoldButton.setSelected(value);
+            maybeSendAccessibilityEvent(mHoldButton,
+                    value ? R.string.accessibility_call_put_on_hold :
+                            R.string.accessibility_call_removed_from_hold);
+        }
     }
 
     @Override
@@ -372,6 +385,30 @@
     public void setAudio(int mode) {
         updateAudioButtons(getPresenter().getSupportedAudio());
         refreshAudioModePopup();
+
+        if (mPrevAudioMode != mode) {
+            if (mPrevAudioMode != 0) {
+                int stringId = 0;
+                switch (mode) {
+                    case AudioState.ROUTE_EARPIECE:
+                        stringId = R.string.accessibility_earpiece_selected;
+                        break;
+                    case AudioState.ROUTE_BLUETOOTH:
+                        stringId = R.string.accessibility_bluetooth_headset_selected;
+                        break;
+                    case AudioState.ROUTE_WIRED_HEADSET:
+                        stringId = R.string.accessibility_wired_headset_selected;
+                        break;
+                    case AudioState.ROUTE_SPEAKER:
+                        stringId = R.string.accessibility_speakerphone_selected;
+                        break;
+                }
+                if (stringId != 0) {
+                    maybeSendAccessibilityEvent(mAudioButton, stringId);
+                }
+            }
+            mPrevAudioMode = mode;
+        }
     }
 
     @Override
@@ -651,4 +688,19 @@
     public void hideExtraRow() {
        mExtraRowButton.setVisibility(View.GONE);
     }
+
+    private void maybeSendAccessibilityEvent(View view, int stringId) {
+        final Context context = getActivity();
+        AccessibilityManager manager =
+                (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
+        if (manager != null && manager.isEnabled()) {
+            AccessibilityEvent e = AccessibilityEvent.obtain();
+            e.setSource(view);
+            e.setEventType(AccessibilityEvent.TYPE_ANNOUNCEMENT);
+            e.setClassName(getClass().getName());
+            e.setPackageName(context.getPackageName());
+            e.getText().add(context.getResources().getString(stringId));
+            manager.sendAccessibilityEvent(e);
+        }
+    }
 }
diff --git a/InCallUI/src/com/android/incallui/CallCardFragment.java b/InCallUI/src/com/android/incallui/CallCardFragment.java
index be9b18d..bd32684 100644
--- a/InCallUI/src/com/android/incallui/CallCardFragment.java
+++ b/InCallUI/src/com/android/incallui/CallCardFragment.java
@@ -32,7 +32,6 @@
 import android.text.TextUtils;
 import android.view.Display;
 import android.view.LayoutInflater;
-import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewAnimationUtils;
 import android.view.ViewGroup;
@@ -56,9 +55,13 @@
  */
 public class CallCardFragment extends BaseFragment<CallCardPresenter, CallCardPresenter.CallCardUi>
         implements CallCardPresenter.CallCardUi {
+
     private int mRevealAnimationDuration;
     private int mShrinkAnimationDuration;
+    private int mFabNormalDiameter;
+    private int mFabSmallDiameter;
     private boolean mIsLandscape;
+    private boolean mIsDialpadShowing;
 
     // Primary caller info
     private TextView mPhoneNumber;
@@ -92,13 +95,15 @@
 
     private FloatingActionButtonController mFloatingActionButtonController;
     private View mFloatingActionButtonContainer;
-    private int mFloatingActionButtonHideOffset;
+    private ImageButton mFloatingActionButton;
+    private int mFloatingActionButtonVerticalOffset;
 
     // Cached DisplayMetrics density.
     private float mDensity;
 
     private float mTranslationOffset;
     private Animation mPulseAnimation;
+
     private int mVideoAnimationDuration;
 
     @Override
@@ -118,8 +123,12 @@
         mRevealAnimationDuration = getResources().getInteger(R.integer.reveal_animation_duration);
         mShrinkAnimationDuration = getResources().getInteger(R.integer.shrink_animation_duration);
         mVideoAnimationDuration = getResources().getInteger(R.integer.video_animation_duration);
-        mFloatingActionButtonHideOffset = getResources().getDimensionPixelOffset(
-                R.dimen.end_call_button_hide_offset);
+        mFloatingActionButtonVerticalOffset = getResources().getDimensionPixelOffset(
+                R.dimen.floating_action_bar_vertical_offset);
+        mFabNormalDiameter = getResources().getDimensionPixelOffset(
+                R.dimen.end_call_floating_action_button_diameter);
+        mFabSmallDiameter = getResources().getDimensionPixelOffset(
+                R.dimen.end_call_floating_action_button_small_diameter);
         mIsLandscape = getResources().getConfiguration().orientation
                 == Configuration.ORIENTATION_LANDSCAPE;
     }
@@ -174,9 +183,9 @@
 
         mFloatingActionButtonContainer = view.findViewById(
                 R.id.floating_end_call_action_button_container);
-        ImageButton floatingActionButton = (ImageButton) view.findViewById(
+        mFloatingActionButton = (ImageButton) view.findViewById(
                 R.id.floating_end_call_action_button);
-        floatingActionButton.setOnClickListener(new View.OnClickListener() {
+        mFloatingActionButton.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
                 getPresenter().endCallClicked();
@@ -185,7 +194,7 @@
         int floatingActionButtonWidth = getResources().getDimensionPixelSize(
                 R.dimen.floating_action_button_width);
         mFloatingActionButtonController = new FloatingActionButtonController(getActivity(),
-                mFloatingActionButtonContainer);
+                mFloatingActionButtonContainer, mFloatingActionButton);
         final ViewGroup parent = (ViewGroup) mPrimaryCallCardContainer.getParent();
         final ViewTreeObserver observer = getView().getViewTreeObserver();
         observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@@ -201,7 +210,7 @@
                         mIsLandscape ? FloatingActionButtonController.ALIGN_QUARTER_END
                             : FloatingActionButtonController.ALIGN_MIDDLE,
                         0 /* offsetX */,
-                        0 /* offsetY */,
+                        mFloatingActionButtonVerticalOffset /* offsetY */,
                         false);
             }
         });
@@ -360,7 +369,7 @@
     @Override
     public void setPrimaryName(String name, boolean nameIsNumber) {
         if (TextUtils.isEmpty(name)) {
-            mPrimaryName.setText("");
+            mPrimaryName.setText(null);
         } else {
             mPrimaryName.setText(name);
 
@@ -384,7 +393,7 @@
     public void setPrimaryPhoneNumber(String number) {
         // Set the number
         if (TextUtils.isEmpty(number)) {
-            mPhoneNumber.setText("");
+            mPhoneNumber.setText(null);
             mPhoneNumber.setVisibility(View.GONE);
         } else {
             mPhoneNumber.setText(number);
@@ -438,6 +447,10 @@
     public void setSecondary(boolean show, String name, boolean nameIsNumber, String label,
             String providerLabel, Drawable providerIcon, boolean isConference, boolean isGeneric) {
 
+        if (show != mSecondaryCallInfo.isShown()) {
+            updateFabPositionOnSecondaryCallInfoLayout();
+        }
+
         if (show) {
             if (isConference) {
                 name = getConferenceString(isGeneric);
@@ -489,6 +502,7 @@
                 mCallStateIcon.setVisibility(View.GONE);
             } else {
                 mCallStateIcon.setVisibility(View.VISIBLE);
+                mCallStateIcon.setImageAlpha(255);
                 mCallStateIcon.setImageDrawable(connectionIcon);
             }
 
@@ -502,16 +516,21 @@
 
             if (state == Call.State.ACTIVE || state == Call.State.CONFERENCED) {
                 mCallStateLabel.clearAnimation();
+                mCallStateIcon.clearAnimation();
             } else {
                 mCallStateLabel.startAnimation(mPulseAnimation);
+                mCallStateIcon.startAnimation(mPulseAnimation);
             }
         } else {
             Animation callStateAnimation = mCallStateLabel.getAnimation();
             if (callStateAnimation != null) {
                 callStateAnimation.cancel();
             }
+            mCallStateLabel.setText(null);
             mCallStateLabel.setAlpha(0);
             mCallStateLabel.setVisibility(View.GONE);
+            mCallStateIcon.setImageAlpha(0);
+            mCallStateIcon.setVisibility(View.GONE);
 
             mCallStateVideoCallIcon.setVisibility(View.GONE);
         }
@@ -767,6 +786,7 @@
             @Override
             public void onClick(View v) {
                 getPresenter().secondaryInfoClicked();
+                updateFabPositionOnSecondaryCallInfoLayout();
             }
         });
     }
@@ -789,8 +809,25 @@
     }
 
     @Override
-    public void setEndCallButtonEnabled(boolean enabled) {
-        mFloatingActionButtonController.setVisible(enabled);
+    public void setEndCallButtonEnabled(boolean enabled, boolean animate) {
+        if (enabled != mFloatingActionButton.isEnabled()) {
+            if (animate) {
+                if (enabled) {
+                    mFloatingActionButtonController.scaleIn();
+                } else {
+                    mFloatingActionButtonController.scaleOut();
+                }
+            } else {
+                if (enabled) {
+                    mFloatingActionButtonContainer.setScaleX(1);
+                    mFloatingActionButtonContainer.setScaleY(1);
+                    mFloatingActionButtonContainer.setVisibility(View.VISIBLE);
+                } else {
+                    mFloatingActionButtonContainer.setVisibility(View.GONE);
+                }
+            }
+            mFloatingActionButton.setEnabled(enabled);
+        }
     }
 
     /**
@@ -836,15 +873,14 @@
                 mPrimaryCallCardContainer.setBottom(parent.getHeight());
 
                 // Set up FAB.
+                mFloatingActionButtonContainer.setVisibility(View.GONE);
                 mFloatingActionButtonController.setScreenWidth(parent.getWidth());
-                // Move it below the screen.
-                mFloatingActionButtonController.manuallyTranslate(
-                        mFloatingActionButtonController.getTranslationXForAlignment(
-                                mIsLandscape ? FloatingActionButtonController.ALIGN_QUARTER_END
-                                        : FloatingActionButtonController.ALIGN_MIDDLE
-                        ),
-                        mFloatingActionButtonHideOffset
-                );
+                mFloatingActionButtonController.align(
+                        mIsLandscape ? FloatingActionButtonController.ALIGN_QUARTER_END
+                                : FloatingActionButtonController.ALIGN_MIDDLE,
+                        0 /* offsetX */,
+                        mFloatingActionButtonVerticalOffset /* offsetY */,
+                        false);
                 mCallButtonsContainer.setAlpha(0);
                 mCallStateLabel.setAlpha(0);
                 mPrimaryName.setAlpha(0);
@@ -861,11 +897,13 @@
                     @Override
                     public void onAnimationCancel(Animator animation) {
                         mPrimaryCallCardContainer.removeOnLayoutChangeListener(listener);
+                        mFloatingActionButtonController.scaleIn();
                     }
 
                     @Override
                     public void onAnimationEnd(Animator animation) {
                         mPrimaryCallCardContainer.removeOnLayoutChangeListener(listener);
+                        mFloatingActionButtonController.scaleIn();
                     }
                 });
                 set.start();
@@ -873,6 +911,49 @@
         });
     }
 
+    public void onDialpadVisiblityChange(boolean isShown) {
+        mIsDialpadShowing = isShown;
+
+        int offsetY = 0;
+        if (!mIsDialpadShowing) {
+            offsetY = mFloatingActionButtonVerticalOffset;
+            if (mSecondaryCallInfo.isShown()) {
+                offsetY -= mSecondaryCallInfo.getHeight();
+            }
+        }
+
+        mFloatingActionButtonController.align(
+                mIsLandscape ? FloatingActionButtonController.ALIGN_QUARTER_END
+                        : FloatingActionButtonController.ALIGN_MIDDLE,
+                0 /* offsetX */,
+                offsetY,
+                true);
+
+        mFloatingActionButtonController.resize(
+                mIsDialpadShowing ? mFabSmallDiameter : mFabNormalDiameter, true);
+    }
+
+    /**
+     * Adds a global layout listener to update the FAB's positioning on the next layout. This allows
+     * us to position the FAB after the secondary call info's height has been calculated.
+     */
+    private void updateFabPositionOnSecondaryCallInfoLayout() {
+        mSecondaryCallInfo.getViewTreeObserver().addOnGlobalLayoutListener(
+                new ViewTreeObserver.OnGlobalLayoutListener() {
+                    @Override
+                    public void onGlobalLayout() {
+                        final ViewTreeObserver observer =
+                                mSecondaryCallInfo.getViewTreeObserver();
+                        if (!observer.isAlive()) {
+                            return;
+                        }
+                        observer.removeOnGlobalLayoutListener(this);
+
+                        onDialpadVisiblityChange(mIsDialpadShowing);
+                    }
+                });
+    }
+
     /**
      * Animator that performs the upwards shrinking animation of the blue call card scrim.
      * At the start of the animation, each child view is moved downwards by a pre-specified amount
@@ -880,24 +961,19 @@
      */
     private Animator getShrinkAnimator(int startHeight, int endHeight) {
         final Animator shrinkAnimator =
-                ObjectAnimator.ofInt(mPrimaryCallCardContainer, "bottom",
-                        startHeight, endHeight);
+                ObjectAnimator.ofInt(mPrimaryCallCardContainer, "bottom", startHeight, endHeight);
         shrinkAnimator.setDuration(mShrinkAnimationDuration);
         shrinkAnimator.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationStart(Animator animation) {
                 assignTranslateAnimation(mCallStateLabel, 1);
+                assignTranslateAnimation(mCallStateIcon, 1);
                 assignTranslateAnimation(mPrimaryName, 2);
                 assignTranslateAnimation(mCallNumberAndLabel, 3);
                 assignTranslateAnimation(mCallTypeLabel, 4);
                 assignTranslateAnimation(mCallButtonsContainer, 5);
 
-                mFloatingActionButtonController.align(
-                        mIsLandscape ? FloatingActionButtonController.ALIGN_QUARTER_END
-                            : FloatingActionButtonController.ALIGN_MIDDLE,
-                        0 /* offsetX */,
-                        0 /* offsetY */,
-                        true);
+                mFloatingActionButton.setEnabled(true);
             }
         });
         shrinkAnimator.setInterpolator(AnimUtils.EASE_IN);
diff --git a/InCallUI/src/com/android/incallui/CallCardPresenter.java b/InCallUI/src/com/android/incallui/CallCardPresenter.java
index ce17109..2dc4274 100644
--- a/InCallUI/src/com/android/incallui/CallCardPresenter.java
+++ b/InCallUI/src/com/android/incallui/CallCardPresenter.java
@@ -187,8 +187,6 @@
         Log.d(this, "Primary call: " + primary);
         Log.d(this, "Secondary call: " + secondary);
 
-        final boolean outgoingCallReady = newState == InCallState.OUTGOING &&
-                oldState == InCallState.PENDING_OUTGOING;
         final boolean primaryChanged = !Call.areSame(mPrimary, primary);
         final boolean secondaryChanged = !Call.areSame(mSecondary, secondary);
 
@@ -252,7 +250,9 @@
 
         final boolean enableEndCallButton = Call.State.isConnectingOrConnected(callState) &&
                 callState != Call.State.INCOMING && mPrimary != null;
-        getUi().setEndCallButtonEnabled(enableEndCallButton);
+        // Hide the end call button instantly if we're receiving an incoming call.
+        getUi().setEndCallButtonEnabled(
+                enableEndCallButton, callState != Call.State.INCOMING /* animate */);
     }
 
     @Override
@@ -653,7 +653,7 @@
         void setPrimaryImage(Drawable image);
         void setPrimaryPhoneNumber(String phoneNumber);
         void setPrimaryLabel(String label);
-        void setEndCallButtonEnabled(boolean enabled);
+        void setEndCallButtonEnabled(boolean enabled, boolean animate);
         void setCallbackNumber(String number, boolean isEmergencyCalls);
         void setPhotoVisible(boolean isVisible);
         void setProgressSpinnerVisible(boolean visible);
diff --git a/InCallUI/src/com/android/incallui/CallList.java b/InCallUI/src/com/android/incallui/CallList.java
index a3fa58d..0908b56 100644
--- a/InCallUI/src/com/android/incallui/CallList.java
+++ b/InCallUI/src/com/android/incallui/CallList.java
@@ -136,8 +136,8 @@
      * Called when a single call has changed.
      */
     public void onUpdate(Call call) {
-        Log.d(this, "onUpdate - ", call);
         onUpdateCall(call);
+        Log.d(this, "onUpdate - ", call);
         notifyGenericListeners();
     }
 
diff --git a/InCallUI/src/com/android/incallui/CallerInfo.java b/InCallUI/src/com/android/incallui/CallerInfo.java
index 044bdba..138575a 100644
--- a/InCallUI/src/com/android/incallui/CallerInfo.java
+++ b/InCallUI/src/com/android/incallui/CallerInfo.java
@@ -333,7 +333,7 @@
     // should be displayed.
     /* package */ CallerInfo markAsEmergency(Context context) {
         phoneNumber = context.getString(R.string.emergency_call_dialog_number_for_display);
-        photoResource = R.drawable.picture_emergency;
+        photoResource = R.drawable.img_emergency;
         mIsEmergency = true;
         return this;
     }
diff --git a/InCallUI/src/com/android/incallui/ContactInfoCache.java b/InCallUI/src/com/android/incallui/ContactInfoCache.java
index d81acb2..ccf5b79 100644
--- a/InCallUI/src/com/android/incallui/ContactInfoCache.java
+++ b/InCallUI/src/com/android/incallui/ContactInfoCache.java
@@ -233,7 +233,7 @@
             // If no image and it's a business, switch to using the default business avatar.
             if (info.getImageUrl() == null && info.isBusiness()) {
                 Log.d(TAG, "Business has no image. Using default.");
-                entry.photo = mContext.getResources().getDrawable(R.drawable.business_unknown);
+                entry.photo = mContext.getResources().getDrawable(R.drawable.img_business);
             }
 
             // Add the contact info to the cache.
diff --git a/InCallUI/src/com/android/incallui/InCallActivity.java b/InCallUI/src/com/android/incallui/InCallActivity.java
index a49342e..02635dc 100644
--- a/InCallUI/src/com/android/incallui/InCallActivity.java
+++ b/InCallUI/src/com/android/incallui/InCallActivity.java
@@ -454,14 +454,20 @@
                 intent.removeExtra(NEW_OUTGOING_CALL);
 
                 Point touchPoint = null;
-                Call call = CallList.getInstance().getOutgoingCall();
-                if (call == null) {
-                    call = CallList.getInstance().getPendingOutgoingCall();
-                }
-                if (call != null) {
-                    Bundle extras = call.getTelecommCall().getDetails().getExtras();
-                    touchPoint = (Point) (extras == null ?
-                            null : extras.getParcelable(TouchPointManager.TOUCH_POINT));
+                if (TouchPointManager.getInstance().hasValidPoint()) {
+                    // Use the most immediate touch point in the InCallUi if available
+                    touchPoint = TouchPointManager.getInstance().getPoint();
+                } else {
+                    // Otherwise retrieve the touch point from the call intent
+                    Call call = CallList.getInstance().getOutgoingCall();
+                    if (call == null) {
+                        call = CallList.getInstance().getPendingOutgoingCall();
+                    }
+                    if (call != null) {
+                        Bundle extras = call.getTelecommCall().getDetails().getExtras();
+                        touchPoint = (Point) (extras == null ?
+                                null : extras.getParcelable(TouchPointManager.TOUCH_POINT));
+                    }
                 }
                 mCallCardFragment.animateForNewOutgoingCall(touchPoint);
             }
@@ -569,6 +575,7 @@
                 showDialpad(true);
                 mDialpadFragment.animateShowDialpad();
             }
+            mCallCardFragment.onDialpadVisiblityChange(showDialpad);
             mDialpadFragment.getView().startAnimation(showDialpad ? mSlideIn : mSlideOut);
         }
 
diff --git a/InCallUI/src/com/android/incallui/InCallPresenter.java b/InCallUI/src/com/android/incallui/InCallPresenter.java
index 38b5f54..77ef49d 100644
--- a/InCallUI/src/com/android/incallui/InCallPresenter.java
+++ b/InCallUI/src/com/android/incallui/InCallPresenter.java
@@ -804,16 +804,18 @@
 
         // A new outgoing call indicates that the user just now dialed a number and when that
         // happens we need to display the screen immediately or show an account picker dialog if
-        // no default is set.
+        // no default is set. However, if the main InCallUI is already visible, we do not want to
+        // re-initiate the start-up animation, so we do not need to do anything here.
         //
         // It is also possible to go into an intermediate state where the call has been initiated
         // but Telecomm has not yet returned with the details of the call (handle, gateway, etc.).
-        // This pending outgoing state also launches the call screen.
+        // This pending outgoing state can also launch the call screen.
         //
         // This is different from the incoming call sequence because we do not need to shock the
         // user with a top-level notification.  Just show the call UI normally.
+        final boolean mainUiNotVisible = !isShowingInCallUi() || !getCallCardFragmentVisible();
         final boolean showCallUi = ((InCallState.PENDING_OUTGOING == newState ||
-                InCallState.OUTGOING == newState) || showAccountPicker);
+                InCallState.OUTGOING == newState) && mainUiNotVisible);
 
         // TODO: Can we be suddenly in a call without it having been in the outgoing or incoming
         // state?  I havent seen that but if it can happen, the code below should be enabled.
@@ -829,7 +831,7 @@
             return mInCallState;
         }
 
-        if (showCallUi) {
+        if (showCallUi || showAccountPicker) {
             Log.i(this, "Start in call UI");
             showInCall(false /* showDialpad */, !showAccountPicker /* newOutgoingCall */);
         } else if (startStartupSequence) {
@@ -1014,6 +1016,18 @@
     }
 
     /**
+     * Returns whether the call card fragment is currently visible.
+     *
+     * @return True if the call card fragment is visible.
+     */
+    public boolean getCallCardFragmentVisible() {
+        if (mInCallActivity != null) {
+            return mInCallActivity.getCallCardFragment().isVisible();
+        }
+        return false;
+    }
+
+    /**
      * @return True if the application is currently running in a right-to-left locale.
      */
     public static boolean isRtl() {
diff --git a/InCallUI/src/com/android/incallui/StatusBarNotifier.java b/InCallUI/src/com/android/incallui/StatusBarNotifier.java
index 7efaa12..809d294 100644
--- a/InCallUI/src/com/android/incallui/StatusBarNotifier.java
+++ b/InCallUI/src/com/android/incallui/StatusBarNotifier.java
@@ -291,6 +291,7 @@
         builder.setSmallIcon(iconResId);
         builder.setContentTitle(contentTitle);
         builder.setLargeIcon(largeIcon);
+        builder.setColor(mContext.getResources().getColor(R.color.dialer_theme_color));
 
         if (isVideoUpgradeRequest) {
             builder.setUsesChronometer(false);
@@ -440,7 +441,7 @@
                 == Call.SessionModificationState.RECEIVED_UPGRADE_TO_VIDEO_REQUEST) {
             return R.drawable.ic_videocam;
         }
-        return R.drawable.fab_ic_call;
+        return R.drawable.ic_call_white_24dp;
     }
 
     /**
diff --git a/InCallUI/src/com/android/incallui/TelecommAdapter.java b/InCallUI/src/com/android/incallui/TelecommAdapter.java
index 22aff11..1f5c9c5 100644
--- a/InCallUI/src/com/android/incallui/TelecommAdapter.java
+++ b/InCallUI/src/com/android/incallui/TelecommAdapter.java
@@ -220,5 +220,9 @@
         }  else {
             Log.e(this, "error phoneAccountSelected, mAdapter is null");
         }
+
+        if (accountHandle == null) {
+            Log.e(this, "error phoneAccountSelected, accountHandle is null");
+        }
     }
 }