Merge "Don't use internal resources in InCallUI"
diff --git a/InCallUI/res/drawable-land/rounded_call_card_background.xml b/InCallUI/res/drawable-land/rounded_call_card_background.xml
new file mode 100644
index 0000000..f41ecda
--- /dev/null
+++ b/InCallUI/res/drawable-land/rounded_call_card_background.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ Copyright (C) 2015 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">
+    <solid android:color="@color/incall_call_banner_background_color" />
+    <corners
+        android:radius="4dp" />
+</shape>
\ No newline at end of file
diff --git a/InCallUI/res/drawable/ic_lockscreen_answer_rx_video.xml b/InCallUI/res/drawable/ic_lockscreen_answer_rx_video.xml
deleted file mode 100644
index c5a41d8..0000000
--- a/InCallUI/res/drawable/ic_lockscreen_answer_rx_video.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (c) 2014, The Linux Foundation. All rights reserved.
-  ~ Not a Contribution.
-  ~ Copyright (C) 2014 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License
-  -->
-<!-- Used with incoming call wigdet. -->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item
-        android:state_enabled="true" android:state_active="false" android:state_focused="false"
-        android:drawable="@drawable/ic_lockscreen_answer_rx_video_normal_layer"/>
-    <item
-        android:state_enabled="true" android:state_active="true"  android:state_focused="false"
-        android:drawable="@drawable/ic_lockscreen_answer_rx_video_activated_layer" />
-    <item
-        android:state_enabled="true" android:state_active="false"  android:state_focused="true"
-        android:drawable="@drawable/ic_lockscreen_answer_rx_video_activated_layer" />
-</selector>
diff --git a/InCallUI/res/drawable/ic_lockscreen_answer_rx_video_activated_layer.xml b/InCallUI/res/drawable/ic_lockscreen_answer_rx_video_activated_layer.xml
deleted file mode 100644
index 750ef5e..0000000
--- a/InCallUI/res/drawable/ic_lockscreen_answer_rx_video_activated_layer.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (c) 2014, The Linux Foundation. All rights reserved.
-  ~ Not a Contribution.
-  ~ Copyright (C) 2014 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License
-  -->
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:drawable="@drawable/fab_red" />
-    <item>
-        <bitmap
-            android:gravity="center"
-            android:src="@drawable/ic_rx_videocam"
-            android:tint="@color/glowpad_widget_active_color"
-            android:autoMirrored="true" />
-    </item>
-</layer-list>
diff --git a/InCallUI/res/drawable/ic_lockscreen_answer_rx_video_normal_layer.xml b/InCallUI/res/drawable/ic_lockscreen_answer_rx_video_normal_layer.xml
deleted file mode 100644
index 5efd3d1..0000000
--- a/InCallUI/res/drawable/ic_lockscreen_answer_rx_video_normal_layer.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (c) 2014, The Linux Foundation. All rights reserved.
-  ~ Not a Contribution.
-  ~ Copyright (C) 2014 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License
-  -->
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
-    <!-- A fake circle to fix the size of this layer asset. -->
-    <item>
-        <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
-            <solid android:color="#00000000"/>
-            <size
-                android:width="@dimen/incoming_call_widget_circle_size"
-                android:height="@dimen/incoming_call_widget_circle_size" />
-        </shape>
-    </item>
-    <item>
-        <bitmap
-            android:gravity="center"
-            android:src="@drawable/ic_rx_videocam"
-            android:tint="@color/glowpad_call_widget_normal_tint"
-            android:autoMirrored="true" />
-    </item>
-</layer-list>
diff --git a/InCallUI/res/drawable/ic_lockscreen_answer_tx_video.xml b/InCallUI/res/drawable/ic_lockscreen_answer_tx_video.xml
deleted file mode 100644
index 15d1197..0000000
--- a/InCallUI/res/drawable/ic_lockscreen_answer_tx_video.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (c) 2014, The Linux Foundation. All rights reserved.
-  ~ Not a Contribution.
-  ~ Copyright (C) 2014 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License
-  -->
-<!-- Used with incoming call wigdet. -->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item
-        android:state_enabled="true" android:state_active="false" android:state_focused="false"
-        android:drawable="@drawable/ic_lockscreen_answer_tx_video_normal_layer"/>
-    <item
-        android:state_enabled="true" android:state_active="true"  android:state_focused="false"
-        android:drawable="@drawable/ic_lockscreen_answer_tx_video_activated_layer" />
-    <item
-        android:state_enabled="true" android:state_active="false"  android:state_focused="true"
-        android:drawable="@drawable/ic_lockscreen_answer_tx_video_activated_layer" />
-</selector>
diff --git a/InCallUI/res/drawable/ic_lockscreen_answer_tx_video_activated_layer.xml b/InCallUI/res/drawable/ic_lockscreen_answer_tx_video_activated_layer.xml
deleted file mode 100644
index c1dca4d..0000000
--- a/InCallUI/res/drawable/ic_lockscreen_answer_tx_video_activated_layer.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (c) 2014, The Linux Foundation. All rights reserved.
-  ~ Not a Contribution.
-  ~ Copyright (C) 2014 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License
-  -->
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:drawable="@drawable/fab_green" />
-    <item>
-        <bitmap
-            android:gravity="center"
-            android:src="@drawable/ic_tx_videocam"
-            android:tint="@color/glowpad_widget_active_color"
-            android:autoMirrored="true" />
-    </item>
-</layer-list>
diff --git a/InCallUI/res/drawable/ic_lockscreen_answer_tx_video_normal_layer.xml b/InCallUI/res/drawable/ic_lockscreen_answer_tx_video_normal_layer.xml
deleted file mode 100644
index b0ad943..0000000
--- a/InCallUI/res/drawable/ic_lockscreen_answer_tx_video_normal_layer.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (c) 2014, The Linux Foundation. All rights reserved.
-  ~ Not a Contribution.
-  ~ Copyright (C) 2014 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License
-  -->
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
-    <!-- A fake circle to fix the size of this layer asset. -->
-    <item>
-        <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
-            <solid android:color="#00000000"/>
-            <size
-                android:width="@dimen/incoming_call_widget_circle_size"
-                android:height="@dimen/incoming_call_widget_circle_size" />
-        </shape>
-    </item>
-    <item>
-        <bitmap
-            android:gravity="center"
-            android:src="@drawable/ic_tx_videocam"
-            android:tint="@color/glowpad_call_widget_normal_tint"
-            android:autoMirrored="true" />
-    </item>
-</layer-list>
diff --git a/InCallUI/res/layout-land/call_card_fragment.xml b/InCallUI/res/layout-land/call_card_fragment.xml
index cdee279..8946615 100644
--- a/InCallUI/res/layout-land/call_card_fragment.xml
+++ b/InCallUI/res/layout-land/call_card_fragment.xml
@@ -30,22 +30,25 @@
         android:layout_height="match_parent"
         android:orientation="vertical"
         android:elevation="@dimen/primary_call_elevation"
-        android:background="@color/incall_call_banner_background_color"
+        android:background="@drawable/rounded_call_card_background"
         android:paddingTop="@dimen/call_banner_primary_call_container_top_padding"
         android:clipChildren="false"
-        android:clipToPadding="false" >
+        android:clipToPadding="false"
+        android:alpha="0.9"
+        android:layout_margin="10dp">
 
         <include layout="@layout/primary_call_info" />
 
-        <fragment android:name="com.android.incallui.CallButtonFragment"
-            android:id="@+id/callButtonFragment"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content" />
-
         <FrameLayout
-            android:layout_width="match_parent"
+            android:layout_width="wrap_content"
             android:layout_height="match_parent" >
 
+            <fragment android:name="com.android.incallui.CallButtonFragment"
+                android:id="@+id/callButtonFragment"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="bottom"
+                android:layout_marginBottom="@dimen/call_buttons_bottom_margin" />
             <!-- Secondary "Call info" block, for the background ("on hold") call. -->
             <include layout="@layout/secondary_call_info"
                 android:layout_width="match_parent"
@@ -73,14 +76,6 @@
         android:layout_height="wrap_content"
         android:layout_alignTop="@id/photo" />
 
-    <fragment android:name="com.android.incallui.VideoCallFragment"
-        android:layout_alignParentStart="true"
-        android:layout_gravity="start|center_vertical"
-        android:id="@+id/videoCallFragment"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:visibility="gone" />
-
     <!-- Progress spinner, useful for indicating pending operations such as upgrade to video. -->
     <FrameLayout
         android:id="@+id/progressSpinner"
@@ -102,7 +97,14 @@
 
     </FrameLayout>
 
-    <!-- Placeholder for various fragments that are added dynamically underneath the caller info. -->
+    <fragment android:name="com.android.incallui.VideoCallFragment"
+        android:layout_alignParentStart="true"
+        android:layout_gravity="start|center_vertical"
+        android:id="@+id/videoCallFragment"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+    <!-- Placeholder for the dialpad which is replaced with the dialpad fragment when shown. -->
     <FrameLayout
         android:id="@+id/answer_and_dialpad_container"
         android:layout_toEndOf="@id/primary_call_info_container"
diff --git a/InCallUI/res/layout/call_button_fragment.xml b/InCallUI/res/layout/call_button_fragment.xml
index 604d79e..3629b8a 100644
--- a/InCallUI/res/layout/call_button_fragment.xml
+++ b/InCallUI/res/layout/call_button_fragment.xml
@@ -67,7 +67,8 @@
         <ToggleButton android:id="@+id/audioButton"
             style="@style/InCallCompoundButton"
             android:background="@drawable/btn_compound_audio"
-            android:contentDescription="@string/audio_mode_speaker" />
+            android:contentDescription="@string/audio_mode_speaker"
+            android:visibility="gone" />
 
         <!-- "Change to audio call" for video calls. -->
         <ImageButton android:id="@+id/changeToVoiceButton"
@@ -82,7 +83,8 @@
         <ToggleButton android:id="@+id/muteButton"
             style="@style/InCallCompoundButton"
             android:background="@drawable/btn_compound_mute"
-            android:contentDescription="@string/onscreenMuteText" />
+            android:contentDescription="@string/onscreenMuteText"
+            android:visibility="gone" />
 
         <!-- CENTER SLOT ======================================================================= -->
 
@@ -90,7 +92,8 @@
         <ToggleButton android:id="@+id/dialpadButton"
             style="@style/InCallCompoundButton"
             android:background="@drawable/btn_compound_dialpad"
-            android:contentDescription="@string/onscreenShowDialpadText" />
+            android:contentDescription="@string/onscreenShowDialpadText"
+            android:visibility="gone" />
 
         <!-- MIDDLE RIGHT SLOT ================================================================= -->
 
@@ -101,7 +104,8 @@
         <ToggleButton android:id="@+id/holdButton"
             style="@style/InCallCompoundButton"
             android:background="@drawable/btn_compound_hold"
-            android:contentDescription="@string/onscreenHoldText" />
+            android:contentDescription="@string/onscreenHoldText_unselected"
+            android:visibility="gone" />
 
         <!-- "Swap" (or "Manage calls" in some CDMA states) -->
         <ImageButton android:id="@+id/swapButton"
diff --git a/InCallUI/res/layout/secondary_call_info.xml b/InCallUI/res/layout/secondary_call_info.xml
index 85eef0e..e866795 100644
--- a/InCallUI/res/layout/secondary_call_info.xml
+++ b/InCallUI/res/layout/secondary_call_info.xml
@@ -40,6 +40,13 @@
         android:paddingBottom="@dimen/secondary_call_info_vertical_padding"
         android:background="?android:attr/selectableItemBackground">
 
+        <ImageView android:id="@+id/secondaryCallVideoCallIcon"
+                   android:layout_width="wrap_content"
+                   android:layout_height="wrap_content"
+                   android:src="@drawable/ic_toolbar_video"
+                   android:tint="@color/incall_banner_secondary_text_color"
+                   android:paddingEnd="16dp"/>
+
         <ImageView android:id="@+id/secondaryCallConferenceCallIcon"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
