Merge "Fix AppOsManager missing mutex unlock."
diff --git a/cmds/flatland/GLHelper.cpp b/cmds/flatland/GLHelper.cpp
index 89eb95f..3928039 100644
--- a/cmds/flatland/GLHelper.cpp
+++ b/cmds/flatland/GLHelper.cpp
@@ -198,7 +198,7 @@
 
 bool GLHelper::createNamedSurfaceTexture(GLuint name, uint32_t w, uint32_t h,
         sp<GLConsumer>* glConsumer, EGLSurface* surface) {
-    sp<BufferQueue> bq = new BufferQueue(true, mGraphicBufferAlloc);
+    sp<BufferQueue> bq = new BufferQueue(mGraphicBufferAlloc);
     sp<GLConsumer> glc = new GLConsumer(bq, name,
             GL_TEXTURE_EXTERNAL_OES, false);
     glc->setDefaultBufferSize(w, h);
diff --git a/cmds/inputflinger/Android.mk b/cmds/inputflinger/Android.mk
deleted file mode 100644
index b44de44..0000000
--- a/cmds/inputflinger/Android.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright (C) 2013 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.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	main.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-	libbinder \
-	libinputflinger \
-	libutils
-
-LOCAL_MODULE := inputflinger
-
-include $(BUILD_EXECUTABLE)
diff --git a/cmds/sensorservice/Android.mk b/cmds/sensorservice/Android.mk
deleted file mode 100644
index 0811be5..0000000
--- a/cmds/sensorservice/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	main_sensorservice.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-	libsensorservice \
-	libbinder \
-	libutils
-
-LOCAL_C_INCLUDES := \
-	$(LOCAL_PATH)/../../services/sensorservice
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_MODULE:= sensorservice
-
-include $(BUILD_EXECUTABLE)
diff --git a/cmds/surfaceflinger/Android.mk b/cmds/surfaceflinger/Android.mk
deleted file mode 100644
index 1df32bb..0000000
--- a/cmds/surfaceflinger/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	main_surfaceflinger.cpp 
-
-LOCAL_SHARED_LIBRARIES := \
-	libsurfaceflinger \
-	libbinder \
-	libutils
-
-LOCAL_C_INCLUDES := \
-	$(LOCAL_PATH)/../../services/surfaceflinger
-
-LOCAL_MODULE:= surfaceflinger
-
-include $(BUILD_EXECUTABLE)
diff --git a/data/etc/android.hardware.nfc.hce.xml b/data/etc/android.hardware.nfc.hce.xml
new file mode 100644
index 0000000..10b96b1
--- /dev/null
+++ b/data/etc/android.hardware.nfc.hce.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+
+<!-- This feature indicates that the device supports host-based
+     NFC card emulation -->
+<permissions>
+    <feature name="android.hardware.nfc.hce" />
+</permissions>
diff --git a/include/gui/BufferItemConsumer.h b/include/gui/BufferItemConsumer.h
index 0af6f8e..9370e81 100644
--- a/include/gui/BufferItemConsumer.h
+++ b/include/gui/BufferItemConsumer.h
@@ -51,9 +51,11 @@
     // the consumer usage flags passed to the graphics allocator. The
     // bufferCount parameter specifies how many buffers can be locked for user
     // access at the same time.
+    // controlledByApp tells whether this consumer is controlled by the
+    // application.
     BufferItemConsumer(const sp<BufferQueue>& bq, uint32_t consumerUsage,
             int bufferCount = BufferQueue::MIN_UNDEQUEUED_BUFFERS,
-            bool synchronousMode = false);
+            bool controlledByApp = false);
 
     virtual ~BufferItemConsumer();
 
diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h
index 0143be3..628678f 100644
--- a/include/gui/BufferQueue.h
+++ b/include/gui/BufferQueue.h
@@ -97,11 +97,9 @@
 
 
     // BufferQueue manages a pool of gralloc memory slots to be used by
-    // producers and consumers. allowSynchronousMode specifies whether or not
-    // synchronous mode can be enabled by the producer. allocator is used to
-    // allocate all the needed gralloc buffers.
-    BufferQueue(bool allowSynchronousMode = true,
-            const sp<IGraphicBufferAlloc>& allocator = NULL);
+    // producers and consumers. allocator is used to allocate all the
+    // needed gralloc buffers.
+    BufferQueue(const sp<IGraphicBufferAlloc>& allocator = NULL);
     virtual ~BufferQueue();
 
     // Query native window attributes.  The "what" values are enumerated in
@@ -169,7 +167,7 @@
     //
     // In both cases, the producer will need to call requestBuffer to get a
     // GraphicBuffer handle for the returned slot.
-    virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence,
+    virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, bool async,
             uint32_t width, uint32_t height, uint32_t format, uint32_t usage);
 
     // queueBuffer returns a filled buffer to the BufferQueue.
@@ -197,15 +195,6 @@
     // will usually be the one obtained from dequeueBuffer.
     virtual void cancelBuffer(int buf, const sp<Fence>& fence);
 
-    // setSynchronousMode sets whether dequeueBuffer is synchronous or
-    // asynchronous. In synchronous mode, dequeueBuffer blocks until
-    // a buffer is available, the currently bound buffer can be dequeued and
-    // queued buffers will be acquired in order.  In asynchronous mode,
-    // a queued buffer may be replaced by a subsequently queued buffer.
-    //
-    // The default mode is asynchronous.
-    virtual status_t setSynchronousMode(bool enabled);
-
     // connect attempts to connect a producer API to the BufferQueue.  This
     // must be called before any other IGraphicBufferProducer methods are
     // called except for getAllocator.  A consumer must already be connected.
@@ -215,7 +204,7 @@
     // 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, QueueBufferOutput* output);
+    virtual status_t connect(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
@@ -234,13 +223,13 @@
     // public facing structure for BufferSlot
     struct BufferItem {
 
-        BufferItem()
-         :
+        BufferItem() :
            mTransform(0),
            mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
            mTimestamp(0),
            mFrameNumber(0),
            mBuf(INVALID_BUFFER_SLOT),
+           mIsDroppable(false),
            mAcquireCalled(false) {
              mCrop.makeInvalid();
         }
@@ -271,6 +260,13 @@
         // mFence is a fence that will signal when the buffer is idle.
         sp<Fence> mFence;
 
+        // mIsDroppable whether this buffer was queued with the
+        // property that it can be replaced by a new buffer for the purpose of
+        // making sure dequeueBuffer() won't block.
+        // i.e.: was the BufferQueue in "mDequeueBufferCannotBlock" when this buffer
+        // was queued.
+        bool mIsDroppable;
+
         // Indicates whether this buffer has been seen by a consumer yet
         bool mAcquireCalled;
     };
@@ -312,9 +308,11 @@
     // consumer may be connected, and when that consumer disconnects the
     // BufferQueue is placed into the "abandoned" state, causing most
     // interactions with the BufferQueue by the producer to fail.
+    // controlledByApp indicates whether the consumer is controlled by
+    // the application.
     //
     // consumer may not be NULL.
-    status_t consumerConnect(const sp<ConsumerListener>& consumer);
+    status_t consumerConnect(const sp<ConsumerListener>& consumer, bool controlledByApp);
 
     // consumerDisconnect disconnects a consumer from the BufferQueue. All
     // buffers will be freed and the BufferQueue is placed in the "abandoned"
@@ -347,10 +345,6 @@
     // fail if a producer is connected to the BufferQueue.
     status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers);
 
-    // isSynchronousMode returns whether the BufferQueue is currently in
-    // synchronous mode.
-    bool isSynchronousMode() const;
-
     // setConsumerName sets the name used in logging
     void setConsumerName(const String8& name);
 
@@ -379,43 +373,35 @@
     // all slots.
     void freeAllBuffersLocked();
 
-    // drainQueueLocked waits for the buffer queue to empty if we're in
-    // synchronous mode, or returns immediately otherwise. It returns NO_INIT
-    // if the BufferQueue is abandoned (consumer disconnected) or disconnected
-    // (producer disconnected) during the call.
-    status_t drainQueueLocked();
-
-    // drainQueueAndFreeBuffersLocked drains the buffer queue if we're in
-    // synchronous mode and free all buffers. In asynchronous mode, all buffers
-    // are freed except the currently queued buffer (if it exists).
-    status_t drainQueueAndFreeBuffersLocked();
-
     // setDefaultMaxBufferCountLocked sets the maximum number of buffer slots
     // that will be used if the producer does not override the buffer slot
     // count.  The count must be between 2 and NUM_BUFFER_SLOTS, inclusive.
     // The initial default is 2.
     status_t setDefaultMaxBufferCountLocked(int count);
 
+    // getMinUndequeuedBufferCount returns the minimum number of buffers
+    // that must remain in a state other than DEQUEUED.
+    // The async parameter tells whether we're in asynchronous mode.
+    int getMinUndequeuedBufferCount(bool async) const;
+
     // getMinBufferCountLocked returns the minimum number of buffers allowed
     // given the current BufferQueue state.
