Promotion of atel.lnx.2.0.c1-00022.

CRs      Change ID                                   Subject
--------------------------------------------------------------------------------------------------------------
1103354   I252b6cfbf4b4b7a947a4ea6de497445cbf911dc0   Dialer: Fix FC due to StringIndexOutOfBoundsException of
1092416   I2222b8b529baa70edf49b2cfa26d4bb8981e2d09   Dialer: The call contact name still show after deleting
1089584   I8d0eb20c3ca45c6ba9182c23e8bb2229788b8343   IMS-VT: Change in position and color of Alert Dialog act
1076039   I03de0a71fac54ee152523ac14032be8ad40b0eef   RCS: Support for Enrich Call

Change-Id: Ifc0ba1cde044f8fc0a6f750db26ed5a5054eebb0
CRs-Fixed: 1089584, 1092416, 1076039, 1103354
diff --git a/Android.mk b/Android.mk
index 2cb292a..561174d 100755
--- a/Android.mk
+++ b/Android.mk
@@ -41,7 +41,8 @@
 
 LOCAL_JAVA_LIBRARIES := telephony-common \
                         telephony-ext \
-                        ims-common
+                        ims-common \
+                        rcscommon
 
 LOCAL_AAPT_FLAGS := \
     --auto-add-overlay \
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 7bbd37f..6af78af 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -68,6 +68,8 @@
      start requests, even if they happen immediately after the user
      presses home. -->
     <uses-permission android:name="android.permission.STOP_APP_SWITCHES" />
+    <!-- For enrich call -->
+    <uses-permission android:name="com.qualcomm.qti.internal.permission.ACCESS_ENRICHED_CALL" />
 
     <application
         android:name="DialerApplication"
@@ -78,6 +80,8 @@
         android:backupAgent='com.android.dialer.DialerBackupAgent'
         android:usesCleartextTraffic="false">
 
+        <uses-library android:name="org.codeaurora.rcscommon" android:required="false" />
+
         <meta-data android:name="com.google.android.backup.api_key"
             android:value="AEdPqrEAAAAIBXgtCEKQ6W0PXVnW-ZVia2KmlV2AxsTw3GjAeQ" />
 
diff --git a/InCallUI/res/anim/pulse.xml b/InCallUI/res/anim/pulse.xml
new file mode 100644
index 0000000..b4415b3
--- /dev/null
+++ b/InCallUI/res/anim/pulse.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+     * Redistributions of source code must retain the above copyright
+       notice, this list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above
+       copyright notice, this list of conditions and the following
+       disclaimer in the documentation and/or other materials provided
+       with the distribution.
+     * Neither the name of The Linux Foundation nor the names of its
+       contributors may be used to endorse or promote products derived
+       from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+    android:fillAfter="true"
+    android:fillEnabled="true">
+
+    <scale xmlns:android="http://schemas.android.com/apk/res/android"
+        android:duration="1000"
+        android:fromXScale="0.8"
+        android:fromYScale="0.8"
+        android:pivotX="50%"
+        android:pivotY="50%"
+        android:repeatCount="-1"
+        android:repeatMode="reverse"
+        android:toXScale="1"
+        android:toYScale="1" />
+</set>
diff --git a/InCallUI/res/anim/scale_in.xml b/InCallUI/res/anim/scale_in.xml
new file mode 100644
index 0000000..04c8948
--- /dev/null
+++ b/InCallUI/res/anim/scale_in.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+     * Redistributions of source code must retain the above copyright
+       notice, this list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above
+       copyright notice, this list of conditions and the following
+       disclaimer in the documentation and/or other materials provided
+       with the distribution.
+     * Neither the name of The Linux Foundation nor the names of its
+       contributors may be used to endorse or promote products derived
+       from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ -->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+    android:fillEnabled="true"
+    android:fillAfter="true">
+    <scale
+
+        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
+        android:fromXScale="1.0"
+        android:toXScale="0.0"
+        android:fromYScale="1.0"
+        android:toYScale="0.0"
+        android:fillAfter="false"
+        />
+
+</set>
\ No newline at end of file
diff --git a/InCallUI/res/anim/scale_in_material.xml b/InCallUI/res/anim/scale_in_material.xml
new file mode 100644
index 0000000..7f2cf2a
--- /dev/null
+++ b/InCallUI/res/anim/scale_in_material.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+     * Redistributions of source code must retain the above copyright
+       notice, this list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above
+       copyright notice, this list of conditions and the following
+       disclaimer in the documentation and/or other materials provided
+       with the distribution.
+     * Neither the name of The Linux Foundation nor the names of its
+       contributors may be used to endorse or promote products derived
+       from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ -->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+    android:fillEnabled="true"
+    android:fillAfter="true">
+    <scale
+
+        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
+        android:duration="325"
+        android:fromXScale="1.0"
+        android:toXScale="1.0"
+        android:fromYScale="1.0"
+        android:toYScale="0.0"
+        android:fillAfter="false"
+        />
+
+    <scale
+
+        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
+        android:startOffset="75"
+        android:duration="300"
+        android:fromXScale="1.0"
+        android:toXScale="0.0"
+        android:fromYScale="1.0"
+        android:toYScale="1.0"
+        android:fillAfter="false"
+        />
+
+</set>
diff --git a/InCallUI/res/anim/scale_out.xml b/InCallUI/res/anim/scale_out.xml
new file mode 100644
index 0000000..191f275
--- /dev/null
+++ b/InCallUI/res/anim/scale_out.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+     * Redistributions of source code must retain the above copyright
+       notice, this list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above
+       copyright notice, this list of conditions and the following
+       disclaimer in the documentation and/or other materials provided
+       with the distribution.
+     * Neither the name of The Linux Foundation nor the names of its
+       contributors may be used to endorse or promote products derived
+       from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ -->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+    android:fillEnabled="true"
+    android:fillAfter="true">
+    <scale
+
+        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
+        android:fromXScale="0.0"
+        android:toXScale="1.0"
+        android:fromYScale="0.0"
+        android:toYScale="1.0"
+        android:fillAfter="false"
+        />
+
+</set>
\ No newline at end of file
diff --git a/InCallUI/res/anim/scale_out_material.xml b/InCallUI/res/anim/scale_out_material.xml
new file mode 100644
index 0000000..ac8959c
--- /dev/null
+++ b/InCallUI/res/anim/scale_out_material.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+     * Redistributions of source code must retain the above copyright
+       notice, this list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above
+       copyright notice, this list of conditions and the following
+       disclaimer in the documentation and/or other materials provided
+       with the distribution.
+     * Neither the name of The Linux Foundation nor the names of its
+       contributors may be used to endorse or promote products derived
+       from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ -->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+    android:fillEnabled="true"
+    android:fillAfter="true">
+    <scale
+
+        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
+        android:fromXScale="0.0"
+        android:duration="275"
+        android:toXScale="1.0"
+        android:fromYScale="1.0"
+        android:toYScale="1.0"
+        android:fillAfter="false"
+        />
+
+    <scale
+        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
+        android:startOffset="25"
+        android:duration="350"
+        android:fromXScale="1.0"
+        android:toXScale="1.0"
+        android:fromYScale="0.0"
+        android:toYScale="1.0"
+        android:fillAfter="false"
+        />
+
+</set>
diff --git a/InCallUI/res/drawable-xxhdpi/enrich_details_bg.xml b/InCallUI/res/drawable-xxhdpi/enrich_details_bg.xml
new file mode 100644
index 0000000..38cdf18
--- /dev/null
+++ b/InCallUI/res/drawable-xxhdpi/enrich_details_bg.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+     * Redistributions of source code must retain the above copyright
+       notice, this list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above
+       copyright notice, this list of conditions and the following
+       disclaimer in the documentation and/or other materials provided
+       with the distribution.
+     * Neither the name of The Linux Foundation nor the names of its
+       contributors may be used to endorse or promote products derived
+       from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <corners
+        android:bottomLeftRadius="@dimen/card_corner_radius"
+        android:bottomRightRadius="@dimen/card_corner_radius"/>
+    <solid android:color="@color/enrichDetailsBackground"/>
+</shape>
\ No newline at end of file
diff --git a/InCallUI/res/drawable-xxhdpi/ic_rcs_collpase.png b/InCallUI/res/drawable-xxhdpi/ic_rcs_collpase.png
new file mode 100644
index 0000000..6d70ec1
--- /dev/null
+++ b/InCallUI/res/drawable-xxhdpi/ic_rcs_collpase.png
Binary files differ
diff --git a/InCallUI/res/drawable-xxhdpi/ic_rcs_expand.png b/InCallUI/res/drawable-xxhdpi/ic_rcs_expand.png
new file mode 100644
index 0000000..1fac46d
--- /dev/null
+++ b/InCallUI/res/drawable-xxhdpi/ic_rcs_expand.png
Binary files differ
diff --git a/InCallUI/res/drawable-xxxhdpi/ic_enrich_call_white_24dp.png b/InCallUI/res/drawable-xxxhdpi/ic_enrich_call_white_24dp.png
new file mode 100644
index 0000000..936dd6c
--- /dev/null
+++ b/InCallUI/res/drawable-xxxhdpi/ic_enrich_call_white_24dp.png
Binary files differ
diff --git a/InCallUI/res/drawable/normal_call_bg.xml b/InCallUI/res/drawable/normal_call_bg.xml
new file mode 100644
index 0000000..7c4bca9
--- /dev/null
+++ b/InCallUI/res/drawable/normal_call_bg.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+     * Redistributions of source code must retain the above copyright
+       notice, this list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above
+       copyright notice, this list of conditions and the following
+       disclaimer in the documentation and/or other materials provided
+       with the distribution.
+     * Neither the name of The Linux Foundation nor the names of its
+       contributors may be used to endorse or promote products derived
+       from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <corners
+        android:topRightRadius="@dimen/card_corner_radius"
+        android:topLeftRadius="@dimen/card_corner_radius" />
+    <solid android:color="@color/normalCallBackground"/>
+</shape>
diff --git a/InCallUI/res/drawable/ring.xml b/InCallUI/res/drawable/ring.xml
new file mode 100644
index 0000000..201b128
--- /dev/null
+++ b/InCallUI/res/drawable/ring.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+     * Redistributions of source code must retain the above copyright
+       notice, this list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above
+       copyright notice, this list of conditions and the following
+       disclaimer in the documentation and/or other materials provided
+       with the distribution.
+     * Neither the name of The Linux Foundation nor the names of its
+       contributors may be used to endorse or promote products derived
+       from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ -->
+<shape
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="oval">
+
+    <stroke
+        android:width="1dp"
+        android:color="@android:color/white"/>
+
+    <size
+        android:width="52dp"
+        android:height="52dp"/>
+</shape>
diff --git a/InCallUI/res/drawable/urgent_call_bg.xml b/InCallUI/res/drawable/urgent_call_bg.xml
new file mode 100644
index 0000000..69b10da
--- /dev/null
+++ b/InCallUI/res/drawable/urgent_call_bg.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+     * Redistributions of source code must retain the above copyright
+       notice, this list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above
+       copyright notice, this list of conditions and the following
+       disclaimer in the documentation and/or other materials provided
+       with the distribution.
+     * Neither the name of The Linux Foundation nor the names of its
+       contributors may be used to endorse or promote products derived
+       from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <corners
+        android:topRightRadius="@dimen/card_corner_radius"
+        android:topLeftRadius="@dimen/card_corner_radius" />
+    <solid android:color="@color/urgentCallBackground"/>
+</shape>
diff --git a/InCallUI/res/layout-h400dp/call_card_fragment.xml b/InCallUI/res/layout-h400dp/call_card_fragment.xml
index ccff385..d75075c 100644
--- a/InCallUI/res/layout-h400dp/call_card_fragment.xml
+++ b/InCallUI/res/layout-h400dp/call_card_fragment.xml
@@ -123,12 +123,19 @@
 
             </FrameLayout>
 
+            <fragment android:name="com.android.incallui.RcsCallFragment"
+                android:id="@+id/enrichcall_container"
+                android:layout_gravity="top|center_horizontal"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/primary_call_info_container" />
+
             <LinearLayout
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:orientation="vertical"
                 android:layout_centerHorizontal="true"
-                android:layout_below="@id/primary_call_info_container">
+                android:layout_below="@id/enrichcall_container">
 
                 <include layout="@layout/manage_conference_call_button"
                     android:layout_width="match_parent"
diff --git a/InCallUI/res/layout-w500dp-land/call_card_fragment.xml b/InCallUI/res/layout-w500dp-land/call_card_fragment.xml
index 343c4da..4d59cb7 100644
--- a/InCallUI/res/layout-w500dp-land/call_card_fragment.xml
+++ b/InCallUI/res/layout-w500dp-land/call_card_fragment.xml
@@ -82,6 +82,12 @@
 
         </FrameLayout>
 
+        <fragment android:name="com.android.incallui.RcsCallFragment"
+            android:id="@+id/enrichcall_container"
+            android:layout_gravity="top|center_horizontal"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" />
+
         <fragment android:name="com.android.incallui.VideoCallFragment"
             android:layout_alignParentStart="true"
             android:layout_gravity="start|center_vertical"
diff --git a/InCallUI/res/layout/call_card_fragment.xml b/InCallUI/res/layout/call_card_fragment.xml
index 2a4c3e2..3a1c61d 100644
--- a/InCallUI/res/layout/call_card_fragment.xml
+++ b/InCallUI/res/layout/call_card_fragment.xml
@@ -98,12 +98,19 @@
 
     </FrameLayout>
 
+    <fragment android:name="com.android.incallui.RcsCallFragment"
+        android:id="@+id/enrichcall_container"
+        android:layout_gravity="top|center_horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/primary_call_info_container" />
+
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:orientation="vertical"
         android:layout_centerHorizontal="true"
-        android:layout_below="@id/primary_call_info_container">
+        android:layout_below="@id/enrichcall_container">
 
         <include layout="@layout/manage_conference_call_button"
             android:layout_width="match_parent"
diff --git a/InCallUI/res/layout/enrich_call_content.xml b/InCallUI/res/layout/enrich_call_content.xml
new file mode 100644
index 0000000..233e901
--- /dev/null
+++ b/InCallUI/res/layout/enrich_call_content.xml
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+     * Redistributions of source code must retain the above copyright
+       notice, this list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above
+       copyright notice, this list of conditions and the following
+       disclaimer in the documentation and/or other materials provided
+       with the distribution.
+     * Neither the name of The Linux Foundation nor the names of its
+       contributors may be used to endorse or promote products derived
+       from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ -->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:visibility="gone"
+    android:gravity="center">
+
+    <LinearLayout
+        android:id="@+id/enrich_main"
+        android:layout_width="@dimen/enrich_min_width"
+        android:layout_height="wrap_content"
+        android:layout_centerHorizontal="true"
+        android:layout_marginTop="@dimen/main_layout_margin_top"
+        android:orientation="vertical">
+
+        <TextView
+            android:id="@+id/call_type"
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/call_type_text_height"
+            android:background="@drawable/normal_call_bg"
+            android:gravity="center_vertical"
+            android:paddingLeft="@dimen/call_type_padding_left"
+            android:textColor="@android:color/white"
+            android:textSize="@dimen/call_type_font_size" />
+
+
+        <LinearLayout
+            android:id="@+id/enrich_details"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:background="@drawable/enrich_details_bg"
+            android:orientation="vertical">
+
+            <TextView
+                android:id="@+id/notes"
+                android:layout_width="match_parent"
+                android:layout_height="@dimen/notes_text_height"
+                android:ellipsize="end"
+                android:gravity="center_vertical"
+                android:maxLines="1"
+                android:paddingLeft="5dp"
+                android:textColor="@android:color/black"
+                android:textSize="@dimen/notes_font_size" />
+
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="horizontal" >
+
+                <ImageView
+                    android:id="@+id/picture"
+                    android:layout_width="0dp"
+                    android:layout_height="@dimen/mini_view_picture_height"
+                    android:layout_weight="1"
+                    android:paddingLeft="@dimen/picture_layout_padding"
+                    android:layout_marginTop="@dimen/picture_layout_padding"
+                    android:layout_marginBottom="@dimen/picture_layout_padding"
+                    android:scaleType="centerCrop"/>
+
+                <Space
+                    android:layout_width="@dimen/picture_layout_padding"
+                    android:layout_height="wrap_content" />
+
+                <ImageView
+                    android:id="@+id/map"
+                    android:layout_width="0dp"
+                    android:layout_height="@dimen/mini_view_picture_height"
+                    android:layout_weight="1"
+                    android:paddingRight="@dimen/picture_layout_padding"
+                    android:layout_marginTop="@dimen/picture_layout_padding"
+                    android:layout_marginBottom="@dimen/picture_layout_padding"
+                    android:scaleType="centerCrop" />
+            </LinearLayout>
+        </LinearLayout>
+    </LinearLayout>
+
+    <RelativeLayout
+        android:layout_width="@dimen/button_layout_width"
+        android:layout_height="@dimen/button_layout_height"
+        android:layout_alignLeft="@+id/enrich_main"
+        android:layout_marginLeft="@dimen/button_margin_left">
+
+        <ImageView
+            android:id="@+id/ring_anim"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerInParent="true"
+            android:src="@drawable/ring" />
+
+
+        <ImageView
+            android:id="@+id/expand_collapse"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerInParent="true"
+            android:src="@drawable/ic_rcs_collpase" />
+    </RelativeLayout>
+</RelativeLayout>
+
diff --git a/InCallUI/res/values/colors.xml b/InCallUI/res/values/colors.xml
index 99cf7b0..3764014 100644
--- a/InCallUI/res/values/colors.xml
+++ b/InCallUI/res/values/colors.xml
@@ -122,4 +122,11 @@
 
     <!-- White background for dialer -->
     <color name="background_dialer_white">#ffffff</color>
+
+    <color name="colorPrimary">#3F51B5</color>
+    <color name="colorPrimaryDark">#303F9F</color>
+    <color name="colorAccent">#FF4081</color>
+    <color name="urgentCallBackground">#f40707</color>
+    <color name="normalCallBackground">#0ab5e0</color>
+    <color name="enrichDetailsBackground">#FFFFFF</color>
 </resources>
diff --git a/InCallUI/res/values/dimens.xml b/InCallUI/res/values/dimens.xml
index 3a926b6..357c582 100644
--- a/InCallUI/res/values/dimens.xml
+++ b/InCallUI/res/values/dimens.xml
@@ -151,4 +151,28 @@
     <dimen name="business_contact_context_detail_font_size">12sp</dimen>
 
     <dimen name="contact_context_small_photo_size">40dp</dimen>