diff --git a/InCallUI/res/menu/incall_overflow_menu.xml b/InCallUI/res/menu/incall_overflow_menu.xml
deleted file mode 100644
index 2de8587..0000000
--- a/InCallUI/res/menu/incall_overflow_menu.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2014 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License
-  -->
-
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:id="@+id/overflow_merge_menu_item"
-          android:title="@string/overflowMergeMenuItemText" />
-
-    <item android:id="@+id/overflow_add_menu_item"
-          android:title="@string/overflowAddMenuItemText" />
-
-    <item android:id="@+id/overflow_hold_menu_item"
-          android:title="@string/overflowHoldMenuItemText" />
-
-    <item android:id="@+id/overflow_resume_menu_item"
-        android:title="@string/overflowResumeMenuItemText" />
-
-    <item android:id="@+id/overflow_swap_menu_item"
-          android:title="@string/overflowSwapMenuItemText" />
-
-    <item android:id="@+id/overflow_manage_conference_menu_item"
-          android:title="@string/overflowManageConferenceMenuItemText" />
-</menu>
diff --git a/InCallUI/res/values-land/colors.xml b/InCallUI/res/values-land/colors.xml
new file mode 100644
index 0000000..77eea2e
--- /dev/null
+++ b/InCallUI/res/values-land/colors.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2015 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<resources>
+    <!-- Background color for status bar. For portrait this will be ignored. -->
+    <color name="statusbar_background_color">#000000</color>
+</resources>
diff --git a/InCallUI/res/values-land/dimens.xml b/InCallUI/res/values-land/dimens.xml
index d992ccd..59a5a9a 100644
--- a/InCallUI/res/values-land/dimens.xml
+++ b/InCallUI/res/values-land/dimens.xml
@@ -16,6 +16,11 @@
   -->
 
 <resources>
+    <!-- Whether or not the landscape mode layout is currently being used -->
+    <bool name="is_layout_landscape">true</bool>
     <!-- Height and width of the in-call buttons. -->
     <dimen name="in_call_button_dimension">40dp</dimen>
+    <!-- Margin underneath the call buttons. This is used only in landscape mode and is sized
+         so that the call buttons are center aligned with the end call button. -->
+    <dimen name="call_buttons_bottom_margin">30dp</dimen>
 </resources>
diff --git a/InCallUI/res/values/array.xml b/InCallUI/res/values/array.xml
index 46592e1..2e38c2c 100644
--- a/InCallUI/res/values/array.xml
+++ b/InCallUI/res/values/array.xml
@@ -74,8 +74,6 @@
         <item>@null</item>
         <item>@drawable/ic_lockscreen_decline</item>
         <item>@drawable/ic_lockscreen_answer_video</item>
-        <item>@drawable/ic_lockscreen_answer_tx_video</item>
-        <item>@drawable/ic_lockscreen_answer_rx_video</item>
     </array>
     <array name="incoming_call_widget_video_without_sms_target_descriptions">
         <item>@string/description_target_answer_video_call</item>
@@ -100,8 +98,6 @@
         <item>@drawable/ic_lockscreen_text</item>
         <item>@drawable/ic_lockscreen_decline</item>
         <item>@drawable/ic_lockscreen_answer</item>
-        <item>@drawable/ic_lockscreen_answer_tx_video</item>
-        <item>@drawable/ic_lockscreen_answer_rx_video</item>
     </array>
     <array name="incoming_call_widget_video_with_sms_target_descriptions">
         <item>@string/description_target_answer_video_call</item>
@@ -126,8 +122,6 @@
         <item>@null</item>
         <item>@drawable/ic_lockscreen_decline</item>
         <item>@drawable/ic_lockscreen_answer</item>
-        <item>@drawable/ic_lockscreen_answer_tx_video</item>
-        <item>@drawable/ic_lockscreen_answer_rx_video</item>
     </array>
     <array name="incoming_call_widget_video_upgrade_request_target_descriptions">
         <item>@string/description_target_accept_upgrade_to_video_request</item>
@@ -152,26 +146,27 @@
 
     <!-- For accept/reject upgrade to video transmit in active video call
          - Accept upgrade to video request (drag right)
-         - Decline upgrade to video request (drag left)-->
+         - Decline upgrade to video request (drag left)
+         TODO: This should be automatically rejected in the lower layers -->
     <array name="incoming_call_widget_video_transmit_accept_reject_request_targets">
-        <item>@drawable/ic_lockscreen_answer_tx_video</item>
+        <item>@drawable/ic_lockscreen_answer_video</item>
         <item>@drawable/ic_lockscreen_decline</item>
     </array>
     <array name="incoming_call_widget_video_transmit_request_target_descriptions">
-        <item>@string/description_target_accept_upgrade_to_video_transmit_request</item>
-        <item>@string/description_target_decline_upgrade_to_video_transmit_request</item>
+        <item>@string/description_target_accept_upgrade_to_video_request</item>
+        <item>@string/description_target_decline_upgrade_to_video_request</item>
     </array>
 
     <!-- For accept/reject upgrade to video receive in active video call
          - Accept upgrade to video request (drag right)
          - Decline upgrade to video request (drag left)-->
     <array name="incoming_call_widget_video_receive_accept_reject_request_targets">
-        <item>@drawable/ic_lockscreen_answer_rx_video</item>
+        <item>@drawable/ic_lockscreen_answer_video</item>
         <item>@drawable/ic_lockscreen_decline</item>
     </array>
     <array name="incoming_call_widget_video_receive_request_target_descriptions">
-        <item>@string/description_target_accept_upgrade_to_video_receive_request</item>
-        <item>@string/description_target_decline_upgrade_to_video_receive_request</item>
+        <item>@string/description_target_accept_upgrade_to_video_request</item>
+        <item>@string/description_target_decline_upgrade_to_video_request</item>
     </array>
 
 </resources>
diff --git a/InCallUI/res/values/colors.xml b/InCallUI/res/values/colors.xml
index afc557b..cac382d 100644
--- a/InCallUI/res/values/colors.xml
+++ b/InCallUI/res/values/colors.xml
@@ -59,6 +59,8 @@
 
     <!-- Background color of action bars -->
     <color name="actionbar_background_color">@color/dialer_theme_color</color>
+    <!-- Background color for status bar. For portrait this will be ignored. -->
+    <color name="statusbar_background_color">@color/dialer_theme_color</color>
 
     <color name="translucent_shadow">#33999999</color>
 
diff --git a/InCallUI/res/values/dimens.xml b/InCallUI/res/values/dimens.xml
index 43307e8..0739234 100644
--- a/InCallUI/res/values/dimens.xml
+++ b/InCallUI/res/values/dimens.xml
@@ -16,6 +16,9 @@
   -->
 
 <resources>
+    <!-- Whether or not the landscape mode layout is currently being used -->
+    <bool name="is_layout_landscape">false</bool>
+
     <!-- Dimensions for CallCard elements (the normal in-call UI) -->
 
     <!-- Height of the "call banner" overlay on top of the upper part of the call info area.
@@ -67,7 +70,7 @@
     <dimen name="dialpad_digits_adjustable_height">50dp</dimen>
     <dimen name="dialpad_key_numbers_size">36dp</dimen>
 
-    <dimen name="floating_action_bar_vertical_offset">-24dp</dimen>
+    <dimen name="floating_action_button_vertical_offset">-24dp</dimen>
 
     <dimen name="call_button_margin_vertical">8dp</dimen>
     <dimen name="call_button_margin_horizontal">6dp</dimen>
diff --git a/InCallUI/res/values/strings.xml b/InCallUI/res/values/strings.xml
index 99b8111..cfe3d41 100644
--- a/InCallUI/res/values/strings.xml
+++ b/InCallUI/res/values/strings.xml
@@ -255,23 +255,14 @@
          to dial using the physical keyboard -->
     <string name="dialerKeyboardHintText">Use keyboard to dial</string>
 
-    <!-- Text for the overflow "Hold call" menu item. -->
-    <string name="overflowHoldMenuItemText">Hold call</string>
-    <!-- Text for the overflow "Resume call" menu item. -->
-    <string name="overflowResumeMenuItemText">Resume call</string>
-    <!-- Text for the overflow "Add call" menu item. -->
-    <string name="overflowAddMenuItemText">Add call</string>
-    <!-- Text for the onscreen "Merge calls" menu item. -->
-    <string name="overflowMergeMenuItemText">Merge calls</string>
-    <!-- Text for the onscreen "Swap calls" menu item. -->
-    <string name="overflowSwapMenuItemText">Swap calls</string>
-    <!-- Text for the overflow "Manage Conference Video Call" menu item. -->
-    <string name="overflowManageConferenceMenuItemText">Manage Conference</string>
-
-    <!-- Text for the onscreen "Hold" button -->
-    <string name="onscreenHoldText">Hold</string>
+    <!-- Text for the onscreen "Hold" button when it is not selected. Pressing it will put
+         the call on hold. -->
+    <string name="onscreenHoldText_unselected">Hold Call</string>
+    <!-- Text for the onscreen "Hold" button when it is selected. Pressing it will resume
+         the call from a previously held state. -->
+    <string name="onscreenHoldText_selected">Resume Call</string>
     <!-- Text for the onscreen "End call" button -->
-    <string name="onscreenEndCallText">End</string>
+    <string name="onscreenEndCallText">End Call</string>
     <!-- Text for the onscreen "Show Dialpad" button -->
     <string name="onscreenShowDialpadText">Dialpad</string>
     <!-- Text for the onscreen "Mute" button -->
@@ -456,7 +447,7 @@
     <!-- This can be used in any application wanting to disable the text "Emergency number" -->
     <string name="emergency_call_dialog_number_for_display">Emergency number</string>
 
-    <!-- STOPSHIP These strings are for debugging only --> 
+    <!-- STOPSHIP These strings are for debugging only -->
     <!-- Call substate label -->
     <string name="call_substate_label" translatable="false">Call substate - \u000a</string>
     <!-- Call substate label for call resumed -->
diff --git a/InCallUI/src/com/android/incallui/CallButtonFragment.java b/InCallUI/src/com/android/incallui/CallButtonFragment.java
index a9fafae..b2c812b 100644
--- a/InCallUI/src/com/android/incallui/CallButtonFragment.java
+++ b/InCallUI/src/com/android/incallui/CallButtonFragment.java
@@ -16,6 +16,8 @@
 
 package com.android.incallui;
 
+import static com.android.incallui.CallButtonFragment.Buttons.*;
+
 import android.app.AlertDialog;
 import android.content.Context;
 import android.content.DialogInterface;
@@ -30,6 +32,7 @@
 import android.telecom.AudioState;
 import android.telecom.TelecomManager;
 import android.telecom.VideoProfile;
+import android.util.SparseIntArray;
 import android.view.ContextThemeWrapper;
 import android.view.HapticFeedbackConstants;
 import android.view.LayoutInflater;
@@ -44,7 +47,6 @@
 import android.widget.PopupMenu.OnDismissListener;
 import android.widget.PopupMenu.OnMenuItemClickListener;
 
-import com.android.contacts.common.util.MaterialColorMapUtils;
 import com.android.contacts.common.util.MaterialColorMapUtils.MaterialPalette;
 import java.util.ArrayList;
 
