Merge "libgralloc: Set Alignment to 1M only for Secured buffers."
diff --git a/libcopybit/Android.mk b/libcopybit/Android.mk
index 2ac7d15..c239c3a 100644
--- a/libcopybit/Android.mk
+++ b/libcopybit/Android.mk
@@ -22,7 +22,7 @@
 include $(BUILD_COPY_HEADERS)
 
 LOCAL_MODULE                  := copybit.$(TARGET_BOARD_PLATFORM)
-LOCAL_MODULE_PATH             := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_MODULE_RELATIVE_PATH    := hw
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
 LOCAL_SHARED_LIBRARIES        := $(common_libs) libdl libmemalloc
diff --git a/libcopybit/copybit_c2d.cpp b/libcopybit/copybit_c2d.cpp
index 771d483..7e2c500 100644
--- a/libcopybit/copybit_c2d.cpp
+++ b/libcopybit/copybit_c2d.cpp
@@ -257,7 +257,8 @@
 static int get_format(int format) {
     switch (format) {
         case HAL_PIXEL_FORMAT_RGB_565:        return C2D_COLOR_FORMAT_565_RGB;
-        case HAL_PIXEL_FORMAT_RGB_888:        return C2D_COLOR_FORMAT_888_RGB;
+        case HAL_PIXEL_FORMAT_RGB_888:        return C2D_COLOR_FORMAT_888_RGB |
+                                              C2D_FORMAT_SWAP_RB;
         case HAL_PIXEL_FORMAT_RGBX_8888:      return C2D_COLOR_FORMAT_8888_ARGB |
                                               C2D_FORMAT_SWAP_RB |
                                                   C2D_FORMAT_DISABLE_ALPHA;
diff --git a/libexternal/Android.mk b/libexternal/Android.mk
index 3df6984..05e42d4 100644
--- a/libexternal/Android.mk
+++ b/libexternal/Android.mk
@@ -3,7 +3,6 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE                  := libexternal
-LOCAL_MODULE_PATH             := $(TARGET_OUT_SHARED_LIBRARIES)
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
 LOCAL_SHARED_LIBRARIES        := $(common_libs) liboverlay libqdutils
diff --git a/libgralloc/Android.mk b/libgralloc/Android.mk
index 18beaf2..412f1be 100644
--- a/libgralloc/Android.mk
+++ b/libgralloc/Android.mk
@@ -18,7 +18,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE                  := gralloc.$(TARGET_BOARD_PLATFORM)
-LOCAL_MODULE_PATH             := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_MODULE_RELATIVE_PATH    := hw
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
 LOCAL_SHARED_LIBRARIES        := $(common_libs) libmemalloc libqdMetaData
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index 6af0eea..77c9922 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -566,8 +566,7 @@
         case HAL_PIXEL_FORMAT_YCbCr_422_SP:
         case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
         case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: //Same as YCbCr_420_SP_VENUS
-            ystride = hnd->width;
-            cstride = hnd->width/2;
+            ystride = cstride = hnd->width;
             ycbcr->y  = (void*)hnd->base;
             ycbcr->cb = (void*)(hnd->base + ystride * hnd->height);
             ycbcr->cr = (void*)(hnd->base + ystride * hnd->height + 1);
@@ -581,8 +580,7 @@
         case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
         case HAL_PIXEL_FORMAT_NV21_ZSL:
         case HAL_PIXEL_FORMAT_RAW_SENSOR:
-            ystride = hnd->width;
-            cstride = hnd->width/2;
+            ystride = cstride = hnd->width;
             ycbcr->y  = (void*)hnd->base;
             ycbcr->cr = (void*)(hnd->base + ystride * hnd->height);
             ycbcr->cb = (void*)(hnd->base + ystride * hnd->height + 1);
diff --git a/libgralloc/ionalloc.cpp b/libgralloc/ionalloc.cpp
index e6d34f8..2097320 100644
--- a/libgralloc/ionalloc.cpp
+++ b/libgralloc/ionalloc.cpp
@@ -73,11 +73,7 @@
 
     ionAllocData.len = data.size;
     ionAllocData.align = data.align;
-#ifdef QCOM_BSP
-    ionAllocData.heap_mask = data.flags & ~ION_SECURE;
-#else
     ionAllocData.heap_id_mask = data.flags & ~ION_SECURE;
-#endif
     ionAllocData.flags = data.uncached ? 0 : ION_FLAG_CACHED;
     // ToDo: replace usage of alloc data structure with
     //  ionallocdata structure.
diff --git a/libhwcomposer/Android.mk b/libhwcomposer/Android.mk
index 7dadfe4..ef7778b 100644
--- a/libhwcomposer/Android.mk
+++ b/libhwcomposer/Android.mk
@@ -3,7 +3,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE                  := hwcomposer.$(TARGET_BOARD_PLATFORM)
-LOCAL_MODULE_PATH             := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_MODULE_RELATIVE_PATH    := hw
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes) \
                                  $(TOP)/external/skia/include/core \
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index e5c7ce7..3d88b3b 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -424,7 +424,11 @@
         ctx->mOverlay->configBegin();
         ctx->mOverlay->configDone();
         ctx->mRotMgr->clear();
-        overlay::Writeback::clear();
+        // If VDS is connected, do not clear WB object as it
+        // will end up detaching IOMMU. This is required
+        // to send black frame to WFD sink on power suspend.
+        // Note: With this change, we keep the WriteBack object
+        // alive on power suspend for AD use case.
     }
     switch(dpy) {
     case HWC_DISPLAY_PRIMARY:
@@ -478,13 +482,6 @@
                     ret = -1;
                 }
             }
-            value = blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK;
-            if(ioctl(ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].fd, FBIOBLANK, value) < 0
-                    ) {
-                ALOGE("%s: Failed to handle blank event(%d) for virtual!!",
-                        __FUNCTION__, blank );
-                return -1;
-            }
             ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isActive = !blank;
         }
         break;
@@ -580,8 +577,14 @@
         hwc_layer_1_t *fbLayer = &list->hwLayers[last];
         int fd = -1; //FenceFD from the Copybit(valid in async mode)
         bool copybitDone = false;
