Merge "Allow creation of heaps that are read-only to partner"
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index f1f6f99..12e8cd1 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -1234,3 +1234,32 @@
     }
     return -1;
 }
+
+int restorecon_data()
+{
+    char *data_dir = build_string2(android_data_dir.path, PRIMARY_USER_PREFIX);
+    char *user_dir = build_string2(android_data_dir.path, SECONDARY_USER_PREFIX);
+
+    unsigned int flags = SELINUX_ANDROID_RESTORECON_RECURSE |
+            SELINUX_ANDROID_RESTORECON_DATADATA;
+
+    int ret = 0;
+
+    if (!data_dir || !user_dir) {
+        return -1;
+    }
+
+    if (selinux_android_restorecon(data_dir, flags) < 0) {
+        ALOGE("restorecon failed for %s: %s\n", data_dir, strerror(errno));
+        ret |= -1;
+    }
+
+    if (selinux_android_restorecon(user_dir, flags) < 0) {
+        ALOGE("restorecon failed for %s: %s\n", user_dir, strerror(errno));
+        ret |= -1;
+    }
+
+    free(data_dir);
+    free(user_dir);
+    return ret;
+}
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
index b4df3a3..a080ee6 100644
--- a/cmds/installd/installd.c
+++ b/cmds/installd/installd.c
@@ -129,6 +129,12 @@
     return idmap(arg[0], arg[1], atoi(arg[2]));
 }
 
+static int do_restorecon_data(char **arg __attribute__((unused)),
+    char reply[REPLY_MAX] __attribute__((unused)))
+{
+    return restorecon_data();
+}
+
 struct cmdinfo {
     const char *name;
     unsigned numargs;
@@ -153,6 +159,7 @@
     { "mkuserdata",           4, do_mk_user_data },
     { "rmuser",               1, do_rm_user },
     { "idmap",                3, do_idmap },
+    { "restorecondata",       0, do_restorecon_data },
 };
 
 static int readx(int s, void *_buf, int count)
@@ -534,6 +541,27 @@
     }
 }
 
