Merge "libgui: assign handle to NULL after free"
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index 713634c..59c1d12 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -351,7 +351,8 @@
 
     run_command("LOG STATISTICS", 10, "logcat", "-b", "all", "-S", NULL);
 
-    run_command("RAFT LOGS", 300, SU_PATH, "root", "logcompressor", "-r", RAFT_DIR, NULL);
+    // raft disabled as per http://b/24159112
+    // run_command("RAFT LOGS", 300, SU_PATH, "root", "logcompressor", "-r", RAFT_DIR, NULL);
 
     /* show the traces we collected in main(), if that was done */
     if (dump_traces_path != NULL) {
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index 769cd34..46d72fd 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -746,7 +746,7 @@
 
 static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name,
     const char* output_file_name, int swap_fd, const char *pkgname, const char *instruction_set,
-    bool vm_safe_mode, bool debuggable, bool post_bootcomplete)
+    bool vm_safe_mode, bool debuggable, bool post_bootcomplete, bool use_jit)
 {
     static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
 
@@ -770,24 +770,11 @@
                                                           dex2oat_compiler_filter_flag, NULL) > 0;
 
     char dex2oat_threads_buf[PROPERTY_VALUE_MAX];
-    bool have_dex2oat_threads_flag = false;
-    if (!post_bootcomplete) {
-        have_dex2oat_threads_flag = property_get("dalvik.vm.boot-dex2oat-threads",
-                                                 dex2oat_threads_buf,
-                                                 NULL) > 0;
-        // If there's no boot property, fall back to the image property.
-        if (!have_dex2oat_threads_flag) {
-            have_dex2oat_threads_flag = property_get("dalvik.vm.image-dex2oat-threads",
-                                                     dex2oat_threads_buf,
-                                                     NULL) > 0;
-        }
-        // If there's neither, fall back to the default property.
-    }
-    if (!have_dex2oat_threads_flag) {
-        have_dex2oat_threads_flag = property_get("dalvik.vm.dex2oat-threads",
-                                                 dex2oat_threads_buf,
-                                                 NULL) > 0;
-    }
+    bool have_dex2oat_threads_flag = property_get(post_bootcomplete
+                                                      ? "dalvik.vm.dex2oat-threads"
+                                                      : "dalvik.vm.boot-dex2oat-threads",
+                                                  dex2oat_threads_buf,
+                                                  NULL) > 0;
     char dex2oat_threads_arg[PROPERTY_VALUE_MAX + 2];
     if (have_dex2oat_threads_flag) {
         sprintf(dex2oat_threads_arg, "-j%s", dex2oat_threads_buf);
@@ -820,7 +807,6 @@
                              (strcmp(vold_decrypt, "trigger_restart_min_framework") == 0 ||
                              (strcmp(vold_decrypt, "1") == 0)));
 
-    bool use_jit = check_boolean_property("debug.usejit");
     bool generate_debug_info = check_boolean_property("debug.generate-debug-info");
 
     static const char* DEX2OAT_BIN = "/system/bin/dex2oat";
@@ -874,6 +860,8 @@
         }
     }
 
+    // use the JIT if either it's specified as a dexopt flag or if the property is set
+    use_jit = use_jit || check_boolean_property("debug.usejit");
     if (have_dex2oat_Xms_flag) {
         sprintf(dex2oat_Xms_arg, "-Xms%s", dex2oat_Xms_flag);
     }
@@ -1081,14 +1069,6 @@
     return true;
 }
 
-static bool IsPostBootComplete() {
-    char dev_bootcomplete_prop_buf[PROPERTY_VALUE_MAX];
-    if (property_get("dev.bootcomplete", dev_bootcomplete_prop_buf, "0") > 0) {
-        return (strcmp(dev_bootcomplete_prop_buf, "1") == 0);
-    }
-    return false;
-}
-
 static void SetDex2OatAndPatchOatScheduling(bool set_to_bg) {
     if (set_to_bg) {
         if (set_sched_policy(0, SP_BACKGROUND) < 0) {
@@ -1102,9 +1082,8 @@
     }
 }
 
-int dexopt(const char *apk_path, uid_t uid, bool is_public,
-           const char *pkgname, const char *instruction_set, int dexopt_needed,
-           bool vm_safe_mode, bool debuggable, const char* oat_dir)
+int dexopt(const char *apk_path, uid_t uid, const char *pkgname, const char *instruction_set,
+           int dexopt_needed, const char* oat_dir, int dexopt_flags)
 {
     struct utimbuf ut;
     struct stat input_stat;
@@ -1113,7 +1092,15 @@
     const char *input_file;
     char in_odex_path[PKG_PATH_MAX];
     int res, input_fd=-1, out_fd=-1, swap_fd=-1;
-    bool post_bootcomplete = IsPostBootComplete();
+    bool is_public = (dexopt_flags & DEXOPT_PUBLIC) != 0;
+    bool vm_safe_mode = (dexopt_flags & DEXOPT_SAFEMODE) != 0;
+    bool debuggable = (dexopt_flags & DEXOPT_DEBUGGABLE) != 0;
+    bool boot_complete = (dexopt_flags & DEXOPT_BOOTCOMPLETE) != 0;
+    bool use_jit = (dexopt_flags & DEXOPT_USEJIT) != 0;
+
+    if ((dexopt_flags & DEXOPT_MASK) != 0) {
+        LOG_FATAL("dexopt flags contains unknown fields\n");
+    }
 
     // Early best-effort check whether we can fit the the path into our buffers.
     // Note: the cache path will require an additional 5 bytes for ".swap", but we'll try to run
@@ -1236,7 +1223,7 @@
             ALOGE("capset failed: %s\n", strerror(errno));
             exit(66);
         }
-        SetDex2OatAndPatchOatScheduling(post_bootcomplete);
+        SetDex2OatAndPatchOatScheduling(boot_complete);
         if (flock(out_fd, LOCK_EX | LOCK_NB) != 0) {
             ALOGE("flock(%s) failed: %s\n", out_path, strerror(errno));
             exit(67);
@@ -1253,7 +1240,7 @@
                 input_file_name++;
             }
             run_dex2oat(input_fd, out_fd, input_file_name, out_path, swap_fd, pkgname,
-                        instruction_set, vm_safe_mode, debuggable, post_bootcomplete);
+                        instruction_set, vm_safe_mode, debuggable, boot_complete, use_jit);
         } else {
             ALOGE("Invalid dexopt needed: %d\n", dexopt_needed);
             exit(73);
diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp
index 13e3168..7a16150 100644
--- a/cmds/installd/installd.cpp
+++ b/cmds/installd/installd.cpp
@@ -47,10 +47,9 @@
 
 static int do_dexopt(char **arg, char reply[REPLY_MAX] __unused)
 {
-    /* apk_path, uid, is_public, pkgname, instruction_set,
-     * dexopt_needed, vm_safe_mode, debuggable, oat_dir */
-    return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3], arg[4], atoi(arg[5]),
-                  atoi(arg[6]), atoi(arg[7]), arg[8]);
+    /* apk_path, uid, pkgname, instruction_set, dexopt_needed, oat_dir, dexopt_flags */
+    return dexopt(arg[0], atoi(arg[1]), arg[2], arg[3], atoi(arg[4]),
+                  arg[5], atoi(arg[6]));
 }
 
 static int do_mark_boot_complete(char **arg, char reply[REPLY_MAX] __unused)
@@ -194,7 +193,7 @@
 struct cmdinfo cmds[] = {
     { "ping",                 0, do_ping },
     { "install",              5, do_install },
-    { "dexopt",               9, do_dexopt },
+    { "dexopt",               7, do_dexopt },
     { "markbootcomplete",     1, do_mark_boot_complete },
     { "movedex",              3, do_move_dex },
     { "rmdex",                2, do_rm_dex },
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index 7ec5793..df13fe4 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -90,6 +90,24 @@
 #define DEXOPT_PATCHOAT_NEEDED       2
 #define DEXOPT_SELF_PATCHOAT_NEEDED  3
 
+/****************************************************************************
+ * IMPORTANT: These values are passed from Java code. Keep them in sync with
+ * frameworks/base/services/core/java/com/android/server/pm/Installer.java
+ ***************************************************************************/
+constexpr int DEXOPT_PUBLIC       = 1 << 1;
+constexpr int DEXOPT_SAFEMODE     = 1 << 2;
+constexpr int DEXOPT_DEBUGGABLE   = 1 << 3;
+constexpr int DEXOPT_BOOTCOMPLETE = 1 << 4;
+constexpr int DEXOPT_USEJIT       = 1 << 5;
+
+/* all known values for dexopt flags */
+constexpr int DEXOPT_MASK =
+    DEXOPT_PUBLIC
+    | DEXOPT_SAFEMODE
+    | DEXOPT_DEBUGGABLE
+    | DEXOPT_BOOTCOMPLETE
+    | DEXOPT_USEJIT;
+
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
 
 /* data structures */
@@ -241,9 +259,8 @@
         const char *instruction_set, int64_t *codesize, int64_t *datasize,
         int64_t *cachesize, int64_t *asecsize);
 int free_cache(const char *uuid, int64_t free_size);
-int dexopt(const char *apk_path, uid_t uid, bool is_public, const char *pkgName,
-           const char *instruction_set, int dexopt_needed, bool vm_safe_mode,
-           bool debuggable, const char* oat_dir);
+int dexopt(const char *apk_path, uid_t uid, const char *pkgName, const char *instruction_set,
+           int dexopt_needed, const char* oat_dir, int dexopt_flags);
 int mark_boot_complete(const char *instruction_set);
 int movefiles();
 int linklib(const char* uuid, const char* pkgname, const char* asecLibDir, int userId);
diff --git a/include/gui/BufferQueueCore.h b/include/gui/BufferQueueCore.h
index e824124..36cd238 100644
--- a/include/gui/BufferQueueCore.h
+++ b/include/gui/BufferQueueCore.h
@@ -85,25 +85,25 @@
     // getMinUndequeuedBufferCountLocked 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 getMinUndequeuedBufferCountLocked(bool async) const;
+    int getMinUndequeuedBufferCountLocked() const;
 
     // getMinMaxBufferCountLocked returns the minimum number of buffers allowed
     // given the current BufferQueue state. The async parameter tells whether
     // we're in asynchonous mode.
-    int getMinMaxBufferCountLocked(bool async) const;
+    int getMinMaxBufferCountLocked() const;
 
     // getMaxBufferCountLocked returns the maximum number of buffers that can be
     // allocated at once. This value depends on the following member variables:
     //
-    //     mDequeueBufferCannotBlock
+    //     mMaxDequeuedBufferCount
     //     mMaxAcquiredBufferCount
-    //     mDefaultMaxBufferCount
-    //     mOverrideMaxBufferCount
-    //     async parameter
+    //     mMaxBufferCount
+    //     mAsyncMode
+    //     mDequeueBufferCannotBlock
     //
     // Any time one of these member variables is changed while a producer is
     // connected, mDequeueCondition must be broadcast.
-    int getMaxBufferCountLocked(bool async) const;
+    int getMaxBufferCountLocked() const;
 
     // freeBufferLocked frees the GraphicBuffer and sync resources for the
     // given slot.
diff --git a/include/gui/BufferQueueProducer.h b/include/gui/BufferQueueProducer.h
index 7827072..6e16a60 100644
--- a/include/gui/BufferQueueProducer.h
+++ b/include/gui/BufferQueueProducer.h
@@ -81,7 +81,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 *outSlot, sp<Fence>* outFence,
-            bool async, uint32_t width, uint32_t height, PixelFormat format,
+            uint32_t width, uint32_t height, PixelFormat format,
             uint32_t usage);
 
     // See IGraphicBufferProducer::detachBuffer
@@ -117,7 +117,7 @@
     //
     // The buffer will not be overwritten until the fence signals.  The fence
     // will usually be the one obtained from dequeueBuffer.
-    virtual void cancelBuffer(int slot, const sp<Fence>& fence);
+    virtual status_t cancelBuffer(int slot, const sp<Fence>& fence);
 
     // Query native window attributes.  The "what" values are enumerated in
     // window.h (e.g. NATIVE_WINDOW_FORMAT).
@@ -158,7 +158,7 @@
     virtual status_t setSidebandStream(const sp<NativeHandle>& stream);
 
     // See IGraphicBufferProducer::allocateBuffers
-    virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
+    virtual void allocateBuffers(uint32_t width, uint32_t height,
             PixelFormat format, uint32_t usage);
 
     // See IGraphicBufferProducer::allowAllocation
@@ -179,8 +179,8 @@
     // mode (producer and consumer controlled by the application). If it blocks,
     // it will release mCore->mMutex while blocked so that other operations on
     // the BufferQueue may succeed.
-    status_t waitForFreeSlotThenRelock(const char* caller, bool async,
-            int* found, status_t* returnFlags) const;
+    status_t waitForFreeSlotThenRelock(const char* caller, int* found,
+            status_t* returnFlags) const;
 
     sp<BufferQueueCore> mCore;
 
diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h
index 5b84bdc..be1874a 100644
--- a/include/gui/IGraphicBufferProducer.h
+++ b/include/gui/IGraphicBufferProducer.h
@@ -74,7 +74,8 @@
     // The slot must be in the range of [0, NUM_BUFFER_SLOTS).
     //
     // Return of a value other than NO_ERROR means an error has occurred:
-    // * NO_INIT - the buffer queue has been abandoned.
+    // * NO_INIT - the buffer queue has been abandoned or the producer is not
+    //             connected.
     // * BAD_VALUE - one of the two conditions occurred:
     //              * slot was out of range (see above)
     //              * buffer specified by the slot is not dequeued
@@ -146,9 +147,6 @@
     // fence signals. If the fence is Fence::NO_FENCE, the buffer may be written
     // immediately.
     //
-    // The async parameter sets whether we're in asynchronous mode for this
-    // dequeueBuffer() call.
-    //
     // The width and height parameters must be no greater than the minimum of
     // GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv).
     // An error due to invalid dimensions might not be reported until
@@ -170,7 +168,8 @@
     // success.
     //
     // Return of a negative means an error has occurred:
-    // * NO_INIT - the buffer queue has been abandoned.
+    // * NO_INIT - the buffer queue has been abandoned or the producer is not
+    //             connected.
     // * BAD_VALUE - both in async mode and buffer count was less than the
     //               max numbers of buffers that can be allocated at once.
     // * INVALID_OPERATION - cannot attach the buffer because it would cause
@@ -185,8 +184,8 @@
     //
     // All other negative values are an unknown error returned downstream
     // from the graphics allocator (typically errno).
-    virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, bool async,
-            uint32_t w, uint32_t h, PixelFormat format, uint32_t usage) = 0;
+    virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w,
+            uint32_t h, PixelFormat format, uint32_t usage) = 0;
 
     // detachBuffer attempts to remove all ownership of the buffer in the given
     // slot from the buffer queue. If this call succeeds, the slot will be
@@ -198,7 +197,8 @@
     // requestBuffer).
     //
     // Return of a value other than NO_ERROR means an error has occurred:
-    // * NO_INIT - the buffer queue has been abandoned.
+    // * NO_INIT - the buffer queue has been abandoned or the producer is not
+    //             connected.
     // * BAD_VALUE - the given slot number is invalid, either because it is
     //               out of the range [0, NUM_BUFFER_SLOTS), or because the slot
     //               it refers to is not currently dequeued and requested.
@@ -218,7 +218,8 @@
     // equivalent to fence from the dequeueBuffer call.
     //
     // Return of a value other than NO_ERROR means an error has occurred:
-    // * NO_INIT - the buffer queue has been abandoned.
+    // * NO_INIT - the buffer queue has been abandoned or the producer is not
+    //             connected.
     // * BAD_VALUE - either outBuffer or outFence were NULL.
     // * NO_MEMORY - no slots were found that were both free and contained a
     //               GraphicBuffer.
@@ -237,7 +238,8 @@
     // success.
     //
     // Return of a negative value means an error has occurred:
-    // * NO_INIT - the buffer queue has been abandoned.
+    // * NO_INIT - the buffer queue has been abandoned or the producer is not
+    //             connected.
     // * BAD_VALUE - outSlot or buffer were NULL, invalid combination of
     //               async mode and buffer count override, or the generation
     //               number of the buffer did not match the buffer queue.
@@ -271,7 +273,8 @@
     // (refer to the documentation below).
     //
     // Return of a value other than NO_ERROR means an error has occurred:
-    // * NO_INIT - the buffer queue has been abandoned.
+    // * NO_INIT - the buffer queue has been abandoned or the producer is not
+    //             connected.
     // * BAD_VALUE - one of the below conditions occurred:
     //              * fence was NULL
     //              * scaling mode was unknown
@@ -291,23 +294,21 @@
         // crop - a crop rectangle that's used as a hint to the consumer
         // scalingMode - a set of flags from NATIVE_WINDOW_SCALING_* in <window.h>
         // transform - a set of flags from NATIVE_WINDOW_TRANSFORM_* in <window.h>
-        // async - if the buffer is queued in asynchronous mode
         // fence - a fence that the consumer must wait on before reading the buffer,
         //         set this to Fence::NO_FENCE if the buffer is ready immediately
         // sticky - the sticky transform set in Surface (only used by the LEGACY
         //          camera mode).
         inline QueueBufferInput(int64_t timestamp, bool isAutoTimestamp,
                 android_dataspace dataSpace, const Rect& crop, int scalingMode,
-                uint32_t transform, bool async, const sp<Fence>& fence,
-                uint32_t sticky = 0)
+                uint32_t transform, const sp<Fence>& fence, uint32_t sticky = 0)
                 : timestamp(timestamp), isAutoTimestamp(isAutoTimestamp),
                   dataSpace(dataSpace), crop(crop), scalingMode(scalingMode),
-                  transform(transform), stickyTransform(sticky),
-                  async(async), fence(fence), surfaceDamage() { }
+                  transform(transform), stickyTransform(sticky), fence(fence),
+                  surfaceDamage() { }
         inline void deflate(int64_t* outTimestamp, bool* outIsAutoTimestamp,
                 android_dataspace* outDataSpace,
                 Rect* outCrop, int* outScalingMode,
-                uint32_t* outTransform, bool* outAsync, sp<Fence>* outFence,
+                uint32_t* outTransform, sp<Fence>* outFence,
                 uint32_t* outStickyTransform = NULL) const {
             *outTimestamp = timestamp;
             *outIsAutoTimestamp = bool(isAutoTimestamp);
@@ -315,7 +316,6 @@
             *outCrop = crop;
             *outScalingMode = scalingMode;
             *outTransform = transform;
-            *outAsync = bool(async);
             *outFence = fence;
             if (outStickyTransform != NULL) {
                 *outStickyTransform = stickyTransform;
@@ -339,7 +339,6 @@
         int scalingMode;
         uint32_t transform;
         uint32_t stickyTransform;
-        int async;
         sp<Fence> fence;
         Region surfaceDamage;
     };
@@ -375,8 +374,8 @@
         uint32_t numPendingBuffers;
     };
 
-    virtual status_t queueBuffer(int slot,
-            const QueueBufferInput& input, QueueBufferOutput* output) = 0;
+    virtual status_t queueBuffer(int slot, const QueueBufferInput& input,
+            QueueBufferOutput* output) = 0;
 
     // cancelBuffer indicates that the client does not wish to fill in the
     // buffer associated with slot and transfers ownership of the slot back to
@@ -384,9 +383,19 @@
     //
     // The buffer is not queued for use by the consumer.
     //
+    // The slot must be in the range of [0, NUM_BUFFER_SLOTS).
+    //
     // The buffer will not be overwritten until the fence signals.  The fence
     // will usually be the one obtained from dequeueBuffer.
-    virtual void cancelBuffer(int slot, const sp<Fence>& fence) = 0;
+    //
+    // Return of a value other than NO_ERROR means an error has occurred:
+    // * NO_INIT - the buffer queue has been abandoned or the producer is not
+    //             connected.
+    // * BAD_VALUE - one of the below conditions occurred:
+    //              * fence was NULL
+    //              * slot index was out of range (see above).
+    //              * the slot was not in the dequeued state
+    virtual status_t cancelBuffer(int slot, const sp<Fence>& fence) = 0;
 
     // query retrieves some information for this surface
     // 'what' tokens allowed are that of NATIVE_WINDOW_* in <window.h>
@@ -477,7 +486,7 @@
     // allocated. This is most useful to avoid an allocation delay during
     // dequeueBuffer. If there are already the maximum number of buffers
     // allocated, this function has no effect.
-    virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
+    virtual void allocateBuffers(uint32_t width, uint32_t height,
             PixelFormat format, uint32_t usage) = 0;
 
     // Sets whether dequeueBuffer is allowed to allocate new buffers.
diff --git a/include/powermanager/IPowerManager.h b/include/powermanager/IPowerManager.h
index 49ff637..461fad7 100644
--- a/include/powermanager/IPowerManager.h
+++ b/include/powermanager/IPowerManager.h
@@ -31,11 +31,23 @@
     // These transaction IDs must be kept in sync with the method order from
     // IPowerManager.aidl.
     enum {
-        ACQUIRE_WAKE_LOCK = IBinder::FIRST_CALL_TRANSACTION,
-        ACQUIRE_WAKE_LOCK_UID = IBinder::FIRST_CALL_TRANSACTION + 1,
-        RELEASE_WAKE_LOCK = IBinder::FIRST_CALL_TRANSACTION + 2,
-        UPDATE_WAKE_LOCK_UIDS = IBinder::FIRST_CALL_TRANSACTION + 3,
-        POWER_HINT = IBinder::FIRST_CALL_TRANSACTION + 4,
+        ACQUIRE_WAKE_LOCK            = IBinder::FIRST_CALL_TRANSACTION,
+        ACQUIRE_WAKE_LOCK_UID        = IBinder::FIRST_CALL_TRANSACTION + 1,
+        RELEASE_WAKE_LOCK            = IBinder::FIRST_CALL_TRANSACTION + 2,
+        UPDATE_WAKE_LOCK_UIDS        = IBinder::FIRST_CALL_TRANSACTION + 3,
+        POWER_HINT                   = IBinder::FIRST_CALL_TRANSACTION + 4,
+        UPDATE_WAKE_LOCK_SOURCE      = IBinder::FIRST_CALL_TRANSACTION + 5,
+        IS_WAKE_LOCK_LEVEL_SUPPORTED = IBinder::FIRST_CALL_TRANSACTION + 6,
+        USER_ACTIVITY                = IBinder::FIRST_CALL_TRANSACTION + 7,
+        WAKE_UP                      = IBinder::FIRST_CALL_TRANSACTION + 8,
+        GO_TO_SLEEP                  = IBinder::FIRST_CALL_TRANSACTION + 9,
+        NAP                          = IBinder::FIRST_CALL_TRANSACTION + 10,
+        IS_INTERACTIVE               = IBinder::FIRST_CALL_TRANSACTION + 11,
+        IS_POWER_SAVE_MODE           = IBinder::FIRST_CALL_TRANSACTION + 12,
+        SET_POWER_SAVE_MODE          = IBinder::FIRST_CALL_TRANSACTION + 13,
+        REBOOT                       = IBinder::FIRST_CALL_TRANSACTION + 14,
+        SHUTDOWN                     = IBinder::FIRST_CALL_TRANSACTION + 15,
+        CRASH                        = IBinder::FIRST_CALL_TRANSACTION + 16,
     };
 
     DECLARE_META_INTERFACE(PowerManager);
@@ -50,8 +62,11 @@
     virtual status_t releaseWakeLock(const sp<IBinder>& lock, int flags, bool isOneWay = false) = 0;
     virtual status_t updateWakeLockUids(const sp<IBinder>& lock, int len, const int *uids,
             bool isOneWay = false) = 0;
-    // oneway in the .aidl
     virtual status_t powerHint(int hintId, int data) = 0;
+    virtual status_t goToSleep(int64_t event_time_ms, int reason, int flags) = 0;
+    virtual status_t reboot(bool confirm, const String16& reason, bool wait) = 0;
+    virtual status_t shutdown(bool confirm, const String16& reason, bool wait) = 0;
+    virtual status_t crash(const String16& message) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/ui/Region.h b/include/ui/Region.h
index e9b3a0b..810f098 100644
--- a/include/ui/Region.h
+++ b/include/ui/Region.h
@@ -28,7 +28,6 @@
 namespace android {
 // ---------------------------------------------------------------------------
 
-class SharedBuffer;
 class String8;
 
 // ---------------------------------------------------------------------------
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index 950a074..d52b47f 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -527,11 +527,13 @@
     }
 
     if ((maxAcquiredBuffers + mCore->mMaxDequeuedBufferCount +
-            (mCore->mAsyncMode ? 1 : 0)) > mCore->mMaxBufferCount) {
+            (mCore->mAsyncMode || mCore->mDequeueBufferCannotBlock ? 1 : 0)) >
+            mCore->mMaxBufferCount) {
         BQ_LOGE("setMaxAcquiredBufferCount: %d acquired buffers would exceed "
                 "the maxBufferCount (%d) (maxDequeued %d async %d)",
                 maxAcquiredBuffers, mCore->mMaxBufferCount,
-                mCore->mMaxDequeuedBufferCount, mCore->mAsyncMode);
+                mCore->mMaxDequeuedBufferCount, mCore->mAsyncMode ||
+                mCore->mDequeueBufferCannotBlock);
         return BAD_VALUE;
     }
 
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index 8b97c2a..b1cbc86 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -101,12 +101,13 @@
     }
 
     result.appendFormat("%s-BufferQueue mMaxAcquiredBufferCount=%d, "
-            "mMaxDequeuedBufferCount=%d, mDequeueBufferCannotBlock=%d, "
-            "default-size=[%dx%d], default-format=%d, transform-hint=%02x, "
-            "FIFO(%zu)={%s}\n",
-            prefix, mMaxAcquiredBufferCount, mMaxDequeuedBufferCount,
-            mDequeueBufferCannotBlock, mDefaultWidth, mDefaultHeight,
-            mDefaultBufferFormat, mTransformHint, mQueue.size(), fifo.string());
+            "mMaxDequeuedBufferCount=%d, mDequeueBufferCannotBlock=%d "
+            "mAsyncMode=%d, default-size=[%dx%d], default-format=%d, "
+            "transform-hint=%02x, FIFO(%zu)={%s}\n", prefix,
+            mMaxAcquiredBufferCount, mMaxDequeuedBufferCount,
+            mDequeueBufferCannotBlock, mAsyncMode, mDefaultWidth,
+            mDefaultHeight, mDefaultBufferFormat, mTransformHint, mQueue.size(),
+            fifo.string());
 
     // Trim the free buffers so as to not spam the dump
     int maxBufferCount = 0;
@@ -137,23 +138,23 @@
     }
 }
 
-int BufferQueueCore::getMinUndequeuedBufferCountLocked(bool async) const {
+int BufferQueueCore::getMinUndequeuedBufferCountLocked() const {
     // If dequeueBuffer is allowed to error out, we don't have to add an
     // extra buffer.
-    if (mDequeueBufferCannotBlock || async) {
+    if (mAsyncMode || mDequeueBufferCannotBlock) {
         return mMaxAcquiredBufferCount + 1;
     }
 
     return mMaxAcquiredBufferCount;
 }
 
-int BufferQueueCore::getMinMaxBufferCountLocked(bool async) const {
-    return getMinUndequeuedBufferCountLocked(async) + 1;
+int BufferQueueCore::getMinMaxBufferCountLocked() const {
+    return getMinUndequeuedBufferCountLocked() + 1;
 }
 
-int BufferQueueCore::getMaxBufferCountLocked(bool async) const {
+int BufferQueueCore::getMaxBufferCountLocked() const {
     int maxBufferCount = mMaxAcquiredBufferCount + mMaxDequeuedBufferCount +
-            (async ? 1 : 0);
+            (mAsyncMode || mDequeueBufferCannotBlock ? 1 : 0);
 
     // limit maxBufferCount by mMaxBufferCount always
     maxBufferCount = std::min(mMaxBufferCount, maxBufferCount);
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 8cc0cfa..deec330 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -57,6 +57,11 @@
         return NO_INIT;
     }
 
+    if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
+        BQ_LOGE("requestBuffer: BufferQueue has no connected producer");
+        return NO_INIT;
+    }
+
     if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
         BQ_LOGE("requestBuffer: slot index %d out of range [0, %d)",
                 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
@@ -97,8 +102,7 @@
             }
         }
 
-        int bufferCount = mCore->getMinUndequeuedBufferCountLocked(
-                mCore->mAsyncMode);
+        int bufferCount = mCore->getMinUndequeuedBufferCountLocked();
         bufferCount += maxDequeuedBuffers;
 
         if (bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) {
@@ -107,8 +111,7 @@
             return BAD_VALUE;
         }
 
-        const int minBufferSlots = mCore->getMinMaxBufferCountLocked(
-                mCore->mAsyncMode);
+        const int minBufferSlots = mCore->getMinMaxBufferCountLocked();
         if (bufferCount < minBufferSlots) {
             BQ_LOGE("setMaxDequeuedBufferCount: requested buffer count %d is "
                     "less than minimum %d", bufferCount, minBufferSlots);
@@ -117,9 +120,10 @@
 
         if (bufferCount > mCore->mMaxBufferCount) {
             BQ_LOGE("setMaxDequeuedBufferCount: %d dequeued buffers would "
-                    "exceed the maxBufferCount (%d) (maxAcquired %d async %d)",
-                    maxDequeuedBuffers, mCore->mMaxBufferCount,
-                    mCore->mMaxAcquiredBufferCount, mCore->mAsyncMode);
+                    "exceed the maxBufferCount (%d) (maxAcquired %d async %d "
+                    "mDequeuedBufferCannotBlock %d)", maxDequeuedBuffers,
+                    mCore->mMaxBufferCount, mCore->mMaxAcquiredBufferCount,
+                    mCore->mAsyncMode, mCore->mDequeueBufferCannotBlock);
             return BAD_VALUE;
         }
 
@@ -164,12 +168,14 @@
         }
 
         if ((mCore->mMaxAcquiredBufferCount + mCore->mMaxDequeuedBufferCount +
-                (async ? 1 : 0)) > mCore->mMaxBufferCount) {
+                (async || mCore->mDequeueBufferCannotBlock ? 1 : 0)) >
+                mCore->mMaxBufferCount) {
             BQ_LOGE("setAsyncMode(%d): this call would cause the "
                     "maxBufferCount (%d) to be exceeded (maxAcquired %d "
-                    "maxDequeued %d)", async,mCore->mMaxBufferCount,
-                    mCore->mMaxAcquiredBufferCount,
-                    mCore->mMaxDequeuedBufferCount);
+                    "maxDequeued %d mDequeueBufferCannotBlock %d)", async,
+                    mCore->mMaxBufferCount, mCore->mMaxAcquiredBufferCount,
+                    mCore->mMaxDequeuedBufferCount,
+                    mCore->mDequeueBufferCannotBlock);
             return BAD_VALUE;
         }
 
