am aefe55f0: Remove dependencies on runtime_libdvm and libdvm.so in general

* commit 'aefe55f0fb9e69be205497ef4fc3432d2f7a2d8b':
  Remove dependencies on runtime_libdvm and libdvm.so in general
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 099c3df..0d71bbd 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -84,6 +84,7 @@
     { "res",        "Resource Loading", ATRACE_TAG_RESOURCES, { } },
     { "dalvik",     "Dalvik VM",        ATRACE_TAG_DALVIK, { } },
     { "rs",         "RenderScript",     ATRACE_TAG_RS, { } },
+    { "bionic",     "Bionic C Library", ATRACE_TAG_BIONIC, { } },
     { "sched",      "CPU Scheduling",   0, {
         { REQ,      "/sys/kernel/debug/tracing/events/sched/sched_switch/enable" },
         { REQ,      "/sys/kernel/debug/tracing/events/sched/sched_wakeup/enable" },
diff --git a/include/android/sensor.h b/include/android/sensor.h
index 86de930..878f8ff 100644
--- a/include/android/sensor.h
+++ b/include/android/sensor.h
@@ -66,6 +66,7 @@
  * Sensor accuracy measure
  */
 enum {
+    ASENSOR_STATUS_NO_CONTACT       = -1,
     ASENSOR_STATUS_UNRELIABLE       = 0,
     ASENSOR_STATUS_ACCURACY_LOW     = 1,
     ASENSOR_STATUS_ACCURACY_MEDIUM  = 2,
@@ -130,6 +131,11 @@
   };
 } AUncalibratedEvent;
 
+typedef struct AHeartRateEvent {
+  float bpm;
+  int8_t status;
+} AHeartRateEvent;
+
 /* NOTE: Must match hardware/sensors.h */
 typedef struct ASensorEvent {
     int32_t version; /* sizeof(struct ASensorEvent) */
@@ -151,6 +157,7 @@
             AUncalibratedEvent uncalibrated_gyro;
             AUncalibratedEvent uncalibrated_magnetic;
             AMetaDataEvent meta_data;
+            AHeartRateEvent heart_rate;
         };
         union {
             uint64_t        data[8];
@@ -299,13 +306,6 @@
  */
 const char* ASensor_getStringType(ASensor const* sensor);
 
-/*
- * Returns the permission required to see or access this sensor, or the
- * empty string if none is required.
- */
-const char* ASensor_getRequiredPermission(ASensor const* sensor);
-
-
 #ifdef __cplusplus
 };
 #endif
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h
index 8042211..1581084 100644
--- a/include/gui/ISurfaceComposer.h
+++ b/include/gui/ISurfaceComposer.h
@@ -41,6 +41,7 @@
 class DisplayInfo;
 class IDisplayEventConnection;
 class IMemoryHeap;
+class Rect;
 
 /*
  * This class defines the Binder IPC interface for accessing various
@@ -131,11 +132,10 @@
      */
     virtual status_t captureScreen(const sp<IBinder>& display,
             const sp<IGraphicBufferProducer>& producer,
-            uint32_t reqWidth, uint32_t reqHeight,
+            Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
             uint32_t minLayerZ, uint32_t maxLayerZ,
             bool useIdentityTransform) = 0;
 
-
     /* Clears the frame statistics for animations.
      *
      * Requires the ACCESS_SURFACE_FLINGER permission.
diff --git a/include/gui/Sensor.h b/include/gui/Sensor.h
index 41a6cc6..c1c98b9 100644
--- a/include/gui/Sensor.h
+++ b/include/gui/Sensor.h
@@ -71,6 +71,7 @@
     int32_t getFifoMaxEventCount() const;
     const String8& getStringType() const;
     const String8& getRequiredPermission() const;
+    int32_t getMaxDelay() const;
     bool isWakeUpSensor() const;
 
     // LightFlattenable protocol
@@ -94,7 +95,7 @@
     int32_t mFifoMaxEventCount;
     String8 mStringType;
     String8 mRequiredPermission;
-    // Todo: Surface this in java SDK.
+    int32_t mMaxDelay;
     bool    mWakeUpSensor;
     static void flattenString8(void*& buffer, size_t& size, const String8& string8);
     static bool unflattenString8(void const*& buffer, size_t& size, String8& outputString8);
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h
index c2192af..e666329 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -180,10 +180,12 @@
 class ScreenshotClient
 {
 public:
+    // if cropping isn't required, callers may pass in a default Rect, e.g.:
+    //   capture(display, producer, Rect(), reqWidth, ...);
     static status_t capture(
             const sp<IBinder>& display,
             const sp<IGraphicBufferProducer>& producer,
-            uint32_t reqWidth, uint32_t reqHeight,
+            Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
             uint32_t minLayerZ, uint32_t maxLayerZ,
             bool useIdentityTransform);
 
@@ -197,13 +199,16 @@
     ScreenshotClient();
     ~ScreenshotClient();
 
-    // frees the previous screenshot and capture a new one
-    status_t update(const sp<IBinder>& display, bool useIdentityTransform);
+    // frees the previous screenshot and captures a new one
+    // if cropping isn't required, callers may pass in a default Rect, e.g.:
+    //   update(display, Rect(), useIdentityTransform);
     status_t update(const sp<IBinder>& display,
-            uint32_t reqWidth, uint32_t reqHeight,
+            Rect sourceCrop, bool useIdentityTransform);
+    status_t update(const sp<IBinder>& display,
+            Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
             bool useIdentityTransform);
     status_t update(const sp<IBinder>& display,
-            uint32_t reqWidth, uint32_t reqHeight,
+            Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
             uint32_t minLayerZ, uint32_t maxLayerZ,
             bool useIdentityTransform);
 
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 58a2ae2..c6c88a9 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -104,7 +104,7 @@
 
     virtual status_t captureScreen(const sp<IBinder>& display,
             const sp<IGraphicBufferProducer>& producer,
-            uint32_t reqWidth, uint32_t reqHeight,
+            Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
             uint32_t minLayerZ, uint32_t maxLayerZ,
             bool useIdentityTransform)
     {
@@ -112,6 +112,7 @@
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         data.writeStrongBinder(display);
         data.writeStrongBinder(producer->asBinder());
+        data.write(sourceCrop);
         data.writeInt32(reqWidth);
         data.writeInt32(reqHeight);
         data.writeInt32(minLayerZ);
@@ -328,6 +329,8 @@
             sp<IBinder> display = data.readStrongBinder();
             sp<IGraphicBufferProducer> producer =
                     interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
+            Rect sourceCrop;
+            data.read(sourceCrop);
             uint32_t reqWidth = data.readInt32();
             uint32_t reqHeight = data.readInt32();
             uint32_t minLayerZ = data.readInt32();
@@ -335,7 +338,7 @@
             bool useIdentityTransform = static_cast<bool>(data.readInt32());
 
             status_t res = captureScreen(display, producer,
-                    reqWidth, reqHeight, minLayerZ, maxLayerZ,
+                    sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
                     useIdentityTransform);
             reply->writeInt32(res);
             return NO_ERROR;
diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp
index 6d12225..70180f8 100644
--- a/libs/gui/Sensor.cpp
+++ b/libs/gui/Sensor.cpp
@@ -16,6 +16,7 @@
 
 #include <stdint.h>
 #include <sys/types.h>
+#include <sys/limits.h>
 
 #include <utils/Errors.h>
 #include <utils/String8.h>
@@ -24,6 +25,7 @@
 #include <hardware/sensors.h>
 
 #include <gui/Sensor.h>
+#include <log/log.h>
 
 // ----------------------------------------------------------------------------
 namespace android {
@@ -33,7 +35,7 @@
     : mHandle(0), mType(0),
       mMinValue(0), mMaxValue(0), mResolution(0),
       mPower(0), mMinDelay(0), mFifoReservedEventCount(0), mFifoMaxEventCount(0),
-      mWakeUpSensor(false)
+      mMaxDelay(0), mWakeUpSensor(false)
 {
 }
 
@@ -61,6 +63,20 @@
         mFifoMaxEventCount = 0;
     }
 
+    if (halVersion >= SENSORS_DEVICE_API_VERSION_1_3) {
+        if (hwSensor->maxDelay > INT_MAX) {
+            // Max delay is declared as a 64 bit integer for 64 bit architectures. But it should
+            // always fit in a 32 bit integer, log error and cap it to INT_MAX.
+            ALOGE("Sensor maxDelay overflow error %s %lld", mName.string(), hwSensor->maxDelay);
+            mMaxDelay = INT_MAX;
+        } else {
+            mMaxDelay = (int32_t) hwSensor->maxDelay;
+        }
+    } else {
+        // For older hals set maxDelay to 0.
+        mMaxDelay = 0;
+    }
+
     // Ensure existing sensors have correct string type and required
     // permissions.
     switch (mType) {
@@ -289,6 +305,10 @@
     return mRequiredPermission;
 }
 
+int32_t Sensor::getMaxDelay() const {
+    return mMaxDelay;
+}
+
 bool Sensor::isWakeUpSensor() const {
     return mWakeUpSensor;
 }
@@ -298,7 +318,8 @@
     size_t fixedSize =
             sizeof(int32_t) * 3 +
             sizeof(float) * 4 +
-            sizeof(int32_t) * 3;
+            sizeof(int32_t) * 4 +
+            sizeof(bool) * 1;
 
     size_t variableSize =
             sizeof(uint32_t) + FlattenableUtils::align<4>(mName.length()) +
@@ -328,6 +349,8 @@
     FlattenableUtils::write(buffer, size, mFifoMaxEventCount);
     flattenString8(buffer, size, mStringType);
     flattenString8(buffer, size, mRequiredPermission);
+    FlattenableUtils::write(buffer, size, mMaxDelay);
+    FlattenableUtils::write(buffer, size, mWakeUpSensor);
     return NO_ERROR;
 }
 
@@ -342,7 +365,8 @@
     size_t fixedSize =
             sizeof(int32_t) * 3 +
             sizeof(float) * 4 +
-            sizeof(int32_t) * 3;
+            sizeof(int32_t) * 4 +
+            sizeof(bool) * 1;
     if (size < fixedSize) {
         return NO_MEMORY;
     }
@@ -364,6 +388,8 @@
     if (!unflattenString8(buffer, size, mRequiredPermission)) {
         return NO_MEMORY;
     }
+    FlattenableUtils::read(buffer, size, mMaxDelay);
+    FlattenableUtils::read(buffer, size, mWakeUpSensor);
     return NO_ERROR;
 }
 
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 1dffdb2..eedeca1 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -676,11 +676,11 @@
 status_t ScreenshotClient::capture(
         const sp<IBinder>& display,
         const sp<IGraphicBufferProducer>& producer,
-        uint32_t reqWidth, uint32_t reqHeight,
+        Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
         uint32_t minLayerZ, uint32_t maxLayerZ, bool useIdentityTransform) {
     sp<ISurfaceComposer> s(ComposerService::getComposerService());
     if (s == NULL) return NO_INIT;
-    return s->captureScreen(display, producer,
+    return s->captureScreen(display, producer, sourceCrop,
             reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform);
 }
 
@@ -704,7 +704,7 @@
 }
 
 status_t ScreenshotClient::update(const sp<IBinder>& display,
-        uint32_t reqWidth, uint32_t reqHeight,
+        Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
         uint32_t minLayerZ, uint32_t maxLayerZ,
         bool useIdentityTransform) {
     sp<ISurfaceComposer> s(ComposerService::getComposerService());
@@ -717,7 +717,7 @@
         mHaveBuffer = false;
     }
 
-    status_t err = s->captureScreen(display, mProducer,
+    status_t err = s->captureScreen(display, mProducer, sourceCrop,
             reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform);
 
     if (err == NO_ERROR) {
@@ -729,16 +729,16 @@
     return err;
 }
 
-status_t ScreenshotClient::update(const sp<IBinder>& display,
+status_t ScreenshotClient::update(const sp<IBinder>& display, Rect sourceCrop,
         bool useIdentityTransform) {
-    return ScreenshotClient::update(display, 0, 0, 0, -1UL,
+    return ScreenshotClient::update(display, sourceCrop, 0, 0, 0, -1UL,
             useIdentityTransform);
 }
 
-status_t ScreenshotClient::update(const sp<IBinder>& display,
+status_t ScreenshotClient::update(const sp<IBinder>& display, Rect sourceCrop,
         uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform) {
-    return ScreenshotClient::update(display, reqWidth, reqHeight, 0, -1UL,
-            useIdentityTransform);
+    return ScreenshotClient::update(display, sourceCrop, reqWidth, reqHeight,
+            0, -1UL, useIdentityTransform);
 }
 
 void ScreenshotClient::release() {
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index bf87fad..5e6aeef 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -21,6 +21,7 @@
 #include <gui/Surface.h>
 #include <gui/SurfaceComposerClient.h>
 #include <gui/BufferItemConsumer.h>
+#include <ui/Rect.h>
 #include <utils/String8.h>
 
 #include <private/gui/ComposerService.h>
@@ -94,7 +95,7 @@
     sp<CpuConsumer> cpuConsumer = new CpuConsumer(consumer, 1);
     sp<ISurfaceComposer> sf(ComposerService::getComposerService());
     sp<IBinder> display(sf->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
-    ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer,
+    ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(),
             64, 64, 0, 0x7fffffff, false));
 
     // Set the PROTECTED usage bit and verify that the screenshot fails.  Note
@@ -123,7 +124,7 @@
                 &buf));
         ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf, -1));
     }
-    ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer,
+    ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(),
             64, 64, 0, 0x7fffffff, false));
 }
 
diff --git a/opengl/libs/EGL/getProcAddress.cpp b/opengl/libs/EGL/getProcAddress.cpp
index add2a79..5470d81 100644
--- a/opengl/libs/EGL/getProcAddress.cpp
+++ b/opengl/libs/EGL/getProcAddress.cpp
@@ -56,6 +56,50 @@
             :                                                   \
             );
 
+#elif defined(__i386__)
+
+    #define API_ENTRY(_api) __attribute__((noinline)) _api
+
+    #define CALL_GL_EXTENSION_API(_api)                         \
+         register void** fn;                                    \
+         __asm__ volatile(                                      \
+            "mov %%gs:0, %[fn]\n"                               \
+            "mov %P[tls](%[fn]), %[fn]\n"                       \
+            "test %[fn], %[fn]\n"                               \
+            "cmovne %P[api](%[fn]), %[fn]\n"                    \
+            "test %[fn], %[fn]\n"                               \
+            "je 1f\n"                                           \
+            "jmp *%[fn]\n"                                      \
+            "1:\n"                                              \
+            : [fn] "=r" (fn)                                    \
+            : [tls] "i" (TLS_SLOT_OPENGL_API*sizeof(void*)),    \
+              [api] "i" (__builtin_offsetof(gl_hooks_t,         \
+                                      ext.extensions[_api]))    \
+            : "cc"                                              \
+            );
+
+#elif defined(__x86_64__)
+
+    #define API_ENTRY(_api) __attribute__((noinline)) _api
+
+    #define CALL_GL_EXTENSION_API(_api)                         \
+         register void** fn;                                    \
+         __asm__ volatile(                                      \
+            "mov %%fs:0, %[fn]\n"                               \
+            "mov %P[tls](%[fn]), %[fn]\n"                       \
+            "test %[fn], %[fn]\n"                               \
+            "cmovne %P[api](%[fn]), %[fn]\n"                    \
+            "test %[fn], %[fn]\n"                               \
+            "je 1f\n"                                           \
+            "jmp *%[fn]\n"                                      \
+            "1:\n"                                              \
+            : [fn] "=r" (fn)                                    \
+            : [tls] "i" (TLS_SLOT_OPENGL_API*sizeof(void*)),    \
+              [api] "i" (__builtin_offsetof(gl_hooks_t,         \
+                                      ext.extensions[_api]))    \
+            : "cc"                                              \
+            );
+
 #elif defined(__mips__)
 
         #define API_ENTRY(_api) __attribute__((noinline)) _api
@@ -86,6 +130,7 @@
                                           ext.extensions[_api]))    \
                 :                                                   \
             );
+
 #endif
 
 #if defined(CALL_GL_EXTENSION_API)
diff --git a/opengl/libs/GLES2/gl2.cpp b/opengl/libs/GLES2/gl2.cpp
index 75fc95c..1aef9f3 100644
--- a/opengl/libs/GLES2/gl2.cpp
+++ b/opengl/libs/GLES2/gl2.cpp
@@ -54,6 +54,44 @@
             :                                                   \
             );
 
+#elif defined(__i386__) && !USE_SLOW_BINDING
+
+    #define API_ENTRY(_api) __attribute__((noinline)) _api
+
+    #define CALL_GL_API(_api, ...)                                  \
+        register void** fn;                                         \
+        __asm__ volatile(                                           \
+            "mov %%gs:0, %[fn]\n"                                   \
+            "mov %P[tls](%[fn]), %[fn]\n"                           \
+            "test %[fn], %[fn]\n"                                   \
+            "je 1f\n"                                               \
+            "jmp *%P[api](%[fn])\n"                                 \
+            "1:\n"                                                  \
+            : [fn] "=r" (fn)                                        \
+            : [tls] "i" (TLS_SLOT_OPENGL_API*sizeof(void*)),        \
+              [api] "i" (__builtin_offsetof(gl_hooks_t, gl._api))   \
+            : "cc"                                                  \
+            );
+
+#elif defined(__x86_64__) && !USE_SLOW_BINDING
+
+    #define API_ENTRY(_api) __attribute__((noinline)) _api
+
+    #define CALL_GL_API(_api, ...)                                  \
+         register void** fn;                                        \
+         __asm__ volatile(                                          \
+            "mov %%fs:0, %[fn]\n"                                   \
+            "mov %P[tls](%[fn]), %[fn]\n"                           \
+            "test %[fn], %[fn]\n"                                   \
+            "je 1f\n"                                               \
+            "jmp *%P[api](%[fn])\n"                                 \
+            "1:\n"                                                  \
+            : [fn] "=r" (fn)                                        \
+            : [tls] "i" (TLS_SLOT_OPENGL_API*sizeof(void*)),        \
+              [api] "i" (__builtin_offsetof(gl_hooks_t, gl._api))   \
+            : "cc"                                                  \
+            );
+
 #elif defined(__mips__) && !USE_SLOW_BINDING
 
     #define API_ENTRY(_api) __attribute__((noinline)) _api
diff --git a/opengl/libs/GLES_CM/gl.cpp b/opengl/libs/GLES_CM/gl.cpp
index e5de4a7..b18c95c 100644
--- a/opengl/libs/GLES_CM/gl.cpp
+++ b/opengl/libs/GLES_CM/gl.cpp
@@ -110,6 +110,44 @@
             :                                                   \
             );
 
+#elif defined(__i386__) && !USE_SLOW_BINDING
+
+    #define API_ENTRY(_api) __attribute__((noinline)) _api
+
+    #define CALL_GL_API(_api, ...)                                  \
+        register void* fn;                                          \
+        __asm__ volatile(                                           \
+            "mov %%gs:0, %[fn]\n"                                   \
+            "mov %P[tls](%[fn]), %[fn]\n"                           \
+            "test %[fn], %[fn]\n"                                   \
+            "je 1f\n"                                               \
+            "jmp *%P[api](%[fn])\n"                                 \
+            "1:\n"                                                  \
+            : [fn] "=r" (fn)                                        \
+            : [tls] "i" (TLS_SLOT_OPENGL_API*sizeof(void*)),        \
+              [api] "i" (__builtin_offsetof(gl_hooks_t, gl._api))   \
+            : "cc"                                                  \
+            );
+
+#elif defined(__x86_64__) && !USE_SLOW_BINDING
+
+    #define API_ENTRY(_api) __attribute__((noinline)) _api
+
+    #define CALL_GL_API(_api, ...)                                  \
+         register void** fn;                                        \
+         __asm__ volatile(                                          \
+            "mov %%fs:0, %[fn]\n"                                   \
+            "mov %P[tls](%[fn]), %[fn]\n"                           \
+            "test %[fn], %[fn]\n"                                   \
+            "je 1f\n"                                               \
+            "jmp *%P[api](%[fn])\n"                                 \
+            "1:\n"                                                  \
+            : [fn] "=r" (fn)                                        \
+            : [tls] "i" (TLS_SLOT_OPENGL_API*sizeof(void*)),        \
+              [api] "i" (__builtin_offsetof(gl_hooks_t, gl._api))   \
+            : "cc"                                                  \
+            );
+
 #elif defined(__mips__) && !USE_SLOW_BINDING
 
     #define API_ENTRY(_api) __attribute__((noinline)) _api
diff --git a/services/sensorservice/SensorInterface.cpp b/services/sensorservice/SensorInterface.cpp
index 2bf5e72..970220b 100644
--- a/services/sensorservice/SensorInterface.cpp
+++ b/services/sensorservice/SensorInterface.cpp
@@ -17,8 +17,6 @@
 #include <stdint.h>
 #include <sys/types.h>
 
-#include <cutils/log.h>
-
 #include "SensorInterface.h"
 
 namespace android {
@@ -34,7 +32,6 @@
     : mSensorDevice(SensorDevice::getInstance()),
       mSensor(&sensor, mSensorDevice.getHalDeviceVersion())
 {
-    ALOGI("%s", sensor.name);
 }
 
 HardwareSensor::~HardwareSensor() {
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index aff4e9a..1bee04f 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -159,7 +159,6 @@
                     mSocketBufferSize = MAX_SOCKET_BUFFER_SIZE_BATCHED;
                 }
             }
-            ALOGD("Max socket buffer size %u", mSocketBufferSize);
             if (fp) {
                 fclose(fp);
             }
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 42993b9..4ebe291 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -283,7 +283,8 @@
 void DisplayDevice::setViewportAndProjection() const {
     size_t w = mDisplayWidth;
     size_t h = mDisplayHeight;
-    mFlinger->getRenderEngine().setViewportAndProjection(w, h, w, h, false);
+    Rect sourceCrop(0, 0, w, h);
+    mFlinger->getRenderEngine().setViewportAndProjection(w, h, sourceCrop, h, false);
 }
 
 // ----------------------------------------------------------------------------
diff --git a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp
index cbff320..d1e324c 100644
--- a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp
@@ -17,6 +17,8 @@
 #include <GLES/gl.h>
 #include <GLES/glext.h>
 
+#include <ui/Rect.h>
+
 #include <utils/String8.h>
 #include <cutils/compiler.h>
 
@@ -72,13 +74,23 @@
 }
 
 void GLES11RenderEngine::setViewportAndProjection(
-        size_t vpw, size_t vph, size_t w, size_t h, bool yswap) {
+        size_t vpw, size_t vph, Rect sourceCrop, size_t hwh, bool yswap) {
     glViewport(0, 0, vpw, vph);
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
-    // put the origin in the left-bottom corner
-    if (yswap)  glOrthof(0, w, h, 0, 0, 1);
-    else        glOrthof(0, w, 0, h, 0, 1);
+
+    size_t l = sourceCrop.left;
+    size_t r = sourceCrop.right;
+
+    // In GL, (0, 0) is the bottom-left corner, so flip y coordinates
+    size_t t = hwh - sourceCrop.top;
+    size_t b = hwh - sourceCrop.bottom;
+
+    if (yswap) {
+        glOrthof(l, r, t, b, 0, 1);
+    } else {
+        glOrthof(l, r, b, t, 0, 1);
+    }
     glMatrixMode(GL_MODELVIEW);
 }
 
diff --git a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h
index cd53aab..1a94592 100644
--- a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h
@@ -49,7 +49,8 @@
     virtual ~GLES11RenderEngine();
 
     virtual void dump(String8& result);
-    virtual void setViewportAndProjection(size_t vpw, size_t vph, size_t w, size_t h, bool yswap);
+    virtual void setViewportAndProjection(size_t vpw, size_t vph,
+            Rect sourceCrop, size_t hwh, bool yswap);
     virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, int alpha);
     virtual void setupDimLayerBlending(int alpha);
     virtual void setupLayerTexturing(const Texture& texture);
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
index a2a6270..8c1f04e 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
@@ -19,6 +19,8 @@
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
 
+#include <ui/Rect.h>
+
 #include <utils/String8.h>
 #include <utils/Trace.h>
 
@@ -78,10 +80,21 @@
 }
 
 void GLES20RenderEngine::setViewportAndProjection(
-        size_t vpw, size_t vph, size_t w, size_t h, bool yswap) {
+        size_t vpw, size_t vph, Rect sourceCrop, size_t hwh, bool yswap) {
+
+    size_t l = sourceCrop.left;
+    size_t r = sourceCrop.right;
+
+    // In GL, (0, 0) is the bottom-left corner, so flip y coordinates
+    size_t t = hwh - sourceCrop.top;
+    size_t b = hwh - sourceCrop.bottom;
+
     mat4 m;
-    if (yswap)  m = mat4::ortho(0, w, h, 0, 0, 1);
-    else        m = mat4::ortho(0, w, 0, h, 0, 1);
+    if (yswap) {
+        m = mat4::ortho(l, r, t, b, 0, 1);
+    } else {
+        m = mat4::ortho(l, r, b, t, 0, 1);
+    }
 
     glViewport(0, 0, vpw, vph);
     mState.setProjectionMatrix(m);
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
index 8b67fcc..b6d32fc 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
@@ -64,7 +64,8 @@
     virtual ~GLES20RenderEngine();
 
     virtual void dump(String8& result);
-    virtual void setViewportAndProjection(size_t vpw, size_t vph, size_t w, size_t h, bool yswap);
+    virtual void setViewportAndProjection(size_t vpw, size_t vph,
+            Rect sourceCrop, size_t hwh, bool yswap);
     virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, int alpha);
     virtual void setupDimLayerBlending(int alpha);
     virtual void setupLayerTexturing(const Texture& texture);
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index 577dc0a..a2d8242 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -89,7 +89,8 @@
 
     // set-up
     virtual void checkErrors() const;
-    virtual void setViewportAndProjection(size_t vpw, size_t vph, size_t w, size_t h, bool yswap) = 0;
+    virtual void setViewportAndProjection(size_t vpw, size_t vph,
+            Rect sourceCrop, size_t hwh, bool yswap) = 0;
     virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, int alpha) = 0;
     virtual void setupDimLayerBlending(int alpha) = 0;
     virtual void setupLayerTexturing(const Texture& texture) = 0;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 59afa66..7152f93 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2790,7 +2790,7 @@
 
 status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
         const sp<IGraphicBufferProducer>& producer,
-        uint32_t reqWidth, uint32_t reqHeight,
+        Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
         uint32_t minLayerZ, uint32_t maxLayerZ,
         bool useIdentityTransform) {
 
@@ -2816,6 +2816,7 @@
         SurfaceFlinger* flinger;
         sp<IBinder> display;
         sp<IGraphicBufferProducer> producer;
+        Rect sourceCrop;
         uint32_t reqWidth, reqHeight;
         uint32_t minLayerZ,maxLayerZ;
         bool useIdentityTransform;
@@ -2824,11 +2825,11 @@
         MessageCaptureScreen(SurfaceFlinger* flinger,
                 const sp<IBinder>& display,
                 const sp<IGraphicBufferProducer>& producer,
-                uint32_t reqWidth, uint32_t reqHeight,
+                Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
                 uint32_t minLayerZ, uint32_t maxLayerZ,
                 bool useIdentityTransform)
             : flinger(flinger), display(display), producer(producer),
-              reqWidth(reqWidth), reqHeight(reqHeight),
+              sourceCrop(sourceCrop), reqWidth(reqWidth), reqHeight(reqHeight),
               minLayerZ(minLayerZ), maxLayerZ(maxLayerZ),
               useIdentityTransform(useIdentityTransform),
               result(PERMISSION_DENIED)
@@ -2841,7 +2842,7 @@
             Mutex::Autolock _l(flinger->mStateLock);
             sp<const DisplayDevice> hw(flinger->getDisplayDevice(display));
             result = flinger->captureScreenImplLocked(hw, producer,
-                    reqWidth, reqHeight, minLayerZ, maxLayerZ,
+                    sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
                     useIdentityTransform);
             static_cast<GraphicProducerWrapper*>(producer->asBinder().get())->exit(result);
             return true;
@@ -2864,7 +2865,8 @@
     // which does the marshaling work forwards to our "fake remote" above.
     sp<MessageBase> msg = new MessageCaptureScreen(this,
             display, IGraphicBufferProducer::asInterface( wrapper ),
-            reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform);
+            sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
+            useIdentityTransform);
 
     status_t res = postMessageAsync(msg);
     if (res == NO_ERROR) {
@@ -2876,7 +2878,7 @@
 
 void SurfaceFlinger::renderScreenImplLocked(
         const sp<const DisplayDevice>& hw,
-        uint32_t reqWidth, uint32_t reqHeight,
+        Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
         uint32_t minLayerZ, uint32_t maxLayerZ,
         bool yswap, bool useIdentityTransform)
 {
@@ -2888,11 +2890,32 @@
     const uint32_t hw_h = hw->getHeight();
     const bool filtering = reqWidth != hw_w || reqWidth != hw_h;
 
+    // if a default or invalid sourceCrop is passed in, set reasonable values
+    if (sourceCrop.width() == 0 || sourceCrop.height() == 0 ||
+            !sourceCrop.isValid()) {
+        sourceCrop.setLeftTop(Point(0, 0));
+        sourceCrop.setRightBottom(Point(hw_w, hw_h));
+    }
+
+    // ensure that sourceCrop is inside screen
+    if (sourceCrop.left < 0) {
+        ALOGE("Invalid crop rect: l = %d (< 0)", sourceCrop.left);
+    }
+    if (sourceCrop.right >= hw_w) {
+        ALOGE("Invalid crop rect: r = %d (>= %d)", sourceCrop.right, hw_w);
+    }
+    if (sourceCrop.top < 0) {
+        ALOGE("Invalid crop rect: t = %d (< 0)", sourceCrop.top);
+    }
+    if (sourceCrop.bottom >= hw_h) {
+        ALOGE("Invalid crop rect: b = %d (>= %d)", sourceCrop.bottom, hw_h);
+    }
+
     // make sure to clear all GL error flags
     engine.checkErrors();
 
     // set-up our viewport
-    engine.setViewportAndProjection(reqWidth, reqHeight, hw_w, hw_h, yswap);
+    engine.setViewportAndProjection(reqWidth, reqHeight, sourceCrop, hw_h, yswap);
     engine.disableTexturing();
 
     // redraw the screen entirely...
@@ -2923,7 +2946,7 @@
 status_t SurfaceFlinger::captureScreenImplLocked(
         const sp<const DisplayDevice>& hw,
         const sp<IGraphicBufferProducer>& producer,
-        uint32_t reqWidth, uint32_t reqHeight,
+        Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
         uint32_t minLayerZ, uint32_t maxLayerZ,
         bool useIdentityTransform)
 {
@@ -2978,7 +3001,7 @@
                         // via an FBO, which means we didn't have to create
                         // an EGLSurface and therefore we're not
                         // dependent on the context's EGLConfig.
-                        renderScreenImplLocked(hw, reqWidth, reqHeight,
+                        renderScreenImplLocked(hw, sourceCrop, reqWidth, reqHeight,
                                 minLayerZ, maxLayerZ, true, useIdentityTransform);
 
                         // Create a sync point and wait on it, so we know the buffer is
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 0b868e2..cc01eb3 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -202,7 +202,7 @@
     virtual sp<IDisplayEventConnection> createDisplayEventConnection();
     virtual status_t captureScreen(const sp<IBinder>& display,
             const sp<IGraphicBufferProducer>& producer,
-            uint32_t reqWidth, uint32_t reqHeight,
+            Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
             uint32_t minLayerZ, uint32_t maxLayerZ,
             bool useIdentityTransform);
     // called when screen needs to turn off
@@ -311,14 +311,14 @@
 
     void renderScreenImplLocked(
             const sp<const DisplayDevice>& hw,
-            uint32_t reqWidth, uint32_t reqHeight,
+            Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
             uint32_t minLayerZ, uint32_t maxLayerZ,
             bool yswap, bool useIdentityTransform);
 
     status_t captureScreenImplLocked(
             const sp<const DisplayDevice>& hw,
             const sp<IGraphicBufferProducer>& producer,
-            uint32_t reqWidth, uint32_t reqHeight,
+            Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
             uint32_t minLayerZ, uint32_t maxLayerZ,
             bool useIdentityTransform);