Merge "sde: Implement rotator session management in rotator controller"
diff --git a/displayengine/include/core/buffer_allocator.h b/displayengine/include/core/buffer_allocator.h
index 4081c54..d81c414 100644
--- a/displayengine/include/core/buffer_allocator.h
+++ b/displayengine/include/core/buffer_allocator.h
@@ -90,8 +90,7 @@
   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
+  @sa CoreInterface::CreateCore
 */
 class BufferAllocator {
  public:
@@ -102,8 +101,6 @@
     @param[in] buffer_info \link BufferInfo \endlink
 
     @return \link DisplayError \endlink
-
-    @sa BufferManager
   */
   virtual DisplayError AllocateBuffer(BufferInfo *buffer_info) = 0;
 
@@ -115,8 +112,6 @@
     @param[in] buffer_info \link BufferInfo \endlink
 
     @return \link DisplayError \endlink
-
-    @sa BufferManager
   */
   virtual DisplayError FreeBuffer(BufferInfo *buffer_info) = 0;
 
diff --git a/displayengine/include/core/buffer_sync_handler.h b/displayengine/include/core/buffer_sync_handler.h
index d0d062e..699d1a1 100644
--- a/displayengine/include/core/buffer_sync_handler.h
+++ b/displayengine/include/core/buffer_sync_handler.h
@@ -45,9 +45,7 @@
   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
+  @sa CoreInterface::CreateCore
 */
 class BufferSyncHandler {
  public:
@@ -58,8 +56,6 @@
     @param[in] fd
 
     @return \link DisplayError \endlink
-
-    @sa BufferManager::GetNextBuffer
   */
 
   virtual DisplayError SyncWait(int fd) = 0;
@@ -74,8 +70,6 @@
     @param[out] merged_fd
 
     @return \link DisplayError \endlink
-
-    @sa HWFrameBuffer::RotatorCommit
  */
 
   virtual DisplayError SyncMerge(int fd1, int fd2, int *merged_fd) = 0;
diff --git a/displayengine/include/core/debug_interface.h b/displayengine/include/core/debug_interface.h
index ff72321..9e83e46 100644
--- a/displayengine/include/core/debug_interface.h
+++ b/displayengine/include/core/debug_interface.h
@@ -46,8 +46,7 @@
   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.
+  kTagRotator,          //!< Debug log is tagged for rotator.
   kTagScalar,           //!< Debug log is tagged for Scalar Helper.
 };
 
diff --git a/displayengine/libs/core/Android.mk b/displayengine/libs/core/Android.mk
index 5623283..b1948fd 100644
--- a/displayengine/libs/core/Android.mk
+++ b/displayengine/libs/core/Android.mk
@@ -25,9 +25,9 @@
                                  strategy_default.cpp \
                                  res_manager.cpp \
                                  res_config.cpp \
-                                 offline_ctrl.cpp \
+                                 rotator_ctrl.cpp \
                                  dump_impl.cpp \
-                                 buffer_manager.cpp \
+                                 session_manager.cpp \
                                  scalar_helper.cpp \
                                  $(LOCAL_HW_INTF_PATH)/hw_info.cpp \
                                  $(LOCAL_HW_INTF_PATH)/hw_device.cpp \
diff --git a/displayengine/libs/core/buffer_manager.cpp b/displayengine/libs/core/buffer_manager.cpp
deleted file mode 100644
index 95c310a..0000000
--- a/displayengine/libs/core/buffer_manager.cpp
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
-* 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/comp_manager.cpp b/displayengine/libs/core/comp_manager.cpp
index 1ca7c16..82f7b8d 100644
--- a/displayengine/libs/core/comp_manager.cpp
+++ b/displayengine/libs/core/comp_manager.cpp
@@ -39,13 +39,12 @@
     registered_displays_(0), configured_displays_(0), safe_mode_(false) {
 }
 
-DisplayError CompManager::Init(const HWResourceInfo &hw_res_info, BufferAllocator *buffer_allocator,
-                               BufferSyncHandler *buffer_sync_handler) {
+DisplayError CompManager::Init(const HWResourceInfo &hw_res_info) {
   SCOPE_LOCK(locker_);
 
   DisplayError error = kErrorNone;
 
-  error = res_mgr_.Init(hw_res_info, buffer_allocator, buffer_sync_handler);
+  error = res_mgr_.Init(hw_res_info);
   if (error != kErrorNone) {
     return error;
   }
diff --git a/displayengine/libs/core/comp_manager.h b/displayengine/libs/core/comp_manager.h
index c445418..ae638e0 100644
--- a/displayengine/libs/core/comp_manager.h
+++ b/displayengine/libs/core/comp_manager.h
@@ -36,8 +36,7 @@
 class CompManager : public DumpImpl {
  public:
   CompManager();
-  DisplayError Init(const HWResourceInfo &hw_res_info_, BufferAllocator *buffer_allocator,
-                    BufferSyncHandler *buffer_sync_handler_);
+  DisplayError Init(const HWResourceInfo &hw_res_info_);
   DisplayError Deinit();
   DisplayError RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
                                const HWPanelInfo &hw_panel_info, Handle *res_mgr_hnd);
diff --git a/displayengine/libs/core/core_impl.cpp b/displayengine/libs/core/core_impl.cpp
index f04bbb9..4f68fcb 100644
--- a/displayengine/libs/core/core_impl.cpp
+++ b/displayengine/libs/core/core_impl.cpp
@@ -31,6 +31,7 @@
 #include "display_hdmi.h"
 #include "display_virtual.h"
 #include "hw_info_interface.h"
+#include "rotator_ctrl.h"
 
 #define __CLASS__ "CoreImpl"
 
@@ -39,7 +40,7 @@
 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_resource_(NULL) {
+    buffer_sync_handler_(buffer_sync_handler), hw_resource_(NULL), rotator_ctrl_(NULL) {
 }
 
 DisplayError CoreImpl::Init() {
@@ -62,16 +63,24 @@
     goto CleanUpOnError;
   }
 
-  error = comp_mgr_.Init(*hw_resource_, buffer_allocator_, buffer_sync_handler_);
+  error = comp_mgr_.Init(*hw_resource_);
   if (error != kErrorNone) {
-    comp_mgr_.Deinit();
     goto CleanUpOnError;
   }
 
-  error = offline_ctrl_.Init(buffer_sync_handler_);
-  if (error != kErrorNone) {
+  rotator_ctrl_ = new RotatorCtrl();
+  if (!rotator_ctrl_) {
+    comp_mgr_.Deinit();
+    error = kErrorMemory;
     goto CleanUpOnError;
   }
+
+  error = rotator_ctrl_->Init(buffer_allocator_, buffer_sync_handler_);
+  if (error != kErrorNone) {
+    delete rotator_ctrl_;
+    rotator_ctrl_ = NULL;
+  }
+
   return kErrorNone;
 
 CleanUpOnError:
@@ -88,7 +97,7 @@
 DisplayError CoreImpl::Deinit() {
   SCOPE_LOCK(locker_);
 
-  offline_ctrl_.Deinit();
+  rotator_ctrl_->Deinit();
   comp_mgr_.Deinit();
   HWInfoInterface::Destroy(hw_info_intf_);
 
@@ -108,15 +117,15 @@
   switch (type) {
   case kPrimary:
     display_base = new DisplayPrimary(event_handler, hw_info_intf_, buffer_sync_handler_,
-                                      &comp_mgr_, &offline_ctrl_);
+                                      &comp_mgr_, rotator_ctrl_);
     break;
   case kHDMI:
     display_base = new DisplayHDMI(event_handler, hw_info_intf_, buffer_sync_handler_,
-                                   &comp_mgr_, &offline_ctrl_);
+                                   &comp_mgr_, rotator_ctrl_);
     break;
   case kVirtual:
     display_base = new DisplayVirtual(event_handler, hw_info_intf_, buffer_sync_handler_,
-                                      &comp_mgr_, &offline_ctrl_);
+                                      &comp_mgr_, rotator_ctrl_);
     break;
   default:
     DLOGE("Spurious display type %d", type);
diff --git a/displayengine/libs/core/core_impl.h b/displayengine/libs/core/core_impl.h
index 03733a8..5ac1613 100644
--- a/displayengine/libs/core/core_impl.h
+++ b/displayengine/libs/core/core_impl.h
@@ -31,13 +31,13 @@
 
 #include "hw_interface.h"
 #include "comp_manager.h"
-#include "offline_ctrl.h"
 
 #define SET_REVISION(major, minor) ((major << 8) | minor)
 
 namespace sde {
 
 class HWInfoInterface;
+class RotatorCtrl;
 
 class CoreImpl : public CoreInterface {
  public:
@@ -66,7 +66,7 @@
   BufferSyncHandler *buffer_sync_handler_;
   HWResourceInfo *hw_resource_;
   CompManager comp_mgr_;
-  OfflineCtrl offline_ctrl_;
+  RotatorCtrl *rotator_ctrl_;
   HWInfoInterface *hw_info_intf_;
 };
 
diff --git a/displayengine/libs/core/display_base.cpp b/displayengine/libs/core/display_base.cpp
index be3b3a8..8725a7b 100644
--- a/displayengine/libs/core/display_base.cpp
+++ b/displayengine/libs/core/display_base.cpp
@@ -26,7 +26,7 @@
 #include <utils/debug.h>
 
 #include "display_base.h"
-#include "offline_ctrl.h"
+#include "rotator_ctrl.h"
 
 #define __CLASS__ "DisplayBase"
 
@@ -35,10 +35,10 @@
 // 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, BufferSyncHandler *buffer_sync_handler,
-                         CompManager *comp_manager, OfflineCtrl *offline_ctrl)
+                         CompManager *comp_manager, RotatorCtrl *rotator_ctrl)
   : display_type_(display_type), event_handler_(event_handler), hw_device_type_(hw_device_type),
     buffer_sync_handler_(buffer_sync_handler), comp_manager_(comp_manager),
-    offline_ctrl_(offline_ctrl), state_(kStateOff), hw_device_(0), display_comp_ctx_(0),
+    rotator_ctrl_(rotator_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) {
 }
@@ -79,9 +79,11 @@
     goto CleanupOnError;
   }
 
-  error = offline_ctrl_->RegisterDisplay(display_type_, &display_offline_ctx_);
-  if (error != kErrorNone) {
-    goto CleanupOnError;
+  if (rotator_ctrl_) {
+    error = rotator_ctrl_->RegisterDisplay(display_type_, &display_rotator_ctx_);
+    if (error != kErrorNone) {
+      goto CleanupOnError;
+    }
   }
 
   return kErrorNone;
@@ -102,7 +104,9 @@
 }
 
 DisplayError DisplayBase::Deinit() {
-  offline_ctrl_->UnregisterDisplay(display_offline_ctx_);
+  if (rotator_ctrl_) {
+    rotator_ctrl_->UnregisterDisplay(display_rotator_ctx_);
+  }
 
   comp_manager_->UnregisterDisplay(display_comp_ctx_);
 
@@ -137,7 +141,13 @@
         break;
       }
 
-      error = offline_ctrl_->Prepare(display_offline_ctx_, &hw_layers_);
+      if (IsRotationRequired(&hw_layers_)) {
+        if (!rotator_ctrl_) {
+          continue;
+        }
+        error = rotator_ctrl_->Prepare(display_rotator_ctx_, &hw_layers_);
+      }
+
       if (error == kErrorNone) {
         error = hw_intf_->Validate(&hw_layers_);
         if (error == kErrorNone) {
@@ -162,30 +172,41 @@
     return kErrorParameters;
   }
 
-  if (state_ == kStateOn) {
-    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_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 {
+  if (state_ != kStateOn) {
     return kErrorNotSupported;
   }
 
+  if (!pending_commit_) {
+    DLOGE("Commit: Corresponding Prepare() is not called for display = %d", display_type_);
+    return kErrorUndefined;
+  }
+
   pending_commit_ = false;
 
+  if (rotator_ctrl_ && IsRotationRequired(&hw_layers_)) {
+    error = rotator_ctrl_->Commit(display_rotator_ctx_, &hw_layers_);
+    if (error != kErrorNone) {
+      return error;
+    }
+  }
+
+  error = hw_intf_->Commit(&hw_layers_);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  if (rotator_ctrl_ && IsRotationRequired(&hw_layers_)) {
+    error = rotator_ctrl_->PostCommit(display_rotator_ctx_, &hw_layers_);
+    if (error != kErrorNone) {
+      return error;
+    }
+  }
+
+  error = comp_manager_->PostCommit(display_comp_ctx_, &hw_layers_);
+  if (error != kErrorNone) {
+    return error;
+  }
+
   return kErrorNone;
 }
 
@@ -406,10 +427,13 @@
     Layer &layer = hw_layers_.info.stack->layers[hw_layers_.info.index[i]];
     LayerBuffer *input_buffer = layer.input_buffer;
     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];
+
+    HWRotatorSession &hw_rotator_session = layer_config.hw_rotator_session;
+    HWRotateInfo &left_rotate = hw_rotator_session.hw_rotate_info[0];
+    HWRotateInfo &right_rotate = hw_rotator_session.hw_rotate_info[1];
 
     DumpImpl::AppendString(buffer, length, "\n\nsde idx: %u, actual idx: %u", i,
                            hw_layers_.info.index[i]);
@@ -458,5 +482,20 @@
   return (num_modes_ == 1) ? 0 : -1;
 }
 
+bool DisplayBase::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]];
+    HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
+
+    if (hw_rotator_session->hw_block_count) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
 }  // namespace sde
 