@@ -186,7 +192,7 @@
 }
 
 status_t BufferQueueProducer::waitForFreeSlotThenRelock(const char* caller,
-        bool async, int* found, status_t* returnFlags) const {
+        int* found, status_t* returnFlags) const {
     bool tryAgain = true;
     while (tryAgain) {
         if (mCore->mIsAbandoned) {
@@ -194,7 +200,7 @@
             return NO_INIT;
         }
 
-        const int maxBufferCount = mCore->getMaxBufferCountLocked(async);
+        const int maxBufferCount = mCore->getMaxBufferCountLocked();
 
         // Free up any buffers that are in slots beyond the max buffer count
         for (int s = maxBufferCount; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
@@ -280,16 +286,26 @@
 }
 
 status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
-        sp<android::Fence> *outFence, bool async,
-        uint32_t width, uint32_t height, PixelFormat format, uint32_t usage) {
+        sp<android::Fence> *outFence, uint32_t width, uint32_t height,
+        PixelFormat format, uint32_t usage) {
     ATRACE_CALL();
     { // Autolock scope
         Mutex::Autolock lock(mCore->mMutex);
         mConsumerName = mCore->mConsumerName;
+
+        if (mCore->mIsAbandoned) {
+            BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned");
+            return NO_INIT;
+        }
+
+        if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
+            BQ_LOGE("dequeueBuffer: BufferQueue has no connected producer");
+            return NO_INIT;
+        }
     } // Autolock scope
 
-    BQ_LOGV("dequeueBuffer: async=%s w=%u h=%u format=%#x, usage=%#x",
-            async ? "true" : "false", width, height, format, usage);
+    BQ_LOGV("dequeueBuffer: w=%u h=%u format=%#x, usage=%#x", width, height,
+            format, usage);
 
     if ((width && !height) || (!width && height)) {
         BQ_LOGE("dequeueBuffer: invalid size: w=%u h=%u", width, height);
@@ -320,8 +336,8 @@
 
         int found = BufferItem::INVALID_BUFFER_SLOT;
         while (found == BufferItem::INVALID_BUFFER_SLOT) {
-            status_t status = waitForFreeSlotThenRelock("dequeueBuffer", async,
-                    &found, &returnFlags);
+            status_t status = waitForFreeSlotThenRelock("dequeueBuffer", &found,
+                    &returnFlags);
             if (status != NO_ERROR) {
                 return status;
             }
@@ -453,6 +469,11 @@
         return NO_INIT;
     }
 
+    if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
+        BQ_LOGE("detachBuffer(P): BufferQueue has no connected producer");
+        return NO_INIT;
+    }
+
     if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
         BQ_LOGE("detachBuffer(P): slot index %d out of range [0, %d)",
                 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
@@ -487,13 +508,19 @@
     }
 
     Mutex::Autolock lock(mCore->mMutex);
-    mCore->waitWhileAllocatingLocked();
 
     if (mCore->mIsAbandoned) {
         BQ_LOGE("detachNextBuffer: BufferQueue has been abandoned");
         return NO_INIT;
     }
 
+    if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
+        BQ_LOGE("detachNextBuffer: BufferQueue has no connected producer");
+        return NO_INIT;
+    }
+
+    mCore->waitWhileAllocatingLocked();
+
     if (mCore->mFreeBuffers.empty()) {
         return NO_MEMORY;
     }
@@ -524,7 +551,16 @@
     }
 
     Mutex::Autolock lock(mCore->mMutex);
-    mCore->waitWhileAllocatingLocked();
+
+    if (mCore->mIsAbandoned) {
+        BQ_LOGE("attachBuffer(P): BufferQueue has been abandoned");
+        return NO_INIT;
+    }
+
+    if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
+        BQ_LOGE("attachBuffer(P): BufferQueue has no connected producer");
+        return NO_INIT;
+    }
 
     if (buffer->getGenerationNumber() != mCore->mGenerationNumber) {
         BQ_LOGE("attachBuffer: generation number mismatch [buffer %u] "
@@ -533,13 +569,12 @@
         return BAD_VALUE;
     }
 
+    mCore->waitWhileAllocatingLocked();
+
     status_t returnFlags = NO_ERROR;
     int found;
-    // TODO: Should we provide an async flag to attachBuffer? It seems
-    // unlikely that buffers which we are attaching to a BufferQueue will
-    // be asynchronous (droppable), but it may not be impossible.
-    status_t status = waitForFreeSlotThenRelock("attachBuffer(P)", false,
-            &found, &returnFlags);
+    status_t status = waitForFreeSlotThenRelock("attachBuffer(P)", &found,
+            &returnFlags);
     if (status != NO_ERROR) {
         return status;
     }
@@ -578,10 +613,9 @@
     int scalingMode;
     uint32_t transform;
     uint32_t stickyTransform;
-    bool async;
     sp<Fence> fence;
     input.deflate(&timestamp, &isAutoTimestamp, &dataSpace, &crop, &scalingMode,
-            &transform, &async, &fence, &stickyTransform);
+            &transform, &fence, &stickyTransform);
     Region surfaceDamage = input.getSurfaceDamage();
 
     if (fence == NULL) {
@@ -612,7 +646,12 @@
             return NO_INIT;
         }
 
-        const int maxBufferCount = mCore->getMaxBufferCountLocked(async);
+        if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
+            BQ_LOGE("queueBuffer: BufferQueue has no connected producer");
+            return NO_INIT;
+        }
+
+        const int maxBufferCount = mCore->getMaxBufferCountLocked();
 
         if (slot < 0 || slot >= maxBufferCount) {
             BQ_LOGE("queueBuffer: slot index %d out of range [0, %d)",
@@ -668,7 +707,8 @@
         item.mFrameNumber = mCore->mFrameCounter;
         item.mSlot = slot;
         item.mFence = fence;
-        item.mIsDroppable = mCore->mDequeueBufferCannotBlock || async;
+        item.mIsDroppable = mCore->mAsyncMode ||
+                mCore->mDequeueBufferCannotBlock;
         item.mSurfaceDamage = surfaceDamage;
 
         mStickyTransform = stickyTransform;
@@ -748,27 +788,32 @@
     return NO_ERROR;
 }
 
-void BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
+status_t BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
     ATRACE_CALL();
     BQ_LOGV("cancelBuffer: slot %d", slot);
     Mutex::Autolock lock(mCore->mMutex);
 
     if (mCore->mIsAbandoned) {
         BQ_LOGE("cancelBuffer: BufferQueue has been abandoned");
-        return;
+        return NO_INIT;
+    }
+
+    if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
+        BQ_LOGE("cancelBuffer: BufferQueue has no connected producer");
+        return NO_INIT;
     }
 
     if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
         BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)",
                 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
-        return;
+        return BAD_VALUE;
     } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
         BQ_LOGE("cancelBuffer: slot %d is not owned by the producer "
                 "(state = %d)", slot, mSlots[slot].mBufferState);
-        return;
+        return BAD_VALUE;
     } else if (fence == NULL) {
         BQ_LOGE("cancelBuffer: fence is NULL");
-        return;
+        return BAD_VALUE;
     }
 
     mCore->mFreeBuffers.push_front(slot);
@@ -776,6 +821,8 @@
     mSlots[slot].mFence = fence;
     mCore->mDequeueCondition.broadcast();
     mCore->validateConsistencyLocked();
+
+    return NO_ERROR;
 }
 
 int BufferQueueProducer::query(int what, int *outValue) {
@@ -804,7 +851,7 @@
             value = static_cast<int32_t>(mCore->mDefaultBufferFormat);
             break;
         case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
-            value = mCore->getMinUndequeuedBufferCountLocked(false);
+            value = mCore->getMinUndequeuedBufferCountLocked();
             break;
         case NATIVE_WINDOW_STICKY_TRANSFORM:
             value = static_cast<int32_t>(mStickyTransform);
@@ -894,8 +941,8 @@
     }
 
     mCore->mBufferHasBeenQueued = false;
-    mCore->mDequeueBufferCannotBlock =
-            mCore->mConsumerControlledByApp && producerControlledByApp;
+    mCore->mDequeueBufferCannotBlock =  mCore->mConsumerControlledByApp &&
+            producerControlledByApp;
     mCore->mAllowAllocation = true;
 
     return status;
@@ -974,8 +1021,8 @@
     return NO_ERROR;
 }
 
-void BufferQueueProducer::allocateBuffers(bool async, uint32_t width,
-        uint32_t height, PixelFormat format, uint32_t usage) {
+void BufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height,
+        PixelFormat format, uint32_t usage) {
     ATRACE_CALL();
     while (true) {
         Vector<int> freeSlots;
@@ -1009,7 +1056,7 @@
                 }
             }
 
-            int maxBufferCount = mCore->getMaxBufferCountLocked(async);
+            int maxBufferCount = mCore->getMaxBufferCountLocked();
             BQ_LOGV("allocateBuffers: allocating from %d buffers up to %d buffers",
                     currentBufferCount, maxBufferCount);
             if (maxBufferCount <= currentBufferCount)
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 6495aa9..8ab963d 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -111,12 +111,10 @@
         return result;
     }
 
-    virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, bool async,
-            uint32_t width, uint32_t height, PixelFormat format,
-            uint32_t usage) {
+    virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, uint32_t width,
+            uint32_t height, PixelFormat format, uint32_t usage) {
         Parcel data, reply;
         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
-        data.writeInt32(static_cast<int32_t>(async));
         data.writeUint32(width);
         data.writeUint32(height);
         data.writeInt32(static_cast<int32_t>(format));
@@ -206,12 +204,17 @@
         return result;
     }
 
-    virtual void cancelBuffer(int buf, const sp<Fence>& fence) {
+    virtual status_t cancelBuffer(int buf, const sp<Fence>& fence) {
         Parcel data, reply;
         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
         data.writeInt32(buf);
         data.write(*fence.get());
-        remote()->transact(CANCEL_BUFFER, data, &reply);
+        status_t result = remote()->transact(CANCEL_BUFFER, data, &reply);
+        if (result != NO_ERROR) {
+            return result;
+        }
+        result = reply.readInt32();
+        return result;
     }
 
     virtual int query(int what, int* value) {
@@ -276,11 +279,10 @@
         return result;
     }
 
-    virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
+    virtual void allocateBuffers(uint32_t width, uint32_t height,
             PixelFormat format, uint32_t usage) {
         Parcel data, reply;
         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
-        data.writeInt32(static_cast<int32_t>(async));
         data.writeUint32(width);
         data.writeUint32(height);
         data.writeInt32(static_cast<int32_t>(format));
@@ -366,15 +368,14 @@
         }
         case DEQUEUE_BUFFER: {
             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
-            bool async = static_cast<bool>(data.readInt32());
             uint32_t width = data.readUint32();
             uint32_t height = data.readUint32();
             PixelFormat format = static_cast<PixelFormat>(data.readInt32());
             uint32_t usage = data.readUint32();
-            int buf;
+            int buf = 0;
             sp<Fence> fence;
-            int result = dequeueBuffer(&buf, &fence, async, width, height,
-                    format, usage);
+            int result = dequeueBuffer(&buf, &fence, width, height, format,
+                    usage);
             reply->writeInt32(buf);
             reply->writeInt32(fence != NULL);
             if (fence != NULL) {
@@ -412,7 +413,7 @@
             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
             sp<GraphicBuffer> buffer = new GraphicBuffer();
             data.read(*buffer.get());
-            int slot;
+            int slot = 0;
             int result = attachBuffer(&slot, buffer);
             reply->writeInt32(slot);
             reply->writeInt32(result);
@@ -434,12 +435,13 @@
             int buf = data.readInt32();
             sp<Fence> fence = new Fence();
             data.read(*fence.get());
-            cancelBuffer(buf, fence);
+            status_t result = cancelBuffer(buf, fence);
+            reply->writeInt32(result);
             return NO_ERROR;
         }
         case QUERY: {
             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
-            int value;
+            int value = 0;
             int what = data.readInt32();
             int res = query(what, &value);
             reply->writeInt32(value);
@@ -480,12 +482,11 @@
         }
         case ALLOCATE_BUFFERS: {
             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
-            bool async = static_cast<bool>(data.readInt32());
             uint32_t width = data.readUint32();
             uint32_t height = data.readUint32();
             PixelFormat format = static_cast<PixelFormat>(data.readInt32());
             uint32_t usage = data.readUint32();
-            allocateBuffers(async, width, height, format, usage);
+            allocateBuffers(width, height, format, usage);
             return NO_ERROR;
         }
         case ALLOW_ALLOCATION: {
@@ -525,7 +526,6 @@
          + sizeof(scalingMode)
          + sizeof(transform)
          + sizeof(stickyTransform)
-         + sizeof(async)
          + fence->getFlattenedSize()
          + surfaceDamage.getFlattenedSize();
 }
@@ -547,7 +547,6 @@
     FlattenableUtils::write(buffer, size, scalingMode);
     FlattenableUtils::write(buffer, size, transform);
     FlattenableUtils::write(buffer, size, stickyTransform);
-    FlattenableUtils::write(buffer, size, async);
     status_t result = fence->flatten(buffer, size, fds, count);
     if (result != NO_ERROR) {
         return result;
@@ -565,8 +564,7 @@
             + sizeof(crop)
             + sizeof(scalingMode)
             + sizeof(transform)
-            + sizeof(stickyTransform)
-            + sizeof(async);
+            + sizeof(stickyTransform);
 
     if (size < minNeeded) {
         return NO_MEMORY;
@@ -579,7 +577,6 @@
     FlattenableUtils::read(buffer, size, scalingMode);
     FlattenableUtils::read(buffer, size, transform);
     FlattenableUtils::read(buffer, size, stickyTransform);
-    FlattenableUtils::read(buffer, size, async);
 
     fence = new Fence();
     status_t result = fence->unflatten(buffer, size, fds, count);
diff --git a/libs/gui/StreamSplitter.cpp b/libs/gui/StreamSplitter.cpp
index dce0e87..bafe947 100644
--- a/libs/gui/StreamSplitter.cpp
+++ b/libs/gui/StreamSplitter.cpp
@@ -144,8 +144,7 @@
             bufferItem.mTimestamp, bufferItem.mIsAutoTimestamp,
             bufferItem.mDataSpace, bufferItem.mCrop,
             static_cast<int32_t>(bufferItem.mScalingMode),
-            bufferItem.mTransform, bufferItem.mIsDroppable,
-            bufferItem.mFence);
+            bufferItem.mTransform, bufferItem.mFence);
 
     // Attach and queue the buffer to each of the outputs
     Vector<sp<IGraphicBufferProducer> >::iterator output = mOutputs.begin();
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index de5c275..a31876b 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -99,8 +99,8 @@
 void Surface::allocateBuffers() {
     uint32_t reqWidth = mReqWidth ? mReqWidth : mUserWidth;
     uint32_t reqHeight = mReqHeight ? mReqHeight : mUserHeight;
-    mGraphicBufferProducer->allocateBuffers(mSwapIntervalZero, reqWidth,
-            reqHeight, mReqFormat, mReqUsage);
+    mGraphicBufferProducer->allocateBuffers(reqWidth, reqHeight,
+            mReqFormat, mReqUsage);
 }
 
 status_t Surface::setGenerationNumber(uint32_t generation) {
@@ -202,6 +202,7 @@
         interval = maxSwapInterval;
 
     mSwapIntervalZero = (interval == 0);
+    mGraphicBufferProducer->setAsyncMode(mSwapIntervalZero);
 
     return NO_ERROR;
 }
@@ -212,7 +213,6 @@
 
     uint32_t reqWidth;
     uint32_t reqHeight;
-    bool swapIntervalZero;
     PixelFormat reqFormat;
     uint32_t reqUsage;
 
@@ -222,20 +222,19 @@
         reqWidth = mReqWidth ? mReqWidth : mUserWidth;
         reqHeight = mReqHeight ? mReqHeight : mUserHeight;
 
-        swapIntervalZero = mSwapIntervalZero;
         reqFormat = mReqFormat;
         reqUsage = mReqUsage;
     } // Drop the lock so that we can still touch the Surface while blocking in IGBP::dequeueBuffer
 
     int buf = -1;
     sp<Fence> fence;
-    status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, swapIntervalZero,
+    status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence,
             reqWidth, reqHeight, reqFormat, reqUsage);
 
     if (result < 0) {
-        ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer(%d, %d, %d, %d, %d)"
-             "failed: %d", swapIntervalZero, reqWidth, reqHeight, reqFormat,
-             reqUsage, result);
+        ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer"
+                "(%d, %d, %d, %d) failed: %d", reqWidth, reqHeight, reqFormat,
+                reqUsage, result);
         return result;
     }
 
@@ -341,7 +340,7 @@
     IGraphicBufferProducer::QueueBufferOutput output;
     IGraphicBufferProducer::QueueBufferInput input(timestamp, isAutoTimestamp,
             mDataSpace, crop, mScalingMode, mTransform ^ mStickyTransform,
-            mSwapIntervalZero, fence, mStickyTransform);
+            fence, mStickyTransform);
 
     if (mConnectedToCpu || mDirtyRegion.bounds() == Rect::INVALID_RECT) {
         input.setSurfaceDamage(Region::INVALID_REGION);
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 8a3be3d..5244d82 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -113,7 +113,7 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
+            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
                     GRALLOC_USAGE_SW_WRITE_OFTEN));
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
 
@@ -125,7 +125,7 @@
 
     IGraphicBufferProducer::QueueBufferInput input(0, false,
             HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
-            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE);
+            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
 
     BufferItem item;
@@ -152,12 +152,12 @@
     sp<GraphicBuffer> buf;
     IGraphicBufferProducer::QueueBufferInput qbi(0, false,
             HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
-            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE);
+            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
     BufferItem item;
 
     for (int i = 0; i < 2; i++) {
         ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-                mProducer->dequeueBuffer(&slot, &fence, false, 1, 1, 0,
+                mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0,
                     GRALLOC_USAGE_SW_READ_OFTEN));
         ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
         ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
@@ -165,7 +165,7 @@
     }
 
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, false, 1, 1, 0,
+            mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0,
                 GRALLOC_USAGE_SW_READ_OFTEN));
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
@@ -248,7 +248,7 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
+            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
                     GRALLOC_USAGE_SW_WRITE_OFTEN));
     ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(slot)); // Not requested
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
@@ -272,7 +272,7 @@
     ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, buffer));
     IGraphicBufferProducer::QueueBufferInput input(0, false,
             HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
-            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE);
+            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
     ASSERT_EQ(OK, mProducer->queueBuffer(newSlot, input, &output));
 
     BufferItem item;
@@ -297,12 +297,12 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
+            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
                     GRALLOC_USAGE_SW_WRITE_OFTEN));
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
     IGraphicBufferProducer::QueueBufferInput input(0, false,
             HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
-            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE);
+            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
 
     ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(-1)); // Index too low
@@ -333,7 +333,7 @@
             EGL_NO_SYNC_KHR, Fence::NO_FENCE));
 
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
+            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
                     GRALLOC_USAGE_SW_WRITE_OFTEN));
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
 
@@ -356,7 +356,7 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
+            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
                     GRALLOC_USAGE_SW_WRITE_OFTEN));
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
 
@@ -368,7 +368,7 @@
 
     IGraphicBufferProducer::QueueBufferInput input(0, false,
             HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
-            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE);
+            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
 
     BufferItem item;
@@ -405,13 +405,13 @@
     sp<GraphicBuffer> buffer;
     // This should return an error since it would require an allocation
     ASSERT_EQ(OK, mProducer->allowAllocation(false));
-    ASSERT_EQ(WOULD_BLOCK, mProducer->dequeueBuffer(&slot, &fence, false, 0, 0,
+    ASSERT_EQ(WOULD_BLOCK, mProducer->dequeueBuffer(&slot, &fence, 0, 0,
             0, GRALLOC_USAGE_SW_WRITE_OFTEN));
 
     // This should succeed, now that we've lifted the prohibition
     ASSERT_EQ(OK, mProducer->allowAllocation(true));
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
+            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
             GRALLOC_USAGE_SW_WRITE_OFTEN));
 
     // Release the previous buffer back to the BufferQueue
@@ -419,7 +419,7 @@
 
     // This should fail since we're requesting a different size
     ASSERT_EQ(OK, mProducer->allowAllocation(false));
-    ASSERT_EQ(WOULD_BLOCK, mProducer->dequeueBuffer(&slot, &fence, false,
+    ASSERT_EQ(WOULD_BLOCK, mProducer->dequeueBuffer(&slot, &fence,
             WIDTH * 2, HEIGHT * 2, 0, GRALLOC_USAGE_SW_WRITE_OFTEN));
 }
 
@@ -437,7 +437,7 @@
     int slot;
     sp<Fence> fence;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0, 0));
+            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
 
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
diff --git a/libs/gui/tests/CpuConsumer_test.cpp b/libs/gui/tests/CpuConsumer_test.cpp
index d559e54..289cc74 100644
--- a/libs/gui/tests/CpuConsumer_test.cpp
+++ b/libs/gui/tests/CpuConsumer_test.cpp
@@ -449,6 +449,9 @@
         const CpuConsumerTestParams& params,
         int maxBufferSlack) {
     status_t err;
+    err = native_window_api_connect(anw.get(), NATIVE_WINDOW_API_CPU);
+    ASSERT_NO_ERROR(err, "connect error: ");
+
     err = native_window_set_buffers_dimensions(anw.get(),
             params.width, params.height);
     ASSERT_NO_ERROR(err, "set_buffers_dimensions error: ");
diff --git a/libs/gui/tests/IGraphicBufferProducer_test.cpp b/libs/gui/tests/IGraphicBufferProducer_test.cpp
index d6bd8a8..7455cd9 100644
--- a/libs/gui/tests/IGraphicBufferProducer_test.cpp
+++ b/libs/gui/tests/IGraphicBufferProducer_test.cpp
@@ -61,7 +61,6 @@
     const Rect QUEUE_BUFFER_INPUT_RECT = Rect(DEFAULT_WIDTH, DEFAULT_HEIGHT);
     const int QUEUE_BUFFER_INPUT_SCALING_MODE = 0;
     const int QUEUE_BUFFER_INPUT_TRANSFORM = 0;
-    const bool QUEUE_BUFFER_INPUT_ASYNC = false;
     const sp<Fence> QUEUE_BUFFER_INPUT_FENCE = Fence::NO_FENCE;
 }; // namespace anonymous
 
@@ -131,7 +130,6 @@
            crop = QUEUE_BUFFER_INPUT_RECT;
            scalingMode = QUEUE_BUFFER_INPUT_SCALING_MODE;
            transform = QUEUE_BUFFER_INPUT_TRANSFORM;
-           async = QUEUE_BUFFER_INPUT_ASYNC;
            fence = QUEUE_BUFFER_INPUT_FENCE;
         }
 
@@ -143,7 +141,6 @@
                     crop,
                     scalingMode,
                     transform,
-                    async,
                     fence);
         }
 
@@ -177,11 +174,6 @@
             return *this;
         }
 
-        QueueBufferInputBuilder& setAsync(bool async) {
-            this->async = async;
-            return *this;
-        }
-
         QueueBufferInputBuilder& setFence(sp<Fence> fence) {
             this->fence = fence;
             return *this;
@@ -194,7 +186,6 @@
         Rect crop;
         int scalingMode;
         uint32_t transform;
-        int async;
         sp<Fence> fence;
     }; // struct QueueBufferInputBuilder
 
@@ -204,8 +195,28 @@
         sp<Fence> fence;
     };
 
-    status_t dequeueBuffer(bool async, uint32_t w, uint32_t h, uint32_t format, uint32_t usage, DequeueBufferResult* result) {
-        return mProducer->dequeueBuffer(&result->slot, &result->fence, async, w, h, format, usage);
+    status_t dequeueBuffer(uint32_t w, uint32_t h, uint32_t format, uint32_t usage, DequeueBufferResult* result) {
+        return mProducer->dequeueBuffer(&result->slot, &result->fence, w, h, format, usage);
+    }
+
+    void setupDequeueRequestBuffer(int *slot, sp<Fence> *fence,
+            sp<GraphicBuffer> *buffer)
+    {
+        ASSERT_TRUE(slot != NULL);
+        ASSERT_TRUE(fence != NULL);
+        ASSERT_TRUE(buffer != NULL);
+
+        ASSERT_NO_FATAL_FAILURE(ConnectProducer());
+
+        ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+                (mProducer->dequeueBuffer(slot, fence, DEFAULT_WIDTH,
+                DEFAULT_HEIGHT, DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS)));
+
+        EXPECT_LE(0, *slot);
+        EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, *slot);
+
+        // Request the buffer (pre-requisite for queueing)
+        ASSERT_OK(mProducer->requestBuffer(*slot, buffer));
     }
 
 private: // hide from test body
@@ -334,12 +345,11 @@
     int dequeuedSlot = -1;
     sp<Fence> dequeuedFence;
 
-    // XX: OK to assume first call returns this flag or not? Not really documented.
-    ASSERT_EQ(OK | IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
-                                     QUEUE_BUFFER_INPUT_ASYNC,
+
+    ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+            (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
                                      DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
-                                     TEST_PRODUCER_USAGE_BITS));
+                                     TEST_PRODUCER_USAGE_BITS)));
 
     EXPECT_LE(0, dequeuedSlot);
     EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, dequeuedSlot);
@@ -400,11 +410,10 @@
     int dequeuedSlot = -1;
     sp<Fence> dequeuedFence;
 
-    ASSERT_EQ(OK | IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
-                                     QUEUE_BUFFER_INPUT_ASYNC,
+    ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+            (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
                                      DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
-                                     TEST_PRODUCER_USAGE_BITS));
+                                     TEST_PRODUCER_USAGE_BITS)));
 
     // Slot was enqueued without requesting a buffer
     {
@@ -470,11 +479,10 @@
     int dequeuedSlot = -1;
     sp<Fence> dequeuedFence;
 
-    ASSERT_EQ(OK | IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
-                                     QUEUE_BUFFER_INPUT_ASYNC,
+    ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+            (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
                                      DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
-                                     TEST_PRODUCER_USAGE_BITS));
+                                     TEST_PRODUCER_USAGE_BITS)));
 
     // No return code, but at least test that it doesn't blow up...
     // TODO: add a return code
@@ -482,6 +490,7 @@
 }
 
 TEST_F(IGraphicBufferProducerTest, SetMaxDequeuedBufferCount_Succeeds) {
+    ASSERT_NO_FATAL_FAILURE(ConnectProducer());
     int minUndequeuedBuffers;
     ASSERT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
             &minUndequeuedBuffers));
@@ -499,10 +508,9 @@
     for (int i = 0; i < minBuffers; ++i) {
         DequeueBufferResult result;
 
-        EXPECT_LE(OK,
-                dequeueBuffer(QUEUE_BUFFER_INPUT_ASYNC,
-                              DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
-                              TEST_PRODUCER_USAGE_BITS, &result))
+        EXPECT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+                (dequeueBuffer(DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
+                              TEST_PRODUCER_USAGE_BITS, &result)))
                 << "iteration: " << i << ", slot: " << result.slot;
 
         dequeueList.push_back(result);
@@ -520,17 +528,17 @@
         int dequeuedSlot = -1;
         sp<Fence> dequeuedFence;
 
-        EXPECT_LE(OK,
-                mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
-                                         QUEUE_BUFFER_INPUT_ASYNC,
+        EXPECT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+                (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
                                          DEFAULT_WIDTH, DEFAULT_HEIGHT,
                                          DEFAULT_FORMAT,
-                                         TEST_PRODUCER_USAGE_BITS))
+                                         TEST_PRODUCER_USAGE_BITS)))
                 << "iteration: " << i << ", slot: " << dequeuedSlot;
     }
 }
 
 TEST_F(IGraphicBufferProducerTest, SetMaxDequeuedBufferCount_Fails) {
+    ASSERT_NO_FATAL_FAILURE(ConnectProducer());
     int minUndequeuedBuffers;
     ASSERT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
                                &minUndequeuedBuffers));
@@ -550,12 +558,11 @@
         int dequeuedSlot = -1;
         sp<Fence> dequeuedFence;
 
-        ASSERT_LE(OK,
-                mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
-                                         QUEUE_BUFFER_INPUT_ASYNC,
+        ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+                (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
                                          DEFAULT_WIDTH, DEFAULT_HEIGHT,
                                          DEFAULT_FORMAT,
-                                         TEST_PRODUCER_USAGE_BITS))
+                                         TEST_PRODUCER_USAGE_BITS)))
                 << "slot: " << dequeuedSlot;
     }
 
@@ -574,40 +581,39 @@
 
 TEST_F(IGraphicBufferProducerTest, SetAsyncMode_Succeeds) {
     ASSERT_OK(mConsumer->setMaxAcquiredBufferCount(1)) << "maxAcquire: " << 1;
+    ASSERT_NO_FATAL_FAILURE(ConnectProducer());
     ASSERT_OK(mProducer->setAsyncMode(true)) << "async mode: " << true;
     ASSERT_OK(mProducer->setMaxDequeuedBufferCount(1)) << "maxDequeue: " << 1;
 
     int dequeuedSlot = -1;
     sp<Fence> dequeuedFence;
-    IGraphicBufferProducer::QueueBufferInput input(QUEUE_BUFFER_INPUT_TIMESTAMP,
-            QUEUE_BUFFER_INPUT_IS_AUTO_TIMESTAMP, QUEUE_BUFFER_INPUT_DATASPACE,
-            QUEUE_BUFFER_INPUT_RECT, QUEUE_BUFFER_INPUT_SCALING_MODE,
-            QUEUE_BUFFER_INPUT_TRANSFORM, true, QUEUE_BUFFER_INPUT_FENCE);
+    IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
     IGraphicBufferProducer::QueueBufferOutput output;
     sp<GraphicBuffer> dequeuedBuffer;
 
     // Should now be able to queue/dequeue as many buffers as we want without
     // blocking
     for (int i = 0; i < 5; ++i) {
-        ASSERT_LE(OK, mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
-                true, DEFAULT_WIDTH, DEFAULT_HEIGHT,
-                DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS)) << "slot : "
-                << dequeuedSlot;
+        ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+                (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
+                DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
+                TEST_PRODUCER_USAGE_BITS))) << "slot : " << dequeuedSlot;
         ASSERT_OK(mProducer->requestBuffer(dequeuedSlot, &dequeuedBuffer));
         ASSERT_OK(mProducer->queueBuffer(dequeuedSlot, input, &output));
     }
 }
 
 TEST_F(IGraphicBufferProducerTest, SetAsyncMode_Fails) {
+    ASSERT_NO_FATAL_FAILURE(ConnectProducer());
     // Prerequisite to fail out a valid setBufferCount call
     {
         int dequeuedSlot = -1;
         sp<Fence> dequeuedFence;
 
-        ASSERT_LE(OK, mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
-                QUEUE_BUFFER_INPUT_ASYNC, DEFAULT_WIDTH, DEFAULT_HEIGHT,
-                DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS)) << "slot: "
-                        << dequeuedSlot;
+        ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+                (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
+                DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
+                TEST_PRODUCER_USAGE_BITS))) << "slot: " << dequeuedSlot;
     }
 
     // Client has one or more buffers dequeued
@@ -622,4 +628,101 @@
             << false;
 }
 
+TEST_F(IGraphicBufferProducerTest,
+        DisconnectedProducerReturnsError_dequeueBuffer) {
+    int slot = -1;
+    sp<Fence> fence;
+
+    ASSERT_EQ(NO_INIT, mProducer->dequeueBuffer(&slot, &fence, DEFAULT_WIDTH,
+            DEFAULT_HEIGHT, DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS));
+}
+
+TEST_F(IGraphicBufferProducerTest,
+        DisconnectedProducerReturnsError_detachNextBuffer) {
+    sp<Fence> fence;
+    sp<GraphicBuffer> buffer;
+
+    ASSERT_EQ(NO_INIT, mProducer->detachNextBuffer(&buffer, &fence));
+}
+
+TEST_F(IGraphicBufferProducerTest,
+        DisconnectedProducerReturnsError_requestBuffer) {
+    ASSERT_NO_FATAL_FAILURE(ConnectProducer());
+
+    int slot = -1;
+    sp<Fence> fence;
+
+    ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+            (mProducer->dequeueBuffer(&slot, &fence, DEFAULT_WIDTH,
+            DEFAULT_HEIGHT, DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS)));
+
+    EXPECT_LE(0, slot);
+    EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, slot);
+
+    ASSERT_OK(mProducer->disconnect(TEST_API));
+
+    sp<GraphicBuffer> buffer;
+
+    ASSERT_EQ(NO_INIT, mProducer->requestBuffer(slot, &buffer));
+}
+
+
+TEST_F(IGraphicBufferProducerTest,
+        DisconnectedProducerReturnsError_detachBuffer) {
+    int slot = -1;
+    sp<Fence> fence;
+    sp<GraphicBuffer> buffer;
+
+    setupDequeueRequestBuffer(&slot, &fence, &buffer);
+
+    ASSERT_OK(mProducer->disconnect(TEST_API));
+
+    ASSERT_EQ(NO_INIT, mProducer->detachBuffer(slot));
+}
+
+TEST_F(IGraphicBufferProducerTest,
+        DisconnectedProducerReturnsError_queueBuffer) {
+    int slot = -1;
+    sp<Fence> fence;
+    sp<GraphicBuffer> buffer;
+
+    setupDequeueRequestBuffer(&slot, &fence, &buffer);
+
+    ASSERT_OK(mProducer->disconnect(TEST_API));
+
+    // A generic "valid" input
+    IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
+    IGraphicBufferProducer::QueueBufferOutput output;
+
+    ASSERT_EQ(NO_INIT, mProducer->queueBuffer(slot, input, &output));
+}
+
+TEST_F(IGraphicBufferProducerTest,
+        DisconnectedProducerReturnsError_cancelBuffer) {
+    int slot = -1;
+    sp<Fence> fence;
+    sp<GraphicBuffer> buffer;
+
+    setupDequeueRequestBuffer(&slot, &fence, &buffer);
+
+    ASSERT_OK(mProducer->disconnect(TEST_API));
+
+    ASSERT_EQ(NO_INIT, mProducer->cancelBuffer(slot, fence));
+}
+
+TEST_F(IGraphicBufferProducerTest,
+        DisconnectedProducerReturnsError_attachBuffer) {
+    int slot = -1;
+    sp<Fence> fence;
+    sp<GraphicBuffer> buffer;
+
+    setupDequeueRequestBuffer(&slot, &fence, &buffer);
+
+    ASSERT_OK(mProducer->detachBuffer(slot));
+
+    ASSERT_OK(mProducer->disconnect(TEST_API));
+
+    ASSERT_EQ(NO_INIT, mProducer->attachBuffer(&slot, buffer));
+}
+
 } // namespace android
diff --git a/libs/gui/tests/StreamSplitter_test.cpp b/libs/gui/tests/StreamSplitter_test.cpp
index afd149e..c7ce263 100644
--- a/libs/gui/tests/StreamSplitter_test.cpp
+++ b/libs/gui/tests/StreamSplitter_test.cpp
@@ -103,7 +103,7 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            inputProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
+            inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
                     GRALLOC_USAGE_SW_WRITE_OFTEN));
     ASSERT_EQ(OK, inputProducer->requestBuffer(slot, &buffer));
 
@@ -114,9 +114,8 @@
     ASSERT_EQ(OK, buffer->unlock());
 
     IGraphicBufferProducer::QueueBufferInput qbInput(0, false,
-            HAL_DATASPACE_UNKNOWN,
-            Rect(0, 0, 1, 1), NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false,
-            Fence::NO_FENCE);
+            HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
+            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
     ASSERT_EQ(OK, inputProducer->queueBuffer(slot, qbInput, &qbOutput));
 
     BufferItem item;
@@ -132,7 +131,7 @@
             EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
 
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            inputProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
+            inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
                     GRALLOC_USAGE_SW_WRITE_OFTEN));
 
     ASSERT_EQ(1, allocator->getAllocCount());
@@ -170,7 +169,7 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            inputProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
+            inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
                     GRALLOC_USAGE_SW_WRITE_OFTEN));
     ASSERT_EQ(OK, inputProducer->requestBuffer(slot, &buffer));
 
@@ -181,9 +180,8 @@
     ASSERT_EQ(OK, buffer->unlock());
 
     IGraphicBufferProducer::QueueBufferInput qbInput(0, false,
-            HAL_DATASPACE_UNKNOWN,
-            Rect(0, 0, 1, 1), NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false,
-            Fence::NO_FENCE);
+            HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
+            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
     ASSERT_EQ(OK, inputProducer->queueBuffer(slot, qbInput, &qbOutput));
 
     for (int output = 0; output < NUM_OUTPUTS; ++output) {
@@ -202,7 +200,7 @@
     }
 
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            inputProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
+            inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
                     GRALLOC_USAGE_SW_WRITE_OFTEN));
 
     ASSERT_EQ(1, allocator->getAllocCount());
@@ -231,7 +229,7 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            inputProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
+            inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
                     GRALLOC_USAGE_SW_WRITE_OFTEN));
     ASSERT_EQ(OK, inputProducer->requestBuffer(slot, &buffer));
 
@@ -239,14 +237,13 @@
     outputConsumer->consumerDisconnect();
 
     IGraphicBufferProducer::QueueBufferInput qbInput(0, false,
-            HAL_DATASPACE_UNKNOWN,
-            Rect(0, 0, 1, 1), NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false,
-            Fence::NO_FENCE);
+            HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
+            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
     ASSERT_EQ(OK, inputProducer->queueBuffer(slot, qbInput, &qbOutput));
 
     // Input should be abandoned
-    ASSERT_EQ(NO_INIT, inputProducer->dequeueBuffer(&slot, &fence, false, 0, 0,
-            0, GRALLOC_USAGE_SW_WRITE_OFTEN));
+    ASSERT_EQ(NO_INIT, inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
+            GRALLOC_USAGE_SW_WRITE_OFTEN));
 }
 
 } // namespace android
diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp
index c61eb1a..2356f54 100644
--- a/libs/gui/tests/SurfaceTextureClient_test.cpp
+++ b/libs/gui/tests/SurfaceTextureClient_test.cpp
@@ -216,6 +216,7 @@
 }
 
 TEST_F(SurfaceTextureClientTest, DefaultGeometryValues) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ANativeWindowBuffer* buf;
     ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
     EXPECT_EQ(1, buf->width);
@@ -225,6 +226,7 @@
 }
 
 TEST_F(SurfaceTextureClientTest, BufferGeometryCanBeSet) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ANativeWindowBuffer* buf;
     EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 16, 8));
     EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), PIXEL_FORMAT_RGB_565));
@@ -236,6 +238,7 @@
 }
 
 TEST_F(SurfaceTextureClientTest, BufferGeometryDefaultSizeSetFormat) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ANativeWindowBuffer* buf;
     EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 0, 0));
     EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), PIXEL_FORMAT_RGB_565));
@@ -247,6 +250,7 @@
 }
 
 TEST_F(SurfaceTextureClientTest, BufferGeometrySetSizeDefaultFormat) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ANativeWindowBuffer* buf;
     EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 16, 8));
     EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), 0));
@@ -258,6 +262,7 @@
 }
 
 TEST_F(SurfaceTextureClientTest, BufferGeometrySizeCanBeUnset) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ANativeWindowBuffer* buf;
     EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 16, 8));
     EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), 0));
@@ -276,6 +281,7 @@
 }
 
 TEST_F(SurfaceTextureClientTest, BufferGeometrySizeCanBeChangedWithoutFormat) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ANativeWindowBuffer* buf;
     EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 0, 0));
     EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), PIXEL_FORMAT_RGB_565));
@@ -293,6 +299,7 @@
 }
 
 TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSize) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     sp<GLConsumer> st(mST);
     ANativeWindowBuffer* buf;
     EXPECT_EQ(OK, st->setDefaultBufferSize(16, 8));
@@ -305,6 +312,7 @@
 
 TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSizeAfterDequeue) {
     ANativeWindowBuffer* buf[2];
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     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]));
@@ -325,6 +333,7 @@
 
 TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSizeVsGeometry) {
     ANativeWindowBuffer* buf[2];
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
     EXPECT_EQ(OK, mST->setDefaultBufferSize(16, 8));
     ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
@@ -351,6 +360,7 @@
 
 TEST_F(SurfaceTextureClientTest, SurfaceTextureTooManyUpdateTexImage) {
     android_native_buffer_t* buf[3];
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(OK, mANW->setSwapInterval(mANW.get(), 0));
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
 
@@ -374,6 +384,7 @@
 
 TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeSlowRetire) {
     android_native_buffer_t* buf[3];
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     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]));
@@ -394,6 +405,7 @@
 
 TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeFastRetire) {
     android_native_buffer_t* buf[3];
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     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]));
@@ -414,8 +426,8 @@
 
 TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeDQQR) {
     android_native_buffer_t* buf[3];
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
-
     ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
     ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1));
     EXPECT_EQ(OK, mST->updateTexImage());
@@ -439,6 +451,7 @@
 TEST_F(SurfaceTextureClientTest, DISABLED_SurfaceTextureSyncModeDequeueCurrent) {
     android_native_buffer_t* buf[3];
     android_native_buffer_t* firstBuf;
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     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));
@@ -458,6 +471,7 @@
 
 TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeMinUndequeued) {
     android_native_buffer_t* buf[3];
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     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.
@@ -483,6 +497,7 @@
 }
 
 TEST_F(SurfaceTextureClientTest, SetCropCropsCrop) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     android_native_rect_t rect = {-2, -13, 40, 18};
     native_window_set_crop(mANW.get(), &rect);
 
@@ -537,6 +552,7 @@
     };
 
     android_native_buffer_t* buf[3];
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     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]));
@@ -560,6 +576,7 @@
 TEST_F(SurfaceTextureClientTest, GetTransformMatrixReturnsVerticalFlip) {
     android_native_buffer_t* buf[3];
     float mtx[16] = {};
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     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, mANW->queueBuffer(mANW.get(), buf[0], -1));
@@ -590,6 +607,7 @@
 TEST_F(SurfaceTextureClientTest, GetTransformMatrixSucceedsAfterFreeingBuffers) {
     android_native_buffer_t* buf[3];
     float mtx[16] = {};
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     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, mANW->queueBuffer(mANW.get(), buf[0], -1));
@@ -639,6 +657,7 @@
     crop.right = 5;
     crop.bottom = 5;
 
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
     ASSERT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 8, 8));
     ASSERT_EQ(OK, native_window_set_buffers_format(mANW.get(), 0));
diff --git a/libs/gui/tests/SurfaceTextureFBO_test.cpp b/libs/gui/tests/SurfaceTextureFBO_test.cpp
index c243fc0..0606839 100644
--- a/libs/gui/tests/SurfaceTextureFBO_test.cpp
+++ b/libs/gui/tests/SurfaceTextureFBO_test.cpp
@@ -27,6 +27,8 @@
     const int texWidth = 64;
     const int texHeight = 64;
 
+    ASSERT_EQ(NO_ERROR, native_window_api_connect(mANW.get(),
+            NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
             texWidth, texHeight));
     ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
diff --git a/libs/gui/tests/SurfaceTextureGL_test.cpp b/libs/gui/tests/SurfaceTextureGL_test.cpp
index 0e85b90..1a904b5 100644
--- a/libs/gui/tests/SurfaceTextureGL_test.cpp
+++ b/libs/gui/tests/SurfaceTextureGL_test.cpp
@@ -28,6 +28,8 @@
     const int texWidth = 64;
     const int texHeight = 66;
 
+    ASSERT_EQ(NO_ERROR, native_window_api_connect(mANW.get(),
+            NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
             texWidth, texHeight));
     ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
@@ -76,6 +78,8 @@
     const int texWidth = 64;
     const int texHeight = 64;
 
+    ASSERT_EQ(NO_ERROR, native_window_api_connect(mANW.get(),
+            NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
             texWidth, texHeight));
     ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
@@ -124,6 +128,8 @@
     const int texWidth = 64;
     const int texHeight = 66;
 
+    ASSERT_EQ(NO_ERROR, native_window_api_connect(mANW.get(),
+            NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
             texWidth, texHeight));
     ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
@@ -190,6 +196,8 @@
     enum { texHeight = 16 };
     enum { numFrames = 1024 };
 
+    ASSERT_EQ(NO_ERROR, native_window_api_connect(mANW.get(),
+            NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
             texWidth, texHeight));
     ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
@@ -333,6 +341,8 @@
     const int texWidth = 64;
     const int texHeight = 66;
 
+    ASSERT_EQ(NO_ERROR, native_window_api_connect(mANW.get(),
+            NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
             texWidth, texHeight));
     ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
@@ -377,6 +387,8 @@
     const int texWidth = 64;
     const int texHeight = 64;
 
+    ASSERT_EQ(NO_ERROR, native_window_api_connect(mANW.get(),
+            NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
             texWidth, texHeight));
     ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
@@ -435,7 +447,10 @@
         virtual bool threadLoop() {
             ANativeWindowBuffer* anb;
 
-            native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_EGL);
+            if (native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU) !=
+                    NO_ERROR) {
+                return false;
+            }
 
             for (int numFrames =0 ; numFrames < 2; numFrames ++) {
 
@@ -452,7 +467,10 @@
                 }
             }
 
-            native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_EGL);
+            if (native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_CPU)
+                    != NO_ERROR) {
+                return false;
+            }
 
             return false;
         }
@@ -486,7 +504,7 @@
 // attempt to release a buffer that it does not owned
 TEST_F(SurfaceTextureGLTest, DisconnectClearsCurrentTexture) {
     ASSERT_EQ(OK, native_window_api_connect(mANW.get(),
-            NATIVE_WINDOW_API_EGL));
+            NATIVE_WINDOW_API_CPU));
 
     ANativeWindowBuffer *anb;
 
@@ -500,9 +518,9 @@
     EXPECT_EQ(OK,mST->updateTexImage());
 
     ASSERT_EQ(OK, native_window_api_disconnect(mANW.get(),
-            NATIVE_WINDOW_API_EGL));
+            NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(OK, native_window_api_connect(mANW.get(),
-            NATIVE_WINDOW_API_EGL));
+            NATIVE_WINDOW_API_CPU));
 
     EXPECT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb));
     EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1));
@@ -512,7 +530,7 @@
     EXPECT_EQ(OK,mST->updateTexImage());
 
     ASSERT_EQ(OK, native_window_api_disconnect(mANW.get(),
-            NATIVE_WINDOW_API_EGL));
+            NATIVE_WINDOW_API_CPU));
 }
 
 TEST_F(SurfaceTextureGLTest, ScaleToWindowMode) {
@@ -614,6 +632,11 @@
             Mutex::Autolock lock(mMutex);
             ANativeWindowBuffer* anb;
 
+            if (native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU) !=
+                    NO_ERROR) {
+                return false;
+            }
+
             // Frame 1
             if (native_window_dequeue_buffer_and_wait(mANW.get(),
                     &anb) != NO_ERROR) {
@@ -678,6 +701,9 @@
     int texHeight = 16;
     ANativeWindowBuffer* anb;
 
+    ASSERT_EQ(NO_ERROR, native_window_api_connect(mANW.get(),
+            NATIVE_WINDOW_API_CPU));
+
     GLint maxTextureSize;
     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
 
diff --git a/libs/gui/tests/SurfaceTextureMultiContextGL_test.cpp b/libs/gui/tests/SurfaceTextureMultiContextGL_test.cpp
index f74ac3d..5b02dcf 100644
--- a/libs/gui/tests/SurfaceTextureMultiContextGL_test.cpp
+++ b/libs/gui/tests/SurfaceTextureMultiContextGL_test.cpp
@@ -26,6 +26,7 @@
 namespace android {
 
 TEST_F(SurfaceTextureMultiContextGLTest, UpdateFromMultipleContextsFails) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
@@ -40,6 +41,7 @@
 }
 
 TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextSucceeds) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
@@ -55,6 +57,7 @@
 
 TEST_F(SurfaceTextureMultiContextGLTest,
         DetachFromContextSucceedsAfterProducerDisconnect) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
@@ -70,6 +73,7 @@
 }
 
 TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWhenAbandoned) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
@@ -82,6 +86,7 @@
 }
 
 TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWhenDetached) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
@@ -96,6 +101,7 @@
 }
 
 TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWithNoDisplay) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
@@ -112,6 +118,7 @@
 }
 
 TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWithNoContext) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
@@ -128,6 +135,7 @@
 }
 
 TEST_F(SurfaceTextureMultiContextGLTest, UpdateTexImageFailsWhenDetached) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Detach from the primary context.
@@ -139,6 +147,7 @@
 }
 
 TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextSucceeds) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
@@ -169,6 +178,7 @@
 
 TEST_F(SurfaceTextureMultiContextGLTest,
         AttachToContextSucceedsAfterProducerDisconnect) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
@@ -200,6 +210,7 @@
 
 TEST_F(SurfaceTextureMultiContextGLTest,
         AttachToContextSucceedsBeforeUpdateTexImage) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Detach from the primary context.
@@ -230,6 +241,7 @@
 }
 
 TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextFailsWhenAbandoned) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
@@ -247,6 +259,7 @@
 }
 
 TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextFailsWhenAttached) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
@@ -259,6 +272,7 @@
 
 TEST_F(SurfaceTextureMultiContextGLTest,
         AttachToContextFailsWhenAttachedBeforeUpdateTexImage) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Attempt to attach to the primary context.
@@ -266,6 +280,7 @@
 }
 
 TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextFailsWithNoDisplay) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
@@ -285,6 +300,7 @@
 }
 
 TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextSucceedsTwice) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
@@ -323,6 +339,7 @@
 
 TEST_F(SurfaceTextureMultiContextGLTest,
         AttachToContextSucceedsTwiceBeforeUpdateTexImage) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Detach from the primary context.
@@ -361,6 +378,7 @@
 
 TEST_F(SurfaceTextureMultiContextGLTest,
         UpdateTexImageSucceedsForBufferConsumedBeforeDetach) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
 
     // produce two frames and consume them both on the primary context
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
@@ -387,6 +405,7 @@
 
 TEST_F(SurfaceTextureMultiContextGLTest,
        AttachAfterDisplayTerminatedSucceeds) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
 
     // produce two frames and consume them both on the primary context
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 3f495f8..6f0104a 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -100,6 +100,8 @@
     ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(),
             64, 64, 0, 0x7fffffff, false));
 
+    ASSERT_EQ(NO_ERROR, native_window_api_connect(anw.get(),
+            NATIVE_WINDOW_API_CPU));
     // Set the PROTECTED usage bit and verify that the screenshot fails.  Note
     // that we need to dequeue a buffer in order for it to actually get
     // allocated in SurfaceFlinger.
@@ -190,6 +192,8 @@
     // Allocate a buffer with a generation number of 0
     ANativeWindowBuffer* buffer;
     int fenceFd;
+    ASSERT_EQ(NO_ERROR, native_window_api_connect(window.get(),
+            NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffer, &fenceFd));
     ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffer, fenceFd));
 
diff --git a/libs/input/Android.mk b/libs/input/Android.mk
index 944ac7f..746de66 100644
--- a/libs/input/Android.mk
+++ b/libs/input/Android.mk
@@ -56,6 +56,9 @@
 
 LOCAL_SRC_FILES:= $(deviceSources)
 
+LOCAL_CLANG := true
+LOCAL_SANITIZE := integer
+
 LOCAL_SHARED_LIBRARIES := \
 	liblog \
 	libcutils \
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index 88cd653..0155007 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -456,7 +456,8 @@
         properties.toolType = parcel->readInt32();
     }
 