-        if(ctx->mCopyBit[dpy])
-            copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
+
+        if (ctx->mCopyBit[dpy]) {
+            if (ctx->mMDP.version < qdutils::MDP_V4_0)
+                copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
+            else
+                fd = ctx->mMDPComp[dpy]->drawOverlap(ctx, list);
+        }
+
         if(list->numHwLayers > 1)
             hwc_sync(ctx, list, dpy, fd);
 
@@ -601,6 +604,12 @@
             hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
         }
 
+        if(isAbcInUse(ctx) == true) {
+            int index = ctx->listStats[dpy].renderBufIndexforABC;
+            hwc_layer_1_t *tempLayer = &list->hwLayers[index];
+            hnd = (private_handle_t *)tempLayer->handle;
+        }
+
         if(hnd) {
             if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
                 ALOGE("%s: FBUpdate draw failed", __FUNCTION__);
@@ -825,7 +834,7 @@
     dumpsys_log(aBuf, "  DisplayPanel=%c\n", ctx->mMDP.panel);
     for(int dpy = 0; dpy < HWC_NUM_DISPLAY_TYPES; dpy++) {
         if(ctx->mMDPComp[dpy])
-            ctx->mMDPComp[dpy]->dump(aBuf);
+            ctx->mMDPComp[dpy]->dump(aBuf, ctx);
     }
     char ovDump[2048] = {'\0'};
     ctx->mOverlay->getDump(ovDump, 2048);
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index f379cf8..f703fa0 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -208,6 +208,46 @@
    return -1;
 }
 