diff --git a/displayengine/libs/core/display_base.h b/displayengine/libs/core/display_base.h
index 6d107a0..1edef9e 100644
--- a/displayengine/libs/core/display_base.h
+++ b/displayengine/libs/core/display_base.h
@@ -31,18 +31,17 @@
 
 #include "hw_interface.h"
 #include "comp_manager.h"
-#include "buffer_manager.h"
 
 
 namespace sde {
 
-class OfflineCtrl;
+class RotatorCtrl;
 
 class DisplayBase : public DisplayInterface {
  public:
   DisplayBase(DisplayType display_type, DisplayEventHandler *event_handler,
               HWDeviceType hw_device_type, BufferSyncHandler *buffer_sync_handler,
-              CompManager *comp_manager, OfflineCtrl *offline_ctrl);
+              CompManager *comp_manager, RotatorCtrl *rotator_ctrl);
   virtual ~DisplayBase() { }
   virtual DisplayError Init();
   virtual DisplayError Deinit();
@@ -61,6 +60,9 @@
   virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
   virtual DisplayError SetDisplayMode(uint32_t mode);
 
+ private:
+  bool IsRotationRequired(HWLayers *hw_layers);
+
  protected:
   // DumpImpl method
   void AppendDump(char *buffer, uint32_t length);
@@ -75,11 +77,11 @@
   HWPanelInfo hw_panel_info_;
   BufferSyncHandler *buffer_sync_handler_;
   CompManager *comp_manager_;
-  OfflineCtrl *offline_ctrl_;
+  RotatorCtrl *rotator_ctrl_;
   DisplayState state_;
   Handle hw_device_;
   Handle display_comp_ctx_;
-  Handle display_offline_ctx_;
+  Handle display_rotator_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 2b6ba81..65ea21f 100644
--- a/displayengine/libs/core/display_hdmi.cpp
+++ b/displayengine/libs/core/display_hdmi.cpp
@@ -35,9 +35,9 @@
 
 DisplayHDMI::DisplayHDMI(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
                          BufferSyncHandler *buffer_sync_handler, CompManager *comp_manager,
-                         OfflineCtrl *offline_ctrl)
+                         RotatorCtrl *rotator_ctrl)
   : DisplayBase(kHDMI, event_handler, kDeviceHDMI, buffer_sync_handler, comp_manager,
-                offline_ctrl), hw_info_intf_(hw_info_intf) {
+                rotator_ctrl), hw_info_intf_(hw_info_intf) {
 }
 
 DisplayError DisplayHDMI::Init() {
diff --git a/displayengine/libs/core/display_hdmi.h b/displayengine/libs/core/display_hdmi.h
index fc2be21..1a96884 100644
--- a/displayengine/libs/core/display_hdmi.h
+++ b/displayengine/libs/core/display_hdmi.h
@@ -36,7 +36,7 @@
  public:
   DisplayHDMI(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
               BufferSyncHandler *buffer_sync_handler, CompManager *comp_manager,
-              OfflineCtrl *offline_ctrl);
+              RotatorCtrl *rotator_ctrl);
   virtual DisplayError Init();
   virtual DisplayError Deinit();
   virtual DisplayError Prepare(LayerStack *layer_stack);
diff --git a/displayengine/libs/core/display_primary.cpp b/displayengine/libs/core/display_primary.cpp
index 1dcd05b..d6116fa 100644
--- a/displayengine/libs/core/display_primary.cpp
+++ b/displayengine/libs/core/display_primary.cpp
@@ -35,9 +35,9 @@
 
 DisplayPrimary::DisplayPrimary(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
                                BufferSyncHandler *buffer_sync_handler, CompManager *comp_manager,
-                               OfflineCtrl *offline_ctrl)
+                               RotatorCtrl *rotator_ctrl)
   : DisplayBase(kPrimary, event_handler, kDevicePrimary, buffer_sync_handler, comp_manager,
-    offline_ctrl), hw_info_intf_(hw_info_intf) {
+    rotator_ctrl), hw_info_intf_(hw_info_intf) {
 }
 
 DisplayError DisplayPrimary::Init() {
diff --git a/displayengine/libs/core/display_primary.h b/displayengine/libs/core/display_primary.h
index da84fe6..be422de 100644
--- a/displayengine/libs/core/display_primary.h
+++ b/displayengine/libs/core/display_primary.h
@@ -36,7 +36,7 @@
  public:
   DisplayPrimary(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
                  BufferSyncHandler *buffer_sync_handler, CompManager *comp_manager,
-                 OfflineCtrl *offline_ctrl);
+                 RotatorCtrl *rotator_ctrl);
   virtual DisplayError Init();
   virtual DisplayError Deinit();
   virtual DisplayError Prepare(LayerStack *layer_stack);
diff --git a/displayengine/libs/core/display_virtual.cpp b/displayengine/libs/core/display_virtual.cpp
index a5af9bf..5480f0e 100644
--- a/displayengine/libs/core/display_virtual.cpp
+++ b/displayengine/libs/core/display_virtual.cpp
@@ -35,9 +35,9 @@
 
 DisplayVirtual::DisplayVirtual(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
                                BufferSyncHandler *buffer_sync_handler, CompManager *comp_manager,
-                               OfflineCtrl *offline_ctrl)
+                               RotatorCtrl *rotator_ctrl)
   : DisplayBase(kVirtual, event_handler, kDeviceVirtual, buffer_sync_handler, comp_manager,
-                offline_ctrl), hw_info_intf_(hw_info_intf) {
+                rotator_ctrl), hw_info_intf_(hw_info_intf) {
 }
 
 DisplayError DisplayVirtual::Init() {
diff --git a/displayengine/libs/core/display_virtual.h b/displayengine/libs/core/display_virtual.h
index 419c6ec..8e7a764 100644
--- a/displayengine/libs/core/display_virtual.h
+++ b/displayengine/libs/core/display_virtual.h
@@ -36,7 +36,7 @@
  public:
   DisplayVirtual(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
                  BufferSyncHandler *buffer_sync_handler, CompManager *comp_manager,
-                 OfflineCtrl *offline_ctrl);
+                 RotatorCtrl *rotator_ctrl);
   virtual DisplayError Init();
   virtual DisplayError Deinit();
   virtual DisplayError Prepare(LayerStack *layer_stack);
diff --git a/displayengine/libs/core/fb/hw_device.cpp b/displayengine/libs/core/fb/hw_device.cpp
index 685d322..230092a 100644
--- a/displayengine/libs/core/fb/hw_device.cpp
+++ b/displayengine/libs/core/fb/hw_device.cpp
@@ -213,14 +213,15 @@
     LayerBuffer *input_buffer = layer.input_buffer;
     HWPipeInfo *left_pipe = &hw_layers->config[i].left_pipe;
     HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe;
+    HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
     mdp_input_layer mdp_layer;
 
     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];
+      HWRotateInfo *hw_rotate_info = &hw_rotator_session->hw_rotate_info[count];
 
-      if (rotate_info->valid) {
-        input_buffer = &rotate_info->hw_buffer_info.output_buffer;
+      if (hw_rotate_info->valid) {
+        input_buffer = &hw_rotator_session->output_buffer;
       }
 
       if (pipe_info->valid) {
@@ -276,8 +277,9 @@
         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);
+                 "vert_deci %d, pipe_id = 0x%x, mdp_flags 0x%x", mdp_layer.alpha, mdp_layer.z_order,
+                 mdp_layer.blend_op, mdp_layer.horz_deci, mdp_layer.vert_deci, mdp_layer.pipe_ndx,
+                 mdp_layer.flags);
         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,
@@ -309,11 +311,11 @@
     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, "********************* 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, "*************************************************************");
+    DLOGI_IF(kTagDriverConfig, "*****************************************************************");
   }
 
   mdp_commit.flags |= MDP_VALIDATE_LAYER;
@@ -330,13 +332,13 @@
   mdp_layer_commit_v1 &mdp_commit = layer_commit.commit_v1;
   mdp_input_layer *mdp_layers = mdp_commit.input_layers;
 