@@ -55,8 +57,34 @@
         extends BaseFragment<CallButtonPresenter, CallButtonPresenter.CallButtonUi>
         implements CallButtonPresenter.CallButtonUi, OnMenuItemClickListener, OnDismissListener,
         View.OnClickListener {
-    private CompoundButton mAudioButton;
     private static final int INVALID_INDEX = -1;
+    private static final int BUTTON_MAX_VISIBLE = 5;
+    // The button is currently visible in the UI
+    private static final int BUTTON_VISIBLE = 1;
+    // The button is hidden in the UI
+    private static final int BUTTON_HIDDEN = 2;
+    // The button has been collapsed into the overflow menu
+    private static final int BUTTON_MENU = 3;
+
+    public interface Buttons {
+        public static final int BUTTON_AUDIO = 0;
+        public static final int BUTTON_DOWNGRADE_TO_VOICE = 1;
+        public static final int BUTTON_MUTE = 2;
+        public static final int BUTTON_DIALPAD = 3;
+        public static final int BUTTON_HOLD = 4;
+        public static final int BUTTON_SWAP = 5;
+        public static final int BUTTON_UPGRADE_TO_VIDEO = 6;
+        public static final int BUTTON_SWITCH_CAMERA = 7;
+        public static final int BUTTON_ADD_CALL = 8;
+        public static final int BUTTON_MERGE = 9;
+        public static final int BUTTON_PAUSE_VIDEO = 10;
+        public static final int BUTTON_MANAGE_VIDEO_CONFERENCE = 11;
+        public static final int BUTTON_COUNT = 12;
+    }
+
+    private SparseIntArray mButtonVisibilityMap = new SparseIntArray(BUTTON_COUNT);
+
+    private CompoundButton mAudioButton;
     private ImageButton mChangeToVoiceButton;
     private CompoundButton mMuteButton;
     private CompoundButton mShowDialpadButton;
@@ -97,6 +125,10 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+
+        for (int i = 0; i < BUTTON_COUNT; i++) {
+            mButtonVisibilityMap.put(i, BUTTON_HIDDEN);
+        }
     }
 
     @Override
@@ -157,7 +189,6 @@
         int id = view.getId();
         Log.d(this, "onClick(View " + view + ", id " + id + ")...");
 
-        boolean isClickHandled = true;
         switch(id) {
             case R.id.audioButton:
                 onAudioButtonClicked();
@@ -200,22 +231,21 @@
                         !mPauseVideoButton.isSelected() /* pause */);
                 break;
             case R.id.overflowButton:
-                mOverflowPopup.show();
+                if (mOverflowPopup != null) {
+                    mOverflowPopup.show();
+                }
                 break;
             case R.id.manageVideoCallConferenceButton:
                 onManageVideoCallConferenceClicked();
                 break;
             default:
-                isClickHandled = false;
                 Log.wtf(this, "onClick: unexpected");
-                break;
+                return;
         }
 