+static int log_callback(int type, const char *fmt, ...) {
+    va_list ap;
+    int priority;
+
+    switch (type) {
+    case SELINUX_WARNING:
+        priority = ANDROID_LOG_WARN;
+        break;
+    case SELINUX_INFO:
+        priority = ANDROID_LOG_INFO;
+        break;
+    default:
+        priority = ANDROID_LOG_ERROR;
+        break;
+    }
+    va_start(ap, fmt);
+    LOG_PRI_VA(priority, "SELinux", fmt, ap);
+    va_end(ap);
+    return 0;
+}
+
 int main(const int argc, const char *argv[]) {
     char buf[BUFFER_MAX];
     struct sockaddr addr;
@@ -543,6 +571,10 @@
 
     ALOGI("installd firing up\n");
 
+    union selinux_callback cb;
+    cb.func_log = log_callback;
+    selinux_set_callback(SELINUX_CB_LOG, cb);
+
     if (initialize_globals() < 0) {
         ALOGE("Could not initialize globals; exiting.\n");
         exit(1);
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index b458031..3e9caf3 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -213,3 +213,4 @@
 int movefiles();
 int linklib(const char* target, const char* source, int userId);
 int idmap(const char *target_path, const char *overlay_path, uid_t uid);
+int restorecon_data();
diff --git a/include/batteryservice/BatteryService.h b/include/batteryservice/BatteryService.h
index 7ae1342..2902d17 100644
--- a/include/batteryservice/BatteryService.h
+++ b/include/batteryservice/BatteryService.h
@@ -48,6 +48,7 @@
     BATTERY_PROP_CHARGE_COUNTER = 1, // equals BatteryProperty.BATTERY_PROP_CHARGE_COUNTER constant
     BATTERY_PROP_CURRENT_NOW = 2, // equals BatteryProperty.BATTERY_PROP_CURRENT_NOW constant
     BATTERY_PROP_CURRENT_AVG = 3, // equals BatteryProperty.BATTERY_PROP_CURRENT_AVG constant
+    BATTERY_PROP_CAPACITY = 4, // equals BatteryProperty.BATTERY_PROP_CAPACITY constant
 };
 
 struct BatteryProperties {
diff --git a/include/input/Input.h b/include/input/Input.h
index ea9c4c2..bb5ceaf 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -22,11 +22,12 @@
  */
 
 #include <android/input.h>
-#include <utils/Vector.h>
+#include <utils/BitSet.h>
 #include <utils/KeyedVector.h>
-#include <utils/Timers.h>
 #include <utils/RefBase.h>
 #include <utils/String8.h>
+#include <utils/Timers.h>
+#include <utils/Vector.h>
 
 /*
  * Additional private constants not defined in ndk/ui/input.h.
@@ -205,7 +206,11 @@
     float values[MAX_AXES];
 
     inline void clear() {
-        bits = 0;
+        BitSet64::clear(bits);
+    }
+
+    bool isEmpty() const {
+        return BitSet64::isEmpty(bits);
     }
 
     float getAxisValue(int32_t axis) const;
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 0163906..19ed047 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -345,7 +345,7 @@
     int fd = open("/dev/binder", O_RDWR);
     if (fd >= 0) {
         fcntl(fd, F_SETFD, FD_CLOEXEC);
-        int vers;
+        int vers = 0;
         status_t result = ioctl(fd, BINDER_VERSION, &vers);
         if (result == -1) {
             ALOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 7db344a..9dd90ba 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -432,6 +432,7 @@
     mSlots[*outSlot].mBufferState = BufferSlot::DEQUEUED;
     mSlots[*outSlot].mEglFence = EGL_NO_SYNC_KHR;
     mSlots[*outSlot].mFence = Fence::NO_FENCE;
+    mSlots[*outSlot].mRequestBufferCalled = true;
 
     return returnFlags;
 }
diff --git a/libs/gui/IGraphicBufferConsumer.cpp b/libs/gui/IGraphicBufferConsumer.cpp
index 3598a86..cdd06f3 100644
--- a/libs/gui/IGraphicBufferConsumer.cpp
+++ b/libs/gui/IGraphicBufferConsumer.cpp
@@ -71,11 +71,11 @@
     size_t c = 0;
     if (mGraphicBuffer != 0) {
         c += mGraphicBuffer->getFlattenedSize();
-        FlattenableUtils::align<4>(c);
+        c = FlattenableUtils::align<4>(c);
     }
     if (mFence != 0) {
         c += mFence->getFlattenedSize();
-        FlattenableUtils::align<4>(c);
+        c = FlattenableUtils::align<4>(c);
     }
     return sizeof(int32_t) + c + getPodSize();
 }
@@ -91,11 +91,21 @@
     return c;
 }
 
+static void writeBoolAsInt(void*& buffer, size_t& size, bool b) {
+    FlattenableUtils::write(buffer, size, static_cast<int32_t>(b));
+}
+
+static bool readBoolFromInt(void const*& buffer, size_t& size) {
+    int32_t i;
+    FlattenableUtils::read(buffer, size, i);
+    return static_cast<bool>(i);
+}
+
 status_t IGraphicBufferConsumer::BufferItem::flatten(
         void*& buffer, size_t& size, int*& fds, size_t& count) const {
 
     // make sure we have enough space
-    if (count < BufferItem::getFlattenedSize()) {
+    if (size < BufferItem::getFlattenedSize()) {
         return NO_MEMORY;
     }
 
@@ -128,12 +138,12 @@
     FlattenableUtils::write(buffer, size, mTransform);
     FlattenableUtils::write(buffer, size, mScalingMode);
     FlattenableUtils::write(buffer, size, mTimestamp);
-    FlattenableUtils::write(buffer, size, mIsAutoTimestamp);
+    writeBoolAsInt(buffer, size, mIsAutoTimestamp);
     FlattenableUtils::write(buffer, size, mFrameNumber);
     FlattenableUtils::write(buffer, size, mBuf);
-    FlattenableUtils::write(buffer, size, mIsDroppable);
-    FlattenableUtils::write(buffer, size, mAcquireCalled);
-    FlattenableUtils::write(buffer, size, mTransformToDisplayInverse);
+    writeBoolAsInt(buffer, size, mIsDroppable);
+    writeBoolAsInt(buffer, size, mAcquireCalled);
+    writeBoolAsInt(buffer, size, mTransformToDisplayInverse);
 
     return NO_ERROR;
 }
@@ -170,12 +180,12 @@
     FlattenableUtils::read(buffer, size, mTransform);
     FlattenableUtils::read(buffer, size, mScalingMode);
     FlattenableUtils::read(buffer, size, mTimestamp);
-    FlattenableUtils::read(buffer, size, mIsAutoTimestamp);
+    mIsAutoTimestamp = readBoolFromInt(buffer, size);
     FlattenableUtils::read(buffer, size, mFrameNumber);
     FlattenableUtils::read(buffer, size, mBuf);
-    FlattenableUtils::read(buffer, size, mIsDroppable);
-    FlattenableUtils::read(buffer, size, mAcquireCalled);
-    FlattenableUtils::read(buffer, size, mTransformToDisplayInverse);
+    mIsDroppable = readBoolFromInt(buffer, size);
+    mAcquireCalled = readBoolFromInt(buffer, size);
+    mTransformToDisplayInverse = readBoolFromInt(buffer, size);
 
     return NO_ERROR;
 }
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index b628a15..95f4084 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -86,6 +86,10 @@
     return mGraphicBufferProducer;
 }
 
+void Surface::setSidebandStream(const sp<NativeHandle>& stream) {
+    mGraphicBufferProducer->setSidebandStream(stream);
+}
+
 int Surface::hook_setSwapInterval(ANativeWindow* window, int interval) {
     Surface* c = getSelf(window);
     return c->setSwapInterval(interval);
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 5aa34a5..7943476 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -24,7 +24,9 @@
 
 #include <ui/GraphicBuffer.h>
 
+#include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
 #include <gui/BufferQueue.h>
 
 namespace android {
@@ -32,20 +34,12 @@
 class BufferQueueTest : public ::testing::Test {
 
 public:
-    static const String16 PRODUCER_NAME;
-    static const String16 CONSUMER_NAME;
-
 protected:
     BufferQueueTest() {
         const ::testing::TestInfo* const testInfo =
             ::testing::UnitTest::GetInstance()->current_test_info();
         ALOGV("Begin test: %s.%s", testInfo->test_case_name(),
                 testInfo->name());
-
-        BufferQueue::createBufferQueue(&mProducer, &mConsumer);
-        sp<IServiceManager> serviceManager = defaultServiceManager();
-        serviceManager->addService(PRODUCER_NAME, mProducer.get());
-        serviceManager->addService(CONSUMER_NAME, mConsumer.get());
     }
 
     ~BufferQueueTest() {
@@ -62,12 +56,13 @@
         ASSERT_GE(*bufferCount, 0);
     }
 
-    sp<BnGraphicBufferProducer> mProducer;
-    sp<BnGraphicBufferConsumer> mConsumer;
-};
+    void createBufferQueue() {
+        BufferQueue::createBufferQueue(&mProducer, &mConsumer);
+    }
 
-const String16 BufferQueueTest::PRODUCER_NAME = String16("BQTestProducer");
-const String16 BufferQueueTest::CONSUMER_NAME = String16("BQTestConsumer");
+    sp<IGraphicBufferProducer> mProducer;
+    sp<IGraphicBufferConsumer> mConsumer;
+};
 
 struct DummyConsumer : public BnConsumerListener {
     virtual void onFrameAvailable() {}
@@ -75,7 +70,74 @@
     virtual void onSidebandStreamChanged() {}
 };
 
+// XXX: Tests that fork a process to hold the BufferQueue must run before tests
+// that use a local BufferQueue, or else Binder will get unhappy
+TEST_F(BufferQueueTest, BufferQueueInAnotherProcess) {
+    const String16 PRODUCER_NAME = String16("BQTestProducer");
+    const String16 CONSUMER_NAME = String16("BQTestConsumer");
+
+    pid_t forkPid = fork();
+    ASSERT_NE(forkPid, -1);
+
+    if (forkPid == 0) {
+        // Child process
+        sp<BnGraphicBufferProducer> producer;
+        sp<BnGraphicBufferConsumer> consumer;
+        BufferQueue::createBufferQueue(&producer, &consumer);
+        sp<IServiceManager> serviceManager = defaultServiceManager();
+        serviceManager->addService(PRODUCER_NAME, producer.get());
+        serviceManager->addService(CONSUMER_NAME, consumer.get());
+        ProcessState::self()->startThreadPool();
+        IPCThreadState::self()->joinThreadPool();
+        LOG_ALWAYS_FATAL("Shouldn't be here");
+    }
+
+    sp<IServiceManager> serviceManager = defaultServiceManager();
+    sp<IBinder> binderProducer =
+        serviceManager->getService(PRODUCER_NAME);
+    mProducer = interface_cast<IGraphicBufferProducer>(binderProducer);
+    EXPECT_TRUE(mProducer != NULL);
+    sp<IBinder> binderConsumer =
+        serviceManager->getService(CONSUMER_NAME);
+    mConsumer = interface_cast<IGraphicBufferConsumer>(binderConsumer);
+    EXPECT_TRUE(mConsumer != NULL);
+
+    sp<DummyConsumer> dc(new DummyConsumer);
+    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
+    IGraphicBufferProducer::QueueBufferOutput output;
+    ASSERT_EQ(OK,
+            mProducer->connect(NULL, NATIVE_WINDOW_API_CPU, false, &output));
+
+    int slot;
+    sp<Fence> fence;
+    sp<GraphicBuffer> buffer;
+    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
+            mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
+                    GRALLOC_USAGE_SW_WRITE_OFTEN));
+    ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
+
+    uint32_t* dataIn;
+    ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
+            reinterpret_cast<void**>(&dataIn)));
+    *dataIn = 0x12345678;
+    ASSERT_EQ(OK, buffer->unlock());
+
+    IGraphicBufferProducer::QueueBufferInput input(0, false, Rect(0, 0, 1, 1),
+            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE);
+    ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
+
+    IGraphicBufferConsumer::BufferItem item;
+    ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
+
+    uint32_t* dataOut;
+    ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
+            reinterpret_cast<void**>(&dataOut)));
+    ASSERT_EQ(*dataOut, 0x12345678);
+    ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
+}
+
 TEST_F(BufferQueueTest, AcquireBuffer_ExceedsMaxAcquireCount_Fails) {
+    createBufferQueue();
     sp<DummyConsumer> dc(new DummyConsumer);
     mConsumer->consumerConnect(dc, false);
     IGraphicBufferProducer::QueueBufferOutput qbo;
@@ -109,6 +171,7 @@
 }
 
 TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithIllegalValues_ReturnsError) {
+    createBufferQueue();
     sp<DummyConsumer> dc(new DummyConsumer);
     mConsumer->consumerConnect(dc, false);
 
@@ -125,6 +188,7 @@
 }
 
 TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithLegalValues_Succeeds) {
+    createBufferQueue();
     sp<DummyConsumer> dc(new DummyConsumer);
     mConsumer->consumerConnect(dc, false);
 
@@ -139,6 +203,7 @@
 }
 
 TEST_F(BufferQueueTest, DetachAndReattachOnProducerSide) {
+    createBufferQueue();
     sp<DummyConsumer> dc(new DummyConsumer);
     ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
     IGraphicBufferProducer::QueueBufferOutput output;
@@ -187,9 +252,11 @@
     ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
             reinterpret_cast<void**>(&dataOut)));
     ASSERT_EQ(*dataOut, 0x12345678);
+    ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
 }
 
 TEST_F(BufferQueueTest, DetachAndReattachOnConsumerSide) {
+    createBufferQueue();
     sp<DummyConsumer> dc(new DummyConsumer);
     ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
     IGraphicBufferProducer::QueueBufferOutput output;
@@ -243,9 +310,11 @@
     ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
             reinterpret_cast<void**>(&dataOut)));
     ASSERT_EQ(*dataOut, 0x12345678);
+    ASSERT_EQ(OK, buffer->unlock());
 }
 
 TEST_F(BufferQueueTest, MoveFromConsumerToProducer) {
+    createBufferQueue();
     sp<DummyConsumer> dc(new DummyConsumer);
     ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
     IGraphicBufferProducer::QueueBufferOutput output;
@@ -283,6 +352,7 @@
     ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
             reinterpret_cast<void**>(&dataOut)));
     ASSERT_EQ(*dataOut, 0x12345678);
+    ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
 }
 
 } // namespace android
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index ccbf52b..d9f22e9 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -158,16 +158,10 @@
 // --- PointerCoords ---
 
 float PointerCoords::getAxisValue(int32_t axis) const {
-    if (axis < 0 || axis > 63) {
+    if (axis < 0 || axis > 63 || !BitSet64::hasBit(bits, axis)){
         return 0;
     }
-
-    uint64_t axisBit = 1LL << axis;
-    if (!(bits & axisBit)) {
-        return 0;
-    }
-    uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL));
-    return values[index];
+    return values[BitSet64::getIndexOfBit(bits, axis)];
 }
 
 status_t PointerCoords::setAxisValue(int32_t axis, float value) {
@@ -175,22 +169,23 @@
         return NAME_NOT_FOUND;
     }
 
-    uint64_t axisBit = 1LL << axis;
-    uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL));
-    if (!(bits & axisBit)) {
+    uint32_t index = BitSet64::getIndexOfBit(bits, axis);
+    if (!BitSet64::hasBit(bits, axis)) {
         if (value == 0) {
             return OK; // axes with value 0 do not need to be stored
         }
-        uint32_t count = __builtin_popcountll(bits);
+
+        uint32_t count = BitSet64::count(bits);
         if (count >= MAX_AXES) {
             tooManyAxes(axis);
             return NO_MEMORY;
         }
-        bits |= axisBit;
+        BitSet64::markBit(bits, axis);
         for (uint32_t i = count; i > index; i--) {
             values[i] = values[i - 1];
         }
     }
+
     values[index] = value;
     return OK;
 }
@@ -222,7 +217,7 @@
 status_t PointerCoords::readFromParcel(Parcel* parcel) {
     bits = parcel->readInt64();
 
-    uint32_t count = __builtin_popcountll(bits);
+    uint32_t count = BitSet64::count(bits);
     if (count > MAX_AXES) {
         return BAD_VALUE;
     }
@@ -236,7 +231,7 @@
 status_t PointerCoords::writeToParcel(Parcel* parcel) const {
     parcel->writeInt64(bits);
 
-    uint32_t count = __builtin_popcountll(bits);
+    uint32_t count = BitSet64::count(bits);
     for (uint32_t i = 0; i < count; i++) {
         parcel->writeFloat(values[i]);
     }
@@ -253,7 +248,7 @@
     if (bits != other.bits) {
         return false;
     }
-    uint32_t count = __builtin_popcountll(bits);
+    uint32_t count = BitSet64::count(bits);
     for (uint32_t i = 0; i < count; i++) {
         if (values[i] != other.values[i]) {
             return false;
@@ -264,7 +259,7 @@
 
 void PointerCoords::copyFrom(const PointerCoords& other) {
     bits = other.bits;
-    uint32_t count = __builtin_popcountll(bits);
+    uint32_t count = BitSet64::count(bits);
     for (uint32_t i = 0; i < count; i++) {
         values[i] = other.values[i];
     }
diff --git a/opengl/tests/lib/WindowSurface.cpp b/opengl/tests/lib/WindowSurface.cpp
index ff91260..1428945 100644
--- a/opengl/tests/lib/WindowSurface.cpp
+++ b/opengl/tests/lib/WindowSurface.cpp
@@ -56,7 +56,7 @@
 
     sp<SurfaceControl> sc = surfaceComposerClient->createSurface(
             String8("Benchmark"), width, height,
-            PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eOpaque);
+            PIXEL_FORMAT_RGBX_8888, ISurfaceComposerClient::eOpaque);
     if (sc == NULL || !sc->isValid()) {
         fprintf(stderr, "Failed to create SurfaceControl\n");
         return;
diff --git a/services/batteryservice/IBatteryPropertiesRegistrar.cpp b/services/batteryservice/IBatteryPropertiesRegistrar.cpp
index 6647122..296bfab 100644
--- a/services/batteryservice/IBatteryPropertiesRegistrar.cpp
+++ b/services/batteryservice/IBatteryPropertiesRegistrar.cpp
@@ -50,7 +50,11 @@
             data.writeInterfaceToken(IBatteryPropertiesRegistrar::getInterfaceDescriptor());
             data.writeInt32(id);
             remote()->transact(GET_PROPERTY, data, &reply);
-            status_t ret = reply.readInt32();
+            int32_t ret = reply.readExceptionCode();
+            if (ret != 0) {
+                return ret;
+            }
+            ret = reply.readInt32();
             int parcelpresent = reply.readInt32();
             if (parcelpresent)
                 val->readFromParcel(&reply);
diff --git a/services/inputflinger/EventHub.cpp b/services/inputflinger/EventHub.cpp
index 94fc0af..b70ea76 100644
--- a/services/inputflinger/EventHub.cpp
+++ b/services/inputflinger/EventHub.cpp
@@ -813,7 +813,7 @@
                 if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {
                     // Device was removed before INotify noticed.
                     ALOGW("could not get event, removed? (fd: %d size: %d bufferSize: %d "
-                            "capacity: %d errno: %d)\n",
+                            "capacity: %zu errno: %d)\n",
                             device->fd, readSize, bufferSize, capacity, errno);
                     deviceChanged = true;
                     closeDeviceLocked(device);
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index f933681..dbfc957 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -148,7 +148,7 @@
         return false;
     }
     if (pointerCount < 1 || pointerCount > MAX_POINTERS) {
-        ALOGE("Motion event has invalid pointer count %d; value must be between 1 and %d.",
+        ALOGE("Motion event has invalid pointer count %zu; value must be between 1 and %d.",
                 pointerCount, MAX_POINTERS);
         return false;
     }
@@ -3141,7 +3141,7 @@
                 dump.append(INDENT3 "Windows:\n");
                 for (size_t i = 0; i < state.windows.size(); i++) {
                     const TouchedWindow& touchedWindow = state.windows[i];
-                    dump.appendFormat(INDENT4 "%d: name='%s', pointerIds=0x%0x, targetFlags=0x%x\n",
+                    dump.appendFormat(INDENT4 "%zu: name='%s', pointerIds=0x%0x, targetFlags=0x%x\n",
                             i, touchedWindow.windowHandle->getName().string(),
                             touchedWindow.pointerIds.value,
                             touchedWindow.targetFlags);
@@ -3160,7 +3160,7 @@
             const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
             const InputWindowInfo* windowInfo = windowHandle->getInfo();
 
-            dump.appendFormat(INDENT2 "%d: name='%s', displayId=%d, "
+            dump.appendFormat(INDENT2 "%zu: name='%s', displayId=%d, "
                     "paused=%s, hasFocus=%s, hasWallpaper=%s, "
                     "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, "
                     "frame=[%d,%d][%d,%d], scale=%f, "
@@ -3190,7 +3190,7 @@
         dump.append(INDENT "MonitoringChannels:\n");
         for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
             const sp<InputChannel>& channel = mMonitoringChannels[i];
-            dump.appendFormat(INDENT2 "%d: '%s'\n", i, channel->getName().string());
+            dump.appendFormat(INDENT2 "%zu: '%s'\n", i, channel->getName().string());
         }
     } else {
         dump.append(INDENT "MonitoringChannels: <none>\n");
@@ -3239,7 +3239,7 @@
         dump.append(INDENT "Connections:\n");
         for (size_t i = 0; i < mConnectionsByFd.size(); i++) {
             const sp<Connection>& connection = mConnectionsByFd.valueAt(i);
-            dump.appendFormat(INDENT2 "%d: channelName='%s', windowName='%s', "
+            dump.appendFormat(INDENT2 "%zu: channelName='%s', windowName='%s', "
                     "status=%s, monitor=%s, inputPublisherBlocked=%s\n",
                     i, connection->getInputChannelName(), connection->getWindowName(),
                     connection->getStatusLabel(), toString(connection->monitor),
@@ -4108,18 +4108,39 @@
     case AMOTION_EVENT_ACTION_POINTER_UP:
     case AMOTION_EVENT_ACTION_POINTER_DOWN:
     case AMOTION_EVENT_ACTION_MOVE: {
+        if (entry->source & AINPUT_SOURCE_CLASS_NAVIGATION) {
+            // Trackballs can send MOVE events with a corresponding DOWN or UP. There's no need to
+            // generate cancellation events for these since they're based in relative rather than
+            // absolute units.
+            return true;
+        }
+
         ssize_t index = findMotionMemento(entry, false /*hovering*/);
+
+        if (entry->source & AINPUT_SOURCE_CLASS_JOYSTICK) {
+            // Joysticks can send MOVE events without a corresponding DOWN or UP. Since all
+            // joystick axes are normalized to [-1, 1] we can trust that 0 means it's neutral. Any
+            // other value and we need to track the motion so we can send cancellation events for
+            // anything generating fallback events (e.g. DPad keys for joystick movements).
+            if (index >= 0) {
+                if (entry->pointerCoords[0].isEmpty()) {
+                    mMotionMementos.removeAt(index);
+                } else {
+                    MotionMemento& memento = mMotionMementos.editItemAt(index);
+                    memento.setPointers(entry);
+                }
+            } else if (!entry->pointerCoords[0].isEmpty()) {
+                addMotionMemento(entry, flags, false /*hovering*/);
+            }
+
+            // Joysticks and trackballs can send MOVE events without corresponding DOWN or UP.
+            return true;
+        }
         if (index >= 0) {
             MotionMemento& memento = mMotionMementos.editItemAt(index);
             memento.setPointers(entry);
             return true;
         }
-        if (actionMasked == AMOTION_EVENT_ACTION_MOVE
-                && (entry->source & (AINPUT_SOURCE_CLASS_JOYSTICK
-                        | AINPUT_SOURCE_CLASS_NAVIGATION))) {
-            // Joysticks and trackballs can send MOVE events without corresponding DOWN or UP.
-            return true;
-        }
 #if DEBUG_OUTBOUND_EVENT_DETAILS
         ALOGD("Dropping inconsistent motion pointer up/down or move event: "
                 "deviceId=%d, source=%08x, actionMasked=%d",
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 05b1a9c..f27ba96 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -2003,9 +2003,9 @@
     dumpParameters(dump);
     dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
     dump.appendFormat(INDENT3 "Orientation: %d\n", mOrientation);
-    dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mKeyDowns.size());
+    dump.appendFormat(INDENT3 "KeyDowns: %zu keys currently down\n", mKeyDowns.size());
     dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mMetaState);
-    dump.appendFormat(INDENT3 "DownTime: %lld\n", mDownTime);
+    dump.appendFormat(INDENT3 "DownTime: %lld\n", (long long)mDownTime);
 }
 
 
@@ -2041,6 +2041,10 @@
     if (mParameters.orientationAware) {
         mParameters.hasAssociatedDisplay = true;
     }
+
+    mParameters.handlesKeyRepeat = false;
+    getDevice()->getConfiguration().tryGetProperty(String8("keyboard.handlesKeyRepeat"),
+            mParameters.handlesKeyRepeat);
 }
 
 void KeyboardInputMapper::dumpParameters(String8& dump) {
@@ -2049,6 +2053,8 @@
             toString(mParameters.hasAssociatedDisplay));
     dump.appendFormat(INDENT4 "OrientationAware: %s\n",
             toString(mParameters.orientationAware));
+    dump.appendFormat(INDENT4 "HandlesKeyRepeat: %s\n",
+            toString(mParameters.handlesKeyRepeat));
 }
 
 void KeyboardInputMapper::reset(nsecs_t when) {
@@ -2166,6 +2172,10 @@
         policyFlags |= POLICY_FLAG_WAKE_DROPPED;
     }
 
+    if (mParameters.handlesKeyRepeat) {
+        policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
+    }
+
     if (metaStateChanged) {
         getContext()->updateGlobalMetaState();
     }
