Merge "Add C++ library for ConnectivityManager"
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index 8e6998f..7710c5b 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -95,6 +95,7 @@
 
     run_command("PROCESSES", 10, "ps", "-P", NULL);
     run_command("PROCESSES AND THREADS", 10, "ps", "-t", "-p", "-P", NULL);
+    run_command("PROCESSES (SELINUX LABELS)", 10, "ps", "-Z", NULL);
     run_command("LIBRANK", 10, "librank", NULL);
 
     do_dmesg();
diff --git a/cmds/flatland/GLHelper.cpp b/cmds/flatland/GLHelper.cpp
index 4f7697f..3928039 100644
--- a/cmds/flatland/GLHelper.cpp
+++ b/cmds/flatland/GLHelper.cpp
@@ -198,9 +198,9 @@
 
 bool GLHelper::createNamedSurfaceTexture(GLuint name, uint32_t w, uint32_t h,
         sp<GLConsumer>* glConsumer, EGLSurface* surface) {
-    sp<BufferQueue> bq = new BufferQueue(true, mGraphicBufferAlloc);
-    sp<GLConsumer> glc = new GLConsumer(name, true,
-            GL_TEXTURE_EXTERNAL_OES, false, bq);
+    sp<BufferQueue> bq = new BufferQueue(mGraphicBufferAlloc);
+    sp<GLConsumer> glc = new GLConsumer(bq, name,
+            GL_TEXTURE_EXTERNAL_OES, false);
     glc->setDefaultBufferSize(w, h);
     glc->setDefaultMaxBufferCount(3);
     glc->setConsumerUsageBits(GRALLOC_USAGE_HW_COMPOSER);
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index 27580f3..84ad204 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -108,11 +108,11 @@
     return 0;
 }
 
-int uninstall(const char *pkgname, uid_t persona)
+int uninstall(const char *pkgname, userid_t userid)
 {
     char pkgdir[PKG_PATH_MAX];
 
-    if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, persona))
+    if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userid))
         return -1;
 
     /* delete contents AND directory, no exceptions */
@@ -173,18 +173,18 @@
     return 0;
 }
 
-int delete_user_data(const char *pkgname, uid_t persona)
+int delete_user_data(const char *pkgname, userid_t userid)
 {
     char pkgdir[PKG_PATH_MAX];
 
-    if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, persona))
+    if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userid))
         return -1;
 
     /* delete contents, excluding "lib", but not the directory itself */
     return delete_dir_contents(pkgdir, 0, "lib");
 }
 
-int make_user_data(const char *pkgname, uid_t uid, uid_t persona)
+int make_user_data(const char *pkgname, uid_t uid, userid_t userid)
 {
     char pkgdir[PKG_PATH_MAX];
     char applibdir[PKG_PATH_MAX];
@@ -192,10 +192,10 @@
     struct stat libStat;
 
     // Create the data dir for the package
-    if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, persona)) {
+    if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userid)) {
         return -1;
     }
-    if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, persona)) {
+    if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, userid)) {
         ALOGE("cannot create package lib symlink origin path\n");
         return -1;
     }
@@ -262,10 +262,10 @@
     return 0;
 }
 