-        if (isClickHandled) {
-            view.performHapticFeedback(
-                    HapticFeedbackConstants.VIRTUAL_KEY,
-                    HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
-        }
+        view.performHapticFeedback(
+                HapticFeedbackConstants.VIRTUAL_KEY,
+                HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
     }
 
     public void updateColors() {
@@ -225,7 +255,6 @@
             return;
         }
 
-        Resources res = getActivity().getResources();
         View[] compoundButtons = {
                 mAudioButton,
                 mMuteButton,
@@ -344,112 +373,81 @@
     }
 
     @Override
-    public void setMute(boolean value) {
-        if (mMuteButton.isSelected() != value) {
-            mMuteButton.setSelected(value);
+    public void showButton(int buttonId, boolean show) {
+        mButtonVisibilityMap.put(buttonId, show ? BUTTON_VISIBLE : BUTTON_HIDDEN);
+    }
+
+    @Override
+    public void enableButton(int buttonId, boolean enable) {
+        final View button = getButtonById(buttonId);
+        if (button != null) {
+            button.setEnabled(enable);
         }
     }
 
-    @Override
-    public void showAudioButton(boolean show) {
-        mAudioButton.setVisibility(show ? View.VISIBLE : View.GONE);
-    }
-
-    @Override
-    public void showChangeToVoiceButton(boolean show) {
-        mChangeToVoiceButton.setVisibility(show ? View.VISIBLE : View.GONE);
-    }
-
-    @Override
-    public void enableMute(boolean enabled) {
-        mMuteButton.setEnabled(enabled);
-    }
-
-    @Override
-    public void showDialpadButton(boolean show) {
-        mShowDialpadButton.setVisibility(show ? View.VISIBLE : View.GONE);
+    private View getButtonById(int id) {
+        switch (id) {
+            case BUTTON_AUDIO:
+                return mAudioButton;
+            case BUTTON_DOWNGRADE_TO_VOICE:
+                return mChangeToVoiceButton;
+            case BUTTON_MUTE:
+                return mMuteButton;
+            case BUTTON_DIALPAD:
+                return mShowDialpadButton;
+            case BUTTON_HOLD:
+                return mHoldButton;
+            case BUTTON_SWAP:
+                return mSwapButton;
+            case BUTTON_UPGRADE_TO_VIDEO:
+                return mChangeToVideoButton;
+            case BUTTON_SWITCH_CAMERA:
+                return mSwitchCameraButton;
+            case BUTTON_ADD_CALL:
+                return mAddCallButton;
+            case BUTTON_MERGE:
+                return mMergeButton;
+            case BUTTON_PAUSE_VIDEO:
+                return mPauseVideoButton;
+            case BUTTON_MANAGE_VIDEO_CONFERENCE:
+                return mManageVideoCallConferenceButton;
+            default:
+                Log.w(this, "Invalid button id");
+                return null;
+        }
     }
 
     @Override
     public void setHold(boolean value) {
         if (mHoldButton.isSelected() != value) {
             mHoldButton.setSelected(value);
+            mHoldButton.setContentDescription(getContext().getString(
+                    value ? R.string.onscreenHoldText_selected
+                            : R.string.onscreenHoldText_unselected));
         }
     }
 
     @Override
-    public void showHoldButton(boolean show) {
-        mHoldButton.setVisibility(show ? View.VISIBLE : View.GONE);
-    }
-
-    @Override
-    public void enableHold(boolean enabled) {
-        mHoldButton.setEnabled(enabled);
-    }
-
-    @Override
-    public void showSwapButton(boolean show) {
-        mSwapButton.setVisibility(show ? View.VISIBLE : View.GONE);
-    }
-
-    @Override
-    public void showChangeToVideoButton(boolean show) {
-        mChangeToVideoButton.setVisibility(show ? View.VISIBLE : View.GONE);
-    }
-
-    @Override
-    public void enableChangeToVideoButton(boolean enable) {
-        mChangeToVideoButton.setEnabled(enable);
-    }
-
-    @Override
-    public void showSwitchCameraButton(boolean show) {
-        mSwitchCameraButton.setVisibility(show ? View.VISIBLE : View.GONE);
-    }
-
-    @Override
-    public void setSwitchCameraButton(boolean isBackFacingCamera) {
+    public void setCameraSwitched(boolean isBackFacingCamera) {
         mSwitchCameraButton.setSelected(isBackFacingCamera);
     }
 
     @Override
-    public void showAddCallButton(boolean show) {
-        Log.d(this, "show Add call button: " + show);
-        mAddCallButton.setVisibility(show ? View.VISIBLE : View.GONE);
-    }
-
-    public void showManageConferenceVideoCallButton(boolean show) {
-        mManageVideoCallConferenceButton.setVisibility(show ? View.VISIBLE : View.GONE);
-    }
-
-    @Override
-    public void showMergeButton(boolean show) {
-        mMergeButton.setVisibility(show ? View.VISIBLE : View.GONE);
-
-        // If the merge button was disabled, re-enable it when hiding it.
-        if (!show) {
-            mMergeButton.setEnabled(true);
-        }
-    }
-
-    @Override
-    public void showPauseVideoButton(boolean show) {
-        mPauseVideoButton.setVisibility(show ? View.VISIBLE : View.GONE);
-    }
-
-    @Override
-    public void setPauseVideoButton(boolean isPaused) {
+    public void setVideoPaused(boolean isPaused) {
         mPauseVideoButton.setSelected(isPaused);
     }
 
     @Override
-    public void showOverflowButton(boolean show) {
-        mOverflowButton.setVisibility(show ? View.VISIBLE : View.GONE);
+    public void setMute(boolean value) {
+        if (mMuteButton.isSelected() != value) {
+            mMuteButton.setSelected(value);
+        }
     }
 
     /**The function is called when Modify Call button gets pressed. The function creates and
      * displays modify call options.
      */
+    @Override
     public void displayModifyCallOptions() {
         CallButtonPresenter.CallButtonUi ui = getUi();
         if (ui == null) {
@@ -520,65 +518,68 @@
         return "";
     }
 
+    private void addToOverflowMenu(int id, View button, PopupMenu menu) {
+        button.setVisibility(View.GONE);
+        menu.getMenu().add(Menu.NONE, id, Menu.NONE, button.getContentDescription());
+        mButtonVisibilityMap.put(id, BUTTON_MENU);
+    }
+
+    private PopupMenu getPopupMenu() {
+        return new PopupMenu(new ContextThemeWrapper(getActivity(), R.style.InCallPopupMenuStyle),
+                mOverflowButton);
+    }
+
+    /**
+     * Iterates through the list of buttons and toggles their visibility depending on the
+     * setting configured by the CallButtonPresenter. If there are more visible buttons than
+     * the allowed maximum, the excess buttons are collapsed into a single overflow menu.
+     */
     @Override
-    public void configureOverflowMenu(boolean showMergeMenuOption, boolean showAddMenuOption,
-            boolean showHoldMenuOption, boolean showSwapMenuOption, 
-            boolean showManageConferenceVideoCallOption) {
-        if (mOverflowPopup == null) {
-            final ContextThemeWrapper contextWrapper = new ContextThemeWrapper(getActivity(),
-                    R.style.InCallPopupMenuStyle);
-            mOverflowPopup = new PopupMenu(contextWrapper, mOverflowButton);
-            mOverflowPopup.getMenuInflater().inflate(R.menu.incall_overflow_menu,
-                    mOverflowPopup.getMenu());
+    public void updateButtonStates() {
+        View prevVisibleButton = null;
+        int prevVisibleId = -1;
+        PopupMenu menu = null;
+        int visibleCount = 0;
+        for (int i = 0; i < BUTTON_COUNT; i++) {
+            final int visibility = mButtonVisibilityMap.get(i);
+            final View button = getButtonById(i);
+            if (visibility == BUTTON_VISIBLE) {
+                visibleCount++;
+                if (visibleCount <= BUTTON_MAX_VISIBLE) {
+                    button.setVisibility(View.VISIBLE);
+                    prevVisibleButton = button;
+                    prevVisibleId = i;
+                } else {
+                    if (menu == null) {
+                        menu = getPopupMenu();
+                    }
+                    // Collapse the current button into the overflow menu. If is the first visible
+                    // button that exceeds the threshold, also collapse the previous visible button
+                    // so that the total number of visible buttons will never exceed the threshold.
+                    if (prevVisibleButton != null) {
+                        addToOverflowMenu(prevVisibleId, prevVisibleButton, menu);
+                        prevVisibleButton = null;
+                        prevVisibleId = -1;
+                    }
+                    addToOverflowMenu(i, button, menu);
+                }
+            } else if (visibility == BUTTON_HIDDEN){
+                button.setVisibility(View.GONE);
+            }
+        }
+
+        mOverflowButton.setVisibility(menu != null ? View.VISIBLE : View.GONE);
+        if (menu != null) {
+            mOverflowPopup = menu;
             mOverflowPopup.setOnMenuItemClickListener(new OnMenuItemClickListener() {
                 @Override
                 public boolean onMenuItemClick(MenuItem item) {
-                    switch (item.getItemId()) {
-                        case R.id.overflow_merge_menu_item:
-                            getPresenter().mergeClicked();
-                            break;
-                        case R.id.overflow_add_menu_item:
-                            getPresenter().addCallClicked();
-                            break;
-                        case R.id.overflow_hold_menu_item:
-                            getPresenter().holdClicked(true /* checked */);
-                            break;
-                        case R.id.overflow_resume_menu_item:
-                            getPresenter().holdClicked(false /* checked */);
-                            break;
-                        case R.id.overflow_swap_menu_item:
-                            getPresenter().addCallClicked();
-                            break;
-                        case R.id.overflow_manage_conference_menu_item:
-                            onManageVideoCallConferenceClicked();
-                            break;
-                        default:
-                            Log.wtf(this, "onMenuItemClick: unexpected overflow menu click");
-                            break;
-                    }
+                    final int id = item.getItemId();
+                    getButtonById(id).performClick();
                     return true;
                 }
             });
-            mOverflowPopup.setOnDismissListener(new OnDismissListener() {
-                @Override
-                public void onDismiss(PopupMenu popupMenu) {
-                    popupMenu.dismiss();
-                }
-            });
         }
-
-        final Menu menu = mOverflowPopup.getMenu();
-        menu.findItem(R.id.overflow_merge_menu_item).setVisible(showMergeMenuOption);
-        menu.findItem(R.id.overflow_add_menu_item).setVisible(showAddMenuOption);
-        menu.findItem(R.id.overflow_hold_menu_item).setVisible(
-                showHoldMenuOption && !mHoldButton.isSelected());
-        menu.findItem(R.id.overflow_resume_menu_item).setVisible(
-                showHoldMenuOption && mHoldButton.isSelected());
-        menu.findItem(R.id.overflow_swap_menu_item).setVisible(showSwapMenuOption);
-        menu.findItem(R.id.overflow_manage_conference_menu_item).setVisible(
-            showManageConferenceVideoCallOption);
-
-        mOverflowButton.setEnabled(menu.hasVisibleItems());
     }
 
     @Override
diff --git a/InCallUI/src/com/android/incallui/CallButtonPresenter.java b/InCallUI/src/com/android/incallui/CallButtonPresenter.java
index b50827f..43431c7 100644
--- a/InCallUI/src/com/android/incallui/CallButtonPresenter.java
+++ b/InCallUI/src/com/android/incallui/CallButtonPresenter.java
@@ -16,7 +16,8 @@
 
 package com.android.incallui;
 
-import android.app.AlertDialog;
+import static com.android.incallui.CallButtonFragment.Buttons.*;
+
 import android.content.Context;
 import android.os.Bundle;
 import android.telecom.AudioState;
@@ -46,7 +47,6 @@
     private Call mCall;
     private boolean mAutomaticallyMuted = false;
     private boolean mPreviousMuteState = false;
-    private static final int BUTTON_THRESOLD_TO_DISPLAY_OVERFLOW_MENU = 5;
 
     public CallButtonPresenter() {
     }
@@ -119,7 +119,7 @@
     @Override
     public void onDetailsChanged(Call call, android.telecom.Call.Details details) {
         if (getUi() != null && Objects.equals(call, mCall)) {
-            updateCallButtons(call, getUi().getContext());
+            updateButtonsState(call);
         }
     }
 
@@ -131,7 +131,7 @@
     @Override
     public void onCanAddCallChanged(boolean canAddCall) {
         if (getUi() != null && mCall != null) {
-            updateCallButtons(mCall, getUi().getContext());
+            updateButtonsState(mCall);
         }
     }
 
@@ -321,7 +321,7 @@
                     mCall.getVideoState() & ~VideoProfile.VideoState.PAUSED);
             videoCall.sendSessionModifyRequest(videoProfile);
         }
-        getUi().setPauseVideoButton(pause);
+        getUi().setVideoPaused(pause);
     }
 
     private void updateUi(InCallState state, Call call) {
@@ -340,9 +340,9 @@
             return;
         }
 
-        updateCallButtons(call, ui.getContext());
+        updateButtonsState(call);
 
-        ui.enableMute(call.can(android.telecom.Call.Details.CAPABILITY_MUTE));
+        ui.enableButton(BUTTON_MUTE, call.can(android.telecom.Call.Details.CAPABILITY_MUTE));
     }
 
     private static int toInteger(boolean b) {
@@ -353,137 +353,49 @@
      * Updates the buttons applicable for the UI.
      *
      * @param call The active call.
-     * @param context The context.
      */
-    private void updateCallButtons(Call call, Context context) {
-        if (CallUtils.isVideoCall(call)) {
-            updateVideoCallButtons(call);
-        }
-        updateVoiceCallButtons(call);
-    }
-
-    private void updateVideoCallButtons(Call call) {
-        Log.v(this, "Showing buttons for video call.");
-        final CallButtonUi ui = getUi();
-
-        // Show all video-call-related buttons.
-        ui.showSwitchCameraButton(true);
-        ui.showPauseVideoButton(true);
-
-        final boolean supportHold = call.can(android.telecom.Call.Details.CAPABILITY_SUPPORT_HOLD);
-        final boolean enableHoldOption = call.can(android.telecom.Call.Details.CAPABILITY_HOLD);
-        ui.showHoldButton(supportHold);
-        ui.enableHold(enableHoldOption);
-        ui.setHold(call.getState() == Call.State.ONHOLD);
-    }
-
-    private void updateVoiceCallButtons(Call call) {
+    private void updateButtonsState(Call call) {
         Log.v(this, "Showing buttons for voice call.");
         final CallButtonUi ui = getUi();
 
-        // Hide all video-call-related buttons.
-        ui.showChangeToVoiceButton(false);
-        ui.showSwitchCameraButton(false);
-        ui.showPauseVideoButton(false);
+        final boolean isVideo = CallUtils.isVideoCall(call);
 
-        // Show all voice-call-related buttons.
-        ui.showAudioButton(true);
-        ui.showDialpadButton(true);
-
-        Log.v(this, "Show hold ", call.can(android.telecom.Call.Details.CAPABILITY_SUPPORT_HOLD));
-        Log.v(this, "Enable hold", call.can(android.telecom.Call.Details.CAPABILITY_HOLD));
-        Log.v(this, "Show merge ", call.can(
-                android.telecom.Call.Details.CAPABILITY_MERGE_CONFERENCE));
-        Log.v(this, "Show swap ", call.can(
-                android.telecom.Call.Details.CAPABILITY_SWAP_CONFERENCE));
-        Log.v(this, "Show add call ", TelecomAdapter.getInstance().canAddCall());
-        Log.v(this, "Show mute ", call.can(android.telecom.Call.Details.CAPABILITY_MUTE));
-
-        boolean canBidiLocal =
-                call.can(android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL);
-        boolean canBidiRemote =
-                call.can(android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL);
-        Log.v(this, "Show video call local:" + canBidiLocal + ", remote: " + canBidiRemote);
-
-        final boolean canAdd = TelecomAdapter.getInstance().canAddCall();
-        final boolean enableHoldOption = call.can(android.telecom.Call.Details.CAPABILITY_HOLD);
-        final boolean supportHold = call.can(android.telecom.Call.Details.CAPABILITY_SUPPORT_HOLD);
-        final boolean isCallOnHold = call.getState() == Call.State.ONHOLD;
-
-        boolean canVideoCall = canBidiLocal && canBidiRemote;
-        ui.showChangeToVideoButton(canVideoCall);
-
-        final boolean showMergeOption = call.can(
-                android.telecom.Call.Details.CAPABILITY_MERGE_CONFERENCE);
-        final boolean showAddCallOption = canAdd;
-        final boolean showManageVideoCallConferenceOption = call.can(
-                android.telecom.Call.Details.CAPABILITY_MANAGE_CONFERENCE)
-                && CallUtils.isVideoCall(call);
-
+        // Common functionality (audio, hold, etc).
         // Show either HOLD or SWAP, but not both. If neither HOLD or SWAP is available:
         //     (1) If the device normally can hold, show HOLD in a disabled state.
         //     (2) If the device doesn't have the concept of hold/swap, remove the button.
-        final boolean showSwapOption = call.can(
+        final boolean showSwap = call.can(
                 android.telecom.Call.Details.CAPABILITY_SWAP_CONFERENCE);
-        final boolean showHoldOption = !showSwapOption && (enableHoldOption || supportHold);
+        final boolean showHold = !showSwap
+                && call.can(android.telecom.Call.Details.CAPABILITY_SUPPORT_HOLD)
+                && call.can(android.telecom.Call.Details.CAPABILITY_HOLD);
+        final boolean isCallOnHold = call.getState() == Call.State.ONHOLD;
 
+        final boolean showAddCall = TelecomAdapter.getInstance().canAddCall();
+        final boolean showMerge = call.can(
+                android.telecom.Call.Details.CAPABILITY_MERGE_CONFERENCE);
+        final boolean showUpgradeToVideo = !isVideo
+                && call.can(android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_LOCAL_TX)
+                && call.can(android.telecom.Call.Details.CAPABILITY_SUPPORTS_VT_REMOTE_RX);
+
+        final boolean showMute = call.can(android.telecom.Call.Details.CAPABILITY_MUTE);
+
+        ui.showButton(BUTTON_AUDIO, true);
+        ui.showButton(BUTTON_SWAP, showSwap);
+        ui.showButton(BUTTON_HOLD, showHold);
         ui.setHold(isCallOnHold);
-        //Initialize buttonCount = 2. Because speaker and dialpad these two always show in Call UI.
-        int buttonCount = 2;
-        buttonCount += toInteger(canVideoCall);
-        buttonCount += toInteger(showAddCallOption);
-        buttonCount += toInteger(showMergeOption);
-        buttonCount += toInteger(showHoldOption);
-        buttonCount += toInteger(showSwapOption);
-        buttonCount += toInteger(call.can(android.telecom.Call.Details.CAPABILITY_MUTE));
-        buttonCount += toInteger(showManageVideoCallConferenceOption);
+        ui.showButton(BUTTON_MUTE, showMute);
+        ui.showButton(BUTTON_ADD_CALL, showAddCall);
+        // TODO: This button is currently being used for both upgrade and downgrade scenarios.
+        // It should be split into BUTTON_DOWNGRADE_TO_VOICE AND BUTTON_UPGRADE_TO_VIDEO
+        ui.showButton(BUTTON_UPGRADE_TO_VIDEO, true);
+        ui.showButton(BUTTON_DOWNGRADE_TO_VOICE, false);
+        ui.showButton(BUTTON_SWITCH_CAMERA, isVideo);
+        ui.showButton(BUTTON_PAUSE_VIDEO, isVideo);
+        ui.showButton(BUTTON_DIALPAD, !isVideo);
+        ui.showButton(BUTTON_MERGE, showMerge);
 
-        Log.v(this, "show ManageVideoCallConference: " + showManageVideoCallConferenceOption);
-        Log.v(this, "No of InCall buttons: " + buttonCount + " canVideoCall: " + canVideoCall);
-
-        // Show overflow menu if number of buttons is greater than 5.
-        final boolean showOverflowMenu =
-                buttonCount > BUTTON_THRESOLD_TO_DISPLAY_OVERFLOW_MENU;
-        final boolean isVideoOverflowScenario = canVideoCall && showOverflowMenu;
-        final boolean isOverflowScenario = !canVideoCall && showOverflowMenu;
-
-        if (isVideoOverflowScenario) {
-            ui.showHoldButton(false);
-            ui.showSwapButton(false);
-            ui.showAddCallButton(false);
-            ui.showMergeButton(false);
-            ui.showManageConferenceVideoCallButton(false);
-
-            ui.configureOverflowMenu(
-                    showMergeOption,
-                    showAddCallOption /* showAddMenuOption */,
-                    showHoldOption && enableHoldOption /* showHoldMenuOption */,
-                    showSwapOption,
-                    showManageVideoCallConferenceOption);
-            ui.showOverflowButton(true);
-        } else {
-            if (isOverflowScenario) {
-                ui.showAddCallButton(false);
-                ui.showMergeButton(false);
-                ui.showManageConferenceVideoCallButton(false);
-
-                ui.configureOverflowMenu(
-                        showMergeOption,
-                        showAddCallOption /* showAddMenuOption */,
-                        false /* showHoldMenuOption */,
-                        false /* showSwapMenuOption */,
-                        showManageVideoCallConferenceOption);
-            } else {
-                ui.showMergeButton(showMergeOption);
-                ui.showAddCallButton(showAddCallOption);
-                ui.showManageConferenceVideoCallButton(showManageVideoCallConferenceOption);
-            }
-
-            ui.showOverflowButton(isOverflowScenario);
-            ui.showHoldButton(showHoldOption);
-            ui.enableHold(enableHoldOption);
-            ui.showSwapButton(showSwapOption);
-        }
+        ui.updateButtonStates();
     }
 
     public void refreshMuteState() {
@@ -515,34 +427,24 @@
     }
 
     public interface CallButtonUi extends Ui {
+        void showButton(int buttonId, boolean show);
+        void enableButton(int buttonId, boolean enable);
         void setEnabled(boolean on);
         void setMute(boolean on);
-        void enableMute(boolean enabled);
-        void showAudioButton(boolean show);
-        void showChangeToVoiceButton(boolean show);
-        void showDialpadButton(boolean show);
         void setHold(boolean on);
-        void showHoldButton(boolean show);
-        void enableHold(boolean enabled);
-        void showSwapButton(boolean show);
-        void showChangeToVideoButton(boolean show);
-        void enableChangeToVideoButton(boolean enable);
-        void showSwitchCameraButton(boolean show);
-        void setSwitchCameraButton(boolean isBackFacingCamera);
-        void showAddCallButton(boolean show);
-        void showManageConferenceVideoCallButton(boolean show);
-        void showMergeButton(boolean show);
-        void showPauseVideoButton(boolean show);
-        void setPauseVideoButton(boolean isPaused);
-        void showOverflowButton(boolean show);
+        void setCameraSwitched(boolean isBackFacingCamera);
+        void setVideoPaused(boolean isPaused);
+        void setAudio(int mode);
+        void setSupportedAudio(int mask);
         void displayDialpad(boolean on, boolean animate);
         void displayModifyCallOptions();
         boolean isDialpadVisible();
-        void setAudio(int mode);
-        void setSupportedAudio(int mask);
-        void configureOverflowMenu(boolean showMergeMenuOption, boolean showAddMenuOption,
-                boolean showHoldMenuOption, boolean showSwapMenuOption,
-                boolean showManageConferenceVideoCallOption);
+
+        /**
+         * Once showButton() has been called on each of the individual buttons in the UI, call
+         * this to configure the overflow menu appropriately.
+         */
+        void updateButtonStates();
         Context getContext();
     }
 
@@ -551,6 +453,6 @@
         if (getUi() == null) {
             return;
         }
-        getUi().setSwitchCameraButton(!isUsingFrontFacingCamera);
+        getUi().setCameraSwitched(!isUsingFrontFacingCamera);
     }
 }
diff --git a/InCallUI/src/com/android/incallui/CallCardFragment.java b/InCallUI/src/com/android/incallui/CallCardFragment.java
index 7420ba9..abe4607 100644
--- a/InCallUI/src/com/android/incallui/CallCardFragment.java
+++ b/InCallUI/src/com/android/incallui/CallCardFragment.java
@@ -28,6 +28,7 @@
 import android.content.res.Configuration;
 import android.graphics.drawable.AnimationDrawable;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.GradientDrawable;
 import android.os.Bundle;
 import android.os.Trace;
 import android.telecom.DisconnectCause;
@@ -96,6 +97,7 @@
     private View mSecondaryCallProviderInfo;
     private TextView mSecondaryCallProviderLabel;
     private View mSecondaryCallConferenceCallIcon;
+    private View mSecondaryCallVideoCallIcon;
     private View mProgressSpinner;
 
     private View mManageConferenceCallButton;
@@ -134,7 +136,7 @@
         mShrinkAnimationDuration = getResources().getInteger(R.integer.shrink_animation_duration);
         mVideoAnimationDuration = getResources().getInteger(R.integer.video_animation_duration);
         mFloatingActionButtonVerticalOffset = getResources().getDimensionPixelOffset(
-                R.dimen.floating_action_bar_vertical_offset);
+                R.dimen.floating_action_button_vertical_offset);
         mFabNormalDiameter = getResources().getDimensionPixelOffset(
                 R.dimen.end_call_floating_action_button_diameter);
         mFabSmallDiameter = getResources().getDimensionPixelOffset(
@@ -156,9 +158,8 @@
         Trace.beginSection(TAG + " onCreate");
         mTranslationOffset =
                 getResources().getDimensionPixelSize(R.dimen.call_card_anim_translate_y_offset);
-        final View view = inflater.inflate(R.layout.call_card_fragment, container, false);
-        Trace.endSection();
-        return view;
+
+        return inflater.inflate(R.layout.call_card_fragment, container, false);
     }
 
     @Override
@@ -285,17 +286,7 @@
                 float videoViewTranslation = 0f;
 
                 // Translate the call card to its pre-animation state.
-                if (mIsLandscape) {
-                    float translationX = mPrimaryCallCardContainer.getWidth();
-                    translationX *= isLayoutRtl ? 1 : -1;
-
-                    mPrimaryCallCardContainer.setTranslationX(visible ? translationX : 0);
-
-                    if (visible) {
-                        videoViewTranslation = videoView.getWidth() / 2 - spaceBesideCallCard / 2;
-                        videoViewTranslation *= isLayoutRtl ? -1 : 1;
-                    }
-                } else {
+                if (!mIsLandscape){
                     mPrimaryCallCardContainer.setTranslationY(visible ?
                             -mPrimaryCallCardContainer.getHeight() : 0);
 
@@ -458,7 +449,7 @@
 
     @Override
     public void setSecondary(boolean show, String name, boolean nameIsNumber, String label,
-            String providerLabel, boolean isConference) {
+            String providerLabel, boolean isConference, boolean isVideoCall) {
 
         if (show != mSecondaryCallInfo.isShown()) {
             updateFabPositionForSecondaryCallInfo();
@@ -469,6 +460,7 @@
             showAndInitializeSecondaryCallInfo(hasProvider);
 
             mSecondaryCallConferenceCallIcon.setVisibility(isConference ? View.VISIBLE : View.GONE);
+            mSecondaryCallVideoCallIcon.setVisibility(isVideoCall ? View.VISIBLE : View.GONE);
 
             mSecondaryCallName.setText(nameIsNumber
                     ? PhoneNumberUtils.getPhoneTtsSpannable(name)
@@ -760,6 +752,8 @@
             mSecondaryCallName = (TextView) getView().findViewById(R.id.secondaryCallName);
             mSecondaryCallConferenceCallIcon =
                     getView().findViewById(R.id.secondaryCallConferenceCallIcon);
+            mSecondaryCallVideoCallIcon =
+                    getView().findViewById(R.id.secondaryCallVideoCallIcon);
         }
 
         if (mSecondaryCallProviderLabel == null && hasProvider) {
@@ -849,7 +843,13 @@
             return;
         }
 
-        mPrimaryCallCardContainer.setBackgroundColor(themeColors.mPrimaryColor);
+        if (getResources().getBoolean(R.bool.is_layout_landscape)) {
+            final GradientDrawable drawable =
+                    (GradientDrawable) mPrimaryCallCardContainer.getBackground();
+            drawable.setColor(themeColors.mPrimaryColor);
+        } else {
+            mPrimaryCallCardContainer.setBackgroundColor(themeColors.mPrimaryColor);
+        }
         mCallButtonsContainer.setBackgroundColor(themeColors.mPrimaryColor);
 
         mCurrentThemeColors = themeColors;
@@ -963,8 +963,7 @@
             mAnimatorSet.cancel();
         }
 
-        mIsLandscape = getResources().getConfiguration().orientation
-                == Configuration.ORIENTATION_LANDSCAPE;
+        mIsLandscape = getResources().getBoolean(R.bool.is_layout_landscape);
 
         final ViewGroup parent = ((ViewGroup) mPrimaryCallCardContainer.getParent());
         final ViewTreeObserver observer = parent.getViewTreeObserver();
diff --git a/InCallUI/src/com/android/incallui/CallCardPresenter.java b/InCallUI/src/com/android/incallui/CallCardPresenter.java
index bddeea3..535ba3b 100644
--- a/InCallUI/src/com/android/incallui/CallCardPresenter.java
+++ b/InCallUI/src/com/android/incallui/CallCardPresenter.java
@@ -254,13 +254,11 @@
         }
 
         maybeShowManageConferenceCallButton();
+        maybeShowProgressSpinner();
 
-        final boolean enableEndCallButton = (Call.State.isConnectingOrConnected(callState)
-                || callState == Call.State.DISCONNECTING) &&
-                callState != Call.State.INCOMING && mPrimary != null;
         // Hide the end call button instantly if we're receiving an incoming call.
-        getUi().setEndCallButtonEnabled(
-                enableEndCallButton, callState != Call.State.INCOMING /* animate */);
+        getUi().setEndCallButtonEnabled(shouldShowEndCallButton(mPrimary, callState),
+                callState != Call.State.INCOMING /* animate */);
     }
 
     @Override
@@ -315,6 +313,13 @@
         getUi().showManageConferenceCallButton(shouldShowManageConference());
     }
 
+    private void maybeShowProgressSpinner() {
+        final boolean show = mPrimary != null && mPrimary.getSessionModificationState()
+                == Call.SessionModificationState.WAITING_FOR_RESPONSE
+                && mPrimary.getState() == Call.State.ACTIVE;
+        getUi().setProgressSpinnerVisible(show);
+    }
+
     /**
      * Determines if the manage conference button should be visible, based on the current primary
      * call.
@@ -531,7 +536,8 @@
 
         if (mSecondary == null) {
             // Clear the secondary display info.
-            ui.setSecondary(false, null, false, null, null, false /* isConference */);
+            ui.setSecondary(false, null, false, null, null, false /* isConference */,
+                    false /* isVideoCall */);
             return;
         }
 
@@ -542,7 +548,8 @@
                     false /* nameIsNumber */,
                     null /* label */,
                     getCallProviderLabel(mSecondary),
-                    true /* isConference */);
+                    true /* isConference */,
+                    mSecondary.isVideoCall(mContext));
         } else if (mSecondaryContactInfo != null) {
             Log.d(TAG, "updateSecondaryDisplayInfo() " + mSecondaryContactInfo);
             String name = getNameForCall(mSecondaryContactInfo);
@@ -553,10 +560,12 @@
                     nameIsNumber,
                     mSecondaryContactInfo.label,
                     getCallProviderLabel(mSecondary),
-                    false /* isConference */);
+                    false /* isConference */,
+                    mSecondary.isVideoCall(mContext));
         } else {
             // Clear the secondary display info.
-            ui.setSecondary(false, null, false, null, null, false /* isConference */);
+            ui.setSecondary(false, null, false, null, null, false /* isConference */,
+                    false /* isVideoCall */);
         }
     }
 