+bool CopyBit::prepareOverlap(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+                            int overlapIndex) {
+
+    if (ctx->mMDP.version < qdutils::MDP_V4_0) {
+        ALOGE("%s: Invalid request", __FUNCTION__);
+        return false;
+    }
+
+    if (mEngine == NULL || !(validateParams(ctx, list))) {
+        ALOGE("%s: Invalid Params", __FUNCTION__);
+        return false;
+    }
+
+    //Allocate render buffers if they're not allocated
+    hwc_rect_t overlap = list->hwLayers[overlapIndex].displayFrame;
+    int width = overlap.right - overlap.left;
+    int height = overlap.bottom - overlap.top;
+    int alignW, alignH;
+
+    getBufferSizeAndDimensions(width, height, HAL_PIXEL_FORMAT_RGBA_8888,
+                               alignW, alignH);
+
+    if ((mAlignedWidth != alignW) || (mAlignedHeight != alignH)) {
+        // Overlap rect has changed, so free render buffers
+        freeRenderBuffers();
+    }
+
+    int ret = allocRenderBuffers(alignW, alignH, HAL_PIXEL_FORMAT_RGBA_8888);
+
+    if (ret < 0) {
+        ALOGE("%s: Render buffer allocation failed", __FUNCTION__);
+        return false;
+    }
+
+    mAlignedWidth = alignW;
+    mAlignedHeight = alignH;
+    mCurRenderBufferIndex = (mCurRenderBufferIndex + 1) % NUM_RENDER_BUFFERS;
+    return true;
+}
+
 bool CopyBit::prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list,
                                                             int dpy) {
 
@@ -286,8 +326,8 @@
     //Allocate render buffers if they're not allocated
     if (ctx->mMDP.version != qdutils::MDP_V3_0_4 &&
             (useCopybitForYUV || useCopybitForRGB)) {
-        int ret = allocRenderBuffers(mAlignedFBWidth,
-                                     mAlignedFBHeight,
+        int ret = allocRenderBuffers(mAlignedWidth,
+                                     mAlignedHeight,
                                      HAL_PIXEL_FORMAT_RGBA_8888);
         if (ret < 0) {
             return false;
@@ -340,8 +380,70 @@
     return ret;
 }
 
-bool CopyBit::draw(hwc_context_t *ctx, hwc_display_contents_1_t *list,
-                                                        int dpy, int32_t *fd) {
+bool CopyBit::drawUsingAppBufferComposition(hwc_context_t *ctx,
+                                      hwc_display_contents_1_t *list,
+                                      int dpy, int *copybitFd) {
+     int layerCount = 0;
+     uint32_t last = list->numHwLayers - 1;
+     hwc_layer_1_t *fbLayer = &list->hwLayers[last];
+     private_handle_t *fbhnd = (private_handle_t *)fbLayer->handle;
+
+    if(ctx->enableABC == false)
+       return false;
+
+    if(ctx->listStats[dpy].numAppLayers > MAX_LAYERS_FOR_ABC )
+       return false;
+
+    layerCount = ctx->listStats[dpy].numAppLayers;
+    //bottom most layer should
+    //equal to FB
+    hwc_layer_1_t *tmpLayer = &list->hwLayers[0];
+    private_handle_t *hnd = (private_handle_t *)tmpLayer->handle;
+    if(hnd && fbhnd && (hnd->size == fbhnd->size) &&
+    (hnd->width == fbhnd->width) && (hnd->height == fbhnd->height)){
+       if(tmpLayer->transform  ||
+       (!(hnd->format == HAL_PIXEL_FORMAT_RGBA_8888 ||
+       hnd->format == HAL_PIXEL_FORMAT_RGBX_8888))  ||
+                   (needsScaling(tmpLayer) == true)) {
+          return false;
+       }else {
+          ctx->listStats[dpy].renderBufIndexforABC = 0;
+       }
+    }
+
+    if(ctx->listStats[dpy].renderBufIndexforABC == 0) {
+       if(layerCount == 1)
+          return true;
+
+       if(layerCount == MAX_LAYERS_FOR_ABC) {
+          // Pass the Acquire Fence FD to driver for base layer
+          int abcRenderBufIdx = ctx->listStats[dpy].renderBufIndexforABC;
+          private_handle_t *renderBuffer =
+          (private_handle_t *)list->hwLayers[abcRenderBufIdx].handle;
+          copybit_device_t *copybit = getCopyBitDevice();
+          if(list->hwLayers[abcRenderBufIdx].acquireFenceFd >=0){
+             copybit->set_sync(copybit,
+             list->hwLayers[abcRenderBufIdx].acquireFenceFd);
+          }
+          for(int i = 1; i < layerCount; i++){
+             int retVal = drawLayerUsingCopybit(ctx,
+               &(list->hwLayers[i]),renderBuffer, 0);
+             if(retVal < 0) {
+                ALOGE("%s : Copybit failed", __FUNCTION__);
+             }
+          }
+          // Get Release Fence FD of copybit for the App layer(s)
+          copybit->flush_get_fence(copybit, copybitFd);
+          close(list->hwLayers[abcRenderBufIdx].acquireFenceFd);
+          list->hwLayers[abcRenderBufIdx].acquireFenceFd = -1;
+          return true;
+       }
+    }
+    return false;
+}
+
+bool  CopyBit::draw(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+                                                          int dpy, int32_t *fd) {
     // draw layers marked for COPYBIT
     int retVal = true;
     int copybitLayerCount = 0;
@@ -353,6 +455,10 @@
        mFbCache.reset(); // there is no layer marked for copybit
        return false ;
     }
+
+    if(drawUsingAppBufferComposition(ctx, list, dpy, fd)) {
+       return true;
+    }
     //render buffer
     if (ctx->mMDP.version == qdutils::MDP_V3_0_4) {
         last = (uint32_t)list->numHwLayers - 1;
@@ -436,6 +542,132 @@
     return true;
 }
 
+int CopyBit::drawOverlap(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+                        int overlapIndex) {
+    int fd = -1;
+
+    if (ctx->mMDP.version < qdutils::MDP_V4_0) {
+        ALOGE("%s: Invalid request", __FUNCTION__);
+        return fd;
+    }
+
+    private_handle_t *renderBuffer = getCurrentRenderBuffer();
+
+    if (!renderBuffer) {
+        ALOGE("%s: Render buffer layer handle is NULL", __FUNCTION__);
+        return fd;
+    }
+
+    int copybitLayerCount = 0;
+    hwc_rect_t overlap = list->hwLayers[overlapIndex].displayFrame;
+
+    // Draw overlapped content of layers on render buffer
+    for (int i = 0; i <= overlapIndex; i++) {
+
+        int ret = -1;
+        if ((list->hwLayers[i].acquireFenceFd != -1)) {
+            // Wait for acquire fence on the App buffers.
+            ret = sync_wait(list->hwLayers[i].acquireFenceFd, 1000);
+            if (ret < 0) {
+                ALOGE("%s: sync_wait error!! error no = %d err str = %s",
+                        __FUNCTION__, errno, strerror(errno));
+            }
+            close(list->hwLayers[i].acquireFenceFd);
+            list->hwLayers[i].acquireFenceFd = -1;
+        }
+
+        hwc_layer_1_t *layer = &list->hwLayers[i];
+        int retVal = drawRectUsingCopybit(ctx, layer, renderBuffer, overlap);
+        copybitLayerCount++;
+
+        if(retVal < 0) {
+            ALOGE("%s: drawRectUsingCopybit failed", __FUNCTION__);
+            copybitLayerCount = 0;
+        }
+    }
+
+    if (copybitLayerCount) {
+        copybit_device_t *copybit = getCopyBitDevice();
+        copybit->flush_get_fence(copybit, &fd);
+    }
+
+    ALOGD_IF(DEBUG_COPYBIT, "%s: done!", __FUNCTION__);
+    return fd;
+}
+
+int CopyBit::drawRectUsingCopybit(hwc_context_t *dev, hwc_layer_1_t *layer,
+                          private_handle_t *renderBuffer, hwc_rect_t rect)
+{
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
+    if (!ctx) {
+        ALOGE("%s: null context ", __FUNCTION__);
+        return -1;
+    }
+
+    private_handle_t *hnd = (private_handle_t *)layer->handle;
+    if (!hnd) {
+        ALOGE("%s: invalid handle", __FUNCTION__);
+        return -1;
+    }
+
+    private_handle_t *dstHandle = (private_handle_t *)renderBuffer;
+    if (!dstHandle) {
+        ALOGE("%s: RenderBuffer handle is NULL", __FUNCTION__);
+        return -1;
+    }
+
+    // Set the Copybit Source
+    copybit_image_t src;
+    src.handle = (native_handle_t *)layer->handle;
+    src.w = hnd->width;
+    src.h = hnd->height;
+    src.base = (void *)hnd->base;
+    src.format = hnd->format;
+    src.horiz_padding = 0;
+    src.vert_padding = 0;
+
+    hwc_rect_t dispFrame = layer->displayFrame;
+    hwc_rect_t iRect = getIntersection(dispFrame, rect);
+    hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
+    qhwc::calculate_crop_rects(crop, dispFrame, iRect, layer->transform);
+
+    // Copybit source rect
+    copybit_rect_t srcRect = {crop.left, crop.top, crop.right, crop.bottom};
+
+    // Copybit destination rect
+    copybit_rect_t dstRect = {rect.left, rect.top, rect.right, rect.bottom};
+
+    // Copybit dst
+    copybit_image_t dst;
+    dst.handle = (native_handle_t *)dstHandle;
+    dst.w = ALIGN(dstHandle->width, 32);
+    dst.h = dstHandle->height;
+    dst.base = (void *)dstHandle->base;
+    dst.format = dstHandle->format;
+
+    copybit_device_t *copybit = mEngine;
+
+    // Copybit region
+    hwc_region_t region = layer->visibleRegionScreen;
+    region_iterator copybitRegion(region);
+    int acquireFd = layer->acquireFenceFd;
+
+    copybit->set_parameter(copybit, COPYBIT_FRAMEBUFFER_WIDTH, renderBuffer->width);
+    copybit->set_parameter(copybit, COPYBIT_FRAMEBUFFER_HEIGHT, renderBuffer->height);
+    copybit->set_parameter(copybit, COPYBIT_TRANSFORM, layer->transform);
+    copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, layer->planeAlpha);
+    copybit->set_parameter(copybit, COPYBIT_BLEND_MODE, layer->blending);
+    copybit->set_parameter(copybit, COPYBIT_DITHER,
+        (dst.format == HAL_PIXEL_FORMAT_RGB_565) ? COPYBIT_ENABLE : COPYBIT_DISABLE);
+    copybit->set_sync(copybit, acquireFd);
+    int err = copybit->stretch(copybit, &dst, &src, &dstRect, &srcRect, &copybitRegion);
+
+    if (err < 0)
+        ALOGE("%s: copybit stretch failed",__FUNCTION__);
+
+    return err;
+}
+
 int  CopyBit::drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_1_t *layer,
                           private_handle_t *renderBuffer, bool isFG)
 {
@@ -806,6 +1038,18 @@
     mRelFd[mCurRenderBufferIndex] = dup(fd);
 }
 
+void CopyBit::setReleaseFdSync(int fd) {
+    if (mRelFd[mCurRenderBufferIndex] >=0) {
+        int ret = -1;
+        ret = sync_wait(mRelFd[mCurRenderBufferIndex], 1000);
+        if (ret < 0)
+            ALOGE("%s: sync_wait error! errno = %d, err str = %s",
+                  __FUNCTION__, errno, strerror(errno));
+        close(mRelFd[mCurRenderBufferIndex]);
+    }
+    mRelFd[mCurRenderBufferIndex] = dup(fd);
+}
+
 struct copybit_device_t* CopyBit::getCopyBitDevice() {
     return mEngine;
 }
@@ -816,8 +1060,8 @@
     getBufferSizeAndDimensions(ctx->dpyAttr[dpy].xres,
             ctx->dpyAttr[dpy].yres,
             HAL_PIXEL_FORMAT_RGBA_8888,
-            mAlignedFBWidth,
-            mAlignedFBHeight);
+            mAlignedWidth,
+            mAlignedHeight);
 
     hw_module_t const *module;
     for (int i = 0; i < NUM_RENDER_BUFFERS; i++) {
diff --git a/libhwcomposer/hwc_copybit.h b/libhwcomposer/hwc_copybit.h
index 14f8cfc..3d3d302 100644
--- a/libhwcomposer/hwc_copybit.h
+++ b/libhwcomposer/hwc_copybit.h
@@ -27,7 +27,7 @@
 //twice
 #define MAX_SCALE_FACTOR 16
 #define MIN_SCALE_FACTOR 0.0625
-
+#define MAX_LAYERS_FOR_ABC 2
 namespace qhwc {
 
 class CopyBit {
@@ -49,6 +49,14 @@
 
     void setReleaseFd(int fd);
 
+    void setReleaseFdSync(int fd);
+
+    bool prepareOverlap(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+                        int overlapIndex);
+
+    int drawOverlap(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+                    int overlapIndex);
+
 private:
     /* cached data */
     struct LayerCache {
@@ -73,9 +81,14 @@
 
     // holds the copybit device
     struct copybit_device_t *mEngine;
+    bool drawUsingAppBufferComposition(hwc_context_t *ctx,
+                                hwc_display_contents_1_t *list,
+                                int dpy, int *fd);
     // Helper functions for copybit composition
     int  drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_1_t *layer,
                           private_handle_t *renderBuffer, bool isFG);
+    int drawRectUsingCopybit(hwc_context_t *dev, hwc_layer_1_t *layer,
+                          private_handle_t *renderBuffer, hwc_rect_t rect);
     int fillColorUsingCopybit(hwc_layer_1_t *layer,
                           private_handle_t *renderBuffer);
     bool canUseCopybitForYUV (hwc_context_t *ctx);
@@ -111,8 +124,8 @@
     //Dynamic composition threshold for deciding copybit usage.
     double mDynThreshold;
     bool mSwapRectEnable;
-    int mAlignedFBWidth;
-    int mAlignedFBHeight;
+    int mAlignedWidth;
+    int mAlignedHeight;
     int mDirtyLayerIndex;
     LayerCache mLayerCache;
     FbCache mFbCache;
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 06e0b12..d2eae88 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -26,6 +26,7 @@
 #include "hwc_fbupdate.h"
 #include "hwc_ad.h"
 #include <overlayRotator.h>
+#include "hwc_copybit.h"
 
 using namespace overlay;
 using namespace qdutils;
@@ -58,7 +59,7 @@
 
 MDPComp::MDPComp(int dpy):mDpy(dpy){};
 
-void MDPComp::dump(android::String8& buf)
+void MDPComp::dump(android::String8& buf, hwc_context_t *ctx)
 {
     if(mCurrentFrame.layerCount > MAX_NUM_APP_LAYERS)
         return;
@@ -72,6 +73,21 @@
     dumpsys_log(buf,"needsFBRedraw:%3s  pipesUsed:%2d  MaxPipesPerMixer: %d \n",
                 (mCurrentFrame.needsRedraw? "YES" : "NO"),
                 mCurrentFrame.mdpCount, sMaxPipesPerMixer);
+    if(isDisplaySplit(ctx, mDpy)) {
+        dumpsys_log(buf, "Programmed ROI's: Left: [%d, %d, %d, %d] "
+                "Right: [%d, %d, %d, %d] \n",
+                ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
+                ctx->listStats[mDpy].lRoi.right,
+                ctx->listStats[mDpy].lRoi.bottom,
+                ctx->listStats[mDpy].rRoi.left,ctx->listStats[mDpy].rRoi.top,
+                ctx->listStats[mDpy].rRoi.right,
+                ctx->listStats[mDpy].rRoi.bottom);
+    } else {
+        dumpsys_log(buf, "Programmed ROI: [%d, %d, %d, %d] \n",
+                ctx->listStats[mDpy].lRoi.left,ctx->listStats[mDpy].lRoi.top,
+                ctx->listStats[mDpy].lRoi.right,
+                ctx->listStats[mDpy].lRoi.bottom);
+    }
     dumpsys_log(buf," ---------------------------------------------  \n");
     dumpsys_log(buf," listIdx | cached? | mdpIndex | comptype  |  Z  \n");
     dumpsys_log(buf," ---------------------------------------------  \n");
@@ -149,6 +165,14 @@
              (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
         sEnable4k2kYUVSplit = true;
     }
+
+    if ((property_get("persist.hwc.ptor.enable", property, NULL) > 0) &&
+            ((!strncasecmp(property, "true", PROPERTY_VALUE_MAX )) ||
+             (!strncmp(property, "1", PROPERTY_VALUE_MAX )))) {
+        ctx->mCopyBit[HWC_DISPLAY_PRIMARY] = new CopyBit(ctx,
+                                                    HWC_DISPLAY_PRIMARY);
+    }
+
     return true;
 }
 
@@ -473,11 +497,17 @@
         hwc_layer_1_t* layer = &list->hwLayers[index];
         if ((mCachedFrame.hnd[index] != layer->handle) ||
                 isYuvBuffer((private_handle_t *)layer->handle)) {
-            hwc_rect_t updatingRect = layer->displayFrame;
+            hwc_rect_t dst = layer->displayFrame;
+            hwc_rect_t updatingRect = dst;
 
 #ifdef QCOM_BSP
             if(!needsScaling(layer) && !layer->transform)
-                updatingRect =  layer->dirtyRect;
+            {
+                hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
+                int x_off = dst.left - src.left;
+                int y_off = dst.top - src.top;
+                updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
+            }
 #endif
 
             roi = getUnion(roi, updatingRect);
@@ -703,6 +733,8 @@
     bool ret = false;
     if(fullMDPComp(ctx, list)) {
         ret = true;
+    } else if(fullMDPCompWithPTOR(ctx, list)) {
+        ret = true;
     } else if(partialMDPComp(ctx, list)) {
         ret = true;
     }
@@ -752,6 +784,136 @@
     return true;
 }
 
+/* Full MDP Composition with Peripheral Tiny Overlap Removal.
+ * MDP bandwidth limitations can be avoided, if the overlap region
+ * covered by the smallest layer at a higher z-order, gets composed
+ * by Copybit on a render buffer, which can be queued to MDP.
+ */
+bool MDPComp::fullMDPCompWithPTOR(hwc_context_t *ctx,
+    hwc_display_contents_1_t* list) {
+
+    const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+    const int stagesForMDP = min(sMaxPipesPerMixer,
+            ctx->mOverlay->availablePipes(mDpy, Overlay::MIXER_DEFAULT));
+
+    // Hard checks where we cannot use this mode
+    if (mDpy || !ctx->mCopyBit[mDpy] || isDisplaySplit(ctx, mDpy)) {
+        ALOGD_IF(isDebug(), "%s: Feature not supported!", __FUNCTION__);
+        return false;
+    }
+
+    // Frame level checks
+    if ((numAppLayers > stagesForMDP) || isSkipPresent(ctx, mDpy) ||
+        isYuvPresent(ctx, mDpy) || mCurrentFrame.dropCount ||
+        isSecurePresent(ctx, mDpy)) {
+        ALOGD_IF(isDebug(), "%s: Frame not supported!", __FUNCTION__);
+        return false;
+    }
+
+    // Find overlap index
+    int overlapIdx = numAppLayers - 1;
+    uint32_t layerPixelCount, minPixelCount = 0;
+    for (int i = numAppLayers - 1; i >= 0; i--) {
+        hwc_layer_1_t* layer = &list->hwLayers[i];
+        hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
+        layerPixelCount = (crop.right - crop.left) * (crop.bottom - crop.top);
+        if (!minPixelCount || (layerPixelCount < minPixelCount)) {
+            minPixelCount = layerPixelCount;
+            overlapIdx = i;
+        }
+    }
+
+    // No overlap
+    if (!overlapIdx)
+        return false;
+
+    /* We cannot use this composition mode, if:
+     1. A below layer needs scaling.
+     2. Overlap is not peripheral to display.
+     3. Overlap or a below layer has 90 degree transform.
+     4. Intersection of Overlap layer with a below layer is not valid.
+     5. Overlap area > (1/3 * FrameBuffer) area, based on Perf inputs.
+     */
+
+    hwc_rect_t overlap = list->hwLayers[overlapIdx].displayFrame;
+    if (!isPeripheral(overlap, ctx->mViewFrame[mDpy]))
+        return false;
+
+    if ((3 * (overlap.right - overlap.left) * (overlap.bottom - overlap.top)) >
+        ((int)ctx->dpyAttr[mDpy].xres * (int)ctx->dpyAttr[mDpy].yres))
+        return false;
+
+    for (int i = overlapIdx; i >= 0; i--) {
+        hwc_layer_1_t* layer = &list->hwLayers[i];
+        hwc_rect_t dispFrame = layer->displayFrame;
+
+        if (has90Transform(layer))
+            return false;
+
+        if (i < overlapIdx) {
+            if (needsScaling(layer) ||
+                !isValidRect(getIntersection(dispFrame, overlap)))
+                return false;
+        }
+    }
+
+    mOverlapIndex = overlapIdx;
+    if (!ctx->mCopyBit[mDpy]->prepareOverlap(ctx, list, overlapIdx)) {
+        ALOGD_IF(isDebug(), "%s: Overlap prepare failed!",__FUNCTION__);
+        mOverlapIndex = -1;
+        return false;
+    }
+
+    hwc_rect_t sourceCrop[overlapIdx];
+    hwc_rect_t displayFrame[overlapIdx];
+
+    // Remove overlap from crop & displayFrame of below layers
+    for (int i = 0; i < overlapIdx; i++) {
+        hwc_layer_1_t* layer = &list->hwLayers[i];
+        displayFrame[i] = layer->displayFrame;
+        sourceCrop[i] = integerizeSourceCrop(layer->sourceCropf);
+
+        // Update layer attributes
+        hwc_rect_t srcCrop = integerizeSourceCrop(layer->sourceCropf);
+        hwc_rect_t destRect = deductRect(layer->displayFrame, overlap);
+        qhwc::calculate_crop_rects(srcCrop, layer->displayFrame, destRect,
+                                   layer->transform);
+
+        layer->sourceCropf.left = (float)srcCrop.left;
+        layer->sourceCropf.top = (float)srcCrop.top;
+        layer->sourceCropf.right = (float)srcCrop.right;
+        layer->sourceCropf.bottom = (float)srcCrop.bottom;
+    }
+
+    mCurrentFrame.mdpCount = numAppLayers;
+    mCurrentFrame.fbCount = 0;
+    mCurrentFrame.fbZ = -1;
+
+    for (int j = 0; j < numAppLayers; j++)
+        mCurrentFrame.isFBComposed[j] = false;
+
+    bool result = postHeuristicsHandling(ctx, list);
+
+    // Restore layer attributes
+    for (int i = 0; i < overlapIdx; i++) {
+        hwc_layer_1_t* layer = &list->hwLayers[i];
+        layer->displayFrame = displayFrame[i];
+        layer->sourceCropf.left = (float)sourceCrop[i].left;
+        layer->sourceCropf.top = (float)sourceCrop[i].top;
+        layer->sourceCropf.right = (float)sourceCrop[i].right;
+        layer->sourceCropf.bottom = (float)sourceCrop[i].bottom;
+    }
+
+    if (!result) {
+        mOverlapIndex = -1;
+        reset(ctx);
+    }
+
+    ALOGD_IF(isDebug(), "%s: Postheuristics %s!, Overlap index = %d",
+        __FUNCTION__, (result ? "successful" : "failed"), mOverlapIndex);
+    return result;
+}
+
 bool MDPComp::partialMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list)
 {
     if(!sEnableMixedMode) {
@@ -1390,6 +1552,7 @@
                     sSimulationFlags, sSimulationFlags);
         }
     }
+    mOverlapIndex = -1;
 
     //Do not cache the information for next draw cycle.
     if(numLayers > MAX_NUM_APP_LAYERS or (!numLayers)) {
@@ -1443,7 +1606,7 @@
         ALOGD("GEOMETRY change: %d",
                 (list->flags & HWC_GEOMETRY_CHANGED));
         android::String8 sDump("");
-        dump(sDump);
+        dump(sDump, ctx);
         ALOGD("%s",sDump.string());
     }
 
@@ -1484,6 +1647,18 @@
     }
     return bRet;
 }
+
+int MDPComp::drawOverlap(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+    int fd = -1;
+    if (mOverlapIndex != -1) {
+        fd = ctx->mCopyBit[mDpy]->drawOverlap(ctx, list, mOverlapIndex);
+        if (fd < 0) {
+            ALOGD_IF(isDebug(),"%s: failed", __FUNCTION__);
+            mOverlapIndex = -1;
+        }
+    }
+    return fd;
+}
 //=============MDPCompNonSplit==================================================
 
 void MDPCompNonSplit::adjustForSourceSplit(hwc_context_t *ctx,
@@ -1674,6 +1849,10 @@
                 continue;
             }
 
+            if (!mDpy && (i == mOverlapIndex)) {
+                hnd = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
+            }
+
             ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
                     using  pipe: %d", __FUNCTION__, layer,
                     hnd, dest );
@@ -1919,6 +2098,10 @@
             ovutils::eDest indexL = pipe_info.lIndex;
             ovutils::eDest indexR = pipe_info.rIndex;
 
+            if (!mDpy && (i == mOverlapIndex)) {
+                hnd = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
+            }
+
             int fd = hnd->fd;
             int offset = (uint32_t)hnd->offset;
 
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 4d9d232..520c176 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -44,8 +44,10 @@
     /* draw */
     virtual bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list) = 0;
     /* dumpsys */
-    void dump(android::String8& buf);
+    void dump(android::String8& buf, hwc_context_t *ctx);
     bool isGLESOnlyComp() { return (mCurrentFrame.mdpCount == 0); }
+    bool isPTORActive() { return (mOverlapIndex != -1); }
+    int drawOverlap(hwc_context_t *ctx, hwc_display_contents_1_t* list);
     static MDPComp* getObject(hwc_context_t *ctx, const int& dpy);
     /* Handler to invoke frame redraw on Idle Timer expiry */
     static void timeout_handler(void *udata);
@@ -170,6 +172,8 @@
     bool tryFullFrame(hwc_context_t *ctx, hwc_display_contents_1_t* list);
     /* checks if full MDP comp can be done */
     bool fullMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+    /* Full MDP Composition with Peripheral Tiny Overlap Removal */
+    bool fullMDPCompWithPTOR(hwc_context_t *ctx,hwc_display_contents_1_t* list);
     /* check if we can use layer cache to do at least partial MDP comp */
     bool partialMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list);
     /* Partial MDP comp that uses caching to save power as primary goal */
@@ -244,6 +248,8 @@
     struct LayerCache mCachedFrame;
     //Enable 4kx2k yuv layer split
     static bool sEnable4k2kYUVSplit;
+    /* Overlap layer index */
+    int mOverlapIndex;
     bool allocSplitVGPipesfor4k2k(hwc_context_t *ctx, int index);
 };
 
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 972f12f..4708368 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -274,6 +274,10 @@
         ctx->mMDPDownscaleEnabled = true;
     }
 
