Merge "hwc: Fix scaling issue in copybit."
diff --git a/Android.mk b/Android.mk
index b3015af..a128327 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,13 +1,16 @@
-# This flag will be set to true during migration to Snapdragon Display Engine.
-TARGET_USES_SDE = false
+ifeq ($(call is-board-platform-in-list, thulium),true)
+    TARGET_USES_SDE = true
+else
+    TARGET_USES_SDE = false
+endif
 
-display-hals := libgralloc libcopybit liblight libmemtrack libqservice
+display-hals := libgralloc libcopybit liblight libmemtrack libqservice libqdutils
 
 ifeq ($(TARGET_USES_SDE), true)
     sde-libs := displayengine/libs
     display-hals += $(sde-libs)/utils $(sde-libs)/core $(sde-libs)/hwc
 else
-    display-hals += libgenlock libhwcomposer liboverlay libqdutils libhdmi
+    display-hals += libgenlock libhwcomposer liboverlay libhdmi
 endif
 
 ifeq ($(call is-vendor-board-platform,QCOM),true)
diff --git a/displayengine/include/core/buffer_allocator.h b/displayengine/include/core/buffer_allocator.h
new file mode 100644
index 0000000..4081c54
--- /dev/null
+++ b/displayengine/include/core/buffer_allocator.h
@@ -0,0 +1,130 @@
+/*
+* Copyright (c) 2015, 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.
+*/
+
+/*! @file buffer_allocator.h
+  @brief Interface file for platform specific buffer allocator.
+
+  @details Buffer manager in display engine uses this interface to allocate buffer for internal
+  usage.
+*/
+
+#ifndef __BUFFER_ALLOCATOR_H__
+#define __BUFFER_ALLOCATOR_H__
+
+#include <core/layer_buffer.h>
+
+namespace sde {
+  /*! @brief Input configuration set by the client for buffer allocation.
+
+    @sa BufferInfo::BufferConfig
+  */
+
+struct BufferConfig {
+  uint32_t width;            //!< Specifies buffer width for buffer allocation.
+  uint32_t height;           //!< Specifies buffer height for buffer allocation.
+  LayerBufferFormat format;  //!< Specifies buffer format for buffer allocation.
+  uint32_t buffer_count;     //!< Specifies number of buffers to be allocated.
+  bool secure;               //!< Specifies buffer to be allocated from secure region.
+  bool cache;                //!< Specifies whether the buffer needs to be cache.
+
+  BufferConfig() : width(0), height(0), format(kFormatInvalid), buffer_count(0), secure(false),
+                  cache(false) { }
+};
+
+/*! @brief Holds the information about the allocated buffer.
+
+  @sa BufferAllocator::AllocateBuffer
+  @sa BufferAllocator::FreeBuffer
+*/
+struct AllocatedBufferInfo {
+  int fd;                    //!< Specifies the fd of the allocated buffer.
+  uint32_t stride;           //!< Specifies aligned buffer width of the allocated buffer.
+  uint32_t size;             //!< Specifies the size of the allocated buffer.
+
+  AllocatedBufferInfo() : fd(-1), stride(0), size(0) { }
+};
+
+/*! @brief Holds the information about the input/output configuration of an output buffer.
+
+  @sa BufferAllocator::AllocateBuffer
+  @sa BufferAllocator::FreeBuffer
+*/
+struct BufferInfo {
+  BufferConfig buffer_config;             //!< Specifies configuration of a buffer to be allocated.
+  AllocatedBufferInfo alloc_buffer_info;  //!< Specifies buffer information of allocated buffer.
+
+  void *private_data;                      //!< Pointer to private data.
+
+  BufferInfo() : private_data(NULL) { }
+};
+
+/*! @brief Buffer allocator implemented by the client
+
+  @details This class declares prototype for BufferAllocator methods which must be
+  implemented by the client. Buffer manager in display engine will use these methods to
+  allocate/deallocate buffers for display engine.
+
+  @sa CompManager::Init
+  @sa ResManager::Init
+*/
+class BufferAllocator {
+ public:
+  /*! @brief Method to allocate ouput buffer for the given input configuration.
+
+    @details This method allocates memory based on input configuration.
+
+    @param[in] buffer_info \link BufferInfo \endlink
+
+    @return \link DisplayError \endlink
+
+    @sa BufferManager
+  */
+  virtual DisplayError AllocateBuffer(BufferInfo *buffer_info) = 0;
+
+
+  /*! @brief Method to deallocate the ouput buffer.
+
+    @details This method deallocates the memory allocated using AllocateBuffer method.
+
+    @param[in] buffer_info \link BufferInfo \endlink
+
+    @return \link DisplayError \endlink
+
+    @sa BufferManager
+  */
+  virtual DisplayError FreeBuffer(BufferInfo *buffer_info) = 0;
+
+ protected:
+  virtual ~BufferAllocator() { }
+};
+
+}  // namespace sde
+
+#endif  // __BUFFER_ALLOCATOR_H__
+
diff --git a/displayengine/include/core/buffer_sync_handler.h b/displayengine/include/core/buffer_sync_handler.h
new file mode 100644
index 0000000..d0d062e
--- /dev/null
+++ b/displayengine/include/core/buffer_sync_handler.h
@@ -0,0 +1,90 @@
+/*
+* Copyright (c) 2015, 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.
+*/
+
+/*! @file buffer_sync_handler.h
+  @brief Interface file for platform specific buffer allocator.
+
+  @details Buffer manager in display engine uses this interface to wait for buffer sync fd to be
+  signaled/merge the two buffer sync fds into one
+*/
+
+#ifndef __BUFFER_SYNC_HANDLER_H__
+#define __BUFFER_SYNC_HANDLER_H__
+
+namespace sde {
+
+/*! @brief Buffer sync handler implemented by the client
+
+  @details This class declares prototype for BufferSyncHandler methods which must be
+  implemented by the client. Buffer manager and HWFramebuffer in display engine will use these
+  methods to wait for buffer sync fd to be signaled/merge two buffer sync fds into one.
+
+  @sa CompManager::Init
+  @sa ResManager::Init
+  @sa HWInterface::Create
+*/
+class BufferSyncHandler {
+ public:
+  /*! @brief Method to wait for ouput buffer to be released.
+
+    @details This method waits for fd to be signaled by the producer/consumer.
+
+    @param[in] fd
+
+    @return \link DisplayError \endlink
+
+    @sa BufferManager::GetNextBuffer
+  */
+
+  virtual DisplayError SyncWait(int fd) = 0;
+
+  /*! @brief Method to merge two sync fds into one sync fd
+
+    @details This method merges two buffer sync fds into one sync fd, if a producer/consumer
+    requires to wait for more than one sync fds.
+
+    @param[in] fd1
+    @param[in] fd2
+    @param[out] merged_fd
+
+    @return \link DisplayError \endlink
+
+    @sa HWFrameBuffer::RotatorCommit
+ */
+
+  virtual DisplayError SyncMerge(int fd1, int fd2, int *merged_fd) = 0;
+
+ protected:
+  virtual ~BufferSyncHandler() { }
+};
+
+}  // namespace sde
+
+#endif  // __BUFFER_SYNC_HANDLER_H__
+
diff --git a/displayengine/include/core/core_interface.h b/displayengine/include/core/core_interface.h
old mode 100755
new mode 100644
index 2229d1e..114d9aa
--- a/displayengine/include/core/core_interface.h
+++ b/displayengine/include/core/core_interface.h
@@ -1,25 +1,30 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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.
+* 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.
+* 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.
 */
 
 /*! @file core_interface.h
@@ -36,6 +41,9 @@
 
 #include "display_interface.h"
 #include "sde_types.h"
+#include "buffer_allocator.h"
+
+class BufferSyncHandler;
 
 /*! @brief Display engine interface version.
 
@@ -65,6 +73,11 @@
 
 namespace sde {
 
+/*! @brief Forward declaration for debug handler.
+*/
+class DebugHandler;
+
+
 /*! @brief Event data associated with hotplug event.
 
   @sa CoreEventHandler::Hotplug
@@ -120,7 +133,9 @@
     This interface shall be called only once.
 
     @param[in] event_handler \link CoreEventHandler \endlink
-    @param[in] log_handler \link LogHandler \endlink
+    @param[in] debug_handler \link DebugHandler \endlink
+    @param[in] buffer_allocator \link BufferAllocator \endlink
+    @param[in] buffer_sync_handler \link BufferSyncHandler \endlink
     @param[out] interface \link CoreInterface \endlink
     @param[in] version \link SDE_VERSION_TAG \endlink. Client must not override this argument.
 
@@ -128,8 +143,10 @@
 
     @sa DestroyCore
   */
-  static DisplayError CreateCore(CoreEventHandler *event_handler, LogHandler *log_handler,
-                                 CoreInterface **interface, uint32_t version = SDE_VERSION_TAG);
+  static DisplayError CreateCore(CoreEventHandler *event_handler, DebugHandler *debug_handler,
+                                 BufferAllocator *buffer_allocator,
+                                 BufferSyncHandler *buffer_sync_handler, CoreInterface **interface,
+                                 uint32_t version = SDE_VERSION_TAG);
 
   /*! @brief Method to release handle to display core interface.
 
diff --git a/displayengine/include/core/debug_interface.h b/displayengine/include/core/debug_interface.h
new file mode 100644
index 0000000..c90e1ff
--- /dev/null
+++ b/displayengine/include/core/debug_interface.h
@@ -0,0 +1,128 @@
+/*
+* Copyright (c) 2015, 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.
+*/
+
+/*! @file debug_interface.h
+  @brief This file provides the debug interface for display engine.
+*/
+#ifndef __DEBUG_INTERFACE_H__
+#define __DEBUG_INTERFACE_H__
+
+namespace sde {
+
+/*! @brief This enum represents different modules/logical unit tags that a log message may
+  be associated with. Client may use this to filter messages for dynamic logging.
+
+  @sa DisplayLogHandler
+*/
+enum DebugTag {
+  kTagNone,             //!< Debug log is not tagged. This type of logs should always be printed.
+  kTagResources,        //!< Debug log is tagged for resource management.
+  kTagStrategy,         //!< Debug log is tagged for strategy decisions.
+  kTagCompManager,      //!< Debug log is tagged for composition manager.
+  kTagDriverConfig,     //!< Debug log is tagged for driver config.
+  kTagBufferManager,    //!< Debug log is tagged for buffer manager state transitions.
+  kTagOfflineCtrl,      //!< Debug log is tagged for offline controller.
+};
+
+/*! @brief Display debug handler class.
+
+  @details This class defines display debug handler. The handle contains methods which client
+  should implement to get different levels of logging/tracing from display engine. Display engine
+   will call into these methods at appropriate times to send logging/tracing information.
+
+  @sa CoreInterface::CreateCore
+*/
+class DebugHandler {
+ public:
+  /*! @brief Method to handle error messages.
+
+    @param[in] tag \link DebugTag \endlink
+    @param[in] format \link message format with variable argument list \endlink
+  */
+  virtual void Error(DebugTag tag, const char *format, ...) = 0;
+
+  /*! @brief Method to handle warning messages.
+
+    @param[in] tag \link DebugTag \endlink
+    @param[in] format \link message format with variable argument list \endlink
+  */
+  virtual void Warning(DebugTag tag, const char *format, ...) = 0;
+
+  /*! @brief Method to handle informative messages.
+
+    @param[in] tag \link DebugTag \endlink
+    @param[in] format \link message format with variable argument list \endlink
+  */
+  virtual void Info(DebugTag tag, const char *format, ...) = 0;
+
+  /*! @brief Method to handle verbose messages.
+
+    @param[in] tag \link DebugTag \endlink
+    @param[in] format \link message format with variable argument list \endlink
+  */
+  virtual void Verbose(DebugTag tag, const char *format, ...) = 0;
+
+  /*! @brief Method to begin trace for a module/logical unit.
+
+    @param[in] class_name \link name of the class that the function belongs to \endlink
+    @param[in] function_name \link name of the function to be traced \endlink
+    @param[in] custom_string \link custom string for multiple traces within a function \endlink
+  */
+  virtual void BeginTrace(const char *class_name, const char *function_name,
+                          const char *custom_string) = 0;
+
+  /*! @brief Method to end trace for a module/logical unit.
+  */
+  virtual void EndTrace() = 0;
+
+ protected:
+  virtual ~DebugHandler() { }
+};
+
+/*! @brief Scope tracer template class.
+
+  @details This class template implements the funtionality to capture the trace for function/
+  module. It starts the trace upon object creation and ends the trace upon object destruction.
+*/
+template <class T>
+class ScopeTracer {
+ public:
+  ScopeTracer(const char *class_name, const char *function_name) {
+    T::Get()->BeginTrace(class_name, function_name, "");
+  }
+
+  ~ScopeTracer() { T::Get()->EndTrace(); }
+};
+
+}  // namespace sde
+
+#endif  // __DEBUG_INTERFACE_H__
+
+
+
diff --git a/displayengine/include/core/display_interface.h b/displayengine/include/core/display_interface.h
old mode 100755
new mode 100644
index bdeb8a3..c054fae
--- a/displayengine/include/core/display_interface.h
+++ b/displayengine/include/core/display_interface.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -207,6 +207,19 @@
   */
   virtual DisplayError Commit(LayerStack *layer_stack) = 0;
 
+  /*! @brief Method to flush any pending buffers/fences submitted previously via Commit() call.
+
+    @details Client shall call this method to request the Display Engine to release all buffers and
+    respective fences currently in use. This operation may result in a blank display on the panel
+    until a new frame is submitted for composition.
+
+    @return \link DisplayError \endlink
+
+    @sa Prepare
+    @sa Commit
+  */
+  virtual DisplayError Flush() = 0;
+
   /*! @brief Method to get current state of the display device.
 
     @param[out] state \link DisplayState \endlink
@@ -271,6 +284,14 @@
 
   /*! @brief Method to set active configuration for variable properties of the display device.
 
+    @param[in] variable_info \link DisplayConfigVariableInfo \endlink
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError SetActiveConfig(DisplayConfigVariableInfo *variable_info) = 0;
+
+  /*! @brief Method to set active configuration for variable properties of the display device.
+
     @param[in] index index of the mode corresponding to variable properties.
 
     @return \link DisplayError \endlink
@@ -285,6 +306,14 @@
   */
   virtual DisplayError SetVSyncState(bool enable) = 0;
 
+  /*! @brief Method to set idle timeout value. Idle fallback is disabled with timeout value 0.
+
+    @param[in] timeout value in milliseconds.
+
+    @return \link void \endlink
+  */
+  virtual void SetIdleTimeoutMs(uint32_t timeout_ms) = 0;
+
  protected:
   virtual ~DisplayInterface() { }
 };
diff --git a/displayengine/include/core/layer_buffer.h b/displayengine/include/core/layer_buffer.h
old mode 100755
new mode 100644
index c069c60..9f7110a
--- a/displayengine/include/core/layer_buffer.h
+++ b/displayengine/include/core/layer_buffer.h
@@ -87,6 +87,17 @@
                                       //!< factor of 2
                                       //!<    u(0), y(0), v(0), y(1), u(2), y(2), v(2), y(3)
                                       //!<    u(n-1), y(n-1), v(n-1), y(n)
+
+  /* All UBWC aligned formats. Any new format will be added towards end of this group to maintain
+     backward compatibility.
+  */
+  kFormatRGBA8888Ubwc = 0x400,        //!< UBWC aligned RGBA8888 format
+
+  kFormatRGB565Ubwc,                  //!< UBWC aligned RGB565 format
+
+  kFormatYCbCr420SPVenusUbwc,         //!< UBWC aligned Venus NV12 format
+
+  kFormatInvalid = 0xFFFFFFFF,
 };
 
 /*! @brief This structure defines a color sample plane belonging to a buffer format. RGB buffer
@@ -114,6 +125,7 @@
                             //!< video/ui buffer
   uint64_t macro_tile : 1;  //!< This flag shall be set by client to indicate that the buffer format
                             //!< is macro tiled.
+
   LayerBufferFlags() : secure(0), video(0), macro_tile(0) { }
 };
 
diff --git a/displayengine/include/core/layer_stack.h b/displayengine/include/core/layer_stack.h
old mode 100755
new mode 100644
index 67a812d..96ec20f
--- a/displayengine/include/core/layer_stack.h
+++ b/displayengine/include/core/layer_stack.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -32,6 +32,7 @@
 #define __LAYER_STACK_H__
 
 #include <stdint.h>
+#include <utils/constants.h>
 
 #include "layer_buffer.h"
 #include "sde_types.h"
@@ -123,7 +124,11 @@
   uint64_t secure_present : 1;    //!< This flag will be set to true, if the current layer stack
                                   //!< contains secure layers.
 
-  LayerStackFlags() : geometry_changed(0), skip_present(0), video_present(0), secure_present(0) { }
+  uint64_t animating : 1;         //!< This flag shall be set by client to indicate that the current
+                                  //!< frame is animating.
+
+  LayerStackFlags()
+    : geometry_changed(0), skip_present(0), video_present(0), secure_present(0), animating(0) { }
 };
 
 /*! @brief This structure defines a rectanglular area inside a display layer.
@@ -137,6 +142,8 @@
   float bottom;   //!< Bottom-most pixel coordinate.
 
   LayerRect() : left(0.0f), top(0.0f), right(0.0f), bottom(0.0f) { }
+
+  LayerRect(float l, float t, float r, float b) : left(l), top(t), right(r), bottom(b) { }
 };
 
 /*! @brief This structure defines an array of display layer rectangles.
@@ -194,8 +201,10 @@
 
   LayerFlags flags;                 //!< Flags associated with this layer.
 
+  uint32_t frame_rate;              //!< Rate at which frames are being updated for this layer.
+
   Layer() : input_buffer(NULL), composition(kCompositionGPU), blending(kBlendingNone),
-            plane_alpha(0) { }
+            plane_alpha(0), frame_rate(0) { }
 };
 
 /*! @brief This structure defines a layer stack that contains layers which need to be composed and
diff --git a/displayengine/include/core/sde_types.h b/displayengine/include/core/sde_types.h
old mode 100755
new mode 100644
index 6090889..0055306
--- a/displayengine/include/core/sde_types.h
+++ b/displayengine/include/core/sde_types.h
@@ -1,25 +1,30 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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.
+* 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.
+* 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.
 */
 
 /*! @file sde_types.h
@@ -48,59 +53,6 @@
   kErrorTimeOut,          //!< The operation has timed out to prevent client from waiting forever.
 };
 
-/*! @brief This enum represents different modules/logical unit tags that a log message may be
-  associated with. Client may use this to filter messages for dynamic logging.
-
-  @sa DisplayLogHandler
-*/
-enum LogTag {
-  kTagNone,             //!< Log is not tagged. This type of logs should always be printed.
-  kTagResources,        //!< Log is tagged for resource management.
-  kTagStrategy,         //!< Log is tagged for strategy decisions.
-};
-
-/*! @brief Display log handler class.
-
-  @details This class defines display log handler. The handle contains methods which client should
-  implement to get different levels of logging from display engine. Display engine will call into
-  these methods at appropriate times to send logging information.
-
-  @sa CoreInterface::CreateCore
-*/
-class LogHandler {
- public:
-  /*! @brief Method to handle error messages.
-
-    @param[in] tag \link LogTag \endlink
-    @param[in] format \link message format with variable argument list \endlink
-  */
-  virtual void Error(LogTag tag, const char *format, ...) = 0;
-
-  /*! @brief Method to handle warning messages.
-
-    @param[in] tag \link LogTag \endlink
-    @param[in] format \link message format with variable argument list \endlink
-  */
-  virtual void Warning(LogTag tag, const char *format, ...) = 0;
-
-  /*! @brief Method to handle informative messages.
-
-    @param[in] tag \link LogTag \endlink
-    @param[in] format \link message format with variable argument list \endlink
-  */
-  virtual void Info(LogTag tag, const char *format, ...) = 0;
-
-  /*! @brief Method to handle verbose messages.
-
-    @param[in] tag \link LogTag \endlink
-    @param[in] format \link message format with variable argument list \endlink
-  */
-  virtual void Verbose(LogTag tag, const char *format, ...) = 0;
-
- protected:
-  virtual ~LogHandler() { }
-};
-
 /*! @brief This structure is defined for client and library compatibility check purpose only. This
   structure is used in SDE_VERSION_TAG definition only. Client should not refer it directly for
   any purpose.
diff --git a/displayengine/include/utils/constants.h b/displayengine/include/utils/constants.h
index a7b9f0f..6f98b07 100644
--- a/displayengine/include/utils/constants.h
+++ b/displayengine/include/utils/constants.h
@@ -25,6 +25,8 @@
 #ifndef __CONSTANTS_H__
 #define __CONSTANTS_H__
 
+#include <stdlib.h>
+
 #define LIKELY(exp) __builtin_expect((exp) != 0, true)
 #define UNLIKELY(exp) __builtin_expect((exp) != 0, false)
 
@@ -47,7 +49,27 @@
 #define SET_BIT(value, bit) (value |= (1 << (bit)))
 #define CLEAR_BIT(value, bit) (value &= (~(1 << (bit))))
 #define IS_BIT_SET(value, bit) (value & (1 << (bit)))
+
 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+template <class T>
+inline void Swap(T &a, T &b) {
+  T c(a);
+  a = b;
+  b = c;
+}
+
+// factor value should be in powers of 2(eg: 1, 2, 4, 8)
+template <class T1, class T2>
+inline T1 FloorToMultipleOf(const T1 &value, const T2 &factor) {
+  return (T1)(value & (~(factor - 1)));
+}
+
+template <class T1, class T2>
+inline T1 CeilToMultipleOf(const T1 &value, const T2 &factor) {
+  return (T1)((value + (factor - 1)) & (~(factor - 1)));
+}
 
 namespace sde {
 
diff --git a/displayengine/include/utils/debug.h b/displayengine/include/utils/debug.h
old mode 100755
new mode 100644
index 99d3968..65079a9
--- a/displayengine/include/utils/debug.h
+++ b/displayengine/include/utils/debug.h
@@ -1,25 +1,30 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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.
+* 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.
+* 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.
 */
 
 #ifndef __DEBUG_H__
@@ -27,9 +32,10 @@
 
 #include <stdint.h>
 #include <core/sde_types.h>
+#include <core/debug_interface.h>
 
-#define DLOG(tag, method, format, ...) Debug::GetLogHandler()->method(tag, \
-                                            __CLASS__ "::%s: " format, __FUNCTION__, ##__VA_ARGS__)
+#define DLOG(tag, method, format, ...) Debug::Get()->method(tag, __CLASS__ "::%s: " format, \
+                                                            __FUNCTION__, ##__VA_ARGS__)
 
 #define DLOGE_IF(tag, format, ...) DLOG(tag, Error, format, ##__VA_ARGS__)
 #define DLOGW_IF(tag, format, ...) DLOG(tag, Warning, format, ##__VA_ARGS__)
@@ -41,31 +47,41 @@
 #define DLOGI(format, ...) DLOGI_IF(kTagNone, format, ##__VA_ARGS__)
 #define DLOGV(format, ...) DLOGV_IF(kTagNone, format, ##__VA_ARGS__)
 
+#define DTRACE_BEGIN(custom_string) Debug::Get()->BeginTrace(__CLASS__, __FUNCTION__, custom_string)
+#define DTRACE_END() Debug::Get()->EndTrace()
+#define DTRACE_SCOPED() ScopeTracer <Debug> scope_tracer(__CLASS__, __FUNCTION__)
+
 namespace sde {
 
 class Debug {
  public:
-  static inline void SetLogHandler(LogHandler *log_handler) { debug_.log_handler_ = log_handler; }
-  static inline LogHandler* GetLogHandler() { return debug_.log_handler_; }
+  static inline void SetDebugHandler(DebugHandler *debug_handler) {
+    debug_.debug_handler_ = debug_handler;
+  }
+  static inline DebugHandler* Get() { return debug_.debug_handler_; }
   static inline bool IsVirtualDriver() { return debug_.virtual_driver_; }
   static uint32_t GetSimulationFlag();
   static uint32_t GetHDMIResolution();
+  static uint32_t GetIdleTimeoutMs();
 
  private:
   Debug();
 
-  // By default, drop any log messages coming from Display Engine. It will be overriden by Display
-  // Engine client when core is successfully initialized.
-  class DefaultLogHandler : public LogHandler {
+  // By default, drop any log messages/traces coming from Display Engine. It will be overriden by
+  // Display Engine client when core is successfully initialized.
+  class DefaultDebugHandler : public DebugHandler {
    public:
-    virtual void Error(LogTag /*tag*/, const char */*format*/, ...) { }
-    virtual void Warning(LogTag /*tag*/, const char */*format*/, ...) { }
-    virtual void Info(LogTag /*tag*/, const char */*format*/, ...) { }
-    virtual void Verbose(LogTag /*tag*/, const char */*format*/, ...) { }
+    virtual void Error(DebugTag /*tag*/, const char */*format*/, ...) { }
+    virtual void Warning(DebugTag /*tag*/, const char */*format*/, ...) { }
+    virtual void Info(DebugTag /*tag*/, const char */*format*/, ...) { }
+    virtual void Verbose(DebugTag /*tag*/, const char */*format*/, ...) { }
+    virtual void BeginTrace(const char */*class_name*/, const char */*function_name*/,
+                            const char */*custom_string*/) { }
+    virtual void EndTrace() { }
   };
 
-  DefaultLogHandler default_log_handler_;
-  LogHandler *log_handler_;
+  DefaultDebugHandler default_debug_handler_;
+  DebugHandler *debug_handler_;
   bool virtual_driver_;
   static Debug debug_;
 };
diff --git a/displayengine/include/utils/locker.h b/displayengine/include/utils/locker.h
index 2c1ef9a..549a282 100644
--- a/displayengine/include/utils/locker.h
+++ b/displayengine/include/utils/locker.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -28,7 +28,11 @@
 #include <stdint.h>
 #include <pthread.h>
 
-#define SCOPE_LOCK(locker) Locker::ScopeLock scopeLock(locker)
+#define SCOPE_LOCK(locker) Locker::ScopeLock lock(locker)
+#define SEQUENCE_ENTRY_SCOPE_LOCK(locker) Locker::SequenceEntryScopeLock lock(locker)
+#define SEQUENCE_EXIT_SCOPE_LOCK(locker) Locker::SequenceExitScopeLock lock(locker)
+#define SEQUENCE_WAIT_SCOPE_LOCK(locker) Locker::SequenceWaitScopeLock lock(locker)
+#define SEQUENCE_CANCEL_SCOPE_LOCK(locker) Locker::SequenceCancelScopeLock lock(locker)
 
 namespace sde {
 
@@ -48,7 +52,78 @@
     Locker &locker_;
   };
 
-  Locker() {
+  class SequenceEntryScopeLock {
+   public:
+    explicit SequenceEntryScopeLock(Locker& locker) : locker_(locker) {
+      locker_.Lock();
+      locker_.sequence_wait_ = 1;
+    }
+
+    ~SequenceEntryScopeLock() {
+      locker_.Unlock();
+    }
+
+   private:
+    Locker &locker_;
+  };
+
+  class SequenceExitScopeLock {
+   public:
+    explicit SequenceExitScopeLock(Locker& locker) : locker_(locker) {
+      locker_.Lock();
+      locker_.sequence_wait_ = 0;
+    }
+
+    ~SequenceExitScopeLock() {
+      locker_.Broadcast();
+      locker_.Unlock();
+    }
+
+   private:
+    Locker &locker_;
+  };
+
+  class SequenceWaitScopeLock {
+   public:
+    explicit SequenceWaitScopeLock(Locker& locker) : locker_(locker), error_(false) {
+      locker_.Lock();
+
+      if (locker_.sequence_wait_ == 1) {
+        locker_.Wait();
+        error_ = (locker_.sequence_wait_ == -1);
+      }
+    }
+
+    ~SequenceWaitScopeLock() {
+      locker_.Unlock();
+    }
+
+    bool IsError() {
+      return error_;
+    }
+
+   private:
+    Locker &locker_;
+    bool error_;
+  };
+
+  class SequenceCancelScopeLock {
+   public:
+    explicit SequenceCancelScopeLock(Locker& locker) : locker_(locker) {
+      locker_.Lock();
+      locker_.sequence_wait_ = -1;
+    }
+
+    ~SequenceCancelScopeLock() {
+      locker_.Broadcast();
+      locker_.Unlock();
+    }
+
+   private:
+    Locker &locker_;
+  };
+
+  Locker() : sequence_wait_(0) {
     pthread_mutex_init(&mutex_, 0);
     pthread_cond_init(&condition_, 0);
   }
@@ -63,7 +138,7 @@
   void Signal() { pthread_cond_signal(&condition_); }
   void Broadcast() { pthread_cond_broadcast(&condition_); }
   void Wait() { pthread_cond_wait(&condition_, &mutex_); }
-  int WaitFinite(long int ms) {
+  int WaitFinite(int ms) {
     struct timespec ts;
     struct timeval tv;
     gettimeofday(&tv, NULL);
@@ -77,6 +152,11 @@
  private:
   pthread_mutex_t mutex_;
   pthread_cond_t condition_;
+  int sequence_wait_;   // This flag is set to 1 on sequence entry, 0 on exit, and -1 on cancel.
+                        // Some routines will wait for sequence of function calls to finish
+                        // so that capturing a transitionary snapshot of context is prevented.
+                        // If flag is set to -1, these routines will exit without doing any
+                        // further processing.
 };
 
 }  // namespace sde
diff --git a/displayengine/include/utils/rect.h b/displayengine/include/utils/rect.h
new file mode 100644
index 0000000..f009cfd
--- /dev/null
+++ b/displayengine/include/utils/rect.h
@@ -0,0 +1,48 @@
+/*
+* Copyright (c) 2015, 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.
+*/
+
+#ifndef __RECT_H__
+#define __RECT_H__
+
+#include <stdint.h>
+#include <core/sde_types.h>
+#include <core/layer_stack.h>
+#include <utils/debug.h>
+
+namespace sde {
+
+  bool IsValidRect(const LayerRect &rect);
+  LayerRect GetIntersection(const LayerRect &rect1, const LayerRect &rect2);
+  void LogRect(DebugTag debug_tag, const char *prefix, const LayerRect &roi);
+  void NormalizeRect(const uint32_t &factor, LayerRect *rect);
+
+}  // namespace sde
+
+#endif  // __RECT_H__
+
diff --git a/displayengine/libs/core/Android.mk b/displayengine/libs/core/Android.mk
index 92569a5..56167e1 100644
--- a/displayengine/libs/core/Android.mk
+++ b/displayengine/libs/core/Android.mk
@@ -4,7 +4,8 @@
 LOCAL_MODULE                  := libsde
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := hardware/qcom/display/displayengine/include/ \
-                                 $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+                                 $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include \
+                                 $(TARGET_OUT_HEADERS)/scalar/inc
 LOCAL_CFLAGS                  := -Wno-missing-field-initializers -Wno-unused-parameter \
                                  -Wconversion -Wall -Werror \
                                  -DLOG_TAG=\"SDE\"
@@ -23,6 +24,7 @@
                                  offline_ctrl.cpp \
                                  hw_interface.cpp \
                                  hw_framebuffer.cpp \
-                                 dump_impl.cpp
+                                 dump_impl.cpp \
+                                 buffer_manager.cpp
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/displayengine/libs/core/buffer_manager.cpp b/displayengine/libs/core/buffer_manager.cpp
new file mode 100644
index 0000000..95c310a
--- /dev/null
+++ b/displayengine/libs/core/buffer_manager.cpp
@@ -0,0 +1,293 @@
+/*
+* Copyright (c) 2015, 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.
+*/
+
+#include <utils/debug.h>
+#include <utils/constants.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+
+#include "buffer_manager.h"
+
+#define __CLASS__ "BufferManager"
+
+namespace sde {
+
+// --------------------------------- BufferSlot Implementation -------------------------------------
+
+DisplayError BufferManager::BufferSlot::Init() {
+  uint32_t buffer_count = hw_buffer_info.buffer_config.buffer_count;
+  size_t buffer_size = hw_buffer_info.alloc_buffer_info.size;
+
+  release_fd = new int[buffer_count];
+  if (release_fd == NULL) {
+    return kErrorMemory;
+  }
+
+  offset = new uint32_t[buffer_count];
+  if (offset == NULL) {
+    delete[] release_fd;
+    release_fd = NULL;
+    return kErrorMemory;
+  }
+
+  for (uint32_t idx = 0; idx < buffer_count; idx++) {
+    release_fd[idx] = -1;
+    offset[idx] = UINT32((buffer_size / buffer_count) * idx);
+  }
+  curr_index = 0;
+
+  return kErrorNone;
+}
+
+DisplayError BufferManager::BufferSlot::Deinit() {
+  uint32_t buffer_count = hw_buffer_info.buffer_config.buffer_count;
+
+  for (uint32_t idx = 0; idx < buffer_count; idx++) {
+    if (release_fd[idx] >= 0) {
+      close(release_fd[idx]);
+      release_fd[idx] = -1;
+    }
+  }
+
+  if (offset) {
+    delete[] offset;
+    offset = NULL;
+  }
+
+  if (release_fd) {
+    delete[] release_fd;
+    release_fd = NULL;
+  }
+
+  state = kBufferSlotFree;
+  hw_buffer_info = HWBufferInfo();
+
+  return kErrorNone;
+}
+
+// BufferManager State Transition
+// *******************************************************
+// Current State *             Next State
+//               *****************************************
+//               *   FREE       READY        ACQUIRED
+// *******************************************************
+//  FREE         *    NA         NA        GetNextBuffer()
+//  READY        *   Stop()      NA        GetNextBuffer()
+//  ACQUIRED     *    NA       Start()          NA
+//********************************************************
+
+// ------------------------------- BufferManager Implementation ------------------------------------
+
+BufferManager::BufferManager(BufferAllocator *buffer_allocator,
+                             BufferSyncHandler *buffer_sync_handler)
+    : buffer_allocator_(buffer_allocator), buffer_sync_handler_(buffer_sync_handler),
+      num_used_slot_(0) {
+}
+
+void BufferManager::Start() {
+  uint32_t slot = 0, num_ready_slot = 0;
+
+  // Change the state of acquired buffer_slot to kBufferSlotReady
+  while ((num_ready_slot < num_used_slot_) && (slot < kMaxBufferSlotCount)) {
+    if (buffer_slot_[slot].state == kBufferSlotFree) {
+      slot++;
+      continue;
+    }
+
+    buffer_slot_[slot++].state = kBufferSlotReady;
+    num_ready_slot++;
+  }
+}
+
+DisplayError BufferManager::GetNextBuffer(HWBufferInfo *hw_buffer_info) {
+  DisplayError error = kErrorNone;
+  const BufferConfig &buffer_config = hw_buffer_info->buffer_config;
+
+  DLOGI_IF(kTagBufferManager, "Input: w = %d h = %d f = %d", buffer_config.width,
+           buffer_config.height, buffer_config.format);
+
+  uint32_t free_slot = num_used_slot_;
+  uint32_t acquired_slot = kMaxBufferSlotCount;
+  uint32_t num_used_slot = 0;
+
+  // First look for a buffer slot in ready state, if no buffer slot found in ready state matching
+  // with current input config, assign a buffer slot in free state and allocate buffers for it.
+  for (uint32_t slot = 0; slot < kMaxBufferSlotCount && num_used_slot < num_used_slot_; slot++) {
+    HWBufferInfo &hw_buffer_info = buffer_slot_[slot].hw_buffer_info;
+
+    if (buffer_slot_[slot].state == kBufferSlotFree) {
+      free_slot = slot;
+    } else {
+      if ((buffer_slot_[slot].state == kBufferSlotReady)) {
+        if ((::memcmp(&buffer_config, &hw_buffer_info.buffer_config, sizeof(BufferConfig)) == 0)) {
+          buffer_slot_[slot].state = kBufferSlotAcquired;
+          acquired_slot = slot;
+          break;
+        }
+      }
+      num_used_slot++;
+    }
+  }
+
+  // If the input config does not match with existing config, then allocate buffers for the new
+  // buffer slot and change the state to kBufferSlotAcquired
+  if (acquired_slot == kMaxBufferSlotCount) {
+    if (free_slot >= kMaxBufferSlotCount) {
+      return kErrorMemory;
+    }
+
+    buffer_slot_[free_slot].hw_buffer_info.buffer_config = hw_buffer_info->buffer_config;
+
+    error = buffer_allocator_->AllocateBuffer(&buffer_slot_[free_slot].hw_buffer_info);
+    if (error != kErrorNone) {
+      return error;
+    }
+
+    buffer_slot_[free_slot].Init();
+    buffer_slot_[free_slot].state = kBufferSlotAcquired;
+    acquired_slot = free_slot;
+    num_used_slot_++;
+
+    DLOGI_IF(kTagBufferManager, "Allocate Buffer acquired_slot = %d ", acquired_slot);
+  }
+
+  const AllocatedBufferInfo &alloc_buffer_info =
+    buffer_slot_[acquired_slot].hw_buffer_info.alloc_buffer_info;
+  uint32_t curr_index = buffer_slot_[acquired_slot].curr_index;
+
+  // Wait for the release fence fd before buffer slot being given to the client.
+  buffer_sync_handler_->SyncWait(buffer_slot_[acquired_slot].release_fd[curr_index]);
+  buffer_slot_[acquired_slot].release_fd[curr_index] = -1;
+
+  hw_buffer_info->output_buffer.width = buffer_config.width;
+  hw_buffer_info->output_buffer.height = buffer_config.height;
+  hw_buffer_info->output_buffer.format = buffer_config.format;
+  hw_buffer_info->output_buffer.flags.secure = buffer_config.secure;
+
+  hw_buffer_info->output_buffer.planes[0].stride = alloc_buffer_info.stride;
+  hw_buffer_info->output_buffer.planes[0].fd = alloc_buffer_info.fd;
+  hw_buffer_info->output_buffer.planes[0].offset = buffer_slot_[acquired_slot].offset[curr_index];
+  hw_buffer_info->slot = acquired_slot;
+
+  DLOGI_IF(kTagBufferManager, "Output: w = %d h = %d f = %d session_id %d acquired slot = %d " \
+           "num_used_slot %d curr_index = %d offset %d", hw_buffer_info->output_buffer.width,
+           hw_buffer_info->output_buffer.height, hw_buffer_info->output_buffer.format,
+           hw_buffer_info->session_id, acquired_slot, num_used_slot_, curr_index,
+           hw_buffer_info->output_buffer.planes[0].offset);
+
+  return kErrorNone;
+}
+
+DisplayError BufferManager::Stop(int *session_ids) {
+  DisplayError error = kErrorNone;
+  uint32_t slot = 0, count = 0;
+
+  // Free all the buffer slots which were not acquired in the current cycle and deallocate the
+  // buffers associated with it.
+  while ((num_used_slot_ > 0) && (slot < kMaxBufferSlotCount)) {
+    if (buffer_slot_[slot].state == kBufferSlotReady) {
+      if (buffer_slot_[slot].hw_buffer_info.session_id != -1) {
+        session_ids[count++] = buffer_slot_[slot].hw_buffer_info.session_id;
+      }
+
+      error = FreeBufferSlot(slot);
+      if (error != kErrorNone) {
+        return error;
+      }
+
+      num_used_slot_--;
+    }
+    slot++;
+  }
+
+  session_ids[count] = -1;
+
+  return kErrorNone;
+}
+
+DisplayError BufferManager::SetReleaseFd(uint32_t slot, int fd) {
+  if ((slot >= kMaxBufferSlotCount) || (buffer_slot_[slot].state != kBufferSlotAcquired)) {
+    DLOGE("Invalid Parameters slot %d state %s", slot, buffer_slot_[slot].state);
+    kErrorParameters;
+  }
+
+  uint32_t &curr_index = buffer_slot_[slot].curr_index;
+  const HWBufferInfo &hw_buffer_info = buffer_slot_[slot].hw_buffer_info;
+  uint32_t buffer_count = hw_buffer_info.buffer_config.buffer_count;
+
+  // 1. Store the release fence fd, so that buffer manager waits for the release fence fd to be
+  //    signaled and gives the buffer slot to the client.
+  // 2. Modify the curr_index to point to next buffer.
+  buffer_slot_[slot].release_fd[curr_index] = fd;
+  curr_index = (curr_index + 1) % buffer_count;
+
+  DLOGI_IF(kTagBufferManager, "w = %d h = %d f = %d session_id %d slot = %d curr_index = %d " \
+           "sync fd %d", hw_buffer_info.output_buffer.width, hw_buffer_info.output_buffer.height,
+           hw_buffer_info.output_buffer.format, hw_buffer_info.session_id, slot, curr_index, fd);
+
+  return kErrorNone;
+}
+
+
+DisplayError BufferManager::SetSessionId(uint32_t slot, int session_id) {
+  if ((slot >= kMaxBufferSlotCount) || (buffer_slot_[slot].state != kBufferSlotAcquired)) {
+    DLOGE("Invalid Parameters slot %d state %s", slot, buffer_slot_[slot].state);
+    kErrorParameters;
+  }
+
+  HWBufferInfo *hw_buffer_info = &buffer_slot_[slot].hw_buffer_info;
+
+  hw_buffer_info->session_id = session_id;
+
+  DLOGI_IF(kTagBufferManager, "w = %d h = %d f = %d session_id %d slot = %d",
+           hw_buffer_info->output_buffer.width, hw_buffer_info->output_buffer.height,
+           hw_buffer_info->output_buffer.format, hw_buffer_info->session_id, slot);
+
+  return kErrorNone;
+}
+
+DisplayError BufferManager::FreeBufferSlot(uint32_t slot) {
+  DisplayError error = kErrorNone;
+
+  HWBufferInfo *hw_buffer_info = &buffer_slot_[slot].hw_buffer_info;
+
+  error = buffer_allocator_->FreeBuffer(hw_buffer_info);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  DLOGI_IF(kTagBufferManager, "session_id %d slot = %d num_used_slot %d",
+           hw_buffer_info->session_id, slot, num_used_slot_);
+
+  buffer_slot_[slot].Deinit();
+
+  return kErrorNone;
+}
+
+}  // namespace sde
diff --git a/displayengine/libs/core/buffer_manager.h b/displayengine/libs/core/buffer_manager.h
new file mode 100644
index 0000000..29bcd03
--- /dev/null
+++ b/displayengine/libs/core/buffer_manager.h
@@ -0,0 +1,82 @@
+/*
+* Copyright (c) 2015, 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.
+*/
+
+#ifndef __BUFFER_MANAGER_H__
+#define __BUFFER_MANAGER_H__
+
+#include <utils/locker.h>
+#include <core/buffer_allocator.h>
+#include "hw_interface.h"
+
+namespace sde {
+
+class BufferManager {
+ public:
+  BufferManager(BufferAllocator *buffer_allocator, BufferSyncHandler *buffer_sync_handler);
+
+  void Start();
+  DisplayError GetNextBuffer(HWBufferInfo *hw_buffer_info);
+  DisplayError Stop(int *session_ids);
+  DisplayError SetReleaseFd(uint32_t slot, int fd);
+  DisplayError SetSessionId(uint32_t slot, int session_id);
+
+ private:
+  static const uint32_t kMaxBufferSlotCount = 32;
+
+  enum kBufferSlotState {
+    kBufferSlotFree     = 0,
+    kBufferSlotReady    = 1,
+    kBufferSlotAcquired = 2,
+  };
+
+  struct BufferSlot {
+    HWBufferInfo hw_buffer_info;
+    kBufferSlotState state;
+    int *release_fd;
+    uint32_t *offset;
+    uint32_t curr_index;
+
+    BufferSlot() : state(kBufferSlotFree), release_fd(NULL), offset(NULL), curr_index(0) { }
+    DisplayError Init();
+    DisplayError Deinit();
+  };
+
+  DisplayError FreeBufferSlot(uint32_t index);
+
+  BufferSlot buffer_slot_[kMaxBufferSlotCount];
+  BufferAllocator *buffer_allocator_;
+  BufferSyncHandler *buffer_sync_handler_;
+  uint32_t num_used_slot_;
+};
+
+}  // namespace sde
+
+#endif  // __BUFFER_MANAGER_H__
+
+
diff --git a/displayengine/libs/core/comp_manager.cpp b/displayengine/libs/core/comp_manager.cpp
index 40191e5..7e888ee 100644
--- a/displayengine/libs/core/comp_manager.cpp
+++ b/displayengine/libs/core/comp_manager.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -25,6 +25,7 @@
 #include <dlfcn.h>
 #include <utils/constants.h>
 #include <utils/debug.h>
+#include <core/buffer_allocator.h>
 
 #include "comp_manager.h"
 #include "strategy_default.h"
@@ -38,12 +39,13 @@
     registered_displays_(0), configured_displays_(0), safe_mode_(false) {
 }
 
-DisplayError CompManager::Init(const HWResourceInfo &hw_res_info) {
+DisplayError CompManager::Init(const HWResourceInfo &hw_res_info, BufferAllocator *buffer_allocator,
+                               BufferSyncHandler *buffer_sync_handler) {
   SCOPE_LOCK(locker_);
 
   DisplayError error = kErrorNone;
 
-  error = res_mgr_.Init(hw_res_info);
+  error = res_mgr_.Init(hw_res_info, buffer_allocator, buffer_sync_handler);
   if (error != kErrorNone) {
     return error;
   }
@@ -108,6 +110,7 @@
                             &display_comp_ctx->strategy_intf) != kErrorNone) {
     DLOGW("Unable to create strategy interface");
     delete display_comp_ctx;
+    display_comp_ctx = NULL;
     return kErrorUndefined;
   }
 
@@ -115,15 +118,22 @@
   if (error != kErrorNone) {
     destroy_strategy_intf_(display_comp_ctx->strategy_intf);
     delete display_comp_ctx;
+    display_comp_ctx = NULL;
     return error;
   }
 
   SET_BIT(registered_displays_, type);
   display_comp_ctx->display_type = type;
   *display_ctx = display_comp_ctx;
-  // New display device has been added, so move the composition mode to safe mode until unless
+  // New non-primary display device has been added, so move the composition mode to safe mode until
   // resources for the added display is configured properly.
-  safe_mode_ = true;
+  if (type != kPrimary) {
+    safe_mode_ = true;
+  }
+
+  DLOGV_IF(kTagCompManager, "registered display bit mask 0x%x, configured display bit mask 0x%x, " \
+           "display type %d", registered_displays_, configured_displays_,
+           display_comp_ctx->display_type);
 
   return kErrorNone;
 }
@@ -140,7 +150,14 @@
   CLEAR_BIT(registered_displays_, display_comp_ctx->display_type);
   CLEAR_BIT(configured_displays_, display_comp_ctx->display_type);
 
-  delete display_comp_ctx;
+  DLOGV_IF(kTagCompManager, "registered display bit mask 0x%x, configured display bit mask 0x%x, " \
+           "display type %d", registered_displays_, configured_displays_,
+           display_comp_ctx->display_type);
+
+  if (display_comp_ctx) {
+    delete display_comp_ctx;
+    display_comp_ctx = NULL;
+  }
 
   return kErrorNone;
 }
@@ -161,6 +178,10 @@
   if (display_comp_ctx->remaining_strategies != display_comp_ctx->max_strategies) {
     constraints->safe_mode = true;
   }
+
+  if (display_comp_ctx->idle_fallback) {
+    constraints->safe_mode = true;
+  }
 }
 
 void CompManager::PrePrepare(Handle display_ctx, HWLayers *hw_layers) {
@@ -170,6 +191,13 @@
   display_comp_ctx->strategy_intf->Start(&hw_layers->info,
                                          &display_comp_ctx->max_strategies);
   display_comp_ctx->remaining_strategies = display_comp_ctx->max_strategies;
+
+  // Avoid idle fallback, if there is only one app layer.
+  // TODO(user): App layer count will change for hybrid composition
+  uint32_t app_layer_count = hw_layers->info.stack->layer_count - 1;
+  if (!display_comp_ctx->idle_fallback && app_layer_count > 1) {
+    display_comp_ctx->handle_idle_timeout = true;
+  }
 }
 
 DisplayError CompManager::Prepare(Handle display_ctx, HWLayers *hw_layers) {
@@ -212,16 +240,27 @@
   return error;
 }
 
-void CompManager::PostPrepare(Handle display_ctx, HWLayers *hw_layers) {
+DisplayError CompManager::PostPrepare(Handle display_ctx, HWLayers *hw_layers) {
   SCOPE_LOCK(locker_);
   DisplayCompositionContext *display_comp_ctx =
                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+  Handle &display_resource_ctx = display_comp_ctx->display_resource_ctx;
+
+  DisplayError error = kErrorNone;
+  error = res_mgr_.PostPrepare(display_resource_ctx, hw_layers);
+  if (error != kErrorNone) {
+    return error;
+  }
+
   display_comp_ctx->strategy_intf->Stop();
+
+  return kErrorNone;
 }
 
-void CompManager::PostCommit(Handle display_ctx, HWLayers *hw_layers) {
+DisplayError CompManager::PostCommit(Handle display_ctx, HWLayers *hw_layers) {
   SCOPE_LOCK(locker_);
 
+  DisplayError error = kErrorNone;
   DisplayCompositionContext *display_comp_ctx =
                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
   SET_BIT(configured_displays_, display_comp_ctx->display_type);
@@ -229,7 +268,18 @@
       safe_mode_ = false;
   }
 
-  res_mgr_.PostCommit(display_comp_ctx->display_resource_ctx, hw_layers);
+  error = res_mgr_.PostCommit(display_comp_ctx->display_resource_ctx, hw_layers);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  display_comp_ctx->idle_fallback = false;
+
+  DLOGV_IF(kTagCompManager, "registered display bit mask 0x%x, configured display bit mask 0x%x, " \
+           "display type %d", registered_displays_, configured_displays_,
+           display_comp_ctx->display_type);
+
+  return kErrorNone;
 }
 
 void CompManager::Purge(Handle display_ctx) {
@@ -241,6 +291,32 @@
   res_mgr_.Purge(display_comp_ctx->display_resource_ctx);
 }
 
+bool CompManager::ProcessIdleTimeout(Handle display_ctx) {
+  SCOPE_LOCK(locker_);
+
+  DisplayCompositionContext *display_comp_ctx =
+                             reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+
+  if (!display_comp_ctx) {
+    return false;
+  }
+
+  // 1. handle_idle_timeout flag is set to true on start of every draw call, if the current
+  //    composition is not due to idle fallback.
+  // 2. idle_fallback flag will be set only if handle_idle_timeout flag is true and there is no
+  //    update to the screen for specified amount of time.
+  // 3. handle_idle_timeout flag helps us handle the very first idle timeout event and
+  //    ignore the next idle timeout event on consecutive two idle timeout events.
+  if (display_comp_ctx->handle_idle_timeout) {
+    display_comp_ctx->idle_fallback = true;
+    display_comp_ctx->handle_idle_timeout = false;
+
+    return true;
+  }
+
+  return false;
+}
+
 void CompManager::AppendDump(char *buffer, uint32_t length) {
   SCOPE_LOCK(locker_);
 }
diff --git a/displayengine/libs/core/comp_manager.h b/displayengine/libs/core/comp_manager.h
index aed357b..24a0fff 100644
--- a/displayengine/libs/core/comp_manager.h
+++ b/displayengine/libs/core/comp_manager.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -36,16 +36,18 @@
 class CompManager : public DumpImpl {
  public:
   CompManager();
-  DisplayError Init(const HWResourceInfo &hw_res_info_);
+  DisplayError Init(const HWResourceInfo &hw_res_info_, BufferAllocator *buffer_allocator,
+                    BufferSyncHandler *buffer_sync_handler_);
   DisplayError Deinit();
   DisplayError RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
                                Handle *res_mgr_hnd);
   DisplayError UnregisterDisplay(Handle res_mgr_hnd);
   void PrePrepare(Handle display_ctx, HWLayers *hw_layers);
   DisplayError Prepare(Handle display_ctx, HWLayers *hw_layers);
-  void PostPrepare(Handle display_ctx, HWLayers *hw_layers);
-  void PostCommit(Handle display_ctx, HWLayers *hw_layers);
+  DisplayError PostPrepare(Handle display_ctx, HWLayers *hw_layers);
+  DisplayError PostCommit(Handle display_ctx, HWLayers *hw_layers);
   void Purge(Handle display_ctx);
+  bool ProcessIdleTimeout(Handle display_ctx);
 
   // DumpImpl method
   virtual void AppendDump(char *buffer, uint32_t length);
@@ -60,6 +62,12 @@
     DisplayType display_type;
     uint32_t max_strategies;
     uint32_t remaining_strategies;
+    bool idle_fallback;
+    bool handle_idle_timeout;
+
+    DisplayCompositionContext()
+      : display_resource_ctx(NULL), display_type(kPrimary), max_strategies(0),
+        remaining_strategies(0), idle_fallback(false), handle_idle_timeout(true) { }
   };
 
   Locker locker_;
diff --git a/displayengine/libs/core/core_impl.cpp b/displayengine/libs/core/core_impl.cpp
old mode 100755
new mode 100644
index 0669f9f..bd6ab9a
--- a/displayengine/libs/core/core_impl.cpp
+++ b/displayengine/libs/core/core_impl.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -35,8 +35,10 @@
 
 namespace sde {
 
-CoreImpl::CoreImpl(CoreEventHandler *event_handler)
-  : event_handler_(event_handler), hw_intf_(NULL) {
+CoreImpl::CoreImpl(CoreEventHandler *event_handler, BufferAllocator *buffer_allocator,
+                   BufferSyncHandler *buffer_sync_handler)
+  : event_handler_(event_handler), buffer_allocator_(buffer_allocator),
+    buffer_sync_handler_(buffer_sync_handler), hw_intf_(NULL) {
 }
 
 DisplayError CoreImpl::Init() {
@@ -44,7 +46,7 @@
 
   DisplayError error = kErrorNone;
 
-  error = HWInterface::Create(&hw_intf_);
+  error = HWInterface::Create(&hw_intf_, buffer_sync_handler_);
   if (UNLIKELY(error != kErrorNone)) {
     return error;
   }
@@ -56,7 +58,7 @@
     return error;
   }
 
-  error = comp_mgr_.Init(hw_res_info);
+  error = comp_mgr_.Init(hw_res_info, buffer_allocator_, buffer_sync_handler_);
   if (UNLIKELY(error != kErrorNone)) {
     HWInterface::Destroy(hw_intf_);
     return error;
@@ -83,7 +85,7 @@
 }
 
 DisplayError CoreImpl::CreateDisplay(DisplayType type, DisplayEventHandler *event_handler,
-                                    DisplayInterface **intf) {
+                                     DisplayInterface **intf) {
   SCOPE_LOCK(locker_);
 
   if (UNLIKELY(!event_handler || !intf)) {
@@ -93,15 +95,15 @@
   DisplayBase *display_base = NULL;
   switch (type) {
   case kPrimary:
-    display_base = new DisplayPrimary(event_handler, hw_intf_, &comp_mgr_);
+    display_base = new DisplayPrimary(event_handler, hw_intf_, &comp_mgr_, &offline_ctrl_);
     break;
 
   case kHDMI:
-    display_base = new DisplayHDMI(event_handler, hw_intf_, &comp_mgr_);
+    display_base = new DisplayHDMI(event_handler, hw_intf_, &comp_mgr_, &offline_ctrl_);
     break;
 
   case kVirtual:
-    display_base = new DisplayVirtual(event_handler, hw_intf_, &comp_mgr_);
+    display_base = new DisplayVirtual(event_handler, hw_intf_, &comp_mgr_, &offline_ctrl_);
     break;
 
   default:
@@ -116,6 +118,7 @@
   DisplayError error = display_base->Init();
   if (UNLIKELY(error != kErrorNone)) {
     delete display_base;
+    display_base = NULL;
     return error;
   }
 
@@ -133,6 +136,7 @@
   DisplayBase *display_base = static_cast<DisplayBase *>(intf);
   display_base->Deinit();
   delete display_base;
+  display_base = NULL;
 
   return kErrorNone;
 }
diff --git a/displayengine/libs/core/core_impl.h b/displayengine/libs/core/core_impl.h
index ad86c60..e289a23 100644
--- a/displayengine/libs/core/core_impl.h
+++ b/displayengine/libs/core/core_impl.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -42,7 +42,8 @@
   // This class implements display core interface revision 1.0.
   static const uint16_t kRevision = SET_REVISION(1, 0);
 
-  explicit CoreImpl(CoreEventHandler *event_handler);
+  CoreImpl(CoreEventHandler *event_handler, BufferAllocator *buffer_allocator,
+           BufferSyncHandler *buffer_sync_handler);
   virtual ~CoreImpl() { }
 
   // This method returns the interface revision for the current display core object.
@@ -59,6 +60,8 @@
  protected:
   Locker locker_;
   CoreEventHandler *event_handler_;
+  BufferAllocator *buffer_allocator_;
+  BufferSyncHandler *buffer_sync_handler_;
   HWInterface *hw_intf_;
   CompManager comp_mgr_;
   OfflineCtrl offline_ctrl_;
diff --git a/displayengine/libs/core/core_interface.cpp b/displayengine/libs/core/core_interface.cpp
old mode 100755
new mode 100644
index fb8700a..c982b4d
--- a/displayengine/libs/core/core_interface.cpp
+++ b/displayengine/libs/core/core_interface.cpp
@@ -1,30 +1,36 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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.
+* 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.
+* 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.
 */
 
 #include <utils/locker.h>
 #include <utils/constants.h>
 #include <utils/debug.h>
+#include <core/buffer_sync_handler.h>
 
 #include "core_impl.h"
 
@@ -45,11 +51,14 @@
   Locker locker;
 } g_core;
 
-DisplayError CoreInterface::CreateCore(CoreEventHandler *event_handler, LogHandler *log_handler,
+// TODO(user): Have a single structure handle carries all the interface pointers.
+DisplayError CoreInterface::CreateCore(CoreEventHandler *event_handler, DebugHandler *debug_handler,
+                                       BufferAllocator *buffer_allocator,
+                                       BufferSyncHandler *buffer_sync_handler,
                                        CoreInterface **interface, uint32_t client_version) {
   SCOPE_LOCK(g_core.locker);
 
-  if (UNLIKELY(!event_handler || !log_handler || !interface)) {
+  if (!event_handler || !debug_handler || !buffer_allocator || !buffer_sync_handler || !interface) {
     return kErrorParameters;
   }
 
@@ -68,11 +77,11 @@
     return kErrorUndefined;
   }
 
-  Debug::SetLogHandler(log_handler);
+  Debug::SetDebugHandler(debug_handler);
 
   // Create appropriate CoreImpl object based on client version.
   if (GET_REVISION(client_version) == CoreImpl::kRevision) {
-    core_impl = new CoreImpl(event_handler);
+    core_impl = new CoreImpl(event_handler, buffer_allocator, buffer_sync_handler);
   } else {
     return kErrorNotSupported;
   }
diff --git a/displayengine/libs/core/display_base.cpp b/displayengine/libs/core/display_base.cpp
index 080deb7..058bacc 100644
--- a/displayengine/libs/core/display_base.cpp
+++ b/displayengine/libs/core/display_base.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -26,17 +26,20 @@
 #include <utils/debug.h>
 
 #include "display_base.h"
+#include "offline_ctrl.h"
 
 #define __CLASS__ "DisplayBase"
 
 namespace sde {
 
+// TODO(user): Have a single structure handle carries all the interface pointers and variables.
 DisplayBase::DisplayBase(DisplayType display_type, DisplayEventHandler *event_handler,
-             HWDeviceType hw_device_type, HWInterface *hw_intf, CompManager *comp_manager)
+                         HWDeviceType hw_device_type, HWInterface *hw_intf,
+                         CompManager *comp_manager, OfflineCtrl *offline_ctrl)
   : display_type_(display_type), event_handler_(event_handler), hw_device_type_(hw_device_type),
-    hw_intf_(hw_intf), comp_manager_(comp_manager), state_(kStateOff), hw_device_(0),
-    display_comp_ctx_(0), display_attributes_(NULL), num_modes_(0), active_mode_index_(0),
-    pending_commit_(false), vsync_enable_(false) {
+    hw_intf_(hw_intf), comp_manager_(comp_manager), offline_ctrl_(offline_ctrl), state_(kStateOff),
+    hw_device_(0), display_comp_ctx_(0), display_attributes_(NULL), num_modes_(0),
+    active_mode_index_(0), pending_commit_(false), vsync_enable_(false) {
 }
 
 DisplayError DisplayBase::Init() {
@@ -49,6 +52,9 @@
     return error;
   }
 
+  // Set the idle timeout value to driver through sysfs node
+  hw_intf_->SetIdleTimeoutMs(hw_device_, Debug::GetIdleTimeoutMs());
+
   error = hw_intf_->GetNumDisplayAttributes(hw_device_, &num_modes_);
   if (error != kErrorNone) {
     goto CleanupOnError;
@@ -80,13 +86,21 @@
     goto CleanupOnError;
   }
 
+  error = offline_ctrl_->RegisterDisplay(display_type_, &display_offline_ctx_);
+  if (UNLIKELY(error != kErrorNone)) {
+    goto CleanupOnError;
+  }
+
   return kErrorNone;
 
 CleanupOnError:
-  comp_manager_->UnregisterDisplay(display_comp_ctx_);
+  if (display_comp_ctx_) {
+    comp_manager_->UnregisterDisplay(display_comp_ctx_);
+  }
 
   if (display_attributes_) {
     delete[] display_attributes_;
+    display_attributes_ = NULL;
   }
 
   hw_intf_->Close(hw_device_);
@@ -97,8 +111,15 @@
 DisplayError DisplayBase::Deinit() {
   SCOPE_LOCK(locker_);
 
+  offline_ctrl_->UnregisterDisplay(display_offline_ctx_);
+
   comp_manager_->UnregisterDisplay(display_comp_ctx_);
-  delete[] display_attributes_;
+
+  if (display_attributes_) {
+    delete[] display_attributes_;
+    display_attributes_ = NULL;
+  }
+
   hw_intf_->Close(hw_device_);
 
   return kErrorNone;
@@ -115,7 +136,7 @@
 
   pending_commit_ = false;
 
-  if ((state_ == kStateOn)) {
+  if (state_ == kStateOn) {
     // Clean hw layers for reuse.
     hw_layers_.info = HWLayersInfo();
     hw_layers_.info.stack = layer_stack;
@@ -127,14 +148,22 @@
         break;
       }
 
-      error = hw_intf_->Validate(hw_device_, &hw_layers_);
+      error = offline_ctrl_->Prepare(display_offline_ctx_, &hw_layers_);
       if (error == kErrorNone) {
-        // Strategy is successful now, wait for Commit().
-        pending_commit_ = true;
-        break;
+        error = hw_intf_->Validate(hw_device_, &hw_layers_);
+        if (error == kErrorNone) {
+          error = comp_manager_->PostPrepare(display_comp_ctx_, &hw_layers_);
+          if (error == kErrorNone) {
+            // Strategy is successful now, wait for Commit().
+            pending_commit_ = true;
+            break;
+          }
+        }
       }
     }
     comp_manager_->PostPrepare(display_comp_ctx_, &hw_layers_);
+  } else {
+    return kErrorNotSupported;
   }
 
   return error;
@@ -149,18 +178,26 @@
     return kErrorParameters;
   }
 
-  if (!pending_commit_) {
-    DLOGE("Commit: Corresponding Prepare() is not called for display = %d", display_type_);
-    return kErrorUndefined;
-  }
-
   if (state_ == kStateOn) {
-    error = hw_intf_->Commit(hw_device_, &hw_layers_);
-    if (error == kErrorNone) {
-      comp_manager_->PostCommit(display_comp_ctx_, &hw_layers_);
-    } else {
-      DLOGE("Unexpected error. Commit failed on driver.");
+    if (!pending_commit_) {
+      DLOGE("Commit: Corresponding Prepare() is not called for display = %d", display_type_);
+      return kErrorUndefined;
     }
+
+    error = offline_ctrl_->Commit(display_offline_ctx_, &hw_layers_);
+    if (error == kErrorNone) {
+      error = hw_intf_->Commit(hw_device_, &hw_layers_);
+      if (error == kErrorNone) {
+        error = comp_manager_->PostCommit(display_comp_ctx_, &hw_layers_);
+        if (error != kErrorNone) {
+          DLOGE("Composition manager PostCommit failed");
+        }
+      } else {
+        DLOGE("Unexpected error. Commit failed on driver.");
+      }
+    }
+  } else {
+    return kErrorNotSupported;
   }
 
   pending_commit_ = false;
@@ -168,6 +205,27 @@
   return kErrorNone;
 }
 
+DisplayError DisplayBase::Flush() {
+  SCOPE_LOCK(locker_);
+
+  DisplayError error = kErrorNone;
+
+  if (state_ != kStateOn) {
+    return kErrorNone;
+  }
+
+  hw_layers_.info.count = 0;
+  error = hw_intf_->Flush(hw_device_);
+  if (error == kErrorNone) {
+    comp_manager_->Purge(display_comp_ctx_);
+    pending_commit_ = false;
+  } else {
+    DLOGV("Failed to flush device.");
+  }
+
+  return error;
+}
+
 DisplayError DisplayBase::GetDisplayState(DisplayState *state) {
   SCOPE_LOCK(locker_);
 
@@ -249,9 +307,14 @@
 
   switch (state) {
   case kStateOff:
-    hw_layers_.info.count = 0;
-    comp_manager_->Purge(display_comp_ctx_);
-    error = hw_intf_->PowerOff(hw_device_);
+    // Invoke flush during suspend for HDMI and virtual displays. StateOff is handled
+    // separately for primary in DisplayPrimary::SetDisplayState() function.
+    error = hw_intf_->Flush(hw_device_);
+    if (error == kErrorNone) {
+      comp_manager_->Purge(display_comp_ctx_);
+      state_ = state;
+      hw_layers_.info.count = 0;
+    }
     break;
 
   case kStateOn:
@@ -278,6 +341,36 @@
   return error;
 }
 
+DisplayError DisplayBase::SetActiveConfig(DisplayConfigVariableInfo *variable_info) {
+  SCOPE_LOCK(locker_);
+  DisplayError error = kErrorNone;
+
+  if (!variable_info) {
+    return kErrorParameters;
+  }
+
+  HWDisplayAttributes display_attributes = display_attributes_[active_mode_index_];
+
+  display_attributes.x_pixels = variable_info->x_pixels;
+  display_attributes.y_pixels = variable_info->y_pixels;
+  display_attributes.fps = variable_info->fps;
+
+  // if display is already connected, unregister display from composition manager and register
+  // the display with new configuration.
+  if (display_comp_ctx_) {
+    comp_manager_->UnregisterDisplay(display_comp_ctx_);
+  }
+
+  error = comp_manager_->RegisterDisplay(display_type_, display_attributes, &display_comp_ctx_);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  display_attributes_[active_mode_index_] = display_attributes;
+
+  return kErrorNone;
+}
+
 DisplayError DisplayBase::SetActiveConfig(uint32_t index) {
   SCOPE_LOCK(locker_);
   DisplayError error = kErrorNone;
@@ -288,9 +381,18 @@
 
   error = hw_intf_->SetDisplayAttributes(hw_device_, index);
   if (error != kErrorNone) {
-    active_mode_index_ = index;
+    return error;
   }
 
+  active_mode_index_ = index;
+
+  if (display_comp_ctx_) {
+    comp_manager_->UnregisterDisplay(display_comp_ctx_);
+  }
+
+  error = comp_manager_->RegisterDisplay(display_type_, display_attributes_[index],
+                                         &display_comp_ctx_);
+
   return error;
 }
 
@@ -307,6 +409,10 @@
   return error;
 }
 
+void DisplayBase::SetIdleTimeoutMs(uint32_t timeout_ms) {
+  hw_intf_->SetIdleTimeoutMs(hw_device_, timeout_ms);
+}
+
 DisplayError DisplayBase::VSync(int64_t timestamp) {
   if (vsync_enable_) {
     DisplayEventVSync vsync;
@@ -321,6 +427,13 @@
   return kErrorNone;
 }
 
+void DisplayBase::IdleTimeout() {
+  bool need_refresh = comp_manager_->ProcessIdleTimeout(display_comp_ctx_);
+  if (need_refresh) {
+    event_handler_->Refresh();
+  }
+}
+
 void DisplayBase::AppendDump(char *buffer, uint32_t length) {
   SCOPE_LOCK(locker_);
 
@@ -350,6 +463,8 @@
     HWLayerConfig &layer_config = hw_layers_.config[i];
     HWPipeInfo &left_pipe = hw_layers_.config[i].left_pipe;
     HWPipeInfo &right_pipe = hw_layers_.config[i].right_pipe;
+    HWRotateInfo &left_rotate = hw_layers_.config[i].rotates[0];
+    HWRotateInfo &right_rotate = hw_layers_.config[i].rotates[1];
 
     AppendString(buffer, length, "\n\nsde idx: %u, actual idx: %u", i, hw_layers_.info.index[i]);
     AppendString(buffer, length, "\nw: %u, h: %u, fmt: %u",
@@ -357,13 +472,29 @@
     AppendRect(buffer, length, "\nsrc_rect:", &layer.src_rect);
     AppendRect(buffer, length, "\ndst_rect:", &layer.dst_rect);
 
-    AppendString(buffer, length, "\n\tleft split =>");
-    AppendString(buffer, length, "\n\t  pipe id: 0x%x", left_pipe.pipe_id);
-    AppendRect(buffer, length, "\n\t  src_roi:", &left_pipe.src_roi);
-    AppendRect(buffer, length, "\n\t  dst_roi:", &left_pipe.dst_roi);
+    if (left_rotate.valid) {
+      AppendString(buffer, length, "\n\tleft rotate =>");
+      AppendString(buffer, length, "\n\t  pipe id: 0x%x", left_rotate.pipe_id);
+      AppendRect(buffer, length, "\n\t  src_roi:", &left_rotate.src_roi);
+      AppendRect(buffer, length, "\n\t  dst_roi:", &left_rotate.dst_roi);
+    }
 
-    if (layer_config.is_right_pipe) {
-      AppendString(buffer, length, "\n\tright split =>");
+    if (right_rotate.valid) {
+      AppendString(buffer, length, "\n\tright rotate =>");
+      AppendString(buffer, length, "\n\t  pipe id: 0x%x", right_rotate.pipe_id);
+      AppendRect(buffer, length, "\n\t  src_roi:", &right_rotate.src_roi);
+      AppendRect(buffer, length, "\n\t  dst_roi:", &right_rotate.dst_roi);
+    }
+
+    if (left_pipe.valid) {
+      AppendString(buffer, length, "\n\tleft pipe =>");
+      AppendString(buffer, length, "\n\t  pipe id: 0x%x", left_pipe.pipe_id);
+      AppendRect(buffer, length, "\n\t  src_roi:", &left_pipe.src_roi);
+      AppendRect(buffer, length, "\n\t  dst_roi:", &left_pipe.dst_roi);
+    }
+
+    if (right_pipe.valid) {
+      AppendString(buffer, length, "\n\tright pipe =>");
       AppendString(buffer, length, "\n\t  pipe id: 0x%x", right_pipe.pipe_id);
       AppendRect(buffer, length, "\n\t  src_roi:", &right_pipe.src_roi);
       AppendRect(buffer, length, "\n\t  dst_roi:", &right_pipe.dst_roi);
diff --git a/displayengine/libs/core/display_base.h b/displayengine/libs/core/display_base.h
index 3f0e24f..d2b67e3 100644
--- a/displayengine/libs/core/display_base.h
+++ b/displayengine/libs/core/display_base.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -31,18 +31,24 @@
 
 #include "hw_interface.h"
 #include "comp_manager.h"
+#include "buffer_manager.h"
+
 
 namespace sde {
 
+class OfflineCtrl;
+
 class DisplayBase : public DisplayInterface, HWEventHandler, DumpImpl {
  public:
   DisplayBase(DisplayType display_type, DisplayEventHandler *event_handler,
-              HWDeviceType hw_device_type, HWInterface *hw_intf, CompManager *comp_manager);
+              HWDeviceType hw_device_type, HWInterface *hw_intf, CompManager *comp_manager,
+              OfflineCtrl *offline_ctrl);
   virtual ~DisplayBase() { }
   virtual DisplayError Init();
   virtual DisplayError Deinit();
   virtual DisplayError Prepare(LayerStack *layer_stack);
   virtual DisplayError Commit(LayerStack *layer_stack);
+  virtual DisplayError Flush();
   virtual DisplayError GetDisplayState(DisplayState *state);
   virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count);
   virtual DisplayError GetConfig(DisplayConfigFixedInfo *fixed_info);
@@ -50,12 +56,15 @@
   virtual DisplayError GetActiveConfig(uint32_t *index);
   virtual DisplayError GetVSyncState(bool *enabled);
   virtual DisplayError SetDisplayState(DisplayState state);
+  virtual DisplayError SetActiveConfig(DisplayConfigVariableInfo *variable_info);
   virtual DisplayError SetActiveConfig(uint32_t index);
   virtual DisplayError SetVSyncState(bool enable);
+  virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
 
   // Implement the HWEventHandlers
   virtual DisplayError VSync(int64_t timestamp);
   virtual DisplayError Blank(bool blank);
+  virtual void IdleTimeout();
 
   // DumpImpl method
   virtual void AppendDump(char *buffer, uint32_t length);
@@ -70,9 +79,11 @@
   HWDeviceType hw_device_type_;
   HWInterface *hw_intf_;
   CompManager *comp_manager_;
+  OfflineCtrl *offline_ctrl_;
   DisplayState state_;
   Handle hw_device_;
   Handle display_comp_ctx_;
+  Handle display_offline_ctx_;
   HWDisplayAttributes *display_attributes_;
   uint32_t num_modes_;
   uint32_t active_mode_index_;
diff --git a/displayengine/libs/core/display_hdmi.cpp b/displayengine/libs/core/display_hdmi.cpp
index 14a09f1..ed2a859 100644
--- a/displayengine/libs/core/display_hdmi.cpp
+++ b/displayengine/libs/core/display_hdmi.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -32,9 +32,8 @@
 namespace sde {
 
 DisplayHDMI::DisplayHDMI(DisplayEventHandler *event_handler, HWInterface *hw_intf,
-                         CompManager *comp_manager)
-  : DisplayBase(kHDMI, event_handler, kDeviceHDMI, hw_intf, comp_manager) {
-}
+                         CompManager *comp_manager, OfflineCtrl *offline_ctrl)
+  : DisplayBase(kHDMI, event_handler, kDeviceHDMI, hw_intf, comp_manager, offline_ctrl) { }
 
 int DisplayHDMI::GetBestConfig() {
   uint32_t best_config_mode = 0;
diff --git a/displayengine/libs/core/display_hdmi.h b/displayengine/libs/core/display_hdmi.h
index 0bb9dc8..91e4797 100644
--- a/displayengine/libs/core/display_hdmi.h
+++ b/displayengine/libs/core/display_hdmi.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -31,7 +31,8 @@
 
 class DisplayHDMI : public DisplayBase {
  public:
-  DisplayHDMI(DisplayEventHandler *event_handler, HWInterface *hw_intf, CompManager *comp_manager);
+  DisplayHDMI(DisplayEventHandler *event_handler, HWInterface *hw_intf, CompManager *comp_manager,
+              OfflineCtrl *offline_ctrl);
   virtual int GetBestConfig();
 };
 
diff --git a/displayengine/libs/core/display_primary.cpp b/displayengine/libs/core/display_primary.cpp
old mode 100755
new mode 100644
index e4bd031..ac44fe3
--- a/displayengine/libs/core/display_primary.cpp
+++ b/displayengine/libs/core/display_primary.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -32,8 +32,31 @@
 namespace sde {
 
 DisplayPrimary::DisplayPrimary(DisplayEventHandler *event_handler, HWInterface *hw_intf,
-                               CompManager *comp_manager)
-  : DisplayBase(kPrimary, event_handler, kDevicePrimary, hw_intf, comp_manager) {
+                               CompManager *comp_manager, OfflineCtrl *offline_ctrl)
+  : DisplayBase(kPrimary, event_handler, kDevicePrimary, hw_intf, comp_manager, offline_ctrl) { }
+
+DisplayError DisplayPrimary::SetDisplayState(DisplayState state) {
+  DisplayError error = kErrorNone;
+
+  DLOGI("Set state = %d", state);
+
+  if (state == kStateOff) {
+    SCOPE_LOCK(locker_);
+    if (state == state_) {
+      DLOGI("Same state transition is requested.");
+      return kErrorNone;
+    }
+    error = hw_intf_->PowerOff(hw_device_);
+    if (error == kErrorNone) {
+      comp_manager_->Purge(display_comp_ctx_);
+      state_ = state;
+      hw_layers_.info.count = 0;
+    }
+  } else {
+    error = DisplayBase::SetDisplayState(state);
+  }
+
+  return error;
 }
 
 }  // namespace sde
diff --git a/displayengine/libs/core/display_primary.h b/displayengine/libs/core/display_primary.h
index 183e964..79fbddf 100644
--- a/displayengine/libs/core/display_primary.h
+++ b/displayengine/libs/core/display_primary.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -32,7 +32,8 @@
 class DisplayPrimary : public DisplayBase {
  public:
   DisplayPrimary(DisplayEventHandler *event_handler, HWInterface *hw_intf,
-                 CompManager *comp_manager);
+                 CompManager *comp_manager, OfflineCtrl *offline_ctrl);
+  virtual DisplayError SetDisplayState(DisplayState state);
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/core/display_virtual.cpp b/displayengine/libs/core/display_virtual.cpp
old mode 100755
new mode 100644
index 2fef178..84a825f
--- a/displayengine/libs/core/display_virtual.cpp
+++ b/displayengine/libs/core/display_virtual.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -32,9 +32,8 @@
 namespace sde {
 
 DisplayVirtual::DisplayVirtual(DisplayEventHandler *event_handler, HWInterface *hw_intf,
-                               CompManager *comp_manager)
-  : DisplayBase(kVirtual, event_handler, kDeviceVirtual, hw_intf, comp_manager) {
-}
+                               CompManager *comp_manager, OfflineCtrl *offline_ctrl)
+  : DisplayBase(kVirtual, event_handler, kDeviceVirtual, hw_intf, comp_manager, offline_ctrl) { }
 
 }  // namespace sde
 
diff --git a/displayengine/libs/core/display_virtual.h b/displayengine/libs/core/display_virtual.h
index a8e29e7..9697702 100644
--- a/displayengine/libs/core/display_virtual.h
+++ b/displayengine/libs/core/display_virtual.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -32,7 +32,7 @@
 class DisplayVirtual : public DisplayBase {
  public:
   DisplayVirtual(DisplayEventHandler *event_handler, HWInterface *hw_intf,
-                 CompManager *comp_manager);
+                 CompManager *comp_manager, OfflineCtrl *offline_ctrl);
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/core/hw_framebuffer.cpp b/displayengine/libs/core/hw_framebuffer.cpp
index 38320a4..4a361da 100644
--- a/displayengine/libs/core/hw_framebuffer.cpp
+++ b/displayengine/libs/core/hw_framebuffer.cpp
@@ -1,25 +1,30 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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.
+* 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.
+* 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.
 */
 
 #define __STDC_FORMAT_MACROS
@@ -39,9 +44,10 @@
 
 #include "hw_framebuffer.h"
 
+
 #define __CLASS__ "HWFrameBuffer"
 
-#define IOCTL_LOGE(ioctl, type) DLOGE("ioctl %s, display = %d errno = %d, desc = %s", #ioctl, \
+#define IOCTL_LOGE(ioctl, type) DLOGE("ioctl %s, device = %d errno = %d, desc = %s", #ioctl, \
                                       type, errno, strerror(errno))
 
 #ifdef DISPLAY_CORE_VIRTUAL_DRIVER
@@ -50,30 +56,29 @@
 extern int virtual_close(int fd);
 extern int virtual_poll(struct pollfd *fds,  nfds_t num, int timeout);
 extern ssize_t virtual_pread(int fd, void *data, size_t count, off_t offset);
+extern ssize_t virtual_pwrite(int fd, const void *data, size_t count, off_t offset);
 extern FILE* virtual_fopen(const char *fname, const char *mode);
 extern int virtual_fclose(FILE* fileptr);
 extern ssize_t virtual_getline(char **lineptr, size_t *linelen, FILE *stream);
-extern ssize_t virtual_read(int fd, void *buf, size_t count);
-extern ssize_t virtual_write(int fd, const void *buf, size_t count);
 
 #endif
 
 namespace sde {
 
-HWFrameBuffer::HWFrameBuffer() : event_thread_name_("SDE_EventThread"), fake_vsync_(false),
-                                 exit_threads_(false), fb_path_("/sys/devices/virtual/graphics/fb"),
-                                 hotplug_enabled_(false) {
+HWFrameBuffer::HWFrameBuffer(BufferSyncHandler *buffer_sync_handler)
+  : event_thread_name_("SDE_EventThread"), fake_vsync_(false), exit_threads_(false),
+    fb_path_("/sys/devices/virtual/graphics/fb"), hotplug_enabled_(false),
+    buffer_sync_handler_(buffer_sync_handler) {
   // Pointer to actual driver interfaces.
   ioctl_ = ::ioctl;
   open_ = ::open;
   close_ = ::close;
   poll_ = ::poll;
   pread_ = ::pread;
+  pwrite_ = ::pwrite;
   fopen_ = ::fopen;
   fclose_ = ::fclose;
   getline_ = ::getline;
-  read_ = ::read;
-  write_ = ::write;
 
 #ifdef DISPLAY_CORE_VIRTUAL_DRIVER
   // If debug property to use virtual driver is set, point to virtual driver interfaces.
@@ -83,11 +88,10 @@
     close_ = virtual_close;
     poll_ = virtual_poll;
     pread_ = virtual_pread;
+    pwrite_ = virtual_pwrite;
     fopen_ = virtual_fopen;
     fclose_ = virtual_fclose;
     getline_ = virtual_getline;
-    read_ = virtual_read;
-    write_ = virtual_write;
   }
 #endif
   for (int i = 0; i < kDeviceMax; i++) {
@@ -99,7 +103,7 @@
   DisplayError error = kErrorNone;
   char node_path[kMaxStringLength] = {0};
   char data[kMaxStringLength] = {0};
-  const char* event_name[kNumDisplayEvents] = {"vsync_event", "show_blank_event"};
+  const char* event_name[kNumDisplayEvents] = {"vsync_event", "show_blank_event", "idle_notify"};
 
   // Read the fb node index
   PopulateFBNodeIndex();
@@ -129,6 +133,11 @@
       for (int event = 0; event < kNumDisplayEvents; event++) {
         pollfd &poll_fd = poll_fds_[display][event];
 
+        if ((primary_panel_info_.type == kCommandModePanel) && (display == kDevicePrimary) &&
+            (!strncmp(event_name[event], "idle_notify", strlen("idle_notify")))) {
+          continue;
+        }
+
         snprintf(node_path, sizeof(node_path), "%s%d/%s", fb_path_, fb_node_index_[display],
                  event_name[event]);
 
@@ -163,6 +172,10 @@
     goto CleanupOnError;
   }
 
+  // Disable HPD at start if HDMI is external, it will be enabled later when the display powers on
+  // This helps for framework reboot or adb shell stop/start
+  EnableHotPlugDetection(0);
+
   return kErrorNone;
 
 CleanupOnError:
@@ -188,7 +201,7 @@
 
   for (int display = 0; display < kNumPhysicalDisplays; display++) {
     for (int event = 0; event < kNumDisplayEvents; event++) {
-      close(poll_fds_[display][event].fd);
+      close_(poll_fds_[display][event].fd);
     }
   }
   if (supported_video_modes_) {
@@ -223,16 +236,20 @@
   case kDeviceVirtual:
     snprintf(device_name, sizeof(device_name), "%s%d", "/dev/graphics/fb", fb_node_index_[type]);
     break;
+  case kDeviceRotator:
+    snprintf(device_name, sizeof(device_name), "%s", "/dev/mdss_rotator");
+    break;
   default:
     break;
   }
 
   hw_context->device_fd = open_(device_name, O_RDWR);
   if (hw_context->device_fd < 0) {
-    DLOGE("open %s failed.", device_name);
-    error = kErrorResources;
+    DLOGE("open %s failed err = %d errstr = %s", device_name, errno,  strerror(errno));
     delete hw_context;
+    return kErrorResources;
   }
+
   hw_context->type = type;
 
   *device = hw_context;
@@ -245,6 +262,7 @@
 
   switch (hw_context->type) {
   case kDevicePrimary:
+  case kDeviceVirtual:
     break;
   case kDeviceHDMI:
     hdmi_mode_count_ = 0;
@@ -266,6 +284,7 @@
 
   switch (hw_context->type) {
   case kDevicePrimary:
+  case kDeviceVirtual:
     *count = 1;
     break;
   case kDeviceHDMI:
@@ -284,6 +303,8 @@
 DisplayError HWFrameBuffer::GetDisplayAttributes(Handle device,
                                                  HWDisplayAttributes *display_attributes,
                                                  uint32_t index) {
+  DTRACE_SCOPED();
+
   HWContext *hw_context = reinterpret_cast<HWContext *>(device);
   int &device_fd = hw_context->device_fd;
   // Variable screen info
@@ -292,7 +313,7 @@
   switch (hw_context->type) {
   case kDevicePrimary:
     {
-      if (ioctl_(device_fd, FBIOGET_VSCREENINFO, &var_screeninfo) == -1) {
+      if (ioctl_(device_fd, FBIOGET_VSCREENINFO, &var_screeninfo) < 0) {
         IOCTL_LOGE(FBIOGET_VSCREENINFO, hw_context->type);
         return kErrorHardware;
       }
@@ -300,7 +321,7 @@
       // Frame rate
       STRUCT_VAR(msmfb_metadata, meta_data);
       meta_data.op = metadata_op_frame_rate;
-      if (ioctl_(device_fd, MSMFB_METADATA_GET, &meta_data) == -1) {
+      if (ioctl_(device_fd, MSMFB_METADATA_GET, &meta_data) < 0) {
         IOCTL_LOGE(MSMFB_METADATA_GET, hw_context->type);
         return kErrorHardware;
       }
@@ -355,6 +376,9 @@
     }
     break;
 
+  case kDeviceVirtual:
+    break;
+
   default:
     return kErrorParameters;
   }
@@ -363,18 +387,21 @@
 }
 
 DisplayError HWFrameBuffer::SetDisplayAttributes(Handle device, uint32_t index) {
+  DTRACE_SCOPED();
+
   HWContext *hw_context = reinterpret_cast<HWContext *>(device);
   DisplayError error = kErrorNone;
 
   switch (hw_context->type) {
   case kDevicePrimary:
+  case kDeviceVirtual:
     break;
 
   case kDeviceHDMI:
     {
       // Variable screen info
       STRUCT_VAR(fb_var_screeninfo, vscreeninfo);
-      if (ioctl_(hw_context->device_fd, FBIOGET_VSCREENINFO, &vscreeninfo) == -1) {
+      if (ioctl_(hw_context->device_fd, FBIOGET_VSCREENINFO, &vscreeninfo) < 0) {
         IOCTL_LOGE(FBIOGET_VSCREENINFO, hw_context->type);
         return kErrorHardware;
       }
@@ -392,24 +419,26 @@
           break;
         }
       }
+
       if (MapHDMIDisplayTiming(timing_mode, &vscreeninfo) == false) {
         return kErrorParameters;
       }
+
       STRUCT_VAR(msmfb_metadata, metadata);
-      memset(&metadata, 0 , sizeof(metadata));
       metadata.op = metadata_op_vic;
       metadata.data.video_info_code = timing_mode->video_format;
-      if (ioctl(hw_context->device_fd, MSMFB_METADATA_SET, &metadata) == -1) {
+      if (ioctl(hw_context->device_fd, MSMFB_METADATA_SET, &metadata) < 0) {
         IOCTL_LOGE(MSMFB_METADATA_SET, hw_context->type);
         return kErrorHardware;
       }
+
       DLOGI("SetInfo<Mode=%d %dx%d (%d,%d,%d),(%d,%d,%d) %dMHz>", vscreeninfo.reserved[3] & 0xFF00,
             vscreeninfo.xres, vscreeninfo.yres, vscreeninfo.right_margin, vscreeninfo.hsync_len,
             vscreeninfo.left_margin, vscreeninfo.lower_margin, vscreeninfo.vsync_len,
             vscreeninfo.upper_margin, vscreeninfo.pixclock/1000000);
 
       vscreeninfo.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_ALL | FB_ACTIVATE_FORCE;
-      if (ioctl_(hw_context->device_fd, FBIOPUT_VSCREENINFO, &vscreeninfo) == -1) {
+      if (ioctl_(hw_context->device_fd, FBIOPUT_VSCREENINFO, &vscreeninfo) < 0) {
         IOCTL_LOGE(FBIOGET_VSCREENINFO, hw_context->type);
         return kErrorHardware;
       }
@@ -451,9 +480,11 @@
 
 
 DisplayError HWFrameBuffer::PowerOn(Handle device) {
+  DTRACE_SCOPED();
+
   HWContext *hw_context = reinterpret_cast<HWContext *>(device);
 
-  if (ioctl_(hw_context->device_fd, FBIOBLANK, FB_BLANK_UNBLANK) == -1) {
+  if (ioctl_(hw_context->device_fd, FBIOBLANK, FB_BLANK_UNBLANK) < 0) {
     IOCTL_LOGE(FB_BLANK_UNBLANK, hw_context->type);
     return kErrorHardware;
   }
@@ -467,28 +498,18 @@
 }
 
 DisplayError HWFrameBuffer::PowerOff(Handle device) {
+  DTRACE_SCOPED();
+
   HWContext *hw_context = reinterpret_cast<HWContext *>(device);
+  HWDisplay *hw_display = &hw_context->hw_display;
 
   switch (hw_context->type) {
   case kDevicePrimary:
-    if (ioctl_(hw_context->device_fd, FBIOBLANK, FB_BLANK_POWERDOWN) == -1) {
+    if (ioctl_(hw_context->device_fd, FBIOBLANK, FB_BLANK_POWERDOWN) < 0) {
       IOCTL_LOGE(FB_BLANK_POWERDOWN, hw_context->type);
       return kErrorHardware;
     }
     break;
-  case kDeviceHDMI:
-    {
-      hw_context->ResetMDPCommit();
-      mdp_layer_commit_v1 &mdp_commit = hw_context->mdp_commit.commit_v1;
-      mdp_commit.input_layer_cnt = 0;
-      mdp_commit.flags &= ~MDP_VALIDATE_LAYER;
-      if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_context->mdp_commit) == -1) {
-        IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, hw_context->type);
-        return kErrorHardware;
-      }
-    }
-    break;
-  case kDeviceVirtual:
   default:
     break;
   }
@@ -509,9 +530,11 @@
 }
 
 DisplayError HWFrameBuffer::SetVSyncState(Handle device, bool enable) {
+  DTRACE_SCOPED();
+
   HWContext *hw_context = reinterpret_cast<HWContext *>(device);
   int vsync_on = enable ? 1 : 0;
-  if (ioctl_(hw_context->device_fd, MSMFB_OVERLAY_VSYNC_CTRL, &vsync_on) == -1) {
+  if (ioctl_(hw_context->device_fd, MSMFB_OVERLAY_VSYNC_CTRL, &vsync_on) < 0) {
     IOCTL_LOGE(MSMFB_OVERLAY_VSYNC_CTRL, hw_context->type);
     return kErrorHardware;
   }
@@ -519,65 +542,243 @@
   return kErrorNone;
 }
 
-DisplayError HWFrameBuffer::Validate(Handle device, HWLayers *hw_layers) {
-  DisplayError error = kErrorNone;
+DisplayError HWFrameBuffer::OpenRotatorSession(Handle device, HWLayers *hw_layers) {
+  HWContext *hw_context = reinterpret_cast<HWContext *>(device);
+  HWRotator *hw_rotator = &hw_context->hw_rotator;
+
+  hw_rotator->Reset();
+
+  HWLayersInfo &hw_layer_info = hw_layers->info;
+
+  for (uint32_t i = 0; i < hw_layer_info.count; i++) {
+    Layer& layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
+    LayerBuffer *input_buffer = layer.input_buffer;
+    bool rot90 = (layer.transform.rotation == 90.0f);
+
+    for (uint32_t count = 0; count < 2; count++) {
+      HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
+
+      if (rotate_info->valid) {
+        HWBufferInfo *rot_buf_info = &rotate_info->hw_buffer_info;
+
+        if (rot_buf_info->session_id < 0) {
+          STRUCT_VAR(mdp_rotation_config, mdp_rot_config);
+          mdp_rot_config.version = MDP_ROTATION_REQUEST_VERSION_1_0;
+          mdp_rot_config.input.width = input_buffer->width;
+          mdp_rot_config.input.height = input_buffer->height;
+          SetFormat(input_buffer->format, &mdp_rot_config.input.format);
+          mdp_rot_config.output.width = rot_buf_info->output_buffer.width;
+          mdp_rot_config.output.height = rot_buf_info->output_buffer.height;
+          SetFormat(rot_buf_info->output_buffer.format, &mdp_rot_config.output.format);
+          mdp_rot_config.frame_rate = layer.frame_rate;
+
+          if (ioctl_(hw_context->device_fd, MDSS_ROTATION_OPEN, &mdp_rot_config) < 0) {
+            IOCTL_LOGE(MDSS_ROTATION_OPEN, hw_context->type);
+            return kErrorHardware;
+          }
+
+          rot_buf_info->session_id = mdp_rot_config.session_id;
+
+          DLOGV_IF(kTagDriverConfig, "session_id %d", rot_buf_info->session_id);
+        }
+      }
+    }
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWFrameBuffer::CloseRotatorSession(Handle device, int32_t session_id) {
   HWContext *hw_context = reinterpret_cast<HWContext *>(device);
 
-  hw_context->ResetMDPCommit();
+  if (ioctl_(hw_context->device_fd, MDSS_ROTATION_CLOSE, (uint32_t)session_id) < 0) {
+    IOCTL_LOGE(MDSS_ROTATION_CLOSE, hw_context->type);
+    return kErrorHardware;
+  }
+
+  DLOGV_IF(kTagDriverConfig, "session_id %d", session_id);
+
+  return kErrorNone;
+}
+
+DisplayError HWFrameBuffer::Validate(Handle device, HWLayers *hw_layers) {
+  DTRACE_SCOPED();
+
+  DisplayError error = kErrorNone;
+
+  HWContext *hw_context = reinterpret_cast<HWContext *>(device);
+  switch (hw_context->type) {
+    case kDevicePrimary:
+    case kDeviceHDMI:
+    case kDeviceVirtual:
+      error = DisplayValidate(hw_context, hw_layers);
+      if (error != kErrorNone) {
+        return error;
+      }
+      break;
+    case kDeviceRotator:
+      error = RotatorValidate(hw_context, hw_layers);
+      if (error != kErrorNone) {
+        return error;
+      }
+      break;
+    default:
+      break;
+  }
+  return error;
+}
+
+DisplayError HWFrameBuffer::Commit(Handle device, HWLayers *hw_layers) {
+  DisplayError error = kErrorNone;
+
+  HWContext *hw_context = reinterpret_cast<HWContext *>(device);
+  switch (hw_context->type) {
+    case kDevicePrimary:
+    case kDeviceHDMI:
+    case kDeviceVirtual:
+      error = DisplayCommit(hw_context, hw_layers);
+      if (error != kErrorNone) {
+        return error;
+      }
+      break;
+    case kDeviceRotator:
+      error = RotatorCommit(hw_context, hw_layers);
+      if (error != kErrorNone) {
+        return error;
+      }
+      break;
+    default:
+      break;
+  }
+  return error;
+}
+
+DisplayError HWFrameBuffer::DisplayValidate(HWContext *hw_context, HWLayers *hw_layers) {
+  DisplayError error = kErrorNone;
+  HWDisplay *hw_display = &hw_context->hw_display;
+
+  hw_display->Reset();
 
   HWLayersInfo &hw_layer_info = hw_layers->info;
   LayerStack *stack = hw_layer_info.stack;
 
-  mdp_layer_commit_v1 &mdp_commit = hw_context->mdp_commit.commit_v1;
-  mdp_input_layer *mdp_layers = hw_context->mdp_layers;
+  DLOGV_IF(kTagDriverConfig, "************************** %s Validate Input ***********************",
+           GetDeviceString(hw_context->type));
+  DLOGV_IF(kTagDriverConfig, "SDE layer count is %d", hw_layer_info.count);
+
+  mdp_layer_commit_v1 &mdp_commit = hw_display->mdp_disp_commit.commit_v1;
+  mdp_input_layer *mdp_layers = hw_display->mdp_in_layers;
+  mdp_output_layer *mdp_out_layer = &hw_display->mdp_out_layer;
   uint32_t &mdp_layer_count = mdp_commit.input_layer_cnt;
 
   for (uint32_t i = 0; i < hw_layer_info.count; i++) {
     uint32_t layer_index = hw_layer_info.index[i];
     Layer &layer = stack->layers[layer_index];
     LayerBuffer *input_buffer = layer.input_buffer;
-    HWLayerConfig &config = hw_layers->config[i];
+    HWPipeInfo *left_pipe = &hw_layers->config[i].left_pipe;
+    HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe;
+    mdp_input_layer mdp_layer;
 
-    uint32_t split_count = hw_layers->config[i].is_right_pipe ? 2 : 1;
-    for (uint32_t j = 0; j < split_count; j++) {
-      HWPipeInfo &pipe = (j == 0) ? config.left_pipe : config.right_pipe;
-      mdp_input_layer &mdp_layer = mdp_layers[mdp_layer_count];
-      mdp_layer.alpha = layer.plane_alpha;
-      mdp_layer.z_order = static_cast<uint16_t>(i);
-      mdp_layer.transp_mask = 0xffffffff;
-      mdp_layer.horz_deci = pipe.horizontal_decimation;
-      mdp_layer.vert_deci = pipe.vertical_decimation;
+    for (uint32_t count = 0; count < 2; count++) {
+      HWPipeInfo *pipe_info = (count == 0) ? left_pipe : right_pipe;
+      HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
 
-      SetBlending(layer.blending, &mdp_layer.blend_op);
-
-      SetRect(pipe.src_roi, &mdp_layer.src_rect);
-      SetRect(pipe.dst_roi, &mdp_layer.dst_rect);
-
-      mdp_layer.pipe_ndx = pipe.pipe_id;
-
-      mdp_layer_buffer &mdp_buffer_left = mdp_layer.buffer;
-      mdp_buffer_left.width = input_buffer->width;
-      mdp_buffer_left.height = input_buffer->height;
-
-      error = SetFormat(layer.input_buffer->format, &mdp_buffer_left.format);
-      if (error != kErrorNone) {
-        return error;
+      if (rotate_info->valid) {
+        input_buffer = &rotate_info->hw_buffer_info.output_buffer;
       }
 
-      if (layer.transform.flip_vertical) {
-        mdp_layer.flags |= MDP_LAYER_FLIP_UD;
-      }
+      if (pipe_info->valid) {
+        mdp_input_layer &mdp_layer = mdp_layers[mdp_layer_count];
+        mdp_layer_buffer &mdp_buffer = mdp_layer.buffer;
 
-      if (layer.transform.flip_horizontal) {
-        mdp_layer.flags |= MDP_LAYER_FLIP_LR;
-      }
+        mdp_buffer.width = input_buffer->width;
+        mdp_buffer.height = input_buffer->height;
 
-      mdp_layer_count++;
+        error = SetFormat(input_buffer->format, &mdp_buffer.format);
+        if (error != kErrorNone) {
+          return error;
+        }
+
+        mdp_layer.alpha = layer.plane_alpha;
+        mdp_layer.z_order = static_cast<uint16_t>(i);
+        mdp_layer.transp_mask = 0xffffffff;
+        SetBlending(layer.blending, &mdp_layer.blend_op);
+        mdp_layer.pipe_ndx = pipe_info->pipe_id;
+        mdp_layer.horz_deci = pipe_info->horizontal_decimation;
+        mdp_layer.vert_deci = pipe_info->vertical_decimation;
+
+        SetRect(pipe_info->src_roi, &mdp_layer.src_rect);
+        SetRect(pipe_info->dst_roi, &mdp_layer.dst_rect);
+
+        // Flips will be taken care by rotator, if layer requires 90 rotation. So Dont use MDP for
+        // flip operation, if layer transform is 90.
+        if (!layer.transform.rotation) {
+          if (layer.transform.flip_vertical) {
+            mdp_layer.flags |= MDP_LAYER_FLIP_UD;
+          }
+
+          if (layer.transform.flip_horizontal) {
+            mdp_layer.flags |= MDP_LAYER_FLIP_LR;
+          }
+        }
+
+        if (pipe_info->scale_data.enable_pxl_ext) {
+          if ((mdp_layer.flags & MDP_LAYER_DEINTERLACE) && (layer.transform.rotation == 90.0f))
+            mdp_buffer.width = pipe_info->scale_data.src_width;
+          hw_display->SetScaleData(pipe_info->scale_data, mdp_layer_count);
+        }
+
+        // Send scale data to MDP driver
+        mdp_layer.scale = hw_display->GetScaleRef(mdp_layer_count);
+        mdp_layer_count++;
+
+        DLOGV_IF(kTagDriverConfig, "******************* Layer[%d] %s pipe Input ******************",
+                 i, count ? "Right" : "Left");
+        DLOGV_IF(kTagDriverConfig, "in_w %d, in_h %d, in_f %d", mdp_buffer.width, mdp_buffer.height,
+                 mdp_buffer.format);
+        DLOGV_IF(kTagDriverConfig, "plane_alpha %d, zorder %d, blending %d, horz_deci %d, "
+                 "vert_deci %d", mdp_layer.alpha, mdp_layer.z_order, mdp_layer.blend_op,
+                 mdp_layer.horz_deci, mdp_layer.vert_deci);
+        DLOGV_IF(kTagDriverConfig, "src_rect [%d, %d, %d, %d]", mdp_layer.src_rect.x,
+                 mdp_layer.src_rect.y, mdp_layer.src_rect.w, mdp_layer.src_rect.h);
+        DLOGV_IF(kTagDriverConfig, "dst_rect [%d, %d, %d, %d]", mdp_layer.dst_rect.x,
+                 mdp_layer.dst_rect.y, mdp_layer.dst_rect.w, mdp_layer.dst_rect.h);
+        for (int j = 0; j < MAX_PLANES; j++) {
+          DLOGV_IF(kTagDriverConfig, "Scale Data[%d]: Phase=[%x %x %x %x] Pixel_Ext=[%d %d %d %d]",
+                 j, mdp_layer.scale->init_phase_x[j], mdp_layer.scale->phase_step_x[j],
+                 mdp_layer.scale->init_phase_y[j], mdp_layer.scale->phase_step_y[j],
+                 mdp_layer.scale->num_ext_pxls_left[j], mdp_layer.scale->num_ext_pxls_top[j],
+                 mdp_layer.scale->num_ext_pxls_right[j], mdp_layer.scale->num_ext_pxls_btm[j]);
+          DLOGV_IF(kTagDriverConfig, "Fetch=[%d %d %d %d]  Repeat=[%d %d %d %d]  roi_width = %d",
+                 mdp_layer.scale->left_ftch[j], mdp_layer.scale->top_ftch[j],
+                 mdp_layer.scale->right_ftch[j], mdp_layer.scale->btm_ftch[j],
+                 mdp_layer.scale->left_rpt[j], mdp_layer.scale->top_rpt[j],
+                 mdp_layer.scale->right_rpt[j], mdp_layer.scale->btm_rpt[j],
+                 mdp_layer.scale->roi_w[j]);
+        }
+        DLOGV_IF(kTagDriverConfig, "*************************************************************");
+      }
     }
   }
 
+  if (hw_context->type == kDeviceVirtual) {
+    LayerBuffer *output_buffer = hw_layers->info.stack->output_buffer;
+    // TODO(user): Need to assign the writeback id from the resource manager, since the support
+    // has not been added hard coding it to 2 for now.
+    mdp_out_layer->writeback_ndx = 2;
+    mdp_out_layer->buffer.width = output_buffer->width;
+    mdp_out_layer->buffer.height = output_buffer->height;
+    SetFormat(output_buffer->format, &mdp_out_layer->buffer.format);
+
+    DLOGI_IF(kTagDriverConfig, "******************* Output buffer Info **********************");
+    DLOGI_IF(kTagDriverConfig, "out_w %d, out_h %d, out_f %d, wb_id %d",
+             mdp_out_layer->buffer.width, mdp_out_layer->buffer.height,
+             mdp_out_layer->buffer.format, mdp_out_layer->writeback_ndx);
+    DLOGI_IF(kTagDriverConfig, "*************************************************************");
+  }
+
   mdp_commit.flags |= MDP_VALIDATE_LAYER;
-  if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_context->mdp_commit) == -1) {
+  if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_display->mdp_disp_commit) < 0) {
     IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, hw_context->type);
     return kErrorHardware;
   }
@@ -585,55 +786,308 @@
   return kErrorNone;
 }
 
-DisplayError HWFrameBuffer::Commit(Handle device, HWLayers *hw_layers) {
-  HWContext *hw_context = reinterpret_cast<HWContext *>(device);
+DisplayError HWFrameBuffer::DisplayCommit(HWContext *hw_context, HWLayers *hw_layers) {
+  DTRACE_SCOPED();
+
+  HWDisplay *hw_display = &hw_context->hw_display;
   HWLayersInfo &hw_layer_info = hw_layers->info;
   LayerStack *stack = hw_layer_info.stack;
 
-  mdp_layer_commit_v1 &mdp_commit = hw_context->mdp_commit.commit_v1;
-  mdp_input_layer *mdp_layers = hw_context->mdp_layers;
+  DLOGV_IF(kTagDriverConfig, "*************************** %s Commit Input ************************",
+           GetDeviceString(hw_context->type));
+  DLOGV_IF(kTagDriverConfig, "SDE layer count is %d", hw_layer_info.count);
+
+  mdp_layer_commit_v1 &mdp_commit = hw_display->mdp_disp_commit.commit_v1;
+  mdp_input_layer *mdp_layers = hw_display->mdp_in_layers;
+  mdp_output_layer *mdp_out_layer = &hw_display->mdp_out_layer;
   uint32_t mdp_layer_index = 0;
 
   for (uint32_t i = 0; i < hw_layer_info.count; i++) {
     uint32_t layer_index = hw_layer_info.index[i];
     LayerBuffer *input_buffer = stack->layers[layer_index].input_buffer;
+    HWPipeInfo *left_pipe = &hw_layers->config[i].left_pipe;
+    HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe;
 
-    uint32_t split_count = hw_layers->config[i].is_right_pipe ? 2 : 1;
-    for (uint32_t j = 0; j < split_count; j++) {
-      mdp_layer_buffer &mdp_buffer = mdp_layers[mdp_layer_index].buffer;
+    for (uint32_t count = 0; count < 2; count++) {
+      HWPipeInfo *pipe_info = (count == 0) ? left_pipe : right_pipe;
+      HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
 
-      if (input_buffer->planes[0].fd >= 0) {
-        mdp_buffer.plane_count = 1;
-        mdp_buffer.planes[0].fd = input_buffer->planes[0].fd;
-        mdp_buffer.planes[0].offset = input_buffer->planes[0].offset;
-        mdp_buffer.planes[0].stride = input_buffer->planes[0].stride;
-      } else {
-        DLOGW("Invalid buffer fd, setting plane count to 0");
-        mdp_buffer.plane_count = 0;
+      if (rotate_info->valid) {
+        input_buffer = &rotate_info->hw_buffer_info.output_buffer;
       }
 
-      mdp_buffer.fence = input_buffer->acquire_fence_fd;
-      mdp_layer_index++;
+      if (pipe_info->valid) {
+        mdp_layer_buffer &mdp_buffer = mdp_layers[mdp_layer_index].buffer;
+        mdp_input_layer &mdp_layer = mdp_layers[mdp_layer_index];
+        if (input_buffer->planes[0].fd >= 0) {
+          mdp_buffer.plane_count = 1;
+          mdp_buffer.planes[0].fd = input_buffer->planes[0].fd;
+          mdp_buffer.planes[0].offset = input_buffer->planes[0].offset;
+          SetStride(hw_context->type, input_buffer->format, input_buffer->planes[0].stride,
+                    &mdp_buffer.planes[0].stride);
+        } else {
+          DLOGW("Invalid buffer fd, setting plane count to 0");
+          mdp_buffer.plane_count = 0;
+        }
+
+        mdp_buffer.fence = input_buffer->acquire_fence_fd;
+        mdp_layer_index++;
+
+        DLOGV_IF(kTagDriverConfig, "****************** Layer[%d] %s pipe Input *******************",
+                 i, count ? "Right" : "Left");
+        DLOGI_IF(kTagDriverConfig, "in_w %d, in_h %d, in_f %d, horz_deci %d, vert_deci %d",
+                 mdp_buffer.width, mdp_buffer.height, mdp_buffer.format, mdp_layer.horz_deci,
+                 mdp_layer.vert_deci);
+        DLOGI_IF(kTagDriverConfig, "in_buf_fd %d, in_buf_offset %d, in_buf_stride %d, " \
+                 "in_plane_count %d, in_fence %d, layer count %d", mdp_buffer.planes[0].fd,
+                 mdp_buffer.planes[0].offset, mdp_buffer.planes[0].stride, mdp_buffer.plane_count,
+                 mdp_buffer.fence, mdp_commit.input_layer_cnt);
+        DLOGV_IF(kTagDriverConfig, "*************************************************************");
+      }
     }
   }
+  if (hw_context->type == kDeviceVirtual) {
+    LayerBuffer *output_buffer = hw_layers->info.stack->output_buffer;
 
-  mdp_commit.flags |= MDP_COMMIT_RETIRE_FENCE;
+    if (output_buffer->planes[0].fd >= 0) {
+      mdp_out_layer->buffer.planes[0].fd = output_buffer->planes[0].fd;
+      mdp_out_layer->buffer.planes[0].offset = output_buffer->planes[0].offset;
+      SetStride(hw_context->type, output_buffer->format, output_buffer->planes[0].stride,
+                &mdp_out_layer->buffer.planes[0].stride);
+      mdp_out_layer->buffer.plane_count = 1;
+    } else {
+      DLOGW("Invalid output buffer fd, setting plane count to 0");
+      mdp_out_layer->buffer.plane_count = 0;
+    }
+
+    mdp_out_layer->buffer.fence = output_buffer->acquire_fence_fd;
+
+    DLOGI_IF(kTagDriverConfig, "******************* Output buffer Info **********************");
+    DLOGI_IF(kTagDriverConfig, "out_fd %d, out_offset %d, out_stride %d, acquire_fence %d",
+             mdp_out_layer->buffer.planes[0].fd, mdp_out_layer->buffer.planes[0].offset,
+             mdp_out_layer->buffer.planes[0].stride,  mdp_out_layer->buffer.fence);
+    DLOGI_IF(kTagDriverConfig, "*************************************************************");
+  }
+
+  mdp_commit.release_fence = -1;
   mdp_commit.flags &= ~MDP_VALIDATE_LAYER;
-  if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_context->mdp_commit) == -1) {
+  if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_display->mdp_disp_commit) < 0) {
     IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, hw_context->type);
     return kErrorHardware;
   }
 
+  stack->retire_fence_fd = mdp_commit.retire_fence;
+
   // MDP returns only one release fence for the entire layer stack. Duplicate this fence into all
   // layers being composed by MDP.
-  stack->retire_fence_fd = mdp_commit.retire_fence;
   for (uint32_t i = 0; i < hw_layer_info.count; i++) {
     uint32_t layer_index = hw_layer_info.index[i];
     LayerBuffer *input_buffer = stack->layers[layer_index].input_buffer;
+    HWRotateInfo *left_rotate = &hw_layers->config[i].rotates[0];
+    HWRotateInfo *right_rotate = &hw_layers->config[i].rotates[1];
 
-    input_buffer->release_fence_fd = dup(mdp_commit.release_fence);
+    if (!left_rotate->valid && !right_rotate->valid) {
+      input_buffer->release_fence_fd = dup(mdp_commit.release_fence);
+      continue;
+    }
+
+    for (uint32_t count = 0; count < 2; count++) {
+      HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
+      if (rotate_info->valid) {
+        input_buffer = &rotate_info->hw_buffer_info.output_buffer;
+        input_buffer->release_fence_fd = dup(mdp_commit.release_fence);
+        close_(input_buffer->acquire_fence_fd);
+        input_buffer->acquire_fence_fd = -1;
+      }
+    }
   }
-  close(mdp_commit.release_fence);
+  DLOGI_IF(kTagDriverConfig, "*************************** %s Commit Input ************************",
+           GetDeviceString(hw_context->type));
+  DLOGI_IF(kTagDriverConfig, "retire_fence_fd %d", stack->retire_fence_fd);
+  DLOGI_IF(kTagDriverConfig, "*************************************************************");
+
+  close_(mdp_commit.release_fence);
+
+  return kErrorNone;
+}
+
+DisplayError HWFrameBuffer::RotatorValidate(HWContext *hw_context, HWLayers *hw_layers) {
+  HWRotator *hw_rotator = &hw_context->hw_rotator;
+  DLOGV_IF(kTagDriverConfig, "************************* %s Validate Input ************************",
+           GetDeviceString(hw_context->type));
+
+  hw_rotator->Reset();
+
+  mdp_rotation_request *mdp_rot_request = &hw_rotator->mdp_rot_req;
+  HWLayersInfo &hw_layer_info = hw_layers->info;
+
+  uint32_t &rot_count = mdp_rot_request->count;
+  for (uint32_t i = 0; i < hw_layer_info.count; i++) {
+    Layer& layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
+
+    for (uint32_t count = 0; count < 2; count++) {
+      HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
+
+      if (rotate_info->valid) {
+        HWBufferInfo *rot_buf_info = &rotate_info->hw_buffer_info;
+        mdp_rotation_item *mdp_rot_item = &mdp_rot_request->list[rot_count];
+        bool rot90 = (layer.transform.rotation == 90.0f);
+
+        if (rot90) {
+          mdp_rot_item->flags |= MDP_ROTATION_90;
+        }
+
+        if (layer.transform.flip_horizontal) {
+          mdp_rot_item->flags |= MDP_ROTATION_FLIP_LR;
+        }
+
+        if (layer.transform.flip_vertical) {
+          mdp_rot_item->flags |= MDP_ROTATION_FLIP_UD;
+        }
+
+        SetRect(rotate_info->src_roi, &mdp_rot_item->src_rect);
+        SetRect(rotate_info->dst_roi, &mdp_rot_item->dst_rect);
+
+        // TODO(user): Need to assign the writeback id and pipe id  returned from resource manager.
+        mdp_rot_item->pipe_idx = 0;
+        mdp_rot_item->wb_idx = 0;
+
+        mdp_rot_item->input.width = layer.input_buffer->width;
+        mdp_rot_item->input.height = layer.input_buffer->height;
+        SetFormat(layer.input_buffer->format, &mdp_rot_item->input.format);
+
+        mdp_rot_item->output.width = rot_buf_info->output_buffer.width;
+        mdp_rot_item->output.height = rot_buf_info->output_buffer.height;
+        SetFormat(rot_buf_info->output_buffer.format, &mdp_rot_item->output.format);
+
+        rot_count++;
+
+        DLOGV_IF(kTagDriverConfig, "******************** Layer[%d] %s rotate ********************",
+                 i, count ? "Right" : "Left");
+        DLOGV_IF(kTagDriverConfig, "in_w %d, in_h %d, in_f %d,\t out_w %d, out_h %d, out_f %d",
+                 mdp_rot_item->input.width, mdp_rot_item->input.height, mdp_rot_item->input.format,
+                 mdp_rot_item->output.width, mdp_rot_item->output.height,
+                 mdp_rot_item->output.format);
+        DLOGV_IF(kTagDriverConfig, "pipe_id %d, wb_id %d, rot_flag %d", mdp_rot_item->pipe_idx,
+                 mdp_rot_item->wb_idx, mdp_rot_item->flags);
+        DLOGV_IF(kTagDriverConfig, "src_rect [%d, %d, %d, %d]", mdp_rot_item->src_rect.x,
+                 mdp_rot_item->src_rect.y, mdp_rot_item->src_rect.w, mdp_rot_item->src_rect.h);
+        DLOGV_IF(kTagDriverConfig, "dst_rect [%d, %d, %d, %d]", mdp_rot_item->dst_rect.x,
+                 mdp_rot_item->dst_rect.y, mdp_rot_item->dst_rect.w, mdp_rot_item->dst_rect.h);
+        DLOGV_IF(kTagDriverConfig, "*************************************************************");
+      }
+    }
+  }
+
+  mdp_rot_request->flags = MDSS_ROTATION_REQUEST_VALIDATE;
+  if (ioctl_(hw_context->device_fd, MDSS_ROTATION_REQUEST, mdp_rot_request) < 0) {
+    IOCTL_LOGE(MDSS_ROTATION_REQUEST, hw_context->type);
+    return kErrorHardware;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWFrameBuffer::RotatorCommit(HWContext *hw_context, HWLayers *hw_layers) {
+  HWRotator *hw_rotator = &hw_context->hw_rotator;
+  mdp_rotation_request *mdp_rot_request = &hw_rotator->mdp_rot_req;
+  HWLayersInfo &hw_layer_info = hw_layers->info;
+  uint32_t rot_count = 0;
+
+  DLOGV_IF(kTagDriverConfig, "************************* %s Commit Input **************************",
+           GetDeviceString(hw_context->type));
+  DLOGV_IF(kTagDriverConfig, "Rotate layer count is %d", mdp_rot_request->count);
+
+  mdp_rot_request->list = hw_rotator->mdp_rot_layers;
+
+  for (uint32_t i = 0; i < hw_layer_info.count; i++) {
+    Layer& layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
+
+    for (uint32_t count = 0; count < 2; count++) {
+      HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
+
+      if (rotate_info->valid) {
+        HWBufferInfo *rot_buf_info = &rotate_info->hw_buffer_info;
+        mdp_rotation_item *mdp_rot_item = &mdp_rot_request->list[rot_count];
+
+        mdp_rot_item->input.planes[0].fd = layer.input_buffer->planes[0].fd;
+        mdp_rot_item->input.planes[0].offset = layer.input_buffer->planes[0].offset;
+        SetStride(hw_context->type, layer.input_buffer->format, layer.input_buffer->width,
+                  &mdp_rot_item->input.planes[0].stride);
+        mdp_rot_item->input.plane_count = 1;
+        mdp_rot_item->input.fence = layer.input_buffer->acquire_fence_fd;
+
+        mdp_rot_item->output.planes[0].fd = rot_buf_info->output_buffer.planes[0].fd;
+        mdp_rot_item->output.planes[0].offset = rot_buf_info->output_buffer.planes[0].offset;
+        SetStride(hw_context->type, rot_buf_info->output_buffer.format,
+                  rot_buf_info->output_buffer.planes[0].stride,
+                  &mdp_rot_item->output.planes[0].stride);
+        mdp_rot_item->output.plane_count = 1;
+        mdp_rot_item->output.fence = -1;
+
+        rot_count++;
+
+        DLOGV_IF(kTagDriverConfig, "******************** Layer[%d] %s rotate ********************",
+                 i, count ? "Right" : "Left");
+        DLOGV_IF(kTagDriverConfig, "in_buf_fd %d, in_buf_offset %d, in_stride %d, " \
+                 "in_plane_count %d, in_fence %d", mdp_rot_item->input.planes[0].fd,
+                 mdp_rot_item->input.planes[0].offset, mdp_rot_item->input.planes[0].stride,
+                 mdp_rot_item->input.plane_count, mdp_rot_item->input.fence);
+        DLOGV_IF(kTagDriverConfig, "out_fd %d, out_offset %d, out_stride %d, out_plane_count %d, " \
+                 "out_fence %d", mdp_rot_item->output.planes[0].fd,
+                 mdp_rot_item->output.planes[0].offset, mdp_rot_item->output.planes[0].stride,
+                 mdp_rot_item->output.plane_count, mdp_rot_item->output.fence);
+        DLOGV_IF(kTagDriverConfig, "*************************************************************");
+      }
+    }
+  }
+
+  mdp_rot_request->flags &= ~MDSS_ROTATION_REQUEST_VALIDATE;
+  if (ioctl_(hw_context->device_fd, MDSS_ROTATION_REQUEST, mdp_rot_request) < 0) {
+    IOCTL_LOGE(MDSS_ROTATION_REQUEST, hw_context->type);
+    return kErrorHardware;
+  }
+
+  rot_count = 0;
+  for (uint32_t i = 0; i < hw_layer_info.count; i++) {
+    Layer& layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
+
+    layer.input_buffer->release_fence_fd = -1;
+
+    for (uint32_t count = 0; count < 2; count++) {
+      HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
+
+      if (rotate_info->valid) {
+        HWBufferInfo *rot_buf_info = &rotate_info->hw_buffer_info;
+        mdp_rotation_item *mdp_rot_item = &mdp_rot_request->list[rot_count];
+
+        SyncMerge(layer.input_buffer->release_fence_fd, dup(mdp_rot_item->output.fence),
+                  &layer.input_buffer->release_fence_fd);
+
+        rot_buf_info->output_buffer.acquire_fence_fd = dup(mdp_rot_item->output.fence);
+
+        close_(mdp_rot_item->output.fence);
+        rot_count++;
+      }
+    }
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWFrameBuffer::Flush(Handle device) {
+  HWContext *hw_context = reinterpret_cast<HWContext *>(device);
+  HWDisplay *hw_display = &hw_context->hw_display;
+
+  hw_display->Reset();
+  mdp_layer_commit_v1 &mdp_commit = hw_display->mdp_disp_commit.commit_v1;
+  mdp_commit.input_layer_cnt = 0;
+  mdp_commit.flags &= ~MDP_VALIDATE_LAYER;
+
+  if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_display->mdp_disp_commit) == -1) {
+    IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, hw_context->type);
+    return kErrorHardware;
+  }
 
   return kErrorNone;
 }
@@ -653,6 +1107,9 @@
   case kFormatYCrCb420SemiPlanar:       *target = MDP_Y_CRCB_H2V2;       break;
   case kFormatYCbCr422Packed:           *target = MDP_YCBYCR_H2V1;       break;
   case kFormatYCbCr420SemiPlanarVenus:  *target = MDP_Y_CBCR_H2V2_VENUS; break;
+  case kFormatRGBA8888Ubwc:             *target = MDP_RGBA_8888_UBWC;    break;
+  case kFormatRGB565Ubwc:               *target = MDP_RGB_565_UBWC;      break;
+  case kFormatYCbCr420SPVenusUbwc:      *target = MDP_Y_CBCR_H2V2_UBWC;  break;
   default:
     DLOGE("Unsupported format type %d", source);
     return kErrorParameters;
@@ -661,6 +1118,47 @@
   return kErrorNone;
 }
 
+DisplayError HWFrameBuffer::SetStride(HWDeviceType device_type, LayerBufferFormat format,
+                                      uint32_t width, uint32_t *target) {
+  // TODO(user): This SetStride function is an workaround to satisfy the driver expectation for
+  // rotator and virtual devices. Eventually this will be taken care in the driver.
+  if (device_type != kDeviceRotator && device_type != kDeviceVirtual) {
+    *target = width;
+    return kErrorNone;
+  }
+
+  switch (format) {
+  case kFormatARGB8888:
+  case kFormatRGBA8888:
+  case kFormatBGRA8888:
+  case kFormatRGBX8888:
+  case kFormatBGRX8888:
+    *target = width * 4;
+    break;
+  case kFormatRGB888:
+    *target = width * 3;
+    break;
+  case kFormatRGB565:
+    *target = width * 3;
+    break;
+  case kFormatYCbCr420SemiPlanarVenus:
+  case kFormatYCbCr420Planar:
+  case kFormatYCrCb420Planar:
+  case kFormatYCbCr420SemiPlanar:
+  case kFormatYCrCb420SemiPlanar:
+    *target = width;
+    break;
+  case kFormatYCbCr422Packed:
+    *target = width * 2;
+    break;
+  default:
+    DLOGE("Unsupported format type %d", format);
+    return kErrorParameters;
+  }
+
+  return kErrorNone;
+}
+
 void HWFrameBuffer::SetBlending(const LayerBlending &source, mdss_mdp_blend_op *target) {
   switch (source) {
   case kBlendingPremultiplied:  *target = BLEND_OP_PREMULTIPLIED;   break;
@@ -676,6 +1174,31 @@
   target->h = UINT32(source.bottom) - target->y;
 }
 
+void HWFrameBuffer::SyncMerge(const int &fd1, const int &fd2, int *target) {
+  if (fd1 >= 0 && fd2 >= 0) {
+    buffer_sync_handler_->SyncMerge(fd1, fd2, target);
+  } else if (fd1 >= 0) {
+    *target = fd1;
+  } else if (fd2 >= 0) {
+    *target = fd2;
+  }
+}
+
+const char *HWFrameBuffer::GetDeviceString(HWDeviceType type) {
+  switch (type) {
+  case kDevicePrimary:
+    return "Primary Display Device";
+  case kDeviceHDMI:
+    return "HDMI Display Device";
+  case kDeviceVirtual:
+    return "Virtual Display Device";
+  case kDeviceRotator:
+    return "Rotator Device";
+  default:
+    return "Invalid Device";
+  }
+}
+
 void* HWFrameBuffer::DisplayEventThread(void *context) {
   if (context) {
     return reinterpret_cast<HWFrameBuffer *>(context)->DisplayEventThreadHandler();
@@ -709,9 +1232,10 @@
     pthread_exit(0);
   }
 
-  typedef void (HWFrameBuffer::*EventHandler)(int, char *);
+  typedef void (HWFrameBuffer::*EventHandler)(int, char*);
   EventHandler event_handler[kNumDisplayEvents] = { &HWFrameBuffer::HandleVSync,
-                                                    &HWFrameBuffer::HandleBlank };
+                                                    &HWFrameBuffer::HandleBlank,
+                                                    &HWFrameBuffer::HandleIdleTimeout };
 
   while (!exit_threads_) {
     int error = poll_(poll_fds_[0], kNumPhysicalDisplays * kNumDisplayEvents, -1);
@@ -756,6 +1280,10 @@
   // TODO(user): Need to send blank Event
 }
 
+void HWFrameBuffer::HandleIdleTimeout(int display_id, char *data) {
+  event_handler_[display_id]->IdleTimeout();
+}
+
 void HWFrameBuffer::PopulateFBNodeIndex() {
   char stringbuffer[kMaxStringLength];
   DisplayError error = kErrorNone;
@@ -779,16 +1307,16 @@
     // TODO(user): For now, assume primary to be cmd/video/lvds/edp mode panel only
     // Need more concrete info from driver
     if ((strncmp(line, "mipi dsi cmd panel", strlen("mipi dsi cmd panel")) == 0)) {
-      pri_panel_info_.type = kCommandModePanel;
+      primary_panel_info_.type = kCommandModePanel;
       fb_node_index_[kDevicePrimary] = i;
     } else if ((strncmp(line, "mipi dsi video panel", strlen("mipi dsi video panel")) == 0))  {
-      pri_panel_info_.type = kVideoModePanel;
+      primary_panel_info_.type = kVideoModePanel;
       fb_node_index_[kDevicePrimary] = i;
     } else if ((strncmp(line, "lvds panel", strlen("lvds panel")) == 0)) {
-      pri_panel_info_.type = kLVDSPanel;
+      primary_panel_info_.type = kLVDSPanel;
       fb_node_index_[kDevicePrimary] = i;
     } else if ((strncmp(line, "edp panel", strlen("edp panel")) == 0)) {
-      pri_panel_info_.type = kEDPPanel;
+      primary_panel_info_.type = kEDPPanel;
       fb_node_index_[kDevicePrimary] = i;
     } else if ((strncmp(line, "dtv panel", strlen("dtv panel")) == 0)) {
       fb_node_index_[kDeviceHDMI] = i;
@@ -820,27 +1348,27 @@
     char *tokens[max_count] = { NULL };
     if (!ParseLine(line, tokens, max_count, &token_count)) {
       if (!strncmp(tokens[0], "pu_en", strlen("pu_en"))) {
-        pri_panel_info_.partial_update = atoi(tokens[1]);
+        primary_panel_info_.partial_update = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "xstart", strlen("xstart"))) {
-        pri_panel_info_.left_align = atoi(tokens[1]);
+        primary_panel_info_.left_align = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "walign", strlen("walign"))) {
-        pri_panel_info_.width_align = atoi(tokens[1]);
+        primary_panel_info_.width_align = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "ystart", strlen("ystart"))) {
-        pri_panel_info_.top_align = atoi(tokens[1]);
+        primary_panel_info_.top_align = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "halign", strlen("halign"))) {
-        pri_panel_info_.height_align = atoi(tokens[1]);
+        primary_panel_info_.height_align = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "min_w", strlen("min_w"))) {
-        pri_panel_info_.min_roi_width = atoi(tokens[1]);
+        primary_panel_info_.min_roi_width = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "min_h", strlen("min_h"))) {
-        pri_panel_info_.min_roi_height = atoi(tokens[1]);
+        primary_panel_info_.min_roi_height = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "roi_merge", strlen("roi_merge"))) {
-        pri_panel_info_.needs_roi_merge = atoi(tokens[1]);
+        primary_panel_info_.needs_roi_merge = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "dynamic_fps_en", strlen("dyn_fps_en"))) {
-        pri_panel_info_.dynamic_fps = atoi(tokens[1]);
+        primary_panel_info_.dynamic_fps = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "min_fps", strlen("min_fps"))) {
-        pri_panel_info_.min_fps = atoi(tokens[1]);
+        primary_panel_info_.min_fps = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "max_fps", strlen("max_fps"))) {
-        pri_panel_info_.max_fps= atoi(tokens[1]);
+        primary_panel_info_.max_fps= atoi(tokens[1]);
       }
     }
   }
@@ -1000,7 +1528,7 @@
     return kErrorHardware;
   }
   char value = enable ? '1' : '0';
-  ssize_t length = write_(hpdfd, &value, 1);
+  ssize_t length = pwrite_(hpdfd, &value, 1, 0);
   if (length <= 0) {
     DLOGE("Write failed 'hpd' = %d", enable);
     ret_value = false;
@@ -1021,7 +1549,7 @@
     return -1;
   }
 
-  length = read_(edid_file, edid_str, sizeof(edid_str)-1);
+  length = pread_(edid_file, edid_str, sizeof(edid_str)-1, 0);
   if (length <= 0) {
     DLOGE("%s: edid_modes file empty");
     edid_str[0] = '\0';
@@ -1073,4 +1601,46 @@
   return true;
 }
 
+void HWFrameBuffer::SetIdleTimeoutMs(Handle device, uint32_t timeout_ms) {
+  char node_path[kMaxStringLength] = {0};
+  HWContext *hw_context = reinterpret_cast<HWContext *>(device);
+
+  DLOGI("idle timeout = %d ms", timeout_ms);
+
+  switch (hw_context->type) {
+  case kDevicePrimary:
+    {
+      // Idle fallback feature is supported only for video mode panel.
+      if (primary_panel_info_.type == kCommandModePanel) {
+        return;
+      }
+
+      snprintf(node_path, sizeof(node_path), "%s%d/idle_time", fb_path_,
+               fb_node_index_[hw_context->type]);
+
+      // Open a sysfs node to send the timeout value to driver.
+      int fd = open_(node_path, O_WRONLY);
+      if (fd < 0) {
+        DLOGE("Unable to open %s, node %s", node_path, strerror(errno));
+        return;
+      }
+
+      char timeout_string[64];
+      snprintf(timeout_string, sizeof(timeout_string), "%d", timeout_ms);
+
+      // Notify driver about the timeout value
+      ssize_t length = pwrite_(fd, timeout_string, strlen(timeout_string), 0);
+      if (length < -1) {
+        DLOGE("Unable to write into %s, node %s", node_path, strerror(errno));
+      }
+
+      close_(fd);
+    }
+    break;
+  default:
+    break;
+  }
+}
+
 }  // namespace sde
+
diff --git a/displayengine/libs/core/hw_framebuffer.h b/displayengine/libs/core/hw_framebuffer.h
index 2fe5078..5c01e5f 100644
--- a/displayengine/libs/core/hw_framebuffer.h
+++ b/displayengine/libs/core/hw_framebuffer.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -30,7 +30,7 @@
 #include <stdlib.h>
 #include <linux/msm_mdp_ext.h>
 #include <video/msm_hdmi_modes.h>
-
+#include <linux/mdss_rotator.h>
 #include <poll.h>
 #include <pthread.h>
 
@@ -40,7 +40,7 @@
 
 class HWFrameBuffer : public HWInterface {
  public:
-  HWFrameBuffer();
+  explicit HWFrameBuffer(BufferSyncHandler *buffer_sync_handler);
   DisplayError Init();
   DisplayError Deinit();
   virtual DisplayError GetHWCapabilities(HWResourceInfo *hw_res_info);
@@ -56,26 +56,97 @@
   virtual DisplayError Doze(Handle device);
   virtual DisplayError SetVSyncState(Handle device, bool enable);
   virtual DisplayError Standby(Handle device);
+  virtual DisplayError OpenRotatorSession(Handle device, HWLayers *hw_layers);
+  virtual DisplayError CloseRotatorSession(Handle device, int32_t session_id);
   virtual DisplayError Validate(Handle device, HWLayers *hw_layers);
   virtual DisplayError Commit(Handle device, HWLayers *hw_layers);
+  virtual DisplayError Flush(Handle device);
+  virtual void SetIdleTimeoutMs(Handle device, uint32_t timeout_ms);
 
  private:
+  struct HWDisplay {
+    mdp_layer_commit mdp_disp_commit;
+    mdp_input_layer mdp_in_layers[kMaxSDELayers * 2];   // split panel (left + right)
+    mdp_scale_data scale_data[kMaxSDELayers * 2];
+    mdp_output_layer mdp_out_layer;
+
+    HWDisplay() { Reset(); }
+
+    void Reset() {
+      memset(&mdp_disp_commit, 0, sizeof(mdp_disp_commit));
+      memset(&mdp_in_layers, 0, sizeof(mdp_in_layers));
+      memset(&mdp_out_layer, 0, sizeof(mdp_out_layer));
+      memset(&scale_data, 0, sizeof(scale_data));
+
+      for (uint32_t i = 0; i < kMaxSDELayers * 2; i++) {
+        mdp_in_layers[i].buffer.fence = -1;
+      }
+
+      mdp_disp_commit.version = MDP_COMMIT_VERSION_1_0;
+      mdp_disp_commit.commit_v1.input_layers = mdp_in_layers;
+      mdp_disp_commit.commit_v1.output_layer = &mdp_out_layer;
+      mdp_disp_commit.commit_v1.release_fence = -1;
+    }
+
+    mdp_scale_data* GetScaleRef(uint32_t index) { return &scale_data[index]; }
+
+    void SetScaleData(scalar::Scale scale, uint32_t index) {
+      mdp_scale_data *mdp_scale = &scale_data[index];
+      mdp_scale->enable_pxl_ext = scale.enable_pxl_ext;
+
+      for (int i = 0; i < MAX_PLANES; i++) {
+        mdp_scale->init_phase_x[i] = scale.init_phase_x[i];
+        mdp_scale->phase_step_x[i] = scale.phase_step_x[i];
+        mdp_scale->init_phase_y[i] = scale.init_phase_y[i];
+        mdp_scale->phase_step_y[i] = scale.phase_step_y[i];
+
+        mdp_scale->num_ext_pxls_left[i] = scale.left.extension[i];
+        mdp_scale->num_ext_pxls_top[i] = scale.top.extension[i];
+        mdp_scale->num_ext_pxls_right[i] = scale.right.extension[i];
+        mdp_scale->num_ext_pxls_btm[i] = scale.bottom.extension[i];
+
+        mdp_scale->left_ftch[i] = scale.left.overfetch[i];
+        mdp_scale->top_ftch[i] = scale.top.overfetch[i];
+        mdp_scale->right_ftch[i] = scale.right.overfetch[i];
+        mdp_scale->btm_ftch[i] = scale.bottom.overfetch[i];
+
+        mdp_scale->left_rpt[i] = scale.left.repeat[i];
+        mdp_scale->top_rpt[i] = scale.top.repeat[i];
+        mdp_scale->right_rpt[i] = scale.right.repeat[i];
+        mdp_scale->btm_rpt[i] = scale.bottom.repeat[i];
+
+        mdp_scale->roi_w[i] = scale.roi_width[i];
+      }
+    }
+  };
+
+  struct HWRotator {
+    struct mdp_rotation_request mdp_rot_req;
+    struct mdp_rotation_item mdp_rot_layers[kMaxSDELayers * 2];  // split panel (left + right)
+
+    HWRotator() { Reset(); }
+
+    void Reset() {
+      memset(&mdp_rot_req, 0, sizeof(mdp_rot_req));
+      memset(&mdp_rot_layers, 0, sizeof(mdp_rot_layers));
+
+      for (uint32_t i = 0; i < kMaxSDELayers * 2; i++) {
+        mdp_rot_layers[i].input.fence = -1;
+        mdp_rot_layers[i].output.fence = -1;
+      }
+
+      mdp_rot_req.version = MDP_ROTATION_REQUEST_VERSION_1_0;
+      mdp_rot_req.list = mdp_rot_layers;
+    }
+  };
+
   struct HWContext {
     HWDeviceType type;
     int device_fd;
-    mdp_layer_commit mdp_commit;
-    mdp_input_layer mdp_layers[kMaxSDELayers * 2];   // split panel (left + right) for worst case
+    HWRotator hw_rotator;
+    HWDisplay hw_display;
 
-    HWContext() : type(kDeviceMax), device_fd(-1) {
-      ResetMDPCommit();
-    }
-
-    void ResetMDPCommit() {
-      memset(&mdp_commit, 0, sizeof(mdp_commit));
-      memset(&mdp_layers, 0, sizeof(mdp_layers));
-      mdp_commit.version = MDP_COMMIT_VERSION_1_0;
-      mdp_commit.commit_v1.input_layers = mdp_layers;
-    }
+    HWContext() : type(kDeviceMax), device_fd(-1) { }
   };
 
   enum PanelType {
@@ -115,12 +186,23 @@
 
   static const int kMaxStringLength = 1024;
   static const int kNumPhysicalDisplays = 2;
-  static const int kNumDisplayEvents = 2;
+  static const int kNumDisplayEvents = 3;
   static const int kHWMdssVersion5 = 500;  // MDSS_V5
 
+  DisplayError DisplayValidate(HWContext *device_ctx, HWLayers *hw_layers);
+  DisplayError DisplayCommit(HWContext *device_ctx, HWLayers *hw_layers);
+
+  DisplayError RotatorValidate(HWContext *device_ctx, HWLayers *hw_layers);
+  DisplayError RotatorCommit(HWContext *device_ctx, HWLayers *hw_layers);
+
   inline DisplayError SetFormat(const LayerBufferFormat &source, uint32_t *target);
+  inline DisplayError SetStride(HWDeviceType device_type, LayerBufferFormat format,
+                                uint32_t width, uint32_t *target);
   inline void SetBlending(const LayerBlending &source, mdss_mdp_blend_op *target);
   inline void SetRect(const LayerRect &source, mdp_rect *target);
+  inline void SyncMerge(const int &fd1, const int &fd2, int *target);
+
+  inline const char *GetDeviceString(HWDeviceType type);
 
   // Event Thread to receive vsync/blank events
   static void* DisplayEventThread(void *context);
@@ -128,6 +210,7 @@
 
   void HandleVSync(int display_id, char *data);
   void HandleBlank(int display_id, char *data);
+  void HandleIdleTimeout(int display_id, char *data);
 
   // Populates HW FrameBuffer Node Index
   void PopulateFBNodeIndex();
@@ -141,7 +224,6 @@
   bool EnableHotPlugDetection(int enable);
   int GetHDMIModeCount();
   bool MapHDMIDisplayTiming(const msm_hdmi_mode_timing_info *mode, fb_var_screeninfo *info);
-  void ResetHDMIModes();
 
   // Pointers to system calls which are either mapped to actual system call or virtual driver.
   int (*ioctl_)(int, int, ...);
@@ -149,12 +231,10 @@
   int (*close_)(int);
   int (*poll_)(struct pollfd *, nfds_t, int);
   ssize_t (*pread_)(int, void *, size_t, off_t);
+  ssize_t (*pwrite_)(int, const void *, size_t, off_t);
   FILE* (*fopen_)( const char *fname, const char *mode);
   int (*fclose_)(FILE* fileptr);
   ssize_t (*getline_)(char **lineptr, size_t *linelen, FILE *stream);
-  ssize_t (*read_)(int fd, void *buf, size_t count);
-  ssize_t (*write_)(int fd, const void *buf, size_t count);
-
 
   // Store the Device EventHandlers - used for callback
   HWEventHandler *event_handler_[kNumPhysicalDisplays];
@@ -166,12 +246,13 @@
   HWResourceInfo hw_resource_;
   int fb_node_index_[kDeviceMax];
   const char* fb_path_;
-  PanelInfo pri_panel_info_;
+  PanelInfo primary_panel_info_;
   bool hotplug_enabled_;
   uint32_t hdmi_mode_count_;
   uint32_t hdmi_modes_[256];
   // Holds the hdmi timing information. Ex: resolution, fps etc.,
   msm_hdmi_mode_timing_info *supported_video_modes_;
+  BufferSyncHandler *buffer_sync_handler_;
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/core/hw_interface.cpp b/displayengine/libs/core/hw_interface.cpp
old mode 100755
new mode 100644
index 3ab0c7e..6b99a73
--- a/displayengine/libs/core/hw_interface.cpp
+++ b/displayengine/libs/core/hw_interface.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -29,11 +29,11 @@
 
 namespace sde {
 
-DisplayError HWInterface::Create(HWInterface **intf) {
+DisplayError HWInterface::Create(HWInterface **intf, BufferSyncHandler *buffer_sync_handler) {
   DisplayError error = kErrorNone;
   HWFrameBuffer *hw_frame_buffer = NULL;
 
-  hw_frame_buffer = new HWFrameBuffer();
+  hw_frame_buffer = new HWFrameBuffer(buffer_sync_handler);
   error = hw_frame_buffer->Init();
   if (UNLIKELY(error != kErrorNone)) {
     delete hw_frame_buffer;
diff --git a/displayengine/libs/core/hw_interface.h b/displayengine/libs/core/hw_interface.h
index c8611f9..084768e 100644
--- a/displayengine/libs/core/hw_interface.h
+++ b/displayengine/libs/core/hw_interface.h
@@ -28,6 +28,9 @@
 #include <core/display_interface.h>
 #include <private/strategy_interface.h>
 #include <utils/constants.h>
+#include <core/buffer_allocator.h>
+#include <core/buffer_sync_handler.h>
+#include <scalar.h>
 
 namespace sde {
 
@@ -44,7 +47,8 @@
   kDevicePrimary,
   kDeviceHDMI,
   kDeviceVirtual,
-  kDeviceMax
+  kDeviceRotator,
+  kDeviceMax,
 };
 
 struct HWResourceInfo {
@@ -90,48 +94,69 @@
       max_pipe_bw(0), max_sde_clk(0), clk_fudge_factor(1.0f), has_bwc(false),
       has_decimation(false), has_macrotile(false), has_rotator_downscale(false),
       has_non_scalar_rgb(false), is_src_split(false), always_src_split(false) { }
+
+  void Reset() { *this = HWResourceInfo(); }
+};
+
+struct HWBufferInfo : public BufferInfo {
+  LayerBuffer output_buffer;
+  int session_id;
+  uint32_t slot;
+
+  HWBufferInfo() : session_id(-1), slot(0) { }
 };
 
 struct HWRotateInfo {
-  int pipe_id;
+  uint32_t pipe_id;
   LayerRect src_roi;
   LayerRect dst_roi;
+  LayerBufferFormat dst_format;
   HWBlockType writeback_id;
   float downscale_ratio_x;
   float downscale_ratio_y;
+  HWBufferInfo hw_buffer_info;
+  bool valid;
 
-  HWRotateInfo() : pipe_id(0), writeback_id(kHWWriteback0), downscale_ratio_x(1.0f),
-      downscale_ratio_y(1.0f) { }
+  HWRotateInfo() : pipe_id(0), dst_format(kFormatInvalid), writeback_id(kHWWriteback0),
+                   downscale_ratio_x(1.0f), downscale_ratio_y(1.0f), valid(false) { }
 
-  inline void Reset() { *this = HWRotateInfo(); }
+  void Reset() { *this = HWRotateInfo(); }
 };
 
 struct HWPipeInfo {
-  int pipe_id;
+  uint32_t pipe_id;
   LayerRect src_roi;
   LayerRect dst_roi;
   uint8_t horizontal_decimation;
   uint8_t vertical_decimation;
+  scalar::Scale scale_data;
+  bool valid;
 
-  HWPipeInfo() : pipe_id(0), horizontal_decimation(0), vertical_decimation(0) { }
+  HWPipeInfo() : pipe_id(0), horizontal_decimation(0), vertical_decimation(0), valid(false) { }
 
-  inline void Reset() { *this = HWPipeInfo(); }
+  void Reset() { *this = HWPipeInfo(); }
 };
 
 struct HWLayerConfig {
   bool use_non_dma_pipe;  // set by client
-  bool is_right_pipe;  // indicate if right pipe is valid
   HWPipeInfo left_pipe;  // pipe for left side of the buffer
   HWPipeInfo right_pipe;  // pipe for right side of the buffer
   uint32_t num_rotate;  // number of rotate
   HWRotateInfo rotates[kMaxRotatePerLayer];  // rotation for the buffer
 
-  HWLayerConfig() : use_non_dma_pipe(false), is_right_pipe(false), num_rotate(0) { }
+  HWLayerConfig() : use_non_dma_pipe(false), num_rotate(0) { }
+
+  void Reset() { *this = HWLayerConfig(); }
 };
 
 struct HWLayers {
   HWLayersInfo info;
   HWLayerConfig config[kMaxSDELayers];
+  int closed_session_ids[kMaxSDELayers * 2];  // split panel (left + right)
+
+  HWLayers() { memset(closed_session_ids, -1, sizeof(closed_session_ids)); }
+
+  void Reset() { *this = HWLayers(); }
 };
 
 struct HWDisplayAttributes : DisplayConfigVariableInfo {
@@ -139,20 +164,23 @@
   uint32_t split_left;
 
   HWDisplayAttributes() : is_device_split(false), split_left(0) { }
+
+  void Reset() { *this = HWDisplayAttributes(); }
 };
 
 // HWEventHandler - Implemented in DisplayBase and HWInterface implementation
 class HWEventHandler {
  public:
   virtual DisplayError VSync(int64_t timestamp) = 0;
-  virtual DisplayError Blank(bool blank)= 0;
+  virtual DisplayError Blank(bool blank) = 0;
+  virtual void IdleTimeout() = 0;
  protected:
-  virtual ~HWEventHandler() {}
+  virtual ~HWEventHandler() { }
 };
 
 class HWInterface {
  public:
-  static DisplayError Create(HWInterface **intf);
+  static DisplayError Create(HWInterface **intf, BufferSyncHandler *buffer_sync_handler);
   static DisplayError Destroy(HWInterface *intf);
   virtual DisplayError GetHWCapabilities(HWResourceInfo *hw_res_info) = 0;
   virtual DisplayError Open(HWDeviceType type, Handle *device, HWEventHandler *eventhandler) = 0;
@@ -167,8 +195,12 @@
   virtual DisplayError Doze(Handle device) = 0;
   virtual DisplayError SetVSyncState(Handle device, bool enable) = 0;
   virtual DisplayError Standby(Handle device) = 0;
+  virtual DisplayError OpenRotatorSession(Handle device, HWLayers *hw_layers) = 0;
+  virtual DisplayError CloseRotatorSession(Handle device, int32_t session_id) = 0;
   virtual DisplayError Validate(Handle device, HWLayers *hw_layers) = 0;
   virtual DisplayError Commit(Handle device, HWLayers *hw_layers) = 0;
+  virtual DisplayError Flush(Handle device) = 0;
+  virtual void SetIdleTimeoutMs(Handle device, uint32_t timeout_ms) = 0;
 
  protected:
   virtual ~HWInterface() { }
diff --git a/displayengine/libs/core/offline_ctrl.cpp b/displayengine/libs/core/offline_ctrl.cpp
old mode 100755
new mode 100644
index c380d52..5ffaf22
--- a/displayengine/libs/core/offline_ctrl.cpp
+++ b/displayengine/libs/core/offline_ctrl.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -31,17 +31,131 @@
 
 namespace sde {
 
-OfflineCtrl::OfflineCtrl() : hw_intf_(NULL) {
+// TODO(user): Move this offline controller under composition manager like other modules
+// [resource manager]. Implement session management and buffer management in offline controller.
+OfflineCtrl::OfflineCtrl() : hw_intf_(NULL), hw_rotator_device_(NULL) {
 }
 
 DisplayError OfflineCtrl::Init(HWInterface *hw_intf, HWResourceInfo hw_res_info) {
   hw_intf_ = hw_intf;
+  DisplayError error = kErrorNone;
+
+  error = hw_intf_->Open(kDeviceRotator, &hw_rotator_device_, NULL);
+  if (error != kErrorNone) {
+    DLOGW("Failed to open rotator device");
+  }
+
   return kErrorNone;
 }
 
 DisplayError OfflineCtrl::Deinit() {
+  DisplayError error = kErrorNone;
+
+  error = hw_intf_->Close(hw_rotator_device_);
+  if (error != kErrorNone) {
+    DLOGW("Failed to close rotator device");
+    return error;
+  }
+
   return kErrorNone;
 }
 
+DisplayError OfflineCtrl::RegisterDisplay(DisplayType type, Handle *display_ctx) {
+  DisplayOfflineContext *disp_offline_ctx = new DisplayOfflineContext();
+  if (disp_offline_ctx == NULL) {
+    return kErrorMemory;
+  }
+
+  disp_offline_ctx->display_type = type;
+  *display_ctx = disp_offline_ctx;
+
+  return kErrorNone;
+}
+
+void OfflineCtrl::UnregisterDisplay(Handle display_ctx) {
+  DisplayOfflineContext *disp_offline_ctx = reinterpret_cast<DisplayOfflineContext *>(display_ctx);
+
+  delete disp_offline_ctx;
+  disp_offline_ctx = NULL;
+}
+
+
+DisplayError OfflineCtrl::Prepare(Handle display_ctx, HWLayers *hw_layers) {
+  DisplayError error = kErrorNone;
+
+  DisplayOfflineContext *disp_offline_ctx = reinterpret_cast<DisplayOfflineContext *>(display_ctx);
+
+  if (!hw_rotator_device_ && IsRotationRequired(hw_layers)) {
+    DLOGV_IF(kTagOfflineCtrl, "No Rotator device found");
+    return kErrorHardware;
+  }
+
+  disp_offline_ctx->pending_rot_commit = false;
+
+  uint32_t i = 0;
+  while (hw_layers->closed_session_ids[i] >= 0) {
+    error = hw_intf_->CloseRotatorSession(hw_rotator_device_, hw_layers->closed_session_ids[i]);
+    if (LIKELY(error != kErrorNone)) {
+      DLOGE("Rotator close session failed");
+      return error;
+    }
+    hw_layers->closed_session_ids[i++] = -1;
+  }
+
+
+  if (IsRotationRequired(hw_layers)) {
+    error = hw_intf_->OpenRotatorSession(hw_rotator_device_, hw_layers);
+    if (LIKELY(error != kErrorNone)) {
+      DLOGE("Rotator open session failed");
+      return error;
+    }
+
+    error = hw_intf_->Validate(hw_rotator_device_, hw_layers);
+    if (LIKELY(error != kErrorNone)) {
+      DLOGE("Rotator validation failed");
+      return error;
+    }
+    disp_offline_ctx->pending_rot_commit = true;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError OfflineCtrl::Commit(Handle display_ctx, HWLayers *hw_layers) {
+  DisplayError error = kErrorNone;
+
+  DisplayOfflineContext *disp_offline_ctx = reinterpret_cast<DisplayOfflineContext *>(display_ctx);
+
+  if (disp_offline_ctx->pending_rot_commit) {
+    error = hw_intf_->Commit(hw_rotator_device_, hw_layers);
+    if (error != kErrorNone) {
+      DLOGE("Rotator commit failed");
+      return error;
+    }
+    disp_offline_ctx->pending_rot_commit = false;
+  }
+
+  return kErrorNone;
+}
+
+bool OfflineCtrl::IsRotationRequired(HWLayers *hw_layers) {
+  HWLayersInfo &layer_info = hw_layers->info;
+
+  for (uint32_t i = 0; i < layer_info.count; i++) {
+    Layer& layer = layer_info.stack->layers[layer_info.index[i]];
+
+    HWRotateInfo *rotate = &hw_layers->config[i].rotates[0];
+    if (rotate->valid) {
+      return true;
+    }
+
+    rotate = &hw_layers->config[i].rotates[1];
+    if (rotate->valid) {
+      return true;
+    }
+  }
+  return false;
+}
+
 }  // namespace sde
 
diff --git a/displayengine/libs/core/offline_ctrl.h b/displayengine/libs/core/offline_ctrl.h
index 8987bb3..fafdf7c 100644
--- a/displayengine/libs/core/offline_ctrl.h
+++ b/displayengine/libs/core/offline_ctrl.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -26,6 +26,7 @@
 #define __OFFLINE_CTRL_H__
 
 #include <utils/locker.h>
+#include <utils/debug.h>
 
 #include "hw_interface.h"
 
@@ -36,9 +37,23 @@
   OfflineCtrl();
   DisplayError Init(HWInterface *hw_intf, HWResourceInfo hw_res_info);
   DisplayError Deinit();
+  DisplayError RegisterDisplay(DisplayType type, Handle *display_ctx);
+  void UnregisterDisplay(Handle display_ctx);
+  DisplayError Prepare(Handle display_ctx, HWLayers *hw_layers);
+  DisplayError Commit(Handle display_ctx, HWLayers *hw_layers);
 
  private:
+  struct DisplayOfflineContext {
+    DisplayType display_type;
+    bool pending_rot_commit;
+
+    DisplayOfflineContext() : display_type(kPrimary), pending_rot_commit(false) { }
+  };
+
+  bool IsRotationRequired(HWLayers *hw_layers);
+
   HWInterface *hw_intf_;
+  Handle hw_rotator_device_;
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/core/res_config.cpp b/displayengine/libs/core/res_config.cpp
index 1fc1598..d3c2d26 100644
--- a/displayengine/libs/core/res_config.cpp
+++ b/displayengine/libs/core/res_config.cpp
@@ -25,11 +25,15 @@
 #include <math.h>
 #include <utils/constants.h>
 #include <utils/debug.h>
+#include <utils/rect.h>
 
 #include "res_manager.h"
 
 #define __CLASS__ "ResManager"
 
+using scalar::PipeInfo;
+using scalar::LayerInfo;
+
 namespace sde {
 
 void ResManager::RotationConfig(const LayerTransform &transform, const float &scale_x,
@@ -47,11 +51,18 @@
   rotate->downscale_ratio_y = scale_y;
 
   // downscale when doing rotation
-  dst_rect.right = src_height / rotate->downscale_ratio_x;
-  dst_rect.bottom = src_width / rotate->downscale_ratio_y;
+  if (IsRotationNeeded(transform.rotation)) {
+    dst_rect.right = src_height / rotate->downscale_ratio_x;
+    dst_rect.bottom = src_width / rotate->downscale_ratio_y;
+  } else {
+    dst_rect.right = src_width / rotate->downscale_ratio_x;
+    dst_rect.bottom = src_height / rotate->downscale_ratio_y;
+  }
 
+  dst_rect.right = floorf(dst_rect.right);
+  dst_rect.bottom = floorf(dst_rect.bottom);
   rotate->src_roi = *src_rect;
-  rotate->pipe_id = kPipeIdNeedsAssignment;
+  rotate->valid = true;
   rotate->dst_roi = dst_rect;
 
   *src_rect = dst_rect;
@@ -65,21 +76,20 @@
   HWDisplayAttributes &display_attributes = display_resource_ctx->display_attributes;
   HWPipeInfo *left_pipe = &layer_config->left_pipe;
   HWPipeInfo *right_pipe = &layer_config->right_pipe;
-  layer_config->is_right_pipe = false;
 
-  if ((src_rect.right - src_rect.left) >= kMaxSourcePipeWidth ||
-      (dst_rect.right - dst_rect.left) >= kMaxInterfaceWidth || hw_res_info_.always_src_split) {
+  if ((src_rect.right - src_rect.left) > kMaxSourcePipeWidth ||
+      (dst_rect.right - dst_rect.left) > kMaxInterfaceWidth || hw_res_info_.always_src_split) {
     SplitRect(transform.flip_horizontal, src_rect, dst_rect, &left_pipe->src_roi,
               &left_pipe->dst_roi, &right_pipe->src_roi, &right_pipe->dst_roi);
-    left_pipe->pipe_id = kPipeIdNeedsAssignment;
-    right_pipe->pipe_id = kPipeIdNeedsAssignment;
-    layer_config->is_right_pipe = true;
+    left_pipe->valid = true;
+    right_pipe->valid = true;
   } else {
     left_pipe->src_roi = src_rect;
     left_pipe->dst_roi = dst_rect;
-    left_pipe->pipe_id = kPipeIdNeedsAssignment;
+    left_pipe->valid = true;
     right_pipe->Reset();
   }
+
   return kErrorNone;
 }
 
@@ -87,12 +97,13 @@
                                             const LayerTransform &transform,
                                             const LayerRect &src_rect, const LayerRect &dst_rect,
                                             HWLayerConfig *layer_config) {
+  LayerRect scissor_dst_left, scissor_dst_right;
   HWDisplayAttributes &display_attributes = display_resource_ctx->display_attributes;
+
   // for display split case
   HWPipeInfo *left_pipe = &layer_config->left_pipe;
   HWPipeInfo *right_pipe = &layer_config->right_pipe;
   LayerRect scissor, dst_left, crop_left, crop_right, dst_right;
-  layer_config->is_right_pipe = false;
   scissor.right = FLOAT(display_attributes.split_left);
   scissor.bottom = FLOAT(display_attributes.y_pixels);
 
@@ -107,29 +118,33 @@
   scissor.right = FLOAT(display_attributes.x_pixels);
   scissor.bottom = FLOAT(display_attributes.y_pixels);
   CalculateCropRects(scissor, transform, &crop_right, &dst_right);
-  if ((crop_left.right - crop_left.left) >= kMaxSourcePipeWidth) {
-    if (crop_right.right != crop_right.left)
+  if ((crop_left.right - crop_left.left) > kMaxSourcePipeWidth) {
+    if (crop_right.right != crop_right.left) {
+      DLOGV_IF(kTagResources, "Need more than 2 pipes: left width = %.0f, right width = %.0f",
+               crop_left.right - crop_left.left, crop_right.right - crop_right.left);
       return kErrorNotSupported;
+    }
     // 2 pipes both are on the left
     SplitRect(transform.flip_horizontal, crop_left, dst_left, &left_pipe->src_roi,
               &left_pipe->dst_roi, &right_pipe->src_roi, &right_pipe->dst_roi);
-    left_pipe->pipe_id = kPipeIdNeedsAssignment;
-    right_pipe->pipe_id = kPipeIdNeedsAssignment;
-    layer_config->is_right_pipe = true;
-  } else if ((crop_right.right - crop_right.left) >= kMaxSourcePipeWidth) {
-    if (crop_left.right != crop_left.left)
+    left_pipe->valid = true;
+    right_pipe->valid = true;
+  } else if ((crop_right.right - crop_right.left) > kMaxSourcePipeWidth) {
+    if (crop_left.right != crop_left.left) {
+      DLOGV_IF(kTagResources, "Need more than 2 pipes: left width = %.0f, right width = %.0f",
+               crop_left.right - crop_left.left, crop_right.right - crop_right.left);
       return kErrorNotSupported;
+    }
     // 2 pipes both are on the right
     SplitRect(transform.flip_horizontal, crop_right, dst_right, &left_pipe->src_roi,
               &left_pipe->dst_roi, &right_pipe->src_roi, &right_pipe->dst_roi);
-    left_pipe->pipe_id = kPipeIdNeedsAssignment;
-    right_pipe->pipe_id = kPipeIdNeedsAssignment;
-    layer_config->is_right_pipe = true;
+    left_pipe->valid = true;
+    right_pipe->valid = true;
   } else if (UINT32(dst_left.right) > UINT32(dst_left.left)) {
     // assign left pipe
     left_pipe->src_roi = crop_left;
     left_pipe->dst_roi = dst_left;
-    left_pipe->pipe_id = kPipeIdNeedsAssignment;
+    left_pipe->valid = true;
   } else {
     // Set default value, left_pipe is not needed.
     left_pipe->Reset();
@@ -137,16 +152,15 @@
 
   // assign right pipe if needed
   if (UINT32(dst_right.right) > UINT32(dst_right.left)) {
-    if (left_pipe->pipe_id) {
+    if (left_pipe->valid) {
       right_pipe->src_roi = crop_right;
       right_pipe->dst_roi = dst_right;
-      right_pipe->pipe_id = kPipeIdNeedsAssignment;
-      layer_config->is_right_pipe = true;
+      right_pipe->valid = true;
     } else {
       // If left pipe is not used, use left pipe first.
       left_pipe->src_roi = crop_right;
       left_pipe->dst_roi = dst_right;
-      left_pipe->pipe_id = kPipeIdNeedsAssignment;
+      left_pipe->valid = true;
       right_pipe->Reset();
     }
   } else {
@@ -168,9 +182,9 @@
     Layer& layer = layer_info.stack->layers[layer_info.index[i]];
     float rot_scale_x = 1.0f, rot_scale_y = 1.0f;
     if (!IsValidDimension(layer.src_rect, layer.dst_rect)) {
-      DLOGE_IF(kTagResources, "Input is invalid");
-      LogRectVerbose("input layer src_rect", layer.src_rect);
-      LogRectVerbose("input layer dst_rect", layer.dst_rect);
+      DLOGV_IF(kTagResources, "Input is invalid");
+      LogRect(kTagResources, "input layer src_rect", layer.src_rect);
+      LogRect(kTagResources, "input layer dst_rect", layer.dst_rect);
       return kErrorNotSupported;
     }
 
@@ -217,27 +231,33 @@
     //    rectangle of video layer to be even.
     // 2. Normalize source and destination rect of a layer to multiple of 1.
     uint32_t factor = (1 << layer.input_buffer->flags.video);
-    if (left_pipe.pipe_id == kPipeIdNeedsAssignment) {
+    if (left_pipe.valid) {
       NormalizeRect(factor, &left_pipe.src_roi);
       NormalizeRect(1, &left_pipe.dst_roi);
     }
 
-    if (right_pipe.pipe_id == kPipeIdNeedsAssignment) {
+    if (right_pipe.valid) {
       NormalizeRect(factor, &right_pipe.src_roi);
       NormalizeRect(1, &right_pipe.dst_roi);
     }
 
     DLOGV_IF(kTagResources, "layer = %d, left pipe_id = %x",
              i, layer_config->left_pipe.pipe_id);
-    LogRectVerbose("input layer src_rect", layer.src_rect);
-    LogRectVerbose("input layer dst_rect", layer.dst_rect);
-    LogRectVerbose("cropped src_rect", src_rect);
-    LogRectVerbose("cropped dst_rect", dst_rect);
-    LogRectVerbose("left pipe src", layer_config->left_pipe.src_roi);
-    LogRectVerbose("left pipe dst", layer_config->left_pipe.dst_roi);
+    LogRect(kTagResources, "input layer src_rect", layer.src_rect);
+    LogRect(kTagResources, "input layer dst_rect", layer.dst_rect);
+    for (uint32_t k = 0; k < layer_config->num_rotate; k++) {
+      DLOGV_IF(kTagResources, "rotate num = %d, scale_x = %.2f, scale_y = %.2f",
+               k, rot_scale_x, rot_scale_y);
+      LogRect(kTagResources, "rotate src", layer_config->rotates[k].src_roi);
+      LogRect(kTagResources, "rotate dst", layer_config->rotates[k].dst_roi);
+    }
+    LogRect(kTagResources, "cropped src_rect", src_rect);
+    LogRect(kTagResources, "cropped dst_rect", dst_rect);
+    LogRect(kTagResources, "left pipe src", layer_config->left_pipe.src_roi);
+    LogRect(kTagResources, "left pipe dst", layer_config->left_pipe.dst_roi);
     if (hw_layers->config[i].right_pipe.pipe_id) {
-      LogRectVerbose("right pipe src", layer_config->right_pipe.src_roi);
-      LogRectVerbose("right pipe dst", layer_config->right_pipe.dst_roi);
+      LogRect(kTagResources, "right pipe src", layer_config->right_pipe.src_roi);
+      LogRect(kTagResources, "right pipe dst", layer_config->right_pipe.dst_roi);
     }
   }
 
@@ -402,6 +422,7 @@
     return;
 
   CalculateCut(transform, &left_cut_ratio, &top_cut_ratio, &right_cut_ratio, &bottom_cut_ratio);
+
   crop_left += crop_width * left_cut_ratio;
   crop_top += crop_height * top_cut_ratio;
   crop_right -= crop_width * right_cut_ratio;
@@ -414,7 +435,7 @@
       src.top - roundf(src.top)       ||
       src.right - roundf(src.right)   ||
       src.bottom - roundf(src.bottom)) {
-    DLOGE_IF(kTagResources, "Input ROI is not integral");
+    DLOGV_IF(kTagResources, "Input ROI is not integral");
     return false;
   }
 
@@ -512,21 +533,123 @@
   }
 }
 
-void ResManager::LogRectVerbose(const char *prefix, const LayerRect &roi) {
-  DLOGV_IF(kTagResources, "%s: left = %.0f, top = %.0f, right = %.0f, bottom = %.0f",
-           prefix, roi.left, roi.top, roi.right, roi.bottom);
+// Scalar helper functions
+static void SetPipeInfo(HWPipeInfo* hw_pipe, PipeInfo* pipe) {
+  pipe->id = hw_pipe->pipe_id;
+  pipe->scale_data = &hw_pipe->scale_data;
+  pipe->horz_deci = hw_pipe->horizontal_decimation;
+  pipe->vert_deci = hw_pipe->vertical_decimation;
+
+  pipe->src_rect.x = UINT32(hw_pipe->src_roi.left);
+  pipe->src_rect.y = UINT32(hw_pipe->src_roi.top);
+  pipe->src_rect.w = UINT32(hw_pipe->src_roi.right) - pipe->src_rect.x;
+  pipe->src_rect.h = UINT32(hw_pipe->src_roi.bottom) - pipe->src_rect.y;
+
+  pipe->dst_rect.x = UINT32(hw_pipe->dst_roi.left);
+  pipe->dst_rect.y = UINT32(hw_pipe->dst_roi.top);
+  pipe->dst_rect.w = UINT32(hw_pipe->dst_roi.right) - pipe->dst_rect.x;
+  pipe->dst_rect.h = UINT32(hw_pipe->dst_roi.bottom) - pipe->dst_rect.y;
 }
 
-void ResManager::NormalizeRect(const uint32_t &factor, LayerRect *rect) {
-  uint32_t left = UINT32(ceilf(rect->left));
-  uint32_t top = UINT32(ceilf(rect->top));
-  uint32_t right = UINT32(floorf(rect->right));
-  uint32_t bottom = UINT32(floorf(rect->bottom));
+static void UpdateSrcRoi(PipeInfo* pipe, HWPipeInfo* hw_pipe) {
+  hw_pipe->src_roi.left   = FLOAT(pipe->src_rect.x);
+  hw_pipe->src_roi.top    = FLOAT(pipe->src_rect.y);
+  hw_pipe->src_roi.right  = FLOAT(pipe->src_rect.x + pipe->src_rect.w);
+  hw_pipe->src_roi.bottom = FLOAT(pipe->src_rect.y + pipe->src_rect.h);
+}
 
-  rect->left = FLOAT(CeilToMultipleOf(left, factor));
-  rect->top = FLOAT(CeilToMultipleOf(top, factor));
-  rect->right = FLOAT(FloorToMultipleOf(right, factor));
-  rect->bottom = FLOAT(FloorToMultipleOf(bottom, factor));
+static uint32_t GetScalarFormat(LayerBufferFormat source) {
+  uint32_t format = scalar::UNKNOWN_FORMAT;
+
+  switch (source) {
+  case kFormatARGB8888:                 format = scalar::ARGB_8888;         break;
+  case kFormatRGBA8888:                 format = scalar::RGBA_8888;         break;
+  case kFormatBGRA8888:                 format = scalar::BGRA_8888;         break;
+  case kFormatXRGB8888:                 format = scalar::XRGB_8888;         break;
+  case kFormatRGBX8888:                 format = scalar::RGBX_8888;         break;
+  case kFormatBGRX8888:                 format = scalar::BGRX_8888;         break;
+  case kFormatRGB888:                   format = scalar::RGB_888;           break;
+  case kFormatRGB565:                   format = scalar::RGB_565;           break;
+  case kFormatYCbCr420Planar:           format = scalar::Y_CB_CR_H2V2;      break;
+  case kFormatYCrCb420Planar:           format = scalar::Y_CR_CB_H2V2;      break;
+  case kFormatYCbCr420SemiPlanar:       format = scalar::Y_CBCR_H2V2;       break;
+  case kFormatYCrCb420SemiPlanar:       format = scalar::Y_CRCB_H2V2;       break;
+  case kFormatYCbCr422Packed:           format = scalar::YCBYCR_H2V1;       break;
+  case kFormatYCbCr420SemiPlanarVenus:  format = scalar::Y_CBCR_H2V2_VENUS; break;
+  case kFormatRGBA8888Ubwc:             format = scalar::RGBA_8888_UBWC;    break;
+  case kFormatRGB565Ubwc:               format = scalar::RGB_565_UBWC;      break;
+  case kFormatYCbCr420SPVenusUbwc:      format = scalar::Y_CBCR_H2V2_UBWC;  break;
+  default:
+    DLOGE("Unsupported source format: %x", source);
+    break;
+  }
+
+  return format;
+}
+
+bool ResManager::ConfigureScaling(HWLayers *hw_layers) {
+  HWLayersInfo &hw_layer_info = hw_layers->info;
+
+  for (uint32_t i = 0; i < hw_layer_info.count; i++) {
+    Layer &layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
+    LayerBuffer *input_buffer = layer.input_buffer;
+    HWPipeInfo* left_pipe = &hw_layers->config[i].left_pipe;
+    HWPipeInfo* right_pipe = &hw_layers->config[i].right_pipe;
+
+    // Prepare data structure for lib scalar
+    uint32_t flags = 0;
+    struct LayerInfo layer_info;
+
+    if (layer.transform.rotation == 90.0f) {
+      // Flips will be taken care by rotator, if layer requires 90 rotation
+      flags |= scalar::SCALAR_SOURCE_ROTATED_90;
+    } else {
+      flags |= layer.transform.flip_vertical ? scalar::SCALAR_FLIP_UD : 0;
+      flags |= layer.transform.flip_horizontal ? scalar::SCALAR_FLIP_LR : 0;
+    }
+
+    for (uint32_t count = 0; count < 2; count++) {
+      HWPipeInfo* hw_pipe = (count == 0) ? left_pipe : right_pipe;
+      HWRotateInfo* rotate_info = &hw_layers->config[i].rotates[count];
+      PipeInfo* scalar_pipe = (count == 0) ? &layer_info.left_pipe : &layer_info.right_pipe;
+
+      if (rotate_info->valid)
+        input_buffer = &rotate_info->hw_buffer_info.output_buffer;
+
+      scalar_pipe->flags = flags;
+      hw_pipe->scale_data.src_width = input_buffer->width;
+      SetPipeInfo(hw_pipe, scalar_pipe);
+    }
+    layer_info.src_format = GetScalarFormat(input_buffer->format);
+
+    DLOGV_IF(kTagResources, "Scalar Input[%d] flags=%x format=%x", i, flags, layer_info.src_format);
+    DLOGV_IF(kTagResources, "Left: id=%d hD=%d vD=%d srcRect=[%d %d %d %d] dstRect=[%d %d %d %d]",
+        layer_info.left_pipe.id, layer_info.left_pipe.horz_deci, layer_info.left_pipe.vert_deci,
+        layer_info.left_pipe.src_rect.x, layer_info.left_pipe.src_rect.y,
+        layer_info.left_pipe.src_rect.w, layer_info.left_pipe.src_rect.h,
+        layer_info.left_pipe.dst_rect.x, layer_info.left_pipe.dst_rect.y,
+        layer_info.left_pipe.dst_rect.w, layer_info.left_pipe.dst_rect.h);
+    DLOGV_IF(kTagResources, "Right: id=%d hD=%d vD=%d srcRect=[%d %d %d %d] dstRect=[%d %d %d %d]",
+        layer_info.right_pipe.id, layer_info.right_pipe.horz_deci, layer_info.right_pipe.vert_deci,
+        layer_info.right_pipe.src_rect.x, layer_info.right_pipe.src_rect.y,
+        layer_info.right_pipe.src_rect.w, layer_info.right_pipe.src_rect.h,
+        layer_info.right_pipe.dst_rect.x, layer_info.right_pipe.dst_rect.y,
+        layer_info.right_pipe.dst_rect.w, layer_info.right_pipe.dst_rect.h);
+
+    // Configure scale data structure
+    if (ScalarConfigureScale(&layer_info) < 0) {
+      DLOGE("Scalar library failed to configure scale data!");
+      return false;
+    }
+
+    // Update Src Roi in HWPipeInfo
+    if (left_pipe->scale_data.enable_pxl_ext)
+      UpdateSrcRoi(&layer_info.left_pipe, left_pipe);
+    if (right_pipe->scale_data.enable_pxl_ext)
+      UpdateSrcRoi(&layer_info.right_pipe, right_pipe);
+  }
+
+  return true;
 }
 
 }  // namespace sde
diff --git a/displayengine/libs/core/res_manager.cpp b/displayengine/libs/core/res_manager.cpp
index 12ef5bd..fb8f2eb 100644
--- a/displayengine/libs/core/res_manager.cpp
+++ b/displayengine/libs/core/res_manager.cpp
@@ -25,20 +25,33 @@
 #include <math.h>
 #include <utils/constants.h>
 #include <utils/debug.h>
+#include <dlfcn.h>
 
 #include "res_manager.h"
 
 #define __CLASS__ "ResManager"
+#define SCALAR_LIBRARY_NAME "libscalar.so"
 
 namespace sde {
 
 ResManager::ResManager()
-  : num_pipe_(0), vig_pipes_(NULL), rgb_pipes_(NULL), dma_pipes_(NULL), virtual_count_(0) {
+  : num_pipe_(0), vig_pipes_(NULL), rgb_pipes_(NULL), dma_pipes_(NULL), virtual_count_(0),
+    buffer_allocator_(NULL), buffer_sync_handler_(NULL) {
 }
 
-DisplayError ResManager::Init(const HWResourceInfo &hw_res_info) {
+DisplayError ResManager::Init(const HWResourceInfo &hw_res_info, BufferAllocator *buffer_allocator,
+                              BufferSyncHandler *buffer_sync_handler) {
   hw_res_info_ = hw_res_info;
 
+  buffer_sync_handler_ = buffer_sync_handler;
+
+  if (!hw_res_info_.max_mixer_width)
+    hw_res_info_.max_mixer_width = kMaxSourcePipeWidth;
+
+  buffer_allocator_ = buffer_allocator;
+
+  buffer_sync_handler_ = buffer_sync_handler;
+
   DisplayError error = kErrorNone;
 
   // TODO(user): Remove this. Disable src_split as kernel not supported yet
@@ -80,6 +93,9 @@
   DLOGI("hw_rev=%x, DMA=%d RGB=%d VIG=%d", hw_res_info_.hw_revision, hw_res_info_.num_dma_pipe,
     hw_res_info_.num_rgb_pipe, hw_res_info_.num_vig_pipe);
 
+  // TODO(user): Need to get it from HW capability
+  hw_res_info_.num_rotator = 2;
+
   if (hw_res_info_.num_rotator > kMaxNumRotator) {
     DLOGE("Number of rotator is over the limit! %d", hw_res_info_.num_rotator);
     return kErrorParameters;
@@ -98,10 +114,23 @@
   rgb_pipes_[0].state = kPipeStateOwnedByKernel;
   rgb_pipes_[1].state = kPipeStateOwnedByKernel;
 
+  ScalarConfigureScale = NULL;
+  lib_scalar_handle_ = dlopen(SCALAR_LIBRARY_NAME, RTLD_NOW);
+  if (lib_scalar_handle_) {
+    void **scalar_func = reinterpret_cast<void **>(&ScalarConfigureScale);
+    *scalar_func = ::dlsym(lib_scalar_handle_, "configureScale");
+  } else {
+    DLOGW("Unable to load %s !", SCALAR_LIBRARY_NAME);
+  }
+
   return kErrorNone;
 }
 
 DisplayError ResManager::Deinit() {
+  if (lib_scalar_handle_) {
+    dlclose(lib_scalar_handle_);
+    lib_scalar_handle_ = NULL;
+  }
   return kErrorNone;
 }
 
@@ -143,6 +172,13 @@
     return kErrorMemory;
   }
 
+  display_resource_ctx->buffer_manager = new BufferManager(buffer_allocator_, buffer_sync_handler_);
+  if (display_resource_ctx->buffer_manager == NULL) {
+    delete display_resource_ctx;
+    display_resource_ctx = NULL;
+    return kErrorMemory;
+  }
+
   hw_block_ctx_[hw_block_id].is_in_use = true;
 
   display_resource_ctx->display_attributes = attributes;
@@ -254,8 +290,9 @@
 
   // allocate rotator
   error = AcquireRotator(display_resource_ctx, rotate_count);
-  if (error != kErrorNone)
+  if (error != kErrorNone) {
     return error;
+  }
 
   rotate_count = 0;
   for (uint32_t i = 0; i < layer_info.count; i++) {
@@ -278,7 +315,7 @@
     bool is_yuv = IsYuvFormat(layer.input_buffer->format);
 
     // left pipe is needed
-    if (pipe_info->pipe_id) {
+    if (pipe_info->valid) {
       need_scale = IsScalingNeeded(pipe_info);
       left_index = GetPipe(hw_block_id, is_yuv, need_scale, false, use_non_dma_pipe);
       if (left_index >= num_pipe_) {
@@ -293,7 +330,7 @@
     }
 
     pipe_info =  &layer_config.right_pipe;
-    if (pipe_info->pipe_id == 0) {
+    if (!pipe_info->valid) {
       // assign single pipe
       if (left_index < num_pipe_) {
         layer_config.left_pipe.pipe_id = src_pipes_[left_index].mdss_pipe_id;
@@ -331,6 +368,19 @@
             i, layer_config.left_pipe.pipe_id,  pipe_info->pipe_id);
   }
 
+  error = AllocRotatorBuffer(display_ctx, hw_layers);
+  if (error != kErrorNone) {
+    DLOGV_IF(kTagResources, "Rotator buffer allocation failed");
+    goto CleanupOnError;
+  }
+
+  if (lib_scalar_handle_ && ScalarConfigureScale) {
+    if (!ConfigureScaling(hw_layers)) {
+      DLOGV_IF(kTagResources, "Scale data configuration has failed!");
+      goto CleanupOnError;
+    }
+  }
+
   if (!CheckBandwidth(display_resource_ctx, hw_layers)) {
     DLOGV_IF(kTagResources, "Bandwidth check failed!");
     goto CleanupOnError;
@@ -348,6 +398,11 @@
 }
 
 bool ResManager::CheckBandwidth(DisplayResourceContext *display_ctx, HWLayers *hw_layers) {
+  // No need to check bandwidth for virtual displays
+  if (display_ctx->display_type == kVirtual) {
+    return true;
+  }
+
   float max_pipe_bw = FLOAT(hw_res_info_.max_pipe_bw) / 1000000;  // KBps to GBps
   float max_sde_clk = FLOAT(hw_res_info_.max_sde_clk) / 1000000;  // Hz to MHz
   const struct HWLayersInfo &layer_info = hw_layers->info;
@@ -360,19 +415,19 @@
   for (uint32_t i = 0; i < layer_info.count; i++) {
     Layer &layer = layer_info.stack->layers[layer_info.index[i]];
     float bpp = GetBpp(layer.input_buffer->format);
-    uint32_t left_id = hw_layers->config[i].left_pipe.pipe_id;
-    uint32_t right_id = hw_layers->config[i].right_pipe.pipe_id;
+    HWPipeInfo *left_pipe = &hw_layers->config[i].left_pipe;
+    HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe;
 
-    left_pipe_bw[i] = left_id ? GetPipeBw(display_ctx, &hw_layers->config[i].left_pipe, bpp) : 0;
-    right_pipe_bw[i] = right_id ? GetPipeBw(display_ctx, &hw_layers->config[i].right_pipe, bpp) : 0;
+    left_pipe_bw[i] = left_pipe->valid ? GetPipeBw(display_ctx, left_pipe, bpp) : 0;
+    right_pipe_bw[i] = right_pipe->valid ? GetPipeBw(display_ctx, right_pipe, bpp) : 0;
 
     if ((left_pipe_bw[i] > max_pipe_bw) || (right_pipe_bw[i] > max_pipe_bw)) {
       DLOGV_IF(kTagResources, "Pipe bandwidth exceeds limit for layer index = %d", i);
       return false;
     }
 
-    float left_clk = left_id ? GetClockForPipe(display_ctx, &hw_layers->config[i].left_pipe) : 0;
-    float right_clk = right_id ? GetClockForPipe(display_ctx, &hw_layers->config[i].right_pipe) : 0;
+    float left_clk = left_pipe->valid ? GetClockForPipe(display_ctx, left_pipe) : 0;
+    float right_clk = right_pipe->valid ? GetClockForPipe(display_ctx, right_pipe) : 0;
 
     left_max_clk = MAX(left_clk, left_max_clk);
     right_max_clk = MAX(right_clk, right_max_clk);
@@ -556,12 +611,105 @@
   }
 }
 
-void ResManager::PostCommit(Handle display_ctx, HWLayers *hw_layers) {
+DisplayError ResManager::AllocRotatorBuffer(Handle display_ctx, HWLayers *hw_layers) {
+  DisplayResourceContext *display_resource_ctx =
+                          reinterpret_cast<DisplayResourceContext *>(display_ctx);
+  DisplayError error = kErrorNone;
+
+  BufferManager *buffer_manager = display_resource_ctx->buffer_manager;
+  HWLayersInfo &layer_info = hw_layers->info;
+
+  // TODO(user): Do session management during prepare and allocate buffer and associate that with
+  // the session during commit.
+  buffer_manager->Start();
+
+  for (uint32_t i = 0; i < layer_info.count; i++) {
+    Layer& layer = layer_info.stack->layers[layer_info.index[i]];
+    HWRotateInfo *rotate = &hw_layers->config[i].rotates[0];
+
+    if (rotate->valid) {
+      LayerBufferFormat rot_ouput_format;
+      SetRotatorOutputFormat(layer.input_buffer->format, false, true, &rot_ouput_format);
+
+      HWBufferInfo *hw_buffer_info = &rotate->hw_buffer_info;
+      hw_buffer_info->buffer_config.width = UINT32(rotate->dst_roi.right - rotate->dst_roi.left);
+      hw_buffer_info->buffer_config.height = UINT32(rotate->dst_roi.bottom - rotate->dst_roi.top);
+      hw_buffer_info->buffer_config.format = rot_ouput_format;
+      hw_buffer_info->buffer_config.buffer_count = 2;
+      hw_buffer_info->buffer_config.secure = layer.input_buffer->flags.secure;
+
+      error = buffer_manager->GetNextBuffer(hw_buffer_info);
+      if (error != kErrorNone) {
+        return error;
+      }
+    }
+
+    rotate = &hw_layers->config[i].rotates[1];
+    if (rotate->valid) {
+      LayerBufferFormat rot_ouput_format;
+      SetRotatorOutputFormat(layer.input_buffer->format, false, true, &rot_ouput_format);
+
+      HWBufferInfo *hw_buffer_info = &rotate->hw_buffer_info;
+      hw_buffer_info->buffer_config.width = UINT32(rotate->dst_roi.right - rotate->dst_roi.left);
+      hw_buffer_info->buffer_config.height = UINT32(rotate->dst_roi.bottom - rotate->dst_roi.top);
+      hw_buffer_info->buffer_config.format = rot_ouput_format;
+      hw_buffer_info->buffer_config.buffer_count = 2;
+      hw_buffer_info->buffer_config.secure = layer.input_buffer->flags.secure;
+
+      error = buffer_manager->GetNextBuffer(hw_buffer_info);
+      if (error != kErrorNone) {
+        return error;
+      }
+    }
+  }
+  buffer_manager->Stop(hw_layers->closed_session_ids);
+
+  return kErrorNone;
+}
+
+DisplayError ResManager::PostPrepare(Handle display_ctx, HWLayers *hw_layers) {
+  SCOPE_LOCK(locker_);
+  DisplayResourceContext *display_resource_ctx =
+                          reinterpret_cast<DisplayResourceContext *>(display_ctx);
+  DisplayError error = kErrorNone;
+
+  BufferManager *buffer_manager = display_resource_ctx->buffer_manager;
+  HWLayersInfo &layer_info = hw_layers->info;
+
+  for (uint32_t i = 0; i < layer_info.count; i++) {
+    Layer& layer = layer_info.stack->layers[layer_info.index[i]];
+    HWRotateInfo *rotate = &hw_layers->config[i].rotates[0];
+
+    if (rotate->valid) {
+      HWBufferInfo *hw_buffer_info = &rotate->hw_buffer_info;
+
+      error = buffer_manager->SetSessionId(hw_buffer_info->slot, hw_buffer_info->session_id);
+      if (error != kErrorNone) {
+        return error;
+      }
+    }
+
+    rotate = &hw_layers->config[i].rotates[1];
+    if (rotate->valid) {
+      HWBufferInfo *hw_buffer_info = &rotate->hw_buffer_info;
+
+      error = buffer_manager->SetSessionId(hw_buffer_info->slot, hw_buffer_info->session_id);
+      if (error != kErrorNone) {
+        return error;
+      }
+    }
+  }
+
+  return kErrorNone;
+}
+
+DisplayError ResManager::PostCommit(Handle display_ctx, HWLayers *hw_layers) {
   SCOPE_LOCK(locker_);
   DisplayResourceContext *display_resource_ctx =
                           reinterpret_cast<DisplayResourceContext *>(display_ctx);
   HWBlockType hw_block_id = display_resource_ctx->hw_block_id;
   uint64_t frame_count = display_resource_ctx->frame_count;
+  DisplayError error = kErrorNone;
 
   DLOGV_IF(kTagResources, "Resource for hw_block = %d, frame_count = %d", hw_block_id, frame_count);
 
@@ -609,6 +757,37 @@
     }
   }
   display_resource_ctx->frame_start = false;
+
+  BufferManager *buffer_manager = display_resource_ctx->buffer_manager;
+  HWLayersInfo &layer_info = hw_layers->info;
+
+  for (uint32_t i = 0; i < layer_info.count; i++) {
+    Layer& layer = layer_info.stack->layers[layer_info.index[i]];
+    HWRotateInfo *rotate = &hw_layers->config[i].rotates[0];
+
+    if (rotate->valid) {
+      HWBufferInfo *rot_buf_info = &rotate->hw_buffer_info;
+
+      error = buffer_manager->SetReleaseFd(rot_buf_info->slot,
+                                                rot_buf_info->output_buffer.release_fence_fd);
+      if (error != kErrorNone) {
+        return error;
+      }
+    }
+
+    rotate = &hw_layers->config[i].rotates[1];
+    if (rotate->valid) {
+      HWBufferInfo *rot_buf_info = &rotate->hw_buffer_info;
+
+      error = buffer_manager->SetReleaseFd(rot_buf_info->slot,
+                                                rot_buf_info->output_buffer.release_fence_fd);
+      if (error != kErrorNone) {
+        return error;
+      }
+    }
+  }
+
+  return kErrorNone;
 }
 
 void ResManager::Purge(Handle display_ctx) {
@@ -775,21 +954,33 @@
 void ResManager::AppendDump(char *buffer, uint32_t length) {
   SCOPE_LOCK(locker_);
   AppendString(buffer, length, "\nresource manager pipe state");
-  for (uint32_t i = 0; i < num_pipe_; i++) {
+  uint32_t i;
+  for (i = 0; i < num_pipe_; i++) {
     SourcePipe *src_pipe = &src_pipes_[i];
     AppendString(buffer, length,
                  "\nindex = %d, id = %x, reserved = %d, state = %d, hw_block = %d, dedicated = %d",
                  src_pipe->index, src_pipe->mdss_pipe_id, src_pipe->reserved_hw_block,
                  src_pipe->state, src_pipe->hw_block_id, src_pipe->dedicated_hw_block);
   }
+
+  for (i = 0; i < hw_res_info_.num_rotator; i++) {
+    if (rotators_[i].client_bit_mask || rotators_[i].request_bit_mask) {
+      AppendString(buffer, length,
+                   "\nrotator = %d, pipe index = %x, client_bit_mask = %x, request_bit_mask = %x",
+                   i, rotators_[i].pipe_index, rotators_[i].client_bit_mask,
+                   rotators_[i].request_bit_mask);
+    }
+  }
 }
 
 DisplayError ResManager::AcquireRotator(DisplayResourceContext *display_resource_ctx,
                                         const uint32_t rotate_count) {
   if (rotate_count == 0)
     return kErrorNone;
-  if (hw_res_info_.num_rotator == 0)
+  if (hw_res_info_.num_rotator == 0) {
+    DLOGV_IF(kTagResources, "Rotator hardware is not available");
     return kErrorResources;
+  }
 
   uint32_t i, j, pipe_index, num_rotator;
   if (rotate_count > hw_res_info_.num_rotator)
@@ -830,7 +1021,7 @@
 }
 
 void ResManager::AssignRotator(HWRotateInfo *rotate, uint32_t *rotate_count) {
-  if (!rotate->pipe_id)
+  if (!rotate->valid)
     return;
   // Interleave rotator assignment
   if ((*rotate_count & 0x1) && (hw_res_info_.num_rotator > 1)) {
@@ -859,5 +1050,45 @@
   }
 }
 
+void ResManager::SetRotatorOutputFormat(const LayerBufferFormat &input_format, bool bwc, bool rot90,
+                                        LayerBufferFormat *output_format) {
+  switch (input_format) {
+  case kFormatRGB565:
+    if (rot90)
+      *output_format = kFormatRGB888;
+    else
+      *output_format = input_format;
+    break;
+  case kFormatRGBA8888:
+    if (bwc)
+      *output_format = kFormatBGRA8888;
+    else
+      *output_format = input_format;
+    break;
+  case kFormatYCbCr420SemiPlanarVenus:
+  case kFormatYCbCr420SemiPlanar:
+    if (rot90)
+      *output_format = kFormatYCrCb420SemiPlanar;
+    else
+      *output_format = input_format;
+    break;
+  case kFormatYCbCr420Planar:
+  case kFormatYCrCb420Planar:
+    *output_format = kFormatYCrCb420SemiPlanar;
+    break;
+  default:
+    *output_format = input_format;
+    break;
+  }
+
+  DLOGV_IF(kTagResources, "Input format %x, Output format = %x, rot90 %d", input_format,
+           *output_format, rot90);
+
+  return;
+}
+
+void* ResManager::lib_scalar_handle_ = NULL;
+int (*ResManager::ScalarConfigureScale)(struct scalar::LayerInfo* layer) = NULL;
+
 }  // namespace sde
 
diff --git a/displayengine/libs/core/res_manager.h b/displayengine/libs/core/res_manager.h
index cf0a55f..c80dc2c 100644
--- a/displayengine/libs/core/res_manager.h
+++ b/displayengine/libs/core/res_manager.h
@@ -30,13 +30,15 @@
 
 #include "hw_interface.h"
 #include "dump_impl.h"
+#include "buffer_manager.h"
 
 namespace sde {
 
 class ResManager : public DumpImpl {
  public:
   ResManager();
-  DisplayError Init(const HWResourceInfo &hw_res_info);
+  DisplayError Init(const HWResourceInfo &hw_res_info, BufferAllocator *buffer_allocator,
+                    BufferSyncHandler *buffer_sync_handler);
   DisplayError Deinit();
   DisplayError RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
                                Handle *display_ctx);
@@ -44,7 +46,8 @@
   DisplayError Start(Handle display_ctx);
   DisplayError Stop(Handle display_ctx);
   DisplayError Acquire(Handle display_ctx, HWLayers *hw_layers);
-  void PostCommit(Handle display_ctx, HWLayers *hw_layers);
+  DisplayError PostPrepare(Handle display_ctx, HWLayers *hw_layers);
+  DisplayError PostCommit(Handle display_ctx, HWLayers *hw_layers);
   void Purge(Handle display_ctx);
 
   // DumpImpl method
@@ -111,14 +114,23 @@
 
   struct DisplayResourceContext {
     HWDisplayAttributes display_attributes;
+    BufferManager *buffer_manager;
     DisplayType display_type;
     HWBlockType hw_block_id;
     uint64_t frame_count;
     int32_t session_id;  // applicable for virtual display sessions only
     uint32_t rotate_count;
     bool frame_start;
+
     DisplayResourceContext() : hw_block_id(kHWBlockMax), frame_count(0), session_id(-1),
                     rotate_count(0), frame_start(false) { }
+
+    ~DisplayResourceContext() {
+      if (buffer_manager) {
+        delete buffer_manager;
+        buffer_manager = NULL;
+      }
+    }
   };
 
   struct HWBlockContext {
@@ -175,33 +187,17 @@
   bool IsYuvFormat(LayerBufferFormat format) { return (format >= kFormatYCbCr420Planar); }
   bool IsRotationNeeded(float rotation)
          { return (UINT32(rotation) == 90 || UINT32(rotation) == 270); }
-  void LogRectVerbose(const char *prefix, const LayerRect &roi);
   void RotationConfig(const LayerTransform &transform, const float &scale_x,
-                      const float &scale_y,LayerRect *src_rect,
+                      const float &scale_y, LayerRect *src_rect,
                       struct HWLayerConfig *layer_config, uint32_t *rotate_count);
   DisplayError AcquireRotator(DisplayResourceContext *display_resource_ctx,
                               const uint32_t roate_cnt);
   void AssignRotator(HWRotateInfo *rotate, uint32_t *rotate_cnt);
   void ClearRotator(DisplayResourceContext *display_resource_ctx);
-  void NormalizeRect(const uint32_t &factor, LayerRect *rect);
-
-  template <class T>
-  inline void Swap(T &a, T &b) {
-    T c(a);
-    a = b;
-    b = c;
-  }
-
-  // factor value should be in powers of 2(eg: 1, 2, 4, 8)
-  template <class T1, class T2>
-  inline T1 FloorToMultipleOf(const T1 &value, const T2 &factor) {
-    return (T1)(value & (~(factor - 1)));
-  }
-
-  template <class T1, class T2>
-  inline T1 CeilToMultipleOf(const T1 &value, const T2 &factor) {
-    return (T1)((value + (factor - 1)) & (~(factor - 1)));
-  }
+  DisplayError AllocRotatorBuffer(Handle display_ctx, HWLayers *hw_layers);
+  void SetRotatorOutputFormat(const LayerBufferFormat &input_format, bool bwc, bool rot90,
+                              LayerBufferFormat *output_format);
+  bool ConfigureScaling(HWLayers *hw_layers);
 
   Locker locker_;
   HWResourceInfo hw_res_info_;
@@ -217,6 +213,11 @@
   float last_primary_bw_;
   uint32_t virtual_count_;
   struct HWRotator rotators_[kMaxNumRotator];
+  BufferAllocator *buffer_allocator_;
+  BufferSyncHandler *buffer_sync_handler_;  // Pointer to buffer sync handler that was defined by
+                                            // the display engine's client
+  static void* lib_scalar_handle_;  // Scalar library handle
+  static int (*ScalarConfigureScale)(struct scalar::LayerInfo* layer);
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/hwc/Android.mk b/displayengine/libs/hwc/Android.mk
old mode 100755
new mode 100644
index 1271e00..d31c71e
--- a/displayengine/libs/hwc/Android.mk
+++ b/displayengine/libs/hwc/Android.mk
@@ -6,17 +6,20 @@
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := hardware/qcom/display/displayengine/include/ \
                                  hardware/qcom/display/libgralloc/ \
-                                 hardware/qcom/display/libqservice/
+                                 hardware/qcom/display/libqservice/ \
+                                 hardware/qcom/display/libqdutils/
 LOCAL_CFLAGS                  := -Wno-missing-field-initializers -Wno-unused-parameter \
                                  -Wconversion -Wall -Werror \
                                  -DLOG_TAG=\"SDE\"
 LOCAL_SHARED_LIBRARIES        := libsde libqservice libbinder libhardware libhardware_legacy \
-                                 libutils libcutils
+                                 libutils libcutils libsync libmemalloc libqdutils
 LOCAL_SRC_FILES               := hwc_session.cpp \
                                  hwc_display.cpp \
                                  hwc_display_primary.cpp \
                                  hwc_display_external.cpp \
                                  hwc_display_virtual.cpp \
-                                 hwc_logger.cpp
+                                 hwc_debugger.cpp \
+                                 hwc_buffer_allocator.cpp \
+                                 hwc_buffer_sync_handler.cpp
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/displayengine/libs/hwc/hwc_buffer_allocator.cpp b/displayengine/libs/hwc/hwc_buffer_allocator.cpp
new file mode 100644
index 0000000..d4f4bac
--- /dev/null
+++ b/displayengine/libs/hwc/hwc_buffer_allocator.cpp
@@ -0,0 +1,171 @@
+/*
+* Copyright (c) 2015, 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.
+*/
+
+#include <gralloc_priv.h>
+#include <memalloc.h>
+#include <gr.h>
+#include <alloc_controller.h>
+#include <utils/constants.h>
+#include <core/buffer_allocator.h>
+
+#include "hwc_debugger.h"
+#include "hwc_buffer_allocator.h"
+
+#define __CLASS__ "HWCBufferAllocator"
+
+namespace sde {
+
+HWCBufferAllocator::HWCBufferAllocator() {
+  alloc_controller_ = gralloc::IAllocController::getInstance();
+}
+
+DisplayError HWCBufferAllocator::AllocateBuffer(BufferInfo *buffer_info) {
+  gralloc::alloc_data data;
+
+  const BufferConfig &buffer_config = buffer_info->buffer_config;
+  AllocatedBufferInfo *alloc_buffer_info = &buffer_info->alloc_buffer_info;
+  MetaBufferInfo *meta_buffer_info = new MetaBufferInfo();
+
+  if (!meta_buffer_info) {
+    return kErrorMemory;
+  }
+
+  int alloc_flags = GRALLOC_USAGE_PRIVATE_IOMMU_HEAP;
+  int error = 0;
+
+  int width = INT(buffer_config.width);
+  int height = INT(buffer_config.height);
+  int format;
+
+  error = SetHALFormat(buffer_config.format, &format);
+  if (error != 0) {
+    return kErrorParameters;
+  }
+
+  if (buffer_config.secure) {
+    alloc_flags = GRALLOC_USAGE_PRIVATE_MM_HEAP;
+    alloc_flags |= GRALLOC_USAGE_PROTECTED;
+    data.align = kSecureBufferAlignment;
+  } else {
+    data.align = getpagesize();
+  }
+
+  if (buffer_config.cache == false) {
+    // Allocate uncached buffers
+    alloc_flags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
+  }
+
+  int aligned_width = 0, aligned_height = 0;
+  uint32_t buffer_size = getBufferSizeAndDimensions(width, height, format, alloc_flags,
+                                                    aligned_width, aligned_height);
+
+  buffer_size = ROUND_UP((buffer_size * buffer_config.buffer_count), data.align);
+
+  data.base = 0;
+  data.fd = -1;
+  data.offset = 0;
+  data.size = buffer_size;
+  data.uncached = !buffer_config.cache;
+
+  error = alloc_controller_->allocate(data, alloc_flags);
+  if (error != 0) {
+    DLOGE("Error allocating memory size %d uncached %d", data.size, data.uncached);
+    return kErrorMemory;
+  }
+
+  alloc_buffer_info->fd = data.fd;
+  alloc_buffer_info->stride = aligned_width;
+  alloc_buffer_info->size = buffer_size;
+
+  meta_buffer_info->base_addr = data.base;
+  meta_buffer_info->alloc_type = data.allocType;
+
+  buffer_info->private_data = meta_buffer_info;
+
+  return kErrorNone;
+}
+
+DisplayError HWCBufferAllocator::FreeBuffer(BufferInfo *buffer_info) {
+  int ret = 0;
+
+  AllocatedBufferInfo *alloc_buffer_info = &buffer_info->alloc_buffer_info;
+  MetaBufferInfo *meta_buffer_info = static_cast<MetaBufferInfo *> (buffer_info->private_data);
+  if ((alloc_buffer_info->fd < 0) || (meta_buffer_info->base_addr == NULL)) {
+    return kErrorNone;
+  }
+
+  gralloc::IMemAlloc *memalloc = alloc_controller_->getAllocator(meta_buffer_info->alloc_type);
+  if (memalloc == NULL) {
+    DLOGE("Memalloc handle is NULL, alloc type %d", meta_buffer_info->alloc_type);
+    return kErrorResources;
+  }
+
+  ret = memalloc->free_buffer(meta_buffer_info->base_addr, alloc_buffer_info->size, 0,
+                              alloc_buffer_info->fd);
+  if (ret != 0) {
+    DLOGE("Error freeing buffer base_addr %p size %d fd %d", meta_buffer_info->base_addr,
+          alloc_buffer_info->size, alloc_buffer_info->fd);
+    return kErrorMemory;
+  }
+
+  alloc_buffer_info->fd = -1;
+  alloc_buffer_info->stride = 0;
+  alloc_buffer_info->size = 0;
+
+  meta_buffer_info->base_addr = NULL;
+  meta_buffer_info->alloc_type = 0;
+
+  delete meta_buffer_info;
+  meta_buffer_info = NULL;
+
+  return kErrorNone;
+}
+
+int HWCBufferAllocator::SetHALFormat(LayerBufferFormat format, int *target) {
+  switch (format) {
+  case kFormatRGBA8888:                 *target = HAL_PIXEL_FORMAT_RGBA_8888;             break;
+  case kFormatRGBX8888:                 *target = HAL_PIXEL_FORMAT_RGBX_8888;             break;
+  case kFormatRGB888:                   *target = HAL_PIXEL_FORMAT_RGB_888;               break;
+  case kFormatRGB565:                   *target = HAL_PIXEL_FORMAT_RGB_565;               break;
+  case kFormatBGRA8888:                 *target = HAL_PIXEL_FORMAT_BGRA_8888;             break;
+  case kFormatYCrCb420Planar:           *target = HAL_PIXEL_FORMAT_YV12;                  break;
+  case kFormatYCrCb420SemiPlanar:       *target = HAL_PIXEL_FORMAT_YCrCb_420_SP;          break;
+  case kFormatYCbCr420SemiPlanar:       *target = HAL_PIXEL_FORMAT_YCbCr_420_SP;          break;
+  case kFormatYCbCr422Packed:           *target = HAL_PIXEL_FORMAT_YCbCr_422_I;           break;
+  case kFormatYCbCr420SemiPlanarVenus:  *target = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS;    break;
+
+  default:
+    DLOGE("Unsupported format = 0x%x", format);
+    return -EINVAL;
+  }
+
+  return 0;
+}
+
+}  // namespace sde
diff --git a/displayengine/libs/hwc/hwc_buffer_allocator.h b/displayengine/libs/hwc/hwc_buffer_allocator.h
new file mode 100644
index 0000000..123f04a
--- /dev/null
+++ b/displayengine/libs/hwc/hwc_buffer_allocator.h
@@ -0,0 +1,67 @@
+/*
+* Copyright (c) 2015, 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.
+*/
+
+
+#ifndef __HWC_BUFFER_ALLOCATOR_H__
+#define __HWC_BUFFER_ALLOCATOR_H__
+
+#include <sys/mman.h>
+#include <fcntl.h>
+
+namespace gralloc {
+
+class IAllocController;
+
+}  // namespace gralloc
+
+namespace sde {
+
+class HWCBufferAllocator : public BufferAllocator {
+ public:
+  HWCBufferAllocator();
+
+  DisplayError AllocateBuffer(BufferInfo *buffer_info);
+  DisplayError FreeBuffer(BufferInfo *buffer_info);
+
+ private:
+  static const size_t kSecureBufferAlignment = 0x00100000;
+
+  struct MetaBufferInfo {
+    int alloc_type;              //!< Specifies allocation type set by the buffer allocator.
+    void *base_addr;             //!< Specifies the base address of the allocated output buffer.
+  };
+
+  int SetHALFormat(LayerBufferFormat format, int *target);
+
+  gralloc::IAllocController *alloc_controller_;
+};
+
+}  // namespace sde
+#endif  // __HWC_BUFFER_ALLOCATOR_H__
+
diff --git a/displayengine/libs/hwc/hwc_buffer_sync_handler.cpp b/displayengine/libs/hwc/hwc_buffer_sync_handler.cpp
new file mode 100644
index 0000000..31788ea
--- /dev/null
+++ b/displayengine/libs/hwc/hwc_buffer_sync_handler.cpp
@@ -0,0 +1,71 @@
+/*
+* Copyright (c) 2015, 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.
+*/
+
+#include <sync/sync.h>
+#include <utils/constants.h>
+
+#include "hwc_debugger.h"
+#include "hwc_buffer_sync_handler.h"
+
+#define __CLASS__ "HWCBufferSyncHandler"
+
+namespace sde {
+
+DisplayError HWCBufferSyncHandler::SyncWait(int fd) {
+  int error = 0;
+
+  if (fd >= 0) {
+    error = sync_wait(fd, 1000);
+    if (error < 0) {
+      DLOGE("sync_wait error errno = %d, desc = %s", errno,  strerror(errno));
+      close(fd);
+      return kErrorTimeOut;
+    }
+    close(fd);
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWCBufferSyncHandler::SyncMerge(int fd1, int fd2, int *merged_fd) {
+  DisplayError error = kErrorNone;
+
+  *merged_fd = sync_merge("SyncMerge", fd1, fd2);
+  if (*merged_fd == -1) {
+    DLOGE(" Sync merge error! fd1 %d fd2 %d", fd1, fd2);
+    error = kErrorFileDescriptor;
+  }
+  close(fd1);
+  close(fd2);
+
+  return error;
+}
+
+}  // namespace sde
+
diff --git a/displayengine/libs/hwc/hwc_buffer_sync_handler.h b/displayengine/libs/hwc/hwc_buffer_sync_handler.h
new file mode 100644
index 0000000..26b1d33
--- /dev/null
+++ b/displayengine/libs/hwc/hwc_buffer_sync_handler.h
@@ -0,0 +1,52 @@
+/*
+* Copyright (c) 2015, 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.
+*/
+
+
+#ifndef __HWC_BUFFER_SYNC_HANDLER_H__
+#define __HWC_BUFFER_SYNC_HANDLER_H__
+
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <core/sde_types.h>
+#include <core/buffer_sync_handler.h>
+
+namespace sde {
+
+class HWCBufferSyncHandler : public BufferSyncHandler {
+ public:
+  HWCBufferSyncHandler() { }
+
+  virtual DisplayError SyncWait(int fd);
+  virtual DisplayError SyncMerge(int fd1, int fd2, int *merged_fd);
+};
+
+}  // namespace sde
+#endif  // __HWC_BUFFER_SYNC_HANDLER_H__
+
+
diff --git a/displayengine/libs/hwc/hwc_debugger.cpp b/displayengine/libs/hwc/hwc_debugger.cpp
new file mode 100644
index 0000000..d35e9cf
--- /dev/null
+++ b/displayengine/libs/hwc/hwc_debugger.cpp
@@ -0,0 +1,135 @@
+/*
+* Copyright (c) 2014 - 2015, 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.
+*/
+
+#include <utils/constants.h>
+
+#include "hwc_debugger.h"
+
+namespace sde {
+
+HWCDebugHandler HWCDebugHandler::debug_handler_;
+uint32_t HWCDebugHandler::debug_flags_ = 0x1;
+
+void HWCDebugHandler::DebugAll(bool enable) {
+  if (enable) {
+    debug_flags_ = 0xFFFFFFFF;
+  } else {
+    debug_flags_ = 0x1;   // kTagNone should always be printed.
+  }
+}
+
+void HWCDebugHandler::DebugResources(bool enable) {
+  if (enable) {
+    SET_BIT(debug_flags_, kTagResources);
+  } else {
+    CLEAR_BIT(debug_flags_, kTagResources);
+  }
+}
+
+void HWCDebugHandler::DebugStrategy(bool enable) {
+  if (enable) {
+    SET_BIT(debug_flags_, kTagStrategy);
+  } else {
+    CLEAR_BIT(debug_flags_, kTagStrategy);
+  }
+}
+
+void HWCDebugHandler::DebugCompManager(bool enable) {
+  if (enable) {
+    SET_BIT(debug_flags_, kTagCompManager);
+  } else {
+    CLEAR_BIT(debug_flags_, kTagCompManager);
+  }
+}
+
+void HWCDebugHandler::DebugDriverConfig(bool enable) {
+  if (enable) {
+    SET_BIT(debug_flags_, kTagDriverConfig);
+  } else {
+    CLEAR_BIT(debug_flags_, kTagDriverConfig);
+  }
+}
+
+void HWCDebugHandler::DebugBufferManager(bool enable) {
+  if (enable) {
+    SET_BIT(debug_flags_, kTagBufferManager);
+  } else {
+    CLEAR_BIT(debug_flags_, kTagBufferManager);
+  }
+}
+
+void HWCDebugHandler::DebugOfflineCtrl(bool enable) {
+  if (enable) {
+    SET_BIT(debug_flags_, kTagOfflineCtrl);
+  } else {
+    CLEAR_BIT(debug_flags_, kTagOfflineCtrl);
+  }
+}
+
+void HWCDebugHandler::Error(DebugTag /*tag*/, const char *format, ...) {
+  va_list list;
+  va_start(list, format);
+  __android_log_vprint(ANDROID_LOG_ERROR, LOG_TAG, format, list);
+}
+
+void HWCDebugHandler::Warning(DebugTag /*tag*/, const char *format, ...) {
+  va_list list;
+  va_start(list, format);
+  __android_log_vprint(ANDROID_LOG_WARN, LOG_TAG, format, list);
+}
+
+void HWCDebugHandler::Info(DebugTag tag, const char *format, ...) {
+  if (IS_BIT_SET(debug_flags_, tag)) {
+    va_list list;
+    va_start(list, format);
+    __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, list);
+  }
+}
+
+void HWCDebugHandler::Verbose(DebugTag tag, const char *format, ...) {
+  if (IS_BIT_SET(debug_flags_, tag)) {
+    va_list list;
+    va_start(list, format);
+    __android_log_vprint(ANDROID_LOG_VERBOSE, LOG_TAG, format, list);
+  }
+}
+
+void HWCDebugHandler::BeginTrace(const char *class_name, const char *function_name,
+                                 const char *custom_string) {
+  char name[PATH_MAX] = {0};
+  snprintf(name, sizeof(name), "%s::%s::%s", class_name, function_name, custom_string);
+  atrace_begin(ATRACE_TAG, name);
+}
+
+void HWCDebugHandler::EndTrace() {
+  atrace_end(ATRACE_TAG);
+}
+
+}  // namespace sde
+
diff --git a/displayengine/libs/hwc/hwc_debugger.h b/displayengine/libs/hwc/hwc_debugger.h
new file mode 100644
index 0000000..def31db
--- /dev/null
+++ b/displayengine/libs/hwc/hwc_debugger.h
@@ -0,0 +1,81 @@
+/*
+* Copyright (c) 2014 - 2015, 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.
+*/
+
+#ifndef __HWC_DEBUGGER_H__
+#define __HWC_DEBUGGER_H__
+
+#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
+
+#include <core/sde_types.h>
+#include <core/debug_interface.h>
+#include <cutils/log.h>
+#include <utils/Trace.h>
+
+#define DLOG(Macro, format, ...) Macro(__CLASS__ "::%s: " format, __FUNCTION__, ##__VA_ARGS__)
+
+#define DLOGE(format, ...) DLOG(ALOGE, format, ##__VA_ARGS__)
+#define DLOGW(format, ...) DLOG(ALOGW, format, ##__VA_ARGS__)
+#define DLOGI(format, ...) DLOG(ALOGI, format, ##__VA_ARGS__)
+#define DLOGV(format, ...) DLOG(ALOGV, format, ##__VA_ARGS__)
+
+#define DTRACE_BEGIN(custom_string) HWCDebugHandler::Get()->BeginTrace(__CLASS__, __FUNCTION__, \
+                                                                       custom_string)
+#define DTRACE_END() HWCDebugHandler::Get()->EndTrace()
+#define DTRACE_SCOPED() ScopeTracer<HWCDebugHandler> scope_tracer(__CLASS__, __FUNCTION__)
+
+namespace sde {
+
+class HWCDebugHandler : public DebugHandler {
+ public:
+  static inline DebugHandler* Get() { return &debug_handler_; }
+  static void DebugAll(bool enable);
+  static void DebugResources(bool enable);
+  static void DebugStrategy(bool enable);
+  static void DebugCompManager(bool enable);
+  static void DebugDriverConfig(bool enable);
+  static void DebugBufferManager(bool enable);
+  static void DebugOfflineCtrl(bool enable);
+
+  virtual void Error(DebugTag tag, const char *format, ...);
+  virtual void Warning(DebugTag tag, const char *format, ...);
+  virtual void Info(DebugTag tag, const char *format, ...);
+  virtual void Verbose(DebugTag tag, const char *format, ...);
+  virtual void BeginTrace(const char *class_name, const char *function_name,
+                          const char *custom_string);
+  virtual void EndTrace();
+
+ private:
+  static HWCDebugHandler debug_handler_;
+  static uint32_t debug_flags_;
+};
+
+}  // namespace sde
+
+#endif  // __HWC_DEBUGGER_H__
+
diff --git a/displayengine/libs/hwc/hwc_display.cpp b/displayengine/libs/hwc/hwc_display.cpp
index bf54a8a..dd1beac 100644
--- a/displayengine/libs/hwc/hwc_display.cpp
+++ b/displayengine/libs/hwc/hwc_display.cpp
@@ -1,33 +1,40 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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.
+* 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.
+* 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.
 */
 
 #include <errno.h>
 #include <gralloc_priv.h>
 #include <utils/constants.h>
+#include <qdMetaData.h>
+#include <sync/sync.h>
 
 #include "hwc_display.h"
-#include "hwc_logger.h"
+#include "hwc_debugger.h"
 
 #define __CLASS__ "HWCDisplay"
 
@@ -35,13 +42,16 @@
 
 HWCDisplay::HWCDisplay(CoreInterface *core_intf, hwc_procs_t const **hwc_procs, DisplayType type,
                        int id)
-  : core_intf_(core_intf), hwc_procs_(hwc_procs), type_(type), id_(id), display_intf_(NULL) {
+  : core_intf_(core_intf), hwc_procs_(hwc_procs), type_(type), id_(id), display_intf_(NULL),
+    flush_(false), output_buffer_(NULL), dump_frame_count_(0), dump_frame_index_(0),
+    dump_input_layers_(false) {
 }
 
 int HWCDisplay::Init() {
   DisplayError error = core_intf_->CreateDisplay(type_, this, &display_intf_);
   if (UNLIKELY(error != kErrorNone)) {
-    DLOGE("Display create failed. Error = %d", error);
+    DLOGE("Display create failed. Error = %d display_type %d event_handler %p disp_intf %p",
+      error, type_, this, &display_intf_);
     return -EINVAL;
   }
 
@@ -55,8 +65,9 @@
     return -EINVAL;
   }
 
-  if (LIKELY(layer_stack_memory_.raw)) {
+  if (layer_stack_memory_.raw) {
     delete[] layer_stack_memory_.raw;
+    layer_stack_memory_.raw = NULL;
   }
 
   return 0;
@@ -173,6 +184,10 @@
   return index;
 }
 
+int HWCDisplay::SetActiveConfig(hwc_display_contents_1_t *content_list) {
+  return 0;
+}
+
 int HWCDisplay::SetActiveConfig(int index) {
   DisplayError error = kErrorNone;
 
@@ -185,6 +200,14 @@
   return 0;
 }
 
+void HWCDisplay::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
+  dump_frame_count_ = count;
+  dump_frame_index_ = 0;
+  dump_input_layers_ = ((bit_mask_layer_type & (1 << INPUT_LAYER_DUMP)) != 0);
+
+  DLOGI("num_frame_dump %d, input_layer_dump_enable %d", dump_frame_count_, dump_input_layers_);
+}
+
 DisplayError HWCDisplay::VSync(const DisplayEventVSync &vsync) {
   if (*hwc_procs_) {
     (*hwc_procs_)->vsync(*hwc_procs_, id_, vsync.timestamp);
@@ -282,6 +305,7 @@
 
   size_t num_hw_layers = content_list->numHwLayers;
   if (num_hw_layers <= 1) {
+    flush_ = true;
     return 0;
   }
 
@@ -294,7 +318,8 @@
     LayerBuffer *layer_buffer = layer.input_buffer;
 
     if (pvt_handle) {
-      if (SetFormat(pvt_handle->format, &layer_buffer->format)) {
+      layer_buffer->format = GetSDEFormat(pvt_handle->format, pvt_handle->flags);
+      if (layer_buffer->format == kFormatInvalid) {
         return -EINVAL;
       }
 
@@ -308,6 +333,13 @@
         layer_stack_.flags.secure_present = true;
         layer_buffer->flags.secure = true;
       }
+
+      // TODO(user) : Initialize it to display refresh rate
+      layer.frame_rate = 60;
+      MetaData_t *meta_data = reinterpret_cast<MetaData_t *>(pvt_handle->base_metadata);
+      if (meta_data && meta_data->operation & UPDATE_REFRESH_RATE) {
+        layer.frame_rate = meta_data->refreshrate;
+      }
     }
 
     SetRect(hwc_layer.displayFrame, &layer.dst_rect);
@@ -329,6 +361,10 @@
     layer.flags.skip = ((hwc_layer.flags & HWC_SKIP_LAYER) > 0);
     layer.flags.updating = (layer_stack_cache_.layer_cache[i].handle != hwc_layer.handle);
 
+    if (hwc_layer.flags & HWC_SCREENSHOT_ANIMATOR_LAYER) {
+      layer_stack_.flags.animating = true;
+    }
+
     if (layer.flags.skip) {
       layer_stack_.flags.skip_present = true;
     }
@@ -338,9 +374,14 @@
   layer_stack_.flags.geometry_changed = ((content_list->flags & HWC_GEOMETRY_CHANGED) > 0);
 
   DisplayError error = display_intf_->Prepare(&layer_stack_);
-  if (UNLIKELY(error != kErrorNone)) {
+  if (error != kErrorNone) {
     DLOGE("Prepare failed. Error = %d", error);
-    return -EINVAL;
+
+    // To prevent surfaceflinger infinite wait, flush the previous frame during Commit() so that
+    // previous buffer and fences are released, and override the error.
+    flush_ = true;
+
+    return 0;
   }
 
   bool needs_fb_refresh = NeedsFrameBufferRefresh(content_list);
@@ -378,38 +419,46 @@
   int status = 0;
 
   size_t num_hw_layers = content_list->numHwLayers;
-  if (num_hw_layers <= 1) {
-    if (!num_hw_layers) {
-      return 0;
+
+  DumpInputBuffers(content_list);
+
+  if (!flush_) {
+    for (size_t i = 0; i < num_hw_layers; i++) {
+      hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
+      const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer.handle);
+      LayerBuffer *layer_buffer = layer_stack_.layers[i].input_buffer;
+
+      if (pvt_handle) {
+        layer_buffer->planes[0].fd = pvt_handle->fd;
+        layer_buffer->planes[0].offset = pvt_handle->offset;
+        layer_buffer->planes[0].stride = pvt_handle->width;
+      }
+
+      layer_buffer->acquire_fence_fd = hwc_layer.acquireFenceFd;
     }
 
-    // TODO(user): handle if only 1 layer(fb target) is received.
-    int &acquireFenceFd = content_list->hwLayers[0].acquireFenceFd;
-    if (acquireFenceFd >= 0) {
-      close(acquireFenceFd);
-    }
+    DisplayError error = display_intf_->Commit(&layer_stack_);
+    if (error != kErrorNone) {
+      DLOGE("Commit failed. Error = %d", error);
 
-    return 0;
+      // To prevent surfaceflinger infinite wait, flush the previous frame during Commit() so that
+      // previous buffer and fences are released, and override the error.
+      flush_ = true;
+    }
   }
 
-  for (size_t i = 0; i < num_hw_layers; i++) {
-    hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
-    const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer.handle);
-    LayerBuffer *layer_buffer = layer_stack_.layers[i].input_buffer;
+  return status;
+}
 
-    if (pvt_handle) {
-      layer_buffer->planes[0].fd = pvt_handle->fd;
-      layer_buffer->planes[0].offset = pvt_handle->offset;
-      layer_buffer->planes[0].stride = pvt_handle->width;
+int HWCDisplay::PostCommitLayerStack(hwc_display_contents_1_t *content_list) {
+  size_t num_hw_layers = content_list->numHwLayers;
+  int status = 0;
+
+  if (flush_) {
+    DisplayError error = display_intf_->Flush();
+    if (error != kErrorNone) {
+      DLOGE("Flush failed. Error = %d", error);
     }
-
-    layer_buffer->acquire_fence_fd = hwc_layer.acquireFenceFd;
-  }
-
-  DisplayError error = display_intf_->Commit(&layer_stack_);
-  if (UNLIKELY(error != kErrorNone)) {
-    DLOGE("Commit failed. Error = %d", error);
-    status = -EINVAL;
   }
 
   for (size_t i = 0; i < num_hw_layers; i++) {
@@ -417,19 +466,45 @@
     Layer &layer = layer_stack_.layers[i];
     LayerBuffer *layer_buffer = layer_stack_.layers[i].input_buffer;
 
-    if ((status == 0) && (layer.composition == kCompositionSDE ||
-                         layer.composition == kCompositionGPUTarget)) {
-      hwc_layer.releaseFenceFd = layer_buffer->release_fence_fd;
+    if (!flush_) {
+      if (layer.composition != kCompositionGPU) {
+        hwc_layer.releaseFenceFd = layer_buffer->release_fence_fd;
+      }
+
+      // During animation on external/virtual display, Display Engine will use the cached
+      // framebuffer layer throughout animation and do not allow framework to do eglswapbuffer on
+      // framebuffer target. So graphics doesn't close the release fence fd of framebuffer target,
+      // Hence close the release fencefd of framebuffer target here.
+      if (layer.composition == kCompositionGPUTarget && layer_stack_cache_.animating) {
+        close(hwc_layer.releaseFenceFd);
+        hwc_layer.releaseFenceFd = -1;
+      }
     }
 
     if (hwc_layer.acquireFenceFd >= 0) {
       close(hwc_layer.acquireFenceFd);
+      hwc_layer.acquireFenceFd = -1;
     }
   }
 
+
+  if (!flush_) {
+    layer_stack_cache_.animating = layer_stack_.flags.animating;
+
+    content_list->retireFenceFd = layer_stack_.retire_fence_fd;
+
+    if (dump_frame_count_) {
+      dump_frame_count_--;
+      dump_frame_index_++;
+    }
+  }
+
+  flush_ = false;
+
   return status;
 }
 
+
 bool HWCDisplay::NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list) {
   uint32_t layer_count = layer_stack_.layer_count;
 
@@ -438,8 +513,8 @@
   // 2. Any layer is added/removed/layer properties changes in the current layer stack.
   // 3. Any layer handle is changed and it is marked for GPU composition
   // 4. Any layer's current composition is different from previous composition.
-  if ((layer_stack_cache_.layer_count != layer_count) || layer_stack_.flags.skip_present ||
-       layer_stack_.flags.geometry_changed) {
+  if (((layer_stack_cache_.layer_count != layer_count) || layer_stack_.flags.skip_present ||
+      layer_stack_.flags.geometry_changed) && !layer_stack_cache_.animating) {
     return true;
   }
 
@@ -456,7 +531,8 @@
       return true;
     }
 
-    if ((layer.composition == kCompositionGPU) && (layer_cache.handle != hwc_layer.handle)) {
+    if ((layer.composition == kCompositionGPU) && (layer_cache.handle != hwc_layer.handle) &&
+        !layer_stack_cache_.animating) {
       return true;
     }
   }
@@ -518,21 +594,159 @@
   }
 }
 
-int HWCDisplay::SetFormat(const int32_t &source, LayerBufferFormat *target) {
-  switch (source) {
-  case HAL_PIXEL_FORMAT_RGBA_8888:            *target = kFormatRGBA8888;                  break;
-  case HAL_PIXEL_FORMAT_BGRA_8888:            *target = kFormatBGRA8888;                  break;
-  case HAL_PIXEL_FORMAT_RGBX_8888:            *target = kFormatRGBX8888;                  break;
-  case HAL_PIXEL_FORMAT_BGRX_8888:            *target = kFormatBGRX8888;                  break;
-  case HAL_PIXEL_FORMAT_RGB_888:              *target = kFormatRGB888;                    break;
-  case HAL_PIXEL_FORMAT_RGB_565:              *target = kFormatRGB565;                    break;
-  case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:   *target = kFormatYCbCr420SemiPlanarVenus;   break;
-  default:
-    DLOGW("Unsupported format type = %d", source);
-    return -EINVAL;
+void HWCDisplay::SetIdleTimeoutMs(uint32_t timeout_ms) {
+  if (display_intf_) {
+    display_intf_->SetIdleTimeoutMs(timeout_ms);
+  }
+}
+
+LayerBufferFormat HWCDisplay::GetSDEFormat(const int32_t &source, const int flags) {
+  LayerBufferFormat format = kFormatInvalid;
+  if (flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
+    switch (source) {
+    case HAL_PIXEL_FORMAT_RGBA_8888:          format = kFormatRGBA8888Ubwc;            break;
+    case HAL_PIXEL_FORMAT_RGB_565:            format = kFormatRGB565Ubwc;              break;
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+    case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:    format = kFormatYCbCr420SPVenusUbwc;     break;
+    default:
+      DLOGE("Unsupported format type for UBWC %d", source);
+      return kFormatInvalid;
+    }
+    return format;
   }
 
-  return 0;
+  switch (source) {
+  case HAL_PIXEL_FORMAT_RGBA_8888:                format = kFormatRGBA8888;                 break;
+  case HAL_PIXEL_FORMAT_BGRA_8888:                format = kFormatBGRA8888;                 break;
+  case HAL_PIXEL_FORMAT_RGBX_8888:                format = kFormatRGBX8888;                 break;
+  case HAL_PIXEL_FORMAT_BGRX_8888:                format = kFormatBGRX8888;                 break;
+  case HAL_PIXEL_FORMAT_RGB_888:                  format = kFormatRGB888;                   break;
+  case HAL_PIXEL_FORMAT_RGB_565:                  format = kFormatRGB565;                   break;
+  case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+  case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:       format = kFormatYCbCr420SemiPlanarVenus;  break;
+  case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:  format = kFormatYCbCr420SPVenusUbwc;      break;
+  case HAL_PIXEL_FORMAT_YCrCb_420_SP:             format = kFormatYCrCb420SemiPlanar;       break;
+  default:
+    DLOGW("Unsupported format type = %d", source);
+    return kFormatInvalid;
+  }
+
+  return format;
+}
+
+void HWCDisplay::DumpInputBuffers(hwc_display_contents_1_t *content_list) {
+  size_t num_hw_layers = content_list->numHwLayers;
+  char dir_path[PATH_MAX];
+
+  if (!dump_frame_count_ || flush_ || !dump_input_layers_) {
+    return;
+  }
+
+  snprintf(dir_path, sizeof(dir_path), "/data/misc/display/frame_dump_%s", GetDisplayString());
+
+  if (mkdir(dir_path, 0777) != 0 && errno != EEXIST) {
+    DLOGW("Failed to create %s directory errno = %d, desc = %s", dir_path, errno, strerror(errno));
+    return;
+  }
+
+  // if directory exists already, need to explicitly change the permission.
+  if (errno == EEXIST && chmod(dir_path, 0777) != 0) {
+    DLOGW("Failed to change permissions on %s directory", dir_path);
+    return;
+  }
+
+  for (uint32_t i = 0; i < num_hw_layers; i++) {
+    hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
+    const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer.handle);
+
+    if (hwc_layer.acquireFenceFd >= 0) {
+      int error = sync_wait(hwc_layer.acquireFenceFd, 1000);
+      if (error < 0) {
+        DLOGW("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
+        return;
+      }
+    }
+
+    if (pvt_handle && pvt_handle->base) {
+      char dump_file_name[PATH_MAX];
+      size_t result = 0;
+
+      snprintf(dump_file_name, sizeof(dump_file_name), "%s/input_layer%d_%dx%d_%s_frame%d.raw",
+               dir_path, i, pvt_handle->width, pvt_handle->height,
+               GetHALPixelFormatString(pvt_handle->format), dump_frame_index_);
+
+      FILE* fp = fopen(dump_file_name, "w+");
+      if (fp) {
+        result = fwrite(reinterpret_cast<void *>(pvt_handle->base), pvt_handle->size, 1, fp);
+        fclose(fp);
+      }
+
+      DLOGI("Frame Dump %s: is %s", dump_file_name, result ? "Successful" : "Failed");
+    }
+  }
+}
+
+const char *HWCDisplay::GetHALPixelFormatString(int format) {
+  switch (format) {
+  case HAL_PIXEL_FORMAT_RGBA_8888:
+    return "RGBA_8888";
+  case HAL_PIXEL_FORMAT_RGBX_8888:
+    return "RGBX_8888";
+  case HAL_PIXEL_FORMAT_RGB_888:
+    return "RGB_888";
+  case HAL_PIXEL_FORMAT_RGB_565:
+    return "RGB_565";
+  case HAL_PIXEL_FORMAT_BGRA_8888:
+    return "BGRA_8888";
+  case HAL_PIXEL_FORMAT_RGBA_5551:
+    return "RGBA_5551";
+  case HAL_PIXEL_FORMAT_RGBA_4444:
+    return "RGBA_4444";
+  case HAL_PIXEL_FORMAT_YV12:
+    return "YV12";
+  case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+    return "YCbCr_422_SP_NV16";
+  case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+    return "YCrCb_420_SP_NV21";
+  case HAL_PIXEL_FORMAT_YCbCr_422_I:
+    return "YCbCr_422_I_YUY2";
+  case HAL_PIXEL_FORMAT_YCrCb_422_I:
+    return "YCrCb_422_I_YVYU";
+  case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+    return "NV12_ENCODEABLE";
+  case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+    return "YCbCr_420_SP_TILED_TILE_4x2";
+  case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+    return "YCbCr_420_SP";
+  case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
+    return "YCrCb_420_SP_ADRENO";
+  case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+    return "YCrCb_422_SP";
+  case HAL_PIXEL_FORMAT_R_8:
+    return "R_8";
+  case HAL_PIXEL_FORMAT_RG_88:
+    return "RG_88";
+  case HAL_PIXEL_FORMAT_INTERLACE:
+    return "INTERLACE";
+  case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+    return "YCbCr_420_SP_VENUS";
+  default:
+    return "Unknown pixel format";
+  }
+}
+
+const char *HWCDisplay::GetDisplayString() {
+  switch (type_) {
+  case kPrimary:
+    return "primary";
+  case kHDMI:
+    return "hdmi";
+  case kVirtual:
+    return "virtual";
+  default:
+    return "invalid";
+  }
 }
 
 }  // namespace sde
diff --git a/displayengine/libs/hwc/hwc_display.h b/displayengine/libs/hwc/hwc_display.h
index 0ba9ca7..a574d6b 100644
--- a/displayengine/libs/hwc/hwc_display.h
+++ b/displayengine/libs/hwc/hwc_display.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -42,6 +42,9 @@
   virtual int GetDisplayAttributes(uint32_t config, const uint32_t *attributes, int32_t *values);
   virtual int GetActiveConfig();
   virtual int SetActiveConfig(int index);
+  virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
+  virtual int SetActiveConfig(hwc_display_contents_1_t *content_list);
+  virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
 
  protected:
   // Maximum number of layers supported by display engine.
@@ -66,8 +69,9 @@
   struct LayerStackCache {
     LayerCache layer_cache[kMaxLayerCount];
     uint32_t layer_count;
+    bool animating;
 
-    LayerStackCache() : layer_count(0) { }
+    LayerStackCache() : layer_count(0), animating(false) { }
   };
 
   HWCDisplay(CoreInterface *core_intf, hwc_procs_t const **hwc_procs, DisplayType type, int id);
@@ -80,6 +84,7 @@
   virtual int AllocateLayerStack(hwc_display_contents_1_t *content_list);
   virtual int PrepareLayerStack(hwc_display_contents_1_t *content_list);
   virtual int CommitLayerStack(hwc_display_contents_1_t *content_list);
+  virtual int PostCommitLayerStack(hwc_display_contents_1_t *content_list);
   bool NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list);
   void CacheLayerStackInfo(hwc_display_contents_1_t *content_list);
   inline void SetRect(const hwc_rect_t &source, LayerRect *target);
@@ -87,7 +92,16 @@
   inline void SetComposition(const int32_t &source, LayerComposition *target);
   inline void SetComposition(const int32_t &source, int32_t *target);
   inline void SetBlending(const int32_t &source, LayerBlending *target);
-  inline int SetFormat(const int32_t &source, LayerBufferFormat *target);
+  int SetFormat(const int32_t &source, const int flags, LayerBufferFormat *target);
+  LayerBufferFormat GetSDEFormat(const int32_t &source, const int flags);
+  void DumpInputBuffers(hwc_display_contents_1_t *content_list);
+  const char *GetHALPixelFormatString(int format);
+  const char *GetDisplayString();
+
+  enum {
+    INPUT_LAYER_DUMP,
+    OUTPUT_LAYER_DUMP,
+  };
 
   CoreInterface *core_intf_;
   hwc_procs_t const **hwc_procs_;
@@ -97,6 +111,11 @@
   LayerStackMemory layer_stack_memory_;
   LayerStack layer_stack_;
   LayerStackCache layer_stack_cache_;
+  bool flush_;
+  LayerBuffer *output_buffer_;
+  uint32_t dump_frame_count_;
+  uint32_t dump_frame_index_;
+  bool dump_input_layers_;
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/hwc/hwc_display_external.cpp b/displayengine/libs/hwc/hwc_display_external.cpp
index 468478b..2758e3a 100644
--- a/displayengine/libs/hwc/hwc_display_external.cpp
+++ b/displayengine/libs/hwc/hwc_display_external.cpp
@@ -1,31 +1,36 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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.
+* 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.
+* 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.
 */
 
 #include <utils/constants.h>
 
 #include "hwc_display_external.h"
-#include "hwc_logger.h"
+#include "hwc_debugger.h"
 
 #define __CLASS__ "HWCDisplayExternal"
 
@@ -59,7 +64,10 @@
     return status;
   }
 
-  content_list->retireFenceFd = layer_stack_.retire_fence_fd;
+  status = HWCDisplay::PostCommitLayerStack(content_list);
+  if (status) {
+    return status;
+  }
 
   return 0;
 }
diff --git a/displayengine/libs/hwc/hwc_display_primary.cpp b/displayengine/libs/hwc/hwc_display_primary.cpp
index b282ba6..6dbb723 100644
--- a/displayengine/libs/hwc/hwc_display_primary.cpp
+++ b/displayengine/libs/hwc/hwc_display_primary.cpp
@@ -1,31 +1,36 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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.
+* 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.
+* 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.
 */
 
 #include <utils/constants.h>
 
 #include "hwc_display_primary.h"
-#include "hwc_logger.h"
+#include "hwc_debugger.h"
 
 #define __CLASS__ "HWCDisplayPrimary"
 
@@ -59,7 +64,10 @@
     return status;
   }
 
-  content_list->retireFenceFd = layer_stack_.retire_fence_fd;
+  status = HWCDisplay::PostCommitLayerStack(content_list);
+  if (status) {
+    return status;
+  }
 
   return 0;
 }
diff --git a/displayengine/libs/hwc/hwc_display_virtual.cpp b/displayengine/libs/hwc/hwc_display_virtual.cpp
old mode 100755
new mode 100644
index 88cd073..9601e63
--- a/displayengine/libs/hwc/hwc_display_virtual.cpp
+++ b/displayengine/libs/hwc/hwc_display_virtual.cpp
@@ -1,47 +1,238 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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.
+* 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.
+* 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.
 */
 
 #include <utils/constants.h>
+#include <gralloc_priv.h>
+#include <sync/sync.h>
 
 #include "hwc_display_virtual.h"
-#include "hwc_logger.h"
+#include "hwc_debugger.h"
 
 #define __CLASS__ "HWCDisplayVirtual"
 
 namespace sde {
 
 HWCDisplayVirtual::HWCDisplayVirtual(CoreInterface *core_intf, hwc_procs_t const **hwc_procs)
-  : HWCDisplay(core_intf, hwc_procs, kVirtual, HWC_DISPLAY_VIRTUAL) {
+  : HWCDisplay(core_intf, hwc_procs, kVirtual, HWC_DISPLAY_VIRTUAL),
+    dump_output_layer_(false) {
+}
+
+int HWCDisplayVirtual::Init() {
+  int status = 0;
+
+  output_buffer_ = new LayerBuffer();
+  if (!output_buffer_) {
+    return -ENOMEM;
+  }
+
+  return HWCDisplay::Init();
+}
+
+int HWCDisplayVirtual::Deinit() {
+  int status = 0;
+
+  status = HWCDisplay::Deinit();
+  if (status) {
+    return status;
+  }
+
+  if (output_buffer_) {
+    delete output_buffer_;
+  }
+
+  return status;
 }
 
 int HWCDisplayVirtual::Prepare(hwc_display_contents_1_t *content_list) {
+  int status = 0;
+  status = AllocateLayerStack(content_list);
+  if (status) {
+    return status;
+  }
+
+  status = SetOutputBuffer(content_list);
+  if (status) {
+    return status;
+  }
+
+  status = PrepareLayerStack(content_list);
+  if (status) {
+    return status;
+  }
+
   return 0;
 }
 
 int HWCDisplayVirtual::Commit(hwc_display_contents_1_t *content_list) {
+  int status = 0;
+
+  status = HWCDisplay::CommitLayerStack(content_list);
+  if (status) {
+    return status;
+  }
+
+  DumpOutputBuffer(content_list);
+
+  status = HWCDisplay::PostCommitLayerStack(content_list);
+  if (status) {
+    return status;
+  }
+
+  if (content_list->outbufAcquireFenceFd >= 0) {
+    close(content_list->outbufAcquireFenceFd);
+    content_list->outbufAcquireFenceFd = -1;
+  }
+
   return 0;
 }
 
+int HWCDisplayVirtual::SetActiveConfig(hwc_display_contents_1_t *content_list) {
+  const private_handle_t *output_handle =
+        static_cast<const private_handle_t *>(content_list->outbuf);
+  DisplayError error = kErrorNone;
+  int status = 0;
+
+  if (output_handle) {
+    LayerBufferFormat format = GetSDEFormat(output_handle->format, output_handle->flags);
+    if (format == kFormatInvalid) {
+      return -EINVAL;
+    }
+
+    if ((output_handle->width != INT(output_buffer_->width)) ||
+        (output_handle->height != INT(output_buffer_->height)) ||
+        (format != output_buffer_->format)) {
+      DisplayConfigVariableInfo variable_info;
+
+      variable_info.x_pixels = output_handle->width;
+      variable_info.y_pixels = output_handle->height;
+      // TODO(user): Need to get the framerate of primary display and update it.
+      variable_info.fps = 60;
+
+      error = display_intf_->SetActiveConfig(&variable_info);
+      if (error != kErrorNone) {
+        return -EINVAL;
+      }
+
+      status = SetOutputBuffer(content_list);
+      if (status) {
+        return status;
+      }
+    }
+  }
+
+  return 0;
+}
+
+int HWCDisplayVirtual::SetOutputBuffer(hwc_display_contents_1_t *content_list) {
+  int status = 0;
+
+  const private_handle_t *output_handle =
+        static_cast<const private_handle_t *>(content_list->outbuf);
+
+  // Fill output buffer parameters (width, height, format, plane information, fence)
+  output_buffer_->acquire_fence_fd = content_list->outbufAcquireFenceFd;
+
+  if (output_handle) {
+    output_buffer_->format = GetSDEFormat(output_handle->format, output_handle->flags);
+    if (output_buffer_->format == kFormatInvalid) {
+      return -EINVAL;
+    }
+
+    output_buffer_->width = output_handle->width;
+    output_buffer_->height = output_handle->height;
+    output_buffer_->flags.secure = 0;
+    output_buffer_->flags.video = 0;
+
+    // ToDo: Need to extend for non-RGB formats
+    output_buffer_->planes[0].fd = output_handle->fd;
+    output_buffer_->planes[0].offset = output_handle->offset;
+    output_buffer_->planes[0].stride = output_handle->width;
+  }
+
+  layer_stack_.output_buffer = output_buffer_;
+
+  return status;
+}
+
+void HWCDisplayVirtual::DumpOutputBuffer(hwc_display_contents_1_t *content_list) {
+  const private_handle_t *output_handle = (const private_handle_t *)(content_list->outbuf);
+  char dir_path[PATH_MAX];
+
+  if (!dump_frame_count_ || flush_ || !dump_output_layer_) {
+    return;
+  }
+
+  snprintf(dir_path, sizeof(dir_path), "/data/misc/display/frame_dump_%s", GetDisplayString());
+
+  if (mkdir(dir_path, 777) != 0 && errno != EEXIST) {
+    DLOGW("Failed to create %s directory errno = %d, desc = %s", dir_path, errno, strerror(errno));
+    return;
+  }
+
+  // if directory exists already, need to explicitly change the permission.
+  if (errno == EEXIST && chmod(dir_path, 0777) != 0) {
+    DLOGW("Failed to change permissions on %s directory", dir_path);
+    return;
+  }
+
+  if (output_handle && output_handle->base) {
+    char dump_file_name[PATH_MAX];
+    size_t result = 0;
+
+    if (content_list->outbufAcquireFenceFd >= 0) {
+      int error = sync_wait(content_list->outbufAcquireFenceFd, 1000);
+      if (error < 0) {
+        DLOGW("sync_wait error errno = %d, desc = %s", errno,  strerror(errno));
+        return;
+      }
+    }
+
+    snprintf(dump_file_name, sizeof(dump_file_name), "%s/output_layer_%dx%d_%s_frame%d.raw",
+             dir_path, output_handle->width, output_handle->height,
+             GetHALPixelFormatString(output_handle->format), dump_frame_index_);
+
+    FILE* fp = fopen(dump_file_name, "w+");
+    if (fp) {
+      result = fwrite(reinterpret_cast<void *>(output_handle->base), output_handle->size, 1, fp);
+      fclose(fp);
+    }
+
+    DLOGI("Frame Dump of %s is %s", dump_file_name, result ? "Successful" : "Failed");
+  }
+}
+
+void HWCDisplayVirtual::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
+  HWCDisplay::SetFrameDumpConfig(count, bit_mask_layer_type);
+  dump_output_layer_ = ((bit_mask_layer_type & (1 << OUTPUT_LAYER_DUMP)) != 0);
+
+  DLOGI("output_layer_dump_enable %d", dump_output_layer_);
+}
+
 }  // namespace sde
 
diff --git a/displayengine/libs/hwc/hwc_display_virtual.h b/displayengine/libs/hwc/hwc_display_virtual.h
index 796ed32..7ac7c22 100644
--- a/displayengine/libs/hwc/hwc_display_virtual.h
+++ b/displayengine/libs/hwc/hwc_display_virtual.h
@@ -32,8 +32,18 @@
 class HWCDisplayVirtual : public HWCDisplay {
  public:
   explicit HWCDisplayVirtual(CoreInterface *core_intf, hwc_procs_t const **hwc_procs);
+  virtual int Init();
+  virtual int Deinit();
   virtual int Prepare(hwc_display_contents_1_t *content_list);
   virtual int Commit(hwc_display_contents_1_t *content_list);
+  virtual int SetActiveConfig(hwc_display_contents_1_t *content_list);
+  virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
+
+ private:
+  int SetOutputBuffer(hwc_display_contents_1_t *content_list);
+  void DumpOutputBuffer(hwc_display_contents_1_t *content_list);
+
+  bool dump_output_layer_;
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/hwc/hwc_logger.cpp b/displayengine/libs/hwc/hwc_logger.cpp
deleted file mode 100755
index 9d65e1c..0000000
--- a/displayengine/libs/hwc/hwc_logger.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
-* Copyright (c) 2014, 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.
-*/
-
-#include <utils/constants.h>
-
-#include "hwc_logger.h"
-
-namespace sde {
-
-HWCLogHandler HWCLogHandler::log_handler_;
-uint32_t HWCLogHandler::log_flags_ = 0x1;
-
-void HWCLogHandler::LogAll(bool enable) {
-  if (enable) {
-    log_flags_ = 0xFFFFFFFF;
-  } else {
-    log_flags_ = 0x1;   // kTagNone should always be printed.
-  }
-}
-
-void HWCLogHandler::LogResources(bool enable) {
-  if (enable) {
-    SET_BIT(log_flags_, kTagResources);
-  } else {
-    CLEAR_BIT(log_flags_, kTagResources);
-  }
-}
-
-void HWCLogHandler::LogStrategy(bool enable) {
-  if (enable) {
-    SET_BIT(log_flags_, kTagStrategy);
-  } else {
-    CLEAR_BIT(log_flags_, kTagStrategy);
-  }
-}
-
-void HWCLogHandler::Error(LogTag /*tag*/, const char *format, ...) {
-  va_list list;
-  va_start(list, format);
-  __android_log_vprint(ANDROID_LOG_ERROR, LOG_TAG, format, list);
-}
-
-void HWCLogHandler::Warning(LogTag /*tag*/, const char *format, ...) {
-  va_list list;
-  va_start(list, format);
-  __android_log_vprint(ANDROID_LOG_WARN, LOG_TAG, format, list);
-}
-
-void HWCLogHandler::Info(LogTag tag, const char *format, ...) {
-  if (IS_BIT_SET(log_flags_, tag)) {
-    va_list list;
-    va_start(list, format);
-    __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, list);
-  }
-}
-
-void HWCLogHandler::Verbose(LogTag tag, const char *format, ...) {
-  if (IS_BIT_SET(log_flags_, tag)) {
-    va_list list;
-    va_start(list, format);
-    __android_log_vprint(ANDROID_LOG_VERBOSE, LOG_TAG, format, list);
-  }
-}
-
-}  // namespace sde
-
diff --git a/displayengine/libs/hwc/hwc_logger.h b/displayengine/libs/hwc/hwc_logger.h
deleted file mode 100755
index 7568990..0000000
--- a/displayengine/libs/hwc/hwc_logger.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
-* Copyright (c) 2014, 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.
-*/
-
-#ifndef __HWC_LOGGER_H__
-#define __HWC_LOGGER_H__
-
-#include <core/sde_types.h>
-#include <cutils/log.h>
-
-#define DLOG(Macro, format, ...) Macro(__CLASS__ "::%s: " format, __FUNCTION__, ##__VA_ARGS__)
-
-#define DLOGE(format, ...) DLOG(ALOGE, format, ##__VA_ARGS__)
-#define DLOGW(format, ...) DLOG(ALOGW, format, ##__VA_ARGS__)
-#define DLOGI(format, ...) DLOG(ALOGI, format, ##__VA_ARGS__)
-#define DLOGV(format, ...) DLOG(ALOGV, format, ##__VA_ARGS__)
-
-namespace sde {
-
-class HWCLogHandler : public LogHandler {
- public:
-  static inline LogHandler* Get() { return &log_handler_; }
-  static void LogAll(bool enable);
-  static void LogResources(bool enable);
-  static void LogStrategy(bool enable);
-
-  virtual void Error(LogTag tag, const char *format, ...);
-  virtual void Warning(LogTag tag, const char *format, ...);
-  virtual void Info(LogTag tag, const char *format, ...);
-  virtual void Verbose(LogTag tag, const char *format, ...);
-
- private:
-  static HWCLogHandler log_handler_;
-  static uint32_t log_flags_;
-};
-
-}  // namespace sde
-
-#endif  // __HWC_LOGGER_H__
-
diff --git a/displayengine/libs/hwc/hwc_session.cpp b/displayengine/libs/hwc/hwc_session.cpp
index 3f99a23..3bc4fd1 100644
--- a/displayengine/libs/hwc/hwc_session.cpp
+++ b/displayengine/libs/hwc/hwc_session.cpp
@@ -1,25 +1,30 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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.
+* 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.
+* 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.
 */
 
 #include <core/dump_interface.h>
@@ -30,9 +35,12 @@
 #include <sys/prctl.h>
 #include <binder/Parcel.h>
 #include <QService.h>
+#include <core/buffer_allocator.h>
 
+#include "hwc_buffer_allocator.h"
+#include "hwc_buffer_sync_handler.h"
 #include "hwc_session.h"
-#include "hwc_logger.h"
+#include "hwc_debugger.h"
 
 #define __CLASS__ "HWCSession"
 
@@ -57,8 +65,8 @@
 Locker HWCSession::locker_;
 
 HWCSession::HWCSession(const hw_module_t *module) : core_intf_(NULL), hwc_procs_(NULL),
-            display_primary_(NULL), display_external_(NULL), hotplug_thread_exit_(false),
-            hotplug_thread_name_("HWC_HotPlugThread") {
+            display_primary_(NULL), display_external_(NULL), display_virtual_(NULL),
+            hotplug_thread_exit_(false), hotplug_thread_name_("HWC_HotPlugThread") {
   hwc_composer_device_1_t::common.tag = HARDWARE_DEVICE_TAG;
   hwc_composer_device_1_t::common.version = HWC_DEVICE_API_VERSION_1_4;
   hwc_composer_device_1_t::common.module = const_cast<hw_module_t*>(module);
@@ -92,7 +100,20 @@
     return -EINVAL;
   }
 
-  DisplayError error = CoreInterface::CreateCore(this, HWCLogHandler::Get(), &core_intf_);
+  buffer_allocator_ = new HWCBufferAllocator();
+  if (buffer_allocator_ == NULL) {
+    DLOGE("Display core initialization failed due to no memory");
+    return -ENOMEM;
+  }
+
+  buffer_sync_handler_ = new HWCBufferSyncHandler();
+  if (buffer_sync_handler_ == NULL) {
+    DLOGE("Display core initialization failed due to no memory");
+    return -ENOMEM;
+  }
+
+  DisplayError error = CoreInterface::CreateCore(this, HWCDebugHandler::Get(), buffer_allocator_,
+                                                 buffer_sync_handler_, &core_intf_);
   if (error != kErrorNone) {
     DLOGE("Display core initialization failed. Error = %d", error);
     return -EINVAL;
@@ -187,7 +208,9 @@
 
 int HWCSession::Prepare(hwc_composer_device_1 *device, size_t num_displays,
                         hwc_display_contents_1_t **displays) {
-  SCOPE_LOCK(locker_);
+  DTRACE_SCOPED();
+
+  SEQUENCE_ENTRY_SCOPE_LOCK(locker_);
 
   if (!device || !displays) {
     return -EINVAL;
@@ -208,6 +231,15 @@
       }
       break;
     case HWC_DISPLAY_VIRTUAL:
+      if (hwc_session->ValidateContentList(content_list)) {
+        hwc_session->CreateVirtualDisplay(hwc_session, content_list);
+      } else {
+        hwc_session->DestroyVirtualDisplay(hwc_session);
+      }
+
+      if (hwc_session->display_virtual_) {
+        hwc_session->display_virtual_->Prepare(content_list);
+      }
       break;
     default:
       break;
@@ -220,7 +252,9 @@
 
 int HWCSession::Set(hwc_composer_device_1 *device, size_t num_displays,
                     hwc_display_contents_1_t **displays) {
-  SCOPE_LOCK(locker_);
+  DTRACE_SCOPED();
+
+  SEQUENCE_EXIT_SCOPE_LOCK(locker_);
 
   if (!device || !displays) {
     return -EINVAL;
@@ -241,6 +275,9 @@
       }
       break;
     case HWC_DISPLAY_VIRTUAL:
+      if (hwc_session->display_virtual_) {
+        hwc_session->display_virtual_->Commit(content_list);
+      }
       break;
     default:
       break;
@@ -252,7 +289,7 @@
 }
 
 int HWCSession::EventControl(hwc_composer_device_1 *device, int disp, int event, int enable) {
-  SCOPE_LOCK(locker_);
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
 
   if (!device) {
     return -EINVAL;
@@ -270,6 +307,8 @@
       status = hwc_session->display_external_->EventControl(event, enable);
     }
     break;
+  case HWC_DISPLAY_VIRTUAL:
+    break;
   default:
     status = -EINVAL;
   }
@@ -278,7 +317,7 @@
 }
 
 int HWCSession::SetPowerMode(hwc_composer_device_1 *device, int disp, int mode) {
-  SCOPE_LOCK(locker_);
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
 
   if (!device) {
     return -EINVAL;
@@ -296,6 +335,11 @@
       status = hwc_session->display_external_->SetPowerMode(mode);
     }
     break;
+  case HWC_DISPLAY_VIRTUAL:
+    if (hwc_session->display_virtual_) {
+      status = hwc_session->display_virtual_->SetPowerMode(mode);
+    }
+    break;
   default:
     status = -EINVAL;
   }
@@ -304,6 +348,8 @@
 }
 
 int HWCSession::Query(hwc_composer_device_1 *device, int param, int *value) {
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
   if (!device || !value) {
     return -EINVAL;
   }
@@ -321,7 +367,7 @@
 }
 
 void HWCSession::Dump(hwc_composer_device_1 *device, char *buffer, int length) {
-  SCOPE_LOCK(locker_);
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
 
   if (!device || !buffer || !length) {
     return;
@@ -332,6 +378,8 @@
 
 int HWCSession::GetDisplayConfigs(hwc_composer_device_1 *device, int disp, uint32_t *configs,
                                   size_t *num_configs) {
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
   if (!device || !configs || !num_configs) {
     return -EINVAL;
   }
@@ -348,6 +396,11 @@
       status = hwc_session->display_external_->GetDisplayConfigs(configs, num_configs);
     }
     break;
+  case HWC_DISPLAY_VIRTUAL:
+    if (hwc_session->display_virtual_) {
+      status = hwc_session->display_virtual_->GetDisplayConfigs(configs, num_configs);
+    }
+    break;
   default:
     status = -EINVAL;
   }
@@ -357,6 +410,8 @@
 
 int HWCSession::GetDisplayAttributes(hwc_composer_device_1 *device, int disp, uint32_t config,
                                      const uint32_t *attributes, int32_t *values) {
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
   if (!device || !attributes || !values) {
     return -EINVAL;
   }
@@ -373,6 +428,11 @@
       status = hwc_session->display_external_->GetDisplayAttributes(config, attributes, values);
     }
     break;
+  case HWC_DISPLAY_VIRTUAL:
+    if (hwc_session->display_virtual_) {
+      status = hwc_session->display_virtual_->GetDisplayAttributes(config, attributes, values);
+    }
+    break;
   default:
     status = -EINVAL;
   }
@@ -381,6 +441,8 @@
 }
 
 int HWCSession::GetActiveConfig(hwc_composer_device_1 *device, int disp) {
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
   if (!device) {
     return -1;
   }
@@ -397,6 +459,11 @@
       active_config = hwc_session->display_external_->GetActiveConfig();
     }
     break;
+  case HWC_DISPLAY_VIRTUAL:
+    if (hwc_session->display_virtual_) {
+      active_config = hwc_session->display_virtual_->GetActiveConfig();
+    }
+    break;
   default:
     active_config = -1;
   }
@@ -405,6 +472,8 @@
 }
 
 int HWCSession::SetActiveConfig(hwc_composer_device_1 *device, int disp, int index) {
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
   if (!device) {
     return -EINVAL;
   }
@@ -422,6 +491,8 @@
       status = 0;  // hwc_session->display_external_->SetActiveConfig(index);
     }
     break;
+  case HWC_DISPLAY_VIRTUAL:
+    break;
   default:
     status = -EINVAL;
   }
@@ -429,12 +500,67 @@
   return status;
 }
 
+bool HWCSession::ValidateContentList(hwc_display_contents_1_t *content_list) {
+  return (content_list && content_list->numHwLayers > 0 && content_list->outbuf);
+}
+
+int HWCSession::CreateVirtualDisplay(HWCSession *hwc_session,
+                                     hwc_display_contents_1_t *content_list) {
+  int status = 0;
+
+  if (!hwc_session->display_virtual_) {
+    // Create virtual display device
+    hwc_session->display_virtual_ = new HWCDisplayVirtual(hwc_session->core_intf_,
+                                                          &hwc_session->hwc_procs_);
+    if (!hwc_session->display_virtual_) {
+      // This is not catastrophic. Leave a warning message for now.
+      DLOGW("Virtual Display creation failed");
+      return -ENOMEM;
+    }
+
+    status = hwc_session->display_virtual_->Init();
+    if (status) {
+      goto CleanupOnError;
+    }
+
+    status = hwc_session->display_virtual_->SetPowerMode(HWC_POWER_MODE_NORMAL);
+    if (status) {
+      goto CleanupOnError;
+    }
+  }
+
+  if (hwc_session->display_virtual_) {
+    status = hwc_session->display_virtual_->SetActiveConfig(content_list);
+  }
+
+  return status;
+
+CleanupOnError:
+  return hwc_session->DestroyVirtualDisplay(hwc_session);
+}
+
+int HWCSession::DestroyVirtualDisplay(HWCSession *hwc_session) {
+  int status = 0;
+
+  if (hwc_session->display_virtual_) {
+    status = hwc_session->display_virtual_->Deinit();
+    if (!status) {
+      delete hwc_session->display_virtual_;
+      hwc_session->display_virtual_ = NULL;
+    }
+  }
+
+  return status;
+}
+
 DisplayError HWCSession::Hotplug(const CoreEventHotplug &hotplug) {
   return kErrorNone;
 }
 
 android::status_t HWCSession::notifyCallback(uint32_t command, const android::Parcel *input_parcel,
                                              android::Parcel */*output_parcel*/) {
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
   switch (command) {
   case qService::IQService::DYNAMIC_DEBUG:
     DynamicDebug(input_parcel);
@@ -444,6 +570,17 @@
     hwc_procs_->invalidate(hwc_procs_);
     break;
 
+  case qService::IQService::SET_IDLE_TIMEOUT:
+    if (display_primary_) {
+      uint32_t timeout = (uint32_t)input_parcel->readInt32();
+      display_primary_->SetIdleTimeoutMs(timeout);
+    }
+    break;
+
+  case qService::IQService::SET_FRAME_DUMP_CONFIG:
+    SetFrameDumpConfig(input_parcel);
+    break;
+
   default:
     DLOGW("QService command = %d is not supported", command);
     return -EINVAL;
@@ -452,6 +589,30 @@
   return 0;
 }
 
+void HWCSession::SetFrameDumpConfig(const android::Parcel *input_parcel) {
+  uint32_t frame_dump_count = UINT32(input_parcel->readInt32());
+  uint32_t bit_mask_display_type = UINT32(input_parcel->readInt32());
+  uint32_t bit_mask_layer_type = UINT32(input_parcel->readInt32());
+
+  if (bit_mask_display_type & (1 << qService::IQService::DUMP_PRIMARY_DISPLAY)) {
+    if (display_primary_) {
+      display_primary_->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
+    }
+  }
+
+  if (bit_mask_display_type & (1 << qService::IQService::DUMP_HDMI_DISPLAY)) {
+    if (display_external_) {
+      display_external_->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
+    }
+  }
+
+  if (bit_mask_display_type & (1 << qService::IQService::DUMP_VIRTUAL_DISPLAY)) {
+    if (display_virtual_) {
+      display_virtual_->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
+    }
+  }
+}
+
 void HWCSession::DynamicDebug(const android::Parcel *input_parcel) {
   int type = input_parcel->readInt32();
   bool enable = (input_parcel->readInt32() > 0);
@@ -459,21 +620,34 @@
 
   switch (type) {
   case qService::IQService::DEBUG_ALL:
-    HWCLogHandler::LogAll(enable);
+    HWCDebugHandler::DebugAll(enable);
     break;
 
   case qService::IQService::DEBUG_MDPCOMP:
-    HWCLogHandler::LogStrategy(enable);
+    HWCDebugHandler::DebugStrategy(enable);
+    HWCDebugHandler::DebugCompManager(enable);
     break;
 
   case qService::IQService::DEBUG_PIPE_LIFECYCLE:
-    HWCLogHandler::LogResources(enable);
+    HWCDebugHandler::DebugResources(enable);
+    break;
+
+  case qService::IQService::DEBUG_DRIVER_CONFIG:
+    HWCDebugHandler::DebugDriverConfig(enable);
+    break;
+
+  case qService::IQService::DEBUG_ROTATOR:
+    HWCDebugHandler::DebugResources(enable);
+    HWCDebugHandler::DebugDriverConfig(enable);
+    HWCDebugHandler::DebugBufferManager(enable);
+    HWCDebugHandler::DebugOfflineCtrl(enable);
     break;
 
   default:
     DLOGW("type = %d is not supported", type);
   }
 }
+
 void* HWCSession::HWCHotPlugThread(void *context) {
   if (context) {
     return reinterpret_cast<HWCSession *>(context)->HWCHotPlugThreadHandler();
@@ -526,7 +700,6 @@
   return -1;
 }
 
-
 int HWCSession::HotPlugHandler(bool connected) {
   if (!hwc_procs_) {
      DLOGW("Ignore hotplug - hwc_proc not registered");
@@ -534,7 +707,7 @@
   }
 
   if (connected) {
-    SCOPE_LOCK(locker_);
+    SEQUENCE_WAIT_SCOPE_LOCK(locker_);
     if (display_external_) {
      DLOGE("HDMI already connected");
      return -1;
@@ -551,7 +724,7 @@
       return -1;
     }
   } else {
-    SCOPE_LOCK(locker_);
+    SEQUENCE_WAIT_SCOPE_LOCK(locker_);
     if (!display_external_) {
      DLOGE("HDMI not connected");
      return -1;
diff --git a/displayengine/libs/hwc/hwc_session.h b/displayengine/libs/hwc/hwc_session.h
index 488da9d..4b8c8ce 100644
--- a/displayengine/libs/hwc/hwc_session.h
+++ b/displayengine/libs/hwc/hwc_session.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -32,6 +32,7 @@
 
 #include "hwc_display_primary.h"
 #include "hwc_display_external.h"
+#include "hwc_display_virtual.h"
 
 namespace sde {
 
@@ -72,6 +73,9 @@
   void* HWCHotPlugThreadHandler();
   int GetHDMIConnectedState(const char *uevent_data, int length);
   int HotPlugHandler(bool connected);
+  bool ValidateContentList(hwc_display_contents_1_t *content_list);
+  int CreateVirtualDisplay(HWCSession *hwc_session, hwc_display_contents_1_t *content_list);
+  int DestroyVirtualDisplay(HWCSession *hwc_session);
 
   // CoreEventHandler methods
   virtual DisplayError Hotplug(const CoreEventHotplug &hotplug);
@@ -80,15 +84,19 @@
   virtual android::status_t notifyCallback(uint32_t command, const android::Parcel *input_parcel,
                                            android::Parcel *output_parcel);
   void DynamicDebug(const android::Parcel *input_parcel);
+  void SetFrameDumpConfig(const android::Parcel *input_parcel);
 
   static Locker locker_;
   CoreInterface *core_intf_;
   hwc_procs_t const *hwc_procs_;
   HWCDisplayPrimary *display_primary_;
   HWCDisplayExternal *display_external_;
+  HWCDisplayVirtual *display_virtual_;
   pthread_t hotplug_thread_;
   bool hotplug_thread_exit_;
   const char *hotplug_thread_name_;
+  HWCBufferAllocator *buffer_allocator_;
+  HWCBufferSyncHandler *buffer_sync_handler_;
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/utils/Android.mk b/displayengine/libs/utils/Android.mk
index db97dd5..264c40a 100644
--- a/displayengine/libs/utils/Android.mk
+++ b/displayengine/libs/utils/Android.mk
@@ -8,6 +8,6 @@
                                  -Wconversion -Wall -Werror \
                                  -DLOG_TAG=\"SDE\"
 LOCAL_SHARED_LIBRARIES        := libcutils
-LOCAL_SRC_FILES               := debug_android.cpp
+LOCAL_SRC_FILES               := debug_android.cpp rect.cpp
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/displayengine/libs/utils/debug_android.cpp b/displayengine/libs/utils/debug_android.cpp
old mode 100755
new mode 100644
index 31bd40b..1b08fe9
--- a/displayengine/libs/utils/debug_android.cpp
+++ b/displayengine/libs/utils/debug_android.cpp
@@ -1,25 +1,30 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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.
+* 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.
+* 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.
 */
 
 #include <stdlib.h>
@@ -31,7 +36,7 @@
 
 Debug Debug::debug_;
 
-Debug::Debug() : log_handler_(&default_log_handler_), virtual_driver_(false) {
+Debug::Debug() : debug_handler_(&default_debug_handler_), virtual_driver_(false) {
   char property[PROPERTY_VALUE_MAX];
   if (property_get("displaycore.virtualdriver", property, NULL) > 0) {
     virtual_driver_ = (atoi(property) == 1);
@@ -56,5 +61,14 @@
   return 0;
 }
 
+uint32_t Debug::GetIdleTimeoutMs() {
+  char property[PROPERTY_VALUE_MAX];
+  if (property_get("debug.mdpcomp.idletime", property, NULL) > 0) {
+    return atoi(property);
+  }
+
+  return 0;
+}
+
 }  // namespace sde
 
diff --git a/displayengine/libs/utils/rect.cpp b/displayengine/libs/utils/rect.cpp
new file mode 100644
index 0000000..2725750
--- /dev/null
+++ b/displayengine/libs/utils/rect.cpp
@@ -0,0 +1,80 @@
+/*
+* Copyright (c) 2015, 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.
+*/
+
+#include <math.h>
+#include <utils/rect.h>
+#include <utils/constants.h>
+
+#define __CLASS__ "RectUtils"
+
+namespace sde {
+
+bool IsValidRect(const LayerRect &rect) {
+  return ((rect.bottom > rect.top) && (rect.right > rect.left));
+}
+
+
+LayerRect GetIntersection(const LayerRect &rect1, const LayerRect &rect2) {
+  LayerRect res;
+
+  if (!IsValidRect(rect1) || !IsValidRect(rect2)) {
+    return LayerRect();
+  }
+
+  res.left = MAX(rect1.left, rect2.left);
+  res.top = MAX(rect1.top, rect2.top);
+  res.right = MIN(rect1.right, rect2.right);
+  res.bottom = MIN(rect1.bottom, rect2.bottom);
+
+  if (!IsValidRect(res)) {
+    return LayerRect();
+  }
+
+  return res;
+}
+
+void LogRect(DebugTag debug_tag, const char *prefix, const LayerRect &roi) {
+  DLOGV_IF(debug_tag, "%s: left = %.0f, top = %.0f, right = %.0f, bottom = %.0f",
+           prefix, roi.left, roi.top, roi.right, roi.bottom);
+}
+
+void NormalizeRect(const uint32_t &factor, LayerRect *rect) {
+  uint32_t left = UINT32(ceilf(rect->left));
+  uint32_t top = UINT32(ceilf(rect->top));
+  uint32_t right = UINT32(floorf(rect->right));
+  uint32_t bottom = UINT32(floorf(rect->bottom));
+
+  rect->left = FLOAT(CeilToMultipleOf(left, factor));
+  rect->top = FLOAT(CeilToMultipleOf(top, factor));
+  rect->right = FLOAT(FloorToMultipleOf(right, factor));
+  rect->bottom = FLOAT(FloorToMultipleOf(bottom, factor));
+}
+
+}  // namespace sde
+
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index a7c4a9a..fd98154 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -37,6 +37,7 @@
 #include "gr.h"
 #include "comptype.h"
 #include "mdp_version.h"
+#include <qdMetaData.h>
 
 #ifdef VENUS_COLOR_FORMAT
 #include <media/msm_media_info.h>
@@ -623,9 +624,19 @@
 int getYUVPlaneInfo(private_handle_t* hnd, struct android_ycbcr* ycbcr)
 {
     int err = 0;
+    int width = hnd->width;
+    int height = hnd->height;
     unsigned int ystride, cstride;
+
     memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
 
+    // Check metadata if the geometry has been updated.
+    MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+    if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
+        AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(metadata->bufferDim.sliceWidth,
+                   metadata->bufferDim.sliceHeight, hnd->format, 0, width, height);
+    }
+
     // Get the chroma offsets from the handle width/height. We take advantage
     // of the fact the width _is_ the stride
     switch (hnd->format) {
@@ -634,10 +645,10 @@
         case HAL_PIXEL_FORMAT_YCbCr_422_SP:
         case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
         case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: //Same as YCbCr_420_SP_VENUS
-            ystride = cstride = hnd->width;
+            ystride = cstride = width;
             ycbcr->y  = (void*)hnd->base;
-            ycbcr->cb = (void*)(hnd->base + ystride * hnd->height);
-            ycbcr->cr = (void*)(hnd->base + ystride * hnd->height + 1);
+            ycbcr->cb = (void*)(hnd->base + ystride * height);
+            ycbcr->cr = (void*)(hnd->base + ystride * height + 1);
             ycbcr->ystride = ystride;
             ycbcr->cstride = cstride;
             ycbcr->chroma_step = 2;
@@ -648,10 +659,10 @@
         case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
         case HAL_PIXEL_FORMAT_NV21_ZSL:
         case HAL_PIXEL_FORMAT_RAW_SENSOR:
-            ystride = cstride = hnd->width;
+            ystride = cstride = width;
             ycbcr->y  = (void*)hnd->base;
-            ycbcr->cr = (void*)(hnd->base + ystride * hnd->height);
-            ycbcr->cb = (void*)(hnd->base + ystride * hnd->height + 1);
+            ycbcr->cr = (void*)(hnd->base + ystride * height);
+            ycbcr->cb = (void*)(hnd->base + ystride * height + 1);
             ycbcr->ystride = ystride;
             ycbcr->cstride = cstride;
             ycbcr->chroma_step = 2;
@@ -659,16 +670,15 @@
 
         //Planar
         case HAL_PIXEL_FORMAT_YV12:
-            ystride = hnd->width;
-            cstride = ALIGN(hnd->width/2, 16);
+            ystride = width;
+            cstride = ALIGN(width/2, 16);
             ycbcr->y  = (void*)hnd->base;
-            ycbcr->cr = (void*)(hnd->base + ystride * hnd->height);
-            ycbcr->cb = (void*)(hnd->base + ystride * hnd->height +
-                    cstride * hnd->height/2);
+            ycbcr->cr = (void*)(hnd->base + ystride * height);
+            ycbcr->cb = (void*)(hnd->base + ystride * height +
+                    cstride * height/2);
             ycbcr->ystride = ystride;
             ycbcr->cstride = cstride;
             ycbcr->chroma_step = 1;
-
         break;
         //Unsupported formats
         case HAL_PIXEL_FORMAT_YCbCr_422_I:
@@ -764,12 +774,15 @@
 
 bool isUBwcEnabled(int format, int usage)
 {
-    if (isUBwcFormat(format) ||
-        ((usage & GRALLOC_USAGE_PRIVATE_ALLOC_UBWC) && isUBwcSupported(format)))
-    {
-        // Allow UBWC, only if GPU supports it and CPU usage flags are not set
-        if (AdrenoMemInfo::getInstance().isUBWCSupportedByGPU(format) &&
-            !(usage & (GRALLOC_USAGE_SW_READ_MASK |
+    // Allow UBWC, if client is using an explicitly defined UBWC pixel format.
+    if (isUBwcFormat(format))
+        return true;
+
+    // Allow UBWC, if client sets UBWC gralloc usage flag & GPU supports format.
+    if ((usage & GRALLOC_USAGE_PRIVATE_ALLOC_UBWC) && isUBwcSupported(format) &&
+        AdrenoMemInfo::getInstance().isUBWCSupportedByGPU(format)) {
+        // Allow UBWC, only if CPU usage flags are not set
+        if (!(usage & (GRALLOC_USAGE_SW_READ_MASK |
                       GRALLOC_USAGE_SW_WRITE_MASK))) {
             return true;
         }
diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp
index 9ab9d09..df7be41 100644
--- a/libgralloc/gpu.cpp
+++ b/libgralloc/gpu.cpp
@@ -149,7 +149,8 @@
             flags |= private_handle_t::PRIV_FLAGS_TILE_RENDERED;
         }
 
-        if (isUBwcEnabled(format, usage)) {
+        if (AdrenoMemInfo::getInstance().isUBWCSupportedByGPU(format) &&
+            isUBwcEnabled(format, usage)) {
             flags |= private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
         }
 
@@ -288,7 +289,9 @@
     //the usage bits, gralloc assigns a format.
     if(format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED ||
        format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
-        if(usage & GRALLOC_USAGE_HW_VIDEO_ENCODER)
+        if (usage & GRALLOC_USAGE_PRIVATE_ALLOC_UBWC)
+            grallocFormat = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC;
+        else if(usage & GRALLOC_USAGE_HW_VIDEO_ENCODER)
             grallocFormat = HAL_PIXEL_FORMAT_NV12_ENCODEABLE; //NV12
         else if((usage & GRALLOC_USAGE_HW_CAMERA_MASK)
                 == GRALLOC_USAGE_HW_CAMERA_ZSL)
diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h
index 8b134ea..e9b9d9d 100755
--- a/libgralloc/gralloc_priv.h
+++ b/libgralloc/gralloc_priv.h
@@ -91,7 +91,6 @@
                              GRALLOC_USAGE_PRIVATE_ADSP_HEAP)
 
 #define INTERLACE_MASK 0x80
-#define S3D_FORMAT_MASK 0xFF000
 /*****************************************************************************/
 
 /* OEM specific HAL formats */
@@ -155,15 +154,11 @@
 
 /* possible formats for 3D content*/
 enum {
-    HAL_NO_3D                         = 0x0000,
-    HAL_3D_IN_SIDE_BY_SIDE_L_R        = 0x10000,
-    HAL_3D_IN_TOP_BOTTOM              = 0x20000,
-    HAL_3D_IN_INTERLEAVE              = 0x40000,
-    HAL_3D_IN_SIDE_BY_SIDE_R_L        = 0x80000,
-    HAL_3D_OUT_SIDE_BY_SIDE           = 0x1000,
-    HAL_3D_OUT_TOP_BOTTOM             = 0x2000,
-    HAL_3D_OUT_INTERLEAVE             = 0x4000,
-    HAL_3D_OUT_MONOSCOPIC             = 0x8000
+    HAL_NO_3D                      = 0x0,
+    HAL_3D_SIDE_BY_SIDE_L_R        = 0x1,
+    HAL_3D_SIDE_BY_SIDE_R_L        = 0x2,
+    HAL_3D_TOP_BOTTOM              = 0x4,
+    HAL_3D_IN_SIDE_BY_SIDE_L_R     = 0x10000, //unused legacy format
 };
 
 enum {
diff --git a/libhdmi/hdmi.cpp b/libhdmi/hdmi.cpp
index 7d709cb..bca7a0b 100644
--- a/libhdmi/hdmi.cpp
+++ b/libhdmi/hdmi.cpp
@@ -21,7 +21,6 @@
 #define DEBUG 0
 #include <fcntl.h>
 #include <linux/msm_mdp.h>
-#include <video/msm_hdmi_modes.h>
 #include <linux/fb.h>
 #include <sys/ioctl.h>
 #include <cutils/properties.h>
@@ -38,62 +37,6 @@
 #define UNKNOWN_STRING                  "unknown"
 #define SPD_NAME_LENGTH                 16
 
-/* The array gEDIDData contains a list of modes currently
- * supported by HDMI and display, and modes that are not
- * supported i.e. interlaced modes.
-
- * In order to add support for a new mode, the mode must be
- * appended to the end of the array.
- *
- * Each new entry must contain the following:
- * -Mode: a video format defined in msm_hdmi_modes.h
- * -Width: x resolution for the mode
- * -Height: y resolution for the mode
- * -FPS: the frame rate for the mode
- * -Mode Order: the priority for the new mode that is used when determining
- *  the best mode when the HDMI display is connected.
- */
-EDIDData gEDIDData [] = {
-    EDIDData(HDMI_VFRMT_1440x480i60_4_3, 1440, 480, 60, 1),
-    EDIDData(HDMI_VFRMT_1440x480i60_16_9, 1440, 480, 60, 2),
-    EDIDData(HDMI_VFRMT_1440x576i50_4_3, 1440, 576, 50, 3),
-    EDIDData(HDMI_VFRMT_1440x576i50_16_9, 1440, 576, 50, 4),
-    EDIDData(HDMI_VFRMT_1920x1080i60_16_9, 1920, 1080, 60, 5),
-    EDIDData(HDMI_VFRMT_640x480p60_4_3, 640, 480, 60, 6),
-    EDIDData(HDMI_VFRMT_720x480p60_4_3, 720, 480, 60, 7),
-    EDIDData(HDMI_VFRMT_720x480p60_16_9, 720, 480, 60, 8),
-    EDIDData(HDMI_VFRMT_720x576p50_4_3, 720, 576, 50, 9),
-    EDIDData(HDMI_VFRMT_720x576p50_16_9, 720, 576, 50, 10),
-    EDIDData(HDMI_VFRMT_800x600p60_4_3, 800, 600, 60, 11),
-    EDIDData(HDMI_VFRMT_848x480p60_16_9, 848, 480, 60, 12),
-    EDIDData(HDMI_VFRMT_1024x768p60_4_3, 1024, 768, 60, 13),
-    EDIDData(HDMI_VFRMT_1280x1024p60_5_4, 1280, 1024, 60, 14),
-    EDIDData(HDMI_VFRMT_1280x720p50_16_9, 1280, 720, 50, 15),
-    EDIDData(HDMI_VFRMT_1280x720p60_16_9, 1280, 720, 60, 16),
-    EDIDData(HDMI_VFRMT_1280x800p60_16_10, 1280, 800, 60, 17),
-    EDIDData(HDMI_VFRMT_1280x960p60_4_3, 1280, 960, 60, 18),
-    EDIDData(HDMI_VFRMT_1360x768p60_16_9, 1360, 768, 60, 19),
-    EDIDData(HDMI_VFRMT_1366x768p60_16_10, 1366, 768, 60, 20),
-    EDIDData(HDMI_VFRMT_1440x900p60_16_10, 1440, 900, 60, 21),
-    EDIDData(HDMI_VFRMT_1400x1050p60_4_3, 1400, 1050, 60, 22),
-    EDIDData(HDMI_VFRMT_1680x1050p60_16_10, 1680, 1050, 60, 23),
-    EDIDData(HDMI_VFRMT_1600x1200p60_4_3, 1600, 1200, 60, 24),
-    EDIDData(HDMI_VFRMT_1920x1080p24_16_9, 1920, 1080, 24, 25),
-    EDIDData(HDMI_VFRMT_1920x1080p25_16_9, 1920, 1080, 25, 26),
-    EDIDData(HDMI_VFRMT_1920x1080p30_16_9, 1920, 1080, 30, 27),
-    EDIDData(HDMI_VFRMT_1920x1080p50_16_9, 1920, 1080, 50, 28),
-    EDIDData(HDMI_VFRMT_1920x1080p60_16_9, 1920, 1080, 60, 29),
-    EDIDData(HDMI_VFRMT_1920x1200p60_16_10, 1920, 1200, 60, 30),
-    EDIDData(HDMI_VFRMT_2560x1600p60_16_9, 2560, 1600, 60, 31),
-    EDIDData(HDMI_VFRMT_3840x2160p24_16_9, 3840, 2160, 24, 32),
-    EDIDData(HDMI_VFRMT_3840x2160p25_16_9, 3840, 2160, 25, 33),
-    EDIDData(HDMI_VFRMT_3840x2160p30_16_9, 3840, 2160, 30, 34),
-    EDIDData(HDMI_VFRMT_4096x2160p24_16_9, 4096, 2160, 24, 35),
-};
-
-// Number of modes in gEDIDData
-const int gEDIDCount = (sizeof(gEDIDData)/sizeof(gEDIDData)[0]);
-
 int HDMIDisplay::configure() {
     if(!openFrameBuffer()) {
         ALOGE("%s: Failed to open FB: %d", __FUNCTION__, mFbNum);
@@ -135,8 +78,8 @@
 }
 
 void HDMIDisplay::getAttributes(uint32_t& width, uint32_t& height) {
-    uint32_t fps = 0;
-    getAttrForMode(width, height, fps);
+    uint32_t refresh = 0, fps = 0;
+    getAttrForConfig(mActiveConfig, width, height, refresh, fps);
 }
 
 int HDMIDisplay::teardown() {
@@ -167,14 +110,7 @@
         writeHPDOption(0);
     }
 
-    // for HDMI - retreive all the modes supported by the driver
     if(mFbNum != -1) {
-        supported_video_mode_lut =
-                        new msm_hdmi_mode_timing_info[HDMI_VFRMT_MAX];
-        // Populate the mode table for supported modes
-        MSM_HDMI_MODES_INIT_TIMINGS(supported_video_mode_lut);
-        MSM_HDMI_MODES_SET_SUPP_TIMINGS(supported_video_mode_lut,
-                                        MSM_HDMI_MODES_ALL);
         // Update the Source Product Information
         // Vendor Name
         setSPDInfo("vendor_name", "ro.product.manufacturer");
@@ -298,7 +234,6 @@
 
 HDMIDisplay::~HDMIDisplay()
 {
-    delete [] supported_video_mode_lut;
     closeFrameBuffer();
 }
 
@@ -356,7 +291,7 @@
 bool HDMIDisplay::readResolution()
 {
     ssize_t len = -1;
-    char edidStr[128] = {'\0'};
+    char edidStr[PAGE_SIZE] = {'\0'};
 
     int hdmiEDIDFile = openDeviceNode("edid_modes", O_RDONLY);
     if (hdmiEDIDFile < 0) {
@@ -383,6 +318,25 @@
         ALOGD_IF(DEBUG, "%s: mModeCount = %d", __FUNCTION__,
                  mModeCount);
     }
+    // Populate the internal data structure with the timing information
+    // for each edid mode read from the driver
+    if (mModeCount > 0) {
+        mDisplayConfigs = new msm_hdmi_mode_timing_info[mModeCount];
+        readConfigs();
+    } else {
+        // If we fail to read from EDID when HDMI is connected, then
+        // mModeCount will be 0 and bestConfigIndex will be invalid.
+        // In this case, we populate the mEDIDModes structure with
+        // a default mode at config index 0.
+        uint32_t defaultConfigIndex = 0;
+        mModeCount = 1;
+        mEDIDModes[defaultConfigIndex] = HDMI_VFRMT_640x480p60_4_3;
+        struct msm_hdmi_mode_timing_info defaultMode =
+                HDMI_VFRMT_640x480p60_4_3_TIMING;
+        mDisplayConfigs = new msm_hdmi_mode_timing_info[mModeCount];
+        mDisplayConfigs[defaultConfigIndex] = defaultMode;
+        ALOGD("%s Defaulting to HDMI_VFRMT_640x480p60_4_3", __FUNCTION__);
+    }
 
     return (len > 0);
 }
@@ -421,30 +375,22 @@
     mYres = 0;
     mVsyncPeriod = 0;
     mMDPScalingMode = false;
+    if (mDisplayConfigs) {
+        delete [] mDisplayConfigs;
+        mDisplayConfigs = 0;
+    }
     // Reset the underscan supported system property
     const char* prop = "0";
     property_set("hw.underscan_supported", prop);
 }
 
-int HDMIDisplay::getModeOrder(int mode)
-{
-    for (int dataIndex = 0; dataIndex < gEDIDCount; dataIndex++) {
-        if (gEDIDData[dataIndex].mMode == mode) {
-            return gEDIDData[dataIndex].mModeOrder;
-        }
-    }
-    ALOGE("%s Mode not found: %d", __FUNCTION__, mode);
-    return -1;
-}
-
 /// Returns the index of the user mode set(if any) using adb shell
 int HDMIDisplay::getUserConfig() {
     /* Based on the property set the resolution */
     char property_value[PROPERTY_VALUE_MAX];
     property_get("hw.hdmi.resolution", property_value, "-1");
     int mode = atoi(property_value);
-    // We dont support interlaced modes
-    if(isValidMode(mode) && !isInterlacedMode(mode)) {
+    if(isValidMode(mode)) {
         ALOGD_IF(DEBUG, "%s: setting the HDMI mode = %d", __FUNCTION__, mode);
         return getModeIndex(mode);
     }
@@ -453,61 +399,137 @@
 
 // Get the index of the best mode for the current HD TV
 int HDMIDisplay::getBestConfig() {
-    int bestOrder = 0;
-    int bestMode = HDMI_VFRMT_640x480p60_4_3;
-    int bestModeIndex = -1;
-    // for all the edid read, get the best mode
-    for(int i = 0; i < mModeCount; i++) {
-        int mode = mEDIDModes[i];
-        int order = getModeOrder(mode);
-        if (order > bestOrder) {
-            bestOrder = order;
-            bestMode = mode;
-            bestModeIndex = i;
+    int bestConfigIndex = 0;
+    int edidMode = -1;
+    struct msm_hdmi_mode_timing_info currentModeInfo = {0};
+    struct msm_hdmi_mode_timing_info bestModeInfo = {0};
+    bestModeInfo.video_format = 0;
+    bestModeInfo.active_v = 0;
+    bestModeInfo.active_h = 0;
+    bestModeInfo.refresh_rate = 0;
+    bestModeInfo.ar = HDMI_RES_AR_INVALID;
+
+    // for all the timing info read, get the best config
+    for (int configIndex = 0; configIndex < mModeCount; configIndex++) {
+        currentModeInfo = mDisplayConfigs[configIndex];
+
+        if (!currentModeInfo.supported) {
+            ALOGD("%s EDID Mode %d is not supported", __FUNCTION__, edidMode);
+            continue;
+        }
+
+        ALOGD_IF(DEBUG, "%s Best (%d) : (%dx%d) @ %d;"
+                " Current (%d) (%dx%d) @ %d",
+                __FUNCTION__, bestConfigIndex, bestModeInfo.active_h,
+                bestModeInfo.active_v, bestModeInfo.refresh_rate, configIndex,
+                currentModeInfo.active_h, currentModeInfo.active_v,
+                currentModeInfo.refresh_rate);
+
+        // Compare two HDMI modes in order of height, width, refresh rate and
+        // aspect ratio.
+        if (currentModeInfo.active_v > bestModeInfo.active_v) {
+            bestConfigIndex = configIndex;
+        } else if (currentModeInfo.active_v == bestModeInfo.active_v) {
+            if (currentModeInfo.active_h > bestModeInfo.active_h) {
+                bestConfigIndex = configIndex;
+            } else if (currentModeInfo.active_h == bestModeInfo.active_h) {
+                if (currentModeInfo.refresh_rate > bestModeInfo.refresh_rate) {
+                    bestConfigIndex = configIndex;
+                } else if (currentModeInfo.refresh_rate ==
+                        bestModeInfo.refresh_rate) {
+                    if (currentModeInfo.ar > bestModeInfo.ar) {
+                        bestConfigIndex = configIndex;
+                    }
+                }
+            }
+        }
+        if (bestConfigIndex == configIndex) {
+            bestModeInfo = mDisplayConfigs[bestConfigIndex];
         }
     }
-    // If we fail to read from EDID when HDMI is connected, then
-    // mModeCount will be 0 and bestModeIndex will be invalid.
-    // In this case, we populate the mEDIDModes structure with
-    // a default mode at index 0.
-    if (bestModeIndex == -1) {
-        bestModeIndex = 0;
-        mModeCount = 1;
-        mEDIDModes[bestModeIndex] = bestMode;
+    return bestConfigIndex;
+}
+
+// Utility function used to request HDMI driver to write a new page of timing
+// info into res_info node
+void HDMIDisplay::requestNewPage(int pageNumber) {
+    char pageString[PAGE_SIZE];
+    int fd = openDeviceNode("res_info", O_WRONLY);
+    if (fd >= 0) {
+        snprintf(pageString, sizeof(pageString), "%d", pageNumber);
+        ALOGD_IF(DEBUG, "%s: page=%s", __FUNCTION__, pageString);
+        ssize_t err = write(fd, pageString, sizeof(pageString));
+        if (err <= 0) {
+            ALOGE("%s: Write to res_info failed (%d)", __FUNCTION__, errno);
+        }
+        close(fd);
     }
-    return bestModeIndex;
+}
+
+// Reads the contents of res_info node into a buffer if the file is not empty
+bool HDMIDisplay::readResFile(char * configBuffer) {
+    bool fileRead = false;
+    size_t bytesRead = 0;
+    int fd = openDeviceNode("res_info", O_RDONLY);
+    if (fd >= 0 && (bytesRead = read(fd, configBuffer, PAGE_SIZE)) != 0) {
+        fileRead = true;
+    }
+    close(fd);
+    ALOGD_IF(DEBUG, "%s: bytesRead=%d fileRead=%d",
+            __FUNCTION__, bytesRead, fileRead);
+    return fileRead;
+}
+
+// Populates the internal timing info structure with the timing info obtained
+// from the HDMI driver
+void HDMIDisplay::readConfigs() {
+    int configIndex = 0;
+    int pageNumber = MSM_HDMI_INIT_RES_PAGE;
+    long unsigned int size = sizeof(msm_hdmi_mode_timing_info);
+
+    while (true) {
+        char configBuffer[PAGE_SIZE] = {0};
+        msm_hdmi_mode_timing_info *info =
+                (msm_hdmi_mode_timing_info*) configBuffer;
+
+        if (!readResFile(configBuffer))
+            break;
+
+        while (info->video_format && size < PAGE_SIZE) {
+            mDisplayConfigs[configIndex] = *info;
+            size += sizeof(msm_hdmi_mode_timing_info);
+            info++;
+            ALOGD_IF(DEBUG, "%s: Config=%d Mode %d: (%dx%d) @ %d",
+                    __FUNCTION__, configIndex,
+                    mDisplayConfigs[configIndex].video_format,
+                    mDisplayConfigs[configIndex].active_h,
+                    mDisplayConfigs[configIndex].active_v,
+                    mDisplayConfigs[configIndex].refresh_rate);
+            configIndex++;
+        }
+        size = sizeof(msm_hdmi_mode_timing_info);
+        // Request HDMI driver to populate res_info with more
+        // timing information
+        pageNumber++;
+        requestNewPage(pageNumber);
+    }
 }
 
 inline bool HDMIDisplay::isValidMode(int ID)
 {
     bool valid = false;
-    for (int i = 0; i < mModeCount; i++) {
-        if(ID == mEDIDModes[i]) {
-            valid = true;
-            break;
-        }
+    int modeIndex = getModeIndex(ID);
+    if (ID <= 0 || modeIndex < 0 || modeIndex > mModeCount) {
+        return false;
+    }
+    struct msm_hdmi_mode_timing_info* mode = &mDisplayConfigs[modeIndex];
+    // We dont support interlaced modes
+    if (mode->supported && !mode->interlaced) {
+        valid = true;
     }
     return valid;
 }
 
-// returns true if the mode(ID) is interlaced mode format
-bool HDMIDisplay::isInterlacedMode(int ID) {
-    bool interlaced = false;
-    switch(ID) {
-        case HDMI_VFRMT_1440x480i60_4_3:
-        case HDMI_VFRMT_1440x480i60_16_9:
-        case HDMI_VFRMT_1440x576i50_4_3:
-        case HDMI_VFRMT_1440x576i50_16_9:
-        case HDMI_VFRMT_1920x1080i60_16_9:
-            interlaced = true;
-            break;
-        default:
-            interlaced = false;
-            break;
-    }
-    return interlaced;
-}
-
 // Does a put_vscreen info on the HDMI interface which will update
 // the configuration (resolution, timing info) to match mCurrentMode
 void HDMIDisplay::activateDisplay()
@@ -525,16 +547,7 @@
             mVInfo.lower_margin, mVInfo.vsync_len, mVInfo.upper_margin,
             mVInfo.pixclock/1000/1000);
 
-    const struct msm_hdmi_mode_timing_info *mode =
-            &supported_video_mode_lut[0];
-    for (unsigned int i = 0; i < HDMI_VFRMT_MAX; ++i) {
-        const struct msm_hdmi_mode_timing_info *cur =
-                &supported_video_mode_lut[i];
-        if (cur->video_format == (uint32_t)mCurrentMode) {
-            mode = cur;
-            break;
-        }
-    }
+    struct msm_hdmi_mode_timing_info *mode = &mDisplayConfigs[mActiveConfig];
     setDisplayTiming(mVInfo, mode);
     ALOGD_IF(DEBUG, "%s: SET Info<ID=%d => Info<ID=%d %dx %d"
             "(%d,%d,%d), (%d,%d,%d) %dMHz>", __FUNCTION__, mCurrentMode,
@@ -585,9 +598,9 @@
 
 
 void HDMIDisplay::setAttributes() {
-    uint32_t fps = 0;
+    uint32_t refresh = 0, fps = 0;
     // Always set dpyAttr res to mVInfo res
-    getAttrForMode(mXres, mYres, fps);
+    getAttrForConfig(mActiveConfig, mXres, mYres, refresh, fps);
     mMDPScalingMode = false;
 
     if(overlay::Overlay::getInstance()->isUIScalingOnExternalSupported()
@@ -653,19 +666,6 @@
     ALOGD_IF(DEBUG, "%s xres=%d, yres=%d", __FUNCTION__, mXres, mYres);
 }
 
-void HDMIDisplay::getAttrForMode(uint32_t& width, uint32_t& height,
-        uint32_t& fps) {
-    for (int dataIndex = 0; dataIndex < gEDIDCount; dataIndex++) {
-        if (gEDIDData[dataIndex].mMode == mCurrentMode) {
-            width = gEDIDData[dataIndex].mWidth;
-            height = gEDIDData[dataIndex].mHeight;
-            fps = gEDIDData[dataIndex].mFps;
-            return;
-        }
-    }
-    ALOGE("%s Unable to get attributes for %d", __FUNCTION__, mCurrentMode);
-}
-
 /* returns the fd related to the node specified*/
 int HDMIDisplay::openDeviceNode(const char* node, int fileMode) const {
     char sysFsFilePath[MAX_SYSFS_FILE_PATH];
@@ -743,8 +743,8 @@
 // not match the current config
 bool HDMIDisplay::isValidConfigChange(int newConfig) {
     int newMode = mEDIDModes[newConfig];
-    uint32_t width = 0, height = 0, refresh = 0;
-    getAttrForConfig(newConfig, width, height, refresh);
+    uint32_t width = 0, height = 0, refresh = 0, fps = 0;
+    getAttrForConfig(newConfig, width, height, refresh, fps);
     return ((mXres == width) && (mYres == height)) || mEnableResolutionChange;
 }
 
@@ -760,21 +760,16 @@
 }
 
 int HDMIDisplay::getAttrForConfig(int config, uint32_t& xres,
-        uint32_t& yres, uint32_t& refresh) const {
+        uint32_t& yres, uint32_t& refresh, uint32_t& fps) const {
     if(config < 0 || config > mModeCount) {
         ALOGE("%s Invalid configuration %d", __FUNCTION__, config);
         return -EINVAL;
     }
-    int mode = mEDIDModes[config];
-    uint32_t fps = 0;
-    // Retrieve the mode attributes from gEDIDData
-    for (int dataIndex = 0; dataIndex < gEDIDCount; dataIndex++) {
-        if (gEDIDData[dataIndex].mMode == mode) {
-            xres = gEDIDData[dataIndex].mWidth;
-            yres = gEDIDData[dataIndex].mHeight;
-            fps = gEDIDData[dataIndex].mFps;
-        }
-    }
+
+    xres = mDisplayConfigs[config].active_h;
+    yres = mDisplayConfigs[config].active_v;
+    fps = (mDisplayConfigs[config].refresh_rate / 1000);
+
     refresh = (uint32_t) 1000000000l / fps;
     ALOGD_IF(DEBUG, "%s xres(%d) yres(%d) fps(%d) refresh(%d)", __FUNCTION__,
             xres, yres, fps, refresh);
diff --git a/libhdmi/hdmi.h b/libhdmi/hdmi.h
index d262a63..32c48ff 100644
--- a/libhdmi/hdmi.h
+++ b/libhdmi/hdmi.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2012-2015, The Linux Foundation. All rights reserved.
  *
  * Not a Contribution, Apache license notifications and license are
  * retained for attribution purposes only.
@@ -22,6 +22,7 @@
 #define HWC_HDMI_DISPLAY_H
 
 #include <linux/fb.h>
+#include <video/msm_hdmi_modes.h>
 
 struct msm_hdmi_mode_timing_info;
 
@@ -35,16 +36,6 @@
     HDMI_SCAN_BOTH_SUPPORTED     = 3
 };
 
-// Structure to store EDID related data
-struct EDIDData {
-    int mMode, mWidth, mHeight, mFps;
-    // Predetermined ordering for each mode
-    int mModeOrder;
-    EDIDData(int mode, int width, int height, int fps, int order)
-    : mMode(mode), mWidth(width), mHeight(height), mFps(fps), mModeOrder(order)
-    { }
-};
-
 class HDMIDisplay
 {
 public:
@@ -71,7 +62,7 @@
     int getActiveConfig() const { return mActiveConfig; };
     int setActiveConfig(int newConfig);
     int getAttrForConfig(int config, uint32_t& xres,
-            uint32_t& yres, uint32_t& refresh) const;
+            uint32_t& yres, uint32_t& refresh, uint32_t& fps) const;
     int getDisplayConfigs(uint32_t* configs, size_t* numConfigs) const;
 
 private:
@@ -90,10 +81,12 @@
     bool isInterlacedMode(int mode);
     void resetInfo();
     void setAttributes();
-    void getAttrForMode(uint32_t& width, uint32_t& height, uint32_t& fps);
     int openDeviceNode(const char* node, int fileMode) const;
     int getModeIndex(int mode);
     bool isValidConfigChange(int newConfig);
+    void requestNewPage(int pageNumber);
+    void readConfigs();
+    bool readResFile(char* configBuffer);
 
     int mFd;
     int mFbNum;
@@ -105,11 +98,11 @@
     int mActiveConfig;
     // mEDIDModes contains a list of HDMI video formats (modes) supported by the
     // HDMI display
-    int mEDIDModes[64];
+    int mEDIDModes[HDMI_VFRMT_MAX];
     int mModeCount;
     fb_var_screeninfo mVInfo;
     // Holds all the HDMI modes and timing info supported by driver
-    msm_hdmi_mode_timing_info* supported_video_mode_lut;
+    msm_hdmi_mode_timing_info *mDisplayConfigs;
     uint32_t mXres, mYres, mVsyncPeriod, mPrimaryWidth, mPrimaryHeight;
     bool mMDPScalingMode;
     bool mUnderscanSupported;
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index fd3bb69..adf48e7 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -255,6 +255,8 @@
     hwc_context_t* ctx = (hwc_context_t*)(dev);
     const int dpy = HWC_DISPLAY_PRIMARY;
     bool fbComp = false;
+    if (!ctx->mBootAnimCompleted)
+        processBootAnimCompleted(ctx);
     if (LIKELY(list && list->numHwLayers > 1) && ctx->dpyAttr[dpy].connected &&
             (ctx->dpyAttr[dpy].isActive ||
              ctx->mHDMIDisplay->isHDMIPrimaryDisplay())
@@ -752,7 +754,7 @@
     bool isVirtualDisplay = (disp == HWC_DISPLAY_VIRTUAL);
     // If hotpluggable or virtual displays are inactive return error
     if ((hotPluggable || isVirtualDisplay) && !ctx->dpyAttr[disp].connected) {
-        ALOGE("%s display (%d) is inactive", __FUNCTION__, disp);
+        ALOGW("%s display (%d) is not connected anymore", __FUNCTION__, disp);
         return -EINVAL;
     }
 
@@ -809,10 +811,11 @@
     const size_t NUM_DISPLAY_ATTRIBUTES = (sizeof(DISPLAY_ATTRIBUTES) /
             sizeof(DISPLAY_ATTRIBUTES)[0]);
 
-    uint32_t xres = 0, yres = 0, refresh = 0;
+    uint32_t xres = 0, yres = 0, refresh = 0, fps = 0;
     int ret = 0;
     if (hotPluggable) {
-        ret = ctx->mHDMIDisplay->getAttrForConfig(config, xres, yres, refresh);
+        ret = ctx->mHDMIDisplay->getAttrForConfig(config, xres,
+                yres, refresh, fps);
         if(ret < 0) {
             ALOGE("%s Error getting attributes for config %d",
                     __FUNCTION__, config);
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index 41c7f62..7fcb9a7 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -131,6 +131,21 @@
     return renderArea;
 }
 
+bool CopyBit::isLayerChanging(hwc_display_contents_1_t *list, int k) {
+    if((mLayerCache.hnd[k] != list->hwLayers[k].handle) ||
+            (mLayerCache.displayFrame[k].left !=
+                         list->hwLayers[k].displayFrame.left) ||
+            (mLayerCache.displayFrame[k].top !=
+                         list->hwLayers[k].displayFrame.top) ||
+            (mLayerCache.displayFrame[k].right !=
+                         list->hwLayers[k].displayFrame.right) ||
+            (mLayerCache.displayFrame[k].bottom !=
+                         list->hwLayers[k].displayFrame.bottom)) {
+        return 1;
+    }
+    return 0;
+}
+
 int CopyBit::getLayersChanging(hwc_context_t *ctx,
                       hwc_display_contents_1_t *list,
                       int dpy){
@@ -146,7 +161,7 @@
     int updatingLayerCount = 0;
     for (int k = ctx->listStats[dpy].numAppLayers-1; k >= 0 ; k--){
        //swap rect will kick in only for single updating layer
-       if(mLayerCache.hnd[k] != list->hwLayers[k].handle){
+       if(isLayerChanging(list, k)) {
            updatingLayerCount ++;
            if(updatingLayerCount == 1)
              changingLayerIndex = k;
@@ -163,19 +178,20 @@
        dirtyRect = list->hwLayers[changingLayerIndex].dirtyRect;
 #endif
 
-       for (int k = ctx->listStats[dpy].numAppLayers-1; k >= 0 ; k--){
-            //disable swap rect for overlapping visible layer(s)
-            hwc_rect_t displayFrame = list->hwLayers[k].displayFrame;
-            hwc_rect_t result = getIntersection(displayFrame,dirtyRect);
-            if((k != changingLayerIndex) && isValidRect(result)){
-              return -1;
+       for (int k = ctx->listStats[dpy].numAppLayers-1; k >= 0 ; k--) {
+           //disable swap rect in case of scaling and video .
+           private_handle_t *hnd =(private_handle_t *)list->hwLayers[k].handle;
+           if(needsScaling(&list->hwLayers[k])||( hnd && isYuvBuffer(hnd))) {
+               mFbCache.reset();
+               return -1;
            }
        }
-       mFbCache.insertAndUpdateFbCache(dirtyRect);
        if(mFbCache.getUnchangedFbDRCount(dirtyRect) <
-                                             NUM_RENDER_BUFFERS)
+                                             NUM_RENDER_BUFFERS) {
+               mFbCache.insertAndUpdateFbCache(dirtyRect);
               changingLayerIndex =  -1;
-    }else {
+       }
+    } else {
        mFbCache.reset();
        changingLayerIndex =  -1;
     }
@@ -189,23 +205,11 @@
 
    //dirty rect will enable only if
    //1.Only single layer is updating.
-   //2.No overlapping
-   //3.No scaling
-   //4.No video layer
+   //2.No scaling
+   //3.No video layer
    if(mSwapRectEnable == false)
       return -1;
-   int changingLayerIndex =  getLayersChanging(ctx, list, dpy);
-   //swap rect will kick in only for single updating layer
-   if(changingLayerIndex == -1){
-      return -1;
-   }
-   if(!needsScaling(&list->hwLayers[changingLayerIndex])){
-     private_handle_t *hnd =
-         (private_handle_t *)list->hwLayers[changingLayerIndex].handle;
-      if( hnd && !isYuvBuffer(hnd))
-           return  changingLayerIndex;
-   }
-   return -1;
+   return getLayersChanging(ctx, list, dpy);
 }
 
 bool CopyBit::prepareOverlap(hwc_context_t *ctx,
@@ -216,8 +220,13 @@
         return false;
     }
 
-    if (mEngine == NULL || !(validateParams(ctx, list))) {
-        ALOGE("%s: Invalid Params", __FUNCTION__);
+    if (mEngine == NULL) {
+        ALOGW("%s: Copybit HAL not enabled", __FUNCTION__);
+        return false;
+    }
+
+    if (!(validateParams(ctx, list))) {
+        ALOGE("%s: validateParams() failed", __FUNCTION__);
         return false;
     }
     PtorInfo* ptorInfo = &(ctx->mPtorInfo);
@@ -467,6 +476,7 @@
              list->hwLayers[abcRenderBufIdx].acquireFenceFd);
           }
           for(int i = abcRenderBufIdx + 1; i < layerCount; i++){
+             mDirtyLayerIndex = -1;
              int retVal = drawLayerUsingCopybit(ctx,
                &(list->hwLayers[i]),renderBuffer, 0);
              if(retVal < 0) {
@@ -475,8 +485,8 @@
           }
           // Get Release Fence FD of copybit for the App layer(s)
           copybit->flush_get_fence(copybit, copybitFd);
-          close(list->hwLayers[abcRenderBufIdx].acquireFenceFd);
-          list->hwLayers[abcRenderBufIdx].acquireFenceFd = -1;
+          close(list->hwLayers[last].acquireFenceFd);
+          list->hwLayers[last].acquireFenceFd = -1;
           return true;
        }
     }
@@ -528,19 +538,16 @@
     }
 
     mDirtyLayerIndex =  checkDirtyRect(ctx, list, dpy);
-    if( mDirtyLayerIndex != -1){
-          hwc_layer_1_t *layer = &list->hwLayers[mDirtyLayerIndex];
-#ifdef QCOM_BSP
-          clear(renderBuffer,layer->dirtyRect);
-#else
-          clear(renderBuffer,layer->displayFrame);
-#endif
-    } else {
-          hwc_rect_t clearRegion = {0,0,0,0};
-          if(CBUtils::getuiClearRegion(list, clearRegion, layerProp))
-             clear(renderBuffer, clearRegion);
-    }
+    ALOGD_IF (DEBUG_COPYBIT, "%s:Dirty Layer Index: %d",
+                                       __FUNCTION__, mDirtyLayerIndex);
+    hwc_rect_t clearRegion = {0,0,0,0};
+    mDirtyRect = list->hwLayers[last].displayFrame;
+    if (mDirtyLayerIndex != -1)
+        mDirtyRect = list->hwLayers[mDirtyLayerIndex].displayFrame;
 
+    if (CBUtils::getuiClearRegion(list, clearRegion, layerProp,
+                                                       mDirtyLayerIndex))
+             clear(renderBuffer, clearRegion);
     // numAppLayers-1, as we iterate from 0th layer index with HWC_COPYBIT flag
     for (int i = 0; i <= (ctx->listStats[dpy].numAppLayers-1); i++) {
         if(!(layerProp[i].mFlags & HWC_COPYBIT)) {
@@ -550,9 +557,6 @@
         if(ctx->copybitDrop[i]) {
             continue;
         }
-        //skip non updating layers
-        if((mDirtyLayerIndex != -1) && (mDirtyLayerIndex != i) )
-            continue;
         int ret = -1;
         if (list->hwLayers[i].acquireFenceFd != -1
                 && ctx->mMDP.version >= qdutils::MDP_V4_0) {
@@ -852,11 +856,18 @@
 #ifdef QCOM_BSP
     //change src and dst with dirtyRect
     if(mDirtyLayerIndex != -1) {
-      srcRect.l = layer->dirtyRect.left;
-      srcRect.t = layer->dirtyRect.top;
-      srcRect.r = layer->dirtyRect.right;
-      srcRect.b = layer->dirtyRect.bottom;
-      dstRect = srcRect;
+      hwc_rect_t result = getIntersection(displayFrame, mDirtyRect);
+      if(!isValidRect(result))
+             return true;
+      dstRect.l = result.left;
+      dstRect.t = result.top;
+      dstRect.r = result.right;
+      dstRect.b = result.bottom;
+
+      srcRect.l += (result.left - displayFrame.left);
+      srcRect.t += (result.top - displayFrame.top);
+      srcRect.r -= (displayFrame.right - result.right);
+      srcRect.b -= (displayFrame.bottom - result.bottom);
     }
 #endif
     // Copybit dst
@@ -1210,6 +1221,7 @@
    layerCount = ctx->listStats[dpy].numAppLayers;
    for (int i=0; i<ctx->listStats[dpy].numAppLayers; i++){
       hnd[i] = list->hwLayers[i].handle;
+      displayFrame[i] = list->hwLayers[i].displayFrame;
    }
 }
 
diff --git a/libhwcomposer/hwc_copybit.h b/libhwcomposer/hwc_copybit.h
index a7ce43e..6ead4a7 100644
--- a/libhwcomposer/hwc_copybit.h
+++ b/libhwcomposer/hwc_copybit.h
@@ -60,6 +60,7 @@
     struct LayerCache {
       int layerCount;
       buffer_handle_t hnd[MAX_NUM_APP_LAYERS];
+      hwc_rect_t displayFrame[MAX_NUM_APP_LAYERS];
       /* c'tor */
       LayerCache();
       /* clear caching info*/
@@ -129,10 +130,12 @@
     int mDirtyLayerIndex;
     LayerCache mLayerCache;
     FbCache mFbCache;
+    hwc_rect_t mDirtyRect;
     int getLayersChanging(hwc_context_t *ctx, hwc_display_contents_1_t *list,
                   int dpy);
     int checkDirtyRect(hwc_context_t *ctx, hwc_display_contents_1_t *list,
                   int dpy);
+    bool isLayerChanging(hwc_display_contents_1_t *list, int k);
 };
 
 }; //namespace qhwc
diff --git a/libhwcomposer/hwc_dump_layers.cpp b/libhwcomposer/hwc_dump_layers.cpp
index 6a8feb2..aad984d 100644
--- a/libhwcomposer/hwc_dump_layers.cpp
+++ b/libhwcomposer/hwc_dump_layers.cpp
@@ -130,7 +130,7 @@
         mDumpCntLimPng = (mDumpCntLimPng < 0) ? 0: mDumpCntLimPng;
         if (mDumpCntLimPng) {
             snprintf(mDumpDirPng, sizeof(mDumpDirPng),
-                    "/data/sfdump.png.%04d.%02d.%02d.%02d.%02d.%02d",
+                    "/data/misc/display/sfdump.png.%04d.%02d.%02d.%02d.%02d.%02d",
                     dumpTime.tm_year + 1900, dumpTime.tm_mon + 1,
                     dumpTime.tm_mday, dumpTime.tm_hour,
                     dumpTime.tm_min, dumpTime.tm_sec);
@@ -160,7 +160,7 @@
         mDumpCntLimRaw = (mDumpCntLimRaw < 0) ? 0: mDumpCntLimRaw;
         if (mDumpCntLimRaw) {
             snprintf(mDumpDirRaw, sizeof(mDumpDirRaw),
-                    "/data/sfdump.raw.%04d.%02d.%02d.%02d.%02d.%02d",
+                    "/data/misc/display/sfdump.raw.%04d.%02d.%02d.%02d.%02d.%02d",
                     dumpTime.tm_year + 1900, dumpTime.tm_mon + 1,
                     dumpTime.tm_mday, dumpTime.tm_hour,
                     dumpTime.tm_min, dumpTime.tm_sec);
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index b63fb3a..8660740 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -541,7 +541,7 @@
             return false;
         }
 
-        if(ctx->mOverlay->comparePipePriority(destL, destR) == -1) {
+        if(ctx->mOverlay->needsPrioritySwap(destL, destR)) {
             qhwc::swap(destL, destR);
         }
 
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index d2962a3..caa1344 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -217,6 +217,9 @@
     mCurrentFrame.reset(numLayers);
     ctx->mOverlay->clear(mDpy);
     ctx->mLayerRotMap[mDpy]->clear();
+    resetROI(ctx, mDpy);
+    memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
+    mCurrentFrame.dropCount = 0;
 }
 
 void MDPComp::reset() {
@@ -390,9 +393,9 @@
 bool MDPComp::isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer) {
     private_handle_t *hnd = (private_handle_t *)layer->handle;
     if((has90Transform(layer) and (not isRotationDoable(ctx, hnd))) ||
-        (not isValidDimension(ctx,layer))
-        //More conditions here, SKIP, sRGB+Blend etc
-        ) {
+        (not isValidDimension(ctx,layer)) ||
+        isSkipLayer(layer)) {
+        //More conditions here, sRGB+Blend etc
         return false;
     }
     return true;
@@ -525,9 +528,11 @@
     return ret;
 }
 
-void MDPCompNonSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect) {
+void MDPCompNonSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect &crop,
+        hwc_rect &dst) {
     hwc_rect_t roi = ctx->listStats[mDpy].lRoi;
-    fbRect = getIntersection(fbRect, roi);
+    dst = getIntersection(dst, roi);
+    crop = dst;
 }
 
 /* 1) Identify layers that are not visible or lying outside the updating ROI and
@@ -593,7 +598,8 @@
             hwc_rect_t updatingRect = dst;
 
 #ifdef QCOM_BSP
-            if(!needsScaling(layer) && !layer->transform)
+            if(!needsScaling(layer) && !layer->transform &&
+                   (!isYuvBuffer((private_handle_t *)layer->handle)))
             {
                 hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
                 int x_off = dst.left - src.left;
@@ -622,14 +628,20 @@
             ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom);
 }
 
-void MDPCompSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect) {
-    hwc_rect l_roi = ctx->listStats[mDpy].lRoi;
-    hwc_rect r_roi = ctx->listStats[mDpy].rRoi;
-
-    hwc_rect_t l_fbRect = getIntersection(fbRect, l_roi);
-    hwc_rect_t r_fbRect = getIntersection(fbRect, r_roi);
-    fbRect = getUnion(l_fbRect, r_fbRect);
+void MDPCompSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect &crop,
+        hwc_rect &dst) {
+    hwc_rect roi = getUnion(ctx->listStats[mDpy].lRoi,
+            ctx->listStats[mDpy].rRoi);
+    hwc_rect tmpDst = getIntersection(dst, roi);
+    if(!isSameRect(dst, tmpDst)) {
+        crop.left = crop.left + (tmpDst.left - dst.left);
+        crop.top = crop.top + (tmpDst.top - dst.top);
+        crop.right = crop.left + (tmpDst.right - tmpDst.left);
+        crop.bottom = crop.top + (tmpDst.bottom - tmpDst.top);
+        dst = tmpDst;
+    }
 }
+
 /* 1) Identify layers that are not visible or lying outside BOTH the updating
  *    ROI's and drop them from composition. If a layer is spanning across both
  *    the halves of the screen but needed by only ROI, the non-contributing
@@ -782,13 +794,6 @@
         return false;
     }
 
-    if(isSkipPresent(ctx, mDpy)) {
-        ALOGD_IF(isDebug(),"%s: SKIP present: %d",
-                __FUNCTION__,
-                isSkipPresent(ctx, mDpy));
-        return false;
-    }
-
     // if secondary is configuring or Padding round, fall back to video only
     // composition and release all assigned non VIG pipes from primary.
     if(isSecondaryConfiguring(ctx)) {
@@ -1123,7 +1128,8 @@
     }
 
     bool ret = false;
-    if(list->flags & HWC_GEOMETRY_CHANGED) { //Try load based first
+    if(isSkipPresent(ctx, mDpy) or list->flags & HWC_GEOMETRY_CHANGED) {
+        //Try load based first
         ret =   loadBasedComp(ctx, list) or
                 cacheBasedComp(ctx, list);
     } else {
@@ -1761,7 +1767,7 @@
             fbRect = getUnion(fbRect, dst);
         }
     }
-    trimAgainstROI(ctx, fbRect);
+    trimAgainstROI(ctx, fbRect, fbRect);
     return fbRect;
 }
 
@@ -2608,6 +2614,122 @@
 }
 
 //================MDPCompSrcSplit==============================================
+
+bool MDPCompSrcSplit::validateAndApplyROI(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+    int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+    hwc_rect_t visibleRect = ctx->listStats[mDpy].lRoi;
+
+    for(int i = numAppLayers - 1; i >= 0; i--) {
+        if(!isValidRect(visibleRect)) {
+            mCurrentFrame.drop[i] = true;
+            mCurrentFrame.dropCount++;
+            continue;
+        }
+
+        const hwc_layer_1_t* layer =  &list->hwLayers[i];
+        hwc_rect_t dstRect = layer->displayFrame;
+        hwc_rect_t res  = getIntersection(visibleRect, dstRect);
+
+        if(!isValidRect(res)) {
+            mCurrentFrame.drop[i] = true;
+            mCurrentFrame.dropCount++;
+        } else {
+            /* Reset frame ROI when any layer which needs scaling also needs ROI
+             * cropping */
+            if(!isSameRect(res, dstRect) && needsScaling (layer)) {
+                ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
+                memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
+                mCurrentFrame.dropCount = 0;
+                return false;
+            }
+
+            /* deduct any opaque region from visibleRect */
+            if (layer->blending == HWC_BLENDING_NONE &&
+                    layer->planeAlpha == 0xFF)
+                visibleRect = deductRect(visibleRect, res);
+        }
+    }
+    return true;
+}
+
+/*
+ * HW Limitation: ping pong split can always split the ping pong output
+ * equally across two DSI's. So the ROI programmed should be of equal width
+ * for both the halves
+ */
+void MDPCompSrcSplit::generateROI(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+    int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+
+
+    if(!canPartialUpdate(ctx, list))
+        return;
+
+    struct hwc_rect roi = (struct hwc_rect){0, 0, 0, 0};
+    hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
+        (int)ctx->dpyAttr[mDpy].yres};
+
+    for(int index = 0; index < numAppLayers; index++ ) {
+        hwc_layer_1_t* layer = &list->hwLayers[index];
+
+        // If we have a RGB layer which needs rotation, no partial update
+        if(!isYuvBuffer((private_handle_t *)layer->handle) && layer->transform)
+            return;
+
+        if ((mCachedFrame.hnd[index] != layer->handle) ||
+                isYuvBuffer((private_handle_t *)layer->handle)) {
+            hwc_rect_t dst = layer->displayFrame;
+            hwc_rect_t updatingRect = dst;
+
+#ifdef QCOM_BSP
+            if(!needsScaling(layer) && !layer->transform)
+            {
+                hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
+                int x_off = dst.left - src.left;
+                int y_off = dst.top - src.top;
+                updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
+            }
+#endif
+
+            roi = getUnion(roi, updatingRect);
+        }
+    }
+
+    /* No layer is updating. Still SF wants a refresh.*/
+    if(!isValidRect(roi))
+        return;
+
+    roi = expandROIFromMidPoint(roi, fullFrame);
+
+    hwc_rect lFrame = fullFrame;
+    lFrame.right /= 2;
+    hwc_rect lRoi = getIntersection(roi, lFrame);
+
+    // Align ROI coordinates to panel restrictions
+    lRoi = getSanitizeROI(lRoi, lFrame);
+
+    hwc_rect rFrame = fullFrame;
+    rFrame.left = lFrame.right;
+    hwc_rect rRoi = getIntersection(roi, rFrame);
+
+    // Align ROI coordinates to panel restrictions
+    rRoi = getSanitizeROI(rRoi, rFrame);
+
+    roi = getUnion(lRoi, rRoi);
+
+    ctx->listStats[mDpy].lRoi = roi;
+    if(!validateAndApplyROI(ctx, list))
+        resetROI(ctx, mDpy);
+
+    ALOGD_IF(isDebug(),"%s: generated ROI: [%d, %d, %d, %d] [%d, %d, %d, %d]",
+            __FUNCTION__,
+            ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
+            ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom,
+            ctx->listStats[mDpy].rRoi.left, ctx->listStats[mDpy].rRoi.top,
+            ctx->listStats[mDpy].rRoi.right, ctx->listStats[mDpy].rRoi.bottom);
+}
+
 bool MDPCompSrcSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
         MdpPipeInfoSplit& pipe_info) {
     private_handle_t *hnd = (private_handle_t *)layer->handle;
@@ -2616,6 +2738,9 @@
     pipe_info.lIndex = ovutils::OV_INVALID;
     pipe_info.rIndex = ovutils::OV_INVALID;
 
+    if(qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() && !mDpy)
+        trimAgainstROI(ctx,crop, dst);
+
     //If 2 pipes are staged on a single stage of a mixer, then the left pipe
     //should have a higher priority than the right one. Pipe priorities are
     //starting with VG0, VG1 ... , RGB0 ..., DMA1
@@ -2647,19 +2772,21 @@
     const uint32_t lSplit = getLeftSplit(ctx, mDpy);
     const uint32_t dstWidth = dst.right - dst.left;
     const uint32_t dstHeight = dst.bottom - dst.top;
-    const uint32_t cropWidth = has90Transform(layer) ? crop.bottom - crop.top :
+    uint32_t cropWidth = has90Transform(layer) ? crop.bottom - crop.top :
             crop.right - crop.left;
-    const uint32_t cropHeight = has90Transform(layer) ? crop.right - crop.left :
+    uint32_t cropHeight = has90Transform(layer) ? crop.right - crop.left :
             crop.bottom - crop.top;
     //Approximation to actual clock, ignoring the common factors in pipe and
     //mixer cases like line_time
     const uint32_t layerClock = getLayerClock(dstWidth, dstHeight, cropHeight);
     const uint32_t mixerClock = lSplit;
 
-    //TODO Even if a 4k video is going to be rot-downscaled to dimensions under
-    //pipe line length, we are still using 2 pipes. This is fine just because
-    //this is source split where destination doesn't matter. Evaluate later to
-    //see if going through all the calcs to save a pipe is worth it
+    const uint32_t downscale = getRotDownscale(ctx, layer);
+    if(downscale) {
+        cropWidth /= downscale;
+        cropHeight /= downscale;
+    }
+
     if(dstWidth > mdpHw.getMaxPipeWidth() or
             cropWidth > mdpHw.getMaxPipeWidth() or
             (primarySplitAlways and
@@ -2669,12 +2796,8 @@
             return false;
         }
 
-        // Return values
-        // 1  Left pipe is higher priority, do nothing.
-        // 0  Pipes of same priority.
-        //-1  Right pipe is of higher priority, needs swap.
-        if(ctx->mOverlay->comparePipePriority(pipe_info.lIndex,
-                pipe_info.rIndex) == -1) {
+        if(ctx->mOverlay->needsPrioritySwap(pipe_info.lIndex,
+                    pipe_info.rIndex)) {
             qhwc::swap(pipe_info.lIndex, pipe_info.rIndex);
         }
     }
@@ -2707,6 +2830,17 @@
     ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
              "dest_pipeR: %d",__FUNCTION__, layer, z, lDest, rDest);
 
+    if(qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() && !mDpy) {
+        /* MDP driver crops layer coordinates against ROI in Non-Split
+         * and Split MDP comp. But HWC needs to crop them for source split.
+         * Reason: 1) Source split is efficient only when the final effective
+         *            load is distributed evenly across mixers.
+         *         2) We have to know the effective width of the layer that
+         *            the ROI needs to find the no. of pipes the layer needs.
+         */
+        trimAgainstROI(ctx, crop, dst);
+    }
+
     // Handle R/B swap
     if (layer->flags & HWC_FORMAT_RB_SWAP) {
         if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 302b047..7c46c1a 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -160,9 +160,9 @@
     /* validates the ROI generated for fallback conditions */
     virtual bool validateAndApplyROI(hwc_context_t *ctx,
             hwc_display_contents_1_t* list) = 0;
-    /* Trims fbRect calculated against ROI generated */
-    virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect) = 0;
-
+    /* Trims layer coordinates against ROI generated */
+    virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& crop,
+            hwc_rect& dst) = 0;
     /* set/reset flags for MDPComp */
     void setMDPCompLayerFlags(hwc_context_t *ctx,
                               hwc_display_contents_1_t* list);
@@ -315,8 +315,9 @@
     /* validates the ROI generated for fallback conditions */
     virtual bool validateAndApplyROI(hwc_context_t *ctx,
             hwc_display_contents_1_t* list);
-    /* Trims fbRect calculated against ROI generated */
-    virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect);
+    /* Trims layer coordinates against ROI generated */
+    virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& crop,
+            hwc_rect& dst);
 };
 
 class MDPCompSplit : public MDPComp {
@@ -342,6 +343,9 @@
     /* allocates pipes to selected candidates */
     virtual bool allocLayerPipes(hwc_context_t *ctx,
                                  hwc_display_contents_1_t* list);
+    /* Trims layer coordinates against ROI generated */
+    virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& crop,
+            hwc_rect& dst);
 private:
     /* Increments mdpCount if 4k2k yuv layer split is enabled.
      * updates framebuffer z order if fb lies above source-split layer */
@@ -357,8 +361,6 @@
     /* validates the ROI generated for fallback conditions */
     virtual bool validateAndApplyROI(hwc_context_t *ctx,
             hwc_display_contents_1_t* list);
-    /* Trims fbRect calculated against ROI generated */
-    virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect);
 };
 
 class MDPCompSrcSplit : public MDPCompSplit {
@@ -371,6 +373,12 @@
 
     virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
             PipeLayerPair& pipeLayerPair);
+    /* generates ROI based on the modified area of the frame */
+    virtual void generateROI(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list);
+    /* validates the ROI generated for fallback conditions */
+    virtual bool validateAndApplyROI(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list);
 };
 
 }; //namespace
diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp
index d1c68a5..c6179e4 100644
--- a/libhwcomposer/hwc_uevents.cpp
+++ b/libhwcomposer/hwc_uevents.cpp
@@ -121,10 +121,19 @@
             /* We need to send hotplug to SF only when we are disconnecting
              * HDMI as an external display. */
             if(dpy == HWC_DISPLAY_EXTERNAL) {
-                ALOGE_IF(UEVENT_DEBUG,"%s:Sending EXTERNAL OFFLINE hotplug"
-                        "event", __FUNCTION__);
+                ALOGI("%s: Sending EXTERNAL OFFLINE event", __FUNCTION__);
                 ctx->proc->hotplug(ctx->proc, dpy, EXTERNAL_OFFLINE);
             }
+
+            //On 8994, 8992 due to hardware limitations, we disable bwc
+            //when HDMI intf is active
+            if((qdutils::MDPVersion::getInstance().is8994() or
+                qdutils::MDPVersion::getInstance().is8092()) and
+                    qdutils::MDPVersion::getInstance().supportsBWC()) {
+                Locker::Autolock _l(ctx->mDrawLock);
+                ctx->mBWCEnabled = true;
+            }
+
             break;
         }
     case EXTERNAL_ONLINE:
@@ -136,6 +145,15 @@
                 break;
             }
 
+            //On 8994, 8992 due to hardware limitations, we disable bwc
+            //when HDMI intf is active
+            if((qdutils::MDPVersion::getInstance().is8994() or
+                qdutils::MDPVersion::getInstance().is8092()) and
+                    qdutils::MDPVersion::getInstance().supportsBWC()) {
+                Locker::Autolock _l(ctx->mDrawLock);
+                ctx->mBWCEnabled = false;
+            }
+
             if (ctx->mHDMIDisplay->isHDMIPrimaryDisplay()) {
                 ctx->mDrawLock.lock();
                 handle_online(ctx, dpy);
@@ -193,14 +211,13 @@
             ctx->mDrawLock.unlock();
 
             /* External display is HDMI */
-            ALOGE_IF(UEVENT_DEBUG, "%s: Sending EXTERNAL ONLINE"
-                    "hotplug event", __FUNCTION__);
+            ALOGI("%s: Sending EXTERNAL ONLINE event", __FUNCTION__);
             ctx->proc->hotplug(ctx->proc, dpy, EXTERNAL_ONLINE);
             break;
         }
     default:
         {
-            ALOGE("%s: Invalid state to swtich:%d", __FUNCTION__, switch_state);
+            ALOGE("%s: Invalid state to switch:%d", __FUNCTION__, switch_state);
             break;
         }
     }
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 8139013..9ea8246 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -44,6 +44,7 @@
 #include "hwc_virtual.h"
 #include "qd_utils.h"
 #include <sys/sysinfo.h>
+#include <dlfcn.h>
 
 using namespace qClient;
 using namespace qService;
@@ -74,7 +75,7 @@
 #endif
 #endif
 
-#define PROP_DEFAULT_APPBUFFER  "ro.sf.default_app_buffer"
+#define PROP_DEFAULT_APPBUFFER  "sf.default.app_buffer_count"
 #define MAX_RAM_SIZE  512*1024*1024
 #define qHD_WIDTH 540
 
@@ -389,6 +390,9 @@
     property_get("debug.sf.hwc.canUseABC", value, "0");
     ctx->enableABC  = atoi(value) ? true : false;
 
+    // Initializing boot anim completed check to false
+    ctx->mBootAnimCompleted = false;
+
     // Initialize gpu perfomance hint related parameters
     property_get("sys.hwc.gpu_perf_mode", value, "0");
 #ifdef QCOM_BSP
@@ -1455,10 +1459,6 @@
     nwr = getIntersection(nwr, fbDisplayFrame);
 }
 
-bool isExternalActive(hwc_context_t* ctx) {
-    return ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive;
-}
-
 void closeAcquireFds(hwc_display_contents_1_t* list) {
     if(LIKELY(list)) {
         for(uint32_t i = 0; i < list->numHwLayers; i++) {
@@ -2352,10 +2352,9 @@
 
 bool isDisplaySplit(hwc_context_t* ctx, int dpy) {
     qdutils::MDPVersion& mdpHw = qdutils::MDPVersion::getInstance();
-    if(ctx->dpyAttr[dpy].xres > mdpHw.getMaxPipeWidth()) {
+    if(ctx->dpyAttr[dpy].xres > mdpHw.getMaxMixerWidth()) {
         return true;
     }
-    //For testing we could split primary via device tree values
     if(dpy == HWC_DISPLAY_PRIMARY && mdpHw.getRightSplit()) {
         return true;
     }
@@ -2492,6 +2491,36 @@
     return (eqBounds == 3);
 }
 
+void processBootAnimCompleted(hwc_context_t *ctx) {
+    char value[PROPERTY_VALUE_MAX];
+    int boot_finished = 0, ret = -1;
+    int (*applyMode)(int) = NULL;
+    void *modeHandle = NULL;
+
+    // Reading property set on boot finish in SF
+    property_get("service.bootanim.exit", value, "0");
+    boot_finished = atoi(value);
+    if (!boot_finished)
+        return;
+
+    modeHandle = dlopen("libmm-qdcm.so", RTLD_NOW);
+    if (modeHandle) {
+        *(void **)&applyMode = dlsym(modeHandle, "applyDefaults");
+        if (applyMode) {
+            ret = applyMode(HWC_DISPLAY_PRIMARY);
+            if (ret)
+                ALOGD("%s: Not able to apply default mode", __FUNCTION__);
+        } else {
+            ALOGE("%s: No symbol applyDefaults found", __FUNCTION__);
+        }
+        dlclose(modeHandle);
+    } else {
+        ALOGE("%s: Not able to load libmm-qdcm.so", __FUNCTION__);
+    }
+
+    ctx->mBootAnimCompleted = true;
+}
+
 void BwcPM::setBwc(const hwc_context_t *ctx, const int& dpy,
         const private_handle_t *hnd,
         const hwc_rect_t& crop, const hwc_rect_t& dst,
@@ -2578,6 +2607,30 @@
     }
 }
 
+hwc_rect expandROIFromMidPoint(hwc_rect roi, hwc_rect fullFrame) {
+    int lRoiWidth = 0, rRoiWidth = 0;
+    int half_frame_width = fullFrame.right/2;
+
+    hwc_rect lFrame = fullFrame;
+    hwc_rect rFrame = fullFrame;
+    lFrame.right = (lFrame.right - lFrame.left)/2;
+    rFrame.left = lFrame.right;
+
+    hwc_rect lRoi = getIntersection(roi, lFrame);
+    hwc_rect rRoi = getIntersection(roi, rFrame);
+
+    lRoiWidth = lRoi.right - lRoi.left;
+    rRoiWidth = rRoi.right - rRoi.left;
+
+    if(lRoiWidth && rRoiWidth) {
+        if(lRoiWidth < rRoiWidth)
+            roi.left = half_frame_width - rRoiWidth;
+        else
+            roi.right = half_frame_width + lRoiWidth;
+    }
+    return roi;
+}
+
 void resetROI(hwc_context_t *ctx, const int dpy) {
     const int fbXRes = (int)ctx->dpyAttr[dpy].xres;
     const int fbYRes = (int)ctx->dpyAttr[dpy].yres;
@@ -2725,12 +2778,6 @@
 // Handles online events when HDMI is the primary display. In particular,
 // online events for hdmi connected before AND after boot up and HWC init.
 void handle_online(hwc_context_t* ctx, int dpy) {
-    //On 8994 due to hardware limitations, we disable bwc completely when HDMI
-    //intf is active
-    if(qdutils::MDPVersion::getInstance().is8994() and
-            qdutils::MDPVersion::getInstance().supportsBWC()) {
-        ctx->mBWCEnabled = false;
-    }
     // Close the current fd if it was opened earlier on when HWC
     // was initialized.
     if (ctx->dpyAttr[dpy].fd >= 0) {
@@ -2761,12 +2808,6 @@
     resetDisplayInfo(ctx, dpy);
     ctx->dpyAttr[dpy].connected = false;
     ctx->dpyAttr[dpy].isActive = false;
-    //On 8994 due to hardware limitations, we enable bwc only when HDMI
-    //intf is inactive
-    if(qdutils::MDPVersion::getInstance().is8994() and
-            qdutils::MDPVersion::getInstance().supportsBWC()) {
-        ctx->mBWCEnabled = true;
-    }
 }
 
 };//namespace qhwc
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 797f9b0..a97c59b 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -245,10 +245,10 @@
 
 inline hwc_rect_t integerizeSourceCrop(const hwc_frect_t& cropF) {
     hwc_rect_t cropI = {0,0,0,0};
-    cropI.left = int(ceilf(cropF.left));
-    cropI.top = int(ceilf(cropF.top));
-    cropI.right = int(floorf(cropF.right));
-    cropI.bottom = int(floorf(cropF.bottom));
+    cropI.left = int(floorf(cropF.left));
+    cropI.top = int(floorf(cropF.top));
+    cropI.right = int(ceilf(cropF.right));
+    cropI.bottom = int(ceilf(cropF.bottom));
     return cropI;
 }
 
@@ -280,7 +280,6 @@
 bool isRotatorSupportedFormat(private_handle_t *hnd);
 //Returns true, if the layer is YUV or the layer has been rendered by CPU
 bool isRotationDoable(hwc_context_t *ctx, private_handle_t *hnd);
-bool isExternalActive(hwc_context_t* ctx);
 bool isAlphaScaled(hwc_layer_1_t const* layer);
 bool needsScaling(hwc_layer_1_t const* layer);
 bool isDownscaleRequired(hwc_layer_1_t const* layer);
@@ -352,6 +351,9 @@
 // Resets display ROI to full panel resoluion
 void resetROI(hwc_context_t *ctx, const int dpy);
 
+// Modifies ROI even from middle of the screen
+hwc_rect expandROIFromMidPoint(hwc_rect roi, hwc_rect fullFrame);
+
 // Aligns updating ROI to panel restrictions
 hwc_rect_t getSanitizeROI(struct hwc_rect roi, hwc_rect boundary);
 
@@ -439,6 +441,9 @@
 // Returns true if rect1 is peripheral to rect2, false otherwise.
 bool isPeripheral(const hwc_rect_t& rect1, const hwc_rect_t& rect2);
 
+// Checks if boot animation has completed and applies default mode
+void processBootAnimCompleted(hwc_context_t *ctx);
+
 // Inline utility functions
 static inline bool isSkipLayer(const hwc_layer_1_t* l) {
     return (UNLIKELY(l && (l->flags & HWC_SKIP_LAYER)));
@@ -641,6 +646,8 @@
     bool mUseMetaDataRefreshRate;
    // Stores the hpd enabled status- avoids re-enabling HDP on suspend resume.
     bool mHPDEnabled;
+    //Used to notify that boot has completed
+    bool mBootAnimCompleted;
 };
 
 namespace qhwc {
diff --git a/libhwcomposer/hwc_virtual.cpp b/libhwcomposer/hwc_virtual.cpp
index 06418bf..a294a75 100644
--- a/libhwcomposer/hwc_virtual.cpp
+++ b/libhwcomposer/hwc_virtual.cpp
@@ -223,13 +223,15 @@
         private_handle_t* ohnd, int dpy) {
     bool scalingMode = false;
     int fbWidth = ctx->dpyAttr[dpy].xres;
-    int fbHeight =  ctx->dpyAttr[dpy].yres;
-    if((getWidth(ohnd) != fbWidth) || (getHeight(ohnd) != fbHeight)) {
+    int fbHeight = ctx->dpyAttr[dpy].yres;
+    int alW = 0, alH = 0;
+    getBufferSizeAndDimensions(fbWidth, fbHeight, ohnd->format, alW, alH);
+    if((getWidth(ohnd) != alW) || (getHeight(ohnd) != alH)) {
         scalingMode = true;
     }
     ctx->dpyAttr[dpy].mMDPScalingMode = scalingMode;
 
     ALOGD_IF(HWCVIRTUAL_LOG, "%s fb(%dx%d) outputBuffer(%dx%d) scalingMode=%d",
-            __FUNCTION__, fbWidth, fbHeight,
+            __FUNCTION__, alW, alH,
             getWidth(ohnd), getHeight(ohnd), scalingMode);
 }
diff --git a/libhwcomposer/hwc_vsync.cpp b/libhwcomposer/hwc_vsync.cpp
index 722916a..89f8044 100644
--- a/libhwcomposer/hwc_vsync.cpp
+++ b/libhwcomposer/hwc_vsync.cpp
@@ -157,7 +157,9 @@
                 }
             }
 
-            pread(pfd[dpy][ev].fd, vdata , MAX_DATA, 0);
+            memset(&vdata, '\0', sizeof(vdata));
+            // Read once from the fds to clear the first notify
+            pread(pfd[dpy][ev].fd, vdata , MAX_DATA - 1, 0);
             if (pfd[dpy][ev].fd >= 0)
                 pfd[dpy][ev].events = POLLPRI | POLLERR;
         }
@@ -170,7 +172,10 @@
                 for (int dpy = HWC_DISPLAY_PRIMARY; dpy < num_displays; dpy++) {
                     for(size_t ev = 0; ev < num_events; ev++) {
                         if (pfd[dpy][ev].revents & POLLPRI) {
-                            ssize_t len = pread(pfd[dpy][ev].fd, vdata, MAX_DATA, 0);
+                            // Clear vdata before writing into it
+                            memset(&vdata, '\0', sizeof(vdata));
+                            ssize_t len = pread(pfd[dpy][ev].fd, vdata,
+                                                MAX_DATA - 1, 0);
                             if (UNLIKELY(len < 0)) {
                                 // If the read was just interrupted - it is not
                                 // a fatal error. Just continue in this case
@@ -179,6 +184,7 @@
                                         __FUNCTION__, ev, dpy, strerror(errno));
                                 continue;
                             }
+                            vdata[len] = '\0';
                             event_list[ev].callback(ctx, dpy, vdata);
                         }
                     }
diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp
index c250919..a34e599 100644
--- a/liboverlay/overlay.cpp
+++ b/liboverlay/overlay.cpp
@@ -282,38 +282,62 @@
     return false;
 }
 
-int Overlay::comparePipePriority(utils::eDest pipe1Index,
+bool Overlay::needsPrioritySwap(utils::eDest pipe1Index,
         utils::eDest pipe2Index) {
     validate((int)pipe1Index);
     validate((int)pipe2Index);
+
     uint8_t pipe1Prio = mPipeBook[(int)pipe1Index].mPipe->getPriority();
     uint8_t pipe2Prio = mPipeBook[(int)pipe2Index].mPipe->getPriority();
-    if(pipe1Prio > pipe2Prio)
-        return -1;
-    else if(pipe1Prio < pipe2Prio)
-        return 1;
-    else {
+
+    int pipe1Id = mPipeBook[(int)pipe1Index].mPipe->getPipeId();
+    int pipe2Id = mPipeBook[(int)pipe2Index].mPipe->getPipeId();
+
+    utils::eMdpPipeType leftType = PipeBook::getPipeType(pipe1Index);
+    utils::eMdpPipeType rightType = PipeBook::getPipeType(pipe2Index);
+
+    if(pipe1Id >=0 && pipe2Id >=0) {
+        // LEFT priority should be higher then RIGHT
+        return (pipe1Prio > pipe2Prio);
+    } else if(pipe1Id < 0 && pipe2Id < 0) {
         // If we are here, Source Split is enabled and both pipes are
         // new requests. In this case left type should be of higher prio
         // than right type
-        utils::eMdpPipeType leftType = PipeBook::getPipeType(pipe1Index);
-        utils::eMdpPipeType rightType = PipeBook::getPipeType(pipe2Index);
-
         if(leftType == rightType) {
             //Safe. Onus on driver to assign correct pipes within same type
-            return 1;
-        } else if(leftType == OV_MDP_PIPE_DMA or rightType == OV_MDP_PIPE_VG) {
-            //If we are here, right is definitely a higher prio type.
+            return false;
+        } else {
             //This check takes advantage of having only 3 types and avoids 3
             //different failure combination checks.
-            return -1;
+            // Swap IF:
+            // ----------------
+            // | Left | Right |
+            // ================
+            // | DMA  | ViG   |
+            // ----------------
+            // | DMA  | RGB   |
+            // ----------------
+            // | RGB  | ViG   |
+            // ----------------
+            return (leftType == OV_MDP_PIPE_DMA or rightType == OV_MDP_PIPE_VG);
+        }
+    } else if(pipe1Id < 0) {
+        //LEFT needs new allocation.
+        if(leftType == rightType) {
+            // If RIGHT has highest priority(lowest id), swap it.
+            return (pipe2Id == PipeBook::pipeMinID[leftType]);
         } else {
-            //Types are correct priority-wise
-            return 1;
+            return (leftType == OV_MDP_PIPE_DMA or rightType == OV_MDP_PIPE_VG);
+        }
+    } else { /* if (pipe2Id < 0) */
+        // RIGHT needs new allocation.
+        if(leftType == rightType) {
+            // If LEFT has lowest priority(highest id), swap it.
+            return (pipe1Id == PipeBook::pipeMaxID[leftType]);
+        } else {
+            return (leftType == OV_MDP_PIPE_DMA or rightType == OV_MDP_PIPE_VG);
         }
     }
-
-    return 0;
 }
 
 bool Overlay::commit(utils::eDest dest) {
@@ -413,6 +437,13 @@
         }
     }
 
+    PipeBook::pipeMinID[OV_MDP_PIPE_RGB] = 8;
+    PipeBook::pipeMaxID[OV_MDP_PIPE_RGB] = (numPipesXType[OV_MDP_PIPE_RGB] == 3)? 32 : 512;
+    PipeBook::pipeMinID[OV_MDP_PIPE_VG] = 1;
+    PipeBook::pipeMaxID[OV_MDP_PIPE_VG] = (numPipesXType[OV_MDP_PIPE_VG] == 3)? 4 : 256;
+    PipeBook::pipeMinID[OV_MDP_PIPE_DMA] = 64;
+    PipeBook::pipeMaxID[OV_MDP_PIPE_DMA] = 128;
+
     FILE *displayDeviceFP = NULL;
     char fbType[MAX_FRAME_BUFFER_NAME_SIZE];
     char msmFbTypePath[MAX_FRAME_BUFFER_NAME_SIZE];
@@ -578,6 +609,8 @@
 int Overlay::PipeBook::sAllocatedBitmap = 0;
 utils::eMdpPipeType Overlay::PipeBook::pipeTypeLUT[utils::OV_MAX] =
     {utils::OV_MDP_PIPE_ANY};
+int Overlay::PipeBook::pipeMinID[utils::OV_MDP_PIPE_ANY] = {0};
+int Overlay::PipeBook::pipeMaxID[utils::OV_MDP_PIPE_ANY] = {0};
 void *Overlay::sLibScaleHandle = NULL;
 int (*Overlay::sFnProgramScale)(struct mdp_overlay_list *) = NULL;
 /* Dynamically link ABL library */
diff --git a/liboverlay/overlay.h b/liboverlay/overlay.h
index 984b439..45b5e57 100644
--- a/liboverlay/overlay.h
+++ b/liboverlay/overlay.h
@@ -123,11 +123,10 @@
      */
     bool isPipeTypeAttached(utils::eMdpPipeType type);
     /* Compare pipe priorities and return
-     * 1 if 1st pipe has a higher priority
-     * 0 if both have the same priority
-     *-1 if 2nd pipe has a higher priority
+     * true - A swap is needed to fix the priority.
+     * false - Good, priority wise.
      */
-    int comparePipePriority(utils::eDest pipe1Index, utils::eDest pipe2Index);
+    bool needsPrioritySwap(utils::eDest pipe1Index, utils::eDest pipe2Index);
     /* Returns pipe dump. Expects a NULL terminated buffer of big enough size
      * to populate.
      */
@@ -229,6 +228,9 @@
 
         static int NUM_PIPES;
         static utils::eMdpPipeType pipeTypeLUT[utils::OV_MAX];
+        static int pipeMinID[utils::OV_MDP_PIPE_ANY];
+        static int pipeMaxID[utils::OV_MDP_PIPE_ANY];
+
         /* Session for reserved pipes */
         enum Session {
             NONE,
diff --git a/liboverlay/overlayMdp.cpp b/liboverlay/overlayMdp.cpp
index 3932c4c..1290f32 100644
--- a/liboverlay/overlayMdp.cpp
+++ b/liboverlay/overlayMdp.cpp
@@ -374,8 +374,21 @@
     if(errVal) {
         /* No dump for failure due to insufficient resource */
         if(errVal != E2BIG) {
-            mdp_wrapper::dump("Bad ov dump: ",
-                *list.overlay_list[list.processed_overlays]);
+            //ENODEV is returned when the driver cannot satisfy a pipe request.
+            //This could happen if previous round's UNSET hasn't been commited
+            //yet, either because of a missed vsync or because of difference in
+            //vsyncs of primary and external. This is expected during
+            //transition scenarios, but should be considered fatal if seen
+            //continuously.
+            if(errVal == ENODEV) {
+                ALOGW("%s: Pipe unavailable. Likely previous UNSET pending. "
+                    "Fatal if seen continuously.", __FUNCTION__);
+            } else {
+                ALOGE("%s failed, error %d: %s", __FUNCTION__, errVal,
+                        strerror(errVal));
+                mdp_wrapper::dump("Bad ov dump: ",
+                        *list.overlay_list[list.processed_overlays]);
+            }
         }
         return false;
     }
diff --git a/libqdutils/cb_utils.cpp b/libqdutils/cb_utils.cpp
index ef66ac6..c17842a 100644
--- a/libqdutils/cb_utils.cpp
+++ b/libqdutils/cb_utils.cpp
@@ -41,13 +41,36 @@
 namespace qdutils {
 
 int CBUtils::getuiClearRegion(hwc_display_contents_1_t* list,
-          hwc_rect_t &clearWormholeRect, LayerProp *layerProp) {
+          hwc_rect_t &clearWormholeRect, LayerProp *layerProp, int dirtyIndex) {
 
     size_t last = list->numHwLayers - 1;
     hwc_rect_t fbFrame = list->hwLayers[last].displayFrame;
     Rect fbFrameRect(fbFrame.left,fbFrame.top,fbFrame.right,fbFrame.bottom);
     Region wormholeRegion(fbFrameRect);
 
+   if (dirtyIndex != -1) {
+#ifdef QCOM_BSP
+      /*
+       * 1. Map dirty rect of updating layer to its display frame.
+       * 2. Use this display frame as wormholeRegion instead of full Frame
+       * */
+      hwc_rect_t dirtyRect = list->hwLayers[dirtyIndex].dirtyRect;
+      hwc_rect_t displayFrame = list->hwLayers[dirtyIndex].displayFrame;
+      hwc_frect_t sCropF = list->hwLayers[dirtyIndex].sourceCropf;
+      hwc_rect_t srcRect = {int(ceilf(sCropF.left)), int(ceilf(sCropF.top)),
+                           int(ceilf(sCropF.right)), int(ceilf(sCropF.bottom))};
+
+      displayFrame.left += dirtyRect.left - srcRect.left;
+      displayFrame.top += dirtyRect.top - srcRect.top;
+      displayFrame.right -= srcRect.right - dirtyRect.right;
+      displayFrame.bottom -= srcRect.bottom - dirtyRect.bottom;
+
+      Rect tmpRect(displayFrame.left,displayFrame.top,displayFrame.right,
+            displayFrame.bottom);
+      Region tmpRegion(tmpRect);
+      wormholeRegion = wormholeRegion.intersect(tmpRegion);
+#endif
+   }
     if(cb_swap_rect::getInstance().checkSwapRectFeature_on() == true){
       wormholeRegion.set(0,0);
       for(size_t i = 0 ; i < last; i++) {
diff --git a/libqdutils/cb_utils.h b/libqdutils/cb_utils.h
index 85dd78f..59f452b 100644
--- a/libqdutils/cb_utils.h
+++ b/libqdutils/cb_utils.h
@@ -38,7 +38,7 @@
 public:
 static int getuiClearRegion(hwc_display_contents_1_t* list,
                               hwc_rect_t &clearWormholeRec,
-                                      LayerProp *layerProp);
+                              LayerProp *layerProp, int dirtyIndex = -1);
 };
 }//namespace qdutils
 #endif /* end of include guard: CB_UTIL_H*/
diff --git a/libqdutils/qdMetaData.cpp b/libqdutils/qdMetaData.cpp
index 88109c9..aae0a47 100644
--- a/libqdutils/qdMetaData.cpp
+++ b/libqdutils/qdMetaData.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2015, 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
@@ -93,6 +93,9 @@
         case MAP_SECURE_BUFFER:
             data->mapSecureBuffer = *((int32_t *)param);
             break;
+        case S3D_FORMAT:
+            data->s3dFormat = *((uint32_t *)param);
+            break;
         default:
             ALOGE("Unknown paramType %d", paramType);
             break;
diff --git a/libqdutils/qdMetaData.h b/libqdutils/qdMetaData.h
index 32d788e..a1afa38 100644
--- a/libqdutils/qdMetaData.h
+++ b/libqdutils/qdMetaData.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2015, 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
@@ -86,6 +86,9 @@
       * for clients to set, and GPU will to read and know when to map the
       * SECURE_BUFFER(ION) */
     int32_t mapSecureBuffer;
+    /* The supported formats are defined in gralloc_priv.h to
+     * support legacy code*/
+    uint32_t s3dFormat;
 };
 
 enum DispParamType {
@@ -100,6 +103,7 @@
     UPDATE_REFRESH_RATE = 0x0100,
     UPDATE_COLOR_SPACE = 0x0200,
     MAP_SECURE_BUFFER = 0x400,
+    S3D_FORMAT = 0x800,
 };
 
 struct private_handle_t;
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index ef47475..cd2d116 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -59,6 +59,7 @@
         CONFIGURE_DYN_REFRESH_RATE = 18,
         SET_PARTIAL_UPDATE = 19,   // Preference on partial update feature
         TOGGLE_SCREEN_UPDATE = 20, // Provides ability to disable screen updates
+        SET_FRAME_DUMP_CONFIG = 21,  // Provides ability to set the frame dump config
         COMMAND_LIST_END = 400,
     };
 
@@ -73,6 +74,14 @@
         DEBUG_VSYNC,
         DEBUG_VD,
         DEBUG_PIPE_LIFECYCLE,
+        DEBUG_DRIVER_CONFIG,
+        DEBUG_ROTATOR,
+    };
+
+    enum {
+        DUMP_PRIMARY_DISPLAY,
+        DUMP_HDMI_DISPLAY,
+        DUMP_VIRTUAL_DISPLAY,
     };
 
     // Register a client that can be notified