-  DLOGE("mdp_commt: flags = %x, release fence = %x", mdp_commit.flags, mdp_commit.release_fence);
+  DLOGE("mdp_commit: flags = %x, release fence = %x", mdp_commit.flags, mdp_commit.release_fence);
   DLOGE("left_roi: x = %d, y = %d, w = %d, h = %d", mdp_commit.left_roi.x, mdp_commit.left_roi.y,
          mdp_commit.left_roi.w, mdp_commit.left_roi.h);
   DLOGE("right_roi: x = %d, y = %d, w = %d, h = %d", mdp_commit.right_roi.x,
          mdp_commit.right_roi.y, mdp_commit.right_roi.w, mdp_commit.right_roi.h);
   for (uint32_t i = 0; i < mdp_commit.input_layer_cnt; i++) {
-    DLOGE("mdp_commt: layer_cnt = %d, pipe_ndx = %x, zorder = %d, flags = %x",
+    DLOGE("mdp_commit: layer_cnt = %d, pipe_ndx = %x, zorder = %d, flags = %x",
           i, mdp_layers[i].pipe_ndx, mdp_layers[i].z_order, mdp_layers[i].flags);
     mdp_rect &src_rect = mdp_layers[i].src_rect;
     DLOGE("src rect: x = %d, y = %d, w = %d, h = %d",
@@ -365,13 +367,14 @@
     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;
+    HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
 
     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];
+      HWRotateInfo *hw_rotate_info = &hw_rotator_session->hw_rotate_info[count];
 
-      if (rotate_info->valid) {
-        input_buffer = &rotate_info->hw_buffer_info.output_buffer;
+      if (hw_rotate_info->valid) {
+        input_buffer = &hw_rotator_session->output_buffer;
       }
 
       if (pipe_info->valid) {
@@ -420,11 +423,11 @@
 
     mdp_out_layer_.buffer.fence = output_buffer->acquire_fence_fd;
 
-    DLOGI_IF(kTagDriverConfig, "******************* Output buffer Info **********************");
+    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, "*************************************************************");
+    DLOGI_IF(kTagDriverConfig, "*****************************************************************");
   }
 
   mdp_commit.release_fence = -1;
@@ -446,8 +449,9 @@
   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];
+    HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
+    HWRotateInfo *left_rotate = &hw_rotator_session->hw_rotate_info[0];
+    HWRotateInfo *right_rotate = &hw_rotator_session->hw_rotate_info[1];
 
     if (!left_rotate->valid && !right_rotate->valid) {
       input_buffer->release_fence_fd = dup(mdp_commit.release_fence);
@@ -455,9 +459,9 @@
     }
 
     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;
+      HWRotateInfo *hw_rotate_info = &hw_rotator_session->hw_rotate_info[count];
+      if (hw_rotate_info->valid) {
+        input_buffer = &hw_rotator_session->output_buffer;
         input_buffer->release_fence_fd = dup(mdp_commit.release_fence);
         close_(input_buffer->acquire_fence_fd);
         input_buffer->acquire_fence_fd = -1;
@@ -467,7 +471,7 @@
   DLOGI_IF(kTagDriverConfig, "*************************** %s Commit Input ************************",
            device_name_);
   DLOGI_IF(kTagDriverConfig, "retire_fence_fd %d", stack->retire_fence_fd);
-  DLOGI_IF(kTagDriverConfig, "*************************************************************");
+  DLOGI_IF(kTagDriverConfig, "*******************************************************************");
 
   close_(mdp_commit.release_fence);
 
@@ -531,7 +535,7 @@
 
 DisplayError HWDevice::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
+  // TODO(user): This SetStride function is a 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;
diff --git a/displayengine/libs/core/fb/hw_rotator.cpp b/displayengine/libs/core/fb/hw_rotator.cpp
index cc9caa5..cc9bd1a 100644
--- a/displayengine/libs/core/fb/hw_rotator.cpp
+++ b/displayengine/libs/core/fb/hw_rotator.cpp
@@ -36,8 +36,8 @@
 
 namespace sde {
 
-DisplayError HWRotatorInterface::Create(HWRotatorInterface **intf,
-                                        BufferSyncHandler *buffer_sync_handler) {
+DisplayError HWRotatorInterface::Create(BufferSyncHandler *buffer_sync_handler,
+                                        HWRotatorInterface **intf) {
   DisplayError error = kErrorNone;
   HWRotator *hw_rotator = NULL;
 
@@ -85,64 +85,93 @@
   return kErrorNone;
 }
 
-DisplayError HWRotator::OpenSession(HWRotateInfo *rotate_info) {
-  LayerBuffer *input_buffer = rotate_info->input_buffer;
-  HWBufferInfo *rot_buf_info = &rotate_info->hw_buffer_info;
+DisplayError HWRotator::OpenSession(HWRotatorSession *hw_rotator_session) {
+  uint32_t frame_rate = hw_rotator_session->hw_session_config.frame_rate;
+  LayerBufferFormat src_format = hw_rotator_session->hw_session_config.src_format;
+  LayerBufferFormat dst_format = hw_rotator_session->hw_session_config.dst_format;
+  bool rot90 = (hw_rotator_session->transform.rotation == 90.0f);
 
-  ResetRotatorParams();
+  for (uint32_t i = 0; i < hw_rotator_session->hw_block_count; i++) {
+    HWRotateInfo *hw_rotate_info = &hw_rotator_session->hw_rotate_info[i];
 
-  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;
-  HWDevice::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;
-  HWDevice::SetFormat(rot_buf_info->output_buffer.format, &mdp_rot_config.output.format);
-  mdp_rot_config.frame_rate = rotate_info->frame_rate;
+    if (!hw_rotate_info->valid) {
+      continue;
+    }
 
-  if (ioctl_(HWDevice::device_fd_, MDSS_ROTATION_OPEN, &mdp_rot_config) < 0) {
-    IOCTL_LOGE(MDSS_ROTATION_OPEN, HWDevice::device_type_);
-    return kErrorHardware;
+    uint32_t src_width = UINT32(hw_rotate_info->src_roi.right - hw_rotate_info->src_roi.left);
+    uint32_t src_height =
+        UINT32(hw_rotate_info->src_roi.bottom - hw_rotate_info->src_roi.top);
+
+    uint32_t dst_width = UINT32(hw_rotate_info->dst_roi.right - hw_rotate_info->dst_roi.left);
+    uint32_t dst_height =
+        UINT32(hw_rotate_info->dst_roi.bottom - hw_rotate_info->dst_roi.top);
+
+    STRUCT_VAR(mdp_rotation_config, mdp_rot_config);
+
+    mdp_rot_config.version = MDP_ROTATION_REQUEST_VERSION_1_0;
+    mdp_rot_config.input.width = src_width;
+    mdp_rot_config.input.height = src_height;
+    SetFormat(src_format, &mdp_rot_config.input.format);
+    mdp_rot_config.output.width = dst_width;
+    mdp_rot_config.output.height = dst_height;
+    SetFormat(dst_format, &mdp_rot_config.output.format);
+    mdp_rot_config.frame_rate = frame_rate;
+
+    if (rot90) {
+      mdp_rot_config.flags |= MDP_ROTATION_90;
+    }
+
+    if (ioctl_(device_fd_, MDSS_ROTATION_OPEN, &mdp_rot_config) < 0) {
+      IOCTL_LOGE(MDSS_ROTATION_OPEN, device_type_);
+      return kErrorHardware;
+    }
+
+    hw_rotate_info->rotate_id = mdp_rot_config.session_id;
+
+    DLOGV_IF(kTagDriverConfig, "session_id %d", hw_rotate_info->rotate_id);
   }
 
-  rot_buf_info->session_id = mdp_rot_config.session_id;
-
-  DLOGV_IF(kTagDriverConfig, "session_id %d", rot_buf_info->session_id);
-
   return kErrorNone;
 }
 
-DisplayError HWRotator::CloseSession(int32_t session_id) {
-  if (ioctl_(HWDevice::device_fd_, MDSS_ROTATION_CLOSE, (uint32_t)session_id) < 0) {
-    IOCTL_LOGE(MDSS_ROTATION_CLOSE, HWDevice::device_type_);
-    return kErrorHardware;
-  }
+DisplayError HWRotator::CloseSession(HWRotatorSession *hw_rotator_session) {
+  for (uint32_t i = 0; i < hw_rotator_session->hw_block_count; i++) {
+    HWRotateInfo *hw_rotate_info = &hw_rotator_session->hw_rotate_info[i];
 
-  DLOGV_IF(kTagDriverConfig, "session_id %d", session_id);
+    if (!hw_rotate_info->valid) {
+      continue;
+    }
+
+    if (ioctl_(device_fd_, MDSS_ROTATION_CLOSE, UINT32(hw_rotate_info->rotate_id)) < 0) {
+      IOCTL_LOGE(MDSS_ROTATION_CLOSE, device_type_);
+      return kErrorHardware;
+    }
+
+    DLOGV_IF(kTagDriverConfig, "session_id %d", hw_rotate_info->rotate_id);
+  }
 
   return kErrorNone;
 }
 
-void HWRotator::SetRotatorCtrlParams(HWLayers *hw_layers) {
+void HWRotator::SetCtrlParams(HWLayers *hw_layers) {
   DLOGV_IF(kTagDriverConfig, "************************* %s Validate Input ************************",
            HWDevice::device_name_);
 
-  ResetRotatorParams();
+  ResetParams();
 
   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]];
+    HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
+    bool rot90 = (layer.transform.rotation == 90.0f);
 
-    for (uint32_t count = 0; count < 2; count++) {
-      HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
+    for (uint32_t count = 0; count < hw_rotator_session->hw_block_count; count++) {
+      HWRotateInfo *hw_rotate_info = &hw_rotator_session->hw_rotate_info[count];
 
-      if (rotate_info->valid) {
-        HWBufferInfo *rot_buf_info = &rotate_info->hw_buffer_info;
+      if (hw_rotate_info->valid) {
         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;
@@ -156,8 +185,8 @@
           mdp_rot_item->flags |= MDP_ROTATION_FLIP_UD;
         }
 
-        HWDevice::SetRect(rotate_info->src_roi, &mdp_rot_item->src_rect);
-        HWDevice::SetRect(rotate_info->dst_roi, &mdp_rot_item->dst_rect);
+        SetRect(hw_rotate_info->src_roi, &mdp_rot_item->src_rect);
+        SetRect(hw_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;
@@ -165,11 +194,13 @@
 
         mdp_rot_item->input.width = layer.input_buffer->width;
         mdp_rot_item->input.height = layer.input_buffer->height;
-        HWDevice::SetFormat(layer.input_buffer->format, &mdp_rot_item->input.format);
+        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;
-        HWDevice::SetFormat(rot_buf_info->output_buffer.format, &mdp_rot_item->output.format);
+        mdp_rot_item->output.width = hw_rotator_session->output_buffer.width;
+        mdp_rot_item->output.height = hw_rotator_session->output_buffer.height;
+        SetFormat(hw_rotator_session->output_buffer.format, &mdp_rot_item->output.format);
+
+        mdp_rot_item->session_id = hw_rotate_info->rotate_id;
 
         rot_count++;
 
@@ -179,8 +210,9 @@
                  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, "pipe_id 0x%x, wb_id %d, rot_flag 0x%x, session_id %d",
+                 mdp_rot_item->pipe_idx, mdp_rot_item->wb_idx, mdp_rot_item->flags,
+                 mdp_rot_item->session_id);
         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,
@@ -191,7 +223,7 @@
   }
 }
 
-void HWRotator::SetRotatorBufferParams(HWLayers *hw_layers) {
+void HWRotator::SetBufferParams(HWLayers *hw_layers) {
   HWLayersInfo &hw_layer_info = hw_layers->info;
   uint32_t rot_count = 0;
 
@@ -201,26 +233,26 @@
 
   for (uint32_t i = 0; i < hw_layer_info.count; i++) {
     Layer& layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
+    HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
 
-    for (uint32_t count = 0; count < 2; count++) {
-      HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
+    for (uint32_t count = 0; count < hw_rotator_session->hw_block_count; count++) {
+      HWRotateInfo *hw_rotate_info = &hw_rotator_session->hw_rotate_info[count];
 
-      if (rotate_info->valid) {
-        HWBufferInfo *rot_buf_info = &rotate_info->hw_buffer_info;
+      if (hw_rotate_info->valid) {
         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;
-        HWDevice::SetStride(HWDevice::device_type_, layer.input_buffer->format,
-                            layer.input_buffer->width, &mdp_rot_item->input.planes[0].stride);
+        SetStride(device_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;
-        HWDevice::SetStride(HWDevice::device_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.planes[0].fd = hw_rotator_session->output_buffer.planes[0].fd;
+        mdp_rot_item->output.planes[0].offset = hw_rotator_session->output_buffer.planes[0].offset;
+        SetStride(device_type_, hw_rotator_session->output_buffer.format,
+                  hw_rotator_session->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;
 
@@ -243,7 +275,7 @@
 }
 
 DisplayError HWRotator::Validate(HWLayers *hw_layers) {
-  SetRotatorCtrlParams(hw_layers);
+  SetCtrlParams(hw_layers);
 
   mdp_rot_request_.flags = MDSS_ROTATION_REQUEST_VALIDATE;
   if (ioctl_(HWDevice::device_fd_, MDSS_ROTATION_REQUEST, &mdp_rot_request_) < 0) {
@@ -258,9 +290,9 @@
   HWLayersInfo &hw_layer_info = hw_layers->info;
   uint32_t rot_count = 0;
 
-  SetRotatorCtrlParams(hw_layers);
+  SetCtrlParams(hw_layers);
 
-  SetRotatorBufferParams(hw_layers);
+  SetBufferParams(hw_layers);
 
   mdp_rot_request_.flags &= ~MDSS_ROTATION_REQUEST_VALIDATE;
   if (ioctl_(HWDevice::device_fd_, MDSS_ROTATION_REQUEST, &mdp_rot_request_) < 0) {
@@ -270,20 +302,20 @@
 
   for (uint32_t i = 0; i < hw_layer_info.count; i++) {
     Layer& layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
+    HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
 
     layer.input_buffer->release_fence_fd = -1;
 
-    for (uint32_t count = 0; count < 2; count++) {
-      HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
+    for (uint32_t count = 0; count < hw_rotator_session->hw_block_count; count++) {
+      HWRotateInfo *hw_rotate_info = &hw_rotator_session->hw_rotate_info[count];
 
-      if (rotate_info->valid) {
-        HWBufferInfo *rot_buf_info = &rotate_info->hw_buffer_info;
+      if (hw_rotate_info->valid) {
         mdp_rotation_item *mdp_rot_item = &mdp_rot_request_.list[rot_count];
 
         HWDevice::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);
+        hw_rotator_session->output_buffer.acquire_fence_fd = dup(mdp_rot_item->output.fence);
 
         close_(mdp_rot_item->output.fence);
         rot_count++;
@@ -294,7 +326,7 @@
   return kErrorNone;
 }
 
-void HWRotator::ResetRotatorParams() {
+void HWRotator::ResetParams() {
   memset(&mdp_rot_request_, 0, sizeof(mdp_rot_request_));
   memset(&mdp_rot_layers_, 0, sizeof(mdp_rot_layers_));
 
diff --git a/displayengine/libs/core/fb/hw_rotator.h b/displayengine/libs/core/fb/hw_rotator.h
index 6e7727d..3b4eebe 100644
--- a/displayengine/libs/core/fb/hw_rotator.h
+++ b/displayengine/libs/core/fb/hw_rotator.h
@@ -44,15 +44,15 @@
   explicit HWRotator(BufferSyncHandler *buffer_sync_handler);
   virtual DisplayError Open();
   virtual DisplayError Close();
-  virtual DisplayError OpenSession(HWRotateInfo *hw_layers);
-  virtual DisplayError CloseSession(int32_t session_id);
+  virtual DisplayError OpenSession(HWRotatorSession *hw_session_info);
+  virtual DisplayError CloseSession(HWRotatorSession *hw_session_info);
   virtual DisplayError Validate(HWLayers *hw_layers);
   virtual DisplayError Commit(HWLayers *hw_layers);
 
  private:
-  void ResetRotatorParams();
-  void SetRotatorCtrlParams(HWLayers *hw_layers);
-  void SetRotatorBufferParams(HWLayers *hw_layers);
+  void ResetParams();
+  void SetCtrlParams(HWLayers *hw_layers);
+  void SetBufferParams(HWLayers *hw_layers);
 
   struct mdp_rotation_request mdp_rot_request_;
   struct mdp_rotation_item mdp_rot_layers_[kMaxSDELayers * 2];  // split panel (left + right)
diff --git a/displayengine/libs/core/hw_interface.h b/displayengine/libs/core/hw_interface.h
index 09fb6a9..36cb85e 100644
--- a/displayengine/libs/core/hw_interface.h
+++ b/displayengine/libs/core/hw_interface.h
@@ -43,33 +43,65 @@
   kHWBlockMax
 };
 
-struct HWBufferInfo : public BufferInfo {
-  LayerBuffer output_buffer;
-  int session_id;
-  uint32_t slot;
+struct HWSessionConfig {
+  uint32_t src_width;
+  uint32_t src_height;
+  LayerBufferFormat src_format;
+  uint32_t dst_width;
+  uint32_t dst_height;
+  LayerBufferFormat dst_format;
+  uint32_t buffer_count;
+  bool secure;
+  bool cache;
+  uint32_t frame_rate;
 
-  HWBufferInfo() : session_id(-1), slot(0) { }
+  HWSessionConfig()
+    : src_width(0), src_height(0), src_format(kFormatInvalid), dst_width(0), dst_height(0),
+      dst_format(kFormatInvalid), buffer_count(0), secure(false), cache(false), frame_rate(0) { }
+
+  bool operator != (const HWSessionConfig &input_config) const {
+    if ((src_width != input_config.src_width) || (src_height != input_config.src_height) ||
+        (src_format != input_config.src_format) || (dst_width != input_config.dst_width) ||
+        (dst_height != input_config.dst_height) || (dst_format != input_config.dst_format) ||
+        (buffer_count != input_config.buffer_count) || (secure != input_config.secure) ||
+        (cache != input_config.cache) || (frame_rate != input_config.frame_rate)) {
+      return true;
+    }
+
+    return false;
+  }
+
+  bool operator == (const HWSessionConfig &input_config) const {
+    return !(operator != (input_config));
+  }
 };
 
 struct HWRotateInfo {
-  LayerBuffer *input_buffer;
   uint32_t pipe_id;
   LayerRect src_roi;
   LayerRect dst_roi;
-  LayerBufferFormat dst_format;
   HWBlockType writeback_id;
-  float downscale_ratio;
-  HWBufferInfo hw_buffer_info;
   bool valid;
-  uint32_t frame_rate;
+  int rotate_id;
 
-  HWRotateInfo() : input_buffer(NULL), pipe_id(0), dst_format(kFormatInvalid),
-                   writeback_id(kHWWriteback0), downscale_ratio(1.0f), valid(false),
-                   frame_rate(0) { }
+  HWRotateInfo()
+    : pipe_id(0), writeback_id(kHWWriteback0), valid(false), rotate_id(-1) { }
 
   void Reset() { *this = HWRotateInfo(); }
 };
 
+struct HWRotatorSession {
+  HWRotateInfo hw_rotate_info[kMaxRotatePerLayer];
+  uint32_t hw_block_count;  // number of rotator hw blocks used by rotator session
+  float downscale_ratio;
+  LayerTransform transform;
+  HWSessionConfig hw_session_config;
+  LayerBuffer output_buffer;
+  int session_id;
+
+  HWRotatorSession() : hw_block_count(0), downscale_ratio(1.0f), session_id(-1) { }
+};
+
 struct HWPipeInfo {
   uint32_t pipe_id;
   LayerRect src_roi;
@@ -79,8 +111,8 @@
   bool valid;
   uint32_t z_order;
 
-  HWPipeInfo() : pipe_id(0), horizontal_decimation(0), vertical_decimation(0), valid(false),
-                 z_order(0) { }
+  HWPipeInfo()
+    : pipe_id(0), horizontal_decimation(0), vertical_decimation(0), valid(false), z_order(0) { }
 
   void Reset() { *this = HWPipeInfo(); }
 };
@@ -89,10 +121,9 @@
   bool use_non_dma_pipe;  // set by client
   HWPipeInfo left_pipe;  // pipe for left side of output
   HWPipeInfo right_pipe;  // pipe for right side of output
-  uint32_t num_rotate;  // number of rotate
-  HWRotateInfo rotates[kMaxRotatePerLayer];  // rotation for the buffer
+  HWRotatorSession hw_rotator_session;
 
-  HWLayerConfig() : use_non_dma_pipe(false), num_rotate(0) { }
+  HWLayerConfig() : use_non_dma_pipe(false) { }
 
   void Reset() { *this = HWLayerConfig(); }
 };
@@ -100,11 +131,6 @@
 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 {
diff --git a/displayengine/libs/core/hw_rotator_interface.h b/displayengine/libs/core/hw_rotator_interface.h
index 35876d6..0de5d52 100644
--- a/displayengine/libs/core/hw_rotator_interface.h
+++ b/displayengine/libs/core/hw_rotator_interface.h
@@ -30,15 +30,16 @@
 class BufferSyncHandler;
 struct HWRotateInfo;
 struct HWLayers;
+struct HWRotatorSession;
 
 class HWRotatorInterface {
  public:
-  static DisplayError Create(HWRotatorInterface **intf, BufferSyncHandler *buffer_sync_handler);
+  static DisplayError Create(BufferSyncHandler *buffer_sync_handler, HWRotatorInterface **intf);
   static DisplayError Destroy(HWRotatorInterface *intf);
   virtual DisplayError Open() = 0;
   virtual DisplayError Close() = 0;
-  virtual DisplayError OpenSession(HWRotateInfo *rotate_info) = 0;
-  virtual DisplayError CloseSession(int32_t session_id) = 0;
+  virtual DisplayError OpenSession(HWRotatorSession *hw_rotator_session) = 0;
+  virtual DisplayError CloseSession(HWRotatorSession *hw_rotator_session) = 0;
   virtual DisplayError Validate(HWLayers *hw_layers) = 0;
   virtual DisplayError Commit(HWLayers *hw_layers) = 0;
 
diff --git a/displayengine/libs/core/offline_ctrl.cpp b/displayengine/libs/core/offline_ctrl.cpp
deleted file mode 100644
index b7d5eef..0000000
--- a/displayengine/libs/core/offline_ctrl.cpp
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
-* 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 <utils/debug.h>
-
-#include "offline_ctrl.h"
-#include "hw_rotator_interface.h"
-#include <core/buffer_sync_handler.h>
-#include "hw_interface.h"
-
-#define __CLASS__ "OfflineCtrl"
-
-namespace sde {
-
-// 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_rotator_intf_(NULL), hw_rotator_present_(false) {
-}
-
-DisplayError OfflineCtrl::Init(BufferSyncHandler *buffer_sync_handler) {
-  DisplayError error = kErrorNone;
-
-  error = HWRotatorInterface::Create(&hw_rotator_intf_, buffer_sync_handler);
-  if (error != kErrorNone) {
-    if (hw_rotator_intf_) {
-      HWRotatorInterface::Destroy(hw_rotator_intf_);
-    }
-    return error;
-  }
-
-  error = hw_rotator_intf_->Open();
-  if (error != kErrorNone) {
-    DLOGW("Failed to open rotator device");
-  } else {
-    hw_rotator_present_ = true;
-  }
-
-  return kErrorNone;
-}
-
-DisplayError OfflineCtrl::Deinit() {
-  DisplayError error = kErrorNone;
-
-  error = hw_rotator_intf_->Close();
-  if (error != kErrorNone) {
-    DLOGW("Failed to close rotator device");
-    return error;
-  }
-  hw_rotator_present_ = false;
-  HWRotatorInterface::Destroy(hw_rotator_intf_);
-
-  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);
-
-  disp_offline_ctx->pending_rot_commit = false;
-
-  if (!hw_rotator_present_ && IsRotationRequired(hw_layers)) {
-    DLOGV_IF(kTagOfflineCtrl, "No Rotator device found");
-    return kErrorHardware;
-  }
-
-  error = CloseRotatorSession(hw_layers);
-  if (error != kErrorNone) {
-    DLOGE("Close rotator session failed for display %d", disp_offline_ctx->display_type);
-    return error;
-  }
-
-
-  if (IsRotationRequired(hw_layers)) {
-    error = OpenRotatorSession(hw_layers);
-    if (error != kErrorNone) {
-      DLOGE("Open rotator session failed for display %d", disp_offline_ctx->display_type);
-      return error;
-    }
-
-    error = hw_rotator_intf_->Validate(hw_layers);
-    if (error != kErrorNone) {
-      DLOGE("Rotator validation failed for display %d", disp_offline_ctx->display_type);
-      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_rotator_intf_->Commit(hw_layers);
-    if (error != kErrorNone) {
-      DLOGE("Rotator commit failed for display %d", disp_offline_ctx->display_type);
-      return error;
-    }
-    disp_offline_ctx->pending_rot_commit = false;
-  }
-
-  return kErrorNone;
-}
-
-DisplayError OfflineCtrl::OpenRotatorSession(HWLayers *hw_layers) {
-  HWLayersInfo &hw_layer_info = hw_layers->info;
-  DisplayError error = kErrorNone;
-
-  for (uint32_t i = 0; i < hw_layer_info.count; i++) {
-    Layer& layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
-    bool rot90 = (layer.transform.rotation == 90.0f);
-
-    for (uint32_t count = 0; count < 2; count++) {
-      HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
-      HWBufferInfo *rot_buf_info = &rotate_info->hw_buffer_info;
-
-      if (!rotate_info->valid || rot_buf_info->session_id >= 0) {
-        continue;
-      }
-
-      rotate_info->input_buffer = layer.input_buffer;
-      rotate_info->frame_rate = layer.frame_rate;
-
-      error = hw_rotator_intf_->OpenSession(rotate_info);
-      if (error != kErrorNone) {
-        return error;
-      }
-    }
-  }
-
-  return kErrorNone;
-}
-
-DisplayError OfflineCtrl::CloseRotatorSession(HWLayers *hw_layers) {
-  DisplayError error = kErrorNone;
-  uint32_t i = 0;
-
-  while (hw_layers->closed_session_ids[i] >= 0) {
-    error = hw_rotator_intf_->CloseSession(hw_layers->closed_session_ids[i]);
-    if (error != kErrorNone) {
-      return error;
-    }
-    hw_layers->closed_session_ids[i++] = -1;
-  }
-
-  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/res_config.cpp b/displayengine/libs/core/res_config.cpp
index ecd8ef1..3cea3db 100644
--- a/displayengine/libs/core/res_config.cpp
+++ b/displayengine/libs/core/res_config.cpp
@@ -44,7 +44,8 @@
 
 void ResManager::RotationConfig(const Layer &layer, const float &downscale, LayerRect *src_rect,
                                 struct HWLayerConfig *layer_config, uint32_t *rotate_count) {
-  HWRotateInfo *rotate = &layer_config->rotates[0];
+  HWRotatorSession *hw_rotator_session = &layer_config->hw_rotator_session;
+  HWRotateInfo *hw_rotate_info = &hw_rotator_session->hw_rotate_info[0];
   float src_width = src_rect->right - src_rect->left;
   float src_height = src_rect->bottom - src_rect->top;
   bool rot90 = IsRotationNeeded(layer.transform.rotation);
@@ -54,7 +55,7 @@
   dst_rect.top = 0.0f;
   dst_rect.left = 0.0f;
 
-  rotate->downscale_ratio = downscale;
+  hw_rotator_session->downscale_ratio = downscale;
   uint32_t align_x, align_y;
   GetAlignFactor(layer.input_buffer->format, &align_x, &align_y);
 
@@ -79,21 +80,17 @@
     dst_rect.bottom = src_height / downscale;
   }
 
-  rotate->src_roi = *src_rect;
-  rotate->valid = true;
-  rotate->dst_roi = dst_rect;
+  hw_rotate_info->src_roi = *src_rect;
+  hw_rotate_info->valid = true;
+  hw_rotate_info->dst_roi = dst_rect;
 
-  // Set WHF for Rotator output
-  LayerBufferFormat output_format;
+  LayerBufferFormat *output_format = &hw_rotator_session->output_buffer.format;
   SetRotatorOutputFormat(layer.input_buffer->format, is_opaque, rot90, (downscale > 1.0f),
-                         &output_format);
-  HWBufferInfo *hw_buffer_info = &rotate->hw_buffer_info;
-  hw_buffer_info->buffer_config.format = output_format;
-  hw_buffer_info->buffer_config.width = UINT32(rotate->dst_roi.right);
-  hw_buffer_info->buffer_config.height = UINT32(rotate->dst_roi.bottom);
+                         output_format);
 
   *src_rect = dst_rect;
-  layer_config->num_rotate = 1;
+  hw_rotator_session->hw_block_count = 1;
+  hw_rotator_session->transform = layer.transform;
   (*rotate_count)++;
 }
 
@@ -254,6 +251,9 @@
     struct HWLayerConfig *layer_config = &hw_layers->config[i];
     HWPipeInfo &left_pipe = layer_config->left_pipe;
     HWPipeInfo &right_pipe = layer_config->right_pipe;
+    HWRotatorSession *hw_rotator_session = &layer_config->hw_rotator_session;
+    LayerTransform transform = layer.transform;
+    bool rot90 = IsRotationNeeded(transform.rotation);
 
     if (!CalculateCropRects(scissor, layer.transform, &src_rect, &dst_rect)) {
       layer_config->Reset();
@@ -274,12 +274,11 @@
 
     // config rotator first
     for (uint32_t j = 0; j < kMaxRotatePerLayer; j++) {
-      layer_config->rotates[j].Reset();
+      hw_rotator_session->hw_rotate_info[j].Reset();
     }
-    layer_config->num_rotate = 0;
+    hw_rotator_session->hw_block_count = 0;
 
-    LayerTransform transform = layer.transform;
-    if (IsRotationNeeded(transform.rotation) || UINT32(rot_scale) != 1) {
+    if (rot90 || UINT32(rot_scale) != 1) {
       RotationConfig(layer, rot_scale, &src_rect, layer_config, rotate_count);
       // rotator will take care of flipping, reset tranform
       transform = LayerTransform();
@@ -306,10 +305,10 @@
              i, layer_config->left_pipe.valid);
     Log(kTagResources, "input layer src_rect", layer.src_rect);
     Log(kTagResources, "input layer dst_rect", layer.dst_rect);
-    for (uint32_t k = 0; k < layer_config->num_rotate; k++) {
+    for (uint32_t k = 0; k < hw_rotator_session->hw_block_count; k++) {
       DLOGV_IF(kTagResources, "rotate num = %d, scale_x = %.2f", k, rot_scale);
-      Log(kTagResources, "rotate src", layer_config->rotates[k].src_roi);
-      Log(kTagResources, "rotate dst", layer_config->rotates[k].dst_roi);
+      Log(kTagResources, "rotate src", hw_rotator_session->hw_rotate_info[k].src_roi);
+      Log(kTagResources, "rotate dst", hw_rotator_session->hw_rotate_info[k].dst_roi);
     }
 
     Log(kTagResources, "cropped src_rect", src_rect);
diff --git a/displayengine/libs/core/res_manager.cpp b/displayengine/libs/core/res_manager.cpp
index 4101fc8..08b055b 100644
--- a/displayengine/libs/core/res_manager.cpp
+++ b/displayengine/libs/core/res_manager.cpp
@@ -39,19 +39,12 @@
     buffer_allocator_(NULL), buffer_sync_handler_(NULL) {
 }
 
-DisplayError ResManager::Init(const HWResourceInfo &hw_res_info, BufferAllocator *buffer_allocator,
-                              BufferSyncHandler *buffer_sync_handler) {
+DisplayError ResManager::Init(const HWResourceInfo &hw_res_info) {
   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;
 
   num_pipe_ = hw_res_info_.num_vig_pipe + hw_res_info_.num_rgb_pipe + hw_res_info_.num_dma_pipe;
@@ -173,13 +166,6 @@
   }
 
   display_resource_ctx->hw_panel_info_ = hw_panel_info;
-  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;
@@ -315,6 +301,7 @@
   for (uint32_t i = 0; i < layer_info.count; i++) {
     Layer &layer = layer_info.stack->layers[layer_info.index[i]];
     struct HWLayerConfig &layer_config = hw_layers->config[i];
+    HWRotatorSession &hw_rotator_session = layer_config.hw_rotator_session;
     bool use_non_dma_pipe = layer_config.use_non_dma_pipe;
 
     // TODO(user): set this from comp_manager
@@ -322,8 +309,8 @@
       use_non_dma_pipe = true;
     }
 
-    for (uint32_t j = 0; j < layer_config.num_rotate; j++) {
-      AssignRotator(&layer_config.rotates[j], &rotate_count);
+    for (uint32_t j = 0; j < hw_rotator_session.hw_block_count; j++) {
+      AssignRotator(&hw_rotator_session.hw_rotate_info[j], &rotate_count);
     }
 
     HWPipeInfo *pipe_info = &layer_config.left_pipe;
@@ -406,12 +393,6 @@
     goto CleanupOnError;
   }
 
-  error = AllocRotatorBuffer(display_ctx, hw_layers);
-  if (error != kErrorNone) {
-    DLOGV_IF(kTagResources, "Rotator buffer allocation failed");
-    goto CleanupOnError;
-  }
-
   return kErrorNone;
 
 CleanupOnError:
@@ -662,84 +643,8 @@
   }
 }
 
-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) {
-      HWBufferInfo *hw_buffer_info = &rotate->hw_buffer_info;
-      // Allocate two rotator output buffers by default for double buffering.
-      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) {
-      HWBufferInfo *hw_buffer_info = &rotate->hw_buffer_info;
-      // Allocate two rotator output buffers by default for double buffering.
-      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;
 }
@@ -799,35 +704,6 @@
   }
   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;
 }
 
diff --git a/displayengine/libs/core/res_manager.h b/displayengine/libs/core/res_manager.h
index 1653c0a..a127645 100644
--- a/displayengine/libs/core/res_manager.h
+++ b/displayengine/libs/core/res_manager.h
@@ -31,15 +31,13 @@
 
 #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, BufferAllocator *buffer_allocator,
-                    BufferSyncHandler *buffer_sync_handler);
+  DisplayError Init(const HWResourceInfo &hw_res_info);
   DisplayError Deinit();
   DisplayError RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
                                const HWPanelInfo &hw_panel_info, Handle *display_ctx);
@@ -117,7 +115,6 @@
 
   struct DisplayResourceContext {
     HWDisplayAttributes display_attributes;
-    BufferManager *buffer_manager;
     DisplayType display_type;
     HWBlockType hw_block_id;
     HWPanelInfo hw_panel_info_;
@@ -129,13 +126,6 @@
 
     DisplayResourceContext() : hw_block_id(kHWBlockMax), frame_count(0), session_id(-1),
                     rotate_count(0), frame_start(false), max_mixer_stages(0) { }
-
-    ~DisplayResourceContext() {
-      if (buffer_manager) {
-        delete buffer_manager;
-        buffer_manager = NULL;
-      }
-    }
   };
 
   struct HWBlockContext {
@@ -203,7 +193,6 @@
                               const uint32_t roate_cnt);
   void AssignRotator(HWRotateInfo *rotate, uint32_t *rotate_cnt);
   void ClearRotator(DisplayResourceContext *display_resource_ctx);
-  DisplayError AllocRotatorBuffer(Handle display_ctx, HWLayers *hw_layers);
   void SetRotatorOutputFormat(const LayerBufferFormat &input_format, const bool &is_opaque,
                               const bool &rot90, const bool &downscale,
                               LayerBufferFormat *output_format);
diff --git a/displayengine/libs/core/rotator_ctrl.cpp b/displayengine/libs/core/rotator_ctrl.cpp
new file mode 100644
index 0000000..701006c
--- /dev/null
+++ b/displayengine/libs/core/rotator_ctrl.cpp
@@ -0,0 +1,233 @@
+/*
+* 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 <utils/debug.h>
+#include <utils/rect.h>
+#include <core/buffer_allocator.h>
+#include <core/buffer_sync_handler.h>
+
+#include "rotator_ctrl.h"
+#include "hw_rotator_interface.h"
+#include "hw_interface.h"
+#include "session_manager.h"
+
+#define __CLASS__ "RotatorCtrl"
+
+namespace sde {
+
+RotatorCtrl::RotatorCtrl() : hw_rotator_intf_(NULL) {
+}
+
+DisplayError RotatorCtrl::Init(BufferAllocator *buffer_allocator,
+                               BufferSyncHandler *buffer_sync_handler) {
+  DisplayError error = kErrorNone;
+
+  error = HWRotatorInterface::Create(buffer_sync_handler, &hw_rotator_intf_);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  error = hw_rotator_intf_->Open();
+  if (error != kErrorNone) {
+    DLOGE("Failed to open rotator device");
+    return error;
+  }
+
+  session_manager_ = new SessionManager(hw_rotator_intf_, buffer_allocator, buffer_sync_handler);
+  if (session_manager_ == NULL) {
+    HWRotatorInterface::Destroy(hw_rotator_intf_);
+    return kErrorMemory;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError RotatorCtrl::Deinit() {
+  DisplayError error = kErrorNone;
+
+  error = hw_rotator_intf_->Close();
+  if (error != kErrorNone) {
+    DLOGW("Failed to close rotator device");
+    return error;
+  }
+
+  if (session_manager_) {
+    delete session_manager_;
+    session_manager_ = NULL;
+  }
+
+  HWRotatorInterface::Destroy(hw_rotator_intf_);
+
+  return kErrorNone;
+}
+
+DisplayError RotatorCtrl::RegisterDisplay(DisplayType type, Handle *display_ctx) {
+  DisplaRotatorContext *disp_rotator_ctx = new DisplaRotatorContext();
+  if (disp_rotator_ctx == NULL) {
+    return kErrorMemory;
+  }
+
+  disp_rotator_ctx->display_type = type;
+  *display_ctx = disp_rotator_ctx;
+
+  return kErrorNone;
+}
+
+void RotatorCtrl::UnregisterDisplay(Handle display_ctx) {
+  DisplaRotatorContext *disp_rotator_ctx = reinterpret_cast<DisplaRotatorContext *>(display_ctx);
+
+  delete disp_rotator_ctx;
+  disp_rotator_ctx = NULL;
+}
+
+
+DisplayError RotatorCtrl::Prepare(Handle display_ctx, HWLayers *hw_layers) {
+  DisplayError error = kErrorNone;
+
+  DisplaRotatorContext *disp_rotator_ctx = reinterpret_cast<DisplaRotatorContext *>(display_ctx);
+
+  error = PrepareSessions(hw_layers);
+  if (error != kErrorNone) {
+    DLOGE("Prepare rotator session failed for display %d", disp_rotator_ctx->display_type);
+    return error;
+  }
+
+  error = hw_rotator_intf_->Validate(hw_layers);
+  if (error != kErrorNone) {
+    DLOGE("Rotator validation failed for display %d", disp_rotator_ctx->display_type);
+    return error;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError RotatorCtrl::Commit(Handle display_ctx, HWLayers *hw_layers) {
+  DisplayError error = kErrorNone;
+
+  DisplaRotatorContext *disp_rotator_ctx = reinterpret_cast<DisplaRotatorContext *>(display_ctx);
+
+  error = GetOutputBuffers(hw_layers);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  error = hw_rotator_intf_->Commit(hw_layers);
+  if (error != kErrorNone) {
+    DLOGE("Rotator commit failed for display %d", disp_rotator_ctx->display_type);
+    return error;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError RotatorCtrl::PostCommit(Handle display_ctx, HWLayers *hw_layers) {
+  HWLayersInfo &hw_layer_info = hw_layers->info;
+  DisplayError error = kErrorNone;
+  DisplaRotatorContext *disp_rotator_ctx = reinterpret_cast<DisplaRotatorContext *>(display_ctx);
+
+  for (uint32_t i = 0; i < hw_layer_info.count; i++) {
+    Layer& layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
+    HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
+
+    if (!hw_rotator_session->hw_block_count) {
+      continue;
+    }
+
+    error = session_manager_->SetReleaseFd(hw_rotator_session);
+    if (error != kErrorNone) {
+      DLOGE("Rotator Post commit failed for display %d", disp_rotator_ctx->display_type);
+      return error;
+    }
+  }
+
+  return kErrorNone;
+}
+
+DisplayError RotatorCtrl::PrepareSessions(HWLayers *hw_layers) {
+  HWLayersInfo &hw_layer_info = hw_layers->info;
+  DisplayError error = kErrorNone;
+
+  session_manager_->Start();
+
+  for (uint32_t i = 0; i < hw_layer_info.count; i++) {
+    Layer& layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
+    HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
+    HWSessionConfig &hw_session_config = hw_rotator_session->hw_session_config;
+    HWRotateInfo *left_rotate = &hw_rotator_session->hw_rotate_info[0];
+    HWRotateInfo *right_rotate = &hw_rotator_session->hw_rotate_info[1];
+
+    if (!hw_rotator_session->hw_block_count) {
+      continue;
+    }
+
+    hw_session_config.src_width = UINT32(layer.src_rect.right - layer.src_rect.left);
+    hw_session_config.src_height = UINT32(layer.src_rect.bottom - layer.src_rect.top);
+    hw_session_config.src_format = layer.input_buffer->format;
+
+    LayerRect dst_rect = Union(left_rotate->dst_roi, right_rotate->dst_roi);
+
+    hw_session_config.dst_width = UINT32(dst_rect.right - dst_rect.left);
+    hw_session_config.dst_height = UINT32(dst_rect.bottom - dst_rect.top);
+    hw_session_config.dst_format = hw_rotator_session->output_buffer.format;
+
+    // Allocate two rotator output buffers by default for double buffering.
+    hw_session_config.buffer_count = kDoubleBuffering;
+    hw_session_config.secure = layer.input_buffer->flags.secure;
+    hw_session_config.frame_rate = layer.frame_rate;
+
+    error = session_manager_->OpenSession(hw_rotator_session);
+    if (error != kErrorNone) {
+      return error;
+    }
+  }
+
+  session_manager_->Stop();
+
+  return kErrorNone;
+}
+
+DisplayError RotatorCtrl::GetOutputBuffers(HWLayers *hw_layers) {
+  HWLayersInfo &hw_layer_info = hw_layers->info;
+  DisplayError error = kErrorNone;
+
+  for (uint32_t i = 0; i < hw_layer_info.count; i++) {
+    Layer& layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
+    HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
+
+    if (!hw_rotator_session->hw_block_count) {
+      continue;
+    }
+
+    error = session_manager_->GetNextBuffer(hw_rotator_session);
+    if (error != kErrorNone) {
+      return error;
+    }
+  }
+
+  return kErrorNone;
+}
+
+}  // namespace sde
+
diff --git a/displayengine/libs/core/offline_ctrl.h b/displayengine/libs/core/rotator_ctrl.h
similarity index 76%
rename from displayengine/libs/core/offline_ctrl.h
rename to displayengine/libs/core/rotator_ctrl.h
index 1525bb8..083f4ca 100644
--- a/displayengine/libs/core/offline_ctrl.h
+++ b/displayengine/libs/core/rotator_ctrl.h
@@ -22,8 +22,8 @@
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-#ifndef __OFFLINE_CTRL_H__
-#define __OFFLINE_CTRL_H__
+#ifndef __ROTATOR_CTRL_H__
+#define __ROTATOR_CTRL_H__
 
 #include <utils/locker.h>
 #include <utils/debug.h>
@@ -32,36 +32,43 @@
 namespace sde {
 
 class HWRotatorInterface;
+class BufferAllocator;
 class BufferSyncHandler;
 struct HWLayers;
+class SessionManager;
 
-class OfflineCtrl {
+class RotatorCtrl {
  public:
-  OfflineCtrl();
-  DisplayError Init(BufferSyncHandler *buffer_sync_handler);
+  RotatorCtrl();
+  DisplayError Init(BufferAllocator *buffer_allocator, BufferSyncHandler *buffer_sync_handler);
   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);
+  DisplayError PostCommit(Handle display_ctx, HWLayers *hw_layers);
 
  private:
-  struct DisplayOfflineContext {
-    DisplayType display_type;
-    bool pending_rot_commit;
-
-    DisplayOfflineContext() : display_type(kPrimary), pending_rot_commit(false) { }
+  enum {
+    kSingleBuffering = 1,
+    kDoubleBuffering = 2,
+    kTripleBuffering = 3,
   };
 
-  DisplayError OpenRotatorSession(HWLayers *hw_layers);
-  DisplayError CloseRotatorSession(HWLayers *hw_layers);
-  bool IsRotationRequired(HWLayers *hw_layers);
+  struct DisplaRotatorContext {
+    DisplayType display_type;
+
+    DisplaRotatorContext() : display_type(kPrimary) { }
+  };
+
+  DisplayError PrepareSessions(HWLayers *hw_layers);
+  DisplayError GetOutputBuffers(HWLayers *hw_layers);
 
   HWRotatorInterface *hw_rotator_intf_;
-  bool hw_rotator_present_;
+  SessionManager *session_manager_;
 };
 
 }  // namespace sde
 
-#endif  // __OFFLINE_CTRL_H__
+#endif  // __ROTATOR_CTRL_H__
 
diff --git a/displayengine/libs/core/scalar_helper.cpp b/displayengine/libs/core/scalar_helper.cpp
index 55b462f..c81e343 100644
--- a/displayengine/libs/core/scalar_helper.cpp
+++ b/displayengine/libs/core/scalar_helper.cpp
@@ -137,6 +137,7 @@
     LayerBufferFormat format = layer.input_buffer->format;
     HWPipeInfo* left_pipe = &hw_layers->config[i].left_pipe;
     HWPipeInfo* right_pipe = &hw_layers->config[i].right_pipe;
+    HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
 
     // Prepare data structure for lib scalar
     uint32_t flags = 0;
@@ -152,12 +153,12 @@
 
     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];
+      HWRotateInfo* hw_rotate_info = &hw_rotator_session->hw_rotate_info[count];
       scalar::PipeInfo* pipe = (count == 0) ? &layer_info.left_pipe : &layer_info.right_pipe;
 
-      if (rotate_info->valid) {
-        width = rotate_info->hw_buffer_info.buffer_config.width;
-        format = rotate_info->hw_buffer_info.buffer_config.format;
+      if (hw_rotate_info->valid) {
+        width = UINT32(hw_rotate_info->dst_roi.right - hw_rotate_info->dst_roi.left);
+        format = hw_rotator_session->output_buffer.format;
       }
 
       pipe->flags = flags;
diff --git a/displayengine/libs/core/session_manager.cpp b/displayengine/libs/core/session_manager.cpp
new file mode 100644
index 0000000..f87bf10
--- /dev/null
+++ b/displayengine/libs/core/session_manager.cpp
@@ -0,0 +1,351 @@
+/*
+* 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 "session_manager.h"
+#include "hw_rotator_interface.h"
+
+#define __CLASS__ "SessionManager"
+
+namespace sde {
+
+// SessionManager State Transition
+// *******************************************************
+// Current State *             Next State
+//               *****************************************
+//               * RELEASED    READY        ACQUIRED
+// *******************************************************
+//  RELEASED     *    NA         NA        OpenSession()
+//  READY        *   Stop()      NA        OpenSession()
+//  ACQUIRED     *    NA       Start()          NA
+//********************************************************
+
+// ------------------------------- SessionManager Implementation -----------------------------------
+
+SessionManager::SessionManager(HWRotatorInterface *hw_rotator_intf,
+                               BufferAllocator *buffer_allocator,
+                               BufferSyncHandler *buffer_sync_handler)
+  : hw_rotator_intf_(hw_rotator_intf), buffer_allocator_(buffer_allocator),
+    buffer_sync_handler_(buffer_sync_handler), active_session_count_(0) {
+}
+
+void SessionManager::Start() {
+  uint32_t session_count = 0;
+  uint32_t ready_session_count = 0;
+
+  // Change the state of acquired session to kSessionReady
+  while ((ready_session_count < active_session_count_) && (session_count < kMaxSessionCount)) {
+    if (session_list_[session_count].state == kSessionReleased) {
+      session_count++;
+      continue;
+    }
+
+    session_list_[session_count++].state = kSessionReady;
+    ready_session_count++;
+  }
+}
+
+DisplayError SessionManager::OpenSession(HWRotatorSession *hw_rotator_session) {
+  DisplayError error = kErrorNone;
+
+  const HWSessionConfig &input_config = hw_rotator_session->hw_session_config;
+
+  DLOGI_IF(kTagRotator, "Src buffer: width = %d, height = %d, format = %d",
+           input_config.src_width, input_config.src_height, input_config.src_format);
+  DLOGI_IF(kTagRotator, "Dst buffer: width = %d, height = %d, format = %d",
+           input_config.dst_width, input_config.dst_height, input_config.dst_format);
+  DLOGI_IF(kTagRotator, "buffer_count = %d, secure = %d, cache = %d, frame_rate = %d",
+           input_config.buffer_count, input_config.secure, input_config.cache,
+           input_config.frame_rate);
+
+  uint32_t free_session = active_session_count_;
+  uint32_t acquired_session = kMaxSessionCount;
+  uint32_t ready_session_count = 0;
+
+  // First look for a session in ready state, if no session found in ready state matching
+  // with current input session config, assign a session in released state.
+  for (uint32_t session_count = 0; session_count < kMaxSessionCount &&
+       ready_session_count < active_session_count_; session_count++) {
+    HWSessionConfig &hw_session_config =
+           session_list_[session_count].hw_rotator_session.hw_session_config;
+
+    if (session_list_[session_count].state == kSessionReleased) {
+      free_session = session_count;
+      continue;
+    }
+
+    if (session_list_[session_count].state != kSessionReady) {
+      continue;
+    }
+
+    if (input_config == hw_session_config) {
+      session_list_[session_count].state = kSessionAcquired;
+      acquired_session = session_count;
+      break;
+    }
+
+    ready_session_count++;
+  }
+
+  // If the input config does not match with existing config, then add new session and change the
+  // state to kSessionAcquired
+  if (acquired_session == kMaxSessionCount) {
+    if (free_session >= kMaxSessionCount) {
+      return kErrorMemory;
+    }
+
+    error = AcquireSession(hw_rotator_session, &session_list_[free_session]);
+    if (error !=kErrorNone) {
+      return error;
+    }
+
+    acquired_session = free_session;
+    hw_rotator_session->session_id = acquired_session;
+    active_session_count_++;
+
+    DLOGV_IF(kTagRotator, "Acquire new session Output: width = %d, height = %d, format = %d, " \
+             "session_id %d", hw_rotator_session->output_buffer.width,
+             hw_rotator_session->output_buffer.height, hw_rotator_session->output_buffer.format,
+             hw_rotator_session->session_id);
+
+    return kErrorNone;
+  }
+
+  hw_rotator_session->output_buffer.width = input_config.dst_width;
+  hw_rotator_session->output_buffer.height = input_config.dst_height;
+  hw_rotator_session->output_buffer.format = input_config.dst_format;
+  hw_rotator_session->output_buffer.flags.secure = input_config.secure;
+  hw_rotator_session->session_id = acquired_session;
+
+  DLOGV_IF(kTagRotator, "Acquire existing session Output: width = %d, height = %d, format = %d, " \
+           "session_id %d", hw_rotator_session->output_buffer.width,
+           hw_rotator_session->output_buffer.height, hw_rotator_session->output_buffer.format,
+           hw_rotator_session->session_id);
+
+  return kErrorNone;
+}
+
+DisplayError SessionManager::GetNextBuffer(HWRotatorSession *hw_rotator_session) {
+  DisplayError error = kErrorNone;
+
+  int session_id = hw_rotator_session->session_id;
+  if (session_id > kMaxSessionCount) {
+    return kErrorParameters;
+  }
+
+  Session *session = &session_list_[session_id];
+  if (session->state != kSessionAcquired) {
+    DLOGE("Invalid session state %d", session->state);
+    kErrorParameters;
+  }
+
+  uint32_t curr_index = session->curr_index;
+
+  BufferInfo *buffer_info = &session->buffer_info;
+  if (buffer_info->alloc_buffer_info.fd < 0) {
+    const uint32_t &buffer_count = buffer_info->buffer_config.buffer_count;
+    const size_t &buffer_size = buffer_info->alloc_buffer_info.size;
+
+    error = buffer_allocator_->AllocateBuffer(buffer_info);
+    if (error != kErrorNone) {
+      return error;
+    }
+
+    for (uint32_t idx = 0; idx < buffer_count; idx++) {
+      session->offset[idx] = UINT32((buffer_size / buffer_count) * idx);
+    }
+  }
+
+  // Wait for the release fence fd before the session being given to the client.
+  buffer_sync_handler_->SyncWait(session->release_fd[curr_index]);
+  close(session->release_fd[curr_index]);
+  session->release_fd[curr_index] = -1;
+
+  hw_rotator_session->output_buffer.planes[0].stride = buffer_info->alloc_buffer_info.stride;
+  hw_rotator_session->output_buffer.planes[0].fd = buffer_info->alloc_buffer_info.fd;
+  hw_rotator_session->output_buffer.planes[0].offset = session->offset[curr_index];
+
+  DLOGI_IF(kTagRotator, "Output: width = %d, height = %d, format = %d, stride %d, " \
+           "curr_index = %d, offset %d, fd %d, session_id %d,",
+           hw_rotator_session->output_buffer.width, hw_rotator_session->output_buffer.height,
+           hw_rotator_session->output_buffer.format,
+           hw_rotator_session->output_buffer.planes[0].stride, curr_index,
+           hw_rotator_session->output_buffer.planes[0].offset,
+           hw_rotator_session->output_buffer.planes[0].fd, hw_rotator_session->session_id);
+
+  return kErrorNone;
+}
+
+DisplayError SessionManager::Stop() {
+  DisplayError error = kErrorNone;
+  uint32_t session_id = 0;
+
+  // Release all the sessions which were not acquired in the current cycle and deallocate the
+  // buffers associated with it.
+  while ((active_session_count_ > 0) && (session_id < kMaxSessionCount)) {
+    if (session_list_[session_id].state == kSessionReady) {
+      error = ReleaseSession(&session_list_[session_id]);
+      if (error != kErrorNone) {
+        return error;
+      }
+      active_session_count_--;
+
+      DLOGI_IF(kTagRotator, "session_id = %d, active_session_count = %d", session_id,
+               active_session_count_);
+    }
+    session_id++;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError SessionManager::SetReleaseFd(HWRotatorSession *hw_rotator_session) {
+  int session_id = hw_rotator_session->session_id;
+  if (session_id > kMaxSessionCount) {
+    return kErrorParameters;
+  }
+
+  Session *session = &session_list_[session_id];
+  if (session->state != kSessionAcquired) {
+    DLOGE("Invalid session state %d", session->state);
+    kErrorParameters;
+  }
+
+  uint32_t &curr_index = session->curr_index;
+  uint32_t buffer_count = hw_rotator_session->hw_session_config.buffer_count;
+
+  // 1. Store the release fence fd, so that session manager waits for the release fence fd
+  //    to be signaled and populates the session info to the client.
+  // 2. Modify the curr_index to point to next buffer.
+  session->release_fd[curr_index] = hw_rotator_session->output_buffer.release_fence_fd;
+
+  curr_index = (curr_index + 1) % buffer_count;
+
+  DLOGI_IF(kTagRotator, "session_id %d, curr_index = %d, release fd %d", session_id,
+           curr_index, hw_rotator_session->output_buffer.release_fence_fd);
+
+  return kErrorNone;
+}
+
+DisplayError SessionManager::AcquireSession(HWRotatorSession *hw_rotator_session,
+                                            Session *session) {
+  DisplayError error = kErrorNone;
+  const HWSessionConfig &input_config = hw_rotator_session->hw_session_config;
+
+  error = hw_rotator_intf_->OpenSession(hw_rotator_session);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  hw_rotator_session->output_buffer = LayerBuffer();
+  hw_rotator_session->output_buffer.width = input_config.dst_width;
+  hw_rotator_session->output_buffer.height = input_config.dst_height;
+  hw_rotator_session->output_buffer.format = input_config.dst_format;
+  hw_rotator_session->output_buffer.flags.secure = input_config.secure;
+
+  uint32_t buffer_count = hw_rotator_session->hw_session_config.buffer_count;
+
+  session->release_fd = new int[buffer_count];
+  if (session->release_fd == NULL) {
+    return kErrorMemory;
+  }
+
+  session->offset = new uint32_t[buffer_count];
+  if (session->offset == NULL) {
+    delete[] session->release_fd;
+    session->release_fd = NULL;
+    return kErrorMemory;
+  }
+
+  for (uint32_t idx = 0; idx < buffer_count; idx++) {
+    session->release_fd[idx] = -1;
+    session->offset[idx] = 0;
+  }
+  session->curr_index = 0;
+
+  session->hw_rotator_session = HWRotatorSession();
+  session->buffer_info = BufferInfo();
+
+  BufferInfo *buffer_info = &session->buffer_info;
+  buffer_info->buffer_config.buffer_count = hw_rotator_session->hw_session_config.buffer_count;
+  buffer_info->buffer_config.secure = hw_rotator_session->hw_session_config.secure;
+  buffer_info->buffer_config.cache = hw_rotator_session->hw_session_config.cache;
+  buffer_info->buffer_config.width = hw_rotator_session->hw_session_config.dst_width;
+  buffer_info->buffer_config.height = hw_rotator_session->hw_session_config.dst_height;
+  buffer_info->buffer_config.format = hw_rotator_session->hw_session_config.dst_format;
+
+  session->state = kSessionAcquired;
+  session->hw_rotator_session = *hw_rotator_session;
+
+  return kErrorNone;
+}
+
+DisplayError SessionManager::ReleaseSession(Session *session) {
+  DisplayError error = kErrorNone;
+
+  BufferInfo *buffer_info = &session->buffer_info;
+
+  error = buffer_allocator_->FreeBuffer(buffer_info);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  error = hw_rotator_intf_->CloseSession(&session->hw_rotator_session);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  uint32_t buffer_count = buffer_info->buffer_config.buffer_count;
+
+  for (uint32_t idx = 0; idx < buffer_count; idx++) {
+    if (session->release_fd[idx] >= 0) {
+      close(session->release_fd[idx]);
+      session->release_fd[idx] = -1;
+    }
+  }
+  session->state = kSessionReleased;
+
+  if (session->offset) {
+    delete[] session->offset;
+    session->offset = NULL;
+  }
+
+  if (session->release_fd) {
+    delete[] session->release_fd;
+    session->release_fd = NULL;
+  }
+
+  return kErrorNone;
+}
+
+}  // namespace sde
diff --git a/displayengine/libs/core/buffer_manager.h b/displayengine/libs/core/session_manager.h
similarity index 60%
rename from displayengine/libs/core/buffer_manager.h
rename to displayengine/libs/core/session_manager.h
index 29bcd03..b27ba8b 100644
--- a/displayengine/libs/core/buffer_manager.h
+++ b/displayengine/libs/core/session_manager.h
@@ -27,8 +27,8 @@
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-#ifndef __BUFFER_MANAGER_H__
-#define __BUFFER_MANAGER_H__
+#ifndef __SESSION_MANAGER_H__
+#define __SESSION_MANAGER_H__
 
 #include <utils/locker.h>
 #include <core/buffer_allocator.h>
@@ -36,47 +36,52 @@
 
 namespace sde {
 
-class BufferManager {
+class HWRotatorInterface;
+
+class SessionManager {
  public:
-  BufferManager(BufferAllocator *buffer_allocator, BufferSyncHandler *buffer_sync_handler);
+  SessionManager(HWRotatorInterface *hw_intf, 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);
+  DisplayError Stop();
+  DisplayError OpenSession(HWRotatorSession *hw_rotator_session);
+  DisplayError GetNextBuffer(HWRotatorSession *hw_rotator_session);
+  DisplayError SetReleaseFd(HWRotatorSession *hw_rotator_session);
 
  private:
-  static const uint32_t kMaxBufferSlotCount = 32;
+  // TODO(user): Read from hw capability instead of hardcoding
+  static const int kMaxSessionCount = 32;
 
-  enum kBufferSlotState {
-    kBufferSlotFree     = 0,
-    kBufferSlotReady    = 1,
-    kBufferSlotAcquired = 2,
+  enum SessionState {
+    kSessionReleased = 0,
+    kSessionReady    = 1,
+    kSessionAcquired = 2,
   };
 
-  struct BufferSlot {
-    HWBufferInfo hw_buffer_info;
-    kBufferSlotState state;
+  struct Session {
+    HWRotatorSession hw_rotator_session;
+    BufferInfo buffer_info;
+    SessionState 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();
+    Session() : state(kSessionReleased), release_fd(NULL), offset(NULL), curr_index(0) { }
   };
 
-  DisplayError FreeBufferSlot(uint32_t index);
+  DisplayError AcquireSession(HWRotatorSession *hw_rotator_session, Session *session);
+  DisplayError ReleaseSession(Session *session);
 
-  BufferSlot buffer_slot_[kMaxBufferSlotCount];
+  Session session_list_[kMaxSessionCount];
+  HWRotatorInterface *hw_rotator_intf_;
   BufferAllocator *buffer_allocator_;
   BufferSyncHandler *buffer_sync_handler_;
-  uint32_t num_used_slot_;
+  uint32_t active_session_count_;           // number of sessions in ready/acquired state.
 };
 
 }  // namespace sde
 
-#endif  // __BUFFER_MANAGER_H__
+#endif  // __SESSION_MANAGER_H__
 
 
diff --git a/displayengine/libs/hwc/hwc_debugger.cpp b/displayengine/libs/hwc/hwc_debugger.cpp
index d35e9cf..38f4f5c 100644
--- a/displayengine/libs/hwc/hwc_debugger.cpp
+++ b/displayengine/libs/hwc/hwc_debugger.cpp
@@ -76,19 +76,11 @@
   }
 }
 
-void HWCDebugHandler::DebugBufferManager(bool enable) {
+void HWCDebugHandler::DebugRotator(bool enable) {
   if (enable) {
-    SET_BIT(debug_flags_, kTagBufferManager);
+    SET_BIT(debug_flags_, kTagRotator);
   } else {
-    CLEAR_BIT(debug_flags_, kTagBufferManager);
-  }
-}
-
-void HWCDebugHandler::DebugOfflineCtrl(bool enable) {
-  if (enable) {
-    SET_BIT(debug_flags_, kTagOfflineCtrl);
-  } else {
-    CLEAR_BIT(debug_flags_, kTagOfflineCtrl);
+    CLEAR_BIT(debug_flags_, kTagRotator);
   }
 }
 
diff --git a/displayengine/libs/hwc/hwc_debugger.h b/displayengine/libs/hwc/hwc_debugger.h
index def31db..2fed120 100644
--- a/displayengine/libs/hwc/hwc_debugger.h
+++ b/displayengine/libs/hwc/hwc_debugger.h
@@ -59,8 +59,7 @@
   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);
+  static void DebugRotator(bool enable);
 
   virtual void Error(DebugTag tag, const char *format, ...);
   virtual void Warning(DebugTag tag, const char *format, ...);
diff --git a/displayengine/libs/hwc/hwc_session.cpp b/displayengine/libs/hwc/hwc_session.cpp
index 652d7e0..2201aa6 100644
--- a/displayengine/libs/hwc/hwc_session.cpp
+++ b/displayengine/libs/hwc/hwc_session.cpp
@@ -706,8 +706,7 @@
   case qService::IQService::DEBUG_ROTATOR:
     HWCDebugHandler::DebugResources(enable);
     HWCDebugHandler::DebugDriverConfig(enable);
-    HWCDebugHandler::DebugBufferManager(enable);
-    HWCDebugHandler::DebugOfflineCtrl(enable);
+    HWCDebugHandler::DebugRotator(enable);
     break;
 
   default: