Merge "atrace: avoid unnecessary writes to trace_clock" into lmp-dev
diff --git a/data/etc/android.hardware.sensor.heartrate.ecg.xml b/data/etc/android.hardware.sensor.heartrate.ecg.xml
new file mode 100644
index 0000000..62a0de5
--- /dev/null
+++ b/data/etc/android.hardware.sensor.heartrate.ecg.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<!-- Feature for devices with a hardware electrocardiography(ECG) sensor. -->
+<permissions>
+    <feature name="android.hardware.sensor.heartrate.ecg" />
+</permissions>
diff --git a/include/gui/SensorEventQueue.h b/include/gui/SensorEventQueue.h
index 4e8a2d2..019308d 100644
--- a/include/gui/SensorEventQueue.h
+++ b/include/gui/SensorEventQueue.h
@@ -27,7 +27,7 @@
 #include <gui/BitTube.h>
 
 // ----------------------------------------------------------------------------
-#define WAKE_UP_SENSOR_EVENT_NEEDS_ACK (1 << 31)
+#define WAKE_UP_SENSOR_EVENT_NEEDS_ACK (1U << 31)
 struct ALooper;
 struct ASensorEvent;
 
diff --git a/libs/gui/CpuConsumer.cpp b/libs/gui/CpuConsumer.cpp
index bff55d1..cefd7f1 100644
--- a/libs/gui/CpuConsumer.cpp
+++ b/libs/gui/CpuConsumer.cpp
@@ -93,41 +93,62 @@
 
     int buf = b.mBuf;
 
-    if (b.mFence.get()) {
-        err = b.mFence->waitForever("CpuConsumer::lockNextBuffer");
-        if (err != OK) {
-            CC_LOGE("Failed to wait for fence of acquired buffer: %s (%d)",
-                    strerror(-err), err);
-            return err;
-        }
-    }
-
     void *bufferPointer = NULL;
     android_ycbcr ycbcr = android_ycbcr();
 