@@ -736,13 +745,27 @@
         return photo;
     }
 
+    private boolean shouldShowEndCallButton(Call primary, int callState) {
+        if (primary == null) {
+            return false;
+        }
+        if (!Call.State.isConnectingOrConnected(callState) || callState == Call.State.INCOMING) {
+            return false;
+        }
+        if (mPrimary.getSessionModificationState()
+                == Call.SessionModificationState.RECEIVED_UPGRADE_TO_VIDEO_REQUEST) {
+            return false;
+        }
+        return true;
+    }
+
     public interface CallCardUi extends Ui {
         void setVisible(boolean on);
         void setCallCardVisible(boolean visible);
         void setPrimary(String number, String name, boolean nameIsNumber, String label,
                 Drawable photo, boolean isSipCall);
         void setSecondary(boolean show, String name, boolean nameIsNumber, String label,
-                String providerLabel, boolean isConference);
+                String providerLabel, boolean isConference, boolean isVideoCall);
         void setCallState(int state, int videoState, int sessionModificationState,
                 DisconnectCause disconnectCause, String connectionLabel,
                 Drawable connectionIcon, String gatewayNumber, boolean isWifi);
diff --git a/InCallUI/src/com/android/incallui/DialpadFragment.java b/InCallUI/src/com/android/incallui/DialpadFragment.java
index 90610a8..f185c54 100644
--- a/InCallUI/src/com/android/incallui/DialpadFragment.java
+++ b/InCallUI/src/com/android/incallui/DialpadFragment.java
@@ -422,7 +422,7 @@
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
             Bundle savedInstanceState) {
         final View parent = inflater.inflate(
-                com.android.incallui.R.layout.incall_dialpad_fragment, container, false);
+                R.layout.incall_dialpad_fragment, container, false);
         mDialpadView = (DialpadView) parent.findViewById(R.id.dialpad_view);
         mDialpadView.setCanDigitsBeEdited(false);
         mDialpadView.setBackgroundResource(R.color.incall_dialpad_background);