+
+    <!-- RCS dimensions. -->
+    <dimen name="enrich_miniview_layout_height">126.6dp</dimen>
+    <dimen name="enrich_miniview_layout_width">306.6dp</dimen>
+    <dimen name="enrich_detail_margin">0dp</dimen>
+    <dimen name="enrich_min_width">306.6dp</dimen>
+    <dimen name="call_type_font_size">18dp</dimen>
+    <dimen name="notes_font_size">15dp</dimen>
+    <dimen name="max_height_for_picture">60dp</dimen>
+    <dimen name="card_corner_radius">5dp</dimen>
+    <dimen name="call_type_text_height">33dp</dimen>
+    <dimen name="notes_text_height">40dp</dimen>
+    <dimen name="call_type_padding_left">60dp</dimen>
+    <dimen name="picture_layout_padding">3.3dp</dimen>
+    <dimen name="button_margin_top">13dp</dimen>
+    <dimen name="button_margin_left">-22dp</dimen>
+    <dimen name="enrich_details_margin_left">17dp</dimen>
+    <integer name="expand_duration">375</integer>
+    <integer name="collapse_duration">300</integer>
+    <dimen name="button_layout_width">64dp</dimen>
+    <dimen name="button_layout_height">64dp</dimen>
+    <dimen name="main_layout_margin_top">17dp</dimen>
+    <dimen name="mini_view_picture_height">50dp</dimen>
+    <dimen name="expanded_view_picture_height">143.3dp</dimen>
 </resources>
diff --git a/InCallUI/res/values/qtistrings.xml b/InCallUI/res/values/qtistrings.xml
index 8f068a0..afa29ab 100644
--- a/InCallUI/res/values/qtistrings.xml
+++ b/InCallUI/res/values/qtistrings.xml
@@ -191,4 +191,27 @@
     <string name="video_call_picture_mode_incoming_video">Incoming Video</string>
     <string name="video_call_picture_mode_cancel_option">Cancel</string>
     <string name="video_call_picture_mode_save_option">Save</string>
+
+
+    <!-- Enrich call strings -->
+    <string name="notification_incoming_enrich_call_high_priority">Incoming urgent call</string>
+    <string name="notification_incoming_enrich_call_normal_priority">Incoming rich call</string>
+    <string name="notification_on_hold_enrich_call_high_priority">Urgent call on hold</string>
+    <string name="notification_on_hold_enrich_call_normal_priority">Rich call on hold</string>
+    <string name="notification_dialing_enrich_call_high_priority">Dialing urgent call</string>
+    <string name="notification_dialing_enrich_call_normal_priority">Dialing rich call</string>
+    <string name="notification_ongoing_enrich_call_high_priority">Ongoing urgent call</string>
+    <string name="notification_ongoing_enrich_call_normal_priority">Ongoing rich call</string>
+    <string name="normal_enrich_call">RICH CALL</string>
+    <string name="urgent_enrich_call">URGENT CALL</string>
+    <string name="rich_call_failed">Rich call failed</string>
+    <string name="urgent_call_failed">Urgent call failed</string>
+    <string name="can_not_launch_image_application">Can not find any application to show shared image</string>
+    <string name="can_not_launch_maps_application">Can not find any application to show maps location</string>
+    <string name="enrich_call_permission">Access Enriched call</string>
+    <string name="access_permission_message">Phone App requires access to photos,
+    media &amp; files on your device to enable Rich Calling. To continue, tap  \'YES\'
+    below &amp;  \'ALLOW\' on the next screen.</string>
+    <string name="yes">Yes</string>
+    <string name="no">No</string>
 </resources>
diff --git a/InCallUI/src/com/android/incallui/CallCardPresenter.java b/InCallUI/src/com/android/incallui/CallCardPresenter.java
index ff90272..c3c9a81 100644
--- a/InCallUI/src/com/android/incallui/CallCardPresenter.java
+++ b/InCallUI/src/com/android/incallui/CallCardPresenter.java
@@ -1165,6 +1165,11 @@
     }
 
     @Override
+    public void onAnswerViewGrab(boolean isGrabbed) {
+        // No-op - required for RcsCallPresenter.
+    }
+
+    @Override
     public void onIncomingVideoAvailabilityChanged(boolean isAvailable) {
         Log.d(this, "onIncomingVideoAvailabilityChanged: available = " + isAvailable);
         if (mPrimary == null) {
diff --git a/InCallUI/src/com/android/incallui/GlowPadWrapper.java b/InCallUI/src/com/android/incallui/GlowPadWrapper.java
index c88a984..ab4660d 100644
--- a/InCallUI/src/com/android/incallui/GlowPadWrapper.java
+++ b/InCallUI/src/com/android/incallui/GlowPadWrapper.java
@@ -95,6 +95,7 @@
     @Override
     public void onGrabbed(View v, int handle) {
         Log.d(this, "onGrabbed()");
+        InCallPresenter.getInstance().notifyAnswerViewGrabChanged(true);
         stopPing();
     }
 
@@ -106,6 +107,7 @@
         } else {
             startPing();
         }
+        InCallPresenter.getInstance().notifyAnswerViewGrabChanged(false);
     }
 
     @Override
diff --git a/InCallUI/src/com/android/incallui/InCallLowBatteryListener.java b/InCallUI/src/com/android/incallui/InCallLowBatteryListener.java
index bdc46e1..c413b07 100644
--- a/InCallUI/src/com/android/incallui/InCallLowBatteryListener.java
+++ b/InCallUI/src/com/android/incallui/InCallLowBatteryListener.java
@@ -30,6 +30,7 @@
 package com.android.incallui;
 
 import android.app.AlertDialog;
