merge in mnc-dr-release history after reset to mnc-dr-dev
diff --git a/Android.mk b/Android.mk
index de1658f..810caac 100644
--- a/Android.mk
+++ b/Android.mk
@@ -52,6 +52,7 @@
 	glworker.cpp \
 	hwcomposer.cpp \
 	seperate_rects.cpp \
+	virtualcompositorworker.cpp \
 	vsyncworker.cpp \
 	worker.cpp
 
diff --git a/drmdisplaycompositor.h b/drmdisplaycompositor.h
index c9973c6..0f3a12f 100644
--- a/drmdisplaycompositor.h
+++ b/drmdisplaycompositor.h
@@ -51,9 +51,9 @@
  private:
   DrmDisplayCompositor(const DrmDisplayCompositor &) = delete;
 
-  // Set to 50ms which is somewhere between a reasonable amount of time to
-  // wait for a long render and a small enough delay to limit jank.
-  static const int kAcquireWaitTimeoutMs = 50;
+  // Set to 83ms (~12fps) which is somewhere between a reasonable amount of
+  // time to wait for a long render and a small enough delay to limit jank.
+  static const int kAcquireWaitTimeoutMs = 83;
 
   int ApplyPreComposite(DrmDisplayComposition *display_comp);
   int ApplyFrame(DrmDisplayComposition *display_comp);
diff --git a/hwcomposer.cpp b/hwcomposer.cpp
index 5181d84..a7c9e43 100644
--- a/hwcomposer.cpp
+++ b/hwcomposer.cpp
@@ -20,6 +20,7 @@
 #include "drm_hwcomposer.h"
 #include "drmresources.h"
 #include "importer.h"
+#include "virtualcompositorworker.h"
 #include "vsyncworker.h"
 
 #include <stdlib.h>
@@ -133,6 +134,7 @@
   }
 
   ~hwc_context_t() {
+    virtual_compositor_worker.Exit();
     delete importer;
   }
 
@@ -145,6 +147,7 @@
   const gralloc_module_t *gralloc;
   DummySwSyncTimeline dummy_timeline;
   bool use_framebuffer_target;
+  VirtualCompositorWorker virtual_compositor_worker;
 };
 
 static native_handle_t *dup_buffer_handle(buffer_handle_t handle) {
@@ -346,17 +349,22 @@
     if (!display_contents[i])
       continue;
 
-    DrmCrtc *crtc = ctx->drm.GetCrtcForDisplay(i);
-    if (!crtc) {
-      ALOGE("No crtc for display %d", i);
-      return -ENODEV;
+    bool use_framebuffer_target = ctx->use_framebuffer_target;
+    if (i == HWC_DISPLAY_VIRTUAL) {
+      use_framebuffer_target = true;
+    } else {
+      DrmCrtc *crtc = ctx->drm.GetCrtcForDisplay(i);
+      if (!crtc) {
+        ALOGE("No crtc for display %d", i);
+        return -ENODEV;
+      }
     }
 
     int num_layers = display_contents[i]->numHwLayers;
     for (int j = 0; j < num_layers; j++) {
       hwc_layer_1_t *layer = &display_contents[i]->hwLayers[j];
 
-      if (!ctx->use_framebuffer_target) {
+      if (!use_framebuffer_target) {
         if (layer->compositionType == HWC_FRAMEBUFFER)
           layer->compositionType = HWC_OVERLAY;
       } else {
@@ -415,6 +423,11 @@
     if (!sf_display_contents[i])
       continue;
 
+    if (i == HWC_DISPLAY_VIRTUAL) {
+      ctx->virtual_compositor_worker.QueueComposite(dc);
+      continue;
+    }
+
     std::ostringstream display_index_formatter;
     display_index_formatter << "retire fence for display " << i;
     std::string display_fence_description(display_index_formatter.str());
@@ -516,6 +529,20 @@
     return -EINVAL;
   }
 
+  for (size_t i = 0; i < num_displays; ++i) {
+    hwc_display_contents_1_t *dc = sf_display_contents[i];
+    if (!dc)
+      continue;
+
+    size_t num_dc_layers = dc->numHwLayers;
+    for (size_t j = 0; j < num_dc_layers; ++j) {
+      hwc_layer_1_t *layer = &dc->hwLayers[j];
+      if (layer->flags & HWC_SKIP_LAYER)
+        continue;
+      hwc_add_layer_to_retire_fence(layer, dc);
+    }
+  }
+
   composition.reset(NULL);
 
   return ret;
@@ -562,7 +589,7 @@
       *value = 1000 * 1000 * 1000 / 60;
       break;
     case HWC_DISPLAY_TYPES_SUPPORTED:
-      *value = HWC_DISPLAY_PRIMARY | HWC_DISPLAY_EXTERNAL;
+      *value = HWC_DISPLAY_PRIMARY | HWC_DISPLAY_EXTERNAL | HWC_DISPLAY_VIRTUAL;
       break;
   }
   return 0;
@@ -775,6 +802,11 @@
     }
   }
 
+  ret = ctx->virtual_compositor_worker.Init();
+  if (ret) {
+    ALOGE("Failed to initialize virtual compositor worker");
+    return ret;
+  }
   return 0;
 }
 