@@ -2293,7 +2303,7 @@
     dump.appendFormat(INDENT3 "Orientation: %d\n", mOrientation);
     dump.appendFormat(INDENT3 "ButtonState: 0x%08x\n", mButtonState);
     dump.appendFormat(INDENT3 "Down: %s\n", toString(isPointerDown(mButtonState)));
-    dump.appendFormat(INDENT3 "DownTime: %lld\n", mDownTime);
+    dump.appendFormat(INDENT3 "DownTime: %lld\n", (long long)mDownTime);
 }
 
 void CursorInputMapper::configure(nsecs_t when,
@@ -3399,7 +3409,7 @@
 
         for (size_t i = 0; i < mVirtualKeys.size(); i++) {
             const VirtualKey& virtualKey = mVirtualKeys.itemAt(i);
-            dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
+            dump.appendFormat(INDENT4 "%zu: scanCode=%d, keyCode=%d, "
                     "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
                     i, virtualKey.scanCode, virtualKey.keyCode,
                     virtualKey.hitLeft, virtualKey.hitRight,
@@ -6164,8 +6174,8 @@
             && mRawPointerAxes.slot.minValue == 0 && mRawPointerAxes.slot.maxValue > 0) {
         size_t slotCount = mRawPointerAxes.slot.maxValue + 1;
         if (slotCount > MAX_SLOTS) {
-            ALOGW("MultiTouch Device %s reported %d slots but the framework "
-                    "only supports a maximum of %d slots at this time.",
+            ALOGW("MultiTouch Device %s reported %zu slots but the framework "
+                    "only supports a maximum of %zu slots at this time.",
                     getDeviceName().string(), slotCount, MAX_SLOTS);
             slotCount = MAX_SLOTS;
         }
@@ -6337,7 +6347,7 @@
         // If there are too many axes, start dropping them.
         // Prefer to keep explicitly mapped axes.
         if (mAxes.size() > PointerCoords::MAX_AXES) {
-            ALOGI("Joystick '%s' has %d axes but the framework only supports a maximum of %d.",
+            ALOGI("Joystick '%s' has %zu axes but the framework only supports a maximum of %d.",
                     getDeviceName().string(), mAxes.size(), PointerCoords::MAX_AXES);
             pruneAxes(true);
             pruneAxes(false);
diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h
index c1ce5f7..9e36e35 100644
--- a/services/inputflinger/InputReader.h
+++ b/services/inputflinger/InputReader.h
@@ -1086,6 +1086,7 @@
     struct Parameters {
         bool hasAssociatedDisplay;
         bool orientationAware;
+        bool handlesKeyRepeat;
     } mParameters;
 
     void configureParameters();
diff --git a/services/inputflinger/main.cpp b/services/inputflinger/main.cpp
index 3209a62..0a517cc 100644
--- a/services/inputflinger/main.cpp
+++ b/services/inputflinger/main.cpp
@@ -19,7 +19,7 @@
 
 using namespace android;
 
-int main(int argc, char** argv) {
+int main(int, char**) {
     ProcessState::self()->setThreadPoolMaxThreadCount(4);
     BinderService<InputFlinger>::publishAndJoinThreadPool(true);
     return 0;
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 49a017f..0834c80 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -11,9 +11,9 @@
     Layer.cpp \
     LayerDim.cpp \
     MessageQueue.cpp \
+    MonitoredProducer.cpp \
     SurfaceFlinger.cpp \
     SurfaceFlingerConsumer.cpp \
-    SurfaceTextureLayer.cpp \
     Transform.cpp \
     DisplayHardware/FramebufferSurface.cpp \
     DisplayHardware/HWComposer.cpp \
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 11c42e0..f4cb8b5 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -47,9 +47,10 @@
 
 VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId,
         const sp<IGraphicBufferProducer>& sink,
-        const sp<BufferQueue>& bq,
+        const sp<IGraphicBufferProducer>& bqProducer,
+        const sp<IGraphicBufferConsumer>& bqConsumer,
         const String8& name)
-:   ConsumerBase(bq),
+:   ConsumerBase(bqConsumer),
     mHwc(hwc),
     mDisplayId(dispId),
     mDisplayName(name),
@@ -60,7 +61,7 @@
     mMustRecompose(false)
 {
     mSource[SOURCE_SINK] = sink;
-    mSource[SOURCE_SCRATCH] = bq;
+    mSource[SOURCE_SCRATCH] = bqProducer;
 
     resetPerFrameState();
 
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index 0d30a1b..09e5544 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -73,7 +73,8 @@
 public:
     VirtualDisplaySurface(HWComposer& hwc, int32_t dispId,
             const sp<IGraphicBufferProducer>& sink,
-            const sp<BufferQueue>& bq,
+            const sp<IGraphicBufferProducer>& bqProducer,
+            const sp<IGraphicBufferConsumer>& bqConsumer,
             const String8& name);
 
     //
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 019d892..7f2ee2a 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -40,8 +40,8 @@
 #include "Colorizer.h"
 #include "DisplayDevice.h"
 #include "Layer.h"
+#include "MonitoredProducer.h"
 #include "SurfaceFlinger.h"
-#include "SurfaceTextureLayer.h"
 
 #include "DisplayHardware/HWComposer.h"
 
@@ -117,8 +117,11 @@
 
 void Layer::onFirstRef() {
     // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
-    mBufferQueue = new SurfaceTextureLayer(mFlinger);
-    mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(mBufferQueue, mTextureName);
+    sp<BnGraphicBufferProducer> producer;
+    sp<BnGraphicBufferConsumer> consumer;
+    BufferQueue::createBufferQueue(&producer, &consumer);
+    mProducer = new MonitoredProducer(producer, mFlinger);
+    mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName);
     mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
     mSurfaceFlingerConsumer->setContentsChangedListener(this);
     mSurfaceFlingerConsumer->setName(mName);
@@ -236,8 +239,8 @@
     return new Handle(mFlinger, this);
 }
 
-sp<IGraphicBufferProducer> Layer::getBufferQueue() const {
-    return mBufferQueue;
+sp<IGraphicBufferProducer> Layer::getProducer() const {
+    return mProducer;
 }
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 43de999..8f8989e 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -37,9 +37,9 @@
 
 #include "FrameTracker.h"
 #include "Client.h"
+#include "MonitoredProducer.h"
 #include "SurfaceFlinger.h"
 #include "SurfaceFlingerConsumer.h"
-#include "SurfaceTextureLayer.h"
 #include "Transform.h"
 
 #include "DisplayHardware/HWComposer.h"
@@ -140,7 +140,7 @@
     Rect computeBounds() const;
 
     sp<IBinder> getHandle();
-    sp<IGraphicBufferProducer> getBufferQueue() const;
+    sp<IGraphicBufferProducer> getProducer() const;
     const String8& getName() const;
 
     // -----------------------------------------------------------------------
@@ -338,7 +338,7 @@
 
     // constants
     sp<SurfaceFlingerConsumer> mSurfaceFlingerConsumer;
-    sp<BufferQueue> mBufferQueue;
+    sp<IGraphicBufferProducer> mProducer;
     uint32_t mTextureName;
     bool mPremultipliedAlpha;
     String8 mName;
diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp
new file mode 100644
index 0000000..8fed676
--- /dev/null
+++ b/services/surfaceflinger/MonitoredProducer.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright 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.
+ */
+
+#include "MessageQueue.h"
+#include "MonitoredProducer.h"
+#include "SurfaceFlinger.h"
+
+namespace android {
+
+MonitoredProducer::MonitoredProducer(const sp<BnGraphicBufferProducer>& producer,
+        const sp<SurfaceFlinger>& flinger) :
+    mProducer(producer),
+    mFlinger(flinger) {}
+
+MonitoredProducer::~MonitoredProducer() {
+    // Remove ourselves from SurfaceFlinger's list. We do this asynchronously
+    // because we don't know where this destructor is called from. It could be
+    // called with the mStateLock held, leading to a dead-lock (it actually
+    // happens).
+    class MessageCleanUpList : public MessageBase {
+    public:
+        MessageCleanUpList(const sp<SurfaceFlinger>& flinger,
+                const wp<IBinder>& producer)
+            : mFlinger(flinger), mProducer(producer) {}
+
+        virtual ~MessageCleanUpList() {}
+
+        virtual bool handler() {
+            Mutex::Autolock _l(mFlinger->mStateLock);
+            mFlinger->mGraphicBufferProducerList.remove(mProducer);
+            return true;
+        }
+
+    private:
+        sp<SurfaceFlinger> mFlinger;
+        wp<IBinder> mProducer;
+    };
+
+    mFlinger->postMessageAsync(new MessageCleanUpList(mFlinger,
+            static_cast<BnGraphicBufferProducer*>(this)));
+}
+
+status_t MonitoredProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
+    return mProducer->requestBuffer(slot, buf);
+}
+
+status_t MonitoredProducer::setBufferCount(int bufferCount) {
+    return mProducer->setBufferCount(bufferCount);
+}
+
+status_t MonitoredProducer::dequeueBuffer(int* slot, sp<Fence>* fence,
+        bool async, uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
+    return mProducer->dequeueBuffer(slot, fence, async, w, h, format, usage);
+}
+
+status_t MonitoredProducer::detachBuffer(int slot) {
+    return mProducer->detachBuffer(slot);
+}
+
+status_t MonitoredProducer::attachBuffer(int* outSlot,
+        const sp<GraphicBuffer>& buffer) {
+    return mProducer->attachBuffer(outSlot, buffer);
+}
+
+status_t MonitoredProducer::queueBuffer(int slot, const QueueBufferInput& input,
+        QueueBufferOutput* output) {
+    return mProducer->queueBuffer(slot, input, output);
+}
+
+void MonitoredProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
+    mProducer->cancelBuffer(slot, fence);
+}
+
+int MonitoredProducer::query(int what, int* value) {
+    return mProducer->query(what, value);
+}
+
+status_t MonitoredProducer::connect(const sp<IBinder>& token, int api,
+        bool producerControlledByApp, QueueBufferOutput* output) {
+    return mProducer->connect(token, api, producerControlledByApp, output);
+}
+
+status_t MonitoredProducer::disconnect(int api) {
+    return mProducer->disconnect(api);
+}
+
+status_t MonitoredProducer::setSidebandStream(const sp<NativeHandle>& stream) {
+    return mProducer->setSidebandStream(stream);
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h
new file mode 100644
index 0000000..f78be20
--- /dev/null
+++ b/services/surfaceflinger/MonitoredProducer.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 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.
+ */
+
+#ifndef ANDROID_MONITORED_PRODUCER_H
+#define ANDROID_MONITORED_PRODUCER_H
+
+#include <gui/IGraphicBufferProducer.h>
+
+namespace android {
+
+class IBinder;
+class NativeHandle;
+class SurfaceFlinger;
+
+// MonitoredProducer wraps an IGraphicBufferProducer so that SurfaceFlinger will
+// be notified upon its destruction
+class MonitoredProducer : public BnGraphicBufferProducer {
+public:
+    MonitoredProducer(const sp<BnGraphicBufferProducer>& producer,
+            const sp<SurfaceFlinger>& flinger);
+    virtual ~MonitoredProducer();
+
+    // From IGraphicBufferProducer
+    virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);
+    virtual status_t setBufferCount(int bufferCount);
+    virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, bool async,
+            uint32_t w, uint32_t h, uint32_t format, uint32_t usage);
+    virtual status_t detachBuffer(int slot);
+    virtual status_t attachBuffer(int* outSlot,
+            const sp<GraphicBuffer>& buffer);
+    virtual status_t queueBuffer(int slot, const QueueBufferInput& input,
+            QueueBufferOutput* output);
+    virtual void cancelBuffer(int slot, const sp<Fence>& fence);
+    virtual int query(int what, int* value);
+    virtual status_t connect(const sp<IBinder>& token, int api,
+            bool producerControlledByApp, QueueBufferOutput* output);
+    virtual status_t disconnect(int api);
+    virtual status_t setSidebandStream(const sp<NativeHandle>& stream);
+
+private:
+    sp<BnGraphicBufferProducer> mProducer;
+    sp<SurfaceFlinger> mFlinger;
+};
+
+}; // namespace android
+
+#endif // ANDROID_MONITORED_PRODUCER_H
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e05417f..0650d97 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -420,12 +420,17 @@
             createBuiltinDisplayLocked(type);
             wp<IBinder> token = mBuiltinDisplays[i];
 
-            sp<BufferQueue> bq = new BufferQueue(new GraphicBufferAlloc());
-            sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i, bq);
+            sp<IGraphicBufferProducer> producer;
+            sp<IGraphicBufferConsumer> consumer;
+            BufferQueue::createBufferQueue(&producer, &consumer,
+                    new GraphicBufferAlloc());
+
+            sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i,
+                    consumer);
             int32_t hwcId = allocateHwcDisplayId(type);
             sp<DisplayDevice> hw = new DisplayDevice(this,
                     type, hwcId, mHwc->getFormat(hwcId), isSecure, token,
-                    fbs, bq,
+                    fbs, producer,
                     mRenderEngine->getEGLConfig());
             if (i > DisplayDevice::DISPLAY_PRIMARY) {
                 // FIXME: currently we don't get blank/unblank requests
@@ -1152,7 +1157,10 @@
 
                     sp<DisplaySurface> dispSurface;
                     sp<IGraphicBufferProducer> producer;
-                    sp<BufferQueue> bq = new BufferQueue(new GraphicBufferAlloc());
+                    sp<IGraphicBufferProducer> bqProducer;
+                    sp<IGraphicBufferConsumer> bqConsumer;
+                    BufferQueue::createBufferQueue(&bqProducer, &bqConsumer,
+                            new GraphicBufferAlloc());
 
                     int32_t hwcDisplayId = -1;
                     if (state.isVirtualDisplay()) {
@@ -1163,8 +1171,8 @@
 
                             hwcDisplayId = allocateHwcDisplayId(state.type);
                             sp<VirtualDisplaySurface> vds = new VirtualDisplaySurface(
-                                    *mHwc, hwcDisplayId, state.surface, bq,
-                                    state.displayName);
+                                    *mHwc, hwcDisplayId, state.surface,
+                                    bqProducer, bqConsumer, state.displayName);
 
                             dispSurface = vds;
                             if (hwcDisplayId >= 0) {
@@ -1183,8 +1191,9 @@
                         hwcDisplayId = allocateHwcDisplayId(state.type);
                         // for supported (by hwc) displays we provide our
                         // own rendering surface
-                        dispSurface = new FramebufferSurface(*mHwc, state.type, bq);
-                        producer = bq;
+                        dispSurface = new FramebufferSurface(*mHwc, state.type,
+                                bqConsumer);
+                        producer = bqProducer;
                     }
 
                     const wp<IBinder>& display(curr.keyAt(i));
@@ -1978,7 +1987,7 @@
     status_t err = (*outLayer)->setBuffers(w, h, format, flags);
     if (err == NO_ERROR) {
         *handle = (*outLayer)->getHandle();
-        *gbp = (*outLayer)->getBufferQueue();
+        *gbp = (*outLayer)->getProducer();
     }
 
     ALOGE_IF(err, "createNormalLayer() failed (%s)", strerror(-err));
@@ -1991,7 +2000,7 @@
 {
     *outLayer = new LayerDim(this, client, name, w, h, flags);
     *handle = (*outLayer)->getHandle();
-    *gbp = (*outLayer)->getBufferQueue();
+    *gbp = (*outLayer)->getProducer();
     return NO_ERROR;
 }
 
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 9230467..630f4b7 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -138,7 +138,7 @@
     friend class Client;
     friend class DisplayEventConnection;
     friend class Layer;
-    friend class SurfaceTextureLayer;
+    friend class MonitoredProducer;
 
     // This value is specified in number of frames.  Log frame stats at most
     // every half hour.
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.h b/services/surfaceflinger/SurfaceFlingerConsumer.h
index becd5d3..0f1bf35 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.h
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.h
@@ -31,8 +31,9 @@
         virtual void onSidebandStreamChanged() = 0;
     };
 
-    SurfaceFlingerConsumer(const sp<BufferQueue>& bq, uint32_t tex)
-        : GLConsumer(bq, tex, GLConsumer::TEXTURE_EXTERNAL, false)
+    SurfaceFlingerConsumer(const sp<IGraphicBufferConsumer>& consumer,
+            uint32_t tex)
+        : GLConsumer(consumer, tex, GLConsumer::TEXTURE_EXTERNAL, false)
     {}
 
     class BufferRejecter {
diff --git a/services/surfaceflinger/SurfaceTextureLayer.cpp b/services/surfaceflinger/SurfaceTextureLayer.cpp
deleted file mode 100644
index 9d79ce2..0000000
--- a/services/surfaceflinger/SurfaceTextureLayer.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-
-#include "SurfaceFlinger.h"
-#include "SurfaceTextureLayer.h"
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-
-SurfaceTextureLayer::SurfaceTextureLayer(const sp<SurfaceFlinger>& flinger)
-    : BufferQueue(), flinger(flinger) {
-}
-
-SurfaceTextureLayer::~SurfaceTextureLayer() {
-    // remove ourselves from SurfaceFlinger's list. We do this asynchronously
-    // because we don't know where this dtor is called from, it could be
-    // called with the mStateLock held, leading to a dead-lock (it actually
-    // happens).
-    class MessageCleanUpList : public MessageBase {
-        sp<SurfaceFlinger> flinger;
-        wp<IBinder> gbp;
-    public:
-        MessageCleanUpList(const sp<SurfaceFlinger>& flinger, const wp<IBinder>& gbp)
-            : flinger(flinger), gbp(gbp) { }
-        virtual bool handler() {
-            Mutex::Autolock _l(flinger->mStateLock);
-            flinger->mGraphicBufferProducerList.remove(gbp);
-            return true;
-        }
-    };
-    flinger->postMessageAsync(
-            new MessageCleanUpList(flinger, static_cast<BnGraphicBufferProducer*>(this)) );
-}
-
-// ---------------------------------------------------------------------------
-}; // namespace android
diff --git a/services/surfaceflinger/SurfaceTextureLayer.h b/services/surfaceflinger/SurfaceTextureLayer.h
deleted file mode 100644
index 5f5e4ef..0000000
--- a/services/surfaceflinger/SurfaceTextureLayer.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_SURFACE_TEXTURE_LAYER_H
-#define ANDROID_SURFACE_TEXTURE_LAYER_H
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-#include <gui/BufferQueue.h>
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-class Layer;
-class SurfaceFlinger;
-
-/*
- * This is a thin wrapper around BufferQueue, used by the Layer class.
- */
-class SurfaceTextureLayer : public BufferQueue {
-    sp<SurfaceFlinger> flinger;
-public:
-    SurfaceTextureLayer(const sp<SurfaceFlinger>& flinger);
-    virtual ~SurfaceTextureLayer();
-};
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_SURFACE_TEXTURE_LAYER_H