+import android.graphics.Color;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnCancelListener;
@@ -401,7 +402,7 @@
         });
 
         if (VideoUtils.isIncomingVideoCall(call)) {
-            alertDialog.setNegativeButton(R.string.low_battery_convert, new OnClickListener() {
+            alertDialog.setPositiveButton(R.string.low_battery_convert, new OnClickListener() {
                 @Override
                 public void onClick(DialogInterface dialog, int which) {
                      Log.d(this, "displayLowBatteryAlert answer as Voice Call");
@@ -411,7 +412,7 @@
             });
 
             alertDialog.setMessage(R.string.low_battery_msg);
-            alertDialog.setPositiveButton(R.string.low_battery_yes, new OnClickListener() {
+            alertDialog.setNegativeButton(R.string.low_battery_yes, new OnClickListener() {
                 @Override
                 public void onClick(DialogInterface dialog, int which) {
                      Log.d(this, "displayLowBatteryAlert answer as Video Call");
@@ -420,7 +421,7 @@
                 }
             });
         } else if (VideoUtils.isOutgoingVideoCall(call)) {
-            alertDialog.setNegativeButton(R.string.low_battery_convert, new OnClickListener() {
+            alertDialog.setPositiveButton(R.string.low_battery_convert, new OnClickListener() {
                 @Override
                 public void onClick(DialogInterface dialog, int which) {
                      Log.d(this, "displayLowBatteryAlert place Voice Call");
@@ -437,7 +438,7 @@
             });
 
             alertDialog.setMessage(R.string.low_battery_msg);
-            alertDialog.setPositiveButton(R.string.low_battery_yes, new OnClickListener() {
+            alertDialog.setNegativeButton(R.string.low_battery_yes, new OnClickListener() {
                 @Override
                 public void onClick(DialogInterface dialog, int which) {
                      Log.d(this, "displayLowBatteryAlert place Video Call");
@@ -453,8 +454,8 @@
             if (QtiCallUtils.hasVoiceCapabilities(call)) {
                 //active video call can be downgraded to voice
                 alertDialog.setMessage(R.string.low_battery_msg);
-                alertDialog.setPositiveButton(R.string.low_battery_yes, null);
-                alertDialog.setNegativeButton(R.string.low_battery_convert, new OnClickListener() {
+                alertDialog.setNegativeButton(R.string.low_battery_yes, null);
+                alertDialog.setPositiveButton(R.string.low_battery_convert, new OnClickListener() {
                     @Override
                     public void onClick(DialogInterface dialog, int which) {
                         Log.d(this, "displayLowBatteryAlert downgrading to voice call");
@@ -465,8 +466,8 @@
                 /* video call doesn't have downgrade capabilities, so alert the user
                    with a hangup dialog*/
                 alertDialog.setMessage(R.string.low_battery_hangup_msg);
-                alertDialog.setNegativeButton(R.string.low_battery_no, null);
-                alertDialog.setPositiveButton(R.string.low_battery_yes, new OnClickListener() {
+                alertDialog.setPositiveButton(R.string.low_battery_no, null);
+                alertDialog.setNegativeButton(R.string.low_battery_yes, new OnClickListener() {
                     @Override
                     public void onClick(DialogInterface dialog, int which) {
                         Log.d(this, "displayLowBatteryAlert hanging up the call: " + call);
@@ -495,6 +496,11 @@
         mAlert.setCanceledOnTouchOutside(false);
         mAlert.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
         mAlert.show();
+        /*
+         * By default both the buttons will have same color. In case we want to have different color
+         * we need to set specifically.
+         */
+        mAlert.getButton(DialogInterface.BUTTON_NEGATIVE).setTextColor(Color.BLACK);
     }
 
     /*
diff --git a/InCallUI/src/com/android/incallui/InCallPresenter.java b/InCallUI/src/com/android/incallui/InCallPresenter.java
index 83a16d9..0bd3a5f 100644
--- a/InCallUI/src/com/android/incallui/InCallPresenter.java
+++ b/InCallUI/src/com/android/incallui/InCallPresenter.java
@@ -2012,6 +2012,16 @@
         return mThemeColors;
     }
 
+    /**
+     * this function will be called from glowpadwrapper to notify
+     * incallpresenter when user touch or release the answer view.
+     */
+    public void notifyAnswerViewGrabChanged(boolean isGrabbed) {
+        for (InCallEventListener listener : mInCallEventListeners) {
+            listener.onAnswerViewGrab(isGrabbed);
+        }
+    }
+
     private MaterialPalette getColorsFromCall(Call call) {
         if (call == null) {
             return getColorsFromPhoneAccountHandle(mPendingPhoneAccountHandle);
@@ -2143,6 +2153,7 @@
         public void updatePrimaryCallState();
         public void onIncomingVideoAvailabilityChanged(boolean isAvailable);
         public void onSendStaticImageStateChanged(boolean isEnabled);
+        public void onAnswerViewGrab(boolean isGrabbed);
     }
 
     public interface InCallUiListener {
diff --git a/InCallUI/src/com/android/incallui/InCallRcsImageDownloader.java b/InCallUI/src/com/android/incallui/InCallRcsImageDownloader.java
new file mode 100644
index 0000000..e119c17
--- /dev/null
+++ b/InCallUI/src/com/android/incallui/InCallRcsImageDownloader.java
@@ -0,0 +1,125 @@
+/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.android.incallui;
+
+import android.content.Context;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Message;
+
+import org.codeaurora.rcscommon.FetchImageCallBack;
+import org.codeaurora.rcscommon.RcsManager;
+
+/**
+ * This class InCallRcsImageDownloader is used to get the RCS shared image and
+ * RCS shared location image from the RCSService. This class will call the RCSManager
+ * to fetch Shared Image and Location image.
+ */
+public class InCallRcsImageDownloader {
+
+    private static final int FETCH_LOCATION_IMAGE = 1;
+    private static final int UPDATE_IMAGE_DETAILS = 2;
+
+    public static interface FetchImageListener {
+        public void onFetchedImage(byte[] arr);
+    }
+
+    private class ImageDetails {
+        FetchImageListener mListener;
+        byte[] result;
+        int width, height;
+        double lat, lon;
+
+        ImageDetails(int width, int height, double lat,
+            double lon, FetchImageListener listener) {
+                mListener = listener;
+                this.width = width;
+                this.height = height;
+                this.lat = lat;
+                this.lon = lon;
+        }
+    }
+
+    private Handler mHandler = new Handler() {
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case FETCH_LOCATION_IMAGE:
+                    fetchLocationImage((ImageDetails) msg.obj);
+                    break;
+                case UPDATE_IMAGE_DETAILS:
+                    ImageDetails details = (ImageDetails) msg.obj;
+                    if (details.mListener != null) {
+                        details.mListener.onFetchedImage(details.result);
+                    }
+                    break;
+            }
+        }
+    };
+
+    private Context mContext;
+    private RcsManager mRcsManager;
+
+    InCallRcsImageDownloader(Context context) {
+        mContext = context;
+        mRcsManager = RcsManager.getInstance(context);
+    }
+
+    /**
+     * request to get the location image.
+     * the image result will be returned asynchronously.
+     * @param int width, int height, double lat,
+     * double lon, FetchImageListener listener.
+     */
+    public void requestFetchLocationImage(int width, int height, double lat,
+            double lon, FetchImageListener listener) {
+        ImageDetails locImgDetails = new ImageDetails(width,
+                height, lat, lon, listener);
+
+        Message msg = new Message();
+        msg.what = FETCH_LOCATION_IMAGE;
+        msg.obj = locImgDetails;
+        mHandler.sendMessage(msg);
+    }
+
+    private void fetchLocationImage(final ImageDetails details) {
+        FetchImageCallBack rcsMapCallBack = new FetchImageCallBack.Stub() {
+            public void onImageFetched( byte[] image) {
+                Log.d(this,"onStaticMapFeatch " + image);
+                details.result = image;
+                Message msg = new Message();
+                msg.what = UPDATE_IMAGE_DETAILS;
+                msg.obj = details;
+                mHandler.sendMessage(msg);
+            }
+        };
+
+        mRcsManager.fetchStaticMap(details.lat, details.lon,
+                    details.width, details.height, rcsMapCallBack);
+    }
+
+}
diff --git a/InCallUI/src/com/android/incallui/InCallRcsUtils.java b/InCallUI/src/com/android/incallui/InCallRcsUtils.java
new file mode 100644
index 0000000..546aae1
--- /dev/null
+++ b/InCallUI/src/com/android/incallui/InCallRcsUtils.java
@@ -0,0 +1,156 @@
+/**
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.android.incallui;
+
+import android.content.Context;
+import android.telecom.Call.Details;
+import android.text.style.ForegroundColorSpan;
+import android.text.SpannableStringBuilder;
+
+import org.codeaurora.rcscommon.CallComposerData;
+
+/**
+ * This class contains Enrich call specific utiltity functions.
+ */
+public class InCallRcsUtils {
+
+    /**
+     * Verify if current call is of enrich call type.
+     * Excludes all other call types [video call, video call upgrade request, conference call
+     * wifi call]
+     *
+     * @param call
+     * @param context
+     * @return
+     */
+    public static boolean isEnrichCall(Call call, Context context) {
+
+        final boolean isVideoUpgradeRequest =
+                call.getSessionModificationState()
+                        == Call.SessionModificationState.
+                        RECEIVED_UPGRADE_TO_VIDEO_REQUEST;
+        RcsCallInfo callInfo = RcsCallHandler.getInstance().getRcsCallInfo(call);
+        return callInfo != null && callInfo.isEnrichedCall()
+                && !call.hasProperty(Details.PROPERTY_WIFI)
+                && !call.isVideoCall(context)
+                && !call.isConferenceCall()
+                && !isVideoUpgradeRequest;
+    }
+
+    /**
+     * Get enrich call notification string for HIGH and NORMAL
+     * priority enrich call based on different call states
+     *
+     * @param call
+     * @param isIncomingOrWaiting
+     * @return
+     */
+    public static int getEnrichContentString(Call call, boolean isIncomingOrWaiting) {
+        int resId = R.string.notification_ongoing_enrich_call_normal_priority;
+
+        RcsCallInfo callInfo = RcsCallHandler.getInstance().getRcsCallInfo(call);
+        CallComposerData data = callInfo != null ? callInfo.getCallComposerData() : null;
+        if (isIncomingOrWaiting) {
+            if (data != null && data.getPriority() == CallComposerData.PRIORITY.HIGH) {
+                resId = R.string.notification_incoming_enrich_call_high_priority;
+            } else {
+                resId = R.string.notification_incoming_enrich_call_normal_priority;
+            }
+        } else if (call.getState() == Call.State.ONHOLD) {
+            if (data != null && data.getPriority() == CallComposerData.PRIORITY.HIGH) {
+                resId = R.string.notification_on_hold_enrich_call_high_priority;
+            } else {
+                resId = R.string.notification_on_hold_enrich_call_normal_priority;
+            }
+
+        } else if (Call.State.isDialing(call.getState())) {
+            if (data != null && data.getPriority() == CallComposerData.PRIORITY.HIGH) {
+                resId = R.string.notification_dialing_enrich_call_high_priority;
+            } else {
+                resId = R.string.notification_dialing_enrich_call_normal_priority;
+            }
+
+        } else {
+            if (data != null && data.getPriority() == CallComposerData.PRIORITY.HIGH) {
+                resId = R.string.notification_ongoing_enrich_call_high_priority;
+            } else {
+                resId = R.string.notification_ongoing_enrich_call_normal_priority;
+            }
+        }
+
+        return resId;
+    }
+
+    /**
+     * Get coloured notification content string for enrich call based
+     * on enrich call priority
+     *
+     * @param context
+     * @param call
+     * @param content
+     * @return
+     */
+    public static SpannableStringBuilder getEnrichContentText(Context context, Call call,
+                String content) {
+        RcsCallInfo callInfo = RcsCallHandler.getInstance().getRcsCallInfo(call);
+        CallComposerData data = callInfo != null ? callInfo.getCallComposerData() : null;
+        SpannableStringBuilder styleContent =
+                new SpannableStringBuilder();
+        if (data != null && data.getPriority() == CallComposerData.PRIORITY.HIGH) {
+            appendStyled(styleContent, content,
+                    new ForegroundColorSpan(context.getResources().
+                            getColor(R.color.urgentCallBackground)));
+        } else {
+            appendStyled(styleContent, content,
+                    new ForegroundColorSpan(context.getResources().
+                            getColor(R.color.normalCallBackground)));
+        }
+
+        return styleContent;
+    }
+
+    /**
+     * Handle color spans for string
+     *
+     * Set styles for subparts in a string. Subparts in a string can be of different styles
+     * like color, bold, italic etc..
+     *
+     * @param builder
+     * @param str
+     * @param spans
+     */
+    private static void appendStyled(SpannableStringBuilder builder,
+                String str, Object... spans) {
+        builder.append(str);
+        for (Object span : spans) {
+            builder.setSpan(span, builder.length() - str.length(), builder.length(), 0);
+        }
+    }
+}
diff --git a/InCallUI/src/com/android/incallui/RcsCallFragment.java b/InCallUI/src/com/android/incallui/RcsCallFragment.java
new file mode 100644
index 0000000..d9d37b3
--- /dev/null
+++ b/InCallUI/src/com/android/incallui/RcsCallFragment.java
@@ -0,0 +1,619 @@
+/**
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.android.incallui;
+
+import android.app.AlertDialog;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.Manifest;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Process;
+import android.text.TextUtils;
+import android.util.TypedValue ;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewAnimationUtils;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import org.codeaurora.rcscommon.CallComposerData;
+
+/**
+ * RcsCallFragment class is used to display the RCS call content on the incall screen.
+ */
+public class RcsCallFragment extends
+        BaseFragment<RcsCallPresenter, RcsCallPresenter.RcsCallUi> implements
+        RcsCallPresenter.RcsCallUi, View.OnClickListener {
+
+    private static final int MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 0;
+    private static final String PREFERENCE_SHOWN_INFO_DLG_KEY = "RCS_SHOWN_INFO_DLG";
+
+    private TextView mPriorityView, mSubject;
+    private ImageView mMapView, mImageView;
+    private View mRootView = null, mEnrichDetailLayout;
+    private ImageView mExpandCollapseBtn, mRingAnimView;
+    private boolean mIsDataAvailable;
+    private boolean mIsPresmissionReqPending;
+    private static RcsCallPresenter sRcsCallPresenter;
+
+    private RcsCallPresenter.ImageBitmapListener mImageViewListener
+            = new RcsCallPresenter.ImageBitmapListener() {
+        public void onFetchBitmap(Bitmap bitmap) {
+            mImageView.setImageBitmap(bitmap);
+        }
+    };
+
+    private RcsCallPresenter.ImageBitmapListener mMapViewListener
+            = new RcsCallPresenter.ImageBitmapListener() {
+        public void onFetchBitmap(Bitmap bitmap) {
+            mMapView.setImageBitmap(bitmap);
+        }
+    };
+
+    @Override
+    public RcsCallPresenter createPresenter() {
+        sRcsCallPresenter = new RcsCallPresenter();
+        return sRcsCallPresenter;
+    }
+
+    /**
+     * getPresenterInstance will return a singleton instance of RcsCallPresenter
+     *
+     * @return RcsCallPresenter
+     */
+    public static RcsCallPresenter getPresenterInstance() {
+        return sRcsCallPresenter;
+    }
+
+    @Override
+    public RcsCallPresenter.RcsCallUi getUi() {
+        return this;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        Log.d(this, "onCreate : ");
+        super.onCreate(savedInstanceState);
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        Log.d(this, "onCreateView : ");
+        mRootView = inflater.inflate(R.layout.enrich_call_content,
+                container, false);
+
+        mPriorityView = (TextView) mRootView.findViewById(R.id.call_type);
+
+        mMapView = (ImageView) mRootView.findViewById(R.id.map);
+        mMapView.setOnClickListener(this);
+
+        mImageView = (ImageView) mRootView.findViewById(R.id.picture);
+        mImageView.setOnClickListener(this);
+
+        mSubject = (TextView) mRootView.findViewById(R.id.notes);
+        mSubject.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                showDetailedNotes(mSubject.getText().toString());
+            }
+        });
+
+        mExpandCollapseBtn= (ImageView) mRootView.findViewById(R.id.expand_collapse);
+
+        mRingAnimView = (ImageView) mRootView.findViewById(R.id.ring_anim);
+        mRingAnimView.setVisibility(View.INVISIBLE);
+
+        mEnrichDetailLayout = (LinearLayout) mRootView
+                .findViewById(R.id.enrich_details);
+        mExpandCollapseBtn.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                animate(mEnrichDetailLayout, (ImageView) view, mRingAnimView,
+                    !(mEnrichDetailLayout.getVisibility() == View.VISIBLE));
+            }
+        });
+
+        return mRootView;
+    }
+
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        Log.d(this, "onActivityCreated");
+        super.onActivityCreated(savedInstanceState);
+    }
+
+    @Override
+    public void onResume() {
+        Log.d(this, "onResume");
+        super.onResume();
+    }
+
+    @Override
+    public void onClick(View view) {
+        Log.d(this,"onClick : " + view);
+        switch(view.getId()) {
+            case R.id.picture:
+                Uri uri = (Uri) mImageView.getTag();
+                if(uri != null){
+                    getPresenter().onSharedImageClicked(uri);
+                }
+                break;
+            case R.id.map:
+                double[] arr = (double[]) mMapView.getTag();
+                if(arr != null && arr.length == 2) {
+                    getPresenter().onMapImageClicked(arr[0], arr[1]);
+                }
+                break;
+        }
+    }
+
+    @Override
+    public Context getContext() {
+        return getActivity();
+    }
+
+    @Override
+    public void updateCallComposerData(RcsCallInfo info) {
+        CallComposerData data = info != null ? info.getCallComposerData() : null;
+        Log.d(this, "updateCallComposerData : " + data);
+        if (data == null) {
+            return;
+        }
+        mIsDataAvailable = false;
+
+        //EnrichCall Subject View update
+        if (TextUtils.isEmpty(data.getSubject())) {
+            mSubject.setVisibility(View.GONE);
+        } else {
+            mIsDataAvailable = true;
+            mSubject.setVisibility(View.VISIBLE);
+        }
+        mSubject.setText(data.getSubject());
+
+        //EnrichCall priority view update
+        if (data.getPriority() == CallComposerData.PRIORITY.NORMAL) {
+            mPriorityView.setBackgroundResource(R.drawable.normal_call_bg);
+            mPriorityView.setText(getString(R.string.normal_enrich_call));
+        } else {
+            mPriorityView.setBackgroundResource(R.drawable.urgent_call_bg);
+            mPriorityView.setText(getString(R.string.urgent_enrich_call));
+        }
+
+        //Location View update
+        if (data.isValidLocation()) {
+            mIsDataAvailable = true;
+            mMapView.setVisibility(View.VISIBLE);
+        } else {
+            mMapView.setVisibility(View.GONE);
+        }
+
+        if (info.getLocationImageArray() != null
+                && info.getLocationImageArray().length > 0) {
+            updateLocationImage(info.getLocationImageArray(), data.getLatitude(),
+                    data.getLongitude());
+        }
+
+        boolean canReadExternalStorage = hasReadStoragePermission();
+        Log.d(this, "canReadExternalStorage : " + canReadExternalStorage);
+
+        //SharedImage view update
+        if (data.isValidSharedImageUri()) {
+            mIsDataAvailable = true;
+            mImageView.setVisibility(View.VISIBLE);
+        } else {
+            mImageView.setVisibility(View.GONE);
+        }
+        if (canReadExternalStorage && data.isValidSharedImageUri()) {
+            getPresenter().updateImageFromUri(data.getImageUri(), mImageViewListener);
+            mImageView.setTag(data.getImageUri());
+        }
+
+        if (!mIsDataAvailable) {
+            mExpandCollapseBtn.setVisibility(View.GONE);
+        } else {
+            mExpandCollapseBtn.setVisibility(View.VISIBLE);
+        }
+    }
+
+    @Override
+    public int getMapImageViewWidth() {
+        return mMapView != null ? mMapView.getWidth() : 0;
+    }
+
+    @Override
+    public int getMapImageViewHeight() {
+        //consider showing map for max height as when call is answered we need to show
+        //full map image.
+        return (int) getResources().
+                getDimension(R.dimen.expanded_view_picture_height);
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        Log.d(this, "setEnabled : " + enabled);
+        if (mRootView == null) {
+            return;
+        }
+        mRootView.setEnabled(enabled);
+    }
+
+    @Override
+    public void setVisible(boolean visible) {
+        Log.d(this, "setVisible : " + visible);
+        if (mRootView == null) {
+            return;
+        }
+        mRootView.setVisibility(visible ? View.VISIBLE : View.GONE);
+    }
+
+    @Override
+    public void showSmallView(boolean showSmall) {
+        Log.d(this, "showSmallView : " + showSmall);
+        if (mRootView == null) {
+            return;
+        }
+        setMiniUi(mEnrichDetailLayout, showSmall);
+    }
+
+    @Override
+    public void showEnrichCallFailed(CallComposerData.PRIORITY priority) {
+        if (priority == CallComposerData.PRIORITY.HIGH) {
+            Toast.makeText(getActivity(), R.string.urgent_call_failed,
+                    Toast.LENGTH_LONG).show();
+        } else {
+            Toast.makeText(getActivity(), R.string.rich_call_failed,
+                    Toast.LENGTH_LONG).show();
+        }
+    }
+
+    @Override
+    public void showEnrichCallDetail() {
+        if (!(mEnrichDetailLayout.getVisibility() == View.VISIBLE)) {
+            expandCollapse(mEnrichDetailLayout, mExpandCollapseBtn, mRingAnimView, true);
+        }
+    }
+
+    @Override
+    public void hideEnrichCallDetail() {
+        if (mEnrichDetailLayout.getVisibility() == View.VISIBLE) {
+            expandCollapse(mEnrichDetailLayout, mExpandCollapseBtn, mRingAnimView, false);
+        }
+    }
+
+    private void updateLocationImage(final byte[] arr, double lat, double lon) {
+        Log.d(this, "updateLocationImage ");
+        mMapView.setTag(new double[]{lat, lon});
+        getPresenter().updateImageFromBytes(arr, mMapViewListener);
+    }
+
+    /**
+     * Hide and show RCS content detailed view
+     *
+     * Additionally if detailed view is hidden ring animation will be shown.
+     *
+     * @param view   parent view
+     * @param buttonView  expand/collapse button view
+     * @param ringView  view to show ring animation on expand/collapse button
+     * @param show  hide/show detailed view with animation
+     */
+    private void expandCollapse(final View view, final ImageView buttonView,
+            final ImageView ringView, boolean show) {
+        /* Show a hide animation if view is visible or when the show variable is false */
+        if (view.getVisibility() == View.VISIBLE || !show) {
+            view.setVisibility(View.GONE);
+            buttonView.setImageResource(R.drawable.ic_rcs_expand);
+            if ((ringView != null) && mIsDataAvailable) {
+                Animation pulse = AnimationUtils.loadAnimation(getActivity(), R.anim.pulse);
+                ringView.startAnimation(pulse);
+            }
+        } else {
+            view.setVisibility(View.VISIBLE);
+            if (ringView != null) {
+                ringView.clearAnimation();
+                ringView.setVisibility(View.GONE);
+            }
+        }
+    }
+
+    /**
+     * Animation function to hide show detailed view.
+     *
+     * When detailed view is shown Collapse button is shown
+     *    when detaild view is hidden Expand button is shown.
+     *
+     * Additionally if detailed view is hidden ring animation will be shown.
+     *
+     * @param view   parent view
+     * @param buttonView  expand/collapse button view
+     * @param ringView  view to show ring animation on expand/collapse button
+     * @param show  hide/show detailed view with animation
+     */
+    private void animate(final View view, final ImageView buttonView,
+            final ImageView ringView, boolean show) {
+        /* Show a hide animation if view is visible or when the show variable is false */
+        if (view.getVisibility() == View.VISIBLE || !show) {
+
+            Animation animation = AnimationUtils.loadAnimation(getActivity(),
+                    R.anim.scale_in);
+            //Setting animation duration for collapsing detailed view.
+            animation.setDuration(getResources()
+                    .getInteger(R.integer.collapse_duration));
+            animation.setAnimationListener(new Animation.AnimationListener() {
+
+                @Override
+                public void onAnimationStart(Animation animation) {
+                }
+
+                @Override
+                public void onAnimationEnd(Animation animation) {
+                    view.setVisibility(View.GONE);
+                    buttonView.setImageResource(R.drawable.ic_rcs_expand);
+                    if ((ringView != null)
+                            && mIsDataAvailable) {
+                        Animation pulse = AnimationUtils.loadAnimation(getActivity(),
+                                R.anim.pulse);
+                        ringView.startAnimation(pulse);
+                    }
+                }
+
+                @Override
+                public void onAnimationRepeat(Animation animation) {
+                }
+            });
+            view.startAnimation(animation);
+
+        } else {
+
+            view.setVisibility(View.VISIBLE);
+            Animation animation = AnimationUtils.loadAnimation(getActivity(),
+                    R.anim.scale_out);
+            //Setting animation duration for expand detailed view.
+            animation.setDuration(getResources().getInteger(R.integer.
+                    expand_duration));
+            animation.setAnimationListener(new Animation.AnimationListener() {
+
+                @Override
+                public void onAnimationStart(Animation animation) {
+                }
+
+                @Override
+                public void onAnimationEnd(Animation animation) {
+                    buttonView.setImageResource(R.drawable.ic_rcs_collpase);
+                    if (ringView != null) {
+                        ringView.clearAnimation();
+                        ringView.setVisibility(View.GONE);
+                    }
+
+                }
+
+                @Override
+                public void onAnimationRepeat(Animation animation) {
+                }
+            });
+            view.startAnimation(animation);
+        }
+
+
+    }
+
+    private void setMiniUi(View parent, boolean isMinimized) {
+
+        int pxMiniViewHeight = (int) getResources().
+                getDimension(R.dimen.mini_view_picture_height);
+        int pxExpandedViewHeight = (int) getResources().
+                getDimension(R.dimen.expanded_view_picture_height);
+
+
+        ImageView picture = (ImageView) parent.findViewById(R.id.picture);
+        ImageView map = (ImageView) parent.findViewById(R.id.map);
+
+        int dimensionInPx = pxExpandedViewHeight;
+
+        if (isMinimized) {
+            dimensionInPx = pxMiniViewHeight;
+        }
+
+        picture.getLayoutParams().height = dimensionInPx;
+        map.getLayoutParams().height = dimensionInPx;
+
+        map.requestLayout();
+        picture.requestLayout();
+
+        parent.requestLayout();
+
+    }
+
+    /**
+     * showDetailedNotes will be called to display the note message in a alert dialog so that
+     * full text can be shown in an dialog message.
+     *
+     * @param String message to display
+     */
+    private void showDetailedNotes(String message) {
+        AlertDialog alertDialog = null;
+
+        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+        builder.setMessage(message);
+        builder.setPositiveButton(android.R.string.ok, new DialogInterface
+                .OnClickListener() {
+            @Override
+            public void onClick(DialogInterface dialogInterface, int i) {
+                dialogInterface.dismiss();
+            }
+        });
+
+        alertDialog = builder.create();
+        alertDialog.show();
+    }
+
+    /**
+     * isInForground function can be used to know if the incall activity is showing or not.
+     *
+     * @return boolean, true if incall activity is showing else false.
+     */
+    public boolean isInForground() {
+        return InCallPresenter.getInstance().isShowingInCallUi();
+    }
+
+    /**
+     * hasReadStoragePermission function can be used to know if the access to read storage
+     * permission is granted or not.
+     *
+     * @return boolean, true if permission is granted else false.
+     */
+    public boolean hasReadStoragePermission() {
+        return getContext().checkPermission(
+                Manifest.permission.READ_EXTERNAL_STORAGE, Process.myPid(),
+                Process.myUid()) == PackageManager.PERMISSION_GRANTED;
+    }
+
+    /**
+     * isPermissionPending function is used to know if request permission is under process of not.
+     *
+     * @return boolean, true if request permission is pending else false.
+     */
+    public boolean isPermissionPending() {
+        return mIsPresmissionReqPending;
+    }
+
+    /**
+     * requestReadStoragePermission function is used to initiate the process to show a dialog to
+     * user to grant the read strorage permission.
+     */
+    public synchronized void requestReadStoragePermission() {
+        Log.d(this, "requestReadStoragePermission");
+        mIsPresmissionReqPending = true;
+        boolean canReadExternalStorage = hasReadStoragePermission();
+        if (!canReadExternalStorage) {
+            if (canShowPermissionInfoDlg()) {
+                showAccessPermissionDialog();
+            } else {
+                requestAskPermission();
+            }
+        } else {
+            Log.d(this, "already permission granted");
+            getPresenter().onReadStoragePermission(true);
+            mIsPresmissionReqPending = false;
+        }
+    }
+
+    /**
+     * This function will show a pre request permission dialog from Incall application,
+     * and this dialog explains hte user that why we need to read storage permission.
+     * Once user presses yes in this dialog then it will ask the actual AOSP permission dialog.
+     * If user presses No then it will simply ignore.
+     *
+     * Note: this explanation dialog will be show to the user only 1 time to avoid showing it
+     * multiple times.
+     */
+    private void showAccessPermissionDialog() {
+        AlertDialog.Builder builder = new AlertDialog.Builder(getContext(),
+                AlertDialog.THEME_DEVICE_DEFAULT_LIGHT);
+        builder.setMessage(R.string.access_permission_message)
+                .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
+                    public void onClick(DialogInterface dialog, int id) {
+                        if (InCallPresenter.getInstance().isShowingInCallUi()) {
+                            requestAskPermission();
+                        }
+                    }
+                }).setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
+                    public void onClick(DialogInterface dialog, int id) {
+                        mIsPresmissionReqPending = false;
+                        getPresenter().onReadStoragePermission(false);
+                    }
+                });
+        AlertDialog dialog = builder.create();
+        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+        dialog.show();
+        shownPremissionInfoDlg();
+    }
+
+    @Override
+    public void onRequestPermissionsResult(int requestCode, String permissions[],
+                int[] grantResults) {
+        Log.d(this, "onRequestPermissionsResult");
+        switch (requestCode) {
+            case MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE: {
+                // If request is cancelled, the result arrays are empty.
+                mIsPresmissionReqPending = false;
+                getPresenter().onReadStoragePermission(grantResults != null
+                        && grantResults.length > 0
+                        && grantResults[0] == PackageManager.PERMISSION_GRANTED);
+            }
+        }
+    }
+
+    /**
+     * Process AOSP request permission for read external storage permission.
+     */
+    private void requestAskPermission() {
+        requestPermissions(new String[] { Manifest.permission.READ_EXTERNAL_STORAGE},
+                MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE);
+    }
+
+    /**
+     * canShowPermissionInfoDlg function can be use to know if Incall application can show
+     * Permission info dialog.
+     *
+     * @return true if need to display, false if already display before.
+     */
+    private boolean canShowPermissionInfoDlg() {
+        SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
+        return !sharedPref.getBoolean(PREFERENCE_SHOWN_INFO_DLG_KEY, false);
+    }
+
+    /**
+     * shownPremissionInfoDlg function is to write the sharedpreference that request permission
+     * info dialog is already displayed.
+     */
+    private void shownPremissionInfoDlg() {
+        SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
+        SharedPreferences.Editor editor = sharedPref.edit();
+        editor.putBoolean(PREFERENCE_SHOWN_INFO_DLG_KEY, true);
+        editor.commit();
+    }
+
+}
diff --git a/InCallUI/src/com/android/incallui/RcsCallHandler.java b/InCallUI/src/com/android/incallui/RcsCallHandler.java
new file mode 100644
index 0000000..5ee875b
--- /dev/null
+++ b/InCallUI/src/com/android/incallui/RcsCallHandler.java
@@ -0,0 +1,176 @@
+/**
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.android.incallui;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * RcsCallHandler class is a singleton class
+ * and this class will handle the RcsCallInfo object of each call.
+ * One can get the RcsCallInfo by calling function getRcsCallInfo.
+ */
+public class RcsCallHandler implements CallList.Listener {
+
+    private static RcsCallHandler sRcsCallHandler;
+
+    /* This mRcsCallInfoContainer is used to save the call vs RcsCallInfo in a hash map
+     * the hasmap will be updated accordingly when a call is initiated and when a call is
+     * disconnected
+     */
+    private ConcurrentHashMap<Call, RcsCallInfo> mRcsCallInfoContainer
+            = new ConcurrentHashMap<Call, RcsCallInfo>();
+
+    /**
+     * makeing it as a singleton class.
+     */
+    private RcsCallHandler() {
+        CallList.getInstance().addListener(this);
+    }
+
+    /**
+     * getInstance will return a singleton instance of RcsCallHandler
+     *
+     * @return RcsCallHandler
+     */
+    public static RcsCallHandler getInstance() {
+        if (sRcsCallHandler == null) {
+            sRcsCallHandler = new RcsCallHandler();
+        }
+        return sRcsCallHandler;
+    }
+
+    /**
+     * getRcsCallInfo function will return the RcsCallInfo from mRcsCallInfoContainer
+     * if available.
+     *
+     * @param Call
+     * @return RcsCallInfo, null if did not find RcsCallInfo.
+     */
+    public RcsCallInfo getRcsCallInfo(Call call) {
+        if (call == null || !mRcsCallInfoContainer.containsKey(call)) {
+            log("getRcsCallInfo : returning null");
+            return null;
+        }
+        return mRcsCallInfoContainer.get(call);
+    }
+
+    /**
+     * addRcsCallInfo function will add a hashmap entry of Call and RcsCallInfo.
+     *
+     * @param Call
+     * @param RcsCallInfo
+     */
+    private void addRcsCallInfo(Call call, RcsCallInfo callInfo) {
+        log("addRcsCallInfo : " + call + " RcsCallInfo : " + callInfo);
+        if(call != null && callInfo != null) {
+            mRcsCallInfoContainer.put(call, callInfo);
+        }
+        log("mRcsCallInfoContainer content : " + mRcsCallInfoContainer);
+    }
+
+    /**
+     * removeRcsCallInfo function will remove the hashmap entry of Call.
+     *
+     * @param Call
+     */
+    private void removeRcsCallInfo(Call call) {
+        log("removeRcsCallInfo: " + call);
+        mRcsCallInfoContainer.remove(call);
+        log("mRcsCallInfoContainer content : " + mRcsCallInfoContainer);
+    }
+
+    private boolean requestAddRcsCallInfo(Call call) {
+        if (call != null && getRcsCallInfo(call) == null) {
+            addRcsCallInfo(call, new RcsCallInfo(call));
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void onIncomingCall(Call call) {
+        log("onIncomingCall: " + call);
+        if (requestAddRcsCallInfo(call)) {
+             log("Added IncomingCall");
+             return;
+         }
+    }
+
+    @Override
+    public void onUpgradeToVideo(Call call) {
+    }
+
+    @Override
+    public void onCallListChange(CallList callList) {
+        log("onCallListChange: " + callList);
+        /*
+         * get the call for each state and check if the call can be added to RCS call list.
+         * If it is successful then just return from the function.
+         */
+        Call call = callList.getIncomingCall();
+        if (requestAddRcsCallInfo(call)) {
+            log("Added IncomingCall");
+            return;
+        }
+
+        call = callList.getPendingOutgoingCall();
+        if (requestAddRcsCallInfo(call)) {
+            log("Added PendingOutgoing call");
+            return;
+        }
+
+        call = callList.getOutgoingCall();
+        if (requestAddRcsCallInfo(call)) {
+            log("Added outgoing call");
+            return;
+        }
+
+        call = callList.getActiveCall();
+        if (requestAddRcsCallInfo(call)) {
+            log("Added active call");
+            return;
+        }
+
+        call = callList.getBackgroundCall();
+        if (requestAddRcsCallInfo(call)) {
+            log("Added Background call");
+            return;
+        }
+    }
+
+    @Override
+    public void onDisconnect(Call call) {
+        log("onDisconnect: " + call);
+        removeRcsCallInfo(call);
+    }
+
+    private void log(String msg) {
+        Log.d(this,msg);
+    }
+}
diff --git a/InCallUI/src/com/android/incallui/RcsCallInfo.java b/InCallUI/src/com/android/incallui/RcsCallInfo.java
new file mode 100644
index 0000000..4e9af0d
--- /dev/null
+++ b/InCallUI/src/com/android/incallui/RcsCallInfo.java
@@ -0,0 +1,168 @@
+/**
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.android.incallui;
+
+import android.content.Context;
+import org.codeaurora.rcscommon.CallComposerData;
+import org.codeaurora.rcscommon.RcsManager;
+import android.os.Bundle;
+/**
+ * RcsCallInfo will contain the RCS call data with location and shared image data.
+ * Each object of this class will be associated with the a perticular call
+ * which is sent in constructor.
+ */
+public class RcsCallInfo {
+
+    public enum AccessPermissionStatus {
+        UNKNOWN, GRANTED, NOT_GRANTED
+    }
+
+    private byte[] mLocationImageArray = null;
+
+    private boolean isLocationImageReqested = false;
+
+    private Call mCall;
+
+    private AccessPermissionStatus mPermissionStatus = AccessPermissionStatus.UNKNOWN;
+
+    /**
+     * Default constructor can not be called as Call object is mandatory to initialize or create
+     * RcsCallInfo object.
+     */
+    private RcsCallInfo() {
+    }
+
+    /**
+     * Constructor  of RcsCallInfo
+     * @param : Call object to handle Enrich call data operations.
+     */
+    public RcsCallInfo(Call call) {
+        mCall = call;
+    }
+
+    /**
+     * Request to get the location image
+     *
+     * @param : int width of the image which need to be fetched
+     * @param : int height of the image which need to be fetched
+     * @param : Context
+     */
+    public void requestRcsLocationImage(int width, int height, Context context) {
+        Log.d(this,"requestRcsLocationImage");
+        if (!isLocationImageReqested) {
+            isLocationImageReqested = true;
+            CallComposerData data = getCallComposerData();
+            new InCallRcsImageDownloader(context)
+                .requestFetchLocationImage(width, height, data.getLatitude(),
+                    data.getLongitude(), new InCallRcsImageDownloader.
+                    FetchImageListener() {
+
+                public void onFetchedImage(byte[] arr) {
+                    mLocationImageArray = arr;
+                    if (RcsCallFragment.getPresenterInstance() != null) {
+                        RcsCallFragment.getPresenterInstance().forceUpdateUi();
+                    }
+                }
+            });
+        } else {
+            Log.d(this, "isLocationImageReqested : " + isLocationImageReqested);
+        }
+    }
+
+    /**
+     * check if any operations are pending to fetch location image.
+     * @return boolean true if pending else false.
+     */
+    public boolean isLocImageReqested() {
+        return isLocationImageReqested;
+    }
+
+    /**
+     * check if the call is enrich call or not
+     * @return boolean true if Enrich call else false
+     */
+    public boolean isEnrichedCall() {
+        return getCallComposerData() != null ? getCallComposerData().isValid() : false;
+    }
+
+    /**
+     * get the callcomposerdata.
+     * @return CallComposerData, null if the call is not a RCS call. else the actual
+     * RCS call content(CallComposerData)
+     */
+    public CallComposerData getCallComposerData() {
+        if (mCall == null || mCall.getTelecomCall() == null) {
+            return null;
+        }
+        Bundle extras = mCall.getTelecomCall().getDetails().getExtras();
+        CallComposerData data = null;
+        if (extras == null ||
+                extras.getBundle(RcsManager.ENRICH_CALL_INTENT_EXTRA) == null) {
+            extras = mCall.getTelecomCall().getDetails().getIntentExtras();
+            if (extras != null) {
+                data = new CallComposerData(extras.getBundle(
+                        RcsManager.ENRICH_CALL_INTENT_EXTRA));
+                Log.d(this, "getCallComposerData() from Intent Extras: " + data);
+            }
+        } else {
+            data = new CallComposerData(
+                    extras.getBundle(RcsManager.ENRICH_CALL_INTENT_EXTRA));
+            Log.d(this, "getCallComposerData() from Extras: " + data);
+        }
+        return data;
+    }
+
+    /**
+     * get the permission status to access shared image.
+     * @return AccessPermissionStatus, GRANTED if the previous request is granted.
+     * NOT_GRANTED if the previous request was not granted.
+     * UNKNOWN if the request is not made yet for this call.
+     */
+    public AccessPermissionStatus getPermissionStatus(){
+        return mPermissionStatus;
+    }
+
+    /**
+     * set the permission status.
+     * @param boolean granted. true if GRANTED else false means NOT_GRANTED.
+     */
+    public void setPermissionStatus(boolean granted) {
+        mPermissionStatus = granted ? AccessPermissionStatus.GRANTED
+                : AccessPermissionStatus.NOT_GRANTED;
+    }
+
+    /**
+     * get the location image byte array
+     * @return byte array, null if image is null.
+     */
+    public byte[] getLocationImageArray() {
+        return mLocationImageArray;
+    }
+
+}
diff --git a/InCallUI/src/com/android/incallui/RcsCallPresenter.java b/InCallUI/src/com/android/incallui/RcsCallPresenter.java
new file mode 100644
index 0000000..ffb85e1
--- /dev/null
+++ b/InCallUI/src/com/android/incallui/RcsCallPresenter.java
@@ -0,0 +1,602 @@
+/**
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.android.incallui;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.telecom.Call.Details;
+import android.util.TypedValue;
+import com.android.incallui.InCallPresenter.InCallState;
+import com.android.incallui.InCallPresenter.InCallStateListener;
+import com.android.incallui.InCallPresenter.InCallDetailsListener;
+import com.android.incallui.InCallPresenter.IncomingCallListener;
+
+import java.util.Locale;
+
+import org.codeaurora.rcscommon.CallComposerData;
+import org.codeaurora.rcscommon.EnrichedCallState;
+import org.codeaurora.rcscommon.RcsManager;
+
+/**
+ * RcsCallPresenter is a presenter to handle the RcsCallFragement. all rcs relatred
+ * view will be handled with RcsCallPresenter.
+ */
+public class RcsCallPresenter extends Presenter<RcsCallPresenter.RcsCallUi>
+        implements InCallStateListener, IncomingCallListener,
+        InCallDetailsListener, InCallPresenter.InCallEventListener {
+
+    public interface RcsCallUi extends Ui {
+        void updateCallComposerData(RcsCallInfo info);
+        Context getContext();
+        int getMapImageViewWidth();
+        int getMapImageViewHeight();
+        void setEnabled(boolean enabled);
+        void setVisible(boolean visible);
+        void showSmallView(boolean showSmall);
+        void showEnrichCallFailed(CallComposerData.PRIORITY priority);
+        void showEnrichCallDetail();
+        void hideEnrichCallDetail();
+        boolean hasReadStoragePermission();
+        void requestReadStoragePermission();
+        boolean isPermissionPending();
+        boolean isInForground();
+    }
+
+    public interface ImageBitmapListener {
+        void onFetchBitmap(Bitmap bitmap);
+    }
+
+    private static final int REQUEST_MAP_IMAGE = 1;
+    private static final int REQUEST_SHARED_IMAGE = 2;
+    private CallComposerData mCallComposerData = null;
+
+    private Handler mHandler = new Handler() {
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+            case REQUEST_MAP_IMAGE:
+                Call call = (Call) msg.obj;
+                requestRcsLocationImage(call);
+                break;
+            case REQUEST_SHARED_IMAGE:
+                call = (Call) msg.obj;
+                requestRcsSharedImage(call);
+                break;
+            }
+        }
+    };
+
+    private RcsCallHandler mRcsCallHandler = RcsCallHandler.getInstance();
+
+    public RcsCallPresenter() {
+        Log.d(this, "constructor");
+    }
+
+    @Override
+    public void onUiReady(RcsCallUi ui) {
+        Log.d(this, "onUiReady");
+        super.onUiReady(ui);
+        final InCallActivity activity = InCallPresenter.getInstance()
+                .getActivity();
+        InCallPresenter.getInstance().addListener(this);
+        InCallPresenter.getInstance().addIncomingCallListener(this);
+        InCallPresenter.getInstance().addDetailsListener(this);
+        InCallPresenter.getInstance().addInCallEventListener(this);
+        onStateChange(InCallState.NO_CALLS, InCallPresenter.getInstance()
+            .getInCallState(), CallList.getInstance());
+
+    }
+
+    @Override
+    public void onUiUnready(RcsCallUi ui) {
+        Log.d(this, "onUiUnready");
+        super.onUiUnready(ui);
+        InCallPresenter.getInstance().removeListener(this);
+        InCallPresenter.getInstance().removeIncomingCallListener(this);
+        InCallPresenter.getInstance().removeDetailsListener(this);
+        InCallPresenter.getInstance().removeInCallEventListener(this);
+        mCallComposerData = null;
+    }
+
+    @Override
+    public void onStateChange(InCallState oldState, InCallState newState,
+            CallList callList) {
+        Log.d(this, "onStateChange");
+        updateRichCallView(getCurrentCall());
+    }
+
+    private Call getCurrentCall() {
+        Call call = null;
+        CallList callList = CallList.getInstance();
+        InCallState newState = InCallPresenter.getInstance().getInCallState();
+        if (newState == InCallState.INCOMING) {
+            call = callList.getIncomingCall();
+        } else if (newState == InCallState.PENDING_OUTGOING
+                || newState == InCallState.OUTGOING) {
+            call = callList.getOutgoingCall();
+            if (call == null) {
+                call = callList.getPendingOutgoingCall();
+            }
+        } else if (newState == InCallState.INCALL) {
+            call = getCallToDisplay(callList);
+        }
+        return call;
+    }
+
+    private void updateRichCallView(Call call) {
+        Log.d(this ,"updateRichCallView");
+        RcsCallUi ui = getUi();
+        if (call != null && ui != null) {
+
+            RcsCallInfo callInfo = getRcsCallInfo(call);
+            CallComposerData data = callInfo != null ? callInfo.getCallComposerData() : null;
+            //Just for debugging purpose
+            Log.d(this ,"call state : " + call.getState());
+            Log.d(this ,"data : " + data);
+            Log.d(this ,"mCallComposerData : " + mCallComposerData);
+
+            /*
+             * Hide the RCS UI for conference call or for video call
+             */
+            if (call.isConferenceCall() || call.isVideoCall(ui.getContext())) {
+                Log.d(this," in conf call or VT call ");
+                ui.setVisible(false);
+                mCallComposerData = null;
+                return;
+            }
+
+            /*
+             * Update rcs content on UI only if we are updating for the first time
+             * and the RCS content is valid or current RCSContent should not be null
+             * and should not be same as previous. And new RCS content should be valid.
+             */
+            if ((mCallComposerData == null && data != null && data.isValid())
+                    || (mCallComposerData != null && !mCallComposerData.equals(data)
+                        && (data != null && data.isValid()))) {
+                /*
+                 * If RCS call state is falied then hide the UI
+                 * and show a enrich call failed toast message, else show the UI.
+                 */
+                if (data.getCallState() == EnrichedCallState.FAILED) {
+                    Log.d(this,"Enriched call failed");
+                    ui.setVisible(false);
+                } else {
+                    Log.d(this,"Setting visible");
+                    ui.setVisible(true);
+                }
+
+                /*
+                 * For a incoming call or waiting call show a small RCS view.
+                 * and disable the RCS view.
+                 *
+                 * Show enabled and show full view in case of non INCOMING/WAITING call.
+                 */
+                if(call.getState() == Call.State.INCOMING
+                        || call.getState() == Call.State.CALL_WAITING) {
+                    ui.setEnabled(false);
+                    ui.showSmallView(true);
+                } else {
+                    ui.setEnabled(true);
+                    ui.showSmallView(false);
+                }
+                updateUi(call);
+            } else if ((data != null && !data.isValid()) || data == null) {
+                /*
+                 * if new data is not valid or if new data is null then hide the UI
+                 */
+                Log.d(this,"content not valid");
+                ui.setVisible(false);
+                /*
+                 * show the enrich call failed message only once when moving state from
+                 * mCallComposerData null to new callcomposerdata call state is FAILED
+                 * or from valid mCallComposerData to new callcomposerdata call state is FAILED
+                 */
+                if ((mCallComposerData == null && data != null
+                        && data.getCallState() == EnrichedCallState.FAILED)
+                        || (mCallComposerData != null
+                        && mCallComposerData.getCallState() != EnrichedCallState.FAILED
+                        && data != null && data.getCallState() == EnrichedCallState.FAILED)) {
+                    Log.d(this, "show enrich call failed toast message");
+                    ui.showEnrichCallFailed(mCallComposerData.getPriority());
+                }
+                mCallComposerData = data;
+            }
+
+            /*
+             * For a incoming call or waiting call show a small RCS view.
+             * and disable the RCS view.
+             */
+            if (call.getState() != Call.State.CALL_WAITING
+                    && call.getState() != Call.State.INCOMING) {
+                ui.showSmallView(false);
+                ui.showEnrichCallDetail();
+            } else {
+                ui.showSmallView(true);
+            }
+
+            /*
+             * Request to get the Shared Image or Location Image for RCSService.
+             */
+            if (mCallComposerData != null && mCallComposerData.isValid()) {
+                boolean hasMapImgMsg = mHandler.hasMessages(REQUEST_MAP_IMAGE);
+                boolean hasShardImgMsg = mHandler.hasMessages(REQUEST_SHARED_IMAGE);
+
+                boolean canReqSharedImg = canRequestSharedImage(call);
+                boolean canReqLocImg = canRequestLocImage(call);
+                Log.d(this, "has REQUEST_MAP_IMAGE msg : " + hasMapImgMsg
+                        + " canReqLocImg : " + canReqLocImg);
+                Log.d(this, "has REQUEST_SHARED_IMAGE msg : " + hasShardImgMsg
+                         + " canReqSharedImg : " + canReqSharedImg);
+                if(!hasMapImgMsg && canReqLocImg) {
+                    Message msg = new Message();
+                    msg.obj = call;
+                    msg.what = REQUEST_MAP_IMAGE;
+                    mHandler.sendMessage(msg);
+                }
+                if(!hasShardImgMsg && canReqSharedImg) {
+                    Message msg = new Message();
+                    msg = new Message();
+                    msg.obj = call;
+                    msg.what = REQUEST_SHARED_IMAGE;
+                    mHandler.sendMessage(msg);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void onDetailsChanged(Call call, android.telecom.Call.Details
+            details) {
+        Log.d(this, "onDetailsChanged");
+        updateRichCallView(getCurrentCall());
+    }
+
+    @Override
+    public void onIncomingCall(InCallState oldState, InCallState newState,
+            Call call) {
+        Log.d(this, "onIncomingCall");
+        updateRichCallView(getCurrentCall());
+    }
+
+    /**
+     * update the UI according to call.
+     * If call is RCS call then RCS content will be updated accordingly on the UI.
+     * If the call is non RCS call then no RCS content will be displayed.
+     */
+    private void updateUi(Call call) {
+        Log.d(this ,"updateUi");
+        if (call == null) {
+            Log.d(this ,"cant update call is null");
+            return;
+        }
+        RcsCallInfo callInfo = getRcsCallInfo(call) ;
+        CallComposerData data = callInfo != null ? callInfo.getCallComposerData() : null;
+        if(getUi() == null || data == null) {
+            Log.d(this ,"UI is null or data is null");
+            return;
+        }
+        getUi().updateCallComposerData(callInfo);
+        mCallComposerData = data;
+    }
+
+    protected void forceUpdateUi(){
+        Log.d(this ,"forceUpdateUi");
+        updateUi(getCurrentCall());
+    }
+
+    /**
+     * request to get the rcs shared image for a call, if available.
+     *
+     * @param Call
+     */
+    public void requestRcsSharedImage(Call call) {
+        Log.d(this, "requestRcsSharedImage : call: ");
+        RcsCallInfo callInfo = getRcsCallInfo(call) ;
+        if (call == null || callInfo == null || callInfo.getCallComposerData() == null) {
+            Log.d(this, " call or rcscallhelper or enrichcalldata is null");
+            return;
+        }
+
+        CallComposerData data = callInfo.getCallComposerData();
+        if (data != null && data.isValidSharedImageUri() && getUi() != null) {
+            Log.d(this, "requesting for permission ");
+            getUi().requestReadStoragePermission();
+        } else {
+            Log.d(this, "not a valid sharedimage or shared image is already downloaded"
+                    + "or UI is null, hence ignoring");
+        }
+    }
+
+    /**
+     * request to get the rcs location image for a call, if available.
+     *
+     * @param Call
+     */
+    public void requestRcsLocationImage(Call call) {
+        Log.d(this, "requestRcsLocationImage : call: " + call);
+        int width = getUi() != null ? getUi().getMapImageViewWidth() : 0;
+        int height = getUi() != null ? getUi().getMapImageViewHeight() : 0;
+        Log.d(this, "requestRcsLocationImage : width : " + width
+                    + " height: " + height);
+
+        RcsCallInfo callInfo = getRcsCallInfo(call) ;
+        if (call == null || callInfo == null || callInfo.getCallComposerData() == null) {
+            Log.d(this, " call or rcscallhelper or enrichcalldata is null");
+            return;
+        }
+        CallComposerData data = callInfo.getCallComposerData();
+        if (data != null && data.isValidLocation() && (callInfo.getLocationImageArray() == null
+                || callInfo.getLocationImageArray().length == 0)
+                && width != 0 && height != 0 && getUi() != null) {
+
+            Log.d(this, "calling requestRcsLocationImage ");
+
+            callInfo.requestRcsLocationImage(width, height,
+                    getUi().getContext());
+        } else {
+            Log.d(this, "not a valid location or location image is already download"
+                    + " or view width/height is 0 or UI is null, hence ignoring");
+        }
+    }
+
+    /**
+     * onSharedImageClicked will be called from the RcsCallFragment when shared image view
+     * is clicked.
+     *
+     * @param uri of the image
+     */
+    public void onSharedImageClicked(Uri uri) {
+        Log.d(this,"onSharedImageClicked : " + uri);
+        Intent intent = new Intent();
+        intent.setAction(Intent.ACTION_VIEW);
+        if(uri != null && !uri.toString().startsWith("file")) {
+            uri = Uri.parse("file://" + uri.getSchemeSpecificPart());
+        }
+        intent.setDataAndType(uri, "image/*");
+        if (intent.resolveActivity(getUi().getContext().getPackageManager()) != null) {
+            getUi().getContext().startActivity(intent);
+        } else {
+            QtiCallUtils.displayToast(getUi().getContext(),
+                    R.string.can_not_launch_image_application);
+        }
+    }
+
+    /**
+     * onMapImageClicked will be called from the RcsCallFragment when Location image view
+     * is clicked.
+     *
+     * @param double latitude
+     * @param double longitude
+     */
+    public void onMapImageClicked(double latitude, double longitude) {
+        String uri = String.format(Locale.ENGLISH, "geo:%f,%f?q=%f,%f", latitude,
+                longitude, latitude, longitude);
+        Log.d(this,"GEO : " + uri);
+        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri));
+        if (intent.resolveActivity(getUi().getContext().getPackageManager()) != null) {
+            getUi().getContext().startActivity(intent);
+        } else {
+            QtiCallUtils.displayToast(getUi().getContext(),
+                    R.string.can_not_launch_maps_application);
+        }
+    }
+
+    /**
+     * onReadStoragePermission will be called from the RcsCallFragment when a read storage access
+     * permission is either accepted or rejected.
+     *
+     * @param boolean granted. true if accepted else false.
+     */
+    public void onReadStoragePermission(boolean granted) {
+        Log.d(this,"onReadStoragePermission : " + granted);
+        Call call = getCurrentCall();
+        if (call != null) {
+            RcsCallInfo callInfo = mRcsCallHandler.getRcsCallInfo(call);
+            if(callInfo != null) {
+                callInfo.setPermissionStatus(granted);
+            }
+        }
+        if (granted) {
+            updateUi(call);
+        }
+    }
+
+    /**
+     * Get the highest priority call to display.
+     * Goes through the calls and chooses which to return based on priority of which type of call
+     * to display to the user.
+     *
+     * @param CallList
+     */
+    private Call getCallToDisplay(CallList callList) {
+        // Active calls come second.  An active call always gets precedent.
+        Call retval = callList.getActiveCall();
+        if (retval != null) {
+            return retval;
+        }
+        retval = callList.getDisconnectingCall();
+        if (retval != null) {
+            return retval;
+        }
+        retval = callList.getDisconnectedCall();
+        if (retval != null) {
+            return retval;
+        }
+        // Then we go to background call.
+        retval = callList.getBackgroundCall();
+        if (retval != null) {
+            return retval;
+        }
+
+        // At last, get second background call.
+        retval = callList.getSecondBackgroundCall();
+
+        return retval;
+    }
+
+    /**
+     * This function is used to check if we can request to get shared image.
+     *
+     * @return  true if there is a valid callcomposerdata attached to call and it is valid
+     * and if the callcomposerdata has the valid shared image uri/path
+     * and application has the read storage permission
+     * and there are no pending request get read storage permission request. Else returns false.
+     *
+     * Note: this function returns false if application is not having read external storage
+     *       permission and the same time call state is INCOMING or CALL_WAITING
+     */
+    private boolean canRequestSharedImage(Call call) {
+        boolean incomingCall = call != null && (call.getState() == Call.State.INCOMING
+                || call.getState() == Call.State.CALL_WAITING);
+
+        RcsCallInfo callInfo = mRcsCallHandler.getRcsCallInfo(call);
+        CallComposerData data = callInfo.getCallComposerData();
+
+        return data != null && data.isValid()
+                && data.isValidSharedImageUri() && call != null
+                && (!getUi().hasReadStoragePermission() ? !incomingCall : true)
+                && !getUi().isPermissionPending()
+                && callInfo != null
+                && callInfo.getPermissionStatus() != RcsCallInfo.AccessPermissionStatus.NOT_GRANTED
+                && getUi().isInForground();
+    }
+
+    /**
+     * This function is used to check if we can request to get location image.
+     *
+     * @return  true if there is a valid callcomposerdata attached to call and it is valid
+     * and if the callcomposerdata has the valid location coordinates
+     * and there are no pending request to fetch location image
+     * and if the location image is not downloaded yet. Else returns false.
+     */
+    private boolean canRequestLocImage(Call call) {
+        RcsCallInfo callInfo = getRcsCallInfo(call);
+        CallComposerData data = callInfo.getCallComposerData();
+        return data != null && data.isValid()
+                && call != null && callInfo != null
+                && !callInfo.isLocImageReqested()
+                && data.isValidLocation()
+                && (callInfo.getLocationImageArray() == null
+                || callInfo.getLocationImageArray().length == 0);
+    }
+
+    /**
+     * getRcsCallInfo function will provide the RcsCallInfo for a
+     * perticular call.
+     *
+     * @return RcsCallInfo, null if RcsCallInfo did not find.
+     */
+    private RcsCallInfo getRcsCallInfo(Call call) {
+        return mRcsCallHandler.getRcsCallInfo(call);
+    }
+
+    /**
+     * updateImageFromUri function will be called from RcsCallFragment to get the bitmap
+     * form a Uri to display the bitmap in an image view.
+     *
+     * @param Uri, image uri
+     * @param ImageBitmapListener callback listener to get the bitmap object
+     */
+    public void updateImageFromUri(final Uri uri, final ImageBitmapListener listener) {
+        Log.d(this, "updateImageFromBytes ");
+        AsyncTask<Void, Void, Bitmap> task = new AsyncTask<Void, Void, Bitmap>() {
+            @Override
+            protected Bitmap doInBackground(Void... params) {
+                return BitmapFactory.decodeFile(uri.getSchemeSpecificPart());
+            }
+
+            @Override
+            protected void onPostExecute(Bitmap image) {
+                listener.onFetchBitmap(image);
+            }
+        };
+        task.execute(null, null, null);
+    }
+
+    /**
+     * updateImageFromBytes function will be called from RcsCallFragment to get the bitmap
+     * form a byte array to display the bitmap in an image view.
+     *
+     * @param byte[], image bytes
+     * @param ImageBitmapListener callback listener to get the bitmap object
+     */
+    public void updateImageFromBytes(final byte[] arr, final ImageBitmapListener listener) {
+        Log.d(this, "updateImageFromBytes ");
+        AsyncTask<Void, Void, Bitmap> task = new AsyncTask<Void, Void, Bitmap>() {
+            @Override
+            protected Bitmap doInBackground(Void... params) {
+                return BitmapFactory.decodeByteArray(arr, 0, arr.length);
+            }
+
+            @Override
+            protected void onPostExecute(Bitmap image) {
+                listener.onFetchBitmap(image);
+            }
+        };
+        task.execute(null, null, null);
+    }
+
+    @Override
+    public void onFullscreenModeChanged(boolean isFullscreenMode) {
+    }
+
+    @Override
+    public void onSecondaryCallerInfoVisibilityChanged(boolean isVisible, int height) {
+    }
+
+    @Override
+    public void onIncomingVideoAvailabilityChanged(boolean isAvailable) {
+    }
+
+    @Override
+    public void onSendStaticImageStateChanged(boolean isEnabled) {
+    }
+
+    @Override
+    public void onAnswerViewGrab(boolean isGrabbed) {
+        Log.d(this, "onAnswerViewGrab : " + isGrabbed);
+        if(isGrabbed) {
+            getUi().hideEnrichCallDetail();
+        } else {
+            getUi().showEnrichCallDetail();
+        }
+    }
+
+    @Override
+    public void updatePrimaryCallState() {
+    }
+
+}
diff --git a/InCallUI/src/com/android/incallui/StatusBarNotifier.java b/InCallUI/src/com/android/incallui/StatusBarNotifier.java
index 1efa3cc..7bd35a3 100644
--- a/InCallUI/src/com/android/incallui/StatusBarNotifier.java
+++ b/InCallUI/src/com/android/incallui/StatusBarNotifier.java
@@ -399,8 +399,16 @@
             builder.setCategory(Notification.CATEGORY_CALL);
         }
 
-        // Set the content
-        builder.setContentText(content);
+        // if enrich call and urgent the highlight text
+        // in red
+        if (InCallRcsUtils.isEnrichCall(call, mContext)) {
+            builder.setContentText(InCallRcsUtils.getEnrichContentText(
+                    mContext, call, content));
+        } else {
+            // Set the content
+            builder.setContentText(content);
+        }
+
         builder.setSmallIcon(iconResId);
         builder.setContentTitle(contentTitle);
         builder.setLargeIcon(largeIcon);
@@ -614,7 +622,11 @@
             if (supportsVoicePrivacy) {
                 resId =  R.drawable.stat_sys_vp_phone_call;
             } else {
-                resId =  R.drawable.ic_call_white_24dp;
+                if (InCallRcsUtils.isEnrichCall(call, mContext)) {
+                    resId = R.drawable.ic_enrich_call_white_24dp;
+                } else {
+                    resId =  R.drawable.ic_call_white_24dp;
+                }
             }
         }
         return resId;
@@ -642,6 +654,12 @@
             resId = R.string.notification_ongoing_call_wifi;
         }
 
+        if (InCallRcsUtils.isEnrichCall(call, mContext)) {
+            resId = InCallRcsUtils.getEnrichContentString(call,
+                    isIncomingOrWaiting);
+            return mContext.getString(resId);
+        }
+
         if (isIncomingOrWaiting) {
             if (call.isIncomingConfCall()) {
                 resId = R.string.notification_incoming_conf_call;
diff --git a/InCallUI/src/com/android/incallui/VideoCallPresenter.java b/InCallUI/src/com/android/incallui/VideoCallPresenter.java
index 92bd5e5..c3e7f38 100644
--- a/InCallUI/src/com/android/incallui/VideoCallPresenter.java
+++ b/InCallUI/src/com/android/incallui/VideoCallPresenter.java
@@ -591,6 +591,11 @@
     }
 
     @Override
+    public void onAnswerViewGrab(boolean isGrabbed) {
+        // No-op - required for RcsCallPresenter.
+    }
+
+    @Override
     public void onIncomingVideoAvailabilityChanged(boolean isAvailable) {
         //NO OP
     }
diff --git a/res/drawable-xxxhdpi/ic_dialer_sip_white_24dp.png b/res/drawable-xxxhdpi/ic_dialer_sip_white_24dp.png
new file mode 100644
index 0000000..936dd6c
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_dialer_sip_white_24dp.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_rcs_call_black_24dp.png b/res/drawable-xxxhdpi/ic_rcs_call_black_24dp.png
new file mode 100644
index 0000000..313d9ad
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_rcs_call_black_24dp.png
Binary files differ
diff --git a/res/layout/call_log_list_item_action_enriched_call.xml b/res/layout/call_log_list_item_action_enriched_call.xml
new file mode 100755
index 0000000..32f0512
--- /dev/null
+++ b/res/layout/call_log_list_item_action_enriched_call.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/rich_call_action"
+    style="@style/CallLogActionStyle"
+    android:visibility="gone" >
+
+    <FrameLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" >
+
+        <ProgressBar
+            android:id="@+id/richfetchprogressBar"
+            style="@style/CallLogActionIconStyle"
+            android:indeterminate="true"
+            android:indeterminateTint="?attr/call_log_secondary_text_color" />
+
+        <ImageView
+            android:id="@+id/richCallIcon"
+            style="@style/CallLogActionIconStyle"
+            android:alpha="0.3"
+            android:src="@drawable/ic_rcs_call_black_24dp"
+            android:visibility="gone" />
+    </FrameLayout>
+
+    <TextView
+        android:id="@+id/rich_call_action_text"
+        style="@style/CallLogActionTextStyle"
+        android:alpha="0.3"
+        android:text="@string/call_log_action_rich_call" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/call_log_list_item_actions.xml b/res/layout/call_log_list_item_actions.xml
index 4cce073..71e4c43 100644
--- a/res/layout/call_log_list_item_actions.xml
+++ b/res/layout/call_log_list_item_actions.xml
@@ -59,6 +59,8 @@
 
     </LinearLayout>
 
+    <include layout="@layout/call_log_list_item_action_enriched_call" />
+
     <LinearLayout
         android:id="@+id/video_call_action"
         style="@style/CallLogActionStyle">
diff --git a/res/layout/shortcut_list_item_rich_call_enabled.xml b/res/layout/shortcut_list_item_rich_call_enabled.xml
new file mode 100755
index 0000000..b8fd899
--- /dev/null
+++ b/res/layout/shortcut_list_item_rich_call_enabled.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:custom="http://schemas.android.com/apk/res/com.android.dialer"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_weight="1.0"
+    android:baselineAligned="false"
+    android:gravity="center_vertical"
+    android:orientation="horizontal" >
+    <FrameLayout
+        android:id="@+id/rich_call_search_group"
+        android:layout_width="@dimen/enriched_rich_call_search_group_width"
+        android:layout_weight="1"
+        android:layout_height="wrap_content">
+        <ProgressBar
+            android:id="@+id/richfetchserachprogressBar"
+            android:layout_width="@dimen/call_log_action_icon_dimen"
+            android:layout_height="@dimen/call_log_action_icon_dimen"
+            android:visibility="gone"
+            android:layout_marginLeft="@dimen/enriched_progressbar_margin_left"
+            android:layout_marginTop="@dimen/enriched_progressbar_margin_top"
+            android:indeterminate="true" />
+        <com.android.contacts.common.list.ContactListItemView
+            android:id="@+id/shortcut_rich_call"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            custom:list_item_gap_between_image_and_text="@dimen/enriched_list_item_gap_between_image_and_text"
+            custom:list_item_padding_right="@dimen/enriched_list_item_padding_right"/>
+    </FrameLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index d9c425d..0f9370a 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -178,4 +178,16 @@
     <dimen name="list_all_calls">200dp</dimen>
     <dimen name="empty_list_message_text_size_for_Marshmallow">16dp</dimen>
     <dimen name="call_log_spinner_text_size">16sp</dimen>
+
+        <!-- Enriched call integration dimensions -->
+    <dimen name="enriched_progressbar_margin_left">24dp</dimen>
+    <dimen name="enriched_progressbar_margin_top">14dp</dimen>
+    <dimen name="enriched_list_item_gap_between_image_and_text">14dp</dimen>
+    <dimen name="enriched_list_item_padding_right">2dp</dimen>
+    <dimen name="enriched_video_list_item_gap_between_image_and_text">1dp</dimen>
+    <dimen name="enriched_video_list_item_padding_left">0dp</dimen>
+    <dimen name="enriched_video_list_item_padding_right">5dp</dimen>
+    <dimen name="enriched_rich_call_search_group_width">0dp</dimen>
+    <dimen name="enriched_shortcut_video_call_width">0dp</dimen>
+
 </resources>
diff --git a/res/values/qtistrings.xml b/res/values/qtistrings.xml
index 73fbf5c..bde2e3a 100644
--- a/res/values/qtistrings.xml
+++ b/res/values/qtistrings.xml
@@ -35,4 +35,14 @@
 
     <!-- Call Settings -->
     <string name="call_settings_lbl">Call Settings</string>
+
+    <!-- RCS feature strings -->
+    <string name="type_incoming_rcs">Incoming Rich Call</string>
+    <string name="type_outgoing_rcs">Outgoing Rich Call</string>
+    <string name="type_missed_rcs">Missed Rich Call</string>
+    <string name="type_declined_rcs">Declined Rich Call</string>
+    <string name="rcs_service_unavailable">Rich call service is currently
+            unavailable, dialing voice call</string>
+    <!-- Rich call feature integration call log details -->
+    <string name="call_log_action_rich_call">Make Rich Call</string>
 </resources>
diff --git a/src/com/android/dialer/DialerApplication.java b/src/com/android/dialer/DialerApplication.java
index 1a0497b..0ed1ebc 100644
--- a/src/com/android/dialer/DialerApplication.java
+++ b/src/com/android/dialer/DialerApplication.java
@@ -43,6 +43,7 @@
         Trace.endSection();
         new BlockedNumbersAutoMigrator(PreferenceManager.getDefaultSharedPreferences(this),
                 new FilteredNumberAsyncQueryHandler(getContentResolver())).autoMigrate();
+        EnrichedCallHandler.init(this);
         Trace.endSection();
     }
 
diff --git a/src/com/android/dialer/DialtactsActivity.java b/src/com/android/dialer/DialtactsActivity.java
index 2ae567f..8633ed8 100644
--- a/src/com/android/dialer/DialtactsActivity.java
+++ b/src/com/android/dialer/DialtactsActivity.java
@@ -51,6 +51,7 @@
 import android.view.ViewTreeObserver;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
+import android.view.inputmethod.EditorInfo;
 import android.widget.AbsListView.OnScrollListener;
 import android.widget.EditText;
 import android.widget.ImageButton;
@@ -72,6 +73,7 @@
 import com.android.dialer.dialpad.SmartDialNameMatcher;
 import com.android.dialer.dialpad.SmartDialPrefix;
 import com.android.dialer.interactions.PhoneNumberInteraction;
+import com.android.dialer.list.DialerPhoneNumberListAdapter;
 import com.android.dialer.list.DragDropController;
 import com.android.dialer.list.ListsFragment;
 import com.android.dialer.list.OnDragDropListener;
@@ -263,6 +265,8 @@
      */
     private String mVoiceSearchQuery;
 
+    private EnrichedCallHandler mEnrichedCallHandler = null;
+
     protected class OptionsPopupMenu extends PopupMenu {
         public OptionsPopupMenu(Context context, View anchor) {
             super(context, anchor, Gravity.END);
@@ -367,6 +371,23 @@
     };
 
     /**
+     * Make changes to rich call button when the search view has focus
+     */
+    private final View.OnClickListener mSearchViewClickListener =
+            new View.OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            if (mEnrichedCallHandler.isRcsFeatureEnabled()) {
+                EnrichedCallHandler.DialtactsActivityListener listener =
+                        getSearchListAdapterHelper();
+                if (listener != null) {
+                    listener.onShowDialpadFragment();
+                }
+            }
+        }
+    };
+
+    /**
      * Handles the user closing the soft keyboard.
      */
     private final View.OnKeyListener mSearchEditTextLayoutListener = new View.OnKeyListener() {
@@ -380,11 +401,22 @@
                     // If the search term is not empty, show the dialpad fab.
                     showFabInSearchUi();
                 }
+                onHideDialpadFragment();
             }
             return false;
         }
     };
 
+    private void onHideDialpadFragment() {
+        if (mEnrichedCallHandler.isRcsFeatureEnabled()) {
+            EnrichedCallHandler.DialtactsActivityListener listener =
+                    getSearchListAdapterHelper();
+            if (listener != null) {
+                listener.onHideDialpadFragment();
+            }
+        }
+    }
+
     @Override
     public boolean dispatchTouchEvent(MotionEvent ev) {
         if (ev.getAction() == MotionEvent.ACTION_DOWN) {
@@ -419,8 +451,19 @@
         searchEditTextLayout.setPreImeKeyListener(mSearchEditTextLayoutListener);
 
         mActionBarController = new ActionBarController(this, searchEditTextLayout);
-
+        mEnrichedCallHandler = EnrichedCallHandler.getInstance();
         mSearchView = (EditText) searchEditTextLayout.findViewById(R.id.search_view);
+        mSearchView.setOnClickListener(mSearchViewClickListener);
+        mSearchView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
+
+            @Override
+            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+                if (actionId == EditorInfo.IME_ACTION_DONE) {
+                    onHideDialpadFragment();
+                }
+                return false;
+            }
+        });
         mSearchView.addTextChangedListener(mPhoneSearchQueryTextListener);
         mVoiceSearchButton = searchEditTextLayout.findViewById(R.id.voice_search_button);
         searchEditTextLayout.findViewById(R.id.search_magnifying_glass)
@@ -817,6 +860,14 @@
      * @see #onDialpadShown
      */
     private void showDialpadFragment(boolean animate) {
+        if (mEnrichedCallHandler.isRcsFeatureEnabled()) {
+            EnrichedCallHandler.DialtactsActivityListener listener =
+                    getSearchListAdapterHelper();
+            if (listener != null) {
+                listener.onShowDialpadFragment();
+            }
+        }
+
         if (mIsDialpadShown || mStateSaved) {
             return;
         }
@@ -878,6 +929,9 @@
      * @see #commitDialpadFragmentHide
      */
     public void hideDialpadFragment(boolean animate, boolean clearDialpad) {
+        if (mIsDialpadShown) {
+            onHideDialpadFragment();
+        }
         if (mDialpadFragment == null || mDialpadFragment.getView() == null) {
             return;
         }
@@ -1310,9 +1364,36 @@
         return false;
     }
 
+    private EnrichedCallHandler.DialtactsActivityListener
+            getSearchListAdapterHelper() {
+        DialerPhoneNumberListAdapter adapter = null;
+        if (mSmartDialSearchFragment != null
+                && mSmartDialSearchFragment.isVisible()) {
+            adapter = (DialerPhoneNumberListAdapter)
+                    mSmartDialSearchFragment.getAdapter();
+        } else if (mRegularSearchFragment != null
+                && mRegularSearchFragment.isVisible()) {
+            adapter = (DialerPhoneNumberListAdapter)
+                    mRegularSearchFragment.getAdapter();
+        }
+        if (adapter != null) {
+            return (EnrichedCallHandler.DialtactsActivityListener)
+                    adapter.getEnrichedHelper();
+        }
+        return null;
+    }
+
     @Override
     public void onListFragmentScrollStateChange(int scrollState) {
         if (scrollState == OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
+            if (mEnrichedCallHandler.isRcsFeatureEnabled()
+                    && mSearchView.hasFocus()) {
+                EnrichedCallHandler.DialtactsActivityListener listener =
+                        getSearchListAdapterHelper();
+                if (listener != null) {
+                    listener.onListFragmentScrollStateChange();
+                }
+            }
             hideDialpadFragment(true, false);
             DialerUtils.hideInputMethod(mParentLayout);
         }
diff --git a/src/com/android/dialer/EnrichedCallHandler.java b/src/com/android/dialer/EnrichedCallHandler.java
new file mode 100755
index 0000000..5a8f4e0
--- /dev/null
+++ b/src/com/android/dialer/EnrichedCallHandler.java
@@ -0,0 +1,171 @@
+/**
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.android.dialer;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.provider.CallLog.Calls;
+import android.telephony.SubscriptionManager;
+
+import com.android.dialer.util.AppCompatConstants;
+import org.codeaurora.rcscommon.RcsManager;
+
+/**
+ * A singleton class which manages the use of RCSManager
+ */
+public class EnrichedCallHandler {
+
+    /**
+     * Interface to be implemented by the search helper
+     */
+    public interface DialtactsActivityListener {
+        void onListFragmentScrollStateChange();
+        void onHideDialpadFragment();
+        void onShowDialpadFragment();
+    }
+
+    private RcsManager mRcsManager;
+    private boolean mIsRcsFeatureEnabled = false;
+    private static EnrichedCallHandler sEnrichedCallHandler = null;
+
+    /** Name used to identify RCS incoming calls. */
+    private final CharSequence mIncomingRcsName;
+    /** Name used to identify RCS outgoing calls. */
+    private final CharSequence mOutgoingRcsName;
+    /** Name used to identify missed calls. */
+    private final CharSequence mMissedName;
+    /** Name used to identify missed RCS incoming calls. */
+    private final CharSequence mMissedRcsName;
+    /** Name used to identify declined RCS incoming calls. */
+    private final CharSequence mDeclinedRcsName;
+
+    // Messages for RCS capability checks
+    public static final int MSG_ENABLE_RCS = 100;
+    public static final int MSG_DISABLE_RCS = 101;
+    public static final int MSG_CHECK_RCS = 102;
+    public static final int MSG_ENABLE_RCS_CHECK_PROGRESS = 103;
+    public static final int MSG_DISABLE_RCS_CHECK_PROGRESS = 104;
+    public static final int MSG_NETWORK_FAILURE = 105;
+    public static final int RCS_CHECK_TIMEOUT = 32*1000;
+
+    private EnrichedCallHandler(Context context) {
+        mRcsManager = RcsManager.getInstance(context);
+        mIsRcsFeatureEnabled = mRcsManager.isEnrichCallFeatureEnabled();
+        if (mIsRcsFeatureEnabled) {
+            mRcsManager.initialize();
+        }
+        // Cache these values so that we do not need to look them up each time.
+        mIncomingRcsName = context.getString(R.string.type_incoming_rcs);
+        mOutgoingRcsName = context.getString(R.string.type_outgoing_rcs);
+        mMissedName = context.getString(R.string.type_missed);
+        mMissedRcsName = context.getString(R.string.type_missed_rcs);
+        mDeclinedRcsName = context.getString(R.string.type_declined_rcs);
+    }
+
+    /**
+     * Initialize enriched call handler
+     * @param context context
+     */
+    public static void init(Context context) {
+        if (sEnrichedCallHandler == null) {
+            sEnrichedCallHandler = new EnrichedCallHandler(context);
+        }
+    }
+
+    /**
+     * Returns the enrich call handler instance
+     * @return singleton instance
+     */
+    public static EnrichedCallHandler getInstance() {
+        return sEnrichedCallHandler;
+    }
+
+    /**
+     * Returns the reference to RCS manager
+     * @return rcsmanager
+     */
+    public RcsManager getRcsManager() {
+        return mRcsManager;
+    }
+
+    /**
+     * Returns the status of the enriched call feature
+     * @return is feature enabled
+     */
+    public boolean isRcsFeatureEnabled() {
+        return mIsRcsFeatureEnabled;
+    }
+
+    /**
+     * get the enriched call capability
+     * @return the feature capability
+     */
+    public boolean isEnrichedCallCapable() {
+        int subId = SubscriptionManager.getDefaultVoiceSubscriptionId();
+        return mRcsManager.isEnrichedCallCapable(subId);
+    }
+
+    /**
+     * get the enriched call capability
+     * @return the feature capability
+     */
+    public boolean isEnrichedCallCapable(int subId) {
+        return mRcsManager.isEnrichedCallCapable(subId);
+    }
+
+    /**
+     * Initialize the RCSManager if the service is not connected
+     */
+    public void initializeRcsManager() {
+        mRcsManager.initialize();
+    }
+
+    /**
+     * Returns the text used to represent the given call type.
+     * @param int callType
+     */
+    public CharSequence getCallTypeText(int callType) {
+        switch (callType) {
+            case Calls.INCOMING_TYPE:
+            case AppCompatConstants.INCOMING_IMS_TYPE:
+                return mIncomingRcsName;
+            case Calls.OUTGOING_TYPE:
+            case AppCompatConstants.OUTGOING_IMS_TYPE:
+                return mOutgoingRcsName;
+            case Calls.MISSED_TYPE:
+            case AppCompatConstants.MISSED_IMS_TYPE:
+                return mMissedRcsName;
+            case AppCompatConstants.CALLS_REJECTED_TYPE:
+                return mDeclinedRcsName;
+            default:
+                return mMissedName;
+        }
+    }
+}
diff --git a/src/com/android/dialer/calllog/CallDetailHistoryAdapter.java b/src/com/android/dialer/calllog/CallDetailHistoryAdapter.java
index 08689ad..a02ae53 100644
--- a/src/com/android/dialer/calllog/CallDetailHistoryAdapter.java
+++ b/src/com/android/dialer/calllog/CallDetailHistoryAdapter.java
@@ -30,6 +30,7 @@
 import com.android.contacts.common.CallUtil;
 import com.android.dialer.PhoneCallDetails;
 import com.android.dialer.R;
+import com.android.dialer.EnrichedCallHandler;
 import com.android.dialer.util.DialerUtils;
 import com.android.dialer.util.AppCompatConstants;
 import com.android.dialer.util.PresenceHelper;
@@ -120,16 +121,31 @@
                     + ", callType = " + callType);
         callTypeIconView.clear();
         callTypeIconView.add(callType);
+
         /**
-         * Ims icon(VoLTE/VoWiFi/ViLTE/ViWiFi) will be shown if carrierOne is supported
-         * otherwise, default video icon will be shown if it is a video call.
+         * RCS icon will be shown if its a RCS call, otherwise go for IMS icon
          */
-        if (QtiImsExtUtils.isCarrierOneSupported()) {
-            callTypeIconView.addImsIcon(callType, isVideoCall);
+        boolean isRcsCall = false;
+        if ((details.features & Calls.FEATURES_ENRICHED) == Calls.FEATURES_ENRICHED) {
+            isRcsCall = true;
+            callTypeIconView.setShowRcs(isRcsCall);
         } else {
-            callTypeIconView.setShowVideo(isVideoCall);
+            /**
+             * Ims icon(VoLTE/VoWiFi/ViLTE/ViWiFi) will be shown if carrierOne is supported
+             * otherwise, default video icon will be shown if it is a video call.
+             */
+            if (QtiImsExtUtils.isCarrierOneSupported()) {
+                callTypeIconView.addImsIcon(callType, isVideoCall);
+            } else {
+                callTypeIconView.setShowVideo(isVideoCall);
+            }
         }
-        callTypeTextView.setText(mCallTypeHelper.getCallTypeText(callType, isVideoCall));
+
+        CharSequence callTypeText =
+                isRcsCall ? EnrichedCallHandler.getInstance().getCallTypeText(callType) :
+                mCallTypeHelper.getCallTypeText(callType, isVideoCall);
+
+        callTypeTextView.setText(callTypeText);
         // Set the date.
         CharSequence dateValue = DateUtils.formatDateRange(mContext, details.date, details.date,
                 DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE |
diff --git a/src/com/android/dialer/calllog/CallLogFragment.java b/src/com/android/dialer/calllog/CallLogFragment.java
index 96551a4..ae24b8d 100644
--- a/src/com/android/dialer/calllog/CallLogFragment.java
+++ b/src/com/android/dialer/calllog/CallLogFragment.java
@@ -444,7 +444,10 @@
             if (!menuVisible) {
                 updateOnTransition();
             } else if (isResumed()) {
-                refreshData();
+                if (mRefreshDataRequired) {
+                    refreshData();
+                    mAdapter.onResume();
+                }
             }
         }
     }
diff --git a/src/com/android/dialer/calllog/CallLogListItemViewHolder.java b/src/com/android/dialer/calllog/CallLogListItemViewHolder.java
index 0a6b1b7..c90d996 100644
--- a/src/com/android/dialer/calllog/CallLogListItemViewHolder.java
+++ b/src/com/android/dialer/calllog/CallLogListItemViewHolder.java
@@ -35,6 +35,7 @@
 import android.view.ContextMenu;
 import android.view.MenuItem;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.ViewStub;
 import android.widget.ImageButton;
 import android.widget.ImageView;
@@ -52,6 +53,7 @@
 import com.android.contacts.common.util.UriUtils;
 import com.android.dialer.DialtactsActivity;
 import com.android.dialer.R;
+import com.android.dialer.EnrichedCallHandler;
 import com.android.dialer.calllog.calllogcache.CallLogCache;
 import com.android.dialer.compat.FilteredNumberCompat;
 import com.android.dialer.database.FilteredNumberAsyncQueryHandler;
@@ -234,6 +236,7 @@
 
     private View.OnClickListener mExpandCollapseListener;
     private boolean mVoicemailPrimaryActionButtonClicked;
+    private EnrichedCallLogListItemHelper mEnrichedHelper;
 
     private CallLogListItemViewHolder(
             Context context,
@@ -431,6 +434,19 @@
             videoCallButtonView = actionsView.findViewById(R.id.video_call_action);
             videoCallButtonView.setOnClickListener(this);
 
+            // rich call feature integration
+            if (EnrichedCallHandler.getInstance().isRcsFeatureEnabled()) {
+                mEnrichedHelper = new EnrichedCallLogListItemHelper(mContext);
+                mEnrichedHelper.inflateEnrichedItem((ViewGroup) actionsView);
+                mEnrichedHelper.setEnrichedGetNumberHelper(
+                        new EnrichedCallLogListItemHelper.EnrichedGetNumberHelper() {
+                    @Override
+                    public String getNumber() {
+                        return number;
+                    }
+                });
+            }
+
             createNewContactButtonView = actionsView.findViewById(R.id.create_new_contact_action);
             createNewContactButtonView.setOnClickListener(this);
 
@@ -669,6 +685,9 @@
         if (show) {
             // Inflate the view stub if necessary, and wire up the event handlers.
             inflateActionViewStub();
+            if (mEnrichedHelper != null) {
+                mEnrichedHelper.showActions();
+            }
 
             actionsView.setVisibility(View.VISIBLE);
             actionsView.setAlpha(1.0f);
diff --git a/src/com/android/dialer/calllog/CallTypeIconsView.java b/src/com/android/dialer/calllog/CallTypeIconsView.java
index 7c0034c..cd353c3 100644
--- a/src/com/android/dialer/calllog/CallTypeIconsView.java
+++ b/src/com/android/dialer/calllog/CallTypeIconsView.java
@@ -29,6 +29,7 @@
 import com.android.contacts.common.testing.NeededForTesting;
 import com.android.contacts.common.util.BitmapUtil;
 import com.android.dialer.R;
+import com.android.dialer.EnrichedCallHandler;
 import com.android.dialer.util.AppCompatConstants;
 import com.google.common.collect.Lists;
 
@@ -44,6 +45,7 @@
 public class CallTypeIconsView extends View {
     private List<Integer> mCallTypes = Lists.newArrayListWithCapacity(3);
     private boolean mShowVideo = false;
+    private boolean mShowRcs = false;
     private int mWidth;
     private int mHeight;
 
@@ -136,6 +138,21 @@
     }
 
     /**
+     * Determines whether the RCS call icon will be shown.
+     *
+     * @param mShowRcs True where the RCS icon should be shown.
+     */
+    public void setShowRcs(boolean showRcs) {
+        mShowRcs = showRcs;
+
+        if (showRcs) {
+            mWidth += sResources.rcsCall.getIntrinsicWidth();
+            mHeight = Math.max(mHeight, sResources.rcsCall.getIntrinsicHeight());
+            invalidate();
+        }
+    }
+
+    /**
      * Determines if the video icon should be shown.
      *
      * @return True if the video icon should be shown.
@@ -206,6 +223,15 @@
             left = right + sResources.iconMargin;
         }
 
+        // If showing the RCS call icon, draw it scaled appropriately.
+        if (mShowRcs && sResources.rcsCall!=null) {
+            final Drawable drawable = sResources.rcsCall;
+            final int right = left + drawable.getIntrinsicWidth();
+            drawable.setBounds(left, 0, right, drawable.getIntrinsicHeight());
+            drawable.draw(canvas);
+            left = right + sResources.iconMargin;
+        }
+
         for (Integer callType : mCallTypes) {
             final Drawable drawableIms = getLteOrWifiDrawable(callType, mShowVideo);
             if (drawableIms != null) {
@@ -237,6 +263,11 @@
         public final Drawable videoCall;
 
         /**
+         * Drawable repesenting a RCS call.
+         */
+        public final Drawable rcsCall;
+
+        /**
          * The margin to use for icons.
          */
         public final int iconMargin;
@@ -295,6 +326,14 @@
             videoCall.setColorFilter(r.getColor(R.color.dialtacts_secondary_text_color),
                     PorterDuff.Mode.MULTIPLY);
 
+            if (EnrichedCallHandler.getInstance().isRcsFeatureEnabled()) {
+                rcsCall = r.getDrawable(R.drawable.ic_dialer_sip_white_24dp).mutate();
+                rcsCall.setColorFilter(r.getColor(R.color.dialtacts_secondary_text_color),
+                        PorterDuff.Mode.MULTIPLY);
+            } else {
+                rcsCall = null;
+            }
+
             iconMargin = r.getDimensionPixelSize(R.dimen.call_log_icon_margin);
 
             viwifiCall = r.getDrawable(R.drawable.viwifi);
diff --git a/src/com/android/dialer/calllog/EnrichedCallLogListItemHelper.java b/src/com/android/dialer/calllog/EnrichedCallLogListItemHelper.java
new file mode 100755
index 0000000..4f7d9c3
--- /dev/null
+++ b/src/com/android/dialer/calllog/EnrichedCallLogListItemHelper.java
@@ -0,0 +1,178 @@
+/**
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.android.dialer.calllog;
+
+import com.android.contacts.common.CallUtil;
+import com.android.dialer.EnrichedCallHandler;
+import com.android.dialer.R;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.Looper;
+import android.telephony.SubscriptionManager;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+import org.codeaurora.rcscommon.RcsManager;
+
+public class EnrichedCallLogListItemHelper implements View.OnClickListener {
+
+    public interface EnrichedGetNumberHelper {
+        String getNumber();
+    }
+
+    private Context mContext;
+    private View mEnrichedCallButtonView;
+    private ProgressBar mRichFetchProgressBar;
+    private TextView mRichCallText;
+    private ImageView mRichCallIcon;
+    private EnrichedGetNumberHelper mEnrichedGetNumberHelper;
+
+    public EnrichedCallLogListItemHelper(Context context) {
+        mContext = context;
+    }
+
+    public void setEnrichedGetNumberHelper(
+            EnrichedGetNumberHelper listener) {
+        this.mEnrichedGetNumberHelper = listener;
+    }
+
+    public void inflateEnrichedItem(ViewGroup root) {
+        mEnrichedCallButtonView = root.findViewById(R.id.rich_call_action);
+        mEnrichedCallButtonView.setVisibility(View.VISIBLE);
+        mRichCallText = (TextView) root
+                .findViewById(R.id.rich_call_action_text);
+        mRichCallIcon = (ImageView) root.findViewById(R.id.richCallIcon);
+        mEnrichedCallButtonView.setOnClickListener(this);
+        mEnrichedCallButtonView.setEnabled(false);
+        mRichFetchProgressBar = (ProgressBar) mEnrichedCallButtonView
+                .findViewById(R.id.richfetchprogressBar);
+    }
+
+    private Handler mHandler = new Handler(Looper.getMainLooper()) {
+        public void handleMessage(android.os.Message msg) {
+            if (msg.what == EnrichedCallHandler.MSG_ENABLE_RCS) {
+                mRichFetchProgressBar.setVisibility(View.GONE);
+                mRichCallIcon.setVisibility(View.VISIBLE);
+                mRichCallIcon.setAlpha(1.0f);
+                mRichCallText.setAlpha(1.0f);
+                mEnrichedCallButtonView.setEnabled(true);
+            } else if (msg.what == EnrichedCallHandler.MSG_DISABLE_RCS) {
+                if (mRichFetchProgressBar.getVisibility() == View.VISIBLE) {
+                    mRichFetchProgressBar.setVisibility(View.GONE);
+                    mRichCallIcon.setVisibility(View.VISIBLE);
+                    mRichCallIcon.setAlpha(0.3f);
+                    mRichCallText.setAlpha(0.3f);
+                    mEnrichedCallButtonView.setEnabled(false);
+                }
+            } else if (msg.what == EnrichedCallHandler.MSG_CHECK_RCS) {
+                if (mEnrichedCallButtonView != null) {
+                    mEnrichedCallButtonView.setEnabled(false);
+                    mRichFetchProgressBar.setVisibility(View.VISIBLE);
+                    mRichCallIcon.setVisibility(View.GONE);
+                    mRichCallIcon.setAlpha(0.3f);
+                    mRichCallText.setAlpha(0.3f);
+                    initilizeAndPerformRcsCheck();
+                    delayDisableRcsCheckTimedout();
+                }
+            }
+        }
+    };
+
+    public void showActions() {
+        if (EnrichedCallHandler.getInstance().isEnrichedCallCapable()) {
+            mHandler.obtainMessage(EnrichedCallHandler.MSG_CHECK_RCS)
+                    .sendToTarget();
+        } else {
+            mHandler.obtainMessage(EnrichedCallHandler.MSG_DISABLE_RCS)
+                    .sendToTarget();
+        }
+    }
+
+    private final org.codeaurora.rcscommon.RichCallCapabilitiesCallback mRcsCallback =
+            new org.codeaurora.rcscommon.RichCallCapabilitiesCallback.Stub() {
+        @Override
+        public void onRichCallCapabilitiesFetch(boolean isCapable) {
+            if (EnrichedCallHandler.getInstance().isEnrichedCallCapable()) {
+                mHandler.obtainMessage(
+                        isCapable ? EnrichedCallHandler.MSG_ENABLE_RCS
+                                : EnrichedCallHandler.MSG_DISABLE_RCS)
+                        .sendToTarget();
+            }
+        }
+    };
+
+    private void delayDisableRcsCheckTimedout() {
+        mEnrichedCallButtonView.postDelayed(new Runnable() {
+            @Override
+            public void run() {
+                mHandler.obtainMessage(EnrichedCallHandler.MSG_DISABLE_RCS)
+                        .sendToTarget();
+            }
+        }, EnrichedCallHandler.RCS_CHECK_TIMEOUT);
+    }
+
+    private void initilizeAndPerformRcsCheck() {
+        EnrichedCallHandler.getInstance().initializeRcsManager();
+        EnrichedCallHandler.getInstance().getRcsManager()
+                .fetchEnrichedCallCapabilities(
+                        mEnrichedGetNumberHelper.getNumber(), mRcsCallback,
+                        SubscriptionManager.getDefaultVoiceSubscriptionId());
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (v.getId() == R.id.rich_call_action) {
+            EnrichedCallHandler.getInstance().getRcsManager()
+                    .makeEnrichedCall(mEnrichedGetNumberHelper.getNumber(),
+                            new org.codeaurora.rcscommon.NewCallComposerCallback.Stub() {
+                                public void onNewCallComposer(
+                                        org.codeaurora.rcscommon.CallComposerData data) {
+                                    final Intent intent;
+                                    if (data != null && data.isValid()
+                                            && data.getPhoneNumber() != null) {
+                                        intent = CallUtil.getCallIntent(data
+                                                .getPhoneNumber());
+                                        intent.putExtra(
+                                                RcsManager.ENRICH_CALL_INTENT_EXTRA,
+                                                data);
+                                    } else {
+                                        intent = CallUtil
+                                                .getCallIntent(mEnrichedGetNumberHelper
+                                                        .getNumber());
+                                    }
+                                    mContext.startActivity(intent);
+                                }
+                            }, SubscriptionManager.getDefaultVoiceSubscriptionId());
+        }
+    }
+}
diff --git a/src/com/android/dialer/calllog/MSimCallLogFragment.java b/src/com/android/dialer/calllog/MSimCallLogFragment.java
index 1eefe53..436145d 100644
--- a/src/com/android/dialer/calllog/MSimCallLogFragment.java
+++ b/src/com/android/dialer/calllog/MSimCallLogFragment.java
@@ -489,7 +489,10 @@
             if (!menuVisible) {
                 updateOnTransition(false /* onEntry */);
             } else if (isResumed()) {
-                refreshData();
+                if (mRefreshDataRequired) {
+                    refreshData();
+                    mAdapter.onResume();
+                }
             }
         }
     }
diff --git a/src/com/android/dialer/dialpad/SmartDialNameMatcher.java b/src/com/android/dialer/dialpad/SmartDialNameMatcher.java
index f82dbf8..1c18206 100644
--- a/src/com/android/dialer/dialpad/SmartDialNameMatcher.java
+++ b/src/com/android/dialer/dialpad/SmartDialNameMatcher.java
@@ -476,7 +476,7 @@
         for (int i = 0; i < indexs.length; i = i + 2) {
             int start = indexs[i];
             int end = indexs[i + 1];
-            if (start >= 0 && end >= 0) {
+            if (start >= 0 && end >= 0 && start < builder.length() - 1 && end < builder.length()) {
                 matchList.add(new SmartDialMatchPosition(start, end + 1));
             } else {
                 Log.d(TAG, "Invalid index, start is:" + start + " end is:"
diff --git a/src/com/android/dialer/list/DialerPhoneNumberListAdapter.java b/src/com/android/dialer/list/DialerPhoneNumberListAdapter.java
index 7164de2..0ff6d9a 100644
--- a/src/com/android/dialer/list/DialerPhoneNumberListAdapter.java
+++ b/src/com/android/dialer/list/DialerPhoneNumberListAdapter.java
@@ -15,6 +15,7 @@
 import com.android.contacts.common.list.ContactListItemView;
 import com.android.contacts.common.list.PhoneNumberListAdapter;
 import com.android.contacts.common.util.ContactDisplayUtils;
+import com.android.dialer.EnrichedCallHandler;
 import com.android.dialer.R;
 
 /**
@@ -33,16 +34,19 @@
 
     public final static int SHORTCUT_INVALID = -1;
     public final static int SHORTCUT_DIRECT_CALL = 0;
-    public final static int SHORTCUT_CREATE_NEW_CONTACT = 1;
-    public final static int SHORTCUT_ADD_TO_EXISTING_CONTACT = 2;
-    public final static int SHORTCUT_SEND_SMS_MESSAGE = 3;
-    public final static int SHORTCUT_MAKE_VIDEO_CALL = 4;
-    public final static int SHORTCUT_BLOCK_NUMBER = 5;
+    public final static int SHORTCUT_MAKE_RICH_CALL = 1;
+    public final static int SHORTCUT_MAKE_VIDEO_CALL = 2;
+    public final static int SHORTCUT_CREATE_NEW_CONTACT = 3;
+    public final static int SHORTCUT_ADD_TO_EXISTING_CONTACT = 4;
+    public final static int SHORTCUT_SEND_SMS_MESSAGE = 5;
+    public final static int SHORTCUT_BLOCK_NUMBER = 6;
 
-    public final static int SHORTCUT_COUNT = 6;
+    public final static int SHORTCUT_COUNT = 7;
 
     private final boolean[] mShortcutEnabled = new boolean[SHORTCUT_COUNT];
 
+    private EnrichedSearchAdapterHelper mEnrichedHelper;
+
     private final BidiFormatter mBidiFormatter = BidiFormatter.getInstance();
     private boolean mVideoCallingEnabled = false;
 
@@ -50,9 +54,16 @@
         super(context);
 
         mCountryIso = GeoUtil.getCurrentCountryIso(context);
+        if (EnrichedCallHandler.getInstance().isRcsFeatureEnabled()) {
+            mEnrichedHelper = new EnrichedSearchAdapterHelper(context, this);
+        }
         mVideoCallingEnabled = CallUtil.isVideoEnabled(context);
     }
 
+    public EnrichedSearchAdapterHelper getEnrichedHelper() {
+        return mEnrichedHelper;
+    }
+
     @Override
     public int getCount() {
         return super.getCount() + getShortcutCount();
@@ -96,6 +107,10 @@
     public View getView(int position, View convertView, ViewGroup parent) {
         final int shortcutType = getShortcutTypeFromPosition(position);
         if (shortcutType >= 0) {
+            if (mEnrichedHelper != null &&
+                    shortcutType == SHORTCUT_MAKE_RICH_CALL) {
+                return mEnrichedHelper.createRichCallEntry();
+            }
             if (convertView != null) {
                 assignShortcutToView((ContactListItemView) convertView, shortcutType);
                 return convertView;
@@ -115,7 +130,9 @@
             Context context, int partition, Cursor cursor, int position, ViewGroup parent) {
         final ContactListItemView view = super.newView(context, partition, cursor, position,
                 parent);
-
+        if (mEnrichedHelper != null) {
+            mEnrichedHelper.setDialButtonAttributes(view, position);
+        }
         view.setSupportVideoCallIcon(mVideoCallingEnabled);
         return view;
     }
diff --git a/src/com/android/dialer/list/EnrichedSearchAdapterHelper.java b/src/com/android/dialer/list/EnrichedSearchAdapterHelper.java
new file mode 100755
index 0000000..ba9af62
--- /dev/null
+++ b/src/com/android/dialer/list/EnrichedSearchAdapterHelper.java
@@ -0,0 +1,376 @@
+/**
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.android.dialer.list;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.TypedArray;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.telephony.SubscriptionManager;
+import android.view.LayoutInflater;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ProgressBar;
+import android.widget.Toast;
+
+import com.android.dialer.R;
+
+import com.android.contacts.common.CallUtil;
+import com.android.contacts.common.list.ContactListItemView;
+import com.android.contacts.common.list.OnPhoneNumberPickerActionListener;
+import com.android.dialer.EnrichedCallHandler;
+import com.android.incallui.Call.LogState;
+
+import org.codeaurora.rcscommon.RcsManager;
+
+/**
+ * A helper class for enriched call search list
+ * This class will help in creating a rich call entry
+ * and enabling/disabling it in the search list.
+ */
+public class EnrichedSearchAdapterHelper implements
+        EnrichedCallHandler.DialtactsActivityListener {
+
+    private Context mContext;
+    private int mButtonBGResource = 0;
+    private View mRichCallGroup;
+    private View mRichCallRootView;
+    private ContactListItemView mRichCallItem;
+    private ProgressBar mRcsCheckProgressBar;
+    private OnPhoneNumberPickerActionListener mPhoneNumberPickerActionListener;
+    private DialerPhoneNumberListAdapter mListAdapter;
+    private EnrichedSearchActionHelper mEnrichedSearchActionHelper;
+    private EnrichedCallHandler mEnrichedCallHandler;
+
+    /**
+     * Interface to be implemented by the Search list adapter
+     */
+    public interface EnrichedSearchActionHelper {
+        void processDialIntent(int position, long id);
+        boolean checkForProhibitedPhoneNumber(String number);
+        String getQueryString();
+    }
+
+    public EnrichedSearchAdapterHelper(Context context,
+            DialerPhoneNumberListAdapter adapter) {
+        mContext = context;
+        mListAdapter = adapter;
+        int[] attrs = new int[] { android.R.attr.selectableItemBackgroundBorderless };
+        TypedArray typedArray = context.obtainStyledAttributes(attrs);
+        mButtonBGResource = typedArray.getResourceId(0, 0);
+        typedArray.recycle();
+        mEnrichedCallHandler = EnrichedCallHandler.getInstance();
+    }
+
+    /**
+     * Handler to handle Enriched call capability check
+     */
+    private Handler mHandler = new Handler(Looper.getMainLooper()) {
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+            case EnrichedCallHandler.MSG_ENABLE_RCS:
+                setRcsCapability(true);
+                break;
+            case EnrichedCallHandler.MSG_DISABLE_RCS:
+                setRcsCapability(false);
+                break;
+            case EnrichedCallHandler.MSG_ENABLE_RCS_CHECK_PROGRESS:
+                changeRcsCheckProgress(true);
+                break;
+            case EnrichedCallHandler.MSG_DISABLE_RCS_CHECK_PROGRESS:
+                changeRcsCheckProgress(false);
+                break;
+            case EnrichedCallHandler.MSG_NETWORK_FAILURE:
+                showFailureMessage();
+                break;
+            default:
+                // do nothing
+            }
+        }
+    };
+
+    /**
+     * set the attributes for the dial button in enriched search list
+     * @param ContactListItemView view
+     * @param int position
+     */
+    public void setDialButtonAttributes(ContactListItemView view, int position) {
+        view.setDialButton(
+                mContext.getResources().getDrawable(
+                        R.drawable.ic_dialer_fork_current_call), true);
+        view.getDialButton().setBackgroundResource(mButtonBGResource);
+        view.getDialButton().setBackgroundTintList(
+                mContext.getResources().getColorStateList(
+                        R.color.call_log_list_item_primary_action_icon_tint));
+        view.getDialButton().setOnClickListener(dialButtonClickListener);
+        view.getDialButton().setTag(new Integer(position));
+    }
+
+    private View.OnClickListener dialButtonClickListener = new View.OnClickListener() {
+
+        @Override
+        public void onClick(View v) {
+            int position = Integer.parseInt(v.getTag().toString());
+            mEnrichedSearchActionHelper.processDialIntent(position, -1);
+        }
+    };
+
+    /**
+     * Interface implementation set by the adapter
+     * @param DialerPhoneNumberListAdapterActionListener listener
+     */
+    public void setEnrichedSearchActionHelper(
+            EnrichedSearchActionHelper listener) {
+        mEnrichedSearchActionHelper = listener;
+    }
+
+    /**
+     * Callback implementation set the adapter
+     * @param OnPhoneNumberPickerActionListener listener
+     */
+    public void setNumberPickerListener(
+            OnPhoneNumberPickerActionListener listener) {
+        this.mPhoneNumberPickerActionListener = listener;
+    }
+
+    /**
+     * Create the rich call entry row
+     * @return enriched call view entry
+     */
+    public View createRichCallEntry() {
+        if (mRichCallRootView != null) {
+            return mRichCallRootView;
+        }
+        mRichCallRootView = (ViewGroup) LayoutInflater.from(mContext).inflate(
+                R.layout.shortcut_list_item_rich_call_enabled, null);
+        mRichCallGroup = mRichCallRootView
+                .findViewById(R.id.rich_call_search_group);
+        mRcsCheckProgressBar = (ProgressBar) mRichCallGroup
+                .findViewById(R.id.richfetchserachprogressBar);
+        mRichCallItem = (ContactListItemView) mRichCallRootView
+                .findViewById(R.id.shortcut_rich_call);
+        mRichCallItem.getPhotoView().setVisibility(View.VISIBLE);
+        setRcsCapability(EnrichedCallHandler.getInstance()
+                .isEnrichedCallCapable());
+        mRichCallItem.setOnClickListener(new View.OnClickListener() {
+
+            @Override
+            public void onClick(View v) {
+                EnrichedCallHandler.getInstance().initializeRcsManager();
+                EnrichedCallHandler.getInstance().getRcsManager()
+                        .makeEnrichedCall(mEnrichedSearchActionHelper.getQueryString(),
+                                new org.codeaurora.rcscommon.NewCallComposerCallback.Stub() {
+                                    public void onNewCallComposer(
+                                            org.codeaurora.rcscommon.CallComposerData data) {
+                                        final Intent intent;
+                                        if (data != null && data.isValid()) {
+                                            intent = CallUtil.getCallIntent(data
+                                                    .getPhoneNumber());
+                                            intent.putExtra(RcsManager.ENRICH_CALL_INTENT_EXTRA,
+                                                    data);
+                                        } else {
+                                            mHandler.obtainMessage(EnrichedCallHandler
+                                                    .MSG_NETWORK_FAILURE).sendToTarget();
+                                            intent = CallUtil.getCallIntent(
+                                                    mEnrichedSearchActionHelper.getQueryString());
+                                        }
+                                        mContext.startActivity(intent);
+                                    }
+                                }, SubscriptionManager.getDefaultVoiceSubscriptionId());
+            }
+        });
+        assignAttrs(mRichCallItem, R.drawable.ic_rcs_call_black_24dp,
+                R.string.call_log_action_rich_call);
+        return mRichCallRootView;
+    }
+
+    /**
+     * Assign attributes to the search list item
+     * @param ContactListItemView v
+     * @param int drawableId
+     * @param int stringId
+     */
+    private void assignAttrs(ContactListItemView v, int drawableId, int stringId) {
+        v.setDrawableResource(drawableId);
+        v.setDisplayName(mContext.getResources().getString(stringId));
+        v.setPhotoPosition(mListAdapter.getPhotoPosition());
+        v.setAdjustSelectionBoundsEnabled(false);
+    }
+
+    /**
+     * Set the RCS capability after the fetch is complete
+     * @param boolean isCapable
+     */
+    private void setRcsCapability(boolean isCapable) {
+        if (mRichCallItem != null) {
+            mRichCallItem.setVisibility(View.VISIBLE);
+            mRichCallItem.getPhotoView().setVisibility(View.VISIBLE);
+            mRcsCheckProgressBar.setVisibility(View.GONE);
+            mRichCallItem.setEnabled(isCapable);
+            mRichCallItem.setAlpha(isCapable ? 1.0f : 0.3f);
+        }
+    }
+
+    /**
+     * Disable the Enriched call capability check after the timeout
+     */
+    private void delayedDisableRcsCheckWhenTimedOut() {
+        if (mRichCallItem != null) {
+            mRichCallItem.postDelayed(mRcsDisableRunnable,
+                    EnrichedCallHandler.RCS_CHECK_TIMEOUT);
+        }
+    }
+
+    private Runnable mRcsDisableRunnable = new Runnable() {
+        @Override
+        public void run() {
+            if (mRichCallItem != null) {
+                if (mRcsCheckProgressBar != null
+                        && mRcsCheckProgressBar.getVisibility() == View.VISIBLE) {
+                    changeRcsCheckProgress(false);
+                }
+            }
+        }
+    };
+
+    /**
+     * Make changes to the Enriched call list item about the capability check
+     * status
+     * @param boolean enable
+     */
+    private void changeRcsCheckProgress(boolean enable) {
+        if (mRichCallItem != null) {
+            mRichCallItem.setVisibility(View.VISIBLE);
+            mRichCallItem.setAlpha(1.0f);
+            if (enable) {
+                mRichCallItem.getPhotoView().setVisibility(View.GONE);
+                mRcsCheckProgressBar.setVisibility(View.VISIBLE);
+                mRichCallItem.setEnabled(false);
+                delayedDisableRcsCheckWhenTimedOut();
+            } else {
+                mRichCallItem.setEnabled(true);
+                mRichCallItem.getPhotoView().setVisibility(View.VISIBLE);
+                mRcsCheckProgressBar.setVisibility(View.GONE);
+                mRichCallItem.removeCallbacks(mRcsDisableRunnable);
+            }
+        }
+    }
+
+    /**
+     * Show a toast message about RCS service unavailability, when mobile data is not present
+     */
+    private void showFailureMessage() {
+        ConnectivityManager cm = (ConnectivityManager)mContext
+                .getSystemService(Context.CONNECTIVITY_SERVICE);
+        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
+        if ((activeNetwork == null) ||
+                (activeNetwork.getType() != ConnectivityManager.TYPE_MOBILE)) {
+            Toast toast = Toast.makeText(mContext.getApplicationContext(),
+                    R.string.rcs_service_unavailable, Toast.LENGTH_SHORT);
+            toast.setGravity(Gravity.CENTER, 0, 0);
+            toast.show();
+        }
+    }
+
+    /**
+     * Called by the dialer activity when the search list scroll state changes
+     */
+    @Override
+    public void onListFragmentScrollStateChange() {
+        if (mEnrichedCallHandler.isEnrichedCallCapable()) {
+            mHandler.obtainMessage(
+                    EnrichedCallHandler.MSG_ENABLE_RCS_CHECK_PROGRESS)
+                    .sendToTarget();
+            initilizeAndPerformRcsCheck();
+        } else {
+            mHandler.obtainMessage(EnrichedCallHandler.MSG_DISABLE_RCS)
+                    .sendToTarget();
+        }
+    }
+
+    /**
+     * Called by the dialer activity when the dialpad is hidden
+     */
+    @Override
+    public void onHideDialpadFragment() {
+        if (mEnrichedCallHandler.isEnrichedCallCapable()) {
+            mHandler.obtainMessage(
+                    EnrichedCallHandler.MSG_ENABLE_RCS_CHECK_PROGRESS)
+                    .sendToTarget();
+            initilizeAndPerformRcsCheck();
+        } else {
+            mHandler.obtainMessage(EnrichedCallHandler.MSG_DISABLE_RCS)
+                    .sendToTarget();
+        }
+    }
+
+    /**
+     * Called by the dialer activity when the dialpad is shown
+     */
+    @Override
+    public void onShowDialpadFragment() {
+        if (mEnrichedCallHandler.isEnrichedCallCapable()) {
+            mHandler.obtainMessage(
+                    EnrichedCallHandler.MSG_DISABLE_RCS_CHECK_PROGRESS)
+                    .sendToTarget();
+        } else {
+            mHandler.obtainMessage(EnrichedCallHandler.MSG_DISABLE_RCS)
+                    .sendToTarget();
+        }
+    }
+
+    private final org.codeaurora.rcscommon.RichCallCapabilitiesCallback mRcsCallback =
+            new org.codeaurora.rcscommon.RichCallCapabilitiesCallback.Stub() {
+        @Override
+        public void onRichCallCapabilitiesFetch(boolean isCapable) {
+            mHandler.obtainMessage(
+                    isCapable ? EnrichedCallHandler.MSG_ENABLE_RCS
+                            : EnrichedCallHandler.MSG_DISABLE_RCS)
+                    .sendToTarget();
+        }
+    };
+
+    /**
+     * Do Enrich call capability check
+     */
+    private void initilizeAndPerformRcsCheck() {
+        mEnrichedCallHandler.initializeRcsManager();
+        mEnrichedCallHandler.getRcsManager().fetchEnrichedCallCapabilities(
+                mEnrichedSearchActionHelper.getQueryString(), mRcsCallback,
+                SubscriptionManager.getDefaultVoiceSubscriptionId());
+    }
+}
diff --git a/src/com/android/dialer/list/RegularSearchFragment.java b/src/com/android/dialer/list/RegularSearchFragment.java
index df18af0..83437a3 100644
--- a/src/com/android/dialer/list/RegularSearchFragment.java
+++ b/src/com/android/dialer/list/RegularSearchFragment.java
@@ -75,6 +75,10 @@
         adapter.setDisplayPhotos(true);
         adapter.setUseCallableUri(usesCallableUri());
         adapter.setListener(this);
+        if (adapter.getEnrichedHelper() != null) {
+            adapter.getEnrichedHelper()
+                .setNumberPickerListener(getOnPhoneNumberPickerListener());
+        }
         return adapter;
     }
 
diff --git a/src/com/android/dialer/list/RegularSearchListAdapter.java b/src/com/android/dialer/list/RegularSearchListAdapter.java
index afc621c..0cebe8f 100644
--- a/src/com/android/dialer/list/RegularSearchListAdapter.java
+++ b/src/com/android/dialer/list/RegularSearchListAdapter.java
@@ -26,6 +26,7 @@
 import com.android.contacts.common.list.DirectoryPartition;
 import com.android.contacts.common.util.PhoneNumberHelper;
 import com.android.dialer.calllog.ContactInfo;
+import com.android.dialer.EnrichedCallHandler;
 import com.android.dialer.service.CachedNumberLookupService;
 import com.android.dialer.service.CachedNumberLookupService.CachedContactInfo;
 
@@ -106,11 +107,15 @@
 
     protected boolean isChanged(boolean showNumberShortcuts) {
         boolean changed = false;
+        changed |= setShortcutEnabled(SHORTCUT_MAKE_RICH_CALL,
+                EnrichedCallHandler.getInstance().isRcsFeatureEnabled()
+                && showNumberShortcuts);
         changed |= setShortcutEnabled(SHORTCUT_DIRECT_CALL,
                 showNumberShortcuts || mIsQuerySipAddress);
         changed |= setShortcutEnabled(SHORTCUT_SEND_SMS_MESSAGE, showNumberShortcuts);
-        changed |= setShortcutEnabled(SHORTCUT_MAKE_VIDEO_CALL,
-                showNumberShortcuts && CallUtil.isVideoEnabled(getContext()));
+        changed |= setShortcutEnabled(
+                SHORTCUT_MAKE_VIDEO_CALL, showNumberShortcuts
+                && CallUtil.isVideoEnabled(getContext()));
         return changed;
     }
 
diff --git a/src/com/android/dialer/list/SearchFragment.java b/src/com/android/dialer/list/SearchFragment.java
index 82395b6..251d202 100644
--- a/src/com/android/dialer/list/SearchFragment.java
+++ b/src/com/android/dialer/list/SearchFragment.java
@@ -44,6 +44,7 @@
 import com.android.contacts.common.util.ViewUtil;
 import com.android.dialer.R;
 import com.android.dialer.dialpad.DialpadFragment.ErrorDialogFragment;
+import com.android.dialer.EnrichedCallHandler;
 import com.android.dialer.util.DialerUtils;
 import com.android.dialer.util.IntentUtil;
 import com.android.dialer.widget.EmptyContentView;
@@ -54,7 +55,8 @@
 
     private OnListFragmentScrolledListener mActivityScrollListener;
     private View.OnTouchListener mActivityOnTouchListener;
-
+    private boolean mIsRcsFeatureEnabled = EnrichedCallHandler
+            .getInstance().isRcsFeatureEnabled();
     /*
      * Stores the untouched user-entered string that is used to populate the add to contacts
      * intent.
@@ -157,6 +159,12 @@
         }
 
         updatePosition(false /* animate */);
+        if (mIsRcsFeatureEnabled) {
+            DialerPhoneNumberListAdapter adapter = (DialerPhoneNumberListAdapter) getAdapter();
+            if (adapter.getEnrichedHelper() != null) {
+                setActionListeners(adapter.getEnrichedHelper());
+            }
+        }
     }
 
     @Override
@@ -199,6 +207,10 @@
         mAddToContactNumber = addToContactNumber;
     }
 
+    public String getAddToContactNumber(){
+        return mAddToContactNumber;
+    }
+
     /**
      * Return true if phone number is prohibited by a value -
      * (R.string.config_prohibited_phone_number_regexp) in the config files. False otherwise.
@@ -234,6 +246,32 @@
         return adapter;
     }
 
+    private void setActionListeners(EnrichedSearchAdapterHelper helper) {
+        helper.setEnrichedSearchActionHelper(
+                new EnrichedSearchAdapterHelper.EnrichedSearchActionHelper(){
+
+            @Override
+            public void processDialIntent(int position, long id) {
+                SearchFragment.super.onItemClick(position, id);
+            }
+
+            @Override
+            public boolean checkForProhibitedPhoneNumber(String number) {
+                return SearchFragment.this.checkForProhibitedPhoneNumber(number);
+            }
+
+            @Override
+            public String getQueryString() {
+                String number = SearchFragment.this.getAddToContactNumber();
+                if (number == null) {
+                    number = SearchFragment.this.getQueryString();
+                }
+                return number;
+            }
+        });
+    }
+
+
     @Override
     protected void onItemClick(int position, long id) {
         final DialerPhoneNumberListAdapter adapter = (DialerPhoneNumberListAdapter) getAdapter();
@@ -246,7 +284,15 @@
 
         switch (shortcutType) {
             case DialerPhoneNumberListAdapter.SHORTCUT_INVALID:
-                super.onItemClick(position, id);
+                if (mIsRcsFeatureEnabled) {
+                    ContactListItemView v = (ContactListItemView)getListView()
+                            .getChildAt(position + 1);
+                    if(v != null) {
+                        v.getQuickContact().onClick(null);
+                    }
+                } else {
+                    super.onItemClick(position, id);
+                }
                 break;
             case DialerPhoneNumberListAdapter.SHORTCUT_DIRECT_CALL:
                 number = adapter.getQueryString();
diff --git a/src/com/android/dialer/list/SmartDialNumberListAdapter.java b/src/com/android/dialer/list/SmartDialNumberListAdapter.java
index ed1f825..de92969 100644
--- a/src/com/android/dialer/list/SmartDialNumberListAdapter.java
+++ b/src/com/android/dialer/list/SmartDialNumberListAdapter.java
@@ -26,6 +26,7 @@
 
 import com.android.contacts.common.CallUtil;
 import com.android.contacts.common.list.ContactListItemView;
+import com.android.dialer.EnrichedCallHandler;
 import com.android.dialer.dialpad.SmartDialCursorLoader;
 import com.android.dialer.dialpad.SmartDialNameMatcher;
 import com.android.dialer.dialpad.SmartDialPrefix;
@@ -117,6 +118,8 @@
     public void setQueryString(String queryString) {
         final boolean showNumberShortcuts = !TextUtils.isEmpty(getFormattedQueryString());
         boolean changed = false;
+        changed |= setShortcutEnabled(SHORTCUT_MAKE_RICH_CALL,
+                EnrichedCallHandler.getInstance().isRcsFeatureEnabled() && showNumberShortcuts);
         changed |= setShortcutEnabled(SHORTCUT_CREATE_NEW_CONTACT, showNumberShortcuts);
         changed |= setShortcutEnabled(SHORTCUT_ADD_TO_EXISTING_CONTACT, showNumberShortcuts);
         changed |= setShortcutEnabled(SHORTCUT_SEND_SMS_MESSAGE, showNumberShortcuts);
diff --git a/src/com/android/dialer/list/SmartDialSearchFragment.java b/src/com/android/dialer/list/SmartDialSearchFragment.java
index fcb61ff..93e79a5 100644
--- a/src/com/android/dialer/list/SmartDialSearchFragment.java
+++ b/src/com/android/dialer/list/SmartDialSearchFragment.java
@@ -28,6 +28,7 @@
 
 import com.android.contacts.common.list.ContactEntryListAdapter;
 import com.android.contacts.common.util.PermissionsUtil;
+import com.android.dialer.EnrichedCallHandler;
 import com.android.dialer.dialpad.SmartDialCursorLoader;
 import com.android.dialer.logging.Logger;
 import com.android.dialer.logging.ScreenEvent;
@@ -58,6 +59,10 @@
         // Set adapter's query string to restore previous instance state.
         adapter.setQueryString(getQueryString());
         adapter.setListener(this);
+        if (adapter.getEnrichedHelper() != null) {
+            adapter.getEnrichedHelper().setNumberPickerListener(getOnPhoneNumberPickerListener());
+        }
+        EnrichedCallHandler.getInstance().initializeRcsManager();
         return adapter;
     }