-    if (mSlots[buf].mGraphicBuffer->getPixelFormat() ==
-            HAL_PIXEL_FORMAT_YCbCr_420_888) {
-        err = mSlots[buf].mGraphicBuffer->lockYCbCr(
-            GraphicBuffer::USAGE_SW_READ_OFTEN,
-            b.mCrop,
-            &ycbcr);
+    if (b.mFence.get()) {
+        if (mSlots[buf].mGraphicBuffer->getPixelFormat() ==
+                HAL_PIXEL_FORMAT_YCbCr_420_888) {
+            err = mSlots[buf].mGraphicBuffer->lockAsyncYCbCr(
+                GraphicBuffer::USAGE_SW_READ_OFTEN,
+                b.mCrop,
+                &ycbcr,
+                b.mFence->dup());
 
-        if (err != OK) {
-            CC_LOGE("Unable to lock YCbCr buffer for CPU reading: %s (%d)",
-                    strerror(-err), err);
-            return err;
+            if (err != OK) {
+                CC_LOGE("Unable to lock YCbCr buffer for CPU reading: %s (%d)",
+                        strerror(-err), err);
+                return err;
+            }
+            bufferPointer = ycbcr.y;
+        } else {
+            err = mSlots[buf].mGraphicBuffer->lockAsync(
+                GraphicBuffer::USAGE_SW_READ_OFTEN,
+                b.mCrop,
+                &bufferPointer,
+                b.mFence->dup());
+
+            if (err != OK) {
+                CC_LOGE("Unable to lock buffer for CPU reading: %s (%d)",
+                        strerror(-err), err);
+                return err;
+            }
         }
-        bufferPointer = ycbcr.y;
     } else {
-        err = mSlots[buf].mGraphicBuffer->lock(
-            GraphicBuffer::USAGE_SW_READ_OFTEN,
-            b.mCrop,
-            &bufferPointer);
+        if (mSlots[buf].mGraphicBuffer->getPixelFormat() ==
+                HAL_PIXEL_FORMAT_YCbCr_420_888) {
+            err = mSlots[buf].mGraphicBuffer->lockYCbCr(
+                GraphicBuffer::USAGE_SW_READ_OFTEN,
+                b.mCrop,
+                &ycbcr);
 
-        if (err != OK) {
-            CC_LOGE("Unable to lock buffer for CPU reading: %s (%d)",
-                    strerror(-err), err);
-            return err;
+            if (err != OK) {
+                CC_LOGE("Unable to lock YCbCr buffer for CPU reading: %s (%d)",
+                        strerror(-err), err);
+                return err;
+            }
+            bufferPointer = ycbcr.y;
+        } else {
+            err = mSlots[buf].mGraphicBuffer->lock(
+                GraphicBuffer::USAGE_SW_READ_OFTEN,
+                b.mCrop,
+                &bufferPointer);
+
+            if (err != OK) {
+                CC_LOGE("Unable to lock buffer for CPU reading: %s (%d)",
+                        strerror(-err), err);
+                return err;
+            }
         }
     }
 
@@ -189,14 +210,22 @@
 
 status_t CpuConsumer::releaseAcquiredBufferLocked(int lockedIdx) {
     status_t err;
+    int fd = -1;
 
-    err = mAcquiredBuffers[lockedIdx].mGraphicBuffer->unlock();
+    err = mAcquiredBuffers[lockedIdx].mGraphicBuffer->unlockAsync(&fd);
     if (err != OK) {
         CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__,
                 lockedIdx);
         return err;
     }
     int buf = mAcquiredBuffers[lockedIdx].mSlot;
+    if (CC_LIKELY(fd != -1)) {
+        sp<Fence> fence(new Fence(fd));
+        addReleaseFenceLocked(
+            mAcquiredBuffers[lockedIdx].mSlot,
+            mSlots[buf].mGraphicBuffer,
+            fence);
+    }
 
     // release the buffer if it hasn't already been freed by the BufferQueue.
     // This can happen, for example, when the producer of this buffer
diff --git a/opengl/libs/GLES_trace/src/gltrace_context.cpp b/opengl/libs/GLES_trace/src/gltrace_context.cpp
index 0323e8f..d1b3586 100644
--- a/opengl/libs/GLES_trace/src/gltrace_context.cpp
+++ b/opengl/libs/GLES_trace/src/gltrace_context.cpp
@@ -133,6 +133,9 @@
         BufferedOutputStream *stream) :
     mId(id),
     mVersion(version),
+    mVersionMajor(0),
+    mVersionMinor(0),
+    mVersionParsed(false),
     mState(state),
     mBufferedOutputStream(stream),
     mElementArrayBuffers(DefaultKeyedVector<GLuint, ElementArrayBuffer*>(NULL))
@@ -149,10 +152,40 @@
     return mVersion;
 }
 
+int GLTraceContext::getVersionMajor() {
+    if (!mVersionParsed) {
+        parseGlesVersion();
+        mVersionParsed = true;
+    }
+    return mVersionMajor;
+}
+
+int GLTraceContext::getVersionMinor() {
+    if (!mVersionParsed) {
+        parseGlesVersion();
+        mVersionParsed = true;
+    }
+    return mVersionMinor;
+}
+
 GLTraceState *GLTraceContext::getGlobalTraceState() {
     return mState;
 }
 
+void GLTraceContext::parseGlesVersion() {
+    const char* str = (const char*)hooks->gl.glGetString(GL_VERSION);
+    int major, minor;
+    if (sscanf(str, "OpenGL ES-CM %d.%d", &major, &minor) != 2) {
+        if (sscanf(str, "OpenGL ES %d.%d", &major, &minor) != 2) {
+            ALOGW("Unable to parse GL_VERSION string: \"%s\"", str);
+            major = 1;
+            minor = 0;
+        }
+    }
+    mVersionMajor = major;
+    mVersionMinor = minor;
+}
+
 void GLTraceContext::resizeFBMemory(unsigned minSize) {
     if (fbcontentsSize >= minSize) {
         return;
diff --git a/opengl/libs/GLES_trace/src/gltrace_context.h b/opengl/libs/GLES_trace/src/gltrace_context.h
index 4c38bba..38c7315 100644
--- a/opengl/libs/GLES_trace/src/gltrace_context.h
+++ b/opengl/libs/GLES_trace/src/gltrace_context.h
@@ -51,6 +51,9 @@
 class GLTraceContext {
     int mId;                    /* unique context id */
     int mVersion;               /* GL version, e.g: egl_connection_t::GLESv2_INDEX */
+    int mVersionMajor;          /* GL major version. Lazily parsed in getVersionX(). */
+    int mVersionMinor;          /* GL minor version. Lazily parsed in getVersionX(). */
+    bool mVersionParsed;        /* True if major and minor versions have been parsed. */
     GLTraceState *mState;       /* parent GL Trace state (for per process GL Trace State Info) */
 
     void *fbcontents;           /* memory area to read framebuffer contents */
@@ -62,6 +65,9 @@
     /* list of element array buffers in use. */
     DefaultKeyedVector<GLuint, ElementArrayBuffer*> mElementArrayBuffers;
 
+    /* Parses the GL version string returned from glGetString(GL_VERSION) to get find the major and
+       minor versions of the GLES API. The context must be current before calling. */
+    void parseGlesVersion();
     void resizeFBMemory(unsigned minSize);
 public:
     gl_hooks_t *hooks;
@@ -69,6 +75,8 @@
     GLTraceContext(int id, int version, GLTraceState *state, BufferedOutputStream *stream);
     int getId();
     int getVersion();
+    int getVersionMajor();
+    int getVersionMinor();
     GLTraceState *getGlobalTraceState();
     void getCompressedFB(void **fb, unsigned *fbsize,
                             unsigned *fbwidth, unsigned *fbheight,
diff --git a/opengl/libs/GLES_trace/src/gltrace_fixup.cpp b/opengl/libs/GLES_trace/src/gltrace_fixup.cpp
index e6d0062..be729c7 100644
--- a/opengl/libs/GLES_trace/src/gltrace_fixup.cpp
+++ b/opengl/libs/GLES_trace/src/gltrace_fixup.cpp
@@ -29,6 +29,33 @@
 namespace android {
 namespace gltrace {
 
+GLint glGetInteger(GLTraceContext *context, GLenum param) {
+    GLint x;
+    context->hooks->gl.glGetIntegerv(param, &x);
+    return x;
+}
+
+GLint glGetVertexAttrib(GLTraceContext *context, GLuint index, GLenum pname) {
+    GLint x;
+    context->hooks->gl.glGetVertexAttribiv(index, pname, &x);
+    return x;
+}
+
+bool isUsingPixelBuffers(GLTraceContext *context) {
+    if (context->getVersionMajor() < 3) {
+        return false; // PBOs not supported prior to GLES 3.0
+    }
+    return glGetInteger(context, GL_PIXEL_UNPACK_BUFFER_BINDING) != 0;
+}
+
+bool isUsingArrayBuffers(GLTraceContext *context) {
+    return glGetInteger(context, GL_ARRAY_BUFFER_BINDING) != 0;
+}
+
+bool isUsingElementArrayBuffers(GLTraceContext *context) {
+    return glGetInteger(context, GL_ELEMENT_ARRAY_BUFFER_BINDING) != 0;
+}
+
 unsigned getBytesPerTexel(const GLenum format, const GLenum type) {
     /*
     Description from glTexImage2D spec:
@@ -156,7 +183,8 @@
 }
 
 /** Common fixup routing for glTexImage2D & glTexSubImage2D. */
-void fixup_glTexImage(int widthIndex, int heightIndex, GLMessage *glmsg, void *dataSrc) {
+void fixup_glTexImage(GLTraceContext *context, int widthIndex, int heightIndex, GLMessage *glmsg,
+                        void *dataSrc) {
     GLMessage_DataType arg_width  = glmsg->args(widthIndex);
     GLMessage_DataType arg_height = glmsg->args(heightIndex);
 
@@ -175,7 +203,7 @@
     arg_data->set_type(GLMessage::DataType::BYTE);
     arg_data->clear_rawbytes();
 
-    if (data != NULL) {
+    if (data != NULL && !isUsingPixelBuffers(context)) {
         arg_data->set_isarray(true);
         arg_data->add_rawbytes(data, bytesPerTexel * width * height);
     } else {
@@ -185,7 +213,7 @@
 }
 
 
-void fixup_glTexImage2D(GLMessage *glmsg, void *pointersToFixup[]) {
+void fixup_glTexImage2D(GLTraceContext *context, GLMessage *glmsg, void *pointersToFixup[]) {
     /* void glTexImage2D(GLenum target,
                         GLint level,
                         GLint internalformat,
@@ -198,10 +226,10 @@
     */
     int widthIndex = 3;
     int heightIndex = 4;
-    fixup_glTexImage(widthIndex, heightIndex, glmsg, pointersToFixup[0]);
+    fixup_glTexImage(context, widthIndex, heightIndex, glmsg, pointersToFixup[0]);
 }
 
-void fixup_glTexSubImage2D(GLMessage *glmsg, void *pointersToFixup[]) {
+void fixup_glTexSubImage2D(GLTraceContext *context, GLMessage *glmsg, void *pointersToFixup[]) {
     /*
     void glTexSubImage2D(GLenum target,
                         GLint level,
@@ -215,10 +243,11 @@
     */
     int widthIndex = 4;
     int heightIndex = 5;
-    fixup_glTexImage(widthIndex, heightIndex, glmsg, pointersToFixup[0]);
+    fixup_glTexImage(context, widthIndex, heightIndex, glmsg, pointersToFixup[0]);
 }
 
-void fixup_glCompressedTexImage2D(GLMessage *glmsg, void *pointersToFixup[]) {
+void fixup_glCompressedTexImage2D(GLTraceContext *context, GLMessage *glmsg,
+                                    void *pointersToFixup[]) {
     /* void glCompressedTexImage2D(GLenum target,
                                    GLint level,
                                    GLenum internalformat,
@@ -235,7 +264,7 @@
     arg_data->set_type(GLMessage::DataType::BYTE);
     arg_data->clear_rawbytes();
 
-    if (data != NULL) {
+    if (data != NULL && !isUsingPixelBuffers(context)) {
         arg_data->set_isarray(true);
         arg_data->add_rawbytes(data, size);
     } else {
@@ -244,7 +273,8 @@
     }
 }
 
-void fixup_glCompressedTexSubImage2D(GLMessage *glmsg, void *pointersToFixup[]) {
+void fixup_glCompressedTexSubImage2D(GLTraceContext *context, GLMessage *glmsg,
+                                        void *pointersToFixup[]) {
     /* void glCompressedTexSubImage2D(GLenum target,
                                       GLint level,
                                       GLint xoffset,
@@ -262,7 +292,7 @@
     arg_data->set_type(GLMessage::DataType::BYTE);
     arg_data->clear_rawbytes();
 
-    if (data != NULL) {
+    if (data != NULL && !isUsingPixelBuffers(context)) {
         arg_data->set_isarray(true);
         arg_data->add_rawbytes(data, size);
     } else {
@@ -436,26 +466,6 @@
     arg_location->add_intvalue(location);
 }
 
-GLint glGetInteger(GLTraceContext *context, GLenum param) {
-    GLint x;
-    context->hooks->gl.glGetIntegerv(param, &x);
-    return x;
-}
-
-GLint glGetVertexAttrib(GLTraceContext *context, GLuint index, GLenum pname) {
-    GLint x;
-    context->hooks->gl.glGetVertexAttribiv(index, pname, &x);
-    return x;
-}
-
-bool isUsingArrayBuffers(GLTraceContext *context) {
-    return glGetInteger(context, GL_ARRAY_BUFFER_BINDING) != 0;
-}
-
-bool isUsingElementArrayBuffers(GLTraceContext *context) {
-    return glGetInteger(context, GL_ELEMENT_ARRAY_BUFFER_BINDING) != 0;
-}
-
 /** Copy @len bytes of data from @src into the @dataIndex'th argument of the message. */
 void addGlBufferData(GLMessage *glmsg, int dataIndex, GLvoid *src, GLsizeiptr len) {
     GLMessage_DataType *arg_datap = glmsg->mutable_args(dataIndex);
@@ -809,22 +819,22 @@
         break;
     case GLMessage::glTexImage2D:
         if (context->getGlobalTraceState()->shouldCollectTextureDataOnGlTexImage()) {
-            fixup_glTexImage2D(glmsg, pointersToFixup);
+            fixup_glTexImage2D(context, glmsg, pointersToFixup);
         }
         break;
     case GLMessage::glTexSubImage2D:
         if (context->getGlobalTraceState()->shouldCollectTextureDataOnGlTexImage()) {
-            fixup_glTexSubImage2D(glmsg, pointersToFixup);
+            fixup_glTexSubImage2D(context, glmsg, pointersToFixup);
         }
         break;
     case GLMessage::glCompressedTexImage2D:
         if (context->getGlobalTraceState()->shouldCollectTextureDataOnGlTexImage()) {
-            fixup_glCompressedTexImage2D(glmsg, pointersToFixup);
+            fixup_glCompressedTexImage2D(context, glmsg, pointersToFixup);
         }
         break;
     case GLMessage::glCompressedTexSubImage2D:
         if (context->getGlobalTraceState()->shouldCollectTextureDataOnGlTexImage()) {
-            fixup_glCompressedTexSubImage2D(glmsg, pointersToFixup);
+            fixup_glCompressedTexSubImage2D(context, glmsg, pointersToFixup);
         }
         break;
     case GLMessage::glShaderSource:
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index 3934509..80845a2 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -54,6 +54,11 @@
                 SENSORS_HARDWARE_MODULE_ID, strerror(-err));
 
         if (mSensorDevice) {
+            if (mSensorDevice->common.version == SENSORS_DEVICE_API_VERSION_1_1 ||
+                mSensorDevice->common.version == SENSORS_DEVICE_API_VERSION_1_2) {
+                ALOGE(">>>> WARNING <<< Upgrade sensor HAL to version 1_3");
+            }
+
             sensor_t const* list;
             ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);
             mActivationCount.setCapacity(count);
@@ -74,6 +79,7 @@
     sensor_t const* list;
     ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);
 
+    result.appendFormat("halVersion %d\n", getHalDeviceVersion());
     result.appendFormat("%d h/w sensors:\n", int(count));
 
     Mutex::Autolock _l(mLock);
@@ -210,24 +216,8 @@
     }
 
     const int halVersion = getHalDeviceVersion();
-    if (halVersion >= SENSORS_DEVICE_API_VERSION_1_1) {
-        if (flags & SENSORS_BATCH_DRY_RUN) {
-            return mSensorDevice->batch(mSensorDevice, handle, flags, samplingPeriodNs,
-                                        maxBatchReportLatencyNs);
-        } else {
-            // Call h/w with dry run to see if the given parameters are feasible or not. Return if
-            // there is an error.
-            status_t errDryRun(NO_ERROR);
-            errDryRun = mSensorDevice->batch(mSensorDevice, handle, flags | SENSORS_BATCH_DRY_RUN,
-                                             samplingPeriodNs, maxBatchReportLatencyNs);
-            if (errDryRun != NO_ERROR) {
-                ALOGD_IF(DEBUG_CONNECTIONS, "SensorDevice::batch dry run error %s",
-                         strerror(-errDryRun));
-                return errDryRun;
-            }
-        }
-    } else if (maxBatchReportLatencyNs != 0) {
-        // Batch is not supported on older devices.
+    if (halVersion < SENSORS_DEVICE_API_VERSION_1_1 && maxBatchReportLatencyNs != 0) {
+        // Batch is not supported on older devices return invalid operation.
         return INVALID_OPERATION;
     }
 
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 8fe79d0..bee5062 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -218,69 +218,85 @@
             const Sensor& s(mSensorList[i]);
             const sensors_event_t& e(mLastEventSeen.valueFor(s.getHandle()));
             result.appendFormat(
-                    "%-48s| %-32s| %-48s| 0x%08x | \"%s\"\n\t",
+                    "%-15s| %-10s| %-20s| 0x%08x | \"%s\" | type=%d |",
                     s.getName().string(),
                     s.getVendor().string(),
                     s.getStringType().string(),
                     s.getHandle(),
-                    s.getRequiredPermission().string());
+                    s.getRequiredPermission().string(),
+                    s.getType());
 
             const int reportingMode = s.getReportingMode();
             if (reportingMode == AREPORTING_MODE_CONTINUOUS) {
-                result.append("continuous      |");
+                result.append(" continuous | ");
             } else if (reportingMode == AREPORTING_MODE_ON_CHANGE) {
-                result.append("on-change       | ");
+                result.append(" on-change | ");
             } else if (reportingMode == AREPORTING_MODE_ONE_SHOT) {
-                result.append("one-shot        | ");
+                result.append(" one-shot | ");
             } else {
-                result.append("special-trigger | ");
+                result.append(" special-trigger | ");
+            }
+
+            if (s.getMaxDelay() > 0) {
+                result.appendFormat("minRate=%.2fHz | ", 1e6f / s.getMaxDelay());
+            } else {
+                result.appendFormat("maxDelay=%dus |", s.getMaxDelay());
             }
 
             if (s.getMinDelay() > 0) {
-                result.appendFormat("maxRate=%7.2fHz | ", 1e6f / s.getMinDelay());
+                result.appendFormat("maxRate=%.2fHz | ", 1e6f / s.getMinDelay());
             } else {
-                result.appendFormat("minDelay=%5dus |", s.getMinDelay());
+                result.appendFormat("minDelay=%dus |", s.getMinDelay());
             }
 
             if (s.getFifoMaxEventCount() > 0) {
                 result.appendFormat("FifoMax=%d events | ",
                         s.getFifoMaxEventCount());
             } else {
-                result.append("no batching support | ");
+                result.append("no batching | ");
+            }
+
+            if (s.isWakeUpSensor()) {
+                result.appendFormat("wakeUp | ");
+            } else {
+                result.appendFormat("non-wakeUp | ");
             }
 
             switch (s.getType()) {
                 case SENSOR_TYPE_ROTATION_VECTOR:
                 case SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR:
                     result.appendFormat(
-                            "last=<%5.1f,%5.1f,%5.1f,%5.1f,%5.1f>\n",
-                            e.data[0], e.data[1], e.data[2], e.data[3], e.data[4]);
+                            "last=<%5.1f,%5.1f,%5.1f,%5.1f,%5.1f, %" PRId64 ">\n",
+                            e.data[0], e.data[1], e.data[2], e.data[3], e.data[4], e.timestamp);
                     break;
                 case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
                 case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
                     result.appendFormat(
-                            "last=<%5.1f,%5.1f,%5.1f,%5.1f,%5.1f,%5.1f>\n",
-                            e.data[0], e.data[1], e.data[2], e.data[3], e.data[4], e.data[5]);
+                            "last=<%5.1f,%5.1f,%5.1f,%5.1f,%5.1f,%5.1f, %" PRId64 ">\n",
+                            e.data[0], e.data[1], e.data[2], e.data[3], e.data[4], e.data[5],
+                            e.timestamp);
                     break;
                 case SENSOR_TYPE_GAME_ROTATION_VECTOR:
                     result.appendFormat(
-                            "last=<%5.1f,%5.1f,%5.1f,%5.1f>\n",
-                            e.data[0], e.data[1], e.data[2], e.data[3]);
+                            "last=<%5.1f,%5.1f,%5.1f,%5.1f, %" PRId64 ">\n",
+                            e.data[0], e.data[1], e.data[2], e.data[3], e.timestamp);
                     break;
                 case SENSOR_TYPE_SIGNIFICANT_MOTION:
                 case SENSOR_TYPE_STEP_DETECTOR:
-                    result.appendFormat( "last=<%f>\n", e.data[0]);
+                    result.appendFormat( "last=<%f %" PRId64 ">\n", e.data[0], e.timestamp);
                     break;
                 case SENSOR_TYPE_STEP_COUNTER:
-                    result.appendFormat( "last=<%" PRIu64 ">\n", e.u64.step_counter);
+                    result.appendFormat( "last=<%" PRIu64 ", %" PRId64 ">\n", e.u64.step_counter,
+                                         e.timestamp);
                     break;
                 default:
                     // default to 3 values
                     result.appendFormat(
-                            "last=<%5.1f,%5.1f,%5.1f>\n",
-                            e.data[0], e.data[1], e.data[2]);
+                            "last=<%5.1f,%5.1f,%5.1f, %" PRId64 ">\n",
+                            e.data[0], e.data[1], e.data[2], e.timestamp);
                     break;
             }
+            result.append("\n");
         }
         SensorFusion::getInstance().dump(result);
         SensorDevice::getInstance().dump(result);
@@ -294,7 +310,8 @@
                     mActiveSensors.valueAt(i)->getNumConnections());
         }
 
-        result.appendFormat("%zu Max Socket Buffer size\n", mSocketBufferSize);
+        result.appendFormat("Max Socket Buffer size = %d events\n",
+                            mSocketBufferSize/sizeof(sensors_event_t));
         result.appendFormat("WakeLock Status: %s \n", mWakeLockAcquired ? "acquired" : "not held");
         result.appendFormat("%zd active connections\n", mActiveConnections.size());
 
@@ -520,6 +537,11 @@
     return sensor != NULL && sensor->getSensor().isWakeUpSensor();
 }
 
+
+SensorService::SensorRecord * SensorService::getSensorRecord(int handle) {
+     return mActiveSensors.valueFor(handle);
+}
+
 Vector<Sensor> SensorService::getSensorList()
 {
     char value[PROPERTY_VALUE_MAX];
@@ -658,18 +680,20 @@
         samplingPeriodNs = minDelayNs;
     }
 
-    ALOGD_IF(DEBUG_CONNECTIONS, "Calling batch handle==%d flags=%d rate=%" PRId64 " timeout== %" PRId64,
+    ALOGD_IF(DEBUG_CONNECTIONS, "Calling batch handle==%d flags=%d"
+                                "rate=%" PRId64 " timeout== %" PRId64"",
              handle, reservedFlags, samplingPeriodNs, maxBatchReportLatencyNs);
 
     status_t err = sensor->batch(connection.get(), handle, reservedFlags, samplingPeriodNs,
                                  maxBatchReportLatencyNs);
-    if (err == NO_ERROR) {
-        connection->setFirstFlushPending(handle, true);
+
+    if (err == NO_ERROR && sensor->getSensor().getReportingMode() != AREPORTING_MODE_ONE_SHOT) {
         status_t err_flush = sensor->flush(connection.get(), handle);
         // Flush may return error if the sensor is not activated or the underlying h/w sensor does
         // not support flush.
-        if (err_flush != NO_ERROR) {
-            connection->setFirstFlushPending(handle, false);
+        if (err_flush == NO_ERROR) {
+            connection->setFirstFlushPending(handle, true);
+            rec->addPendingFlushConnection(connection.get());
         }
     }
 
@@ -775,7 +799,13 @@
         ALOGE("flush called on a one-shot sensor");
         return INVALID_OPERATION;
     }
-    return sensor->flush(connection.get(), handle);
+
+    status_t ret = sensor->flush(connection.get(), handle);
+    if (ret == NO_ERROR) {
+        SensorRecord* rec = mActiveSensors.valueFor(handle);
+        if (rec != NULL) rec->addPendingFlushConnection(connection);
+    }
+    return ret;
 }
 
 
@@ -823,6 +853,7 @@
         mWakeLockAcquired = false;
     }
 }
+
 // ---------------------------------------------------------------------------
 SensorService::SensorRecord::SensorRecord(
         const sp<SensorEventConnection>& connection)
@@ -847,9 +878,37 @@
     if (index >= 0) {
         mConnections.removeItemsAt(index, 1);
     }
+    // Remove this connections from the queue of flush() calls made on this sensor.
+    for (Vector< wp<SensorEventConnection> >::iterator it =
+            mPendingFlushConnections.begin(); it != mPendingFlushConnections.end();) {
+        if (it->unsafe_get() == connection.unsafe_get()) {
+            it = mPendingFlushConnections.erase(it);
+        } else {
+            ++it;
+        }
+    }
     return mConnections.size() ? false : true;
 }
 
+void SensorService::SensorRecord::addPendingFlushConnection(
+        const sp<SensorEventConnection>& connection) {
+    mPendingFlushConnections.add(connection);
+}
+
+void SensorService::SensorRecord::removeFirstPendingFlushConnection() {
+    if (mPendingFlushConnections.size() > 0) {
+        mPendingFlushConnections.removeAt(0);
+    }
+}
+
+SensorService::SensorEventConnection *
+SensorService::SensorRecord::getFirstPendingFlushConnection() {
+   if (mPendingFlushConnections.size() > 0) {
+        return mPendingFlushConnections[0].unsafe_get();
+    }
+    return NULL;
+}
+
 // ---------------------------------------------------------------------------
 
 SensorService::SensorEventConnection::SensorEventConnection(
@@ -890,13 +949,13 @@
     result.appendFormat("\t %d WakeLockRefCount \n", mWakeLockRefCount);
     for (size_t i = 0; i < mSensorInfo.size(); ++i) {
         const FlushInfo& flushInfo = mSensorInfo.valueAt(i);
-        result.appendFormat("\t %s | status: %s | pending flush events %d | flush calls %d| uid %d|"
+        result.appendFormat("\t %s 0x%08x | status: %s | pending flush events %d | uid %d|"
                             "cache size: %d max cache size %d\n",
                             mService->getSensorName(mSensorInfo.keyAt(i)).string(),
+                            mSensorInfo.keyAt(i),
                             flushInfo.mFirstFlushPending ? "First flush pending" :
                                                            "active",
                             flushInfo.mPendingFlushEventsToSend,
-                            flushInfo.mNumFlushCalls,
                             mUid,
                             mCacheSize,
                             mMaxCacheSize);
@@ -905,7 +964,7 @@
                                         mEventsReceived,
                                         mEventsSent,
                                         mEventsSentFromCache,
-                                        mEventsReceived - (mEventsSentFromCache +
+                                        mEventsReceived - (mEventsSentFromCache
                                                            mEventsSent + mCacheSize));
 #endif
 
@@ -961,15 +1020,15 @@
     if (scratch) {
         size_t i=0;
         while (i<numEvents) {
-            int32_t curr = buffer[i].sensor;
+            int32_t sensor_handle = buffer[i].sensor;
             if (buffer[i].type == SENSOR_TYPE_META_DATA) {
                 ALOGD_IF(DEBUG_CONNECTIONS, "flush complete event sensor==%d ",
                          buffer[i].meta_data.sensor);
-                // Setting curr to the correct sensor to ensure the sensor events per connection are
+                // Setting sensor_handle to the correct sensor to ensure the sensor events per connection are
                 // filtered correctly. buffer[i].sensor is zero for meta_data events.
-                curr = buffer[i].meta_data.sensor;
+                sensor_handle = buffer[i].meta_data.sensor;
             }
-            ssize_t index = mSensorInfo.indexOfKey(curr);
+            ssize_t index = mSensorInfo.indexOfKey(sensor_handle);
             // Check if this connection has registered for this sensor. If not continue to the
             // next sensor_event.
             if (index < 0) {
@@ -977,16 +1036,16 @@
                 continue;
             }
 
-            // Check if there is a pending flush_complete event for this sensor on this connection.
             FlushInfo& flushInfo = mSensorInfo.editValueAt(index);
-            if (buffer[i].type == SENSOR_TYPE_META_DATA) {
-                if (flushInfo.mFirstFlushPending == true) {
-                    // This is the first flush before activate is called. Events can now be sent for
-                    // this sensor on this connection.
-                    ALOGD_IF(DEBUG_CONNECTIONS, "First flush event for sensor==%d ",
-                                                    buffer[i].meta_data.sensor);
+            // Check if there is a pending flush_complete event for this sensor on this connection.
+            if (buffer[i].type == SENSOR_TYPE_META_DATA && flushInfo.mFirstFlushPending == true) {
+                SensorService::SensorRecord *rec = mService->getSensorRecord(sensor_handle);
+                if (rec && rec->getFirstPendingFlushConnection() == this) {
+                    rec->removeFirstPendingFlushConnection();
                     flushInfo.mFirstFlushPending = false;
                     ++i;
+                    ALOGD_IF(DEBUG_CONNECTIONS, "First flush event for sensor==%d ",
+                                                    buffer[i].meta_data.sensor);
                     continue;
                 }
             }
@@ -1000,26 +1059,28 @@
 
             do {
                 if (buffer[i].type == SENSOR_TYPE_META_DATA) {
-                    // Send flush complete event only if flush() has been explicitly called by
-                    // this app else ignore.
-                    if (flushInfo.mNumFlushCalls > 0) {
+                   // Check if this connection has called flush() on this sensor. Only if
+                   // a flush() has been explicitly called, send a flush_complete_event.
+                   SensorService::SensorRecord *rec = mService->getSensorRecord(sensor_handle);
+                   if (rec && rec->getFirstPendingFlushConnection() == this) {
+                        rec->removeFirstPendingFlushConnection();
                         scratch[count++] = buffer[i];
-                        flushInfo.mNumFlushCalls--;
                     }
                     ++i;
                 } else {
                     // Regular sensor event, just copy it to the scratch buffer.
                     scratch[count++] = buffer[i++];
                 }
-            } while ((i<numEvents) && ((buffer[i].sensor == curr) ||
+            } while ((i<numEvents) && ((buffer[i].sensor == sensor_handle) ||
                                        (buffer[i].type == SENSOR_TYPE_META_DATA  &&
-                                        buffer[i].meta_data.sensor == curr)));
+                                        buffer[i].meta_data.sensor == sensor_handle)));
         }
     } else {
         scratch = const_cast<sensors_event_t *>(buffer);
         count = numEvents;
     }
 
+    sendPendingFlushEventsLocked();
     // Early return if there are no events for this connection.
     if (count == 0) {
         return status_t(NO_ERROR);
@@ -1035,6 +1096,12 @@
             memcpy(&mEventCache[mCacheSize], scratch, count * sizeof(sensors_event_t));
             mCacheSize += count;
         } else {
+            // Check if any new sensors have registered on this connection which may have increased
+            // the max cache size that is desired.
+            if (mCacheSize + count < computeMaxCacheSizeLocked()) {
+                reAllocateCacheLocked(scratch, count);
+                return status_t(NO_ERROR);
+            }
             // Some events need to be dropped.
             int remaningCacheSize = mMaxCacheSize - mCacheSize;
             if (remaningCacheSize != 0) {
@@ -1054,15 +1121,22 @@
         return status_t(NO_ERROR);
     }
 
-    int numWakeUpSensorEvents = countWakeUpSensorEventsLocked(scratch, count);
-    mWakeLockRefCount += numWakeUpSensorEvents;
+    int index_wake_up_event = findWakeUpSensorEventLocked(scratch, count);
+    if (index_wake_up_event >= 0) {
+        scratch[index_wake_up_event].flags |= WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
+        ++mWakeLockRefCount;
+    }
 
     // NOTE: ASensorEvent and sensors_event_t are the same type.
     ssize_t size = SensorEventQueue::write(mChannel,
                                     reinterpret_cast<ASensorEvent const*>(scratch), count);
     if (size < 0) {
         // Write error, copy events to local cache.
-        mWakeLockRefCount -= numWakeUpSensorEvents;
+        if (index_wake_up_event >= 0) {
+            // If there was a wake_up sensor_event, reset the flag.
+            scratch[index_wake_up_event].flags &= ~WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
+            --mWakeLockRefCount;
+        }
         if (mEventCache == NULL) {
             mMaxCacheSize = computeMaxCacheSizeLocked();
             mEventCache = new sensors_event_t[mMaxCacheSize];
@@ -1087,53 +1161,81 @@
     return size < 0 ? status_t(size) : status_t(NO_ERROR);
 }
 
+void SensorService::SensorEventConnection::reAllocateCacheLocked(sensors_event_t const* scratch,
+                                                                 int count) {
+    sensors_event_t *eventCache_new;
+    const int new_cache_size = computeMaxCacheSizeLocked();
+    // Allocate new cache, copy over events from the old cache & scratch, free up memory.
+    eventCache_new = new sensors_event_t[new_cache_size];
+    memcpy(eventCache_new, mEventCache, mCacheSize * sizeof(sensors_event_t));
+    memcpy(&eventCache_new[mCacheSize], scratch, count * sizeof(sensors_event_t));
+
+    ALOGD_IF(DEBUG_CONNECTIONS, "reAllocateCacheLocked maxCacheSize=%d %d", mMaxCacheSize,
+            new_cache_size);
+
+    delete mEventCache;
+    mEventCache = eventCache_new;
+    mCacheSize += count;
+    mMaxCacheSize = new_cache_size;
+}
+
+void SensorService::SensorEventConnection::sendPendingFlushEventsLocked() {
+    ASensorEvent flushCompleteEvent;
+    flushCompleteEvent.type = SENSOR_TYPE_META_DATA;
+    flushCompleteEvent.sensor = 0;
+    // Loop through all the sensors for this connection and check if there are any pending
+    // flush complete events to be sent.
+    for (size_t i = 0; i < mSensorInfo.size(); ++i) {
+        FlushInfo& flushInfo = mSensorInfo.editValueAt(i);
+        while (flushInfo.mPendingFlushEventsToSend > 0) {
+            flushCompleteEvent.meta_data.sensor = mSensorInfo.keyAt(i);
+            ssize_t size = SensorEventQueue::write(mChannel, &flushCompleteEvent, 1);
+            if (size < 0) {
+                return;
+            }
+            ALOGD_IF(DEBUG_CONNECTIONS, "sent dropped flush complete event==%d ",
+                    flushCompleteEvent.meta_data.sensor);
+            flushInfo.mPendingFlushEventsToSend--;
+        }
+    }
+}
+
 void SensorService::SensorEventConnection::writeToSocketFromCacheLocked() {
     // At a time write at most half the size of the receiver buffer in SensorEventQueue.
     const int maxWriteSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT/2;
-    // Send pending flush events (if any) before sending events from the buffer.
-    {
-        ASensorEvent flushCompleteEvent;
-        flushCompleteEvent.type = SENSOR_TYPE_META_DATA;
-        flushCompleteEvent.sensor = 0;
-        // Loop through all the sensors for this connection and check if there are any pending
-        // flush complete events to be sent.
-        for (size_t i = 0; i < mSensorInfo.size(); ++i) {
-            FlushInfo& flushInfo = mSensorInfo.editValueAt(i);
-            while (flushInfo.mPendingFlushEventsToSend > 0) {
-                flushCompleteEvent.meta_data.sensor = mSensorInfo.keyAt(i);
-                ssize_t size = SensorEventQueue::write(mChannel, &flushCompleteEvent, 1);
-                if (size < 0) {
-                    return;
-                }
-                ALOGD_IF(DEBUG_CONNECTIONS, "sent dropped flush complete event==%d ",
-                                                flushCompleteEvent.meta_data.sensor);
-                flushInfo.mPendingFlushEventsToSend--;
-            }
-        }
-    }
+    sendPendingFlushEventsLocked();
     // Write "count" events at a time.
     for (int numEventsSent = 0; numEventsSent < mCacheSize;) {
-        const int count = (mCacheSize - numEventsSent) < maxWriteSize ?
+        const int numEventsToWrite = (mCacheSize - numEventsSent) < maxWriteSize ?
                                         mCacheSize - numEventsSent : maxWriteSize;
-        int numWakeUpSensorEvents =
-                  countWakeUpSensorEventsLocked(mEventCache + numEventsSent, count);
-        mWakeLockRefCount += numWakeUpSensorEvents;
+        int index_wake_up_event =
+                  findWakeUpSensorEventLocked(mEventCache + numEventsSent, numEventsToWrite);
+        if (index_wake_up_event >= 0) {
+            mEventCache[index_wake_up_event + numEventsSent].flags |=
+                    WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
+            ++mWakeLockRefCount;
+        }
 
         ssize_t size = SensorEventQueue::write(mChannel,
                           reinterpret_cast<ASensorEvent const*>(mEventCache + numEventsSent),
-                          count);
+                          numEventsToWrite);
         if (size < 0) {
+            if (index_wake_up_event >= 0) {
+                // If there was a wake_up sensor_event, reset the flag.
+                mEventCache[index_wake_up_event + numEventsSent].flags  &=
+                        ~WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
+                --mWakeLockRefCount;
+            }
             memmove(mEventCache, &mEventCache[numEventsSent],
                                  (mCacheSize - numEventsSent) * sizeof(sensors_event_t));
             ALOGD_IF(DEBUG_CONNECTIONS, "wrote %d events from cache size==%d ",
-                                            numEventsSent, mCacheSize);
+                    numEventsSent, mCacheSize);
             mCacheSize -= numEventsSent;
-            mWakeLockRefCount -= numWakeUpSensorEvents;
             return;
         }
-        numEventsSent += count;
+        numEventsSent += numEventsToWrite;
 #if DEBUG_CONNECTIONS
-        mEventsSentFromCache += count;
+        mEventsSentFromCache += numEventsToWrite;
 #endif
     }
     ALOGD_IF(DEBUG_CONNECTIONS, "wrote all events from cache size=%d ", mCacheSize);
@@ -1159,15 +1261,14 @@
     return;
 }
 
-int SensorService::SensorEventConnection::countWakeUpSensorEventsLocked(
-                       sensors_event_t* scratch, const int count) {
+int SensorService::SensorEventConnection::findWakeUpSensorEventLocked(
+                       sensors_event_t const* scratch, const int count) {
     for (int i = 0; i < count; ++i) {
         if (mService->isWakeUpSensorEvent(scratch[i])) {
-            scratch[i].flags |= WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
-            return 1;
+            return i;
         }
     }
-    return 0;
+    return -1;
 }
 
 sp<BitTube> SensorService::SensorEventConnection::getSensorChannel() const
@@ -1211,9 +1312,7 @@
             flushInfo.mPendingFlushEventsToSend++;
         } else {
             status_t err_flush = mService->flushSensor(this, handle);
-            if (err_flush == NO_ERROR) {
-                flushInfo.mNumFlushCalls++;
-            } else {
+            if (err_flush != NO_ERROR) {
                 ALOGE("Flush error handle=%d %s", handle, strerror(-err_flush));
             }
             err = (err_flush != NO_ERROR) ? err_flush : err;
@@ -1280,9 +1379,9 @@
    }
    if (fifoWakeUpSensors + fifoNonWakeUpSensors == 0) {
        // It is extremely unlikely that there is a write failure in non batch mode. Return a cache
-       // size of 100.
+       // size that is equal to that of the batch mode.
        ALOGI("Write failure in non-batch mode");
-       return 100;
+       return MAX_SOCKET_BUFFER_SIZE_BATCHED/sizeof(sensors_event_t);
    }
    return fifoWakeUpSensors + fifoNonWakeUpSensors;
 }
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 3cdc825..15759ae 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -44,7 +44,6 @@
 #define MAX_SOCKET_BUFFER_SIZE_BATCHED 100 * 1024
 // For older HALs which don't support batching, use a smaller socket buffer size.
 #define SOCKET_BUFFER_SIZE_NON_BATCHED 4 * 1024
-#define WAKE_UP_SENSOR_EVENT_NEEDS_ACK (1U << 31)
 
 struct sensors_poll_device_t;
 struct sensors_module_t;
@@ -89,11 +88,17 @@
         // sent separately before the next batch of events.
         void countFlushCompleteEventsLocked(sensors_event_t* scratch, int numEventsDropped);
 
-        // Check if there are any wake up events in the buffer. If yes, increment the ref count.
-        // Increment it by exactly one unit for each packet sent on the socket. SOCK_SEQPACKET for
-        // the socket ensures that either the entire packet is read or dropped.
-        // Return 1 if mWakeLockRefCount has been incremented, zero if not.
-        int countWakeUpSensorEventsLocked(sensors_event_t* scratch, int count);
+        // Check if there are any wake up events in the buffer. If yes, return the index of the
+        // first wake_up sensor event in the buffer else return -1. This wake_up sensor event will
+        // have the flag WAKE_UP_SENSOR_EVENT_NEEDS_ACK set. Exactly one event per packet will have
+        // the wake_up flag set. SOCK_SEQPACKET ensures that either the entire packet is read or
+        // dropped.
+        int findWakeUpSensorEventLocked(sensors_event_t const* scratch, int count);
+
+        // Send pending flush_complete events. There may have been flush_complete_events that are
+        // dropped which need to be sent separately before other events. On older HALs (1_0) this
+        // method emulates the behavior of flush().
+        void sendPendingFlushEventsLocked();
 
         // Writes events from mEventCache to the socket.
         void writeToSocketFromCacheLocked();
@@ -103,6 +108,10 @@
         // shared amongst wake-up sensors and non-wake up sensors.
         int computeMaxCacheSizeLocked() const;
 
+        // When more sensors register, the maximum cache size desired may change. Compute max cache
+        // size, reallocate memory and copy over events from the older cache.
+        void reAllocateCacheLocked(sensors_event_t const* scratch, int count);
+
         // LooperCallback method. If there is data to read on this fd, it is an ack from the
         // app that it has read events from a wake up sensor, decrement mWakeLockRefCount.
         // If this fd is available for writing send the data from the cache.
@@ -124,11 +133,7 @@
             // Every activate is preceded by a flush. Only after the first flush complete is
             // received, the events for the sensor are sent on that *connection*.
             bool mFirstFlushPending;
-            // Number of time flush() was called on this connection. This is incremented every time
-            // flush() is called and decremented when flush_complete_event is received.
-            int mNumFlushCalls;
-            FlushInfo() : mPendingFlushEventsToSend(0), mFirstFlushPending(false),
-                                            mNumFlushCalls(0) {}
+            FlushInfo() : mPendingFlushEventsToSend(0), mFirstFlushPending(false) {}
         };
         // protected by SensorService::mLock. Key for this vector is the sensor handle.
         KeyedVector<int, FlushInfo> mSensorInfo;
@@ -157,11 +162,18 @@
 
     class SensorRecord {
         SortedVector< wp<SensorEventConnection> > mConnections;
+        // A queue of all flush() calls made on this sensor. Flush complete events will be
+        // sent in this order.
+        Vector< wp<SensorEventConnection> > mPendingFlushConnections;
     public:
         SensorRecord(const sp<SensorEventConnection>& connection);
         bool addConnection(const sp<SensorEventConnection>& connection);
         bool removeConnection(const wp<SensorEventConnection>& connection);
         size_t getNumConnections() const { return mConnections.size(); }
+
+        void addPendingFlushConnection(const sp<SensorEventConnection>& connection);
+        void removeFirstPendingFlushConnection();
+        SensorEventConnection * getFirstPendingFlushConnection();
     };
 
     class SensorEventAckReceiver : public Thread {
@@ -194,6 +206,8 @@
     void checkWakeLockStateLocked();
     bool isWakeUpSensorEvent(const sensors_event_t& event) const;
 
+    SensorRecord * getSensorRecord(int handle);
+
     sp<Looper> getLooper() const;
 
     // constants
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 2213259..bf42b77 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -59,7 +59,8 @@
         const sp<DisplaySurface>& displaySurface,
         const sp<IGraphicBufferProducer>& producer,
         EGLConfig config)
-    : mFlinger(flinger),
+    : lastCompositionHadVisibleLayers(false),
+      mFlinger(flinger),
       mType(type), mHwcDisplayId(hwcId),
       mDisplayToken(displayToken),
       mDisplaySurface(displaySurface),
@@ -401,6 +402,11 @@
 void DisplayDevice::setDisplaySize(const int newWidth, const int newHeight) {
     dirtyRegion.set(getBounds());
 
+    if (mSurface != EGL_NO_SURFACE) {
+        eglDestroySurface(mDisplay, mSurface);
+        mSurface = EGL_NO_SURFACE;
+    }
+
     mDisplaySurface->resizeBuffers(newWidth, newHeight);
 
     ANativeWindow* const window = mNativeWindow.get();
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 00e0918..d3f784a 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -53,6 +53,7 @@
     mutable Region swapRegion;
     // region in screen space
     Region undefinedRegion;
+    bool lastCompositionHadVisibleLayers;
 
     enum DisplayType {
         DISPLAY_ID_INVALID = -1,
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 53409d1..bd07d24 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -799,6 +799,9 @@
     dd.lastRetireFence = Fence::NO_FENCE;
     dd.lastDisplayFence = Fence::NO_FENCE;
     dd.outbufAcquireFence = Fence::NO_FENCE;
+    // clear all the previous configs and repopulate when a new
+    // device is added
+    dd.configs.clear();
 }
 
 int HWComposer::getVisualID() const {
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 716d24e..a36ddd9 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -323,25 +323,56 @@
         // which means using the inverse of the current transform set on the
         // SurfaceFlingerConsumer.
         uint32_t invTransform = mCurrentTransform;
+        if (mSurfaceFlingerConsumer->getTransformToDisplayInverse()) {
+            /*
+             * the code below applies the display's inverse transform to the buffer
+             */
+            uint32_t invTransformOrient = hw->getOrientationTransform();
+            // calculate the inverse transform
+            if (invTransformOrient & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+                invTransformOrient ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
+                        NATIVE_WINDOW_TRANSFORM_FLIP_H;
+                // If the transform has been rotated the axis of flip has been swapped
+                // so we need to swap which flip operations we are performing
+                bool is_h_flipped = (invTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) != 0;
+                bool is_v_flipped = (invTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) != 0;
+                if (is_h_flipped != is_v_flipped) {
+                    invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
+                            NATIVE_WINDOW_TRANSFORM_FLIP_H;
+                }
+            }
+            // and apply to the current transform
+            invTransform = (Transform(invTransform) * Transform(invTransformOrient)).getOrientation();
+        }
+
         int winWidth = s.active.w;
         int winHeight = s.active.h;
         if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
-            invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
-                    NATIVE_WINDOW_TRANSFORM_FLIP_H;
+            // If the activeCrop has been rotate the ends are rotated but not
+            // the space itself so when transforming ends back we can't rely on
+            // a modification of the axes of rotation. To account for this we
+            // need to reorient the inverse rotation in terms of the current
+            // axes of rotation.
+            bool is_h_flipped = (invTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) != 0;
+            bool is_v_flipped = (invTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) != 0;
+            if (is_h_flipped == is_v_flipped) {
+                invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
+                        NATIVE_WINDOW_TRANSFORM_FLIP_H;
+            }
             winWidth = s.active.h;
             winHeight = s.active.w;
         }
         const Rect winCrop = activeCrop.transform(
-                invTransform, winWidth, winHeight);
+                invTransform, s.active.w, s.active.h);
 
         // below, crop is intersected with winCrop expressed in crop's coordinate space
         float xScale = crop.getWidth()  / float(winWidth);
         float yScale = crop.getHeight() / float(winHeight);
 
-        float insetL = winCrop.left                  * xScale;
-        float insetT = winCrop.top                   * yScale;
-        float insetR = (s.active.w - winCrop.right ) * xScale;
-        float insetB = (s.active.h - winCrop.bottom) * yScale;
+        float insetL = winCrop.left                 * xScale;
+        float insetT = winCrop.top                  * yScale;
+        float insetR = (winWidth - winCrop.right )  * xScale;
+        float insetB = (winHeight - winCrop.bottom) * yScale;
 
         crop.left   += insetL;
         crop.top    += insetT;
@@ -397,13 +428,22 @@
          * the code below applies the display's inverse transform to the buffer
          */
         uint32_t invTransform = hw->getOrientationTransform();
+        uint32_t t_orientation = transform.getOrientation();
         // calculate the inverse transform
         if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
             invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
                     NATIVE_WINDOW_TRANSFORM_FLIP_H;
+            // If the transform has been rotated the axis of flip has been swapped
+            // so we need to swap which flip operations we are performing
+            bool is_h_flipped = (t_orientation & NATIVE_WINDOW_TRANSFORM_FLIP_H) != 0;
+            bool is_v_flipped = (t_orientation & NATIVE_WINDOW_TRANSFORM_FLIP_V) != 0;
+            if (is_h_flipped != is_v_flipped) {
+                t_orientation ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
+                        NATIVE_WINDOW_TRANSFORM_FLIP_H;
+            }
         }
         // and apply to the current transform
-        transform = transform * Transform(invTransform);
+        transform = Transform(t_orientation) * Transform(invTransform);
     }
 
     // this gives us only the "orientation" component of the transform
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index bbe2aa1..4070f03 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -987,9 +987,32 @@
 
 void SurfaceFlinger::setUpHWComposer() {
     for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
-        bool mustRecompose =
-                !(mDisplays[dpy]->getDirtyRegion(false).isEmpty());
+        bool dirty = !mDisplays[dpy]->getDirtyRegion(false).isEmpty();
+        bool empty = mDisplays[dpy]->getVisibleLayersSortedByZ().size() == 0;
+        bool wasEmpty = !mDisplays[dpy]->lastCompositionHadVisibleLayers;
+
+        // If nothing has changed (!dirty), don't recompose.
+        // If something changed, but we don't currently have any visible layers,
+        //   and didn't when we last did a composition, then skip it this time.
+        // The second rule does two things:
+        // - When all layers are removed from a display, we'll emit one black
+        //   frame, then nothing more until we get new layers.
+        // - When a display is created with a private layer stack, we won't
+        //   emit any black frames until a layer is added to the layer stack.
+        bool mustRecompose = dirty && !(empty && wasEmpty);
+
+        ALOGV_IF(mDisplays[dpy]->getDisplayType() == DisplayDevice::DISPLAY_VIRTUAL,
+                "dpy[%zu]: %s composition (%sdirty %sempty %swasEmpty)", dpy,
+                mustRecompose ? "doing" : "skipping",
+                dirty ? "+" : "-",
+                empty ? "+" : "-",
+                wasEmpty ? "+" : "-");
+
         mDisplays[dpy]->beginFrame(mustRecompose);
+
+        if (mustRecompose) {
+            mDisplays[dpy]->lastCompositionHadVisibleLayers = !empty;
+        }
     }
 
     HWComposer& hwc(getHwComposer());
@@ -3111,6 +3134,7 @@
              */
             result = native_window_dequeue_buffer_and_wait(window,  &buffer);
             if (result == NO_ERROR) {
+                int syncFd = -1;
                 // create an EGLImage from the buffer so we can later
                 // turn it into a texture
                 EGLImageKHR image = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT,
@@ -3127,27 +3151,41 @@
                         renderScreenImplLocked(hw, sourceCrop, reqWidth, reqHeight,
                                 minLayerZ, maxLayerZ, true, useIdentityTransform);
 
-                        // Create a sync point and wait on it, so we know the buffer is
-                        // ready before we pass it along.  We can't trivially call glFlush(),
-                        // so we use a wait flag instead.
-                        // TODO: pass a sync fd to queueBuffer() and let the consumer wait.
-                        EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, NULL);
-                        if (sync != EGL_NO_SYNC_KHR) {
-                            EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync,
-                                    EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, 2000000000 /*2 sec*/);
-                            EGLint eglErr = eglGetError();
-                            eglDestroySyncKHR(mEGLDisplay, sync);
-                            if (result == EGL_TIMEOUT_EXPIRED_KHR) {
-                                ALOGW("captureScreen: fence wait timed out");
-                            } else {
-                                ALOGW_IF(eglErr != EGL_SUCCESS,
-                                        "captureScreen: error waiting on EGL fence: %#x", eglErr);
-                            }
+                        // Attempt to create a sync khr object that can produce a sync point. If that
+                        // isn't available, create a non-dupable sync object in the fallback path and
+                        // wait on it directly.
+                        EGLSyncKHR sync;
+                        if (!DEBUG_SCREENSHOTS) {
+                           sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
                         } else {
-                            ALOGW("captureScreen: error creating EGL fence: %#x", eglGetError());
-                            // not fatal
+                            sync = EGL_NO_SYNC_KHR;
                         }
-
+                        if (sync != EGL_NO_SYNC_KHR) {
+                            // get the sync fd
+                            syncFd = eglDupNativeFenceFDANDROID(mEGLDisplay, sync);
+                            if (syncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
+                                ALOGW("captureScreen: failed to dup sync khr object");
+                                syncFd = -1;
+                            }
+                            eglDestroySyncKHR(mEGLDisplay, sync);
+                        } else {
+                            // fallback path
+                            sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, NULL);
+                            if (sync != EGL_NO_SYNC_KHR) {
+                                EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync,
+                                    EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, 2000000000 /*2 sec*/);
+                                EGLint eglErr = eglGetError();
+                                if (result == EGL_TIMEOUT_EXPIRED_KHR) {
+                                    ALOGW("captureScreen: fence wait timed out");
+                                } else {
+                                    ALOGW_IF(eglErr != EGL_SUCCESS,
+                                            "captureScreen: error waiting on EGL fence: %#x", eglErr);
+                                }
+                                eglDestroySyncKHR(mEGLDisplay, sync);
+                            } else {
+                                ALOGW("captureScreen: error creating EGL fence: %#x", eglGetError());
+                            }
+                        }
                         if (DEBUG_SCREENSHOTS) {
                             uint32_t* pixels = new uint32_t[reqWidth*reqHeight];
                             getRenderEngine().readPixels(0, 0, reqWidth, reqHeight, pixels);
@@ -3165,7 +3203,10 @@
                 } else {
                     result = BAD_VALUE;
                 }
-                window->queueBuffer(window, buffer, -1);
+                window->queueBuffer(window, buffer, syncFd);
+                if (syncFd != -1) {
+                    close(syncFd);
+                }
             }
         } else {
             result = BAD_VALUE;