-    int getMinMaxBufferCountLocked() const;
-
-    // getMinUndequeuedBufferCountLocked returns the minimum number of buffers
-    // that must remain in a state other than DEQUEUED.
-    int getMinUndequeuedBufferCountLocked() const;
+    // The async parameter tells whether we're in asynchronous mode.
+    int getMinMaxBufferCountLocked(bool async) const;
 
     // getMaxBufferCountLocked returns the maximum number of buffers that can
     // be allocated at once.  This value depends upon the following member
     // variables:
     //
-    //      mSynchronousMode
+    //      mDequeueBufferCannotBlock
     //      mMaxAcquiredBufferCount
     //      mDefaultMaxBufferCount
     //      mOverrideMaxBufferCount
+    //      async parameter
     //
     // Any time one of these member variables is changed while a producer is
     // connected, mDequeueCondition must be broadcast.
-    int getMaxBufferCountLocked() const;
+    int getMaxBufferCountLocked(bool async) const;
 
     // stillTracking returns true iff the buffer item is still being tracked
     // in one of the slots.
@@ -568,12 +554,14 @@
     // to NULL and is written by consumerConnect and consumerDisconnect.
     sp<ConsumerListener> mConsumerListener;
 
-    // mSynchronousMode whether we're in synchronous mode or not
-    bool mSynchronousMode;
+    // mConsumerControlledByApp whether the connected consumer is controlled by the
+    // application.
+    bool mConsumerControlledByApp;
 
-    // mAllowSynchronousMode whether we allow synchronous mode or not.  Set
-    // when the BufferQueue is created (by the consumer).
-    const bool mAllowSynchronousMode;
+    // mDequeueBufferCannotBlock whether dequeueBuffer() isn't allowed to block.
+    // this flag is set durring connect() when both consumer and producer are controlled
+    // by the application.
+    bool mDequeueBufferCannotBlock;
 
     // mConnectedApi indicates the producer API that is currently connected
     // to this BufferQueue.  It defaults to NO_CONNECTED_API (= 0), and gets
diff --git a/include/gui/ConsumerBase.h b/include/gui/ConsumerBase.h
index 42b84cc..7b58bc5 100644
--- a/include/gui/ConsumerBase.h
+++ b/include/gui/ConsumerBase.h
@@ -87,7 +87,9 @@
 
     // ConsumerBase constructs a new ConsumerBase object to consume image
     // buffers from the given BufferQueue.
-    ConsumerBase(const sp<BufferQueue> &bufferQueue);
+    // The controlledByApp flag indicates that this consumer is under the application's
+    // control.
+    ConsumerBase(const sp<BufferQueue> &bufferQueue, bool controlledByApp = false);
 
     // onLastStrongRef gets called by RefBase just before the dtor of the most
     // derived class.  It is used to clean up the buffers so that ConsumerBase
diff --git a/include/gui/CpuConsumer.h b/include/gui/CpuConsumer.h
index 5f1e369..2890350 100644
--- a/include/gui/CpuConsumer.h
+++ b/include/gui/CpuConsumer.h
@@ -67,7 +67,7 @@
     // Create a new CPU consumer. The maxLockedBuffers parameter specifies
     // how many buffers can be locked for user access at the same time.
     CpuConsumer(const sp<BufferQueue>& bq,
-            uint32_t maxLockedBuffers, bool synchronousMode = true);
+            uint32_t maxLockedBuffers, bool controlledByApp = false);
 
     virtual ~CpuConsumer();
 
diff --git a/include/gui/DummyConsumer.h b/include/gui/DummyConsumer.h
deleted file mode 100644
index 08e8ec8..0000000
--- a/include/gui/DummyConsumer.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2012 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_GUI_DUMMYCONSUMER_H
-#define ANDROID_GUI_DUMMYCONSUMER_H
-
-#include <gui/BufferQueue.h>
-
-namespace android {
-// ----------------------------------------------------------------------------
-
-
-// The DummyConsumer does not keep a reference to BufferQueue
-// unlike GLConsumer.  This prevents a circular reference from
-// forming without having to use a ProxyConsumerListener
-class DummyConsumer : public BufferQueue::ConsumerListener {
-public:
-    DummyConsumer();
-    virtual ~DummyConsumer();
-protected:
-
-    // Implementation of the BufferQueue::ConsumerListener interface.  These
-    // calls are used to notify the GLConsumer of asynchronous events in the
-    // BufferQueue.
-    virtual void onFrameAvailable();
-    virtual void onBuffersReleased();
-
-};
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_GUI_DUMMYCONSUMER_H
diff --git a/include/gui/GLConsumer.h b/include/gui/GLConsumer.h
index 65544bd..1df5b42 100644
--- a/include/gui/GLConsumer.h
+++ b/include/gui/GLConsumer.h
@@ -87,7 +87,7 @@
     // requirement that either of these methods be called.
     GLConsumer(const sp<BufferQueue>& bq,
             GLuint tex, GLenum texTarget = GL_TEXTURE_EXTERNAL_OES,
-            bool useFenceSync = true);
+            bool useFenceSync = true, bool isControlledByApp = false);
 
     // updateTexImage acquires the most recently queued buffer, and sets the
     // image contents of the target texture to it.
@@ -177,10 +177,6 @@
     // current texture buffer.
     status_t doGLFenceWait() const;
 
-    // isSynchronousMode returns whether the GLConsumer is currently in
-    // synchronous mode.
-    bool isSynchronousMode() const;
-
     // set the name of the GLConsumer that will be used to identify it in
     // log messages.
     void setName(const String8& name);
@@ -190,7 +186,6 @@
     status_t setDefaultBufferFormat(uint32_t defaultFormat);
     status_t setConsumerUsageBits(uint32_t usage);
     status_t setTransformHint(uint32_t hint);
-    virtual status_t setSynchronousMode(bool enabled);
 
     // getBufferQueue returns the BufferQueue object to which this
     // GLConsumer is connected.
diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h
index 29c7ff3..9677962 100644
--- a/include/gui/IGraphicBufferProducer.h
+++ b/include/gui/IGraphicBufferProducer.h
@@ -84,7 +84,10 @@
     // the buffer. The contents of the buffer must not be overwritten until the
     // fence signals. If the fence is NULL, the buffer may be written
     // immediately.
-    virtual status_t dequeueBuffer(int *slot, sp<Fence>* fence,
+    //
+    // The async parameter sets whether we're in asynchrnous mode for this
+    // deququeBuffer() call.
+    virtual status_t dequeueBuffer(int *slot, sp<Fence>* fence, bool async,
             uint32_t w, uint32_t h, uint32_t format, uint32_t usage) = 0;
 
     // queueBuffer indicates that the client has finished filling in the
@@ -96,6 +99,8 @@
     // must be monotonically increasing. Its other properties (zero point, etc)
     // are client-dependent, and should be documented by the client.
     //
+    // The async parameter sets whether we're queuing a buffer in asynchronous mode.
+    //
     // outWidth, outHeight and outTransform are filled with the default width
     // and height of the window and current transform applied to buffers,
     // respectively.
@@ -103,17 +108,18 @@
     struct QueueBufferInput : public Flattenable {
         inline QueueBufferInput(const Parcel& parcel);
         inline QueueBufferInput(int64_t timestamp,
-                const Rect& crop, int scalingMode, uint32_t transform,
-                sp<Fence> fence)
+                const Rect& crop, int scalingMode, uint32_t transform, bool async,
+                const sp<Fence>& fence)
         : timestamp(timestamp), crop(crop), scalingMode(scalingMode),
-          transform(transform), fence(fence) { }
+          transform(transform), async(async), fence(fence) { }
         inline void deflate(int64_t* outTimestamp, Rect* outCrop,
-                int* outScalingMode, uint32_t* outTransform,
+                int* outScalingMode, uint32_t* outTransform, bool* outAsync,
                 sp<Fence>* outFence) const {
             *outTimestamp = timestamp;
             *outCrop = crop;
             *outScalingMode = scalingMode;
             *outTransform = transform;
+            *outAsync = bool(async);
             *outFence = fence;
         }
 
@@ -130,6 +136,7 @@
         Rect crop;
         int scalingMode;
         uint32_t transform;
+        int async;
         sp<Fence> fence;
     };
 
@@ -171,13 +178,6 @@
     // 'what' tokens allowed are that of android_natives.h
     virtual int query(int what, int* value) = 0;
 
-    // setSynchronousMode set whether dequeueBuffer is synchronous or
-    // asynchronous. In synchronous mode, dequeueBuffer blocks until
-    // a buffer is available, the currently bound buffer can be dequeued and
-    // queued buffers will be retired in order.
-    // The default mode is asynchronous.
-    virtual status_t setSynchronousMode(bool enabled) = 0;
-
     // connect attempts to connect a client API to the IGraphicBufferProducer.
     // This must be called before any other IGraphicBufferProducer methods are
     // called except for getAllocator.
@@ -188,7 +188,7 @@
     // 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, QueueBufferOutput* output) = 0;