+    ctx->enableABC = false;
+    property_get("debug.sf.hwc.canUseABC", value, "0");
+    ctx->enableABC  = atoi(value) ? true : false;
+
     // Initialize gpu perfomance hint related parameters
     property_get("sys.hwc.gpu_perf_mode", value, "0");
 #ifdef QCOM_BSP
@@ -838,6 +842,7 @@
     ctx->listStats[dpy].yuv4k2kCount = 0;
     ctx->mViewFrame[dpy] = (hwc_rect_t){0, 0, 0, 0};
     ctx->dpyAttr[dpy].mActionSafePresent = isActionSafePresent(ctx, dpy);
+    ctx->listStats[dpy].renderBufIndexforABC = -1;
 
     resetROI(ctx, dpy);
 
@@ -1323,11 +1328,20 @@
     }
 
     for(uint32_t i = 0; i < list->numHwLayers; i++) {
-        if(list->hwLayers[i].compositionType == HWC_OVERLAY &&
+        if(((isAbcInUse(ctx)== true ) ||
+          (list->hwLayers[i].compositionType == HWC_OVERLAY)) &&
                         list->hwLayers[i].acquireFenceFd >= 0) {
             if(UNLIKELY(swapzero))
                 acquireFd[count++] = -1;
-            else
+            // if ABC is enabled for more than one layer.
+            // renderBufIndexforABC will work as FB.Hence
+            // set the acquireFD from fd - which is coming from copybit
+            else if(fd >= 0 && (isAbcInUse(ctx) == true)) {
+                if(ctx->listStats[dpy].renderBufIndexforABC ==(int32_t)i)
+                   acquireFd[count++] = fd;
+                else
+                   continue;
+            } else
                 acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
         }
         if(list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
@@ -1344,6 +1358,11 @@
         }
     }
 
+    if ((fd >= 0) && !dpy && ctx->mMDPComp[dpy]->isPTORActive()) {
+        // Acquire c2d fence of Overlap render buffer
+        acquireFd[count++] = fd;
+    }
+
     data.acq_fen_fd_cnt = count;
     fbFd = ctx->dpyAttr[dpy].fd;
 
@@ -1379,9 +1398,16 @@
             } else if(list->hwLayers[i].releaseFenceFd < 0 ) {
 #ifdef QCOM_BSP
                 //If rotator has not already populated this field
-                if(list->hwLayers[i].compositionType == HWC_BLIT) {
-                    //For Blit, the app layers should be released when the Blit is
-                    //complete. This fd was passed from copybit->draw
+                // & if it's a not VPU layer
+
+                // if ABC is enabled for more than one layer
+                if(fd >= 0 && (isAbcInUse(ctx) == true) &&
+                  ctx->listStats[dpy].renderBufIndexforABC !=(int32_t)i){
+                    list->hwLayers[i].releaseFenceFd = dup(fd);
+                } else if((list->hwLayers[i].compositionType == HWC_BLIT)&&
+                                               (isAbcInUse(ctx) == false)){
+                    //For Blit, the app layers should be released when the Blit
+                    //is complete. This fd was passed from copybit->draw
                     list->hwLayers[i].releaseFenceFd = dup(fd);
                 } else
 #endif
@@ -1397,8 +1423,12 @@
         fd = -1;
     }
 
-    if (ctx->mCopyBit[dpy])
-        ctx->mCopyBit[dpy]->setReleaseFd(releaseFd);
+    if (!dpy && ctx->mCopyBit[dpy]) {
+        if (ctx->mMDPComp[dpy]->isPTORActive())
+            ctx->mCopyBit[dpy]->setReleaseFdSync(releaseFd);
+        else
+            ctx->mCopyBit[dpy]->setReleaseFd(releaseFd);
+    }
 
     //Signals when MDP finishes reading rotator buffers.
     ctx->mLayerRotMap[dpy]->setReleaseFd(releaseFd);
@@ -1773,14 +1803,17 @@
 
     const int lSplit = getLeftSplit(ctx, dpy);
 
-    if(lDest != OV_INVALID) {
+    // Calculate Left rects
+    if(dst.left < lSplit) {
         tmp_cropL = crop;
         tmp_dstL = dst;
         hwc_rect_t scissor = {0, 0, lSplit, hw_h };
         scissor = getIntersection(ctx->mViewFrame[dpy], scissor);
         qhwc::calculate_crop_rects(tmp_cropL, tmp_dstL, scissor, 0);
     }
-    if(rDest != OV_INVALID) {
+
+    // Calculate Right rects
+    if(dst.right > lSplit) {
         tmp_cropR = crop;
         tmp_dstR = dst;
         hwc_rect_t scissor = {lSplit, 0, hw_w, hw_h };
@@ -1793,8 +1826,8 @@
     //When buffer is H-flipped, contents of mixer config also needs to swapped
     //Not needed if the layer is confined to one half of the screen.
     //If rotator has been used then it has also done the flips, so ignore them.
-    if((orient & OVERLAY_TRANSFORM_FLIP_H) && lDest != OV_INVALID
-            && rDest != OV_INVALID && (*rot) == NULL) {
+    if((orient & OVERLAY_TRANSFORM_FLIP_H) && (dst.left < lSplit) &&
+            (dst.right > lSplit) && (*rot) == NULL) {
         hwc_rect_t new_cropR;
         new_cropR.left = tmp_cropL.left;
         new_cropR.right = new_cropR.left + (tmp_cropR.right - tmp_cropR.left);
@@ -2017,6 +2050,10 @@
     ctx->layerProp[dpy] = new LayerProp[numAppLayers];
 }
 
+bool isAbcInUse(hwc_context_t *ctx){
+  return (ctx->enableABC && ctx->listStats[0].renderBufIndexforABC == 0);
+}
+
 /* Since we fake non-Hybrid WFD solution as external display, this
  * function helps us in determining the priority between external
  * (hdmi/non-Hybrid WFD display) and virtual display devices(SSD/
@@ -2118,6 +2155,20 @@
 #endif
 }
 
+bool isPeripheral(const hwc_rect_t& rect1, const hwc_rect_t& rect2) {
+    // To be peripheral, 3 boundaries should match.
+    uint8_t eqBounds = 0;
+    if (rect1.left == rect2.left)
+        eqBounds++;
+    if (rect1.top == rect2.top)
+        eqBounds++;
+    if (rect1.right == rect2.right)
+        eqBounds++;
+    if (rect1.bottom == rect2.bottom)
+        eqBounds++;
+    return (eqBounds == 3);
+}
+
 void BwcPM::setBwc(const hwc_rect_t& crop,
             const hwc_rect_t& dst, const int& transform,
             ovutils::eMdpFlags& mdpFlags) {
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 4cfed2a..c7b7ded 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -127,6 +127,8 @@
     bool isSecurePresent;
     hwc_rect_t lRoi;  //left ROI
     hwc_rect_t rRoi;  //right ROI. Unused in single DSI panels.
+    //App Buffer Composition index
+    int  renderBufIndexforABC;
 };
 
 struct LayerProp {
@@ -251,6 +253,7 @@
 int getBlending(int blending);
 bool isGLESOnlyComp(hwc_context_t *ctx, const int& dpy);
 void reset_layer_prop(hwc_context_t* ctx, int dpy, int numAppLayers);
+bool isAbcInUse(hwc_context_t *ctx);
 
 bool canUseMDPforVirtualDisplay(hwc_context_t* ctx,
                                 const hwc_display_contents_1_t *list);
@@ -373,6 +376,9 @@
 // due to idle fallback or MDP composition.
 void setGPUHint(hwc_context_t* ctx, hwc_display_contents_1_t* list);
 
+// Returns true if rect1 is peripheral to rect2, false otherwise.
+bool isPeripheral(const hwc_rect_t& rect1, const hwc_rect_t& rect2);
+
 // Inline utility functions
 static inline bool isSkipLayer(const hwc_layer_1_t* l) {
     return (UNLIKELY(l && (l->flags & HWC_SKIP_LAYER)));
@@ -556,6 +562,8 @@
     // persist.hwc.enable_vds
     bool mVDSEnabled;
     struct gpu_hint_info mGPUHintInfo;
+    //App Buffer Composition
+    bool enableABC;
 };
 
 namespace qhwc {
diff --git a/libhwcomposer/hwc_virtual.cpp b/libhwcomposer/hwc_virtual.cpp
index 97b19ea..adda35b 100644
--- a/libhwcomposer/hwc_virtual.cpp
+++ b/libhwcomposer/hwc_virtual.cpp
@@ -137,6 +137,7 @@
              * Mark all application layers as OVERLAY so that
              * GPU will not compose.
              */
+            Writeback::getInstance(); //Ensure that WB is active during pause
             for(size_t i = 0 ;i < (size_t)(list->numHwLayers - 1); i++) {
                 hwc_layer_1_t *layer = &list->hwLayers[i];
                 layer->compositionType = HWC_OVERLAY;
@@ -224,6 +225,17 @@
     }
     usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
             * 2 / 1000);
+    // At this point all the pipes used by External have been
+    // marked as UNSET.
+    {
+        Locker::Autolock _l(ctx->mDrawLock);
+        // Perform commit to unstage the pipes.
+        if (!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
+            ALOGE("%s: display commit fail! for %d dpy",
+                    __FUNCTION__, dpy);
+        }
+        ctx->proc->invalidate(ctx->proc);
+    }
     return;
 }
 
diff --git a/liblight/Android.mk b/liblight/Android.mk
index 40115d5..977fc55 100644
--- a/liblight/Android.mk
+++ b/liblight/Android.mk
@@ -18,7 +18,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := lights.c
-LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_MODULE_RELATIVE_PATH := hw
 LOCAL_SHARED_LIBRARIES := liblog
 LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdlights\"
 LOCAL_MODULE := lights.$(TARGET_BOARD_PLATFORM)
diff --git a/libmemtrack/Android.mk b/libmemtrack/Android.mk
index 306eb07..2fda0b7 100644
--- a/libmemtrack/Android.mk
+++ b/libmemtrack/Android.mk
@@ -18,7 +18,7 @@
 # hw/<POWERS_HARDWARE_MODULE_ID>.<ro.hardware>.so
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_MODULE_RELATIVE_PATH := hw
 LOCAL_C_INCLUDES += hardware/libhardware/include
 LOCAL_SHARED_LIBRARIES := liblog
 LOCAL_SRC_FILES := memtrack_msm.c kgsl.c
diff --git a/liboverlay/Android.mk b/liboverlay/Android.mk
index 277b44c..aa1ea24 100644
--- a/liboverlay/Android.mk
+++ b/liboverlay/Android.mk
@@ -3,7 +3,6 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE                  := liboverlay
-LOCAL_MODULE_PATH             := $(TARGET_OUT_SHARED_LIBRARIES)
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
 LOCAL_SHARED_LIBRARIES        := $(common_libs) libqdutils libmemalloc \
diff --git a/libqdutils/Android.mk b/libqdutils/Android.mk
index 2907ccf..212c8d8 100644
--- a/libqdutils/Android.mk
+++ b/libqdutils/Android.mk
@@ -21,7 +21,6 @@
 
 LOCAL_COPY_HEADERS_TO           := $(common_header_export_path)
 LOCAL_COPY_HEADERS              := qdMetaData.h
-LOCAL_MODULE_PATH               := $(TARGET_OUT_SHARED_LIBRARIES)
 LOCAL_SHARED_LIBRARIES          := liblog libcutils
 LOCAL_C_INCLUDES                := $(common_includes)
 LOCAL_ADDITIONAL_DEPENDENCIES   := $(common_deps)
diff --git a/libqservice/Android.mk b/libqservice/Android.mk
index 0c6123b..78b1d77 100644
--- a/libqservice/Android.mk
+++ b/libqservice/Android.mk
@@ -3,7 +3,6 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE                  := libqservice
-LOCAL_MODULE_PATH             := $(TARGET_OUT_SHARED_LIBRARIES)
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
 LOCAL_SHARED_LIBRARIES        := $(common_libs) libbinder
diff --git a/libqservice/QService.cpp b/libqservice/QService.cpp
index e4af422..12dd995 100644
--- a/libqservice/QService.cpp
+++ b/libqservice/QService.cpp
@@ -28,6 +28,8 @@
  */
 
 #include <QService.h>
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
 
 #define QSERVICE_DEBUG 0
 
@@ -55,6 +57,10 @@
 status_t QService::dispatch(uint32_t command, const Parcel* inParcel,
         Parcel* outParcel) {
     status_t err = (status_t) FAILED_TRANSACTION;
+    IPCThreadState* ipc = IPCThreadState::self();
+    //Rewind parcel in case we're calling from the same process
+    if (ipc->getCallingPid() == getpid())
+        inParcel->setDataPosition(0);
     if (mClient.get()) {
         ALOGD_IF(QSERVICE_DEBUG, "Dispatching command: %d", command);
         err = mClient->notifyCallback(command, inParcel, outParcel);
diff --git a/libvirtual/Android.mk b/libvirtual/Android.mk
index beeef25..a41ef33 100644
--- a/libvirtual/Android.mk
+++ b/libvirtual/Android.mk
@@ -3,7 +3,6 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE                  := libvirtual
-LOCAL_MODULE_PATH             := $(TARGET_OUT_SHARED_LIBRARIES)
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
 LOCAL_SHARED_LIBRARIES        := $(common_libs) liboverlay libqdutils