diff --git a/InCallUI/src/com/android/incallui/GlowPadWrapper.java b/InCallUI/src/com/android/incallui/GlowPadWrapper.java
index 584ce65..58a5f30 100644
--- a/InCallUI/src/com/android/incallui/GlowPadWrapper.java
+++ b/InCallUI/src/com/android/incallui/GlowPadWrapper.java
@@ -128,14 +128,6 @@
                 mAnswerListener.onAnswer(VideoProfile.VideoState.BIDIRECTIONAL, getContext());
                 mTargetTriggered = true;
                 break;
-            case R.drawable.ic_lockscreen_answer_tx_video:
-                mAnswerListener.onAnswer(VideoProfile.VideoState.TX_ENABLED, getContext());
-                mTargetTriggered = true;
-                break;
-            case R.drawable.ic_lockscreen_answer_rx_video:
-                mAnswerListener.onAnswer(VideoProfile.VideoState.RX_ENABLED, getContext());
-                mTargetTriggered = true;
-                break;
             case R.drawable.ic_toolbar_video_off:
                 InCallPresenter.getInstance().declineUpgradeRequest(getContext());
                 mTargetTriggered = true;
diff --git a/InCallUI/src/com/android/incallui/InCallActivity.java b/InCallUI/src/com/android/incallui/InCallActivity.java
index 1283177..5ecb96e 100644
--- a/InCallUI/src/com/android/incallui/InCallActivity.java
+++ b/InCallUI/src/com/android/incallui/InCallActivity.java
@@ -473,16 +473,11 @@
         return false;
     }
 
-    @Override
-    public void onConfigurationChanged(Configuration config) {
-        InCallPresenter.getInstance().getProximitySensor().onConfigurationChanged(config);
-        Log.d(this, "onConfigurationChanged "+config.orientation);
-
-        doOrientationChanged(config.orientation);
-        super.onConfigurationChanged(config);
-    }
-
-
+    /**
+     * Handles changes in device orientation.
+     *
+     * @param orientation The new device orientation.
+     */
     private void doOrientationChanged(int orientation) {
         Log.d(this, "doOrientationChanged prevOrientation=" + sCurrentOrientation +
                 " newOrientation=" + orientation);
diff --git a/InCallUI/src/com/android/incallui/InCallPresenter.java b/InCallUI/src/com/android/incallui/InCallPresenter.java
index fdf1933..d5aa0e5 100644
--- a/InCallUI/src/com/android/incallui/InCallPresenter.java
+++ b/InCallUI/src/com/android/incallui/InCallPresenter.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
+import android.content.res.Resources;
 import android.graphics.Point;
 import android.net.Uri;
 import android.os.Bundle;
@@ -179,7 +180,7 @@
 
     /**
      * When configuration changes Android kills the current activity and starts a new one.
-     * The flag is used to check if full clean up is necessary (activity is stopped and new 
+     * The flag is used to check if full clean up is necessary (activity is stopped and new
      * activity won't be started), or if a new activity will be started right after the current one
      * is destroyed, and therefore no need in release all resources.
      */
@@ -1446,7 +1447,13 @@
             return;
         }
 
-        mInCallActivity.getWindow().setStatusBarColor(mThemeColors.mSecondaryColor);
+        final Resources resources = mInCallActivity.getResources();
+        if (resources.getBoolean(R.bool.is_layout_landscape)) {
+            mInCallActivity.getWindow().setStatusBarColor(
+                    resources.getColor(R.color.statusbar_background_color));
+        } else {
+            mInCallActivity.getWindow().setStatusBarColor(mThemeColors.mSecondaryColor);
+        }
     }
 
     /**
diff --git a/InCallUI/src/com/android/incallui/InCallVideoCallListener.java b/InCallUI/src/com/android/incallui/InCallVideoCallListener.java
index df9dfdc..741b8d6 100644
--- a/InCallUI/src/com/android/incallui/InCallVideoCallListener.java
+++ b/InCallUI/src/com/android/incallui/InCallVideoCallListener.java
@@ -87,8 +87,10 @@
             boolean isVideoCall = VideoProfile.VideoState.isVideo(responseProfile.getVideoState());
             if (modifySucceeded && isVideoCall) {
                 InCallVideoCallListenerNotifier.getInstance().upgradeToVideoSuccess(mCall);
-            } else if (!modifySucceeded) {
+            } else if (!modifySucceeded && isVideoCall) {
                 InCallVideoCallListenerNotifier.getInstance().upgradeToVideoFail(status, mCall);
+            } else if (modifySucceeded && !isVideoCall) {
+                InCallVideoCallListenerNotifier.getInstance().downgradeToAudio(mCall);
             }
         } else {
             Log.d(this, "onSessionModifyResponseReceived request and response Profiles are null");
diff --git a/InCallUI/src/com/android/incallui/VideoCallFragment.java b/InCallUI/src/com/android/incallui/VideoCallFragment.java
index d0ef13a..fb29c9c 100644
--- a/InCallUI/src/com/android/incallui/VideoCallFragment.java
+++ b/InCallUI/src/com/android/incallui/VideoCallFragment.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.graphics.Matrix;
 import android.graphics.Point;
 import android.graphics.SurfaceTexture;
 import android.os.Bundle;
@@ -90,11 +91,6 @@
     private View mVideoViews;
 
     /**
-     * {@code True} when the entering the activity again after a restart due to orientation change.
-     */
-    private boolean mIsActivityRestart;
-
-    /**
      * {@code True} when the layout of the activity has been completed.
      */
     private boolean mIsLayoutComplete = false;
@@ -404,12 +400,20 @@
                 Log.e(this, "onClick: Presenter is null.");
             }
         }
+
+        /**
+         * Returns the dimensions of the surface.
+         *
+         * @return The dimensions of the surface.
+         */
+        public Point getSurfaceDimensions() {
+            return new Point(mWidth, mHeight);
+        }
     };
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        mIsActivityRestart = sVideoSurfacesInUse;
     }
 
     /**
@@ -421,21 +425,12 @@
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
 
-        mIsLandscape = getResources().getConfiguration().orientation
-                == Configuration.ORIENTATION_LANDSCAPE;
+        mIsLandscape = getResources().getBoolean(R.bool.is_layout_landscape);
 
         Log.d(this, "onActivityCreated: IsLandscape=" + mIsLandscape);
         getPresenter().init(getActivity());
     }
 
-    /**
-     * Handles creation of the fragment view.
-     *
-     * @param inflater The inflater.
-     * @param container The view group containing the fragment.
-     * @param savedInstanceState The saved instance state.
-     * @return
-     */
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
             Bundle savedInstanceState) {
@@ -447,36 +442,15 @@
     }
 
     /**
-     * Centers the display view vertically for portrait orientation, and horizontally for
-     * lanscape orientations.  The view is centered within the available space not occupied by
-     * the call card.
+     * Centers the display view vertically for portrait orientations. The view is centered within
+     * the available space not occupied by the call card. This is a no-op for landscape mode.
      *
      * @param displayVideo The video view to center.
      */
     private void centerDisplayView(View displayVideo) {
-        // In a lansdcape layout we need to ensure we horizontally center the view based on whether
-        // the layout is left-to-right or right-to-left.
-        // In a left-to-right locale, the space for the video view is to the right of the call card
-        // so we need to translate it in the +X direction.
-        // In a right-to-left locale, the space for the video view is to the left of the call card
-        // so we need to translate it in the -X direction.
-        final boolean isLayoutRtl = InCallPresenter.isRtl();
-
-        ViewGroup.LayoutParams params = displayVideo.getLayoutParams();
-        float spaceBesideCallCard = InCallPresenter.getInstance().getSpaceBesideCallCard();
-        Log.d(this, "centerDisplayView: IsLandscape= " + mIsLandscape + " Layout width: " +
-                params.width + " height: " + params.height + " spaceBesideCallCard: "
-                + spaceBesideCallCard);
-        if (mIsLandscape) {
-            float videoViewTranslation = params.width / 2
-                    - spaceBesideCallCard / 2;
-            if (isLayoutRtl) {
-                displayVideo.setTranslationX(-videoViewTranslation);
-            } else {
-                displayVideo.setTranslationX(videoViewTranslation);
-            }
-        } else {
-            float videoViewTranslation = params.height / 2
+        if (!mIsLandscape) {
+            float spaceBesideCallCard = InCallPresenter.getInstance().getSpaceBesideCallCard();
+            float videoViewTranslation = displayVideo.getHeight() / 2
                     - spaceBesideCallCard / 2;
             displayVideo.setTranslationY(videoViewTranslation);
         }
@@ -701,12 +675,6 @@
         }
     }
 
-    @Override
-    public boolean isActivityRestart() {
-        Log.d(this, "isActivityRestart " + mIsActivityRestart);
-        return mIsActivityRestart;
-    }
-
     /**
      * @return {@code True} if the display video surface has been created.
      */
@@ -767,12 +735,12 @@
             params.height = height;
             preview.setLayoutParams(params);
 
-            int rotation = InCallPresenter.toRotationAngle(getCurrentRotation());
-            int rotationAngle = 360 - rotation;
-            preview.setRotation(rotationAngle);
-            Log.d(this, "setPreviewSize: rotation=" + rotation +
-                    " rotationAngle=" + rotationAngle);
-
+            // The width and height are interchanged outside of this method based on the current
+            // orientation, so we can transform using "width", which will be either the width or
+            // the height.
+            Matrix transform = new Matrix();
+            transform.setScale(-1, 1, width/2, 0);
+            preview.setTransform(transform);
         }
     }
 
@@ -879,6 +847,19 @@
     }
 
     /**
+     * Determines the size of the preview surface.
+     *
+     * @return {@link Point} specifying the width and height of the preview surface.
+     */
+    @Override
+    public Point getPreviewSize() {
+        if (sPreviewSurface == null) {
+            return null;
+        }
+        return sPreviewSurface.getSurfaceDimensions();
+    }
+
+    /**
      * Inflates the {@link ViewStub} containing the incoming and outgoing surfaces, if necessary,
      * and creates {@link VideoCallSurface} instances to track the surfaces.
      */
diff --git a/InCallUI/src/com/android/incallui/VideoCallPresenter.java b/InCallUI/src/com/android/incallui/VideoCallPresenter.java
index 33b7d54..16a6e48 100644
--- a/InCallUI/src/com/android/incallui/VideoCallPresenter.java
+++ b/InCallUI/src/com/android/incallui/VideoCallPresenter.java
@@ -61,7 +61,7 @@
  * When downgrading to an audio-only video state, the {@code VideoCallPresenter} nulls both
  * surfaces.
  */
-public class VideoCallPresenter extends Presenter<VideoCallPresenter.VideoCallUi>  implements
+public class VideoCallPresenter extends Presenter<VideoCallPresenter.VideoCallUi> implements
         IncomingCallListener, InCallOrientationListener, InCallStateListener,
         InCallDetailsListener, SurfaceChangeListener, VideoEventListener,
         InCallVideoCallListenerNotifier.SessionModificationListener {
@@ -163,7 +163,6 @@
      */
     private int mCurrentCallSubstate;
 
-
     /** Handler which resets request state to NO_REQUEST after an interval. */
     private Handler mSessionModificationResetHandler;
     private static final long SESSION_MODIFICATION_RESET_DELAY_MS = 3000;
@@ -335,11 +334,11 @@
         toggleFullScreen();
     }
 
-
     /**
      * Handles incoming calls.
      *
-     * @param state The in call state.
+     * @param oldState The old in call state.
+     * @param newState The new in call state.
      * @param call The call.
      */
     @Override
@@ -410,12 +409,14 @@
                 + " hasVideoStateChanged=" +
                 hasVideoStateChanged + " isVideoMode=" + isVideoMode());
 
-        if (!hasVideoStateChanged) { return;}
+        if (!hasVideoStateChanged) {
+            return;
+        }
 
         updateCameraSelection(call);
 
         if (isVideoCall) {
-            enterVideoMode(call.getVideoCall(), call.getVideoState());
+            enterVideoMode(call);
         } else if (isVideoMode()) {
             exitVideoMode();
         }
@@ -443,6 +444,9 @@
         if (!Objects.equals(prevCameraId, newCameraId) && CallUtils.isActiveVideoCall(call)) {
             enableCamera(call.getVideoCall(), true);
         }
+
+        // Make sure we hide or show the video UI if needed.
+        showVideoUi(call.getVideoState(), call.getState());
     }
 
     private void checkForCallSubstateChange(Call call) {
@@ -483,7 +487,7 @@
             Log.d(this, "onPrimaryCallChanged: Entering video mode...");
 
             updateCameraSelection(newPrimaryCall);
-            enterVideoMode(newPrimaryCall.getVideoCall(), newPrimaryCall.getVideoState());
+            enterVideoMode(newPrimaryCall);
         }
     }
 
@@ -534,6 +538,11 @@
         checkForVideoCallChange(call);
         checkForVideoStateChange(call);
         checkForCallStateChange(call);
+        checkForOrientationAllowedChange(call);
+    }
+
+    private void checkForOrientationAllowedChange(Call call) {
+        InCallPresenter.getInstance().setInCallAllowsOrientationChange(CallUtils.isVideoCall(call));
     }
 
     /**
@@ -573,7 +582,7 @@
         }
 
         if (CallUtils.isVideoCall(call) && hasChanged) {
-            enterVideoMode(call.getVideoCall(), call.getVideoState());
+            enterVideoMode(call);
         }
     }
 
@@ -590,7 +599,10 @@
      * Enters video mode by showing the video surfaces and making other adjustments (eg. audio).
      * TODO(vt): Need to adjust size and orientation of preview surface here.
      */
-    private void enterVideoMode(VideoCall videoCall, int newVideoState) {
+    private void enterVideoMode(Call call) {
+        VideoCall videoCall = call.getVideoCall();
+        int newVideoState = call.getVideoState();
+
         Log.d(this, "enterVideoMode videoCall= " + videoCall + " videoState: " + newVideoState);
         VideoCallUi ui = getUi();
         if (ui == null) {
@@ -598,8 +610,7 @@
             return;
         }
 
-        showVideoUi(newVideoState);
-        InCallPresenter.getInstance().setInCallAllowsOrientationChange(true);
+        showVideoUi(newVideoState, call.getState());
 
         // Communicate the current camera to telephony and make a request for the camera
         // capabilities.
@@ -688,9 +699,7 @@
     private void exitVideoMode() {
         Log.d(this, "exitVideoMode");
 
-        InCallPresenter.getInstance().setInCallAllowsOrientationChange(false);
-
-        showVideoUi(VideoProfile.VideoState.AUDIO_ONLY);
+        showVideoUi(VideoProfile.VideoState.AUDIO_ONLY, Call.State.ACTIVE);
         enableCamera(mVideoCall, false);
 
         Log.d(this, "exitVideoMode mIsFullScreen: " + mIsFullScreen);
@@ -702,21 +711,28 @@
     }
 
     /**
-     * Show video Ui depends on video state.
+     * Based on the current {@link VideoProfile.VideoState} and {@code CallState}, show or hide the
+     * incoming and outgoing video surfaces.  The outgoing video surface is shown any time video
+     * is transmitting.  The incoming video surface is shown whenever the video is un-paused and
+     * active.
+     *
+     * @param videoState The video state.
+     * @param callState The call state.
      */
-    private void showVideoUi(int videoState) {
+    private void showVideoUi(int videoState, int callState) {
         VideoCallUi ui = getUi();
         if (ui == null) {
             Log.e(this, "showVideoUi, VideoCallUi is null returning");
             return;
         }
-
+        boolean isPaused = VideoProfile.VideoState.isPaused(videoState);
+        boolean isCallActive = callState == Call.State.ACTIVE;
         if (VideoProfile.VideoState.isBidirectional(videoState)) {
-            ui.showVideoViews(true, true);
+            ui.showVideoViews(true, !isPaused && isCallActive);
         } else if (VideoProfile.VideoState.isTransmissionEnabled(videoState)) {
             ui.showVideoViews(true, false);
         } else if (VideoProfile.VideoState.isReceptionEnabled(videoState)) {
-            ui.showVideoViews(false, true);
+            ui.showVideoViews(false, !isPaused && isCallActive);
         } else {
             ui.hideVideoUi();
         }
@@ -813,14 +829,7 @@
         }
 
         mPreviewSurfaceState = PreviewSurfaceState.CAPABILITIES_RECEIVED;
-        ui.setPreviewSurfaceSize(width, height);
-
-        // Configure the preview surface to the correct aspect ratio.
-        float aspectRatio = 1.0f;
-        if (width > 0 && height > 0) {
-            aspectRatio = (float) width / (float) height;
-        }
-        setPreviewSize(mDeviceOrientation, aspectRatio);
+        changePreviewDimensions(width, height);
 
         // Check if the preview surface is ready yet; if it is, set it on the {@code VideoCall}.
         // If it not yet ready, it will be set when when creation completes.
@@ -831,6 +840,32 @@
     }
 
     /**
+     * Changes the dimensions of the preview surface.
+     *
+     * @param width The new width.
+     * @param height The new height.
+     */
+    private void changePreviewDimensions(int width, int height) {
+        VideoCallUi ui = getUi();
+        if (ui == null) {
+            return;
+        }
+
+        // Resize the surface used to display the preview video
+        ui.setPreviewSurfaceSize(width, height);
+
+        // Configure the preview surface to the correct aspect ratio.
+        float aspectRatio = 1.0f;
+        if (width > 0 && height > 0) {
+            aspectRatio = (float) width / (float) height;
+        }
+
+        // Resize the textureview housing the preview video and rotate it appropriately based on
+        // the device orientation
+        setPreviewSize(mDeviceOrientation, aspectRatio);
+    }
+
+    /**
      * Called when call session event is raised.
      *
      * @param event The call session event.
@@ -869,8 +904,11 @@
      */
     @Override
     public void onDeviceOrientationChanged(int orientation) {
-        Log.d(this, "onDeviceOrientationChanged: orientation=" + orientation);
         mDeviceOrientation = orientation;
+        Point previewDimensions = getUi().getPreviewSize();
+        Log.d(this, "onDeviceOrientationChanged: orientation=" + orientation + " size: "
+                + previewDimensions);
+        changePreviewDimensions(previewDimensions.x, previewDimensions.y);
     }
 
     @Override
@@ -934,6 +972,7 @@
 
     @Override
     public void onDowngradeToAudio(Call call) {
+        call.setSessionModificationState(Call.SessionModificationState.NO_REQUEST);
         // exit video mode
         exitVideoMode();
     }
@@ -1097,8 +1136,8 @@
         void setCallDataUsage(Context context, long dataUsage);
         void displayCallSessionEvent(int event);
         Point getScreenSize();
+        Point getPreviewSize();
         void cleanupSurfaces();
-        boolean isActivityRestart();
         void showCallSubstateChanged(int callSubstate);
     }
 }
diff --git a/InCallUI/src/com/android/incallui/VideoPauseController.java b/InCallUI/src/com/android/incallui/VideoPauseController.java
index 727780e..dd47c7f 100644
--- a/InCallUI/src/com/android/incallui/VideoPauseController.java
+++ b/InCallUI/src/com/android/incallui/VideoPauseController.java
@@ -35,15 +35,19 @@
 import com.android.incallui.InCallPresenter.InCallStateListener;
 import com.android.incallui.InCallPresenter.IncomingCallListener;
 import com.android.incallui.InCallVideoCallListenerNotifier.SessionModificationListener;
