merge in klp-release history after reset to klp-dev
diff --git a/data/etc/handheld_core_hardware.xml b/data/etc/handheld_core_hardware.xml
index 290afc2..4a9f2dd 100644
--- a/data/etc/handheld_core_hardware.xml
+++ b/data/etc/handheld_core_hardware.xml
@@ -36,6 +36,8 @@
     <feature name="android.software.app_widgets" />
     <feature name="android.software.home_screen" />
     <feature name="android.software.input_methods" />
+    <!-- Feature to specify if the device supports adding device admins. -->
+    <feature name="android.software.device_admin" />
     <!-- devices with GPS must include android.hardware.location.gps.xml -->
     <!-- devices with an autofocus camera and/or flash must include either
          android.hardware.camera.autofocus.xml or 
diff --git a/data/etc/tablet_core_hardware.xml b/data/etc/tablet_core_hardware.xml
index 207fc9a..78b9736 100644
--- a/data/etc/tablet_core_hardware.xml
+++ b/data/etc/tablet_core_hardware.xml
@@ -37,6 +37,8 @@
     <feature name="android.software.app_widgets" />
     <feature name="android.software.home_screen" />
     <feature name="android.software.input_methods" />
+    <!-- Feature to specify if the device supports adding device admins. -->
+    <feature name="android.software.device_admin" />
     <!-- devices with GPS must include android.hardware.location.gps.xml -->
     <!-- devices with a rear-facing camera must include one of these as appropriate:
          android.hardware.camera.xml or 
diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h
index 7e404fe..408956b 100644
--- a/include/gui/BufferQueue.h
+++ b/include/gui/BufferQueue.h
@@ -20,6 +20,8 @@
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 
+#include <binder/IBinder.h>
+
 #include <gui/IConsumerListener.h>
 #include <gui/IGraphicBufferAlloc.h>
 #include <gui/IGraphicBufferProducer.h>
@@ -35,7 +37,9 @@
 namespace android {
 // ----------------------------------------------------------------------------
 
-class BufferQueue : public BnGraphicBufferProducer, public BnGraphicBufferConsumer {
+class BufferQueue : public BnGraphicBufferProducer,
+                    public BnGraphicBufferConsumer,
+                    private IBinder::DeathRecipient {
 public:
     enum { MIN_UNDEQUEUED_BUFFERS = 2 };
     enum { NUM_BUFFER_SLOTS = 32 };
@@ -79,6 +83,12 @@
     virtual ~BufferQueue();
 
     /*
+     * IBinder::DeathRecipient interface
+     */
+
+    virtual void binderDied(const wp<IBinder>& who);
+
+    /*
      * IGraphicBufferProducer interface
      */
 
@@ -184,7 +194,8 @@
     // it's still connected to a producer).
     //
     // APIs are enumerated in window.h (e.g. NATIVE_WINDOW_API_CPU).
-    virtual status_t connect(int api, bool producerControlledByApp, QueueBufferOutput* output);
+    virtual status_t connect(const sp<IBinder>& token,
+            int api, bool producerControlledByApp, QueueBufferOutput* output);
 
     // disconnect attempts to disconnect a producer API from the BufferQueue.
     // Calling this method will cause any subsequent calls to other
@@ -552,6 +563,9 @@
 
     // mTransformHint is used to optimize for screen rotations
     uint32_t mTransformHint;
+
+    // mConnectedProducerToken is used to set a binder death notification on the producer
+    sp<IBinder> mConnectedProducerToken;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h
index c3ede5e..342ba08 100644
--- a/include/gui/IGraphicBufferProducer.h
+++ b/include/gui/IGraphicBufferProducer.h
@@ -189,8 +189,11 @@
     //
     // outWidth, outHeight and outTransform are filled with the default width
     // and height of the window and current transform applied to buffers,
-    // respectively.
-    virtual status_t connect(int api, bool producerControlledByApp, QueueBufferOutput* output) = 0;
+    // respectively. The token needs to be any binder object that lives in the
+    // producer process -- it is solely used for obtaining a death notification
+    // when the producer is killed.
+    virtual status_t connect(const sp<IBinder>& token,
+            int api, bool producerControlledByApp, QueueBufferOutput* output) = 0;
 
     // disconnect attempts to disconnect a client API from the
     // IGraphicBufferProducer.  Calling this method will cause any subsequent
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index 57a41f2..50e3079 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -635,7 +635,9 @@
     mDequeueCondition.broadcast();
 }
 
-status_t BufferQueue::connect(int api, bool producerControlledByApp, QueueBufferOutput* output) {
+
+status_t BufferQueue::connect(const sp<IBinder>& token,
+        int api, bool producerControlledByApp, QueueBufferOutput* output) {
     ATRACE_CALL();
     ST_LOGV("connect: api=%d producerControlledByApp=%s", api,
             producerControlledByApp ? "true" : "false");
@@ -663,8 +665,14 @@
                 err = -EINVAL;
             } else {
                 mConnectedApi = api;
-                output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint,
-                        mQueue.size());
+                output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint, mQueue.size());
+
+                // set-up a death notification so that we can disconnect automatically
+                // when/if the remote producer dies.
+                // This will fail with INVALID_OPERATION if the "token" is local to our process.
+                if (token->linkToDeath(static_cast<IBinder::DeathRecipient*>(this)) == NO_ERROR) {
+                    mConnectedProducerToken = token;
+                }
             }
             break;
         default:
@@ -678,6 +686,16 @@
     return err;
 }
 
+void BufferQueue::binderDied(const wp<IBinder>& who) {
+    // If we're here, it means that a producer we were connected to died.
+    // We're GUARANTEED that we still are connected to it because it has no other way
+    // to get disconnected -- or -- we wouldn't be here because we're removing this
+    // callback upon disconnect. Therefore, it's okay to read mConnectedApi without
+    // synchronization here.
+    int api = mConnectedApi;
+    this->disconnect(api);
+}
+
 status_t BufferQueue::disconnect(int api) {
     ATRACE_CALL();
     ST_LOGV("disconnect: api=%d", api);
@@ -701,6 +719,14 @@
             case NATIVE_WINDOW_API_CAMERA:
                 if (mConnectedApi == api) {
                     freeAllBuffersLocked();
+                    // remove our death notification callback if we have one
+                    sp<IBinder> token = mConnectedProducerToken;
+                    if (token != NULL) {
+                        // this can fail if we're here because of the death notification
+                        // either way, we just ignore.
+                        token->unlinkToDeath(static_cast<IBinder::DeathRecipient*>(this));
+                    }
+                    mConnectedProducerToken = NULL;
                     mConnectedApi = NO_CONNECTED_API;
                     mDequeueCondition.broadcast();
                     listener = mConsumerListener;
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 3080220..fc86e60 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -41,7 +41,6 @@
     DISCONNECT,
 };
 
-
 class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
 {
 public:
@@ -139,9 +138,11 @@
         return result;
     }
 
-    virtual status_t connect(int api, bool producerControlledByApp, QueueBufferOutput* output) {
+    virtual status_t connect(const sp<IBinder>& token,
+            int api, bool producerControlledByApp, QueueBufferOutput* output) {
         Parcel data, reply;
         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
+        data.writeStrongBinder(token);
         data.writeInt32(api);
         data.writeInt32(producerControlledByApp);
         status_t result = remote()->transact(CONNECT, data, &reply);
@@ -241,12 +242,13 @@
         } break;
         case CONNECT: {
             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
+            sp<IBinder> token = data.readStrongBinder();
             int api = data.readInt32();
             bool producerControlledByApp = data.readInt32();
             QueueBufferOutput* const output =
                     reinterpret_cast<QueueBufferOutput *>(
                             reply->writeInplace(sizeof(QueueBufferOutput)));
-            status_t res = connect(api, producerControlledByApp, output);
+            status_t res = connect(token, api, producerControlledByApp, output);
             reply->writeInt32(res);
             return NO_ERROR;
         } break;
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 1bae0fe..27dbc4e 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -490,9 +490,10 @@
 int Surface::connect(int api) {
     ATRACE_CALL();
     ALOGV("Surface::connect");
+    static sp<BBinder> sLife = new BBinder();
     Mutex::Autolock lock(mMutex);
     IGraphicBufferProducer::QueueBufferOutput output;
-    int err = mGraphicBufferProducer->connect(api, mProducerControlledByApp, &output);
+    int err = mGraphicBufferProducer->connect(sLife, api, mProducerControlledByApp, &output);
     if (err == NO_ERROR) {
         uint32_t numPendingBuffers = 0;
         output.deflate(&mDefaultWidth, &mDefaultHeight, &mTransformHint,
@@ -505,6 +506,7 @@
     return err;
 }
 
+
 int Surface::disconnect(int api) {
     ATRACE_CALL();
     ALOGV("Surface::disconnect");
diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp
index f4e88f5..16e533c 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -46,13 +46,13 @@
 // ============================================================================
 
 SurfaceControl::SurfaceControl(
-        const sp<SurfaceComposerClient>& client, 
+        const sp<SurfaceComposerClient>& client,
         const sp<IBinder>& handle,
         const sp<IGraphicBufferProducer>& gbp)
     : mClient(client), mHandle(handle), mGraphicBufferProducer(gbp)
 {
 }
-        
+
 SurfaceControl::~SurfaceControl()
 {
     destroy();
@@ -71,7 +71,7 @@
     IPCThreadState::self()->flushCommands();
 }
 
-void SurfaceControl::clear() 
+void SurfaceControl::clear()
 {
     // here, the window manager tells us explicitly that we should destroy
     // the surface's resource. Soon after this call, it will also release
@@ -83,7 +83,7 @@
 }
 
 bool SurfaceControl::isSameSurface(
-        const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs) 
+        const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs)
 {
     if (lhs == 0 || rhs == 0)
         return false;
@@ -181,7 +181,9 @@
 {
     Mutex::Autolock _l(mLock);
     if (mSurfaceData == 0) {
-        mSurfaceData = new Surface(mGraphicBufferProducer);
+        // This surface is always consumed by SurfaceFlinger, so the
+        // producerControlledByApp value doesn't matter; using false.
+        mSurfaceData = new Surface(mGraphicBufferProducer, false);
     }
     return mSurfaceData;
 }
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 47b1a9e..03c1a29 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -64,7 +64,7 @@
     sp<DummyConsumer> dc(new DummyConsumer);
     mBQ->consumerConnect(dc, false);
     IGraphicBufferProducer::QueueBufferOutput qbo;
-    mBQ->connect(NATIVE_WINDOW_API_CPU, false, &qbo);
+    mBQ->connect(NULL, NATIVE_WINDOW_API_CPU, false, &qbo);
     mBQ->setBufferCount(4);
 
     int slot;
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index d3bc14a..04d5f45 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -49,6 +49,10 @@
 
 using namespace android;
 
+// This extension has not been ratified yet, so can't be shipped.
+// Implementation is incomplete and untested.
+#define ENABLE_EGL_KHR_GL_COLORSPACE 0
+
 // ----------------------------------------------------------------------------
 
 namespace android {
@@ -82,7 +86,9 @@
         "EGL_KHR_image_base "                   // mandatory
         "EGL_KHR_image_pixmap "
         "EGL_KHR_lock_surface "
+#if (ENABLE_EGL_KHR_GL_COLORSPACE != 0)
         "EGL_KHR_gl_colorspace "
+#endif
         "EGL_KHR_gl_texture_2D_image "
         "EGL_KHR_gl_texture_cubemap_image "
         "EGL_KHR_gl_renderbuffer_image "
@@ -366,7 +372,7 @@
 // surfaces
 // ----------------------------------------------------------------------------
 
-// The EGL_KHR_gl_colorspace spec hasn't been published yet, so these haven't
+// The EGL_KHR_gl_colorspace spec hasn't been ratified yet, so these haven't
 // been added to the Khronos egl.h.
 #define EGL_GL_COLORSPACE_KHR           EGL_VG_COLORSPACE
 #define EGL_GL_COLORSPACE_SRGB_KHR      EGL_VG_COLORSPACE_sRGB
@@ -427,7 +433,17 @@
                     attr += 2) {
                 if (*attr == EGL_GL_COLORSPACE_KHR &&
                         dp->haveExtension("EGL_KHR_gl_colorspace")) {
-                    format = modifyFormatColorspace(format, *(attr+1));
+                    if (ENABLE_EGL_KHR_GL_COLORSPACE) {
+                        format = modifyFormatColorspace(format, *(attr+1));
+                    } else {
+                        // Normally we'd pass through unhandled attributes to
+                        // the driver. But in case the driver implements this
+                        // extension but we're disabling it, we want to prevent
+                        // it getting through -- support will be broken without
+                        // our help.
+                        ALOGE("sRGB window surfaces not supported");
+                        return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+                    }
                 }
             }
         }
@@ -458,7 +474,17 @@
         if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
             for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
                 if (*attr == EGL_GL_COLORSPACE_KHR) {
-                    format = modifyFormatColorspace(format, attr[1]);
+                    if (ENABLE_EGL_KHR_GL_COLORSPACE) {
+                        format = modifyFormatColorspace(format, *(attr+1));
+                    } else {
+                        // Normally we'd pass through unhandled attributes to
+                        // the driver. But in case the driver implements this
+                        // extension but we're disabling it, we want to prevent
+                        // it getting through -- support will be broken without
+                        // our help.
+                        ALOGE("sRGB window surfaces not supported");
+                        return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+                    }
                 }
             }
         }
diff --git a/services/sensorservice/CorrectedGyroSensor.cpp b/services/sensorservice/CorrectedGyroSensor.cpp
index 09f60a9..31487a7 100644
--- a/services/sensorservice/CorrectedGyroSensor.cpp
+++ b/services/sensorservice/CorrectedGyroSensor.cpp
@@ -57,13 +57,13 @@
 }
 
 status_t CorrectedGyroSensor::activate(void* ident, bool enabled) {
-    mSensorDevice.activate(this, mGyro.getHandle(), enabled);
-    return mSensorFusion.activate(this, enabled);
+    mSensorDevice.activate(ident, mGyro.getHandle(), enabled);
+    return mSensorFusion.activate(ident, enabled);
 }
 
 status_t CorrectedGyroSensor::setDelay(void* ident, int handle, int64_t ns) {
-    mSensorDevice.setDelay(this, mGyro.getHandle(), ns);
-    return mSensorFusion.setDelay(this, ns);
+    mSensorDevice.setDelay(ident, mGyro.getHandle(), ns);
+    return mSensorFusion.setDelay(ident, ns);
 }
 
 Sensor CorrectedGyroSensor::getSensor() const {
diff --git a/services/sensorservice/GravitySensor.cpp b/services/sensorservice/GravitySensor.cpp
index 0bf20db..dd1f650 100644
--- a/services/sensorservice/GravitySensor.cpp
+++ b/services/sensorservice/GravitySensor.cpp
@@ -67,11 +67,11 @@
 }
 
 status_t GravitySensor::activate(void* ident, bool enabled) {
-    return mSensorFusion.activate(this, enabled);
+    return mSensorFusion.activate(ident, enabled);
 }
 
 status_t GravitySensor::setDelay(void* ident, int handle, int64_t ns) {
-    return mSensorFusion.setDelay(this, ns);
+    return mSensorFusion.setDelay(ident, ns);
 }
 
 Sensor GravitySensor::getSensor() const {
diff --git a/services/sensorservice/LinearAccelerationSensor.cpp b/services/sensorservice/LinearAccelerationSensor.cpp
index 25ae473..d5f20d2 100644
--- a/services/sensorservice/LinearAccelerationSensor.cpp
+++ b/services/sensorservice/LinearAccelerationSensor.cpp
@@ -51,11 +51,11 @@
 }
 
 status_t LinearAccelerationSensor::activate(void* ident, bool enabled) {
-    return mGravitySensor.activate(this, enabled);
+    return mGravitySensor.activate(ident, enabled);
 }
 
 status_t LinearAccelerationSensor::setDelay(void* ident, int handle, int64_t ns) {
-    return mGravitySensor.setDelay(this, handle, ns);
+    return mGravitySensor.setDelay(ident, handle, ns);
 }
 
 Sensor LinearAccelerationSensor::getSensor() const {
diff --git a/services/sensorservice/OrientationSensor.cpp b/services/sensorservice/OrientationSensor.cpp
index b146332..10b391c 100644
--- a/services/sensorservice/OrientationSensor.cpp
+++ b/services/sensorservice/OrientationSensor.cpp
@@ -66,11 +66,11 @@
 }
 
 status_t OrientationSensor::activate(void* ident, bool enabled) {
-    return mSensorFusion.activate(this, enabled);
+    return mSensorFusion.activate(ident, enabled);
 }
 
 status_t OrientationSensor::setDelay(void* ident, int handle, int64_t ns) {
-    return mSensorFusion.setDelay(this, ns);
+    return mSensorFusion.setDelay(ident, ns);
 }
 
 Sensor OrientationSensor::getSensor() const {
diff --git a/services/sensorservice/RotationVectorSensor.cpp b/services/sensorservice/RotationVectorSensor.cpp
index 725deb4..a2157b4 100644
--- a/services/sensorservice/RotationVectorSensor.cpp
+++ b/services/sensorservice/RotationVectorSensor.cpp
@@ -53,11 +53,11 @@
 }
 
 status_t RotationVectorSensor::activate(void* ident, bool enabled) {
-    return mSensorFusion.activate(this, enabled);
+    return mSensorFusion.activate(ident, enabled);
 }
 
 status_t RotationVectorSensor::setDelay(void* ident, int handle, int64_t ns) {
-    return mSensorFusion.setDelay(this, ns);
+    return mSensorFusion.setDelay(ident, ns);
 }
 
 Sensor RotationVectorSensor::getSensor() const {
@@ -102,11 +102,11 @@
 }
 
 status_t GyroDriftSensor::activate(void* ident, bool enabled) {
-    return mSensorFusion.activate(this, enabled);
+    return mSensorFusion.activate(ident, enabled);
 }
 
 status_t GyroDriftSensor::setDelay(void* ident, int handle, int64_t ns) {
-    return mSensorFusion.setDelay(this, ns);
+    return mSensorFusion.setDelay(ident, ns);
 }
 
 Sensor GyroDriftSensor::getSensor() const {
diff --git a/services/sensorservice/SensorFusion.cpp b/services/sensorservice/SensorFusion.cpp
index 27967dc..03f94be 100644
--- a/services/sensorservice/SensorFusion.cpp
+++ b/services/sensorservice/SensorFusion.cpp
@@ -103,7 +103,7 @@
     }
 
     if (enabled) {
-        ALOGD("SensorFusion calling batch ident=%p ", ident);
+        ALOGD_IF(DEBUG_CONNECTIONS, "SensorFusion calling batch ident=%p ", ident);
         // Activating a sensor in continuous mode is equivalent to calling batch with the default
         // period and timeout equal to ZERO, followed by a call to activate.
         mSensorDevice.batch(ident, mAcc.getHandle(), 0, DEFAULT_EVENTS_PERIOD, 0);
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index cb99531..b26e572 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -148,6 +148,21 @@
             // debugging sensor list
             mUserSensorListDebug = mSensorList;
 
+            mSocketBufferSize = SOCKET_BUFFER_SIZE_NON_BATCHED;
+            FILE *fp = fopen("/proc/sys/net/core/wmem_max", "r");
+            char line[128];
+            if (fp != NULL && fgets(line, sizeof(line), fp) != NULL) {
+                line[sizeof(line) - 1] = '\0';
+                sscanf(line, "%u", &mSocketBufferSize);
+                if (mSocketBufferSize > MAX_SOCKET_BUFFER_SIZE_BATCHED) {
+                    mSocketBufferSize = MAX_SOCKET_BUFFER_SIZE_BATCHED;
+                }
+            }
+            ALOGD("Max socket buffer size %u", mSocketBufferSize);
+            if (fp) {
+                fclose(fp);
+            }
+
             run("SensorService", PRIORITY_URGENT_DISPLAY);
             mInitCheck = NO_ERROR;
         }
@@ -255,7 +270,6 @@
         SensorFusion::getInstance().dump(result);
         SensorDevice::getInstance().dump(result);
 
-        result.appendFormat("%d active connections\n", mActiveConnections.size());
         result.append("Active sensors:\n");
         for (size_t i=0 ; i<mActiveSensors.size() ; i++) {
             int handle = mActiveSensors.keyAt(i);
@@ -264,6 +278,17 @@
                     handle,
                     mActiveSensors.valueAt(i)->getNumConnections());
         }
+
+        result.appendFormat("%u Max Socket Buffer size\n", mSocketBufferSize);
+        result.appendFormat("%d active connections\n", mActiveConnections.size());
+
+        for (size_t i=0 ; i < mActiveConnections.size() ; i++) {
+            sp<SensorEventConnection> connection(mActiveConnections[i].promote());
+            if (connection != 0) {
+                result.appendFormat("Connection Number: %d \n", i);
+                connection->dump(result);
+            }
+        }
     }
     write(fd, result.string(), result.size());
     return NO_ERROR;
@@ -404,7 +429,6 @@
         sensors_event_t const * buffer, size_t count)
 {
     Mutex::Autolock _l(mLock);
-
     // record the last event for each sensor
     int32_t prev = buffer[0].sensor;
     for (size_t i=1 ; i<count ; i++) {
@@ -565,6 +589,15 @@
 
     status_t err = sensor->batch(connection.get(), handle, reservedFlags, samplingPeriodNs,
                                  maxBatchReportLatencyNs);
+    if (err == NO_ERROR) {
+        connection->setFirstFlushPending(handle, true);
+        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 == NO_ERROR) {
         ALOGD_IF(DEBUG_CONNECTIONS, "Calling activate on %d", handle);
@@ -649,6 +682,21 @@
    if (sensor == NULL) {
        return BAD_VALUE;
   }
+  SensorDevice& dev(SensorDevice::getInstance());
+
+  if (dev.getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_1) {
+      // For older devices increment pending flush count, which will send a trivial flush complete
+      // event for all the connections which are registered for updates on this sensor.
+      const SortedVector< wp<SensorEventConnection> > activeConnections(
+                                      getActiveConnections());
+      for (size_t i=0 ; i<activeConnections.size() ; i++) {
+          sp<SensorEventConnection> connection(activeConnections[i].promote());
+          if (connection != 0) {
+              connection->incrementPendingFlushCount(handle);
+          }
+      }
+      return NO_ERROR;
+  }
   return sensor->flush(connection.get(), handle);
 }
 // ---------------------------------------------------------------------------
@@ -683,8 +731,15 @@
 
 SensorService::SensorEventConnection::SensorEventConnection(
         const sp<SensorService>& service, uid_t uid)
-    : mService(service), mChannel(new BitTube()), mUid(uid)
+    : mService(service), mUid(uid)
 {
+    const SensorDevice& device(SensorDevice::getInstance());
+    if (device.getHalDeviceVersion() >= SENSORS_DEVICE_API_VERSION_1_1) {
+        // Increase socket buffer size to 1MB for batching capabilities.
+        mChannel = new BitTube(service->mSocketBufferSize);
+    } else {
+        mChannel = new BitTube(SOCKET_BUFFER_SIZE_NON_BATCHED);
+    }
 }
 
 SensorService::SensorEventConnection::~SensorEventConnection()
@@ -697,10 +752,22 @@
 {
 }
 
+void SensorService::SensorEventConnection::dump(String8& result) {
+    Mutex::Autolock _l(mConnectionLock);
+    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\n",
+                            mService->getSensorName(mSensorInfo.keyAt(i)).string(),
+                            flushInfo.mFirstFlushPending ? "First flush pending" :
+                                                           "active",
+                            flushInfo.mPendingFlushEventsToSend);
+    }
+}
+
 bool SensorService::SensorEventConnection::addSensor(int32_t handle) {
     Mutex::Autolock _l(mConnectionLock);
-    if (mSensorInfo.indexOf(handle) < 0) {
-        mSensorInfo.add(handle);
+    if (mSensorInfo.indexOfKey(handle) < 0) {
+        mSensorInfo.add(handle, FlushInfo());
         return true;
     }
     return false;
@@ -708,7 +775,7 @@
 
 bool SensorService::SensorEventConnection::removeSensor(int32_t handle) {
     Mutex::Autolock _l(mConnectionLock);
-    if (mSensorInfo.remove(handle) >= 0) {
+    if (mSensorInfo.removeItem(handle) >= 0) {
         return true;
     }
     return false;
@@ -716,7 +783,7 @@
 
 bool SensorService::SensorEventConnection::hasSensor(int32_t handle) const {
     Mutex::Autolock _l(mConnectionLock);
-    return mSensorInfo.indexOf(handle) >= 0;
+    return mSensorInfo.indexOfKey(handle) >= 0;
 }
 
 bool SensorService::SensorEventConnection::hasAnySensor() const {
@@ -724,12 +791,32 @@
     return mSensorInfo.size() ? true : false;
 }
 
+void SensorService::SensorEventConnection::setFirstFlushPending(int32_t handle,
+                                bool value) {
+    Mutex::Autolock _l(mConnectionLock);
+    ssize_t index = mSensorInfo.indexOfKey(handle);
+    if (index >= 0) {
+        FlushInfo& flushInfo = mSensorInfo.editValueAt(index);
+        flushInfo.mFirstFlushPending = value;
+    }
+}
+
+void SensorService::SensorEventConnection::incrementPendingFlushCount(int32_t handle) {
+    Mutex::Autolock _l(mConnectionLock);
+    ssize_t index = mSensorInfo.indexOfKey(handle);
+    if (index >= 0) {
+        FlushInfo& flushInfo = mSensorInfo.editValueAt(index);
+        flushInfo.mPendingFlushEventsToSend++;
+    }
+}
+
 status_t SensorService::SensorEventConnection::sendEvents(
         sensors_event_t const* buffer, size_t numEvents,
         sensors_event_t* scratch)
 {
     // filter out events not for this connection
     size_t count = 0;
+
     if (scratch) {
         Mutex::Autolock _l(mConnectionLock);
         size_t i=0;
@@ -742,10 +829,18 @@
                 // filtered correctly. buffer[i].sensor is zero for meta_data events.
                 curr = buffer[i].meta_data.sensor;
             }
-            if (mSensorInfo.indexOf(curr) >= 0)  {
+            ssize_t index = mSensorInfo.indexOfKey(curr);
+            if (index >= 0 && mSensorInfo[index].mFirstFlushPending == true &&
+                buffer[i].type == SENSOR_TYPE_META_DATA) {
+                // 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);
+                mSensorInfo.editValueAt(index).mFirstFlushPending = false;
+            }
+            if (index >= 0 && mSensorInfo[index].mFirstFlushPending == false)  {
                 do {
-                    scratch[count] = buffer[i];
-                    ++count; ++i;
+                    scratch[count++] = buffer[i++];
                 } while ((i<numEvents) && ((buffer[i].sensor == curr) ||
                          (buffer[i].type == SENSOR_TYPE_META_DATA  &&
                           buffer[i].meta_data.sensor == curr)));
@@ -758,19 +853,62 @@
         count = numEvents;
     }
 
+    // Send pending flush events (if any) before sending events from the cache.
+    {
+        ASensorEvent flushCompleteEvent;
+        flushCompleteEvent.type = SENSOR_TYPE_META_DATA;
+        flushCompleteEvent.sensor = 0;
+        Mutex::Autolock _l(mConnectionLock);
+        // 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) {
+                    // ALOGW("dropping %d events on the floor", count);
+                    countFlushCompleteEvents(scratch, count);
+                    return size;
+                }
+                ALOGD_IF(DEBUG_CONNECTIONS, "sent dropped flush complete event==%d ",
+                         flushCompleteEvent.meta_data.sensor);
+                flushInfo.mPendingFlushEventsToSend--;
+            }
+        }
+    }
+
     // NOTE: ASensorEvent and sensors_event_t are the same type
     ssize_t size = SensorEventQueue::write(mChannel,
             reinterpret_cast<ASensorEvent const*>(scratch), count);
     if (size == -EAGAIN) {
         // the destination doesn't accept events anymore, it's probably
         // full. For now, we just drop the events on the floor.
-        //ALOGW("dropping %d events on the floor", count);
+        // ALOGW("dropping %d events on the floor", count);
+        countFlushCompleteEvents(scratch, count);
         return size;
     }
 
     return size < 0 ? status_t(size) : status_t(NO_ERROR);
 }
 
+void SensorService::SensorEventConnection::countFlushCompleteEvents(
+                sensors_event_t* scratch, const int numEventsDropped) {
+    ALOGD_IF(DEBUG_CONNECTIONS, "dropping %d events ", numEventsDropped);
+    Mutex::Autolock _l(mConnectionLock);
+    // Count flushComplete events in the events that are about to the dropped. These will be sent
+    // separately before the next batch of events.
+    for (int j = 0; j < numEventsDropped; ++j) {
+        if (scratch[j].type == SENSOR_TYPE_META_DATA) {
+            FlushInfo& flushInfo = mSensorInfo.editValueFor(scratch[j].meta_data.sensor);
+            flushInfo.mPendingFlushEventsToSend++;
+            ALOGD_IF(DEBUG_CONNECTIONS, "increment pendingFlushCount %d",
+                     flushInfo.mPendingFlushEventsToSend);
+        }
+    }
+    return;
+}
+
 sp<BitTube> SensorService::SensorEventConnection::getSensorChannel() const
 {
     return mChannel;
@@ -799,6 +937,7 @@
 status_t  SensorService::SensorEventConnection::flushSensor(int handle) {
     return mService->flushSensor(this, handle);
 }
+
 // ---------------------------------------------------------------------------
 }; // namespace android
 
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 6267dd1..2311bff 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -38,6 +38,9 @@
 // ---------------------------------------------------------------------------
 
 #define DEBUG_CONNECTIONS   false
+// Max size is 1 MB which is enough to accept a batch of about 10k events.
+#define MAX_SOCKET_BUFFER_SIZE_BATCHED 1024 * 1024
+#define SOCKET_BUFFER_SIZE_NON_BATCHED 4 * 1024
 
 struct sensors_poll_device_t;
 struct sensors_module_t;
@@ -77,14 +80,27 @@
                                        nsecs_t maxBatchReportLatencyNs, int reservedFlags);
         virtual status_t setEventRate(int handle, nsecs_t samplingPeriodNs);
         virtual status_t flushSensor(int handle);
+        // Count the number of flush complete events which are about to be dropped in the buffer.
+        // Increment mPendingFlushEventsToSend in mSensorInfo. These flush complete events will be
+        // sent separately before the next batch of events.
+        void countFlushCompleteEvents(sensors_event_t* scratch, int numEventsDropped);
 
         sp<SensorService> const mService;
-        sp<BitTube> const mChannel;
+        sp<BitTube> mChannel;
         uid_t mUid;
         mutable Mutex mConnectionLock;
 
-        // protected by SensorService::mLock
-        SortedVector<int> mSensorInfo;
+        struct FlushInfo {
+            // The number of flush complete events dropped for this sensor is stored here.
+            // They are sent separately before the next batch of events.
+            int mPendingFlushEventsToSend;
+            // 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;
+            FlushInfo() : mPendingFlushEventsToSend(0), mFirstFlushPending(false) {}
+        };
+        // protected by SensorService::mLock. Key for this vector is the sensor handle.
+        KeyedVector<int, FlushInfo> mSensorInfo;
 
     public:
         SensorEventConnection(const sp<SensorService>& service, uid_t uid);
@@ -95,6 +111,9 @@
         bool hasAnySensor() const;
         bool addSensor(int32_t handle);
         bool removeSensor(int32_t handle);
+        void setFirstFlushPending(int32_t handle, bool value);
+        void incrementPendingFlushCount(int32_t handle);
+        void dump(String8& result);
 
         uid_t getUid() const { return mUid; }
     };
@@ -130,6 +149,7 @@
     DefaultKeyedVector<int, SensorInterface*> mSensorMap;
     Vector<SensorInterface *> mVirtualSensorList;
     status_t mInitCheck;
+    size_t mSocketBufferSize;
 
     // protected by mLock
     mutable Mutex mLock;
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 61a9361..917d4cd 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -73,7 +73,7 @@
       mLayerStack(NO_LAYER_STACK),
       mOrientation()
 {
-    mNativeWindow = new Surface(producer);
+    mNativeWindow = new Surface(producer, false);
     ANativeWindow* const window = mNativeWindow.get();
 
     int format;
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 43d27bb..c06043d 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -358,10 +358,11 @@
     return mSource[SOURCE_SINK]->query(what, value);
 }
 
-status_t VirtualDisplaySurface::connect(int api, bool producerControlledByApp,
+status_t VirtualDisplaySurface::connect(const sp<IBinder>& token,
+        int api, bool producerControlledByApp,
         QueueBufferOutput* output) {
     QueueBufferOutput qbo;
-    status_t result = mSource[SOURCE_SINK]->connect(api, producerControlledByApp, &qbo);
+    status_t result = mSource[SOURCE_SINK]->connect(token, api, producerControlledByApp, &qbo);
     if (result == NO_ERROR) {
         updateQueueBufferOutput(qbo);
         *output = mQueueBufferOutput;
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index 536007e..18fb5a7 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -102,7 +102,8 @@
             const QueueBufferInput& input, QueueBufferOutput* output);
     virtual void cancelBuffer(int pslot, const sp<Fence>& fence);
     virtual int query(int what, int* value);
-    virtual status_t connect(int api, bool producerControlledByApp, QueueBufferOutput* output);
+    virtual status_t connect(const sp<IBinder>& token,
+            int api, bool producerControlledByApp, QueueBufferOutput* output);
     virtual status_t disconnect(int api);
 
     //
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index fa1ea09..def4618 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2782,7 +2782,7 @@
 
     // create a surface (because we're a producer, and we need to
     // dequeue/queue a buffer)
-    sp<Surface> sur = new Surface(producer);
+    sp<Surface> sur = new Surface(producer, false);
     ANativeWindow* window = sur.get();
 
     status_t result = NO_ERROR;