+    virtual status_t connect(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/include/gui/Surface.h b/include/gui/Surface.h
index c25847c..2f7406e 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -61,8 +61,11 @@
      * However, once a Surface is connected, it'll prevent other Surfaces
      * referring to the same IGraphicBufferProducer to become connected and
      * therefore prevent them to be used as actual producers of buffers.
+     *
+     * the controlledByApp flag indicates that this Surface (producer) is
+     * controlled by the application. This flag is used at connect time.
      */
-    Surface(const sp<IGraphicBufferProducer>& bufferProducer);
+    Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp = false);
 
     /* getIGraphicBufferProducer() returns the IGraphicBufferProducer this
      * Surface was created with. Usually it's an error to use the
@@ -228,6 +231,14 @@
     // window. this is only a hint, actual transform may differ.
     uint32_t mTransformHint;
 
+    // mProducerControlledByApp whether this buffer producer is controlled
+    // by the application
+    bool mProducerControlledByApp;
+
+    // mSwapIntervalZero set if we should drop buffers at queue() time to
+    // achieve an asynchronous swap interval
+    bool mSwapIntervalZero;
+
     // mConsumerRunningBehind whether the consumer is running more than
     // one buffer behind the producer.
     mutable bool mConsumerRunningBehind;
diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h
index 4672ad4..d8256c1 100644
--- a/include/input/InputDevice.h
+++ b/include/input/InputDevice.h
@@ -101,6 +101,9 @@
     inline void setVibrator(bool hasVibrator) { mHasVibrator = hasVibrator; }
     inline bool hasVibrator() const { return mHasVibrator; }
 
+    inline void setButtonUnderPad(bool hasButton) { mHasButtonUnderPad = hasButton; }
+    inline bool hasButtonUnderPad() const { return mHasButtonUnderPad; }
+
     inline const Vector<MotionRange>& getMotionRanges() const {
         return mMotionRanges;
     }
@@ -115,6 +118,7 @@
     int32_t mKeyboardType;
     sp<KeyCharacterMap> mKeyCharacterMap;
     bool mHasVibrator;
+    bool mHasButtonUnderPad;
 
     Vector<MotionRange> mMotionRanges;
 };
diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk
index c080f47..f627e5d 100644
--- a/libs/gui/Android.mk
+++ b/libs/gui/Android.mk
@@ -8,7 +8,6 @@
 	ConsumerBase.cpp \
 	CpuConsumer.cpp \
 	DisplayEventReceiver.cpp \
-	DummyConsumer.cpp \
 	GLConsumer.cpp \
 	GraphicBufferAlloc.cpp \
 	GuiConfig.cpp \
diff --git a/libs/gui/BufferItemConsumer.cpp b/libs/gui/BufferItemConsumer.cpp
index f5b2c7e..0f818b7 100644
--- a/libs/gui/BufferItemConsumer.cpp
+++ b/libs/gui/BufferItemConsumer.cpp
@@ -30,11 +30,10 @@
 namespace android {
 
 BufferItemConsumer::BufferItemConsumer(const sp<BufferQueue>& bq,
-        uint32_t consumerUsage, int bufferCount, bool synchronousMode) :
-    ConsumerBase(bq)
+        uint32_t consumerUsage, int bufferCount, bool controlledByApp) :
+    ConsumerBase(bq, controlledByApp)
 {
     mBufferQueue->setConsumerUsageBits(consumerUsage);
-    mBufferQueue->setSynchronousMode(synchronousMode);
     mBufferQueue->setMaxAcquiredBufferCount(bufferCount);
 }
 
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index 8d4b174..73bd488 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -30,6 +30,7 @@
 
 #include <utils/Log.h>
 #include <utils/Trace.h>
+#include <utils/CallStack.h>
 
 // Macros for including the BufferQueue name in log messages
 #define ST_LOGV(x, ...) ALOGV("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
@@ -63,15 +64,14 @@
     }
 }
 
-BufferQueue::BufferQueue(bool allowSynchronousMode,
-        const sp<IGraphicBufferAlloc>& allocator) :
+BufferQueue::BufferQueue(const sp<IGraphicBufferAlloc>& allocator) :
     mDefaultWidth(1),
     mDefaultHeight(1),
     mMaxAcquiredBufferCount(1),
     mDefaultMaxBufferCount(2),
     mOverrideMaxBufferCount(0),
-    mSynchronousMode(false),
-    mAllowSynchronousMode(allowSynchronousMode),
+    mConsumerControlledByApp(false),
+    mDequeueBufferCannotBlock(false),
     mConnectedApi(NO_CONNECTED_API),
     mAbandoned(false),
     mFrameCounter(0),
@@ -109,11 +109,6 @@
     return NO_ERROR;
 }
 
-bool BufferQueue::isSynchronousMode() const {
-    Mutex::Autolock lock(mMutex);
-    return mSynchronousMode;
-}
-
 void BufferQueue::setConsumerName(const String8& name) {
     Mutex::Autolock lock(mMutex);
     mConsumerName = name;
@@ -156,21 +151,21 @@
         }
 
         // Error out if the user has dequeued buffers
-        int maxBufferCount = getMaxBufferCountLocked();
-        for (int i=0 ; i<maxBufferCount; i++) {
+        for (int i=0 ; i<NUM_BUFFER_SLOTS; i++) {
             if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
                 ST_LOGE("setBufferCount: client owns some buffers");
                 return -EINVAL;
             }
         }
 
-        const int minBufferSlots = getMinMaxBufferCountLocked();
         if (bufferCount == 0) {
             mOverrideMaxBufferCount = 0;
             mDequeueCondition.broadcast();
             return NO_ERROR;
         }
 
+        // fine to assume async to false before we're setting the buffer count
+        const int minBufferSlots = getMinMaxBufferCountLocked(false);
         if (bufferCount < minBufferSlots) {
             ST_LOGE("setBufferCount: requested buffer count (%d) is less than "
                     "minimum (%d)", bufferCount, minBufferSlots);
@@ -215,7 +210,7 @@
         value = mDefaultBufferFormat;
         break;
     case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
-        value = getMinUndequeuedBufferCountLocked();
+        value = getMinUndequeuedBufferCount(false);
         break;
     case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
         value = (mQueue.size() >= 2);
@@ -235,15 +230,11 @@
         ST_LOGE("requestBuffer: BufferQueue has been abandoned!");
         return NO_INIT;
     }
-    int maxBufferCount = getMaxBufferCountLocked();
-    if (slot < 0 || maxBufferCount <= slot) {
+    if (slot < 0 || slot >= NUM_BUFFER_SLOTS) {
         ST_LOGE("requestBuffer: slot index out of range [0, %d]: %d",
-                maxBufferCount, slot);
+                NUM_BUFFER_SLOTS, slot);
         return BAD_VALUE;
     } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
-        // XXX: I vaguely recall there was some reason this can be valid, but
-        // for the life of me I can't recall under what circumstances that's
-        // the case.
         ST_LOGE("requestBuffer: slot %d is not owned by the client (state=%d)",
                 slot, mSlots[slot].mBufferState);
         return BAD_VALUE;
@@ -253,7 +244,7 @@
     return NO_ERROR;
 }
 
-status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence,
+status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence, bool async,
         uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
     ATRACE_CALL();
     ST_LOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage);
@@ -285,7 +276,16 @@
                 return NO_INIT;
             }
 
-            const int maxBufferCount = getMaxBufferCountLocked();
+            const int maxBufferCount = getMaxBufferCountLocked(async);
+            if (async && mOverrideMaxBufferCount) {
+                // FIXME: some drivers are manually setting the buffer-count (which they
+                // shouldn't), so we do this extra test here to handle that case.
+                // This is TEMPORARY, until we get this fixed.
+                if (mOverrideMaxBufferCount < maxBufferCount) {
+                    ST_LOGE("dequeueBuffer: async mode is invalid with buffercount override");
+                    return BAD_VALUE;
+                }
+            }
 
             // Free up any buffers that are in slots beyond the max buffer
             // count.
@@ -334,7 +334,7 @@
                 // make sure the client is not trying to dequeue more buffers
                 // than allowed.
                 const int newUndequeuedCount = maxBufferCount - (dequeuedCount+1);
-                const int minUndequeuedCount = getMinUndequeuedBufferCountLocked();
+                const int minUndequeuedCount = getMinUndequeuedBufferCount(async);
                 if (newUndequeuedCount < minUndequeuedCount) {
                     ST_LOGE("dequeueBuffer: min undequeued buffer count (%d) "
                             "exceeded (dequeued=%d undequeudCount=%d)",
@@ -348,6 +348,10 @@
             // the max buffer count to change.
             tryAgain = found == INVALID_BUFFER_SLOT;
             if (tryAgain) {
+                if (mDequeueBufferCannotBlock) {
+                    ST_LOGE("dequeueBuffer: would block! returning an error instead.");
+                    return WOULD_BLOCK;
+                }
                 mDequeueCondition.wait(mMutex);
             }
         }
@@ -441,38 +445,6 @@
     return returnFlags;
 }
 
-status_t BufferQueue::setSynchronousMode(bool enabled) {
-    ATRACE_CALL();
-    ST_LOGV("setSynchronousMode: enabled=%d", enabled);
-    Mutex::Autolock lock(mMutex);
-
-    if (mAbandoned) {
-        ST_LOGE("setSynchronousMode: BufferQueue has been abandoned!");
-        return NO_INIT;
-    }
-
-    status_t err = OK;
-    if (!mAllowSynchronousMode && enabled)
-        return err;
-
-    if (!enabled) {
-        // going to asynchronous mode, drain the queue
-        err = drainQueueLocked();
-        if (err != NO_ERROR)
-            return err;
-    }
-
-    if (mSynchronousMode != enabled) {
-        // - if we're going to asynchronous mode, the queue is guaranteed to be
-        // empty here
-        // - if the client set the number of buffers, we're guaranteed that
-        // we have at least 3 (because we don't allow less)
-        mSynchronousMode = enabled;
-        mDequeueCondition.broadcast();
-    }
-    return err;
-}
-
 status_t BufferQueue::queueBuffer(int buf,
         const QueueBufferInput& input, QueueBufferOutput* output) {
     ATRACE_CALL();
@@ -482,9 +454,10 @@
     uint32_t transform;
     int scalingMode;
     int64_t timestamp;
+    bool async;
     sp<Fence> fence;
 
-    input.deflate(&timestamp, &crop, &scalingMode, &transform, &fence);
+    input.deflate(&timestamp, &crop, &scalingMode, &transform, &async, &fence);
 
     if (fence == NULL) {
         ST_LOGE("queueBuffer: fence is NULL");
@@ -511,7 +484,17 @@
             ST_LOGE("queueBuffer: BufferQueue has been abandoned!");
             return NO_INIT;
         }
-        int maxBufferCount = getMaxBufferCountLocked();
+
+        const int maxBufferCount = getMaxBufferCountLocked(async);
+        if (async && mOverrideMaxBufferCount) {
+            // FIXME: some drivers are manually setting the buffer-count (which they
+            // shouldn't), so we do this extra test here to handle that case.
+            // This is TEMPORARY, until we get this fixed.
+            if (mOverrideMaxBufferCount < maxBufferCount) {
+                ST_LOGE("queueBuffer: async mode is invalid with buffercount override");
+                return BAD_VALUE;
+            }
+        }
         if (buf < 0 || buf >= maxBufferCount) {
             ST_LOGE("queueBuffer: slot index out of range [0, %d]: %d",
                     maxBufferCount, buf);
@@ -557,31 +540,30 @@
         item.mFrameNumber = mFrameCounter;
         item.mBuf = buf;
         item.mFence = fence;
+        item.mIsDroppable = mDequeueBufferCannotBlock || async;
 
-        if (mSynchronousMode) {
-            // In synchronous mode we queue all buffers in a FIFO.
+        if (mQueue.empty()) {
+            // when the queue is empty, we can ignore "mDequeueBufferCannotBlock", and
+            // simply queue this buffer.
             mQueue.push_back(item);
-
-            // Synchronous mode always signals that an additional frame should
-            // be consumed.
             listener = mConsumerListener;
         } else {
-            // In asynchronous mode we only keep the most recent buffer.
-            if (mQueue.empty()) {
-                mQueue.push_back(item);
-
-                // Asynchronous mode only signals that a frame should be
-                // consumed if no previous frame was pending. If a frame were
-                // pending then the consumer would have already been notified.
-                listener = mConsumerListener;
-            } else {
-                Fifo::iterator front(mQueue.begin());
+            // when the queue is not empty, we need to look at the front buffer
+            // state and see if we need to replace it.
+            Fifo::iterator front(mQueue.begin());
+            if (front->mIsDroppable) {
                 // buffer slot currently queued is marked free if still tracked
                 if (stillTracking(front)) {
                     mSlots[front->mBuf].mBufferState = BufferSlot::FREE;
+                    // reset the frame number of the freed buffer so that it is the first in
+                    // line to be dequeued again.
+                    mSlots[front->mBuf].mFrameNumber = 0;
                 }
-                // and we record the new buffer index in the queued list
+                // and we record the new buffer in the queued list
                 *front = item;
+            } else {
+                mQueue.push_back(item);
+                listener = mConsumerListener;
             }
         }
 
@@ -611,10 +593,9 @@
         return;
     }
 
-    int maxBufferCount = getMaxBufferCountLocked();
-    if (buf < 0 || buf >= maxBufferCount) {
+    if (buf < 0 || buf >= NUM_BUFFER_SLOTS) {
         ST_LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
-                maxBufferCount, buf);
+                NUM_BUFFER_SLOTS, buf);
         return;
     } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
         ST_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
@@ -630,7 +611,7 @@
     mDequeueCondition.broadcast();
 }
 
-status_t BufferQueue::connect(int api, QueueBufferOutput* output) {
+status_t BufferQueue::connect(int api, bool producerControlledByApp, QueueBufferOutput* output) {
     ATRACE_CALL();
     ST_LOGV("connect: api=%d", api);
     Mutex::Autolock lock(mMutex);
@@ -667,6 +648,7 @@
     }
 
     mBufferHasBeenQueued = false;
+    mDequeueBufferCannotBlock = mConsumerControlledByApp && producerControlledByApp;
 
     return err;
 }
@@ -693,7 +675,7 @@
             case NATIVE_WINDOW_API_MEDIA:
             case NATIVE_WINDOW_API_CAMERA:
                 if (mConnectedApi == api) {
-                    drainQueueAndFreeBuffersLocked();
+                    freeAllBuffersLocked();
                     mConnectedApi = NO_CONNECTED_API;
                     mDequeueCondition.broadcast();
                     listener = mConsumerListener;
@@ -739,12 +721,11 @@
         fifoSize++;
     }
 
-    int maxBufferCount = getMaxBufferCountLocked();
 
     result.appendFormat(
-            "%s-BufferQueue maxBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
+            "%s-BufferQueue mMaxAcquiredBufferCount=%d, mDequeueBufferCannotBlock=%d, default-size=[%dx%d], "
             "default-format=%d, transform-hint=%02x, FIFO(%d)={%s}\n",
-            prefix, maxBufferCount, mSynchronousMode, mDefaultWidth,
+            prefix, mMaxAcquiredBufferCount, mDequeueBufferCannotBlock, mDefaultWidth,
             mDefaultHeight, mDefaultBufferFormat, mTransformHint,
             fifoSize, fifo.string());
 
@@ -760,16 +741,25 @@
         }
     } stateName;
 
+    // just trim the free buffers to not spam the dump
+    int maxBufferCount = 0;
+    for (int i=NUM_BUFFER_SLOTS-1 ; i>=0 ; i--) {
+        const BufferSlot& slot(mSlots[i]);
+        if ((slot.mBufferState != BufferSlot::FREE) || (slot.mGraphicBuffer != NULL)) {
+            maxBufferCount = i+1;
+            break;
+        }
+    }
+
     for (int i=0 ; i<maxBufferCount ; i++) {
         const BufferSlot& slot(mSlots[i]);
+        const sp<GraphicBuffer>& buf(slot.mGraphicBuffer);
         result.appendFormat(
             "%s%s[%02d:%p] state=%-8s",
-                prefix, (slot.mBufferState == BufferSlot::ACQUIRED)?">":" ", i,
-                slot.mGraphicBuffer.get(),
+                prefix, (slot.mBufferState == BufferSlot::ACQUIRED)?">":" ", i, buf.get(),
                 stateName(slot.mBufferState)
         );
 
-        const sp<GraphicBuffer>& buf(slot.mGraphicBuffer);
         if (buf != NULL) {
             result.appendFormat(
                     ", %p [%4ux%4u:%4u,%3X]",
@@ -799,8 +789,6 @@
 }
 
 void BufferQueue::freeAllBuffersLocked() {
-    ALOGD_IF(!mQueue.isEmpty(),
-            "freeAllBuffersLocked called with non-empty mQueue");
     mBufferHasBeenQueued = false;
     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
         freeBufferLocked(i);
@@ -950,7 +938,8 @@
     return NO_ERROR;
 }
 
-status_t BufferQueue::consumerConnect(const sp<ConsumerListener>& consumerListener) {
+status_t BufferQueue::consumerConnect(const sp<ConsumerListener>& consumerListener,
+        bool controlledByApp) {
     ST_LOGV("consumerConnect");
     Mutex::Autolock lock(mMutex);
 
@@ -964,6 +953,7 @@
     }
 
     mConsumerListener = consumerListener;
+    mConsumerControlledByApp = controlledByApp;
 
     return NO_ERROR;
 }
@@ -1053,40 +1043,17 @@
     return NO_ERROR;
 }
 
-status_t BufferQueue::drainQueueLocked() {
-    while (mSynchronousMode && mQueue.size() > 1) {
-        mDequeueCondition.wait(mMutex);
-        if (mAbandoned) {
-            ST_LOGE("drainQueueLocked: BufferQueue has been abandoned!");
-            return NO_INIT;
-        }
-        if (mConnectedApi == NO_CONNECTED_API) {
-            ST_LOGE("drainQueueLocked: BufferQueue is not connected!");
-            return NO_INIT;
-        }
-    }
-    return NO_ERROR;
+int BufferQueue::getMinUndequeuedBufferCount(bool async) const {
+    return (mDequeueBufferCannotBlock || async) ?
+                mMaxAcquiredBufferCount+1 : mMaxAcquiredBufferCount;
 }
 
-status_t BufferQueue::drainQueueAndFreeBuffersLocked() {
-    status_t err = drainQueueLocked();
-    if (err == NO_ERROR) {
-        freeAllBuffersLocked();
-    }
-    return err;
+int BufferQueue::getMinMaxBufferCountLocked(bool async) const {
+    return getMinUndequeuedBufferCount(async) + 1;
 }
 
-int BufferQueue::getMinMaxBufferCountLocked() const {
-    return getMinUndequeuedBufferCountLocked() + 1;
-}
-
-int BufferQueue::getMinUndequeuedBufferCountLocked() const {
-    return mSynchronousMode ? mMaxAcquiredBufferCount :
-            mMaxAcquiredBufferCount + 1;
-}
-
-int BufferQueue::getMaxBufferCountLocked() const {
-    int minMaxBufferCount = getMinMaxBufferCountLocked();
+int BufferQueue::getMaxBufferCountLocked(bool async) const {
+    int minMaxBufferCount = getMinMaxBufferCountLocked(async);
 
     int maxBufferCount = mDefaultMaxBufferCount;
     if (maxBufferCount < minMaxBufferCount) {
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index deb2646..cd94ce1 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -51,7 +51,7 @@
     return android_atomic_inc(&globalCounter);
 }
 
-ConsumerBase::ConsumerBase(const sp<BufferQueue>& bufferQueue) :
+ConsumerBase::ConsumerBase(const sp<BufferQueue>& bufferQueue, bool controlledByApp) :
         mAbandoned(false),
         mBufferQueue(bufferQueue) {
     // Choose a name using the PID and a process-unique ID.
@@ -66,7 +66,7 @@
     listener = static_cast<BufferQueue::ConsumerListener*>(this);
     proxy = new BufferQueue::ProxyConsumerListener(listener);
 
-    status_t err = mBufferQueue->consumerConnect(proxy);
+    status_t err = mBufferQueue->consumerConnect(proxy, controlledByApp);
     if (err != NO_ERROR) {
         CB_LOGE("ConsumerBase: error connecting to BufferQueue: %s (%d)",
                 strerror(-err), err);
diff --git a/libs/gui/CpuConsumer.cpp b/libs/gui/CpuConsumer.cpp
index adddfc2..b8c00af 100644
--- a/libs/gui/CpuConsumer.cpp
+++ b/libs/gui/CpuConsumer.cpp
@@ -31,15 +31,14 @@
 namespace android {
 
 CpuConsumer::CpuConsumer(const sp<BufferQueue>& bq,
-        uint32_t maxLockedBuffers, bool synchronousMode) :
-    ConsumerBase(bq),
+        uint32_t maxLockedBuffers, bool controlledByApp) :
+    ConsumerBase(bq, controlledByApp),
     mMaxLockedBuffers(maxLockedBuffers),
     mCurrentLockedBuffers(0)
 {
     // Create tracking entries for locked buffers
     mAcquiredBuffers.insertAt(0, maxLockedBuffers);
 
-    mBufferQueue->setSynchronousMode(synchronousMode);
     mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_SW_READ_OFTEN);
     mBufferQueue->setMaxAcquiredBufferCount(maxLockedBuffers);
 }
diff --git a/libs/gui/DummyConsumer.cpp b/libs/gui/DummyConsumer.cpp
deleted file mode 100644
index be47e0e..0000000
--- a/libs/gui/DummyConsumer.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "DummyConsumer"
-// #define LOG_NDEBUG 0
-
-#include <gui/DummyConsumer.h>
-
-#include <utils/Log.h>
-#include <utils/String8.h>
-
-namespace android {
-
-DummyConsumer::DummyConsumer() {
-    ALOGV("DummyConsumer");
-}
-
-DummyConsumer::~DummyConsumer() {
-    ALOGV("~DummyConsumer");
-}
-
-void DummyConsumer::onFrameAvailable() {
-    ALOGV("onFrameAvailable");
-}
-
-void DummyConsumer::onBuffersReleased() {
-    ALOGV("onBuffersReleased");
-}
-
-}; // namespace android
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 07f27c3..92f07eb 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -79,8 +79,8 @@
 
 
 GLConsumer::GLConsumer(const sp<BufferQueue>& bq, GLuint tex,
-        GLenum texTarget, bool useFenceSync) :
-    ConsumerBase(bq),
+        GLenum texTarget, bool useFenceSync, bool isControlledByApp) :
+    ConsumerBase(bq, isControlledByApp),
     mCurrentTransform(0),
     mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
     mCurrentFence(Fence::NO_FENCE),
@@ -844,11 +844,6 @@
     return NO_ERROR;
 }
 
-bool GLConsumer::isSynchronousMode() const {
-    Mutex::Autolock lock(mMutex);
-    return mBufferQueue->isSynchronousMode();
-}
-
 void GLConsumer::freeBufferLocked(int slotIndex) {
     ST_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
     if (slotIndex == mCurrentTexture) {
@@ -891,13 +886,6 @@
     return mBufferQueue->setTransformHint(hint);
 }
 
-// Used for refactoring BufferQueue from GLConsumer
-// Should not be in final interface once users of GLConsumer are clean up.
-status_t GLConsumer::setSynchronousMode(bool enabled) {
-    Mutex::Autolock lock(mMutex);
-    return mBufferQueue->setSynchronousMode(enabled);
-}
-
 void GLConsumer::dumpLocked(String8& result, const char* prefix) const
 {
     result.appendFormat(
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 63d7628..2e561df 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -37,7 +37,6 @@
     QUEUE_BUFFER,
     CANCEL_BUFFER,
     QUERY,
-    SET_SYNCHRONOUS_MODE,
     CONNECT,
     DISCONNECT,
 };
@@ -81,10 +80,11 @@
         return result;
     }
 
-    virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence,
+    virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, bool async,
             uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
         Parcel data, reply;
         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
+        data.writeInt32(async);
         data.writeInt32(w);
         data.writeInt32(h);
         data.writeInt32(format);
@@ -142,22 +142,11 @@
         return result;
     }
 
-    virtual status_t setSynchronousMode(bool enabled) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
-        data.writeInt32(enabled);
-        status_t result = remote()->transact(SET_SYNCHRONOUS_MODE, data, &reply);
-        if (result != NO_ERROR) {
-            return result;
-        }
-        result = reply.readInt32();
-        return result;
-    }
-
-    virtual status_t connect(int api, QueueBufferOutput* output) {
+    virtual status_t connect(int api, bool producerControlledByApp, QueueBufferOutput* output) {
         Parcel data, reply;
         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
         data.writeInt32(api);
+        data.writeInt32(producerControlledByApp);
         status_t result = remote()->transact(CONNECT, data, &reply);
         if (result != NO_ERROR) {
             return result;
@@ -209,13 +198,14 @@
         } break;
         case DEQUEUE_BUFFER: {
             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
+            bool async      = data.readInt32();
             uint32_t w      = data.readInt32();
             uint32_t h      = data.readInt32();
             uint32_t format = data.readInt32();
             uint32_t usage  = data.readInt32();
             int buf;
             sp<Fence> fence;
-            int result = dequeueBuffer(&buf, &fence, w, h, format, usage);
+            int result = dequeueBuffer(&buf, &fence, async, w, h, format, usage);
             reply->writeInt32(buf);
             reply->writeInt32(fence != NULL);
             if (fence != NULL) {
@@ -252,20 +242,14 @@
             reply->writeInt32(res);
             return NO_ERROR;
         } break;
-        case SET_SYNCHRONOUS_MODE: {
-            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
-            bool enabled = data.readInt32();
-            status_t res = setSynchronousMode(enabled);
-            reply->writeInt32(res);
-            return NO_ERROR;
-        } break;
         case CONNECT: {
             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
             int api = data.readInt32();
+            bool producerControlledByApp = data.readInt32();
             QueueBufferOutput* const output =
                     reinterpret_cast<QueueBufferOutput *>(
                             reply->writeInplace(sizeof(QueueBufferOutput)));
-            status_t res = connect(api, output);
+            status_t res = connect(api, producerControlledByApp, output);
             reply->writeInt32(res);
             return NO_ERROR;
         } break;
@@ -292,6 +276,7 @@
          + sizeof(crop)
          + sizeof(scalingMode)
          + sizeof(transform)
+         + sizeof(async)
          + fence->getFlattenedSize();
 }
 
@@ -309,6 +294,7 @@
     memcpy(p, &crop,        sizeof(crop));        p += sizeof(crop);
     memcpy(p, &scalingMode, sizeof(scalingMode)); p += sizeof(scalingMode);
     memcpy(p, &transform,   sizeof(transform));   p += sizeof(transform);
+    memcpy(p, &async,       sizeof(async));       p += sizeof(async);
     err = fence->flatten(p, size - (p - (char*)buffer), fds, count);
     return err;
 }
@@ -322,6 +308,7 @@
     memcpy(&crop,        p, sizeof(crop));        p += sizeof(crop);
     memcpy(&scalingMode, p, sizeof(scalingMode)); p += sizeof(scalingMode);
     memcpy(&transform,   p, sizeof(transform));   p += sizeof(transform);
+    memcpy(&async,       p, sizeof(async));       p += sizeof(async);
     fence = new Fence();
     err = fence->unflatten(p, size - (p - (const char*)buffer), fds, count);
     return err;
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index a616c1e..998ea8a 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -37,7 +37,8 @@
 namespace android {
 
 Surface::Surface(
-        const sp<IGraphicBufferProducer>& bufferProducer)
+        const sp<IGraphicBufferProducer>& bufferProducer,
+        bool controlledByApp)
     : mGraphicBufferProducer(bufferProducer)
 {
     // Initialize the ANativeWindow function pointers.
@@ -71,6 +72,8 @@
     mTransformHint = 0;
     mConsumerRunningBehind = false;
     mConnectedToCpu = false;
+    mProducerControlledByApp = true;
+    mSwapIntervalZero = false;
 }
 
 Surface::~Surface() {
@@ -160,7 +163,6 @@
     // EGL specification states:
     //  interval is silently clamped to minimum and maximum implementation
     //  dependent values before being stored.
-    // Although we don't have to, we apply the same logic here.
 
     if (interval < minSwapInterval)
         interval = minSwapInterval;
@@ -168,9 +170,9 @@
     if (interval > maxSwapInterval)
         interval = maxSwapInterval;
 
-    status_t res = mGraphicBufferProducer->setSynchronousMode(interval ? true : false);
+    mSwapIntervalZero = (interval == 0);
 
-    return res;
+    return NO_ERROR;
 }
 
 int Surface::dequeueBuffer(android_native_buffer_t** buffer,
@@ -182,7 +184,7 @@
     int reqW = mReqWidth ? mReqWidth : mUserWidth;
     int reqH = mReqHeight ? mReqHeight : mUserHeight;
     sp<Fence> fence;
-    status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence,
+    status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, mSwapIntervalZero,
             reqW, reqH, mReqFormat, mReqUsage);
     if (result < 0) {
         ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer(%d, %d, %d, %d)"
@@ -278,7 +280,7 @@
     sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
     IGraphicBufferProducer::QueueBufferOutput output;
     IGraphicBufferProducer::QueueBufferInput input(timestamp, crop, mScalingMode,
-            mTransform, fence);
+            mTransform, mSwapIntervalZero, fence);
     status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);
     if (err != OK)  {
         ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
@@ -486,7 +488,7 @@
     ALOGV("Surface::connect");
     Mutex::Autolock lock(mMutex);
     IGraphicBufferProducer::QueueBufferOutput output;
-    int err = mGraphicBufferProducer->connect(api, &output);
+    int err = mGraphicBufferProducer->connect(api, mProducerControlledByApp, &output);
     if (err == NO_ERROR) {
         uint32_t numPendingBuffers = 0;
         output.deflate(&mDefaultWidth, &mDefaultHeight, &mTransformHint,
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 9682987..b691fc1 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -62,21 +62,21 @@
 
 TEST_F(BufferQueueTest, AcquireBuffer_ExceedsMaxAcquireCount_Fails) {
     sp<DummyConsumer> dc(new DummyConsumer);
-    mBQ->consumerConnect(dc);
+    mBQ->consumerConnect(dc, false);
     IGraphicBufferProducer::QueueBufferOutput qbo;
-    mBQ->connect(NATIVE_WINDOW_API_CPU, &qbo);
+    mBQ->connect(NATIVE_WINDOW_API_CPU, false, &qbo);
     mBQ->setBufferCount(4);
 
     int slot;
     sp<Fence> fence;
     sp<GraphicBuffer> buf;
     IGraphicBufferProducer::QueueBufferInput qbi(0, Rect(0, 0, 1, 1),
-            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
+            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE);
     BufferQueue::BufferItem item;
 
     for (int i = 0; i < 2; i++) {
         ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-                mBQ->dequeueBuffer(&slot, &fence, 1, 1, 0,
+                mBQ->dequeueBuffer(&slot, &fence, false, 1, 1, 0,
                     GRALLOC_USAGE_SW_READ_OFTEN));
         ASSERT_EQ(OK, mBQ->requestBuffer(slot, &buf));
         ASSERT_EQ(OK, mBQ->queueBuffer(slot, qbi, &qbo));
@@ -84,7 +84,7 @@
     }
 
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mBQ->dequeueBuffer(&slot, &fence, 1, 1, 0,
+            mBQ->dequeueBuffer(&slot, &fence, false, 1, 1, 0,
                 GRALLOC_USAGE_SW_READ_OFTEN));
     ASSERT_EQ(OK, mBQ->requestBuffer(slot, &buf));
     ASSERT_EQ(OK, mBQ->queueBuffer(slot, qbi, &qbo));
@@ -95,7 +95,7 @@
 
 TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithIllegalValues_ReturnsError) {
     sp<DummyConsumer> dc(new DummyConsumer);
-    mBQ->consumerConnect(dc);
+    mBQ->consumerConnect(dc, false);
 
     ASSERT_EQ(BAD_VALUE, mBQ->setMaxAcquiredBufferCount(0));
     ASSERT_EQ(BAD_VALUE, mBQ->setMaxAcquiredBufferCount(-3));
@@ -106,7 +106,7 @@
 
 TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithLegalValues_Succeeds) {
     sp<DummyConsumer> dc(new DummyConsumer);
-    mBQ->consumerConnect(dc);
+    mBQ->consumerConnect(dc, false);
 
     ASSERT_EQ(OK, mBQ->setMaxAcquiredBufferCount(1));
     ASSERT_EQ(OK, mBQ->setMaxAcquiredBufferCount(2));
diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp
index 46bcb22..158c94b 100644
--- a/libs/gui/tests/SurfaceTextureClient_test.cpp
+++ b/libs/gui/tests/SurfaceTextureClient_test.cpp
@@ -338,7 +338,7 @@
 
 TEST_F(SurfaceTextureClientTest, SurfaceTextureTooManyUpdateTexImage) {
     android_native_buffer_t* buf[3];
-    ASSERT_EQ(OK, mST->setSynchronousMode(false));
+    ASSERT_EQ(OK, mANW->setSwapInterval(mANW.get(), 0));
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
 
     ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
@@ -346,7 +346,7 @@
     EXPECT_EQ(OK, mST->updateTexImage());
     EXPECT_EQ(OK, mST->updateTexImage());
 
-    ASSERT_EQ(OK, mST->setSynchronousMode(true));
+    ASSERT_EQ(OK, mANW->setSwapInterval(mANW.get(), 1));
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
 
     ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
@@ -361,7 +361,6 @@
 
 TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeSlowRetire) {
     android_native_buffer_t* buf[3];
-    ASSERT_EQ(OK, mST->setSynchronousMode(true));
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
     ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
     ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
@@ -382,7 +381,6 @@
 
 TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeFastRetire) {
     android_native_buffer_t* buf[3];
-    ASSERT_EQ(OK, mST->setSynchronousMode(true));
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
     ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
     ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
@@ -403,7 +401,6 @@
 
 TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeDQQR) {
     android_native_buffer_t* buf[3];
-    ASSERT_EQ(OK, mST->setSynchronousMode(true));
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
 
     ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
@@ -429,7 +426,6 @@
 TEST_F(SurfaceTextureClientTest, DISABLED_SurfaceTextureSyncModeDequeueCurrent) {
     android_native_buffer_t* buf[3];
     android_native_buffer_t* firstBuf;
-    ASSERT_EQ(OK, mST->setSynchronousMode(true));
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
     ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &firstBuf));
     ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), firstBuf, -1));
@@ -449,7 +445,6 @@
 
 TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeMinUndequeued) {
     android_native_buffer_t* buf[3];
-    ASSERT_EQ(OK, mST->setSynchronousMode(true));
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
 
     // We should be able to dequeue all the buffers before we've queued mANWy.
@@ -528,7 +523,6 @@
     };
 
     android_native_buffer_t* buf[3];
-    ASSERT_EQ(OK, mST->setSynchronousMode(true));
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
     // dequeue/queue/update so we have a current buffer
     ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp
index d97521a..e6d87db 100644
--- a/libs/gui/tests/SurfaceTexture_test.cpp
+++ b/libs/gui/tests/SurfaceTexture_test.cpp
@@ -944,7 +944,6 @@
     enum { texHeight = 16 };
     enum { numFrames = 1024 };
 
-    ASSERT_EQ(NO_ERROR, mST->setSynchronousMode(true));
     ASSERT_EQ(NO_ERROR, mST->setDefaultMaxBufferCount(2));
     ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
             texWidth, texHeight, HAL_PIXEL_FORMAT_YV12));
@@ -1211,10 +1210,8 @@
         sp<ANativeWindow> mANW;
     };
 
-    ASSERT_EQ(OK, mST->setSynchronousMode(true));
-
     sp<DisconnectWaiter> dw(new DisconnectWaiter());
-    mST->getBufferQueue()->consumerConnect(dw);
+    mST->getBufferQueue()->consumerConnect(dw, false);
 
 
     sp<Thread> pt(new ProducerThread(mANW));
@@ -1237,8 +1234,6 @@
 // when it is disconnected and reconnected.  Otherwise it will
 // attempt to release a buffer that it does not owned
 TEST_F(SurfaceTextureGLTest, DisconnectClearsCurrentTexture) {
-    ASSERT_EQ(OK, mST->setSynchronousMode(true));
-
     ASSERT_EQ(OK, native_window_api_connect(mANW.get(),
             NATIVE_WINDOW_API_EGL));
 
@@ -1258,8 +1253,6 @@
     ASSERT_EQ(OK, native_window_api_connect(mANW.get(),
             NATIVE_WINDOW_API_EGL));
 
-    ASSERT_EQ(OK, mST->setSynchronousMode(true));
-
     EXPECT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb));
     EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1));
 
@@ -1272,8 +1265,6 @@
 }
 
 TEST_F(SurfaceTextureGLTest, ScaleToWindowMode) {
-    ASSERT_EQ(OK, mST->setSynchronousMode(true));
-
     ASSERT_EQ(OK, native_window_set_scaling_mode(mANW.get(),
         NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW));
 
@@ -1306,8 +1297,6 @@
 // the image such that it has the same aspect ratio as the
 // default buffer size
 TEST_F(SurfaceTextureGLTest, CroppedScalingMode) {
-    ASSERT_EQ(OK, mST->setSynchronousMode(true));
-
     ASSERT_EQ(OK, native_window_set_scaling_mode(mANW.get(),
         NATIVE_WINDOW_SCALING_MODE_SCALE_CROP));
 
@@ -1417,7 +1406,6 @@
         Mutex mMutex;
     };
 
-    ASSERT_EQ(OK, mST->setSynchronousMode(true));
     ASSERT_EQ(OK, mST->setDefaultMaxBufferCount(2));
 
     sp<Thread> pt(new ProducerThread(mANW));
@@ -1810,32 +1798,6 @@
     EXPECT_EQ(1, buffer->getStrongCount());
 }
 
-
-TEST_F(SurfaceTextureGLToGLTest, EglSurfaceDefaultsToSynchronousMode) {
-    // This test requires 3 buffers to run on a single thread.
-    mST->setDefaultMaxBufferCount(3);
-
-    ASSERT_TRUE(mST->isSynchronousMode());
-
-    for (int i = 0; i < 10; i++) {
-        // Produce a frame
-        EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
-                mProducerEglSurface, mProducerEglContext));
-        ASSERT_EQ(EGL_SUCCESS, eglGetError());
-        glClear(GL_COLOR_BUFFER_BIT);
-        EXPECT_TRUE(eglSwapBuffers(mEglDisplay, mProducerEglSurface));
-        ASSERT_EQ(EGL_SUCCESS, eglGetError());
-
-        // Consume a frame
-        EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
-                mEglContext));
-        ASSERT_EQ(EGL_SUCCESS, eglGetError());
-        ASSERT_EQ(NO_ERROR, mST->updateTexImage());
-    }
-
-    ASSERT_TRUE(mST->isSynchronousMode());
-}
-
 TEST_F(SurfaceTextureGLToGLTest, TexturingFromUserSizedGLFilledBuffer) {
     enum { texWidth = 64 };
     enum { texHeight = 64 };
@@ -2285,7 +2247,6 @@
         }
     };
 
-    ASSERT_EQ(OK, mST->setSynchronousMode(true));
     ASSERT_EQ(OK, mST->setDefaultMaxBufferCount(2));
 
     runProducerThread(new PT());
@@ -2826,7 +2787,6 @@
 
 TEST_F(SurfaceTextureMultiContextGLTest,
         UpdateTexImageSucceedsForBufferConsumedBeforeDetach) {
-    ASSERT_EQ(NO_ERROR, mST->setSynchronousMode(true));
     ASSERT_EQ(NO_ERROR, mST->setDefaultMaxBufferCount(2));
 
     // produce two frames and consume them both on the primary context
diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp
index 77fa49d..54703d4 100644
--- a/libs/input/InputDevice.cpp
+++ b/libs/input/InputDevice.cpp
@@ -136,6 +136,7 @@
         mKeyboardType(other.mKeyboardType),
         mKeyCharacterMap(other.mKeyCharacterMap),
         mHasVibrator(other.mHasVibrator),
+        mHasButtonUnderPad(other.mHasButtonUnderPad),
         mMotionRanges(other.mMotionRanges) {
 }
 
@@ -152,6 +153,7 @@
     mSources = 0;
     mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE;
     mHasVibrator = false;
+    mHasButtonUnderPad = false;
     mMotionRanges.clear();
 }
 
diff --git a/opengl/tests/EGLTest/EGL_test.cpp b/opengl/tests/EGLTest/EGL_test.cpp
index c0daba2..86bbb84 100644
--- a/opengl/tests/EGLTest/EGL_test.cpp
+++ b/opengl/tests/EGLTest/EGL_test.cpp
@@ -20,7 +20,6 @@
 
 #include <EGL/egl.h>
 #include <gui/Surface.h>
-#include <gui/DummyConsumer.h>
 
 
 namespace android {
@@ -101,9 +100,14 @@
     };
     EXPECT_TRUE(eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs));
 
+    struct DummyConsumer : public BufferQueue::ConsumerListener {
+        virtual void onFrameAvailable() {}
+        virtual void onBuffersReleased() {}
+    };
+
     // Create a EGLSurface
     sp<BufferQueue> bq = new BufferQueue();
-    bq->consumerConnect(new DummyConsumer());
+    bq->consumerConnect(new DummyConsumer, false);
     sp<Surface> mSTC = new Surface(static_cast<sp<IGraphicBufferProducer> >( bq));
     sp<ANativeWindow> mANW = mSTC;
 
diff --git a/services/inputflinger/Android.mk b/services/inputflinger/Android.mk
index 7148db8..e32d38a 100644
--- a/services/inputflinger/Android.mk
+++ b/services/inputflinger/Android.mk
@@ -33,3 +33,18 @@
 
 include $(BUILD_SHARED_LIBRARY)
 
+########################################################################
+# build input flinger executable
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	main.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libbinder \
+	libinputflinger \
+	libutils
+
+LOCAL_MODULE := inputflinger
+
+include $(BUILD_EXECUTABLE)
diff --git a/cmds/inputflinger/main.cpp b/services/inputflinger/main.cpp
similarity index 96%
rename from cmds/inputflinger/main.cpp
rename to services/inputflinger/main.cpp
index 6de7b24..3209a62 100644
--- a/cmds/inputflinger/main.cpp
+++ b/services/inputflinger/main.cpp
@@ -15,7 +15,7 @@
  */
 
 #include <binder/BinderService.h>
-#include <InputFlinger.h>
+#include "InputFlinger.h"
 
 using namespace android;
 
diff --git a/services/sensorservice/Android.mk b/services/sensorservice/Android.mk
index 14a4e55..4f24ddc 100644
--- a/services/sensorservice/Android.mk
+++ b/services/sensorservice/Android.mk
@@ -31,3 +31,21 @@
 LOCAL_MODULE:= libsensorservice
 
 include $(BUILD_SHARED_LIBRARY)
+
+#####################################################################
+# build executable
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	main_sensorservice.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libsensorservice \
+	libbinder \
+	libutils
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE:= sensorservice
+
+include $(BUILD_EXECUTABLE)
diff --git a/cmds/sensorservice/main_sensorservice.cpp b/services/sensorservice/main_sensorservice.cpp
similarity index 96%
rename from cmds/sensorservice/main_sensorservice.cpp
rename to services/sensorservice/main_sensorservice.cpp
index 8610627..303b65f 100644
--- a/cmds/sensorservice/main_sensorservice.cpp
+++ b/services/sensorservice/main_sensorservice.cpp
@@ -15,7 +15,7 @@
  */
 
 #include <binder/BinderService.h>
-#include <SensorService.h>
+#include "SensorService.h"
 
 using namespace android;
 
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 2ec575e..8dbb9c5 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -36,7 +36,6 @@
 endif
 ifeq ($(TARGET_BOARD_PLATFORM),s5pc110)
 	LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY
-	LOCAL_CFLAGS += -DNEVER_DEFAULT_TO_ASYNC_MODE
 endif
 
 ifeq ($(TARGET_DISABLE_TRIPLE_BUFFERING),true)
@@ -66,6 +65,22 @@
 include $(BUILD_SHARED_LIBRARY)
 
 ###############################################################
+# build surfaceflinger's executable
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	main_surfaceflinger.cpp 
+
+LOCAL_SHARED_LIBRARIES := \
+	libsurfaceflinger \
+	libbinder \
+	libutils
+
+LOCAL_MODULE:= surfaceflinger
+
+include $(BUILD_EXECUTABLE)
+
+###############################################################
 # uses jni which may not be available in PDK
 ifneq ($(wildcard libnativehelper/include),)
 include $(CLEAR_VARS)
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 7987da3..bd2f5f3 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -51,7 +51,7 @@
  */
 
 FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp) :
-    ConsumerBase(new BufferQueue(true, new GraphicBufferAlloc())),
+    ConsumerBase(new BufferQueue(new GraphicBufferAlloc())),
     mDisplayType(disp),
     mCurrentBufferSlot(-1),
     mCurrentBuffer(0),
@@ -64,7 +64,6 @@
                                        GRALLOC_USAGE_HW_COMPOSER);
     mBufferQueue->setDefaultBufferFormat(mHwc.getFormat(disp));
     mBufferQueue->setDefaultBufferSize(mHwc.getWidth(disp),  mHwc.getHeight(disp));