diff --git a/virtualcompositorworker.cpp b/virtualcompositorworker.cpp
new file mode 100644
index 0000000..e7acef0
--- /dev/null
+++ b/virtualcompositorworker.cpp
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "hwc-virtual-compositor-worker"
+
+#include "virtualcompositorworker.h"
+#include "worker.h"
+
+#include <errno.h>
+#include <stdlib.h>
+
+#include <cutils/log.h>
+#include <hardware/hardware.h>
+#include <hardware/hwcomposer.h>
+#include <sched.h>
+#include <sw_sync.h>
+#include <sync/sync.h>
+
+namespace android {
+
+static const int kMaxQueueDepth = 3;
+static const int kAcquireWaitTimeoutMs = 50;
+
+VirtualCompositorWorker::VirtualCompositorWorker()
+    : Worker("virtual-compositor", HAL_PRIORITY_URGENT_DISPLAY)
+    , timeline_fd_(-1)
+    , timeline_(0)
+    , timeline_current_(0) {
+}
+
+VirtualCompositorWorker::~VirtualCompositorWorker() {
+  if (timeline_fd_ >= 0) {
+    FinishComposition(timeline_);
+    close(timeline_fd_);
+    timeline_fd_ = -1;
+  }
+}
+
+int VirtualCompositorWorker::Init() {
+  int ret = sw_sync_timeline_create();
+  if (ret < 0) {
+    ALOGE("Failed to create sw sync timeline %d", ret);
+    return ret;
+  }
+  timeline_fd_ = ret;
+  return InitWorker();
+}
+
+void VirtualCompositorWorker::QueueComposite(hwc_display_contents_1_t *dc) {
+  std::unique_ptr<VirtualComposition> composition(new VirtualComposition);
+
+  composition->outbuf_acquire_fence.Set(dc->outbufAcquireFenceFd);
+  dc->outbufAcquireFenceFd = -1;
+  if (dc->retireFenceFd >= 0)
+    close(dc->retireFenceFd);
+  dc->retireFenceFd = CreateNextTimelineFence();
+
+  for (size_t i = 0; i < dc->numHwLayers; ++i) {
+    hwc_layer_1_t *layer = &dc->hwLayers[i];
+    if (layer->flags & HWC_SKIP_LAYER)
+      continue;
+    composition->layer_acquire_fences.emplace_back(layer->acquireFenceFd);
+    layer->acquireFenceFd = -1;
+    if (layer->releaseFenceFd >= 0)
+      close(layer->releaseFenceFd);
+    layer->releaseFenceFd = CreateNextTimelineFence();
+  }
+
+  composition->release_timeline = timeline_;
+
+  Lock();
+  while (composite_queue_.size() >= kMaxQueueDepth) {
+    Unlock();
+    sched_yield();
+    Lock();
+  }
+
+  composite_queue_.push(std::move(composition));
+  SignalLocked();
+  Unlock();
+}
+
+void VirtualCompositorWorker::Routine() {
+  int ret = Lock();
+  if (ret) {
+    ALOGE("Failed to lock worker, %d", ret);
+    return;
+  }
+
+  int wait_ret = 0;
+  if (composite_queue_.empty()) {
+    wait_ret = WaitForSignalOrExitLocked();
+  }
+
+  std::unique_ptr<VirtualComposition> composition;
+  if (!composite_queue_.empty()) {
+    composition = std::move(composite_queue_.front());
+    composite_queue_.pop();
+  }
+
+  ret = Unlock();
+  if (ret) {
+    ALOGE("Failed to unlock worker, %d", ret);
+    return;
+  }
+
+  if (wait_ret == -EINTR) {
+    return;
+  } else if (wait_ret) {
+    ALOGE("Failed to wait for signal, %d", wait_ret);
+    return;
+  }
+
+  Compose(std::move(composition));
+}
+
+int VirtualCompositorWorker::CreateNextTimelineFence() {
+  ++timeline_;
+  return sw_sync_fence_create(timeline_fd_, "drm_fence", timeline_);
+}
+
+int VirtualCompositorWorker::FinishComposition(int point) {
+  int timeline_increase = point - timeline_current_;
+  if (timeline_increase <= 0)
+    return 0;
+  int ret = sw_sync_timeline_inc(timeline_fd_, timeline_increase);
+  if (ret)
+    ALOGE("Failed to increment sync timeline %d", ret);
+  else
+    timeline_current_ = point;
+  return ret;
+}
+
+void VirtualCompositorWorker::Compose(
+    std::unique_ptr<VirtualComposition> composition) {
+  if (!composition.get())
+    return;
+
+  int ret;
+  int outbuf_acquire_fence = composition->outbuf_acquire_fence.get();
+  if (outbuf_acquire_fence >= 0) {
+    ret = sync_wait(outbuf_acquire_fence, kAcquireWaitTimeoutMs);
+    if (ret) {
+      ALOGE("Failed to wait for acquire %d/%d", outbuf_acquire_fence, ret);
+      return;
+    }
+    composition->outbuf_acquire_fence.Close();
+  }
+  for (size_t i = 0; i < composition->layer_acquire_fences.size(); ++i) {
+    int layer_acquire_fence = composition->layer_acquire_fences[i].get();
+    if (layer_acquire_fence >= 0) {
+      ret = sync_wait(layer_acquire_fence, kAcquireWaitTimeoutMs);
+      if (ret) {
+        ALOGE("Failed to wait for acquire %d/%d", layer_acquire_fence, ret);
+        return;
+      }
+      composition->layer_acquire_fences[i].Close();
+    }
+  }
+  FinishComposition(composition->release_timeline);
+}
+}
diff --git a/virtualcompositorworker.h b/virtualcompositorworker.h
new file mode 100644
index 0000000..4a15f0c
--- /dev/null
+++ b/virtualcompositorworker.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_VIRTUAL_COMPOSITOR_WORKER_H_
+#define ANDROID_VIRTUAL_COMPOSITOR_WORKER_H_
+
+#include "drm_hwcomposer.h"
+#include "worker.h"
+
+#include <queue>
+
+namespace android {
+
+class VirtualCompositorWorker : public Worker {
+ public:
+  VirtualCompositorWorker();
+  ~VirtualCompositorWorker();
+
+  int Init();
+  void QueueComposite(hwc_display_contents_1_t *dc);
+
+ protected:
+  virtual void Routine();
+
+ private:
+  struct VirtualComposition {
+    UniqueFd outbuf_acquire_fence;
+    std::vector<UniqueFd> layer_acquire_fences;
+    int release_timeline;
+  };
+
+  int CreateNextTimelineFence();
+  int FinishComposition(int timeline);
+  void Compose(std::unique_ptr<VirtualComposition> composition);
+
+  std::queue<std::unique_ptr<VirtualComposition>> composite_queue_;
+  int timeline_fd_;
+  int timeline_;
+  int timeline_current_;
+};
+}
+
+#endif