-int delete_persona(uid_t persona)
+int delete_user(userid_t userid)
 {
     char data_path[PKG_PATH_MAX];
-    if (create_persona_path(data_path, persona)) {
+    if (create_user_path(data_path, userid)) {
         return -1;
     }
     if (delete_dir_contents(data_path, 1, NULL)) {
@@ -273,7 +273,7 @@
     }
 
     char media_path[PATH_MAX];
-    if (create_persona_media_path(media_path, (userid_t) persona) == -1) {
+    if (create_user_media_path(media_path, userid) == -1) {
         return -1;
     }
     if (delete_dir_contents(media_path, 1, NULL) == -1) {
@@ -283,11 +283,11 @@
     return 0;
 }
 
-int delete_cache(const char *pkgname, uid_t persona)
+int delete_cache(const char *pkgname, userid_t userid)
 {
     char cachedir[PKG_PATH_MAX];
 
-    if (create_pkg_path(cachedir, pkgname, CACHE_DIR_POSTFIX, persona))
+    if (create_pkg_path(cachedir, pkgname, CACHE_DIR_POSTFIX, userid))
         return -1;
 
         /* delete contents, not the directory, no exceptions */
@@ -319,7 +319,7 @@
     cache = start_cache_collection();
 
     // Collect cache files for primary user.
-    if (create_persona_path(tmpdir, 0) == 0) {
+    if (create_user_path(tmpdir, 0) == 0) {
         //ALOGI("adding cache files from %s\n", tmpdir);
         add_cache_files(cache, tmpdir, "cache");
     }
@@ -420,7 +420,7 @@
     }
 }
 
-int get_size(const char *pkgname, int persona, const char *apkpath,
+int get_size(const char *pkgname, userid_t userid, const char *apkpath,
              const char *libdirpath, const char *fwdlock_apkpath, const char *asecpath,
              int64_t *_codesize, int64_t *_datasize, int64_t *_cachesize,
              int64_t* _asecsize)
@@ -477,7 +477,7 @@
         }
     }
 
-    if (create_pkg_path(path, pkgname, PKG_DIR_POSTFIX, persona)) {
+    if (create_pkg_path(path, pkgname, PKG_DIR_POSTFIX, userid)) {
         goto done;
     }
 
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
index 87f900a..1904408 100644
--- a/cmds/installd/installd.c
+++ b/cmds/installd/installd.c
@@ -83,7 +83,7 @@
     int64_t asecsize = 0;
     int res = 0;
 
-        /* pkgdir, persona, apkpath */
+        /* pkgdir, userid, apkpath */
     res = get_size(arg[0], atoi(arg[1]), arg[2], arg[3], arg[4], arg[5],
             &codesize, &datasize, &cachesize, &asecsize);
 
@@ -108,7 +108,7 @@
 
 static int do_rm_user(char **arg, char reply[REPLY_MAX])
 {
-    return delete_persona(atoi(arg[0])); /* userid */
+    return delete_user(atoi(arg[0])); /* userid */
 }
 
 static int do_movefiles(char **arg, char reply[REPLY_MAX])
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index fbfc876..635b07c 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -78,9 +78,6 @@
 #define PKG_NAME_MAX  128   /* largest allowed package name */
 #define PKG_PATH_MAX  256   /* max size of any path we use */
 
-#define PER_USER_RANGE ((uid_t)100000)   /* range of uids per user
-                                            uid = persona * PER_USER_RANGE + appid */
-
 /* data structures */
 
 typedef struct {
@@ -138,17 +135,17 @@
 int create_pkg_path(char path[PKG_PATH_MAX],
                     const char *pkgname,
                     const char *postfix,
-                    uid_t persona);
+                    userid_t userid);
 
-int create_persona_path(char path[PKG_PATH_MAX],
-                    uid_t persona);
+int create_user_path(char path[PKG_PATH_MAX],
+                    userid_t userid);
 
-int create_persona_media_path(char path[PKG_PATH_MAX], userid_t userid);
+int create_user_media_path(char path[PKG_PATH_MAX], userid_t userid);
 
 int create_move_path(char path[PKG_PATH_MAX],
                      const char* pkgname,
                      const char* leaf,
-                     uid_t persona);
+                     userid_t userid);
 
 int is_valid_package_name(const char* pkgname);
 
@@ -193,17 +190,17 @@
 /* commands.c */
 
 int install(const char *pkgname, uid_t uid, gid_t gid, const char *seinfo);
-int uninstall(const char *pkgname, uid_t persona);
+int uninstall(const char *pkgname, userid_t userid);
 int renamepkg(const char *oldpkgname, const char *newpkgname);
 int fix_uid(const char *pkgname, uid_t uid, gid_t gid);
-int delete_user_data(const char *pkgname, uid_t persona);
-int make_user_data(const char *pkgname, uid_t uid, uid_t persona);
-int delete_persona(uid_t persona);
-int delete_cache(const char *pkgname, uid_t persona);
+int delete_user_data(const char *pkgname, userid_t userid);
+int make_user_data(const char *pkgname, uid_t uid, userid_t userid);
+int delete_user(userid_t userid);
+int delete_cache(const char *pkgname, userid_t userid);
 int move_dex(const char *src, const char *dst);
 int rm_dex(const char *path);
 int protect(char *pkgname, gid_t gid);
-int get_size(const char *pkgname, int persona, const char *apkpath, const char *libdirpath,
+int get_size(const char *pkgname, userid_t userid, const char *apkpath, const char *libdirpath,
              const char *fwdlock_apkpath, const char *asecpath, int64_t *codesize,
              int64_t *datasize, int64_t *cachesize, int64_t *asecsize);
 int free_cache(int64_t free_size);
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index 7cb9b37..0b182af 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -340,7 +340,7 @@
 TEST_F(UtilsTest, CreatePersonaPath_Primary) {
     char path[PKG_PATH_MAX];
 
-    EXPECT_EQ(0, create_persona_path(path, 0))
+    EXPECT_EQ(0, create_user_path(path, 0))
             << "Should successfully build primary user path.";
 
     EXPECT_STREQ("/data/data/", path)
@@ -350,7 +350,7 @@
 TEST_F(UtilsTest, CreatePersonaPath_Secondary) {
     char path[PKG_PATH_MAX];
 
-    EXPECT_EQ(0, create_persona_path(path, 1))
+    EXPECT_EQ(0, create_user_path(path, 1))
             << "Should successfully build primary user path.";
 
     EXPECT_STREQ("/data/user/1/", path)
diff --git a/cmds/installd/utils.c b/cmds/installd/utils.c
index 625a35e..ef634c6 100644
--- a/cmds/installd/utils.c
+++ b/cmds/installd/utils.c
@@ -53,38 +53,39 @@
 
 /**
  * Create the package path name for a given package name with a postfix for
- * a certain persona. Returns 0 on success, and -1 on failure.
+ * a certain userid. Returns 0 on success, and -1 on failure.
  */
 int create_pkg_path(char path[PKG_PATH_MAX],
                     const char *pkgname,
                     const char *postfix,
-                    uid_t persona)
+                    userid_t userid)
 {
-    size_t uid_len;
-    char* persona_prefix;
-    if (persona == 0) {
-        persona_prefix = PRIMARY_USER_PREFIX;
-        uid_len = 0;
+    size_t userid_len;
+    char* userid_prefix;
+    if (userid == 0) {
+        userid_prefix = PRIMARY_USER_PREFIX;
+        userid_len = 0;
     } else {
-        persona_prefix = SECONDARY_USER_PREFIX;
-        uid_len = snprintf(NULL, 0, "%d", persona);
+        userid_prefix = SECONDARY_USER_PREFIX;
+        userid_len = snprintf(NULL, 0, "%d", userid);
     }
 
-    const size_t prefix_len = android_data_dir.len + strlen(persona_prefix) + uid_len + 1 /*slash*/;
+    const size_t prefix_len = android_data_dir.len + strlen(userid_prefix)
+            + userid_len + 1 /*slash*/;
     char prefix[prefix_len + 1];
 
     char *dst = prefix;
     size_t dst_size = sizeof(prefix);
 
     if (append_and_increment(&dst, android_data_dir.path, &dst_size) < 0
-            || append_and_increment(&dst, persona_prefix, &dst_size) < 0) {
+            || append_and_increment(&dst, userid_prefix, &dst_size) < 0) {
         ALOGE("Error building prefix for APK path");
         return -1;
     }
 
-    if (persona != 0) {
-        int ret = snprintf(dst, dst_size, "%d/", persona);
-        if (ret < 0 || (size_t) ret != uid_len + 1) {
+    if (userid != 0) {
+        int ret = snprintf(dst, dst_size, "%d/", userid);
+        if (ret < 0 || (size_t) ret != userid_len + 1) {
             ALOGW("Error appending UID to APK path");
             return -1;
         }
@@ -98,39 +99,39 @@
 }
 
 /**
- * Create the path name for user data for a certain persona.
+ * Create the path name for user data for a certain userid.
  * Returns 0 on success, and -1 on failure.
  */
-int create_persona_path(char path[PKG_PATH_MAX],
-                    uid_t persona)
+int create_user_path(char path[PKG_PATH_MAX],
+                    userid_t userid)
 {
-    size_t uid_len;
-    char* persona_prefix;
-    if (persona == 0) {
-        persona_prefix = PRIMARY_USER_PREFIX;
-        uid_len = 0;
+    size_t userid_len;
+    char* userid_prefix;
+    if (userid == 0) {
+        userid_prefix = PRIMARY_USER_PREFIX;
+        userid_len = 0;
     } else {
-        persona_prefix = SECONDARY_USER_PREFIX;
-        uid_len = snprintf(NULL, 0, "%d/", persona);
+        userid_prefix = SECONDARY_USER_PREFIX;
+        userid_len = snprintf(NULL, 0, "%d/", userid);
     }
 
     char *dst = path;
     size_t dst_size = PKG_PATH_MAX;
 
     if (append_and_increment(&dst, android_data_dir.path, &dst_size) < 0
-            || append_and_increment(&dst, persona_prefix, &dst_size) < 0) {
+            || append_and_increment(&dst, userid_prefix, &dst_size) < 0) {
         ALOGE("Error building prefix for user path");
         return -1;
     }
 
-    if (persona != 0) {
-        if (dst_size < uid_len + 1) {
+    if (userid != 0) {
+        if (dst_size < userid_len + 1) {
             ALOGE("Error building user path");
             return -1;
         }
-        int ret = snprintf(dst, dst_size, "%d/", persona);
-        if (ret < 0 || (size_t) ret != uid_len) {
-            ALOGE("Error appending persona id to path");
+        int ret = snprintf(dst, dst_size, "%d/", userid);
+        if (ret < 0 || (size_t) ret != userid_len) {
+            ALOGE("Error appending userid to path");
             return -1;
         }
     }
@@ -138,10 +139,10 @@
 }
 
 /**
- * Create the path name for media for a certain persona.
+ * Create the path name for media for a certain userid.
  * Returns 0 on success, and -1 on failure.
  */
-int create_persona_media_path(char path[PATH_MAX], userid_t userid) {
+int create_user_media_path(char path[PATH_MAX], userid_t userid) {
     if (snprintf(path, PATH_MAX, "%s%d", android_media_dir.path, userid) > PATH_MAX) {
         return -1;
     }
@@ -151,7 +152,7 @@
 int create_move_path(char path[PKG_PATH_MAX],
     const char* pkgname,
     const char* leaf,
-    uid_t persona)
+    userid_t userid)
 {
     if ((android_data_dir.len + strlen(PRIMARY_USER_PREFIX) + strlen(pkgname) + strlen(leaf) + 1)
             >= PKG_PATH_MAX) {
@@ -997,7 +998,7 @@
     char path[PATH_MAX];
 
     // Ensure /data/media/<userid> exists
-    create_persona_media_path(media_user_path, userid);
+    create_user_media_path(media_user_path, userid);
     if (fs_prepare_dir(media_user_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
         return -1;
     }
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/android/keycodes.h b/include/android/keycodes.h
index cf38d1a..1ca1332 100644
--- a/include/android/keycodes.h
+++ b/include/android/keycodes.h
@@ -265,6 +265,7 @@
     AKEYCODE_ASSIST          = 219,
     AKEYCODE_BRIGHTNESS_DOWN = 220,
     AKEYCODE_BRIGHTNESS_UP   = 221,
+    AKEYCODE_MEDIA_AUDIO_TRACK = 222,
 
     // NOTE: If you add a new keycode here you must also add it to several other files.
     //       Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
diff --git a/include/binder/IAppOpsService.h b/include/binder/IAppOpsService.h
index 7cb55e5..193e9cc 100644
--- a/include/binder/IAppOpsService.h
+++ b/include/binder/IAppOpsService.h
@@ -32,11 +32,14 @@
 
     virtual int32_t checkOperation(int32_t code, int32_t uid, const String16& packageName) = 0;
     virtual int32_t noteOperation(int32_t code, int32_t uid, const String16& packageName) = 0;
-    virtual int32_t startOperation(int32_t code, int32_t uid, const String16& packageName) = 0;
-    virtual void finishOperation(int32_t code, int32_t uid, const String16& packageName) = 0;
+    virtual int32_t startOperation(const sp<IBinder>& token, int32_t code, int32_t uid,
+            const String16& packageName) = 0;
+    virtual void finishOperation(const sp<IBinder>& token, int32_t code, int32_t uid,
+            const String16& packageName) = 0;
     virtual void startWatchingMode(int32_t op, const String16& packageName,
             const sp<IAppOpsCallback>& callback) = 0;
     virtual void stopWatchingMode(const sp<IAppOpsCallback>& callback) = 0;
+    virtual sp<IBinder> getToken(const sp<IBinder>& clientToken) = 0;
 
     enum {
         CHECK_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
@@ -44,7 +47,8 @@
         START_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+2,
         FINISH_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+3,
         START_WATCHING_MODE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+4,
-        STOP_WATCHING_MODE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+5
+        STOP_WATCHING_MODE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+5,
+        GET_TOKEN_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+6,
     };
 
     enum {
diff --git a/include/binder/IPCThreadState.h b/include/binder/IPCThreadState.h
index ad0daee..5bc123e 100644
--- a/include/binder/IPCThreadState.h
+++ b/include/binder/IPCThreadState.h
@@ -39,8 +39,8 @@
             
             status_t            clearLastError();
 
-            int                 getCallingPid();
-            int                 getCallingUid();
+            int                 getCallingPid() const;
+            int                 getCallingUid() const;
 
             void                setStrictModePolicy(int32_t policy);
             int32_t             getStrictModePolicy() const;
diff --git a/include/gui/BufferItemConsumer.h b/include/gui/BufferItemConsumer.h
index 5bf9acb..9370e81 100644
--- a/include/gui/BufferItemConsumer.h
+++ b/include/gui/BufferItemConsumer.h
@@ -29,6 +29,8 @@
 
 namespace android {
 
+class BufferQueue;
+
 /**
  * BufferItemConsumer is a BufferQueue consumer endpoint that allows clients
  * access to the whole BufferItem entry from BufferQueue. Multiple buffers may
@@ -49,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.
-    BufferItemConsumer(uint32_t consumerUsage,
+    // 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 3c178ef..2890350 100644
--- a/include/gui/CpuConsumer.h
+++ b/include/gui/CpuConsumer.h
@@ -28,6 +28,8 @@
 
 namespace android {
 
+class BufferQueue;
+
 /**
  * CpuConsumer is a BufferQueue consumer endpoint that allows direct CPU
  * access to the underlying gralloc buffers provided by BufferQueue. Multiple
@@ -64,7 +66,8 @@
 
     // Create a new CPU consumer. The maxLockedBuffers parameter specifies
     // how many buffers can be locked for user access at the same time.
-    CpuConsumer(uint32_t maxLockedBuffers, bool synchronousMode = true);
+    CpuConsumer(const sp<BufferQueue>& bq,
+            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 fbc8840..1df5b42 100644
--- a/include/gui/GLConsumer.h
+++ b/include/gui/GLConsumer.h
@@ -85,9 +85,9 @@
     // purely to allow a GLConsumer to be transferred from one consumer
     // context to another. If such a transfer is not needed there is no
     // requirement that either of these methods be called.
-    GLConsumer(GLuint tex, bool allowSynchronousMode = true,
-            GLenum texTarget = GL_TEXTURE_EXTERNAL_OES, bool useFenceSync = true,
-            const sp<BufferQueue> &bufferQueue = 0);
+    GLConsumer(const sp<BufferQueue>& bq,
+            GLuint tex, GLenum texTarget = GL_TEXTURE_EXTERNAL_OES,
+            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/IInputFlinger.h b/include/input/IInputFlinger.h
new file mode 100644
index 0000000..79ff12a
--- /dev/null
+++ b/include/input/IInputFlinger.h
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+#ifndef _LIBINPUT_IINPUT_FLINGER_H
+#define _LIBINPUT_IINPUT_FLINGER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <binder/IInterface.h>
+
+namespace android {
+
+/*
+ * This class defines the Binder IPC interface for accessing various
+ * InputFlinger features.
+ */
+class IInputFlinger : public IInterface {
+public:
+    DECLARE_META_INTERFACE(InputFlinger);
+
+    virtual status_t doSomething() = 0;
+};
+
+
+/**
+ * Binder implementation.
+ */
+class BnInputFlinger : public BnInterface<IInputFlinger> {
+public:
+    enum {
+        DO_SOMETHING_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
+    };
+
+    virtual status_t onTransact(uint32_t code, const Parcel& data,
+            Parcel* reply, uint32_t flags = 0);
+};
+
+} // namespace android
+
+#endif // _LIBINPUT_IINPUT_FLINGER_H
diff --git a/include/input/Input.h b/include/input/Input.h
index 6d49b18..e778076 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -28,10 +28,6 @@
 #include <utils/RefBase.h>
 #include <utils/String8.h>
 
-#ifdef HAVE_ANDROID_OS
-class SkMatrix;
-#endif
-
 /*
  * Additional private constants not defined in ndk/ui/input.h.
  */
@@ -529,9 +525,11 @@
 
     void scale(float scaleFactor);
 
-#ifdef HAVE_ANDROID_OS
-    void transform(const SkMatrix* matrix);
+    // Apply 3x3 perspective matrix transformation.
+    // Matrix is in row-major form and compatible with SkMatrix.
+    void transform(const float matrix[9]);
 
+#ifdef HAVE_ANDROID_OS
     status_t readFromParcel(Parcel* parcel);
     status_t writeToParcel(Parcel* parcel) const;
 #endif
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/include/input/KeycodeLabels.h b/include/input/KeycodeLabels.h
index c76ba12..c64c5d8 100644
--- a/include/input/KeycodeLabels.h
+++ b/include/input/KeycodeLabels.h
@@ -246,6 +246,7 @@
     { "ASSIST", 219 },
     { "BRIGHTNESS_DOWN", 220 },
     { "BRIGHTNESS_UP", 221 },
+    { "MEDIA_AUDIO_TRACK", 222 },
 
     // NOTE: If you add a new keycode here you must also add it to several other files.
     //       Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
diff --git a/include/media/hardware/HardwareAPI.h b/include/media/hardware/HardwareAPI.h
index a6a849d..ac67f94 100644
--- a/include/media/hardware/HardwareAPI.h
+++ b/include/media/hardware/HardwareAPI.h
@@ -38,9 +38,13 @@
 //
 // When Android native buffer use has been enabled for a given port, the video
 // color format for the port is to be interpreted as an Android pixel format
-// rather than an OMX color format.  The node should then expect to receive
-// UseAndroidNativeBuffer calls (via OMX_SetParameter) rather than UseBuffer
-// calls for that port.
+// rather than an OMX color format.  Enabling Android native buffers may also
+// change how the component receives the native buffers.  If store-metadata-mode
+// is enabled on the port, the component will receive the buffers as specified
+// in the section below. Otherwise, unless the node supports the
+// 'OMX.google.android.index.useAndroidNativeBuffer2' extension, it should
+// expect to receive UseAndroidNativeBuffer calls (via OMX_SetParameter) rather
+// than UseBuffer calls for that port.
 struct EnableAndroidNativeBuffersParams {
     OMX_U32 nSize;
     OMX_VERSIONTYPE nVersion;
@@ -62,11 +66,15 @@
 //
 // Currently, this is specifically used to pass meta data from video source
 // (camera component, for instance) to video encoder to avoid memcpying of
-// input video frame data. To do this, bStoreMetaDta is set to OMX_TRUE.
+// input video frame data. To do this, bStoreMetaData is set to OMX_TRUE.
 // If bStoreMetaData is set to false, real YUV frame data will be stored
 // in the buffers. In addition, if no OMX_SetParameter() call is made
 // with the corresponding extension index, real YUV data is stored
 // in the buffers.
+//
+// For video decoder output port, the metadata buffer layout is defined below.
+//
+// Metadata buffers are registered with the component using UseBuffer calls.
 struct StoreMetaDataInBuffersParams {
     OMX_U32 nSize;
     OMX_VERSIONTYPE nVersion;
diff --git a/libs/binder/AppOpsManager.cpp b/libs/binder/AppOpsManager.cpp
index 7ac1b11..61b4f7d 100644
--- a/libs/binder/AppOpsManager.cpp
+++ b/libs/binder/AppOpsManager.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <binder/AppOpsManager.h>
+#include <binder/Binder.h>
 #include <binder/IServiceManager.h>
 
 #include <utils/SystemClock.h>
@@ -22,6 +23,17 @@
 namespace android {
 
 static String16 _appops("appops");
+static pthread_mutex_t gTokenMutex = PTHREAD_MUTEX_INITIALIZER;
+static sp<IBinder> gToken;
+
+static const sp<IBinder>& getToken(const sp<IAppOpsService>& service) {
+    pthread_mutex_lock(&gTokenMutex);
+    if (gToken == NULL) {
+        gToken = service->getToken(new BBinder());
+    }
+    pthread_mutex_unlock(&gTokenMutex);
+    return gToken;
+}
 
 AppOpsManager::AppOpsManager()
 {
@@ -66,13 +78,14 @@
 
 int32_t AppOpsManager::startOp(int32_t op, int32_t uid, const String16& callingPackage) {
     sp<IAppOpsService> service = getService();
-    return service != NULL ? service->startOperation(op, uid, callingPackage) : MODE_IGNORED;
+    return service != NULL ? service->startOperation(getToken(service), op, uid, callingPackage)
+            : MODE_IGNORED;
 }
 
 void AppOpsManager::finishOp(int32_t op, int32_t uid, const String16& callingPackage) {
     sp<IAppOpsService> service = getService();
     if (service != NULL) {
-        service->finishOperation(op, uid, callingPackage);
+        service->finishOperation(getToken(service), op, uid, callingPackage);
     }
 }
 
diff --git a/libs/binder/IAppOpsService.cpp b/libs/binder/IAppOpsService.cpp
index 282b30f..471e3e9 100644
--- a/libs/binder/IAppOpsService.cpp
+++ b/libs/binder/IAppOpsService.cpp
@@ -61,9 +61,11 @@
         return reply.readInt32();
     }
 
-    virtual int32_t startOperation(int32_t code, int32_t uid, const String16& packageName) {
+    virtual int32_t startOperation(const sp<IBinder>& token, int32_t code, int32_t uid,
+                const String16& packageName) {
         Parcel data, reply;
         data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
+        data.writeStrongBinder(token);
         data.writeInt32(code);
         data.writeInt32(uid);
         data.writeString16(packageName);
@@ -73,9 +75,11 @@
         return reply.readInt32();
     }
 
-    virtual void finishOperation(int32_t code, int32_t uid, const String16& packageName) {
+    virtual void finishOperation(const sp<IBinder>& token, int32_t code, int32_t uid,
+            const String16& packageName) {
         Parcel data, reply;
         data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
+        data.writeStrongBinder(token);
         data.writeInt32(code);
         data.writeInt32(uid);
         data.writeString16(packageName);
@@ -98,6 +102,16 @@
         data.writeStrongBinder(callback->asBinder());
         remote()->transact(STOP_WATCHING_MODE_TRANSACTION, data, &reply);
     }
+
+    virtual sp<IBinder> getToken(const sp<IBinder>& clientToken) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
+        data.writeStrongBinder(clientToken);
+        remote()->transact(GET_TOKEN_TRANSACTION, data, &reply);
+        // fail on exception
+        if (reply.readExceptionCode() != 0) return NULL;
+        return reply.readStrongBinder();
+    }
 };
 
 IMPLEMENT_META_INTERFACE(AppOpsService, "com.android.internal.app.IAppOpsService");
@@ -131,20 +145,22 @@
         } break;
         case START_OPERATION_TRANSACTION: {
             CHECK_INTERFACE(IAppOpsService, data, reply);
+            sp<IBinder> token = data.readStrongBinder();
             int32_t code = data.readInt32();
             int32_t uid = data.readInt32();
             String16 packageName = data.readString16();
-            int32_t res = startOperation(code, uid, packageName);
+            int32_t res = startOperation(token, code, uid, packageName);
             reply->writeNoException();
             reply->writeInt32(res);
             return NO_ERROR;
         } break;
         case FINISH_OPERATION_TRANSACTION: {
             CHECK_INTERFACE(IAppOpsService, data, reply);
+            sp<IBinder> token = data.readStrongBinder();
             int32_t code = data.readInt32();
             int32_t uid = data.readInt32();
             String16 packageName = data.readString16();
-            finishOperation(code, uid, packageName);
+            finishOperation(token, code, uid, packageName);
             reply->writeNoException();
             return NO_ERROR;
         } break;
@@ -164,6 +180,14 @@
             reply->writeNoException();
             return NO_ERROR;
         } break;
+        case GET_TOKEN_TRANSACTION: {
+            CHECK_INTERFACE(IAppOpsService, data, reply);
+            sp<IBinder> clientToken = data.readStrongBinder();
+            sp<IBinder> token = getToken(clientToken);
+            reply->writeNoException();
+            reply->writeStrongBinder(token);
+            return NO_ERROR;
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 5a38b95..5951a3f 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -362,12 +362,12 @@
     return err;
 }
 
-int IPCThreadState::getCallingPid()
+int IPCThreadState::getCallingPid() const
 {
     return mCallingPid;
 }
 
-int IPCThreadState::getCallingUid()
+int IPCThreadState::getCallingUid() const
 {
     return mCallingUid;
 }
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 8d86c59..0f818b7 100644
--- a/libs/gui/BufferItemConsumer.cpp
+++ b/libs/gui/BufferItemConsumer.cpp
@@ -29,12 +29,11 @@
 
 namespace android {
 
-BufferItemConsumer::BufferItemConsumer(uint32_t consumerUsage,
-        int bufferCount, bool synchronousMode) :
-    ConsumerBase(new BufferQueue(true) )
+BufferItemConsumer::BufferItemConsumer(const sp<BufferQueue>& 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..ad2f1bb 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);
@@ -855,13 +843,13 @@
     if (presentWhen != 0 && desiredPresent > presentWhen &&
             desiredPresent - presentWhen < MAX_FUTURE_NSEC)
     {
-        ALOGV("pts defer: des=%lld when=%lld (%lld) now=%lld",
+        ST_LOGV("pts defer: des=%lld when=%lld (%lld) now=%lld",
                 desiredPresent, presentWhen, desiredPresent - presentWhen,
                 systemTime(CLOCK_MONOTONIC));
         return PRESENT_LATER;
     }
     if (presentWhen != 0) {
-        ALOGV("pts accept: %p[%d] sig=%lld des=%lld when=%lld (%lld)",
+        ST_LOGV("pts accept: %p[%d] sig=%lld des=%lld when=%lld (%lld)",
                 mSlots, buf, mSlots[buf].mFence->getSignalTime(),
                 desiredPresent, presentWhen, desiredPresent - presentWhen);
     }
@@ -901,35 +889,31 @@
     ATRACE_CALL();
     ATRACE_BUFFER_INDEX(buf);
 
-    Mutex::Autolock _l(mMutex);
-
     if (buf == INVALID_BUFFER_SLOT || fence == NULL) {
         return BAD_VALUE;
     }
 
-    // Check if this buffer slot is on the queue
-    bool slotQueued = false;
-    Fifo::iterator front(mQueue.begin());
-    while (front != mQueue.end() && !slotQueued) {
-        if (front->mBuf == buf)
-            slotQueued = true;
-        front++;
-    }
+    Mutex::Autolock _l(mMutex);
 
     // If the frame number has changed because buffer has been reallocated,
     // we can ignore this releaseBuffer for the old buffer.
     if (frameNumber != mSlots[buf].mFrameNumber) {
-        // This should only occur if new buffer is still in the queue
-        ALOGE_IF(!slotQueued,
-                "received old buffer(#%lld) after new buffer(#%lld) on same "
-                "slot #%d already acquired", frameNumber,
-                mSlots[buf].mFrameNumber, buf);
         return STALE_BUFFER_SLOT;
     }
-    // this should never happen
-    ALOGE_IF(slotQueued,
-            "received new buffer(#%lld) on slot #%d that has not yet been "
-            "acquired", frameNumber, buf);
+
+
+    // Internal state consistency checks:
+    // Make sure this buffers hasn't been queued while we were owning it (acquired)
+    Fifo::iterator front(mQueue.begin());
+    Fifo::const_iterator const end(mQueue.end());
+    while (front != end) {
+        if (front->mBuf == buf) {
+            LOG_ALWAYS_FATAL("[%s] received new buffer(#%lld) on slot #%d that has not yet been "
+                    "acquired", mConsumerName.string(), frameNumber, buf);
+            break; // never reached
+        }
+        front++;
+    }
 
     // The buffer can now only be released if its in the acquired state
     if (mSlots[buf].mBufferState == BufferSlot::ACQUIRED) {
@@ -950,7 +934,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 +949,7 @@
     }
 
     mConsumerListener = consumerListener;
+    mConsumerControlledByApp = controlledByApp;
 
     return NO_ERROR;
 }
@@ -1017,8 +1003,7 @@
     return NO_ERROR;
 }
 
-status_t BufferQueue::setDefaultBufferSize(uint32_t w, uint32_t h)
-{
+status_t BufferQueue::setDefaultBufferSize(uint32_t w, uint32_t h) {
     ST_LOGV("setDefaultBufferSize: w=%d, h=%d", w, h);
     if (!w || !h) {
         ST_LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)",
@@ -1053,40 +1038,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 56bc7c6..b8c00af 100644
--- a/libs/gui/CpuConsumer.cpp
+++ b/libs/gui/CpuConsumer.cpp
@@ -30,15 +30,15 @@
 
 namespace android {
 
-CpuConsumer::CpuConsumer(uint32_t maxLockedBuffers, bool synchronousMode) :
-    ConsumerBase(new BufferQueue(true) ),
+CpuConsumer::CpuConsumer(const sp<BufferQueue>& 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 d12083f..92f07eb 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -78,9 +78,9 @@
 static void mtxMul(float out[16], const float a[16], const float b[16]);
 
 
-GLConsumer::GLConsumer(GLuint tex, bool allowSynchronousMode,
-        GLenum texTarget, bool useFenceSync, const sp<BufferQueue> &bufferQueue) :
-    ConsumerBase(bufferQueue == 0 ? new BufferQueue(allowSynchronousMode) : bufferQueue),
+GLConsumer::GLConsumer(const sp<BufferQueue>& bq, GLuint tex,
+        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/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index f345df8..94f21b6 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -633,7 +633,8 @@
 
 sp<CpuConsumer> ScreenshotClient::getCpuConsumer() const {
     if (mCpuConsumer == NULL) {
-        mCpuConsumer = new CpuConsumer(1);
+        sp<BufferQueue> bq = new BufferQueue();
+        mCpuConsumer = new CpuConsumer(bq, 1);
         mCpuConsumer->setName(String8("ScreenshotClient"));
     }
     return mCpuConsumer;
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/CpuConsumer_test.cpp b/libs/gui/tests/CpuConsumer_test.cpp
index 73fdd04..f8a35b4 100644
--- a/libs/gui/tests/CpuConsumer_test.cpp
+++ b/libs/gui/tests/CpuConsumer_test.cpp
@@ -66,7 +66,8 @@
                 test_info->name(),
                 params.width, params.height,
                 params.maxLockedBuffers, params.format);
-        mCC = new CpuConsumer(params.maxLockedBuffers);
+        sp<BufferQueue> bq = new BufferQueue();
+        mCC = new CpuConsumer(bq, params.maxLockedBuffers);
         String8 name("CpuConsumer_Under_Test");
         mCC->setName(name);
         mSTC = new Surface(mCC->getProducerInterface());
diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp
index 7376b4c..158c94b 100644
--- a/libs/gui/tests/SurfaceTextureClient_test.cpp
+++ b/libs/gui/tests/SurfaceTextureClient_test.cpp
@@ -40,7 +40,8 @@
         ALOGV("Begin test: %s.%s", testInfo->test_case_name(),
                 testInfo->name());
 
-        mST = new GLConsumer(123);
+        sp<BufferQueue> bq = new BufferQueue();
+        mST = new GLConsumer(bq, 123);
         mSTC = new Surface(mST->getBufferQueue());
         mANW = mSTC;
 
@@ -337,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]));
@@ -345,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]));
@@ -360,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]));
@@ -381,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]));
@@ -402,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]));
@@ -428,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));
@@ -448,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.
@@ -527,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]));
@@ -715,7 +710,8 @@
         ASSERT_NE(EGL_NO_CONTEXT, mEglContext);
 
         for (int i = 0; i < NUM_SURFACE_TEXTURES; i++) {
-            sp<GLConsumer> st(new GLConsumer(i));
+            sp<BufferQueue> bq = new BufferQueue();
+            sp<GLConsumer> st(new GLConsumer(bq, i));
             sp<Surface> stc(new Surface(st->getBufferQueue()));
             mEglSurfaces[i] = eglCreateWindowSurface(mEglDisplay, myConfig,
                     static_cast<ANativeWindow*>(stc.get()), NULL);
diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp
index dd6c435..e6d87db 100644
--- a/libs/gui/tests/SurfaceTexture_test.cpp
+++ b/libs/gui/tests/SurfaceTexture_test.cpp
@@ -385,7 +385,8 @@
 
     virtual void SetUp() {
         GLTest::SetUp();
-        mGlConsumer = new GLConsumer(TEX_ID);
+        sp<BufferQueue> bq = new BufferQueue();
+        mGlConsumer = new GLConsumer(bq, TEX_ID);
         mSurface = new Surface(mGlConsumer->getBufferQueue());
         mANW = mSurface.get();
 
@@ -479,7 +480,8 @@
 
     virtual void SetUp() {
         GLTest::SetUp();
-        mST = new GLConsumer(TEX_ID);
+        sp<BufferQueue> bq = new BufferQueue();
+        mST = new GLConsumer(bq, TEX_ID);
         mSTC = new Surface(mST->getBufferQueue());
         mANW = mSTC;
         mTextureRenderer = new TextureRenderer(TEX_ID, mST);
@@ -942,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));
@@ -1209,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));
@@ -1235,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));
 
@@ -1256,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));
 