-    while (sampleCount-- > 0) {
+    while (sampleCount > 0) {
+        sampleCount--;
         mSampleEventTimes.push(parcel->readInt64());
         for (size_t i = 0; i < pointerCount; i++) {
             mSamplePointerCoords.push();
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 0382f57..2dff4e0 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -51,6 +51,10 @@
 // Minimum time difference between consecutive samples before attempting to resample.
 static const nsecs_t RESAMPLE_MIN_DELTA = 2 * NANOS_PER_MS;
 
+// Maximum time difference between consecutive samples before attempting to resample
+// by extrapolation.
+static const nsecs_t RESAMPLE_MAX_DELTA = 20 * NANOS_PER_MS;
+
 // Maximum time to predict forward from the last known state, to avoid predicting too
 // far into the future.  This time is further bounded by 50% of the last time delta.
 static const nsecs_t RESAMPLE_MAX_PREDICTION = 8 * NANOS_PER_MS;
@@ -512,7 +516,8 @@
 status_t InputConsumer::consumeBatch(InputEventFactoryInterface* factory,
         nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
     status_t result;
-    for (size_t i = mBatches.size(); i-- > 0; ) {
+    for (size_t i = mBatches.size(); i > 0; ) {
+        i--;
         Batch& batch = mBatches.editItemAt(i);
         if (frameTime < 0) {
             result = consumeSamples(factory, batch, batch.samples.size(),
@@ -724,7 +729,7 @@
         nsecs_t delta = future.eventTime - current->eventTime;
         if (delta < RESAMPLE_MIN_DELTA) {
 #if DEBUG_RESAMPLING
-            ALOGD("Not resampled, delta time is %lld ns.", delta);
+            ALOGD("Not resampled, delta time is too small: %lld ns.", delta);
 #endif
             return;
         }
@@ -736,7 +741,12 @@
         nsecs_t delta = current->eventTime - other->eventTime;
         if (delta < RESAMPLE_MIN_DELTA) {
 #if DEBUG_RESAMPLING
-            ALOGD("Not resampled, delta time is %lld ns.", delta);
+            ALOGD("Not resampled, delta time is too small: %lld ns.", delta);
+#endif
+            return;
+        } else if (delta > RESAMPLE_MAX_DELTA) {
+#if DEBUG_RESAMPLING
+            ALOGD("Not resampled, delta time is too large: %lld ns.", delta);
 #endif
             return;
         }
@@ -817,7 +827,8 @@
         uint32_t currentSeq = seq;
         uint32_t chainSeqs[seqChainCount];
         size_t chainIndex = 0;
-        for (size_t i = seqChainCount; i-- > 0; ) {
+        for (size_t i = seqChainCount; i > 0; ) {
+             i--;
              const SeqChain& seqChain = mSeqChains.itemAt(i);
              if (seqChain.seq == currentSeq) {
                  currentSeq = seqChain.chain;
@@ -826,7 +837,8 @@
              }
         }
         status_t status = OK;
-        while (!status && chainIndex-- > 0) {
+        while (!status && chainIndex > 0) {
+            chainIndex--;
             status = sendUnchainedFinishedSignal(chainSeqs[chainIndex], handled);
         }
         if (status) {
@@ -836,7 +848,10 @@
                 seqChain.seq = chainIndex != 0 ? chainSeqs[chainIndex - 1] : seq;
                 seqChain.chain = chainSeqs[chainIndex];
                 mSeqChains.push(seqChain);
-            } while (chainIndex-- > 0);
+                if (chainIndex != 0) {
+                    chainIndex--;
+                }
+            } while (chainIndex > 0);
             return status;
         }
     }
diff --git a/libs/input/VelocityTracker.cpp b/libs/input/VelocityTracker.cpp
index 6c70c3c..7f6b157 100644
--- a/libs/input/VelocityTracker.cpp
+++ b/libs/input/VelocityTracker.cpp
@@ -46,7 +46,8 @@
 
 static float vectorDot(const float* a, const float* b, uint32_t m) {
     float r = 0;
-    while (m--) {
+    while (m) {
+        m--;
         r += *(a++) * *(b++);
     }
     return r;
@@ -54,7 +55,8 @@
 
 static float vectorNorm(const float* a, uint32_t m) {
     float r = 0;
-    while (m--) {
+    while (m) {
+        m--;
         float t = *(a++);
         r += t * t;
     }
@@ -511,7 +513,8 @@
     for (uint32_t h = 0; h < m; h++) {
         wy[h] = y[h] * w[h];
     }
-    for (uint32_t i = n; i-- != 0; ) {
+    for (uint32_t i = n; i != 0; ) {
+        i--;
         outB[i] = vectorDot(&q[i][0], wy, m);
         for (uint32_t j = n - 1; j > i; j--) {
             outB[i] -= r[i][j] * outB[j];
diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk
index 29749c0..7fb0f77 100644
--- a/opengl/libs/Android.mk
+++ b/opengl/libs/Android.mk
@@ -59,7 +59,7 @@
   LOCAL_CFLAGS += -DMAX_EGL_CACHE_SIZE=$(MAX_EGL_CACHE_SIZE)
 endif
 
-ifeq (address, $(strip $(SANITIZE_TARGET)))
+ifneq ($(filter address,$(SANITIZE_TARGET)),)
   LOCAL_CFLAGS_32 += -DEGL_WRAPPER_DIR=\"/$(TARGET_COPY_OUT_DATA)/lib\"
   LOCAL_CFLAGS_64 += -DEGL_WRAPPER_DIR=\"/$(TARGET_COPY_OUT_DATA)/lib64\"
 endif
diff --git a/opengl/tools/glgen/src/JniCodeEmitter.java b/opengl/tools/glgen/src/JniCodeEmitter.java
index 1bed05b..5a412bf 100644
--- a/opengl/tools/glgen/src/JniCodeEmitter.java
+++ b/opengl/tools/glgen/src/JniCodeEmitter.java
@@ -673,7 +673,7 @@
                         "\";");
         cStream.println();
 
-        cStream.println("static JNINativeMethod methods[] = {");
+        cStream.println("static const JNINativeMethod methods[] = {");
 
         cStream.println("{\"_nativeClassInit\", \"()V\", (void*)nativeClassInit },");
 
diff --git a/services/inputflinger/host/InputDriver.cpp b/services/inputflinger/host/InputDriver.cpp
index cb4ccbe..bd11d56 100644
--- a/services/inputflinger/host/InputDriver.cpp
+++ b/services/inputflinger/host/InputDriver.cpp
@@ -35,48 +35,6 @@
 
 #define INDENT2 "    "
 
-namespace android {
-
-static input_host_callbacks_t kCallbacks = {
-    .create_device_identifier = create_device_identifier,
-    .create_device_definition = create_device_definition,
-    .create_input_report_definition = create_input_report_definition,
-    .create_output_report_definition = create_output_report_definition,
-    .free_report_definition = free_report_definition,
-    .input_device_definition_add_report = input_device_definition_add_report,
-    .input_report_definition_add_collection = input_report_definition_add_collection,
-    .input_report_definition_declare_usage_int = input_report_definition_declare_usage_int,
-    .input_report_definition_declare_usages_bool = input_report_definition_declare_usages_bool,
-    .register_device = register_device,
-    .input_allocate_report = input_allocate_report,
-    .input_report_set_usage_int = input_report_set_usage_int,
-    .input_report_set_usage_bool = input_report_set_usage_bool,
-    .report_event = report_event,
-    .input_get_device_property_map = input_get_device_property_map,
-    .input_get_device_property = input_get_device_property,
-    .input_get_property_key = input_get_property_key,
-    .input_get_property_value = input_get_property_value,
-    .input_free_device_property = input_free_device_property,
-    .input_free_device_property_map = input_free_device_property_map,
-};
-
-InputDriver::InputDriver(const char* name) : mName(String8(name)) {
-    const hw_module_t* module;
-    int err = input_open(&module, name);
-    LOG_ALWAYS_FATAL_IF(err != 0, "Input module %s not found", name);
-    mHal = reinterpret_cast<const input_module_t*>(module);
-}
-
-void InputDriver::init(InputHostInterface* host) {
-    mHal->init(mHal, static_cast<input_host_t*>(host), kCallbacks);
-}
-
-void InputDriver::dump(String8& result) {
-    result.appendFormat(INDENT2 "HAL Input Driver (%s)\n", mName.string());
-}
-
-} // namespace android
-
 struct input_property_map {
     android::PropertyMap* propertyMap;
 };
@@ -127,92 +85,130 @@
     std::unordered_map<input_collection_id_t, input_collection, InputCollectionIdHasher> collections;
 };
 
-// HAL wrapper functions
 
 namespace android {
 
-::input_device_identifier_t* create_device_identifier(input_host_t* host,
-        const char* name, int32_t product_id, int32_t vendor_id,
-        input_bus_t bus, const char* unique_id) {
+static input_host_callbacks_t kCallbacks = {
+    .create_device_identifier = create_device_identifier,
+    .create_device_definition = create_device_definition,
+    .create_input_report_definition = create_input_report_definition,
+    .create_output_report_definition = create_output_report_definition,
+    .free_report_definition = free_report_definition,
+    .input_device_definition_add_report = input_device_definition_add_report,
+    .input_report_definition_add_collection = input_report_definition_add_collection,
+    .input_report_definition_declare_usage_int = input_report_definition_declare_usage_int,
+    .input_report_definition_declare_usages_bool = input_report_definition_declare_usages_bool,
+    .register_device = register_device,
+    .input_allocate_report = input_allocate_report,
+    .input_report_set_usage_int = input_report_set_usage_int,
+    .input_report_set_usage_bool = input_report_set_usage_bool,
+    .report_event = report_event,
+    .input_get_device_property_map = input_get_device_property_map,
+    .input_get_device_property = input_get_device_property,
+    .input_get_property_key = input_get_property_key,
+    .input_get_property_value = input_get_property_value,
+    .input_free_device_property = input_free_device_property,
+    .input_free_device_property_map = input_free_device_property_map,
+};
+
+InputDriver::InputDriver(const char* name) : mName(String8(name)) {
+    const hw_module_t* module;
+    int err = input_open(&module, name);
+    LOG_ALWAYS_FATAL_IF(err != 0, "Input module %s not found", name);
+    mHal = reinterpret_cast<const input_module_t*>(module);
+}
+
+void InputDriver::init() {
+    mHal->init(mHal, static_cast<input_host_t*>(this), kCallbacks);
+}
+
+input_device_identifier_t* InputDriver::createDeviceIdentifier(
+            const char* name, int32_t productId, int32_t vendorId,
+            input_bus_t bus, const char* uniqueId) {
     auto identifier = new ::input_device_identifier {
         .name = name,
-        .productId = product_id,
-        .vendorId = vendor_id,
-        //.bus = bus,
-        .uniqueId = unique_id,
+        .productId = productId,
+        .vendorId = vendorId,
+        .bus = bus,
+        .uniqueId = uniqueId,
     };
-    // store this identifier somewhere? in the host?
+    // TODO: store this identifier somewhere
     return identifier;
 }
 
-input_device_definition_t* create_device_definition(input_host_t* host) {
+input_device_definition_t* InputDriver::createDeviceDefinition() {
     return new ::input_device_definition;
 }
 
-input_report_definition_t* create_input_report_definition(input_host_t* host) {
+input_report_definition_t* InputDriver::createInputReportDefinition() {
     return new ::input_report_definition;
 }
 
-input_report_definition_t* create_output_report_definition(input_host_t* host) {
+input_report_definition_t* InputDriver::createOutputReportDefinition() {
     return new ::input_report_definition;
 }
 
-void free_report_definition(input_host_t* host, input_report_definition_t* report_def) {
-    delete report_def;
+void InputDriver::freeReportDefinition(input_report_definition_t* reportDef) {
+    delete reportDef;
 }
 
-void input_device_definition_add_report(input_host_t* host,
-        input_device_definition_t* d, input_report_definition_t* r) {
+void InputDriver::inputDeviceDefinitionAddReport(input_device_definition_t* d,
+        input_report_definition_t* r) {
     d->reportDefs.push_back(r);
 }
 
-void input_report_definition_add_collection(input_host_t* host,
-        input_report_definition_t* report, input_collection_id_t id, int32_t arity) {
+void InputDriver::inputReportDefinitionAddCollection(input_report_definition_t* report,
+        input_collection_id_t id, int32_t arity) {
     report->collections[id] = {.arity = arity};
 }
 
-void input_report_definition_declare_usage_int(input_host_t* host,
-        input_report_definition_t* report, input_collection_id_t id,
-        input_usage_t usage, int32_t min, int32_t max, float resolution) {
+void InputDriver::inputReportDefinitionDeclareUsageInt(input_report_definition_t* report,
+        input_collection_id_t id, input_usage_t usage, int32_t min, int32_t max,
+        float resolution) {
     if (report->collections.find(id) != report->collections.end()) {
         report->collections[id].intUsages.push_back({
                 .usage = usage, .min = min, .max = max, .resolution = resolution});
     }
 }
 
-void input_report_definition_declare_usages_bool(input_host_t* host,
-        input_report_definition_t* report, input_collection_id_t id,
-        input_usage_t* usage, size_t usage_count) {
+void InputDriver::inputReportDefinitionDeclareUsagesBool(input_report_definition_t* report,
+        input_collection_id_t id, input_usage_t* usage, size_t usageCount) {
     if (report->collections.find(id) != report->collections.end()) {
-        for (size_t i = 0; i < usage_count; ++i) {
+        for (size_t i = 0; i < usageCount; ++i) {
             report->collections[id].boolUsages.push_back(usage[i]);
         }
     }
 }
 
-input_device_handle_t* register_device(input_host_t* host,
-        input_device_identifier_t* id, input_device_definition_t* d) {
-    ALOGD("Registering device %s with %d input reports", id->name, d->reportDefs.size());
+input_device_handle_t* InputDriver::registerDevice(input_device_identifier_t* id,
+        input_device_definition_t* d) {
+    ALOGD("Registering device %s with %zu input reports", id->name, d->reportDefs.size());
+    // TODO: save this device handle
     return new input_device_handle{ .id = id, .def = d };
 }
 
-input_report_t* input_allocate_report(input_host_t* host, input_report_definition_t* r) {
+void InputDriver::unregisterDevice(input_device_handle_t* handle) {
+    delete handle;
+}
+
+input_report_t* InputDriver::inputAllocateReport(input_report_definition_t* r) {
     ALOGD("Allocating input report for definition %p", r);
     return nullptr;
 }
 
-void input_report_set_usage_int(input_host_t* host, input_report_t* r,
-        input_collection_id_t id, input_usage_t usage, int32_t value, int32_t arity_index) { }
+void InputDriver::inputReportSetUsageInt(input_report_t* r, input_collection_id_t id,
+        input_usage_t usage, int32_t value, int32_t arity_index) {
+}
 
-void input_report_set_usage_bool(input_host_t* host, input_report_t* r,
-        input_collection_id_t id, input_usage_t usage, bool value, int32_t arity_index) { }
+void InputDriver::inputReportSetUsageBool(input_report_t* r, input_collection_id_t id,
+        input_usage_t usage, bool value, int32_t arity_index) {
+}
 
-void report_event(input_host_t* host, input_device_handle_t* d, input_report_t* report) {
+void InputDriver::reportEvent(input_device_handle_t* d, input_report_t* report) {
     ALOGD("report_event %p for handle %p", report, d);
 }
 
-input_property_map_t* input_get_device_property_map(input_host_t* host,
-        input_device_identifier_t* id) {
+input_property_map_t* InputDriver::inputGetDevicePropertyMap(input_device_identifier_t* id) {
     InputDeviceIdentifier idi;
     idi.name = id->name;
     idi.uniqueId = id->uniqueId;
@@ -241,7 +237,7 @@
     return nullptr;
 }
 
-input_property_t* input_get_device_property(input_host_t* host, input_property_map_t* map,
+input_property_t* InputDriver::inputGetDeviceProperty(input_property_map_t* map,
         const char* key) {
     String8 keyString(key);
     if (map != nullptr) {
@@ -258,31 +254,159 @@
     return nullptr;
 }
 
-const char* input_get_property_key(input_host_t* host, input_property_t* property) {
+const char* InputDriver::inputGetPropertyKey(input_property_t* property) {
     if (property != nullptr) {
         return property->key.string();
     }
     return nullptr;
 }
 
-const char* input_get_property_value(input_host_t* host, input_property_t* property) {
+const char* InputDriver::inputGetPropertyValue(input_property_t* property) {
     if (property != nullptr) {
         return property->value.string();
     }
     return nullptr;
 }
 
-void input_free_device_property(input_host_t* host, input_property_t* property) {
+void InputDriver::inputFreeDeviceProperty(input_property_t* property) {
     if (property != nullptr) {
         delete property;
     }
 }
 
-void input_free_device_property_map(input_host_t* host, input_property_map_t* map) {
+void InputDriver::inputFreeDevicePropertyMap(input_property_map_t* map) {
     if (map != nullptr) {
         delete map->propertyMap;
         delete map;
     }
 }
 
+void InputDriver::dump(String8& result) {
+    result.appendFormat(INDENT2 "HAL Input Driver (%s)\n", mName.string());
+}
+
+} // namespace android
+
+// HAL wrapper functions
+
+namespace android {
+
+::input_device_identifier_t* create_device_identifier(input_host_t* host,
+        const char* name, int32_t product_id, int32_t vendor_id,
+        input_bus_t bus, const char* unique_id) {
+    auto driver = static_cast<InputDriverInterface*>(host);
+    return driver->createDeviceIdentifier(name, product_id, vendor_id, bus, unique_id);
+}
+
+input_device_definition_t* create_device_definition(input_host_t* host) {
+    auto driver = static_cast<InputDriverInterface*>(host);
+    return driver->createDeviceDefinition();
+}
+
+input_report_definition_t* create_input_report_definition(input_host_t* host) {
+    auto driver = static_cast<InputDriverInterface*>(host);
+    return driver->createInputReportDefinition();
+}
+
+input_report_definition_t* create_output_report_definition(input_host_t* host) {
+    auto driver = static_cast<InputDriverInterface*>(host);
+    return driver->createOutputReportDefinition();
+}
+
+void free_report_definition(input_host_t* host, input_report_definition_t* report_def) {
+    auto driver = static_cast<InputDriverInterface*>(host);
+    driver->freeReportDefinition(report_def);
+}
+
+void input_device_definition_add_report(input_host_t* host,
+        input_device_definition_t* d, input_report_definition_t* r) {
+    auto driver = static_cast<InputDriverInterface*>(host);
+    driver->inputDeviceDefinitionAddReport(d, r);
+}
+
+void input_report_definition_add_collection(input_host_t* host,
+        input_report_definition_t* report, input_collection_id_t id, int32_t arity) {
+    auto driver = static_cast<InputDriverInterface*>(host);
+    driver->inputReportDefinitionAddCollection(report, id, arity);
+}
+
+void input_report_definition_declare_usage_int(input_host_t* host,
+        input_report_definition_t* report, input_collection_id_t id,
+        input_usage_t usage, int32_t min, int32_t max, float resolution) {
+    auto driver = static_cast<InputDriverInterface*>(host);
+    driver->inputReportDefinitionDeclareUsageInt(report, id, usage, min, max, resolution);
+}
+
+void input_report_definition_declare_usages_bool(input_host_t* host,
+        input_report_definition_t* report, input_collection_id_t id,
+        input_usage_t* usage, size_t usage_count) {
+    auto driver = static_cast<InputDriverInterface*>(host);
+    driver->inputReportDefinitionDeclareUsagesBool(report, id, usage, usage_count);
+}
+
+input_device_handle_t* register_device(input_host_t* host,
+        input_device_identifier_t* id, input_device_definition_t* d) {
+    auto driver = static_cast<InputDriverInterface*>(host);
+    return driver->registerDevice(id, d);
+}
+
+void unregister_device(input_host_t* host, input_device_handle_t* handle) {
+    auto driver = static_cast<InputDriverInterface*>(host);
+    driver->unregisterDevice(handle);
+}
+
+input_report_t* input_allocate_report(input_host_t* host, input_report_definition_t* r) {
+    auto driver = static_cast<InputDriverInterface*>(host);
+    return driver->inputAllocateReport(r);
+}
+
+void input_report_set_usage_int(input_host_t* host, input_report_t* r,
+        input_collection_id_t id, input_usage_t usage, int32_t value, int32_t arity_index) {
+    auto driver = static_cast<InputDriverInterface*>(host);
+    driver->inputReportSetUsageInt(r, id, usage, value, arity_index);
+}
+
+void input_report_set_usage_bool(input_host_t* host, input_report_t* r,
+        input_collection_id_t id, input_usage_t usage, bool value, int32_t arity_index) {
+    auto driver = static_cast<InputDriverInterface*>(host);
+    driver->inputReportSetUsageBool(r, id, usage, value, arity_index);
+}
+
+void report_event(input_host_t* host, input_device_handle_t* d, input_report_t* report) {
+    auto driver = static_cast<InputDriverInterface*>(host);
+    driver->reportEvent(d, report);
+}
+
+input_property_map_t* input_get_device_property_map(input_host_t* host,
+        input_device_identifier_t* id) {
+    auto driver = static_cast<InputDriverInterface*>(host);
+    return driver->inputGetDevicePropertyMap(id);
+}
+
+input_property_t* input_get_device_property(input_host_t* host, input_property_map_t* map,
+        const char* key) {
+    auto driver = static_cast<InputDriverInterface*>(host);
+    return driver->inputGetDeviceProperty(map, key);
+}
+
+const char* input_get_property_key(input_host_t* host, input_property_t* property) {
+    auto driver = static_cast<InputDriverInterface*>(host);
+    return driver->inputGetPropertyKey(property);
+}
+
+const char* input_get_property_value(input_host_t* host, input_property_t* property) {
+    auto driver = static_cast<InputDriverInterface*>(host);
+    return driver->inputGetPropertyValue(property);
+}
+
+void input_free_device_property(input_host_t* host, input_property_t* property) {
+    auto driver = static_cast<InputDriverInterface*>(host);
+    driver->inputFreeDeviceProperty(property);
+}
+
+void input_free_device_property_map(input_host_t* host, input_property_map_t* map) {
+    auto driver = static_cast<InputDriverInterface*>(host);
+    driver->inputFreeDevicePropertyMap(map);
+}
+
 } // namespace android
diff --git a/services/inputflinger/host/InputDriver.h b/services/inputflinger/host/InputDriver.h
index 9bc14a7..8d5a31e 100644
--- a/services/inputflinger/host/InputDriver.h
+++ b/services/inputflinger/host/InputDriver.h
@@ -26,17 +26,56 @@
 #include <utils/RefBase.h>
 #include <utils/String8.h>
 
+// Declare a concrete type for the HAL
+struct input_host {
+};
+
 namespace android {
 
-class InputHostInterface;
-
-class InputDriverInterface : public virtual RefBase {
+class InputDriverInterface : public input_host_t, public virtual RefBase {
 protected:
     InputDriverInterface() = default;
     virtual ~InputDriverInterface() = default;
 
 public:
-    virtual void init(InputHostInterface* host) = 0;
+    virtual void init() = 0;
+
+    virtual input_device_identifier_t* createDeviceIdentifier(
+            const char* name, int32_t productId, int32_t vendorId,
+            input_bus_t bus, const char* uniqueId) = 0;
+    virtual input_device_definition_t* createDeviceDefinition() = 0;
+    virtual input_report_definition_t* createInputReportDefinition() = 0;
+    virtual input_report_definition_t* createOutputReportDefinition() = 0;
+    virtual void freeReportDefinition(input_report_definition_t* reportDef) = 0;
+
+    virtual void inputDeviceDefinitionAddReport(input_device_definition_t* d,
+            input_report_definition_t* r) = 0;
+    virtual void inputReportDefinitionAddCollection(input_report_definition_t* report,
+            input_collection_id_t id, int32_t arity) = 0;
+    virtual void inputReportDefinitionDeclareUsageInt(input_report_definition_t* report,
+            input_collection_id_t id, input_usage_t usage, int32_t min, int32_t max,
+            float resolution) = 0;
+    virtual void inputReportDefinitionDeclareUsagesBool(input_report_definition_t* report,
+            input_collection_id_t id, input_usage_t* usage, size_t usageCount) = 0;
+
+    virtual input_device_handle_t* registerDevice(input_device_identifier_t* id,
+            input_device_definition_t* d) = 0;
+    virtual void unregisterDevice(input_device_handle_t* handle) = 0;
+
+    virtual input_report_t* inputAllocateReport(input_report_definition_t* r) = 0;
+    virtual void inputReportSetUsageInt(input_report_t* r, input_collection_id_t id,
+            input_usage_t usage, int32_t value, int32_t arity_index) = 0;
+    virtual void inputReportSetUsageBool(input_report_t* r, input_collection_id_t id,
+            input_usage_t usage, bool value, int32_t arity_index) = 0;
+    virtual void reportEvent(input_device_handle_t* d, input_report_t* report) = 0;
+
+    virtual input_property_map_t* inputGetDevicePropertyMap(input_device_identifier_t* id) = 0;
+    virtual input_property_t* inputGetDeviceProperty(input_property_map_t* map,
+            const char* key) = 0;
+    virtual const char* inputGetPropertyKey(input_property_t* property) = 0;
+    virtual const char* inputGetPropertyValue(input_property_t* property) = 0;
+    virtual void inputFreeDeviceProperty(input_property_t* property) = 0;
+    virtual void inputFreeDevicePropertyMap(input_property_map_t* map) = 0;
 
     virtual void dump(String8& result) = 0;
 };
@@ -46,7 +85,44 @@
     InputDriver(const char* name);
     virtual ~InputDriver() = default;
 
-    virtual void init(InputHostInterface* host) override;
+    virtual void init() override;
+
+    virtual input_device_identifier_t* createDeviceIdentifier(
+            const char* name, int32_t productId, int32_t vendorId,
+            input_bus_t bus, const char* uniqueId) override;
+    virtual input_device_definition_t* createDeviceDefinition() override;
+    virtual input_report_definition_t* createInputReportDefinition() override;
+    virtual input_report_definition_t* createOutputReportDefinition() override;
+    virtual void freeReportDefinition(input_report_definition_t* reportDef) override;
+
+    virtual void inputDeviceDefinitionAddReport(input_device_definition_t* d,
+            input_report_definition_t* r) override;
+    virtual void inputReportDefinitionAddCollection(input_report_definition_t* report,
+            input_collection_id_t id, int32_t arity) override;
+    virtual void inputReportDefinitionDeclareUsageInt(input_report_definition_t* report,
+            input_collection_id_t id, input_usage_t usage, int32_t min, int32_t max,
+            float resolution) override;
+    virtual void inputReportDefinitionDeclareUsagesBool(input_report_definition_t* report,
+            input_collection_id_t id, input_usage_t* usage, size_t usageCount) override;
+
+    virtual input_device_handle_t* registerDevice(input_device_identifier_t* id,
+            input_device_definition_t* d) override;
+    virtual void unregisterDevice(input_device_handle_t* handle) override;
+
+    virtual input_report_t* inputAllocateReport(input_report_definition_t* r) override;
+    virtual void inputReportSetUsageInt(input_report_t* r, input_collection_id_t id,
+            input_usage_t usage, int32_t value, int32_t arity_index) override;
+    virtual void inputReportSetUsageBool(input_report_t* r, input_collection_id_t id,
+            input_usage_t usage, bool value, int32_t arity_index) override;
+    virtual void reportEvent(input_device_handle_t* d, input_report_t* report) override;
+
+    virtual input_property_map_t* inputGetDevicePropertyMap(input_device_identifier_t* id) override;
+    virtual input_property_t* inputGetDeviceProperty(input_property_map_t* map,
+            const char* key) override;
+    virtual const char* inputGetPropertyKey(input_property_t* property) override;
+    virtual const char* inputGetPropertyValue(input_property_t* property) override;
+    virtual void inputFreeDeviceProperty(input_property_t* property) override;
+    virtual void inputFreeDevicePropertyMap(input_property_map_t* map) override;
 
     virtual void dump(String8& result) override;
 
diff --git a/services/inputflinger/host/InputHost.cpp b/services/inputflinger/host/InputHost.cpp
index 51d3e6b..094200a 100644
--- a/services/inputflinger/host/InputHost.cpp
+++ b/services/inputflinger/host/InputHost.cpp
@@ -28,7 +28,7 @@
 
 void InputHost::registerInputDriver(InputDriverInterface* driver) {
     LOG_ALWAYS_FATAL_IF(driver == nullptr, "Cannot register a nullptr as an InputDriver!");
-    driver->init(this);
+    driver->init();
     mDrivers.push_back(driver);
 }
 
diff --git a/services/inputflinger/host/InputHost.h b/services/inputflinger/host/InputHost.h
index 42a66e0..eda4a89 100644
--- a/services/inputflinger/host/InputHost.h
+++ b/services/inputflinger/host/InputHost.h
@@ -26,15 +26,11 @@
 
 #include "InputDriver.h"
 
-// Declare a concrete type for the HAL
-struct input_host {
-};
-
 namespace android {
 
 class InputDriverInterface;
 
-class InputHostInterface : public input_host_t, public virtual RefBase {
+class InputHostInterface : public virtual RefBase {
 protected:
     InputHostInterface() = default;
     virtual ~InputHostInterface() = default;
diff --git a/services/powermanager/IPowerManager.cpp b/services/powermanager/IPowerManager.cpp
index 0a4244f..bff8719 100644
--- a/services/powermanager/IPowerManager.cpp
+++ b/services/powermanager/IPowerManager.cpp
@@ -95,6 +95,44 @@
         // This FLAG_ONEWAY is in the .aidl, so there is no way to disable it
         return remote()->transact(POWER_HINT, data, &reply, IBinder::FLAG_ONEWAY);
     }
+
+    virtual status_t goToSleep(int64_t event_time_ms, int reason, int flags)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IPowerManager::getInterfaceDescriptor());
+        data.writeInt64(event_time_ms);
+        data.writeInt32(reason);
+        data.writeInt32(flags);
+        return remote()->transact(GO_TO_SLEEP, data, &reply, 0);
+    }
+
+    virtual status_t reboot(bool confirm, const String16& reason, bool wait)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IPowerManager::getInterfaceDescriptor());
+        data.writeInt32(confirm);
+        data.writeString16(reason);
+        data.writeInt32(wait);
+        return remote()->transact(REBOOT, data, &reply, 0);
+    }
+
+    virtual status_t shutdown(bool confirm, const String16& reason, bool wait)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IPowerManager::getInterfaceDescriptor());
+        data.writeInt32(confirm);
+        data.writeString16(reason);
+        data.writeInt32(wait);
+        return remote()->transact(SHUTDOWN, data, &reply, 0);
+    }
+
+    virtual status_t crash(const String16& message)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IPowerManager::getInterfaceDescriptor());
+        data.writeString16(message);
+        return remote()->transact(CRASH, data, &reply, 0);
+    }
 };
 
 IMPLEMENT_META_INTERFACE(PowerManager, "android.os.IPowerManager");
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 94f30d5..48971bc 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -92,6 +92,7 @@
     mConsumer->setConsumerName(ConsumerBase::mName);
     mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_COMPOSER);
     mConsumer->setDefaultBufferSize(sinkWidth, sinkHeight);
+    sink->setAsyncMode(true);
 }
 
 VirtualDisplaySurface::~VirtualDisplaySurface() {
@@ -238,7 +239,6 @@
                         HAL_DATASPACE_UNKNOWN,
                         Rect(mSinkBufferWidth, mSinkBufferHeight),
                         NATIVE_WINDOW_SCALING_MODE_FREEZE, 0 /* transform */,
-                        true /* async*/,
                         outFence),
                     &qbo);
             if (result == NO_ERROR) {
@@ -293,10 +293,8 @@
 status_t VirtualDisplaySurface::dequeueBuffer(Source source,
         PixelFormat format, uint32_t usage, int* sslot, sp<Fence>* fence) {
     LOG_FATAL_IF(mDisplayId < 0, "mDisplayId=%d but should not be < 0.", mDisplayId);
-    // Don't let a slow consumer block us
-    bool async = (source == SOURCE_SINK);
 
-    status_t result = mSource[source]->dequeueBuffer(sslot, fence, async,
+    status_t result = mSource[source]->dequeueBuffer(sslot, fence,
             mSinkBufferWidth, mSinkBufferHeight, format, usage);
     if (result < 0)
         return result;
@@ -335,16 +333,15 @@
     return result;
 }
 
-status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence, bool async,
+status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence,
         uint32_t w, uint32_t h, PixelFormat format, uint32_t usage) {
     if (mDisplayId < 0)
-        return mSource[SOURCE_SINK]->dequeueBuffer(pslot, fence, async, w, h, format, usage);
+        return mSource[SOURCE_SINK]->dequeueBuffer(pslot, fence, w, h, format, usage);
 
     VDS_LOGW_IF(mDbgState != DBG_STATE_PREPARED,
             "Unexpected dequeueBuffer() in %s state", dbgStateStr());
     mDbgState = DBG_STATE_GLES;
 
-    VDS_LOGW_IF(!async, "EGL called dequeueBuffer with !async despite eglSwapInterval(0)");
     VDS_LOGV("dequeueBuffer %dx%d fmt=%d usage=%#x", w, h, format, usage);
 
     status_t result = NO_ERROR;
@@ -464,9 +461,8 @@
         Rect crop;
         int scalingMode;
         uint32_t transform;
-        bool async;
         input.deflate(&timestamp, &isAutoTimestamp, &dataSpace, &crop,
-                &scalingMode, &transform, &async, &mFbFence);
+                &scalingMode, &transform, &mFbFence);
 
         mFbProducerSlot = pslot;
         mOutputFence = mFbFence;
@@ -476,7 +472,8 @@
     return NO_ERROR;
 }
 
-void VirtualDisplaySurface::cancelBuffer(int pslot, const sp<Fence>& fence) {
+status_t VirtualDisplaySurface::cancelBuffer(int pslot,
+        const sp<Fence>& fence) {
     if (mDisplayId < 0)
         return mSource[SOURCE_SINK]->cancelBuffer(mapProducer2SourceSlot(SOURCE_SINK, pslot), fence);
 
@@ -524,9 +521,8 @@
     return INVALID_OPERATION;
 }
 
-void VirtualDisplaySurface::allocateBuffers(bool /* async */,
-        uint32_t /* width */, uint32_t /* height */, PixelFormat /* format */,
-        uint32_t /* usage */) {
+void VirtualDisplaySurface::allocateBuffers(uint32_t /* width */,
+        uint32_t /* height */, PixelFormat /* format */, uint32_t /* usage */) {
     // TODO: Should we actually allocate buffers for a virtual display?
 }
 
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index 5807eb1..d53d43c 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -100,21 +100,21 @@
     virtual status_t requestBuffer(int pslot, sp<GraphicBuffer>* outBuf);
     virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers);
     virtual status_t setAsyncMode(bool async);
-    virtual status_t dequeueBuffer(int* pslot, sp<Fence>* fence, bool async,
-            uint32_t w, uint32_t h, PixelFormat format, uint32_t usage);
+    virtual status_t dequeueBuffer(int* pslot, sp<Fence>* fence, uint32_t w,
+            uint32_t h, PixelFormat format, uint32_t usage);
     virtual status_t detachBuffer(int slot);
     virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer,
             sp<Fence>* outFence);
     virtual status_t attachBuffer(int* slot, const sp<GraphicBuffer>& buffer);
     virtual status_t queueBuffer(int pslot,
             const QueueBufferInput& input, QueueBufferOutput* output);
-    virtual void cancelBuffer(int pslot, const sp<Fence>& fence);
+    virtual status_t cancelBuffer(int pslot, const sp<Fence>& fence);
     virtual int query(int what, int* value);
     virtual status_t connect(const sp<IProducerListener>& listener,
             int api, bool producerControlledByApp, QueueBufferOutput* output);
     virtual status_t disconnect(int api);
     virtual status_t setSidebandStream(const sp<NativeHandle>& stream);
-    virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
+    virtual void allocateBuffers(uint32_t width, uint32_t height,
             PixelFormat format, uint32_t usage);
     virtual status_t allowAllocation(bool allow);
     virtual status_t setGenerationNumber(uint32_t generationNumber);
diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp
index 85182d9..79ef92f 100644
--- a/services/surfaceflinger/MonitoredProducer.cpp
+++ b/services/surfaceflinger/MonitoredProducer.cpp
@@ -66,8 +66,8 @@
 }
 
 status_t MonitoredProducer::dequeueBuffer(int* slot, sp<Fence>* fence,
-        bool async, uint32_t w, uint32_t h, PixelFormat format, uint32_t usage) {
-    return mProducer->dequeueBuffer(slot, fence, async, w, h, format, usage);
+        uint32_t w, uint32_t h, PixelFormat format, uint32_t usage) {
+    return mProducer->dequeueBuffer(slot, fence, w, h, format, usage);
 }
 
 status_t MonitoredProducer::detachBuffer(int slot) {
@@ -89,8 +89,8 @@
     return mProducer->queueBuffer(slot, input, output);
 }
 
-void MonitoredProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
-    mProducer->cancelBuffer(slot, fence);
+status_t MonitoredProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
+    return mProducer->cancelBuffer(slot, fence);
 }
 
 int MonitoredProducer::query(int what, int* value) {
@@ -110,9 +110,9 @@
     return mProducer->setSidebandStream(stream);
 }
 
-void MonitoredProducer::allocateBuffers(bool async, uint32_t width,
-        uint32_t height, PixelFormat format, uint32_t usage) {
-    mProducer->allocateBuffers(async, width, height, format, usage);
+void MonitoredProducer::allocateBuffers(uint32_t width, uint32_t height,
+        PixelFormat format, uint32_t usage) {
+    mProducer->allocateBuffers(width, height, format, usage);
 }
 
 status_t MonitoredProducer::allowAllocation(bool allow) {
diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h
index f5575ff..3df6f0f 100644
--- a/services/surfaceflinger/MonitoredProducer.h
+++ b/services/surfaceflinger/MonitoredProducer.h
@@ -37,8 +37,8 @@
     virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);
     virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers);
     virtual status_t setAsyncMode(bool async);
-    virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, bool async,
-            uint32_t w, uint32_t h, PixelFormat format, uint32_t usage);
+    virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w,
+            uint32_t h, PixelFormat format, uint32_t usage);
     virtual status_t detachBuffer(int slot);
     virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer,
             sp<Fence>* outFence);
@@ -46,13 +46,13 @@
             const sp<GraphicBuffer>& buffer);
     virtual status_t queueBuffer(int slot, const QueueBufferInput& input,
             QueueBufferOutput* output);
-    virtual void cancelBuffer(int slot, const sp<Fence>& fence);
+    virtual status_t cancelBuffer(int slot, const sp<Fence>& fence);
     virtual int query(int what, int* value);
     virtual status_t connect(const sp<IProducerListener>& token, int api,
             bool producerControlledByApp, QueueBufferOutput* output);
     virtual status_t disconnect(int api);
     virtual status_t setSidebandStream(const sp<NativeHandle>& stream);
-    virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
+    virtual void allocateBuffers(uint32_t width, uint32_t height,
             PixelFormat format, uint32_t usage);
     virtual status_t allowAllocation(bool allow);
     virtual status_t setGenerationNumber(uint32_t generationNumber);
diff --git a/services/surfaceflinger/surfaceflinger.rc b/services/surfaceflinger/surfaceflinger.rc
index 718b6b65..59a43e2 100644
--- a/services/surfaceflinger/surfaceflinger.rc
+++ b/services/surfaceflinger/surfaceflinger.rc
@@ -3,3 +3,4 @@
     user system
     group graphics drmrpc
     onrestart restart zygote
+    writepid /dev/cpuset/system-background/tasks
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 3ae85a9..ee4ad4e 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -24,10 +24,13 @@
 #include <gui/Surface.h>
 #include <gui/SurfaceComposerClient.h>
 #include <private/gui/ComposerService.h>
+#include <private/gui/LayerState.h>
 
 #include <utils/String8.h>
 #include <ui/DisplayInfo.h>
 
+#include <math.h>
+
 namespace android {
 
 // Fill an RGBA_8888 formatted surface with a single color.
@@ -38,8 +41,8 @@
     ASSERT_TRUE(s != NULL);
     ASSERT_EQ(NO_ERROR, s->lock(&outBuffer, NULL));
     uint8_t* img = reinterpret_cast<uint8_t*>(outBuffer.bits);
-    for (uint32_t y = 0; y < outBuffer.height; y++) {
-        for (uint32_t x = 0; x < outBuffer.width; x++) {
+    for (int y = 0; y < outBuffer.height; y++) {
+        for (int x = 0; x < outBuffer.width; x++) {
             uint8_t* pixel = img + (4 * (y*outBuffer.stride + x));
             pixel[0] = r;
             pixel[1] = g;
@@ -76,7 +79,7 @@
             String8 err(String8::format("pixel @ (%3d, %3d): "
                     "expected [%3d, %3d, %3d], got [%3d, %3d, %3d]",
                     x, y, r, g, b, pixel[0], pixel[1], pixel[2]));
-            EXPECT_EQ(String8(), err);
+            EXPECT_EQ(String8(), err) << err.string();
         }
     }
 
@@ -134,6 +137,8 @@
 
         SurfaceComposerClient::openGlobalTransaction();
 
+        mComposerClient->setDisplayLayerStack(display, 0);
+
         ASSERT_EQ(NO_ERROR, mBGSurfaceControl->setLayer(INT_MAX-2));
         ASSERT_EQ(NO_ERROR, mBGSurfaceControl->show());
 
@@ -356,4 +361,77 @@
     }
 }
 
+TEST_F(LayerUpdateTest, LayerSetLayerStackWorks) {
+    sp<ScreenCapture> sc;
+    {
+        SCOPED_TRACE("before setLayerStack");
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel( 24,  24,  63,  63, 195);
+        sc->checkPixel( 75,  75, 195,  63,  63);
+        sc->checkPixel(145, 145,  63,  63, 195);
+    }
+
+    SurfaceComposerClient::openGlobalTransaction();
+    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setLayerStack(1));
+    SurfaceComposerClient::closeGlobalTransaction(true);
+    {
+        // This should hide the foreground surface since it goes to a different
+        // layer stack.
+        SCOPED_TRACE("after setLayerStack");
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel( 24,  24,  63,  63, 195);
+        sc->checkPixel( 75,  75,  63,  63, 195);
+        sc->checkPixel(145, 145,  63,  63, 195);
+    }
+}
+
+TEST_F(LayerUpdateTest, LayerSetFlagsWorks) {
+    sp<ScreenCapture> sc;
+    {
+        SCOPED_TRACE("before setFlags");
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel( 24,  24,  63,  63, 195);
+        sc->checkPixel( 75,  75, 195,  63,  63);
+        sc->checkPixel(145, 145,  63,  63, 195);
+    }
+
+    SurfaceComposerClient::openGlobalTransaction();
+    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setFlags(
+            layer_state_t::eLayerHidden, layer_state_t::eLayerHidden));
+    SurfaceComposerClient::closeGlobalTransaction(true);
+    {
+        // This should hide the foreground surface
+        SCOPED_TRACE("after setFlags");
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel( 24,  24,  63,  63, 195);
+        sc->checkPixel( 75,  75,  63,  63, 195);
+        sc->checkPixel(145, 145,  63,  63, 195);
+    }
+}
+
+TEST_F(LayerUpdateTest, LayerSetMatrixWorks) {
+    sp<ScreenCapture> sc;
+    {
+        SCOPED_TRACE("before setMatrix");
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel( 24,  24,  63,  63, 195);
+        sc->checkPixel( 91,  96, 195,  63,  63);
+        sc->checkPixel( 96, 101, 195,  63,  63);
+        sc->checkPixel(145, 145,  63,  63, 195);
+    }
+
+    SurfaceComposerClient::openGlobalTransaction();
+    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setMatrix(M_SQRT1_2, M_SQRT1_2,
+            -M_SQRT1_2, M_SQRT1_2));
+    SurfaceComposerClient::closeGlobalTransaction(true);
+    {
+        SCOPED_TRACE("after setMatrix");
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel( 24,  24,  63,  63, 195);
+        sc->checkPixel( 91,  96, 195,  63,  63);
+        sc->checkPixel( 96,  91,  63,  63, 195);
+        sc->checkPixel(145, 145,  63,  63, 195);
+    }
+}
+
 }