-    mBufferQueue->setSynchronousMode(true);
     mBufferQueue->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS);
 }
 
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index a324e94..57cb361 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -41,7 +41,7 @@
 
 VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId,
         const sp<IGraphicBufferProducer>& sink, const String8& name)
-:   ConsumerBase(new BufferQueue(true)),
+:   ConsumerBase(new BufferQueue()),
     mHwc(hwc),
     mDisplayId(dispId),
     mDisplayName(name),
@@ -126,7 +126,7 @@
         mQueueBufferOutput.deflate(&mSinkBufferWidth, &mSinkBufferHeight,
                 &transformHint, &numPendingBuffers);
         int sslot;
-        result = dequeueBuffer(SOURCE_SINK, 0, &sslot, &outFence);
+        result = dequeueBuffer(SOURCE_SINK, 0, &sslot, &outFence, false);
         if (result < 0)
             return result;
         mOutputProducerSlot = mapSource2ProducerSlot(SOURCE_SINK, sslot);
@@ -196,7 +196,7 @@
         status_t result = mSource[SOURCE_SINK]->queueBuffer(sslot,
                 QueueBufferInput(systemTime(),
                     Rect(mSinkBufferWidth, mSinkBufferHeight),
-                    NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, outFence),
+                    NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, outFence),
                 &qbo);
         if (result == NO_ERROR) {
             updateQueueBufferOutput(qbo);
@@ -224,8 +224,8 @@
 }
 
 status_t VirtualDisplaySurface::dequeueBuffer(Source source,
-        uint32_t format, int* sslot, sp<Fence>* fence) {
-    status_t result = mSource[source]->dequeueBuffer(sslot, fence,
+        uint32_t format, int* sslot, sp<Fence>* fence, bool async) {
+    status_t result = mSource[source]->dequeueBuffer(sslot, fence, async,
             mSinkBufferWidth, mSinkBufferHeight, format, mProducerUsage);
     if (result < 0)
         return result;
@@ -257,7 +257,7 @@
     return result;
 }
 
-status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence,
+status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence, bool async,
         uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
     VDS_LOGW_IF(mDbgState != DBG_STATE_PREPARED,
             "Unexpected dequeueBuffer() in %s state", dbgStateStr());
@@ -273,7 +273,7 @@
     }
 
     int sslot;