@@ -1270,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));
 
@@ -1304,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));
 
@@ -1415,7 +1406,6 @@
         Mutex mMutex;
     };
 
-    ASSERT_EQ(OK, mST->setSynchronousMode(true));
     ASSERT_EQ(OK, mST->setDefaultMaxBufferCount(2));
 
     sp<Thread> pt(new ProducerThread(mANW));
@@ -1808,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 };
@@ -2283,7 +2247,6 @@
         }
     };
 
-    ASSERT_EQ(OK, mST->setSynchronousMode(true));
     ASSERT_EQ(OK, mST->setDefaultMaxBufferCount(2));
 
     runProducerThread(new PT());
@@ -2824,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/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 429becf..953f6f9 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -87,7 +87,8 @@
     sp<ANativeWindow> anw(mSurface);
 
     // Verify the screenshot works with no protected buffers.
-    sp<CpuConsumer> consumer = new CpuConsumer(1);
+    sp<BufferQueue> bq = new BufferQueue();
+    sp<CpuConsumer> consumer = new CpuConsumer(bq, 1);
     sp<ISurfaceComposer> sf(ComposerService::getComposerService());
     sp<IBinder> display(sf->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
     ASSERT_EQ(NO_ERROR, sf->captureScreen(display, consumer->getBufferQueue(),
diff --git a/libs/input/Android.mk b/libs/input/Android.mk
index 2a1e762..944ac7f 100644
--- a/libs/input/Android.mk
+++ b/libs/input/Android.mk
@@ -12,8 +12,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-ifneq ($(TARGET_BUILD_PDK),true)
-
 LOCAL_PATH:= $(call my-dir)
 
 # libinput is partially built for the host (used by build time keymap validation tool)
@@ -29,6 +27,7 @@
 
 deviceSources := \
     $(commonSources) \
+    IInputFlinger.cpp \
     InputTransport.cpp \
     VelocityControl.cpp \
     VelocityTracker.cpp
@@ -61,14 +60,7 @@
 	liblog \
 	libcutils \
 	libutils \
-	libbinder \
-	libskia \
-	libz
-
-LOCAL_C_INCLUDES := \
-    external/skia/include/core \
-    external/icu4c/common \
-	external/zlib
+	libbinder
 
 LOCAL_MODULE:= libinput
 
@@ -85,5 +77,3 @@
 ifeq (,$(ONE_SHOT_MAKEFILE))
 include $(call first-makefiles-under,$(LOCAL_PATH))
 endif
-
-endif #!PDK
diff --git a/libs/input/IInputFlinger.cpp b/libs/input/IInputFlinger.cpp
new file mode 100644
index 0000000..e009731
--- /dev/null
+++ b/libs/input/IInputFlinger.cpp
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+
+#include <input/IInputFlinger.h>
+
+
+namespace android {
+
+class BpInputFlinger : public BpInterface<IInputFlinger> {
+public:
+    BpInputFlinger(const sp<IBinder>& impl) :
+            BpInterface<IInputFlinger>(impl) { }
+
+    virtual status_t doSomething() {
+        Parcel data, reply;
+        data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor());
+        remote()->transact(BnInputFlinger::DO_SOMETHING_TRANSACTION, data, &reply);
+        return reply.readInt32();
+    }
+};
+
+IMPLEMENT_META_INTERFACE(InputFlinger, "android.input.IInputFlinger");
+
+
+status_t BnInputFlinger::onTransact(
+        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
+    switch(code) {
+    case DO_SOMETHING_TRANSACTION: {
+        CHECK_INTERFACE(IInputFlinger, data, reply);
+        reply->writeInt32(0);
+        break;
+    }
+    default:
+        return BBinder::onTransact(code, data, reply, flags);
+    }
+    return NO_ERROR;
+}
+
+};
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index 7a217c3..6f53996 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -24,10 +24,6 @@
 
 #ifdef HAVE_ANDROID_OS
 #include <binder/Parcel.h>
-
-#include "SkPoint.h"
-#include "SkMatrix.h"
-#include "SkScalar.h"
 #endif
 
 namespace android {
@@ -74,6 +70,7 @@
         case AKEYCODE_MUTE:
         case AKEYCODE_BRIGHTNESS_DOWN:
         case AKEYCODE_BRIGHTNESS_UP:
+        case AKEYCODE_MEDIA_AUDIO_TRACK:
             return true;
     }
     
@@ -112,6 +109,7 @@
         case AKEYCODE_SEARCH:
         case AKEYCODE_BRIGHTNESS_DOWN:
         case AKEYCODE_BRIGHTNESS_UP:
+        case AKEYCODE_MEDIA_AUDIO_TRACK:
             return true;
     }
     
@@ -421,17 +419,30 @@
     }
 }
 
-#ifdef HAVE_ANDROID_OS
-static inline float transformAngle(const SkMatrix* matrix, float angleRadians) {
+static void transformPoint(const float matrix[9], float x, float y, float *outX, float *outY) {
+    // Apply perspective transform like Skia.
+    float newX = matrix[0] * x + matrix[1] * y + matrix[2];
+    float newY = matrix[3] * x + matrix[4] * y + matrix[5];
+    float newZ = matrix[6] * x + matrix[7] * y + matrix[8];
+    if (newZ) {
+        newZ = 1.0f / newZ;
+    }
+    *outX = newX * newZ;
+    *outY = newY * newZ;
+}
+
+static float transformAngle(const float matrix[9], float angleRadians,
+        float originX, float originY) {
     // Construct and transform a vector oriented at the specified clockwise angle from vertical.
     // Coordinate system: down is increasing Y, right is increasing X.
-    SkPoint vector;
-    vector.fX = SkFloatToScalar(sinf(angleRadians));
-    vector.fY = SkFloatToScalar(-cosf(angleRadians));
-    matrix->mapVectors(& vector, 1);
+    float x = sinf(angleRadians);
+    float y = -cosf(angleRadians);
+    transformPoint(matrix, x, y, &x, &y);
+    x -= originX;
+    y -= originY;
 
     // Derive the transformed vector's clockwise angle from vertical.
-    float result = atan2f(SkScalarToFloat(vector.fX), SkScalarToFloat(-vector.fY));
+    float result = atan2f(x, -y);
     if (result < - M_PI_2) {
         result += M_PI;
     } else if (result > M_PI_2) {
@@ -440,25 +451,24 @@
     return result;
 }
 
-void MotionEvent::transform(const SkMatrix* matrix) {
-    float oldXOffset = mXOffset;
-    float oldYOffset = mYOffset;
-
+void MotionEvent::transform(const float matrix[9]) {
     // The tricky part of this implementation is to preserve the value of
     // rawX and rawY.  So we apply the transformation to the first point
-    // then derive an appropriate new X/Y offset that will preserve rawX and rawY.
-    SkPoint point;
+    // then derive an appropriate new X/Y offset that will preserve rawX
+     // and rawY for that point.
+    float oldXOffset = mXOffset;
+    float oldYOffset = mYOffset;
+    float newX, newY;
     float rawX = getRawX(0);
     float rawY = getRawY(0);
-    matrix->mapXY(SkFloatToScalar(rawX + oldXOffset), SkFloatToScalar(rawY + oldYOffset),
-            & point);
-    float newX = SkScalarToFloat(point.fX);
-    float newY = SkScalarToFloat(point.fY);
-    float newXOffset = newX - rawX;
-    float newYOffset = newY - rawY;
+    transformPoint(matrix, rawX + oldXOffset, rawY + oldYOffset, &newX, &newY);
+    mXOffset = newX - rawX;
+    mYOffset = newY - rawY;
 
-    mXOffset = newXOffset;
-    mYOffset = newYOffset;
+    // Determine how the origin is transformed by the matrix so that we
+    // can transform orientation vectors.
+    float originX, originY;
+    transformPoint(matrix, 0, 0, &originX, &originY);
 
     // Apply the transformation to all samples.
     size_t numSamples = mSamplePointerCoords.size();
@@ -466,15 +476,17 @@
         PointerCoords& c = mSamplePointerCoords.editItemAt(i);
         float x = c.getAxisValue(AMOTION_EVENT_AXIS_X) + oldXOffset;
         float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y) + oldYOffset;
-        matrix->mapXY(SkFloatToScalar(x), SkFloatToScalar(y), &point);
-        c.setAxisValue(AMOTION_EVENT_AXIS_X, SkScalarToFloat(point.fX) - newXOffset);
-        c.setAxisValue(AMOTION_EVENT_AXIS_Y, SkScalarToFloat(point.fY) - newYOffset);
+        transformPoint(matrix, x, y, &x, &y);
+        c.setAxisValue(AMOTION_EVENT_AXIS_X, x - mXOffset);
+        c.setAxisValue(AMOTION_EVENT_AXIS_Y, y - mYOffset);
 
         float orientation = c.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION);
-        c.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, transformAngle(matrix, orientation));
+        c.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION,
+                transformAngle(matrix, orientation, originX, originY));
     }
 }
 
+#ifdef HAVE_ANDROID_OS
 status_t MotionEvent::readFromParcel(Parcel* parcel) {
     size_t pointerCount = parcel->readInt32();
     size_t sampleCount = parcel->readInt32();
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/libs/input/tests/Android.mk b/libs/input/tests/Android.mk
index 4292741..c62dff1 100644
--- a/libs/input/tests/Android.mk
+++ b/libs/input/tests/Android.mk
@@ -14,8 +14,7 @@
     libutils \
     libbinder \
     libui \
-    libstlport \
-    libskia
+    libstlport
 
 static_libraries := \
     libgtest \
diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp
index ab1feb3..78ea98e 100644
--- a/libs/input/tests/InputEvent_test.cpp
+++ b/libs/input/tests/InputEvent_test.cpp
@@ -17,7 +17,6 @@
 #include <math.h>
 
 #include <binder/Parcel.h>
-#include <core/SkMatrix.h>
 #include <gtest/gtest.h>
 #include <input/Input.h>
 
@@ -519,6 +518,20 @@
     ASSERT_NO_FATAL_FAILURE(assertEqualsEventWithHistory(&outEvent));
 }
 
+static void setRotationMatrix(float matrix[9], float angle) {
+    float sin = sinf(angle);
+    float cos = cosf(angle);
+    matrix[0] = cos;
+    matrix[1] = -sin;
+    matrix[2] = 0;
+    matrix[3] = sin;
+    matrix[4] = cos;
+    matrix[5] = 0;
+    matrix[6] = 0;
+    matrix[7] = 0;
+    matrix[8] = 1.0f;
+}
+
 TEST_F(MotionEventTest, Transform) {
     // Generate some points on a circle.
     // Each point 'i' is a point on a circle of radius ROTATION centered at (3,2) at an angle
@@ -561,9 +574,9 @@
     ASSERT_NEAR(originalRawY, event.getRawY(0), 0.001);
 
     // Apply a rotation about the origin by ROTATION degrees clockwise.
-    SkMatrix matrix;
-    matrix.setRotate(ROTATION);
-    event.transform(&matrix);
+    float matrix[9];
+    setRotationMatrix(matrix, ROTATION * PI_180);
+    event.transform(matrix);
 
     // Check the points.
     for (size_t i = 0; i < pointerCount; i++) {
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 015740a..6c285d3 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -373,7 +373,7 @@
         if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) != OK) {
             ALOGE("EGLNativeWindowType %p already connected to another API",
                     window);
-            return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
+            return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
         }
 
         // set the native window's buffers format to match this config
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
new file mode 100644
index 0000000..e32d38a
--- /dev/null
+++ b/services/inputflinger/Android.mk
@@ -0,0 +1,50 @@
+# 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:= \
+    InputFlinger.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+    libbinder \
+    libcutils \
+    libinput \
+    liblog \
+    libutils
+
+LOCAL_CFLAGS += -fvisibility=hidden
+
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
+
+LOCAL_MODULE := libinputflinger
+
+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/services/inputflinger/InputFlinger.cpp b/services/inputflinger/InputFlinger.cpp
new file mode 100644
index 0000000..9ea6ce5
--- /dev/null
+++ b/services/inputflinger/InputFlinger.cpp
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "InputFlinger"
+
+#include "InputFlinger.h"
+
+#include <stdint.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+
+#include <binder/IPCThreadState.h>
+#include <binder/PermissionCache.h>
+#include <cutils/log.h>
+#include <private/android_filesystem_config.h>
+
+namespace android {
+
+const String16 sAccessInputFlingerPermission("android.permission.ACCESS_INPUT_FLINGER");
+const String16 sDumpPermission("android.permission.DUMP");
+
+
+InputFlinger::InputFlinger() :
+        BnInputFlinger() {
+    ALOGI("InputFlinger is starting");
+}
+
+InputFlinger::~InputFlinger() {
+}
+
+status_t InputFlinger::onTransact(
+        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
+    switch (code) {
+    case DO_SOMETHING_TRANSACTION:
+        const IPCThreadState* ipc = IPCThreadState::self();
+        const int pid = ipc->getCallingPid();
+        const int uid = ipc->getCallingUid();
+        if (!PermissionCache::checkPermission(sAccessInputFlingerPermission, pid, uid)) {
+            ALOGE("Permission Denial: "
+                    "can't access InputFlinger from pid=%d, uid=%d", pid, uid);
+            return PERMISSION_DENIED;
+        }
+        break;
+    }
+
+    return BnInputFlinger::onTransact(code, data, reply, flags);
+}
+
+status_t InputFlinger::dump(int fd, const Vector<String16>& args) {
+    String8 result;
+    const IPCThreadState* ipc = IPCThreadState::self();
+    const int pid = ipc->getCallingPid();
+    const int uid = ipc->getCallingUid();
+    if ((uid != AID_SHELL)
+            && !PermissionCache::checkPermission(sDumpPermission, pid, uid)) {
+        result.appendFormat("Permission Denial: "
+                "can't dump SurfaceFlinger from pid=%d, uid=%d\n", pid, uid);
+    } else {
+        dumpInternal(result);
+    }
+    write(fd, result.string(), result.size());
+    return OK;
+}
+
+void InputFlinger::dumpInternal(String8& result) {
+    result.append("INPUT FLINGER (dumpsys inputflinger)\n");
+    result.append("... nothing here yet...\n");
+}
+
+status_t InputFlinger::doSomething() {
+    ALOGI("Did something...");
+    return OK;
+}
+
+}; // namespace android
diff --git a/services/inputflinger/InputFlinger.h b/services/inputflinger/InputFlinger.h
new file mode 100644
index 0000000..731ab17
--- /dev/null
+++ b/services/inputflinger/InputFlinger.h
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_INPUT_FLINGER_H
+#define ANDROID_INPUT_FLINGER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <cutils/compiler.h>
+#include <input/IInputFlinger.h>
+#include <utils/String8.h>
+#include <utils/String16.h>
+
+namespace android {
+
+class InputFlinger : public BnInputFlinger {
+public:
+    static char const* getServiceName() ANDROID_API {
+        return "inputflinger";
+    }
+
+    InputFlinger() ANDROID_API;
+
+    // IBinder interface
+    virtual status_t onTransact(uint32_t code,
+            const Parcel& data, Parcel* reply, uint32_t flags);
+    virtual status_t dump(int fd, const Vector<String16>& args);
+
+    // IInputFlinger interface
+    virtual status_t doSomething();
+
+private:
+    virtual ~InputFlinger();
+
+    void dumpInternal(String8& result);
+};
+
+} // namespace android
+
+#endif // ANDROID_INPUT_FLINGER_H
diff --git a/cmds/sensorservice/main_sensorservice.cpp b/services/inputflinger/main.cpp
similarity index 76%
copy from cmds/sensorservice/main_sensorservice.cpp
copy to services/inputflinger/main.cpp
index 8610627..3209a62 100644
--- a/cmds/sensorservice/main_sensorservice.cpp
+++ b/services/inputflinger/main.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 The Android Open Source Project
+ * 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.
@@ -15,11 +15,12 @@
  */
 
 #include <binder/BinderService.h>
-#include <SensorService.h>
+#include "InputFlinger.h"
 
 using namespace android;
 
 int main(int argc, char** argv) {
-    SensorService::publishAndJoinThreadPool();
+    ProcessState::self()->setThreadPoolMaxThreadCount(4);
+    BinderService<InputFlinger>::publishAndJoinThreadPool(true);
     return 0;
 }
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/services/sensorservice/BatteryService.cpp b/services/sensorservice/BatteryService.cpp
index 70b65ab..38dc749 100644
--- a/services/sensorservice/BatteryService.cpp
+++ b/services/sensorservice/BatteryService.cpp
@@ -33,7 +33,7 @@
 BatteryService::BatteryService() {
     const sp<IServiceManager> sm(defaultServiceManager());
     if (sm != NULL) {
-        const String16 name("batteryinfo");
+        const String16 name("batterystats");
         mBatteryStatService = sm->getService(name);
     }
 }
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/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 2eae9c2..c67f4d8 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -188,6 +188,25 @@
     mPageFlipCount++;
 }
 
+status_t DisplayDevice::prepareFrame(const HWComposer& hwc) const {
+    DisplaySurface::CompositionType compositionType;
+    bool haveGles = hwc.hasGlesComposition(mHwcDisplayId);
+    bool haveHwc = hwc.hasHwcComposition(mHwcDisplayId);
+    if (haveGles && haveHwc) {
+        compositionType = DisplaySurface::COMPOSITION_MIXED;
+    } else if (haveGles) {
+        compositionType = DisplaySurface::COMPOSITION_GLES;
+    } else if (haveHwc) {
+        compositionType = DisplaySurface::COMPOSITION_HWC;
+    } else {
+        // Nothing to do -- when turning the screen off we get a frame like
+        // this. Call it a HWC frame since we won't be doing any GLES work but
+        // will do a prepare/set cycle.
+        compositionType = DisplaySurface::COMPOSITION_HWC;
+    }
+    return mDisplaySurface->prepareFrame(compositionType);
+}
+
 void DisplayDevice::swapBuffers(HWComposer& hwc) const {
     // We need to call eglSwapBuffers() unless:
     // (a) there was no GLES composition this frame, or
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index eefc107..748be1a 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -119,6 +119,8 @@
     int32_t                 getHwcDisplayId() const { return mHwcDisplayId; }
     const wp<IBinder>&      getDisplayToken() const { return mDisplayToken; }
 
+    status_t prepareFrame(const HWComposer& hwc) const;
+
     void swapBuffers(HWComposer& hwc) const;
     status_t compositionComplete() const;
 
diff --git a/services/surfaceflinger/DisplayHardware/DisplaySurface.h b/services/surfaceflinger/DisplayHardware/DisplaySurface.h
index 2eca3cb..b0f460d 100644
--- a/services/surfaceflinger/DisplayHardware/DisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/DisplaySurface.h
@@ -32,6 +32,18 @@
 public:
     virtual sp<IGraphicBufferProducer> getIGraphicBufferProducer() const = 0;
 
+    // prepareFrame is called after the composition configuration is known but
+    // before composition takes place. The DisplaySurface can use the
+    // composition type to decide how to manage the flow of buffers between
+    // GLES and HWC for this frame.
+    enum CompositionType {
+        COMPOSITION_UNKNOWN = 0,
+        COMPOSITION_GLES    = 1,
+        COMPOSITION_HWC     = 2,
+        COMPOSITION_MIXED   = COMPOSITION_GLES | COMPOSITION_HWC
+    };
+    virtual status_t prepareFrame(CompositionType compositionType) = 0;
+
     // Should be called when composition rendering is complete for a frame (but
     // eglSwapBuffers hasn't necessarily been called). Required by certain
     // older drivers for synchronization.
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 938459e..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);
 }
 
@@ -72,6 +71,10 @@
     return getBufferQueue();
 }
 
+status_t FramebufferSurface::prepareFrame(CompositionType compositionType) {
+    return NO_ERROR;
+}
+
 status_t FramebufferSurface::advanceFrame() {
     // Once we remove FB HAL support, we can call nextBuffer() from here
     // instead of using onFrameAvailable(). No real benefit, except it'll be
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index c86e9ae..92a7f9b 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -41,6 +41,7 @@
 
     virtual sp<IGraphicBufferProducer> getIGraphicBufferProducer() const;
 
+    virtual status_t prepareFrame(CompositionType compositionType);
     virtual status_t compositionComplete();
     virtual status_t advanceFrame();
     virtual void onFrameCommitted();
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 1cdabc4..f6256f9 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -16,9 +16,6 @@
 
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
-// Uncomment this to remove support for HWC_DEVICE_API_VERSION_0_3 and older
-#define HWC_REMOVE_DEPRECATED_VERSIONS 1
-
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -51,9 +48,9 @@
 
 namespace android {
 
-// This is not a real HWC version. It's used for in-development features that
-// haven't been committed to a specific real HWC version.
-#define HWC_DEVICE_API_VERSION_1_EXP HARDWARE_DEVICE_API_VERSION_2(1, 0xFF, HWC_HEADER_VERSION)
+#ifndef HWC_DEVICE_API_VERSION_1_3
+#define HWC_DEVICE_API_VERSION_1_3 HARDWARE_DEVICE_API_VERSION_2(1, 3, HWC_HEADER_VERSION)
+#endif
 
 #define MIN_HWC_HEADER_VERSION HWC_HEADER_VERSION
 
@@ -157,8 +154,8 @@
 
         // the number of displays we actually have depends on the
         // hw composer version
-        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_EXP)) {
-            // 1.?? adds support for virtual displays
+        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
+            // 1.3 adds support for virtual displays
             mNumDisplays = MAX_DISPLAYS;
         } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
             // 1.1 adds support for multiple displays
@@ -583,7 +580,7 @@
         }
         mLists[i] = disp.list;
         if (mLists[i]) {
-            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_EXP)) {
+            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
                 mLists[i]->outbuf = NULL;
                 mLists[i]->outbufAcquireFenceFd = -1;
             } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 2838b23..57cb361 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -14,27 +14,89 @@
  * limitations under the License.
  */
 
+// #define LOG_NDEBUG 0
 #include "VirtualDisplaySurface.h"
-
-#include <cutils/log.h>
-#include <gui/IGraphicBufferProducer.h>
+#include "HWComposer.h"
 
 // ---------------------------------------------------------------------------
 namespace android {
 // ---------------------------------------------------------------------------
 
+#define VDS_LOGE(msg, ...) ALOGE("[%s] "msg, \
+        mDisplayName.string(), ##__VA_ARGS__)
+#define VDS_LOGW_IF(cond, msg, ...) ALOGW_IF(cond, "[%s] "msg, \
+        mDisplayName.string(), ##__VA_ARGS__)
+#define VDS_LOGV(msg, ...) ALOGV("[%s] "msg, \
+        mDisplayName.string(), ##__VA_ARGS__)
+
+static const char* dbgCompositionTypeStr(DisplaySurface::CompositionType type) {
+    switch (type) {
+        case DisplaySurface::COMPOSITION_UNKNOWN: return "UNKNOWN";
+        case DisplaySurface::COMPOSITION_GLES:    return "GLES";
+        case DisplaySurface::COMPOSITION_HWC:     return "HWC";
+        case DisplaySurface::COMPOSITION_MIXED:   return "MIXED";
+        default:                                  return "<INVALID>";
+    }
+}
+
 VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId,
         const sp<IGraphicBufferProducer>& sink, const String8& name)
-:   mSink(sink)
+:   ConsumerBase(new BufferQueue()),
+    mHwc(hwc),
+    mDisplayId(dispId),
+    mDisplayName(name),
+    mProducerUsage(GRALLOC_USAGE_HW_COMPOSER),
+    mProducerSlotSource(0),
+    mDbgState(DBG_STATE_IDLE),
+    mDbgLastCompositionType(COMPOSITION_UNKNOWN)
 {
-    LOG_ALWAYS_FATAL_IF(dispId >= 0);
+    mSource[SOURCE_SINK] = sink;
+    mSource[SOURCE_SCRATCH] = mBufferQueue;
+
+    resetPerFrameState();
+
+    int sinkWidth, sinkHeight;
+    mSource[SOURCE_SINK]->query(NATIVE_WINDOW_WIDTH, &sinkWidth);
+    mSource[SOURCE_SINK]->query(NATIVE_WINDOW_HEIGHT, &sinkHeight);
+
+    ConsumerBase::mName = String8::format("VDS: %s", mDisplayName.string());
+    mBufferQueue->setConsumerName(ConsumerBase::mName);
+    mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_HW_COMPOSER);
+    mBufferQueue->setDefaultBufferSize(sinkWidth, sinkHeight);
+    mBufferQueue->setDefaultMaxBufferCount(2);
 }
 
 VirtualDisplaySurface::~VirtualDisplaySurface() {
 }
 
 sp<IGraphicBufferProducer> VirtualDisplaySurface::getIGraphicBufferProducer() const {
-    return mSink;
+    if (mDisplayId >= 0) {
+        return static_cast<IGraphicBufferProducer*>(
+                const_cast<VirtualDisplaySurface*>(this));
+    } else {
+        // There won't be any interaction with HWC for this virtual display,
+        // so the GLES driver can pass buffers directly to the sink.
+        return mSource[SOURCE_SINK];
+    }
+}
+
+status_t VirtualDisplaySurface::prepareFrame(CompositionType compositionType) {
+    if (mDisplayId < 0)
+        return NO_ERROR;
+
+    VDS_LOGW_IF(mDbgState != DBG_STATE_IDLE,
+            "Unexpected prepareFrame() in %s state", dbgStateStr());
+    mDbgState = DBG_STATE_PREPARED;
+
+    mCompositionType = compositionType;
+
+    if (mCompositionType != mDbgLastCompositionType) {
+        VDS_LOGV("prepareFrame: composition type changed to %s",
+                dbgCompositionTypeStr(mCompositionType));
+        mDbgLastCompositionType = mCompositionType;
+    }
+
+    return NO_ERROR;
 }
 
 status_t VirtualDisplaySurface::compositionComplete() {
@@ -42,15 +104,317 @@
 }
 
 status_t VirtualDisplaySurface::advanceFrame() {
-    return NO_ERROR;
+    if (mDisplayId < 0)
+        return NO_ERROR;
+
+    if (mCompositionType == COMPOSITION_HWC) {
+        VDS_LOGW_IF(mDbgState != DBG_STATE_PREPARED,
+                "Unexpected advanceFrame() in %s state on HWC frame",
+                dbgStateStr());
+    } else {
+        VDS_LOGW_IF(mDbgState != DBG_STATE_GLES_DONE,
+                "Unexpected advanceFrame() in %s state on GLES/MIXED frame",
+                dbgStateStr());
+    }
+    mDbgState = DBG_STATE_HWC;
+
+    status_t result;
+    sp<Fence> outFence;
+    if (mCompositionType != COMPOSITION_GLES) {
+        // Dequeue an output buffer from the sink
+        uint32_t transformHint, numPendingBuffers;
+        mQueueBufferOutput.deflate(&mSinkBufferWidth, &mSinkBufferHeight,
+                &transformHint, &numPendingBuffers);
+        int sslot;
+        result = dequeueBuffer(SOURCE_SINK, 0, &sslot, &outFence, false);
+        if (result < 0)
+            return result;
+        mOutputProducerSlot = mapSource2ProducerSlot(SOURCE_SINK, sslot);
+    }
+
+    if (mCompositionType == COMPOSITION_HWC) {
+        // We just dequeued the output buffer, use it for FB as well
+        mFbProducerSlot = mOutputProducerSlot;
+        mFbFence = outFence;
+    } else if (mCompositionType == COMPOSITION_GLES) {
+        mOutputProducerSlot = mFbProducerSlot;
+        outFence = mFbFence;
+    } else {
+        // mFbFence and mFbProducerSlot were set in queueBuffer,
+        // and mOutputProducerSlot and outFence were set above when dequeueing
+        // the sink buffer.
+    }
+
+    if (mFbProducerSlot < 0 || mOutputProducerSlot < 0) {
+        // Last chance bailout if something bad happened earlier. For example,
+        // in a GLES configuration, if the sink disappears then dequeueBuffer
+        // will fail, the GLES driver won't queue a buffer, but SurfaceFlinger
+        // will soldier on. So we end up here without a buffer. There should
+        // be lots of scary messages in the log just before this.
+        VDS_LOGE("advanceFrame: no buffer, bailing out");
+        return NO_MEMORY;
+    }
+
+    sp<GraphicBuffer> fbBuffer = mProducerBuffers[mFbProducerSlot];
+    sp<GraphicBuffer> outBuffer = mProducerBuffers[mOutputProducerSlot];
+    VDS_LOGV("advanceFrame: fb=%d(%p) out=%d(%p)",
+            mFbProducerSlot, fbBuffer.get(),
+            mOutputProducerSlot, outBuffer.get());
+
+    result = mHwc.fbPost(mDisplayId, mFbFence, fbBuffer);
+    if (result == NO_ERROR) {
+        result = mHwc.setOutputBuffer(mDisplayId, outFence, outBuffer);
+    }
+
+    return result;
 }
 
 void VirtualDisplaySurface::onFrameCommitted() {
+    if (mDisplayId < 0)
+        return;
+
+    VDS_LOGW_IF(mDbgState != DBG_STATE_HWC,
+            "Unexpected onFrameCommitted() in %s state", dbgStateStr());
+    mDbgState = DBG_STATE_IDLE;
+
+    sp<Fence> fbFence = mHwc.getAndResetReleaseFence(mDisplayId);
+    if (mCompositionType == COMPOSITION_MIXED && mFbProducerSlot >= 0) {
+        // release the scratch buffer back to the pool
+        Mutex::Autolock lock(mMutex);
+        int sslot = mapProducer2SourceSlot(SOURCE_SCRATCH, mFbProducerSlot);
+        VDS_LOGV("onFrameCommitted: release scratch sslot=%d", sslot);
+        addReleaseFenceLocked(sslot, mProducerBuffers[mFbProducerSlot], fbFence);
+        releaseBufferLocked(sslot, mProducerBuffers[mFbProducerSlot],
+                EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
+    }
+
+    if (mOutputProducerSlot >= 0) {
+        int sslot = mapProducer2SourceSlot(SOURCE_SINK, mOutputProducerSlot);
+        QueueBufferOutput qbo;
+        sp<Fence> outFence = mHwc.getLastRetireFence(mDisplayId);
+        VDS_LOGV("onFrameCommitted: queue sink sslot=%d", sslot);
+        status_t result = mSource[SOURCE_SINK]->queueBuffer(sslot,
+                QueueBufferInput(systemTime(),
+                    Rect(mSinkBufferWidth, mSinkBufferHeight),
+                    NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, outFence),
+                &qbo);
+        if (result == NO_ERROR) {
+            updateQueueBufferOutput(qbo);
+        }
+    }
+
+    resetPerFrameState();
 }
 
 void VirtualDisplaySurface::dump(String8& result) const {
 }
 
+status_t VirtualDisplaySurface::requestBuffer(int pslot,
+        sp<GraphicBuffer>* outBuf) {
+    VDS_LOGW_IF(mDbgState != DBG_STATE_GLES,
+            "Unexpected requestBuffer pslot=%d in %s state",
+            pslot, dbgStateStr());
+
+    *outBuf = mProducerBuffers[pslot];
+    return NO_ERROR;
+}
+
+status_t VirtualDisplaySurface::setBufferCount(int bufferCount) {
+    return mSource[SOURCE_SINK]->setBufferCount(bufferCount);
+}
+
+status_t VirtualDisplaySurface::dequeueBuffer(Source source,
+        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;
+    int pslot = mapSource2ProducerSlot(source, *sslot);
+    VDS_LOGV("dequeueBuffer(%s): sslot=%d pslot=%d result=%d",
+            dbgSourceStr(source), *sslot, pslot, result);
+    uint32_t sourceBit = static_cast<uint32_t>(source) << pslot;
+
+    if ((mProducerSlotSource & (1u << pslot)) != sourceBit) {
+        // This slot was previously dequeued from the other source; must
+        // re-request the buffer.
+        result |= BUFFER_NEEDS_REALLOCATION;
+        mProducerSlotSource &= ~(1u << pslot);
+        mProducerSlotSource |= sourceBit;
+    }
+
+    if (result & RELEASE_ALL_BUFFERS) {
+        for (uint32_t i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
+            if ((mProducerSlotSource & (1u << i)) == sourceBit)
+                mProducerBuffers[i].clear();
+        }
+    }
+    if (result & BUFFER_NEEDS_REALLOCATION) {
+        mSource[source]->requestBuffer(*sslot, &mProducerBuffers[pslot]);
+        VDS_LOGV("dequeueBuffer(%s): buffers[%d]=%p",
+                dbgSourceStr(source), pslot, mProducerBuffers[pslot].get());
+    }
+
+    return result;
+}
+
+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());
+    mDbgState = DBG_STATE_GLES;
+
+    VDS_LOGV("dequeueBuffer %dx%d fmt=%d usage=%#x", w, h, format, usage);
+
+    mProducerUsage = usage | GRALLOC_USAGE_HW_COMPOSER;
+    Source source = fbSourceForCompositionType(mCompositionType);
+    if (source == SOURCE_SINK) {
+        mSinkBufferWidth = w;
+        mSinkBufferHeight = h;
+    }
+
+    int sslot;
+    status_t result = dequeueBuffer(source, format, &sslot, fence, async);
+    if (result >= 0) {
+        *pslot = mapSource2ProducerSlot(source, sslot);
+    }
+    return result;
+}
+
+status_t VirtualDisplaySurface::queueBuffer(int pslot,
+        const QueueBufferInput& input, QueueBufferOutput* output) {
+    VDS_LOGW_IF(mDbgState != DBG_STATE_GLES,
+            "Unexpected queueBuffer(pslot=%d) in %s state", pslot,
+            dbgStateStr());
+    mDbgState = DBG_STATE_GLES_DONE;
+
+    VDS_LOGV("queueBuffer pslot=%d", pslot);
+
+    status_t result;
+    if (mCompositionType == COMPOSITION_MIXED) {
+        // Queue the buffer back into the scratch pool
+        QueueBufferOutput scratchQBO;
+        int sslot = mapProducer2SourceSlot(SOURCE_SCRATCH, pslot);
+        result = mBufferQueue->queueBuffer(sslot, input, &scratchQBO);
+        if (result != NO_ERROR)
+            return result;
+
+        // Now acquire the buffer from the scratch pool -- should be the same
+        // slot and fence as we just queued.
+        Mutex::Autolock lock(mMutex);
+        BufferQueue::BufferItem item;
+        result = acquireBufferLocked(&item, 0);
+        if (result != NO_ERROR)
+            return result;
+        VDS_LOGW_IF(item.mBuf != sslot,
+                "queueBuffer: acquired sslot %d from SCRATCH after queueing sslot %d",
+                item.mBuf, sslot);
+        mFbProducerSlot = mapSource2ProducerSlot(SOURCE_SCRATCH, item.mBuf);
+        mFbFence = mSlots[item.mBuf].mFence;
+
+    } else {
+        LOG_FATAL_IF(mCompositionType != COMPOSITION_GLES,
+                "Unexpected queueBuffer in state %s for compositionType %s",
+                dbgStateStr(), dbgCompositionTypeStr(mCompositionType));
+
+        // Extract the GLES release fence for HWC to acquire
+        int64_t timestamp;
+        Rect crop;
+        int scalingMode;
+        uint32_t transform;
+        bool async;
+        input.deflate(&timestamp, &crop, &scalingMode, &transform,
+                &async, &mFbFence);
+
+        mFbProducerSlot = pslot;
+    }
+
+    *output = mQueueBufferOutput;
+    return NO_ERROR;
+}
+
+void VirtualDisplaySurface::cancelBuffer(int pslot, const sp<Fence>& fence) {
+    VDS_LOGW_IF(mDbgState != DBG_STATE_GLES,
+            "Unexpected cancelBuffer(pslot=%d) in %s state", pslot,
+            dbgStateStr());
+    VDS_LOGV("cancelBuffer pslot=%d", pslot);
+    Source source = fbSourceForCompositionType(mCompositionType);
+    return mSource[source]->cancelBuffer(
+            mapProducer2SourceSlot(source, pslot), fence);
+}
+
+int VirtualDisplaySurface::query(int what, int* value) {
+    return mSource[SOURCE_SINK]->query(what, value);
+}
+
+status_t VirtualDisplaySurface::connect(int api, bool producerControlledByApp,
+        QueueBufferOutput* output) {
+    QueueBufferOutput qbo;
+    status_t result = mSource[SOURCE_SINK]->connect(api, producerControlledByApp, &qbo);
+    if (result == NO_ERROR) {
+        updateQueueBufferOutput(qbo);
+        *output = mQueueBufferOutput;
+    }
+    return result;
+}
+
+status_t VirtualDisplaySurface::disconnect(int api) {
+    return mSource[SOURCE_SINK]->disconnect(api);
+}
+
+void VirtualDisplaySurface::updateQueueBufferOutput(
+        const QueueBufferOutput& qbo) {
+    uint32_t w, h, transformHint, numPendingBuffers;
+    qbo.deflate(&w, &h, &transformHint, &numPendingBuffers);
+    mQueueBufferOutput.inflate(w, h, 0, numPendingBuffers);
+}
+
+void VirtualDisplaySurface::resetPerFrameState() {
+    mCompositionType = COMPOSITION_UNKNOWN;
+    mSinkBufferWidth = 0;
+    mSinkBufferHeight = 0;
+    mFbFence = Fence::NO_FENCE;
+    mFbProducerSlot = -1;
+    mOutputProducerSlot = -1;
+}
+
+// This slot mapping function is its own inverse, so two copies are unnecessary.
+// Both are kept to make the intent clear where the function is called, and for
+// the (unlikely) chance that we switch to a different mapping function.
+int VirtualDisplaySurface::mapSource2ProducerSlot(Source source, int sslot) {
+    if (source == SOURCE_SCRATCH) {
+        return BufferQueue::NUM_BUFFER_SLOTS - sslot - 1;
+    } else {
+        return sslot;
+    }
+}
+int VirtualDisplaySurface::mapProducer2SourceSlot(Source source, int pslot) {
+    return mapSource2ProducerSlot(source, pslot);
+}
+
+VirtualDisplaySurface::Source
+VirtualDisplaySurface::fbSourceForCompositionType(CompositionType type) {
+    return type == COMPOSITION_MIXED ? SOURCE_SCRATCH : SOURCE_SINK;
+}
+
+const char* VirtualDisplaySurface::dbgStateStr() const {
+    switch (mDbgState) {
+        case DBG_STATE_IDLE:      return "IDLE";
+        case DBG_STATE_PREPARED:  return "PREPARED";
+        case DBG_STATE_GLES:      return "GLES";
+        case DBG_STATE_GLES_DONE: return "GLES_DONE";
+        case DBG_STATE_HWC:       return "HWC";
+        default:                  return "INVALID";
+    }
+}
+
+const char* VirtualDisplaySurface::dbgSourceStr(Source s) {
+    switch (s) {
+        case SOURCE_SINK:    return "SINK";
+        case SOURCE_SCRATCH: return "SCRATCH";
+        default:             return "INVALID";
+    }
+}
+
 // ---------------------------------------------------------------------------
 } // namespace android
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index f321795..dc9655b 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -17,6 +17,9 @@
 #ifndef ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H
 #define ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H
 
+#include <gui/ConsumerBase.h>
+#include <gui/IGraphicBufferProducer.h>
+
 #include "DisplaySurface.h"
 
 // ---------------------------------------------------------------------------
@@ -25,26 +28,186 @@
 
 class HWComposer;
 
-/* This DisplaySurface implementation is a stub used for developing HWC
- * virtual display support. It is currently just a passthrough.
+/* This DisplaySurface implementation supports virtual displays, where GLES
+ * and/or HWC compose into a buffer that is then passed to an arbitrary
+ * consumer (the sink) running in another process.
+ *
+ * The simplest case is when the virtual display will never use the h/w
+ * composer -- either the h/w composer doesn't support writing to buffers, or
+ * there are more virtual displays than it supports simultaneously. In this
+ * case, the GLES driver works directly with the output buffer queue, and
+ * calls to the VirtualDisplay from SurfaceFlinger and DisplayHardware do
+ * nothing.
+ *
+ * If h/w composer might be used, then each frame will fall into one of three
+ * configurations: GLES-only, HWC-only, and MIXED composition. In all of these,
+ * we must provide a FB target buffer and output buffer for the HWC set() call.
+ *
+ * In GLES-only composition, the GLES driver is given a buffer from the sink to
+ * render into. When the GLES driver queues the buffer to the
+ * VirtualDisplaySurface, the VirtualDisplaySurface holds onto it instead of
+ * immediately queueing it to the sink. The buffer is used as both the FB
+ * target and output buffer for HWC, though on these frames the HWC doesn't
+ * do any work for this display and doesn't write to the output buffer. After
+ * composition is complete, the buffer is queued to the sink.
+ *
+ * In HWC-only composition, the VirtualDisplaySurface dequeues a buffer from
+ * the sink and passes it to HWC as both the FB target buffer and output
+ * buffer. The HWC doesn't need to read from the FB target buffer, but does
+ * write to the output buffer. After composition is complete, the buffer is
+ * queued to the sink.
+ *
+ * On MIXED frames, things become more complicated, since some h/w composer
+ * implementations can't read from and write to the same buffer. This class has
+ * an internal BufferQueue that it uses as a scratch buffer pool. The GLES
+ * driver is given a scratch buffer to render into. When it finishes rendering,
+ * the buffer is queued and then immediately acquired by the
+ * VirtualDisplaySurface. The scratch buffer is then used as the FB target
+ * buffer for HWC, and a separate buffer is dequeued from the sink and used as
+ * the HWC output buffer. When HWC composition is complete, the scratch buffer
+ * is released and the output buffer is queued to the sink.
  */
-class VirtualDisplaySurface : public DisplaySurface {
+class VirtualDisplaySurface : public DisplaySurface,
+                              private BnGraphicBufferProducer,
+                              private ConsumerBase {
 public:
     VirtualDisplaySurface(HWComposer& hwc, int32_t dispId,
             const sp<IGraphicBufferProducer>& sink,
             const String8& name);
 
+    //
+    // DisplaySurface interface
+    //
     virtual sp<IGraphicBufferProducer> getIGraphicBufferProducer() const;
-
+    virtual status_t prepareFrame(CompositionType compositionType);
     virtual status_t compositionComplete();
     virtual status_t advanceFrame();
     virtual void onFrameCommitted();
     virtual void dump(String8& result) const;
 
 private:
+    enum Source {SOURCE_SINK = 0, SOURCE_SCRATCH = 1};
+
     virtual ~VirtualDisplaySurface();
 
-    sp<IGraphicBufferProducer> mSink;
+    //
+    // IGraphicBufferProducer interface, used by the GLES driver.
+    //
+    virtual status_t requestBuffer(int pslot, sp<GraphicBuffer>* outBuf);
+    virtual status_t setBufferCount(int bufferCount);
+    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 connect(int api, bool producerControlledByApp, QueueBufferOutput* output);
+    virtual status_t disconnect(int api);
+
+    //
+    // Utility methods
+    //
+    static Source fbSourceForCompositionType(CompositionType type);
+    status_t dequeueBuffer(Source source, uint32_t format,
+            int* sslot, sp<Fence>* fence, bool async);
+    void updateQueueBufferOutput(const QueueBufferOutput& qbo);
+    void resetPerFrameState();
+
+    // Both the sink and scratch buffer pools have their own set of slots
+    // ("source slots", or "sslot"). We have to merge these into the single
+    // set of slots used by the GLES producer ("producer slots" or "pslot") and
+    // internally in the VirtualDisplaySurface. To minimize the number of times
+    // a producer slot switches which source it comes from, we map source slot
+    // numbers to producer slot numbers differently for each source.
+    static int mapSource2ProducerSlot(Source source, int sslot);
+    static int mapProducer2SourceSlot(Source source, int pslot);
+
+    //
+    // Immutable after construction
+    //
+    HWComposer& mHwc;
+    const int32_t mDisplayId;
+    const String8 mDisplayName;
+    sp<IGraphicBufferProducer> mSource[2]; // indexed by SOURCE_*
+
+    //
+    // Inter-frame state
+    //
+
+    // To avoid buffer reallocations, we track the buffer usage requested by
+    // the GLES driver in dequeueBuffer so we can use the same flags on
+    // HWC-only frames.
+    uint32_t mProducerUsage;
+
+    // Since we present a single producer interface to the GLES driver, but
+    // are internally muxing between the sink and scratch producers, we have
+    // to keep track of which source last returned each producer slot from
+    // dequeueBuffer. Each bit in mLastSlotSource corresponds to a producer
+    // slot. Both mProducerSlotSource and mProducerBuffers are indexed by a
+    // "producer slot"; see the mapSlot*() functions.
+    uint32_t mProducerSlotSource;
+    sp<GraphicBuffer> mProducerBuffers[BufferQueue::NUM_BUFFER_SLOTS];
+
+    // The QueueBufferOutput with the latest info from the sink, and with the
+    // transform hint cleared. Since we defer queueBuffer from the GLES driver
+    // to the sink, we have to return the previous version.
+    QueueBufferOutput mQueueBufferOutput;
+
+    //
+    // Intra-frame state
+    //
+
+    // Composition type and GLES buffer source for the current frame.
+    // Valid after prepareFrame(), cleared in onFrameCommitted.
+    CompositionType mCompositionType;
+
+    // Details of the current sink buffer. These become valid when a buffer is
+    // dequeued from the sink, and are used when queueing the buffer.
+    uint32_t mSinkBufferWidth, mSinkBufferHeight;
+
+    // mFbFence is the fence HWC should wait for before reading the framebuffer
+    // target buffer.
+    sp<Fence> mFbFence;
+
+    // Producer slot numbers for the buffers to use for HWC framebuffer target
+    // and output.
+    int mFbProducerSlot;
+    int mOutputProducerSlot;
+
+    // Debug only -- track the sequence of events in each frame so we can make
+    // sure they happen in the order we expect. This class implicitly models
+    // a state machine; this enum/variable makes it explicit.
+    //
+    // +-----------+-------------------+-------------+
+    // | State     | Event             || Next State |
+    // +-----------+-------------------+-------------+
+    // | IDLE      | prepareFrame      || PREPARED   |
+    // | PREPARED  | dequeueBuffer [1] || GLES       |
+    // | PREPARED  | advanceFrame [2]  || HWC        |
+    // | GLES      | queueBuffer       || GLES_DONE  |
+    // | GLES_DONE | advanceFrame      || HWC        |
+    // | HWC       | onFrameCommitted  || IDLE       |
+    // +-----------+-------------------++------------+
+    // [1] COMPOSITION_GLES and COMPOSITION_MIXED frames.
+    // [2] COMPOSITION_HWC frames.
+    //
+    enum DbgState {
+        // no buffer dequeued, don't know anything about the next frame
+        DBG_STATE_IDLE,
+        // no buffer dequeued, but we know the buffer source for the frame
+        DBG_STATE_PREPARED,
+        // GLES driver has a buffer dequeued
+        DBG_STATE_GLES,
+        // GLES driver has queued the buffer, we haven't sent it to HWC yet
+        DBG_STATE_GLES_DONE,
+        // HWC has the buffer for this frame
+        DBG_STATE_HWC,
+    };
+    DbgState mDbgState;
+    CompositionType mDbgLastCompositionType;
+
+    const char* dbgStateStr() const;
+    static const char* dbgSourceStr(Source s);
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h
index f6bd676..35ac0c8 100644
--- a/services/surfaceflinger/EventThread.h
+++ b/services/surfaceflinger/EventThread.h
@@ -104,7 +104,7 @@
     // protected by mLock
     SortedVector< wp<Connection> > mDisplayEventConnections;
     Vector< DisplayEventReceiver::Event > mPendingEvents;
-    DisplayEventReceiver::Event mVSyncEvent[HWC_DISPLAY_TYPES_SUPPORTED];
+    DisplayEventReceiver::Event mVSyncEvent[HWC_NUM_DISPLAY_TYPES];
     bool mUseSoftwareVSync;
 
     // for debugging
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index f31d650..52211c2 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -110,12 +110,11 @@
 {
     // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
     sp<BufferQueue> bq = new SurfaceTextureLayer(mFlinger);
-    mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(mTextureName, true,
-            GL_TEXTURE_EXTERNAL_OES, false, bq);
+    mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(bq, mTextureName,
+            GL_TEXTURE_EXTERNAL_OES, false);
 
     mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
     mSurfaceFlingerConsumer->setFrameAvailableListener(this);
-    mSurfaceFlingerConsumer->setSynchronousMode(true);
     mSurfaceFlingerConsumer->setName(mName);
 
 #ifdef TARGET_DISABLE_TRIPLE_BUFFERING
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index ecf9fa7..9adabe8 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -895,6 +895,11 @@
 
         status_t err = hwc.prepare();
         ALOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
+
+        for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+            sp<const DisplayDevice> hw(mDisplays[dpy]);
+            hw->prepareFrame(hwc);
+        }
     }
 }
 
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.h b/services/surfaceflinger/SurfaceFlingerConsumer.h
index d774c33..5de6d12 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.h
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.h
@@ -27,11 +27,10 @@
  */
 class SurfaceFlingerConsumer : public GLConsumer {
 public:
-    SurfaceFlingerConsumer(GLuint tex, bool allowSynchronousMode = true,
-            GLenum texTarget = GL_TEXTURE_EXTERNAL_OES, bool useFenceSync = true,
-            const sp<BufferQueue> &bufferQueue = 0)
-        : GLConsumer(tex, allowSynchronousMode, texTarget, useFenceSync,
-            bufferQueue)
+    SurfaceFlingerConsumer(const sp<BufferQueue>& bq, GLuint tex,
+            GLenum texTarget = GL_TEXTURE_EXTERNAL_OES,
+            bool useFenceSync = true)
+        : GLConsumer(bq, tex, texTarget, useFenceSync)
     {}
 
     class BufferRejecter {
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;