-import com.android.internal.util.Preconditions;
+import com.google.common.base.Preconditions;
 
 /**
- * The class is responsible for generating video pause/resume request.
+ * This class is responsible for generating video pause/resume requests when the InCall UI is sent
+ * to the background and subsequently brought back to the foreground.
  */
 class VideoPauseController implements InCallStateListener, IncomingCallListener,
         SessionModificationListener {
-    private static final String TAG = "VideoCallPauseController:";
+    private static final String TAG = "VideoPauseController:";
 
+    /**
+     * Keeps track of the current active/foreground call.
+     */
     private class CallContext {
         public CallContext(Call call) {
             Preconditions.checkNotNull(call);
@@ -53,7 +57,6 @@
         public void update(Call call) {
             mCall = Preconditions.checkNotNull(call);
             mState = call.getState();
-            mId = call.getId();
             mVideoState = call.getVideoState();
         }
 
@@ -61,17 +64,13 @@
             return mState;
         }
 
-        public String getId() {
-            return mId;
-        }
-
         public int getVideoState() {
             return mVideoState;
         }
 
         public String toString() {
-            return String.format("CallContext {CallId=%s, State=%s, VideoState=",
-                    mId, mState, mVideoState);
+            return String.format("CallContext {CallId=%s, State=%s, VideoState=%d}",
+                    mCall.getId(), mState, mVideoState);
         }
 
         public Call getCall() {
@@ -79,7 +78,6 @@
         }
 
         private int mState = State.INVALID;
-        private String mId;
         private int mVideoState;
         private Call mCall;
     }
@@ -87,27 +85,21 @@
     private InCallPresenter mInCallPresenter;
     private static VideoPauseController sVideoPauseController;
 
-    private CallContext mPrimaryCallContext = null; // Context of primary call, if any.
-    private boolean mIsInBackground = false; // True if UI is not visible, false otherwise.
-    private int mVideoPauseMode = VIDEO_PAUSE_MODE_DISABLED;
+    /**
+     * The current call context, if applicable.
+     */
+    private CallContext mPrimaryCallContext = null;
 
     /**
-     * Stores current video pause mode.
-     * 0 - Video Pause is disabled.
-     * 1 - Video Pause is enabled.
+     * Tracks whether the application is in the background. {@code True} if the application is in
+     * the background, {@code false} otherwise.
      */
-    private static final String PROPERTY_VIDEO_PAUSE_MODE = "persist.radio.videopause.mode";
-    private static int VIDEO_PAUSE_MODE_DISABLED = 0;
-    private static int VIDEO_PAUSE_MODE_ENABLED = 1;
+    private boolean mIsInBackground = false;
 
-    private VideoPauseController() {
-        mVideoPauseMode = SystemProperties.getInt(PROPERTY_VIDEO_PAUSE_MODE,
-                VIDEO_PAUSE_MODE_DISABLED);
-        if (mVideoPauseMode != VIDEO_PAUSE_MODE_ENABLED) { // Validate the mode before using.
-            mVideoPauseMode = VIDEO_PAUSE_MODE_DISABLED;
-        }
-    }
-
+    /**
+     * Singleton accessor for the {@link VideoPauseController}.
+     * @return Singleton instance of the {@link VideoPauseController}.
+     */
     /*package*/
     static synchronized VideoPauseController getInstance() {
         if (sVideoPauseController == null) {
@@ -116,23 +108,25 @@
         return sVideoPauseController;
     }
 
+    /**
+     * Configures the {@link VideoPauseController} to listen to call events.  Configured via the
+     * {@link com.android.incallui.InCallPresenter}.
+     *
+     * @param inCallPresenter The {@link com.android.incallui.InCallPresenter}.
+     */
     public void setUp(InCallPresenter inCallPresenter) {
-        if (!isVideoPausedEnabled()) {
-            return;
-        }
-
-        log("setUp...");
+        log("setUp");
         mInCallPresenter = Preconditions.checkNotNull(inCallPresenter);
         mInCallPresenter.addListener(this);
         mInCallPresenter.addIncomingCallListener(this);
         InCallVideoCallListenerNotifier.getInstance().addSessionModificationListener(this);
     }
 
+    /**
+     * Cleans up the {@link VideoPauseController} by removing all listeners and clearing its
+     * internal state.  Called from {@link com.android.incallui.InCallPresenter}.
+     */
     public void tearDown() {
-        if (!isVideoPausedEnabled()) {
-            return;
-        }
-
         log("tearDown...");
         InCallVideoCallListenerNotifier.getInstance().removeSessionModificationListener(this);
         mInCallPresenter.removeListener(this);
@@ -140,6 +134,9 @@
         clear();
     }
 
+    /**
+     * Clears the internal state for the {@link VideoPauseController}.
+     */
     private void clear() {
         mInCallPresenter = null;
         mPrimaryCallContext = null;
@@ -147,8 +144,11 @@
     }
 
     /**
-     * The function gets called when call state changes.
-     * @param state Phone state.
+     * Handles changes in the {@link InCallState}.  Triggers pause and resumption of video for the
+     * current foreground call.
+     *
+     * @param oldState The previous {@link InCallState}.
+     * @param newState The current {@link InCallState}.
      * @param callList List of current call.
      */
     @Override
@@ -179,7 +179,7 @@
             return;
         }
 
-        if (isOutgoing(mPrimaryCallContext) && canVideoPause && mIsInBackground) {
+        if (isDialing(mPrimaryCallContext) && canVideoPause && mIsInBackground) {
             // Bring UI to foreground if outgoing request becomes active while UI is in
             // background.
             bringToForeground();
@@ -192,6 +192,15 @@
         updatePrimaryCallContext(call);
     }
 
+    /**
+     * Handles a change to the primary call.
+     * <p>
+     * Reject incoming or hangup dialing call: Where the previous call was an incoming call or a
+     * call in dialing state, resume the new primary call.
+     * Call swap: Where the new primary call is incoming, pause video on the previous primary call.
+     *
+     * @param call The new primary call.
+     */
     private void onPrimaryCallChanged(Call call) {
         log("onPrimaryCallChanged: New call = " + call);
         log("onPrimaryCallChanged: Old call = " + mPrimaryCallContext);
@@ -200,25 +209,26 @@
         Preconditions.checkState(!areSame(call, mPrimaryCallContext));
         final boolean canVideoPause = CallUtils.canVideoPause(call);
 
-        if (isWaitingCall(mPrimaryCallContext) && canVideoPause && !mIsInBackground) {
-            // Send resume request for the active call, if user rejects incoming
-            // call and UI is in foreground.
+        if ((isIncomingCall(mPrimaryCallContext) || isDialing(mPrimaryCallContext))
+                && canVideoPause && !mIsInBackground) {
+            // Send resume request for the active call, if user rejects incoming call or ends
+            // dialing call and UI is in the foreground.
             sendRequest(call, true);
-        } else if (isWaitingCall(call) && canVideoPause(mPrimaryCallContext)) {
+        } else if (isIncomingCall(call) && canVideoPause(mPrimaryCallContext)) {
             // Send pause request if there is an active video call, and we just received a new
             // incoming call.
             sendRequest(mPrimaryCallContext.getCall(), false);
-        } else if (isOutgoing(mPrimaryCallContext) && canVideoPause && !mIsInBackground) {
-            // Send resume request for the active call, if user ends outgoing call
-            // and UI is in foreground.
-            sendRequest(call, true);
         }
 
         updatePrimaryCallContext(call);
     }
 
     /**
-     * The function gets called when InCallUI receives a new incoming call.
+     * Handles new incoming calls by triggering a change in the primary call.
+     *
+     * @param oldState the old {@link InCallState}.
+     * @param newState the new {@link InCallState}.
+     * @param call the incoming call.
      */
     @Override
     public void onIncomingCall(InCallState oldState, InCallState newState, Call call) {
@@ -231,6 +241,11 @@
         onPrimaryCallChanged(call);
     }
 
+    /**
+     * Caches a reference to the primary call and stores its previous state.
+     *
+     * @param call The new primary call.
+     */
     private void updatePrimaryCallContext(Call call) {
         if (call == null) {
             mPrimaryCallContext = null;
@@ -246,43 +261,67 @@
      * @param showing true if UI is in the foreground, false otherwise.
      */
     public void onUiShowing(boolean showing) {
-        if (!isVideoPausedEnabled() || mInCallPresenter == null) {
+        // Only send pause/unpause requests if we are in the INCALL state.
+        if (mInCallPresenter == null || mInCallPresenter.getInCallState() != InCallState.INCALL) {
             return;
         }
 
-        final boolean notify = mInCallPresenter.getInCallState() == InCallState.INCALL;
         if (showing) {
-            onResume(notify);
+            onResume();
         } else {
-            onPause(notify);
+            onPause();
         }
     }
 
+    /**
+     * Handles requests to upgrade to video.
+     *
+     * @param call The call the request was received for.
+     * @param videoState The video state that the request wants to upgrade to.
+     */
     @Override
     public void onUpgradeToVideoRequest(Call call, int videoState) {
+        // Not used.
     }
 
+    /**
+     * Handles successful upgrades to video.
+     * @param call The call the request was successful for.
+     */
     @Override
     public void onUpgradeToVideoSuccess(Call call) {
+        // Not used.
     }
 
+    /**
+     * Handles a failure to upgrade a call to video.
+     *
+     * @param status The failure status.
+     * @param call The call the request was successful for.
+     */
     @Override
     public void onUpgradeToVideoFail(int status, Call call) {
         // TODO (ims-vt) Automatically bring in call ui to foreground.
     }
 
+    /**
+     * Handles a downgrade of a call to audio-only.
+     *
+     * @param call The call which was downgraded to audio-only.
+     */
     @Override
     public void onDowngradeToAudio(Call call) {
     }
 
     /**
-     * Called when UI becomes visible. This will send resume request for current video call, if any.
+     * Called when UI is brought to the foreground.  Sends a session modification request to resume
+     * the outgoing video.
      */
-    private void onResume(boolean notify) {
-        log("onResume: notify=" + notify);
+    private void onResume() {
+        log("onResume");
 
         mIsInBackground = false;
-        if (canVideoPause(mPrimaryCallContext) && notify) {
+        if (canVideoPause(mPrimaryCallContext)) {
             sendRequest(mPrimaryCallContext.getCall(), true);
         } else {
             log("onResume. Ignoring...");
@@ -290,13 +329,14 @@
     }
 
     /**
-     * Called when UI becomes invisible. This will send pause request for current video call, if any.
+     * Called when UI is sent to the background.  Sends a session modification request to pause the
+     * outgoing video.
      */
-    private void onPause(boolean notify) {
-        log("onPause: notify=" + notify);
+    private void onPause() {
+        log("onPause");
 
         mIsInBackground = true;
-        if (canVideoPause(mPrimaryCallContext) && notify) {
+        if (canVideoPause(mPrimaryCallContext)) {
             sendRequest(mPrimaryCallContext.getCall(), false);
         } else {
             log("onPause, Ignoring...");
@@ -314,75 +354,118 @@
 
     /**
      * Sends Pause/Resume request.
+     *
      * @param call Call to be paused/resumed.
      * @param resume If true resume request will be sent, otherwise pause request.
      */
     private void sendRequest(Call call, boolean resume) {
+        // Check if this call supports pause/un-pause.
+        if (!call.can(android.telecom.Call.Details.CAPABILITY_CAN_PAUSE_VIDEO)) {
+            return;
+        }
+
         if (resume) {
             log("sending resume request, call=" + call);
-            call.getVideoCall().sendSessionModifyRequest(CallUtils.makeVideoUnPauseProfile(call));
+            call.getVideoCall()
+                    .sendSessionModifyRequest(CallUtils.makeVideoUnPauseProfile(call));
         } else {
             log("sending pause request, call=" + call);
             call.getVideoCall().sendSessionModifyRequest(CallUtils.makeVideoPauseProfile(call));
         }
     }
 
-    private boolean isVideoPausedEnabled() {
-        return mVideoPauseMode != VIDEO_PAUSE_MODE_DISABLED;
-    }
-
+    /**
+     * Determines if a given call is the same one stored in a {@link CallContext}.
+     *
+     * @param call The call.
+     * @param callContext The call context.
+     * @return {@code true} if the {@link Call} is the same as the one referenced in the
+     *      {@link CallContext}.
+     */
     private static boolean areSame(Call call, CallContext callContext) {
         if (call == null && callContext == null) {
             return true;
         } else if (call == null || callContext == null) {
             return false;
         }
-        return call.getId().equals(callContext.getId());
+        return call.equals(callContext.getCall());
     }
 
-    private static boolean areSame(CallContext callContext, Call call) {
-        return areSame(call, callContext);
-    }
-
+    /**
+     * Determines if a video call can be paused.  Only a video call which is active can be paused.
+     *
+     * @param callContext The call context to check.
+     * @return {@code true} if the call is an active video call.
+     */
     private static boolean canVideoPause(CallContext callContext) {
         return isVideoCall(callContext) && callContext.getState() == Call.State.ACTIVE;
     }
 
+    /**
+     * Determines if a call referenced by a {@link CallContext} is a video call.
+     *
+     * @param callContext The call context.
+     * @return {@code true} if the call is a video call, {@code false} otherwise.
+     */
     private static boolean isVideoCall(CallContext callContext) {
         return callContext != null && VideoProfile.VideoState.isVideo(callContext.getVideoState());
     }
 
     /**
-     * Returns true if call is in incoming/waiting state, false otherwise.
+     * Determines if call is in incoming/waiting state.
+     *
+     * @param call The call context.
+     * @return {@code true} if the call is in incoming or waiting state, {@code false} otherwise.
      */
-    private static boolean isWaitingCall(CallContext call) {
-        return call != null && (call.getState() == Call.State.CALL_WAITING
-                || call.getState() == Call.State.INCOMING);
+    private static boolean isIncomingCall(CallContext call) {
+        return call != null && isIncomingCall(call.getCall());
     }
 
-    private static boolean isWaitingCall(Call call) {
+    /**
+     * Determines if a call is in incoming/waiting state.
+     *
+     * @param call The call.
+     * @return {@code true} if the call is in incoming or waiting state, {@code false} otherwise.
+     */
+    private static boolean isIncomingCall(Call call) {
         return call != null && (call.getState() == Call.State.CALL_WAITING
                 || call.getState() == Call.State.INCOMING);
     }
 
     /**
-     * Returns true if the call is outgoing, false otherwise
+     * Determines if a call is dialing.
+     *
+     * @param call The call context.
+     * @return {@code true} if the call is dialing, {@code false} otherwise.
      */
-    private static boolean isOutgoing(CallContext call) {
+    private static boolean isDialing(CallContext call) {
         return call != null && Call.State.isDialing(call.getState());
     }
 
     /**
-     * Returns true if the call is on hold, false otherwise
+     * Determines if a call is holding.
+     *
+     * @param call The call context.
+     * @return {@code true} if the call is holding, {@code false} otherwise.
      */
     private static boolean isHolding(CallContext call) {
         return call != null && call.getState() == Call.State.ONHOLD;
     }
 
+    /**
+     * Logs a debug message.
+     *
+     * @param msg The message.
+     */
     private void log(String msg) {
         Log.d(this, TAG + msg);
     }
 
+    /**
+     * Logs an error message.
+     *
+     * @param msg The message.
+     */
     private void loge(String msg) {
         Log.e(this, TAG + msg);
     }