-    status_t result = dequeueBuffer(source, format, &sslot, fence);
+    status_t result = dequeueBuffer(source, format, &sslot, fence, async);
     if (result >= 0) {
         *pslot = mapSource2ProducerSlot(source, sslot);
     }
@@ -321,8 +321,9 @@
         Rect crop;
         int scalingMode;
         uint32_t transform;
+        bool async;
         input.deflate(&timestamp, &crop, &scalingMode, &transform,
-                &mFbFence);
+                &async, &mFbFence);
 
         mFbProducerSlot = pslot;
     }
@@ -345,13 +346,10 @@
     return mSource[SOURCE_SINK]->query(what, value);
 }
 
-status_t VirtualDisplaySurface::setSynchronousMode(bool enabled) {
-    return mSource[SOURCE_SINK]->setSynchronousMode(enabled);
-}
-
-status_t VirtualDisplaySurface::connect(int api, QueueBufferOutput* output) {
+status_t VirtualDisplaySurface::connect(int api, bool producerControlledByApp,
+        QueueBufferOutput* output) {
     QueueBufferOutput qbo;
-    status_t result = mSource[SOURCE_SINK]->connect(api, &qbo);
+    status_t result = mSource[SOURCE_SINK]->connect(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 2b4cf8f..dc9655b 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -95,14 +95,13 @@
     //
     virtual status_t requestBuffer(int pslot, sp<GraphicBuffer>* outBuf);
     virtual status_t setBufferCount(int bufferCount);
-    virtual status_t dequeueBuffer(int* pslot, sp<Fence>* fence,
+    virtual status_t dequeueBuffer(int* pslot, sp<Fence>* fence, bool async,
             uint32_t w, uint32_t h, uint32_t format, uint32_t usage);
     virtual status_t queueBuffer(int pslot,
             const QueueBufferInput& input, QueueBufferOutput* output);
     virtual void cancelBuffer(int pslot, const sp<Fence>& fence);
     virtual int query(int what, int* value);
-    virtual status_t setSynchronousMode(bool enabled);
-    virtual status_t connect(int api, QueueBufferOutput* output);
+    virtual status_t connect(int api, bool producerControlledByApp, QueueBufferOutput* output);
     virtual status_t disconnect(int api);
 
     //
@@ -110,7 +109,7 @@
     //
     static Source fbSourceForCompositionType(CompositionType type);
     status_t dequeueBuffer(Source source, uint32_t format,
-            int* sslot, sp<Fence>* fence);
+            int* sslot, sp<Fence>* fence, bool async);
     void updateQueueBufferOutput(const QueueBufferOutput& qbo);
     void resetPerFrameState();
 
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 2962115..52211c2 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -115,7 +115,6 @@
 
     mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
     mSurfaceFlingerConsumer->setFrameAvailableListener(this);
-    mSurfaceFlingerConsumer->setSynchronousMode(true);
     mSurfaceFlingerConsumer->setName(mName);
 
 #ifdef TARGET_DISABLE_TRIPLE_BUFFERING
diff --git a/services/surfaceflinger/SurfaceTextureLayer.cpp b/services/surfaceflinger/SurfaceTextureLayer.cpp
index d0f0dae..b76dc0c 100644
--- a/services/surfaceflinger/SurfaceTextureLayer.cpp
+++ b/services/surfaceflinger/SurfaceTextureLayer.cpp
@@ -28,7 +28,7 @@
 
 
 SurfaceTextureLayer::SurfaceTextureLayer(const sp<SurfaceFlinger>& flinger)
-    : BufferQueue(true), flinger(flinger) {
+    : BufferQueue(), flinger(flinger) {
 }
 
 SurfaceTextureLayer::~SurfaceTextureLayer() {
@@ -51,32 +51,5 @@
     flinger->postMessageAsync( new MessageCleanUpList(flinger, this) );
 }
 
-status_t SurfaceTextureLayer::connect(int api, QueueBufferOutput* output) {
-    status_t err = BufferQueue::connect(api, output);
-    if (err == NO_ERROR) {
-        switch(api) {
-            case NATIVE_WINDOW_API_MEDIA:
-            case NATIVE_WINDOW_API_CAMERA:
-                // Camera preview and videos are rate-limited on the producer
-                // side.  If enabled for this build, we use async mode to always
-                // show the most recent frame at the cost of requiring an
-                // additional buffer.
-#ifndef NEVER_DEFAULT_TO_ASYNC_MODE
-                err = setSynchronousMode(false);
-                break;
-#endif
-                // fall through to set synchronous mode when not defaulting to
-                // async mode.
-            default:
-                err = setSynchronousMode(true);
-                break;
-        }
-        if (err != NO_ERROR) {
-            disconnect(api);
-        }
-    }
-    return err;
-}
-
 // ---------------------------------------------------------------------------
 }; // namespace android
diff --git a/services/surfaceflinger/SurfaceTextureLayer.h b/services/surfaceflinger/SurfaceTextureLayer.h
index 13cff2f..5f5e4ef 100644
--- a/services/surfaceflinger/SurfaceTextureLayer.h
+++ b/services/surfaceflinger/SurfaceTextureLayer.h
@@ -38,10 +38,6 @@
 public:
     SurfaceTextureLayer(const sp<SurfaceFlinger>& flinger);
     virtual ~SurfaceTextureLayer();
-
-    // After calling the superclass connect(), set or clear synchronous
-    // mode appropriately for the specified API.
-    virtual status_t connect(int api, QueueBufferOutput* output);
 };
 
 // ---------------------------------------------------------------------------
diff --git a/cmds/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp
similarity index 96%
rename from cmds/surfaceflinger/main_surfaceflinger.cpp
rename to services/surfaceflinger/main_surfaceflinger.cpp
index ce7fde0..8503d4e 100644
--- a/cmds/surfaceflinger/main_surfaceflinger.cpp
+++ b/services/surfaceflinger/main_surfaceflinger.cpp
@@ -15,7 +15,7 @@
  */
 
 #include <binder/BinderService.h>
-#include <SurfaceFlinger.h>
+#include "SurfaceFlinger.h"
 
 using namespace android;