Merge "Rewrite VirtualDisplaySurface"
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index 38b0b24..7710c5b 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -95,6 +95,7 @@
 
     run_command("PROCESSES", 10, "ps", "-P", NULL);
     run_command("PROCESSES AND THREADS", 10, "ps", "-t", "-p", "-P", NULL);
+    run_command("PROCESSES (SELINUX LABELS)", 10, "ps", "-Z", NULL);
     run_command("LIBRANK", 10, "librank", NULL);
 
     do_dmesg();
@@ -285,7 +286,7 @@
     run_command("CHECKIN MEMINFO", 30, "dumpsys", "meminfo", "--checkin", NULL);
     run_command("CHECKIN NETSTATS", 30, "dumpsys", "netstats", "--checkin", NULL);
     run_command("CHECKIN PROCSTATS", 30, "dumpsys", "procstats", "-c", NULL);
-    run_command("CHECKIN USAGESTATS", 30, "dumpsys", "usagestats", "--c", NULL);
+    run_command("CHECKIN USAGESTATS", 30, "dumpsys", "usagestats", "-c", NULL);
 
     printf("========================================================\n");
     printf("== Running Application Activities\n");
diff --git a/cmds/flatland/GLHelper.cpp b/cmds/flatland/GLHelper.cpp
index 4f7697f..89eb95f 100644
--- a/cmds/flatland/GLHelper.cpp
+++ b/cmds/flatland/GLHelper.cpp
@@ -199,8 +199,8 @@
 bool GLHelper::createNamedSurfaceTexture(GLuint name, uint32_t w, uint32_t h,
         sp<GLConsumer>* glConsumer, EGLSurface* surface) {
     sp<BufferQueue> bq = new BufferQueue(true, mGraphicBufferAlloc);
-    sp<GLConsumer> glc = new GLConsumer(name, true,
-            GL_TEXTURE_EXTERNAL_OES, false, bq);
+    sp<GLConsumer> glc = new GLConsumer(bq, name,
+            GL_TEXTURE_EXTERNAL_OES, false);
     glc->setDefaultBufferSize(w, h);
     glc->setDefaultMaxBufferCount(3);
     glc->setConsumerUsageBits(GRALLOC_USAGE_HW_COMPOSER);
diff --git a/cmds/inputflinger/Android.mk b/cmds/inputflinger/Android.mk
new file mode 100644
index 0000000..b44de44
--- /dev/null
+++ b/cmds/inputflinger/Android.mk
@@ -0,0 +1,28 @@
+# Copyright (C) 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	main.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libbinder \
+	libinputflinger \
+	libutils
+
+LOCAL_MODULE := inputflinger
+
+include $(BUILD_EXECUTABLE)
diff --git a/cmds/inputflinger/main.cpp b/cmds/inputflinger/main.cpp
new file mode 100644
index 0000000..6de7b24
--- /dev/null
+++ b/cmds/inputflinger/main.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <binder/BinderService.h>
+#include <InputFlinger.h>
+
+using namespace android;
+
+int main(int argc, char** argv) {
+    ProcessState::self()->setThreadPoolMaxThreadCount(4);
+    BinderService<InputFlinger>::publishAndJoinThreadPool(true);
+    return 0;
+}
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index 131e03f..84ad204 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -108,11 +108,11 @@
     return 0;
 }
 
-int uninstall(const char *pkgname, uid_t persona)
+int uninstall(const char *pkgname, userid_t userid)
 {
     char pkgdir[PKG_PATH_MAX];
 
-    if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, persona))
+    if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userid))
         return -1;
 
     /* delete contents AND directory, no exceptions */
@@ -173,18 +173,18 @@
     return 0;
 }
 
-int delete_user_data(const char *pkgname, uid_t persona)
+int delete_user_data(const char *pkgname, userid_t userid)
 {
     char pkgdir[PKG_PATH_MAX];
 
-    if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, persona))
+    if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userid))
         return -1;
 
     /* delete contents, excluding "lib", but not the directory itself */
     return delete_dir_contents(pkgdir, 0, "lib");
 }
 
-int make_user_data(const char *pkgname, uid_t uid, uid_t persona)
+int make_user_data(const char *pkgname, uid_t uid, userid_t userid)
 {
     char pkgdir[PKG_PATH_MAX];
     char applibdir[PKG_PATH_MAX];
@@ -192,10 +192,10 @@
     struct stat libStat;
 
     // Create the data dir for the package
-    if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, persona)) {
+    if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userid)) {
         return -1;
     }
-    if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, persona)) {
+    if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, userid)) {
         ALOGE("cannot create package lib symlink origin path\n");
         return -1;
     }
@@ -262,10 +262,10 @@
     return 0;
 }
 
-int delete_persona(uid_t persona)
+int delete_user(userid_t userid)
 {
     char data_path[PKG_PATH_MAX];
-    if (create_persona_path(data_path, persona)) {
+    if (create_user_path(data_path, userid)) {
         return -1;
     }
     if (delete_dir_contents(data_path, 1, NULL)) {
@@ -273,7 +273,7 @@
     }
 
     char media_path[PATH_MAX];
-    if (create_persona_media_path(media_path, (userid_t) persona) == -1) {
+    if (create_user_media_path(media_path, userid) == -1) {
         return -1;
     }
     if (delete_dir_contents(media_path, 1, NULL) == -1) {
@@ -283,11 +283,11 @@
     return 0;
 }
 
-int delete_cache(const char *pkgname, uid_t persona)
+int delete_cache(const char *pkgname, userid_t userid)
 {
     char cachedir[PKG_PATH_MAX];
 
-    if (create_pkg_path(cachedir, pkgname, CACHE_DIR_POSTFIX, persona))
+    if (create_pkg_path(cachedir, pkgname, CACHE_DIR_POSTFIX, userid))
         return -1;
 
         /* delete contents, not the directory, no exceptions */
@@ -319,7 +319,7 @@
     cache = start_cache_collection();
 
     // Collect cache files for primary user.
-    if (create_persona_path(tmpdir, 0) == 0) {
+    if (create_user_path(tmpdir, 0) == 0) {
         //ALOGI("adding cache files from %s\n", tmpdir);
         add_cache_files(cache, tmpdir, "cache");
     }
@@ -420,7 +420,7 @@
     }
 }
 
-int get_size(const char *pkgname, int persona, const char *apkpath,
+int get_size(const char *pkgname, userid_t userid, const char *apkpath,
              const char *libdirpath, const char *fwdlock_apkpath, const char *asecpath,
              int64_t *_codesize, int64_t *_datasize, int64_t *_cachesize,
              int64_t* _asecsize)
@@ -477,7 +477,7 @@
         }
     }
 
-    if (create_pkg_path(path, pkgname, PKG_DIR_POSTFIX, persona)) {
+    if (create_pkg_path(path, pkgname, PKG_DIR_POSTFIX, userid)) {
         goto done;
     }
 
@@ -656,7 +656,7 @@
     struct stat apk_stat, dex_stat;
     char out_path[PKG_PATH_MAX];
     char dexopt_flags[PROPERTY_VALUE_MAX];
-    char dalvik_vm_lib[PROPERTY_VALUE_MAX];
+    char persist_sys_dalvik_vm_lib[PROPERTY_VALUE_MAX];
     char *end;
     int res, zip_fd=-1, out_fd=-1;
 
@@ -668,9 +668,8 @@
     property_get("dalvik.vm.dexopt-flags", dexopt_flags, "");
     ALOGV("dalvik.vm.dexopt_flags=%s\n", dexopt_flags);
 
-    /* The command to run depend ones the value of dalvik.vm.lib */
-    property_get("dalvik.vm.lib", dalvik_vm_lib, "libdvm.so");
-    ALOGV("dalvik.vm.lib=%s\n", dalvik_vm_lib);
+    /* The command to run depend ones the value of persist.sys.dalvik.vm.lib */
+    property_get("persist.sys.dalvik.vm.lib", persist_sys_dalvik_vm_lib, "libdvm.so");
 
     /* Before anything else: is there a .odex file?  If so, we have
      * precompiled the apk and there is nothing to do here.
@@ -739,12 +738,12 @@
             exit(67);
         }
 
-        if (strncmp(dalvik_vm_lib, "libdvm", 6) == 0) {
+        if (strncmp(persist_sys_dalvik_vm_lib, "libdvm", 6) == 0) {
             run_dexopt(zip_fd, out_fd, apk_path, out_path, dexopt_flags);
-        } else if (strncmp(dalvik_vm_lib, "libart", 6) == 0) {
+        } else if (strncmp(persist_sys_dalvik_vm_lib, "libart", 6) == 0) {
             run_dex2oat(zip_fd, out_fd, apk_path, out_path, dexopt_flags);
         } else {
-            exit(69);   /* Unexpected dalvik.vm.lib value */
+            exit(69);   /* Unexpected persist.sys.dalvik.vm.lib value */
         }
         exit(68);   /* only get here on exec failure */
     } else {
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
index 87f900a..1904408 100644
--- a/cmds/installd/installd.c
+++ b/cmds/installd/installd.c
@@ -83,7 +83,7 @@
     int64_t asecsize = 0;
     int res = 0;
 
-        /* pkgdir, persona, apkpath */
+        /* pkgdir, userid, apkpath */
     res = get_size(arg[0], atoi(arg[1]), arg[2], arg[3], arg[4], arg[5],
             &codesize, &datasize, &cachesize, &asecsize);
 
@@ -108,7 +108,7 @@
 
 static int do_rm_user(char **arg, char reply[REPLY_MAX])
 {
-    return delete_persona(atoi(arg[0])); /* userid */
+    return delete_user(atoi(arg[0])); /* userid */
 }
 
 static int do_movefiles(char **arg, char reply[REPLY_MAX])
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index fbfc876..635b07c 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -78,9 +78,6 @@
 #define PKG_NAME_MAX  128   /* largest allowed package name */
 #define PKG_PATH_MAX  256   /* max size of any path we use */
 
-#define PER_USER_RANGE ((uid_t)100000)   /* range of uids per user
-                                            uid = persona * PER_USER_RANGE + appid */
-
 /* data structures */
 
 typedef struct {
@@ -138,17 +135,17 @@
 int create_pkg_path(char path[PKG_PATH_MAX],
                     const char *pkgname,
                     const char *postfix,
-                    uid_t persona);
+                    userid_t userid);
 
-int create_persona_path(char path[PKG_PATH_MAX],
-                    uid_t persona);
+int create_user_path(char path[PKG_PATH_MAX],
+                    userid_t userid);
 
-int create_persona_media_path(char path[PKG_PATH_MAX], userid_t userid);
+int create_user_media_path(char path[PKG_PATH_MAX], userid_t userid);
 
 int create_move_path(char path[PKG_PATH_MAX],
                      const char* pkgname,
                      const char* leaf,
-                     uid_t persona);
+                     userid_t userid);
 
 int is_valid_package_name(const char* pkgname);
 
@@ -193,17 +190,17 @@
 /* commands.c */
 
 int install(const char *pkgname, uid_t uid, gid_t gid, const char *seinfo);
-int uninstall(const char *pkgname, uid_t persona);
+int uninstall(const char *pkgname, userid_t userid);
 int renamepkg(const char *oldpkgname, const char *newpkgname);
 int fix_uid(const char *pkgname, uid_t uid, gid_t gid);
-int delete_user_data(const char *pkgname, uid_t persona);
-int make_user_data(const char *pkgname, uid_t uid, uid_t persona);
-int delete_persona(uid_t persona);
-int delete_cache(const char *pkgname, uid_t persona);
+int delete_user_data(const char *pkgname, userid_t userid);
+int make_user_data(const char *pkgname, uid_t uid, userid_t userid);
+int delete_user(userid_t userid);
+int delete_cache(const char *pkgname, userid_t userid);
 int move_dex(const char *src, const char *dst);
 int rm_dex(const char *path);
 int protect(char *pkgname, gid_t gid);
-int get_size(const char *pkgname, int persona, const char *apkpath, const char *libdirpath,
+int get_size(const char *pkgname, userid_t userid, const char *apkpath, const char *libdirpath,
              const char *fwdlock_apkpath, const char *asecpath, int64_t *codesize,
              int64_t *datasize, int64_t *cachesize, int64_t *asecsize);
 int free_cache(int64_t free_size);
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index 7cb9b37..0b182af 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -340,7 +340,7 @@
 TEST_F(UtilsTest, CreatePersonaPath_Primary) {
     char path[PKG_PATH_MAX];
 
-    EXPECT_EQ(0, create_persona_path(path, 0))
+    EXPECT_EQ(0, create_user_path(path, 0))
             << "Should successfully build primary user path.";
 
     EXPECT_STREQ("/data/data/", path)
@@ -350,7 +350,7 @@
 TEST_F(UtilsTest, CreatePersonaPath_Secondary) {
     char path[PKG_PATH_MAX];
 
-    EXPECT_EQ(0, create_persona_path(path, 1))
+    EXPECT_EQ(0, create_user_path(path, 1))
             << "Should successfully build primary user path.";
 
     EXPECT_STREQ("/data/user/1/", path)
diff --git a/cmds/installd/utils.c b/cmds/installd/utils.c
index 625a35e..ef634c6 100644
--- a/cmds/installd/utils.c
+++ b/cmds/installd/utils.c
@@ -53,38 +53,39 @@
 
 /**
  * Create the package path name for a given package name with a postfix for
- * a certain persona. Returns 0 on success, and -1 on failure.
+ * a certain userid. Returns 0 on success, and -1 on failure.
  */
 int create_pkg_path(char path[PKG_PATH_MAX],
                     const char *pkgname,
                     const char *postfix,
-                    uid_t persona)
+                    userid_t userid)
 {
-    size_t uid_len;
-    char* persona_prefix;
-    if (persona == 0) {
-        persona_prefix = PRIMARY_USER_PREFIX;
-        uid_len = 0;
+    size_t userid_len;
+    char* userid_prefix;
+    if (userid == 0) {
+        userid_prefix = PRIMARY_USER_PREFIX;
+        userid_len = 0;
     } else {
-        persona_prefix = SECONDARY_USER_PREFIX;
-        uid_len = snprintf(NULL, 0, "%d", persona);
+        userid_prefix = SECONDARY_USER_PREFIX;
+        userid_len = snprintf(NULL, 0, "%d", userid);
     }
 
-    const size_t prefix_len = android_data_dir.len + strlen(persona_prefix) + uid_len + 1 /*slash*/;
+    const size_t prefix_len = android_data_dir.len + strlen(userid_prefix)
+            + userid_len + 1 /*slash*/;
     char prefix[prefix_len + 1];
 
     char *dst = prefix;
     size_t dst_size = sizeof(prefix);
 
     if (append_and_increment(&dst, android_data_dir.path, &dst_size) < 0
-            || append_and_increment(&dst, persona_prefix, &dst_size) < 0) {
+            || append_and_increment(&dst, userid_prefix, &dst_size) < 0) {
         ALOGE("Error building prefix for APK path");
         return -1;
     }
 
-    if (persona != 0) {
-        int ret = snprintf(dst, dst_size, "%d/", persona);
-        if (ret < 0 || (size_t) ret != uid_len + 1) {
+    if (userid != 0) {
+        int ret = snprintf(dst, dst_size, "%d/", userid);
+        if (ret < 0 || (size_t) ret != userid_len + 1) {
             ALOGW("Error appending UID to APK path");
             return -1;
         }
@@ -98,39 +99,39 @@
 }
 
 /**
- * Create the path name for user data for a certain persona.
+ * Create the path name for user data for a certain userid.
  * Returns 0 on success, and -1 on failure.
  */
-int create_persona_path(char path[PKG_PATH_MAX],
-                    uid_t persona)
+int create_user_path(char path[PKG_PATH_MAX],
+                    userid_t userid)
 {
-    size_t uid_len;
-    char* persona_prefix;
-    if (persona == 0) {
-        persona_prefix = PRIMARY_USER_PREFIX;
-        uid_len = 0;
+    size_t userid_len;
+    char* userid_prefix;
+    if (userid == 0) {
+        userid_prefix = PRIMARY_USER_PREFIX;
+        userid_len = 0;
     } else {
-        persona_prefix = SECONDARY_USER_PREFIX;
-        uid_len = snprintf(NULL, 0, "%d/", persona);
+        userid_prefix = SECONDARY_USER_PREFIX;
+        userid_len = snprintf(NULL, 0, "%d/", userid);
     }
 
     char *dst = path;
     size_t dst_size = PKG_PATH_MAX;
 
     if (append_and_increment(&dst, android_data_dir.path, &dst_size) < 0
-            || append_and_increment(&dst, persona_prefix, &dst_size) < 0) {
+            || append_and_increment(&dst, userid_prefix, &dst_size) < 0) {
         ALOGE("Error building prefix for user path");
         return -1;
     }
 
-    if (persona != 0) {
-        if (dst_size < uid_len + 1) {
+    if (userid != 0) {
+        if (dst_size < userid_len + 1) {
             ALOGE("Error building user path");
             return -1;
         }
-        int ret = snprintf(dst, dst_size, "%d/", persona);
-        if (ret < 0 || (size_t) ret != uid_len) {
-            ALOGE("Error appending persona id to path");
+        int ret = snprintf(dst, dst_size, "%d/", userid);
+        if (ret < 0 || (size_t) ret != userid_len) {
+            ALOGE("Error appending userid to path");
             return -1;
         }
     }
@@ -138,10 +139,10 @@
 }
 
 /**
- * Create the path name for media for a certain persona.
+ * Create the path name for media for a certain userid.
  * Returns 0 on success, and -1 on failure.
  */
-int create_persona_media_path(char path[PATH_MAX], userid_t userid) {
+int create_user_media_path(char path[PATH_MAX], userid_t userid) {
     if (snprintf(path, PATH_MAX, "%s%d", android_media_dir.path, userid) > PATH_MAX) {
         return -1;
     }
@@ -151,7 +152,7 @@
 int create_move_path(char path[PKG_PATH_MAX],
     const char* pkgname,
     const char* leaf,
-    uid_t persona)
+    userid_t userid)
 {
     if ((android_data_dir.len + strlen(PRIMARY_USER_PREFIX) + strlen(pkgname) + strlen(leaf) + 1)
             >= PKG_PATH_MAX) {
@@ -997,7 +998,7 @@
     char path[PATH_MAX];
 
     // Ensure /data/media/<userid> exists
-    create_persona_media_path(media_user_path, userid);
+    create_user_media_path(media_user_path, userid);
     if (fs_prepare_dir(media_user_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
         return -1;
     }
diff --git a/include/android/keycodes.h b/include/android/keycodes.h
index cf38d1a..1ca1332 100644
--- a/include/android/keycodes.h
+++ b/include/android/keycodes.h
@@ -265,6 +265,7 @@
     AKEYCODE_ASSIST          = 219,
     AKEYCODE_BRIGHTNESS_DOWN = 220,
     AKEYCODE_BRIGHTNESS_UP   = 221,
+    AKEYCODE_MEDIA_AUDIO_TRACK = 222,
 
     // NOTE: If you add a new keycode here you must also add it to several other files.
     //       Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
diff --git a/include/binder/IPCThreadState.h b/include/binder/IPCThreadState.h
index ad0daee..5bc123e 100644
--- a/include/binder/IPCThreadState.h
+++ b/include/binder/IPCThreadState.h
@@ -39,8 +39,8 @@
             
             status_t            clearLastError();
 
-            int                 getCallingPid();
-            int                 getCallingUid();
+            int                 getCallingPid() const;
+            int                 getCallingUid() const;
 
             void                setStrictModePolicy(int32_t policy);
             int32_t             getStrictModePolicy() const;
diff --git a/include/gui/BufferItemConsumer.h b/include/gui/BufferItemConsumer.h
index 98b450c..0af6f8e 100644
--- a/include/gui/BufferItemConsumer.h
+++ b/include/gui/BufferItemConsumer.h
@@ -29,6 +29,8 @@
 
 namespace android {
 
+class BufferQueue;
+
 /**
  * BufferItemConsumer is a BufferQueue consumer endpoint that allows clients
  * access to the whole BufferItem entry from BufferQueue. Multiple buffers may
@@ -49,7 +51,7 @@
     // the consumer usage flags passed to the graphics allocator. The
     // bufferCount parameter specifies how many buffers can be locked for user
     // access at the same time.
-    BufferItemConsumer(uint32_t consumerUsage,
+    BufferItemConsumer(const sp<BufferQueue>& bq, uint32_t consumerUsage,
             int bufferCount = BufferQueue::MIN_UNDEQUEUED_BUFFERS,
             bool synchronousMode = false);
 
@@ -71,7 +73,8 @@
     //
     // If waitForFence is true, and the acquired BufferItem has a valid fence object,
     // acquireBuffer will wait on the fence with no timeout before returning.
-    status_t acquireBuffer(BufferItem *item, bool waitForFence = true);
+    status_t acquireBuffer(BufferItem *item, nsecs_t presentWhen,
+        bool waitForFence = true);
 
     // Returns an acquired buffer to the queue, allowing it to be reused. Since
     // only a fixed number of buffers may be acquired at a time, old buffers
diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h
index 766fa0f..0143be3 100644
--- a/include/gui/BufferQueue.h
+++ b/include/gui/BufferQueue.h
@@ -39,7 +39,7 @@
     enum { NUM_BUFFER_SLOTS = 32 };
     enum { NO_CONNECTED_API = 0 };
     enum { INVALID_BUFFER_SLOT = -1 };
-    enum { STALE_BUFFER_SLOT = 1, NO_BUFFER_AVAILABLE };
+    enum { STALE_BUFFER_SLOT = 1, NO_BUFFER_AVAILABLE, PRESENT_LATER };
 
     // When in async mode we reserve two slots in order to guarantee that the
     // producer and consumer can run asynchronously.
@@ -284,7 +284,13 @@
     // acquired then the BufferItem::mGraphicBuffer field of buffer is set to
     // NULL and it is assumed that the consumer still holds a reference to the
     // buffer.
-    status_t acquireBuffer(BufferItem *buffer);
+    //
+    // If presentWhen is nonzero, it indicates the time when the buffer will
+    // be displayed on screen.  If the buffer's timestamp is farther in the
+    // future, the buffer won't be acquired, and PRESENT_LATER will be
+    // returned.  The presentation time is in nanoseconds, and the time base
+    // is CLOCK_MONOTONIC.
+    status_t acquireBuffer(BufferItem *buffer, nsecs_t presentWhen);
 
     // releaseBuffer releases a buffer slot from the consumer back to the
     // BufferQueue.  This may be done while the buffer's contents are still
diff --git a/include/gui/ConsumerBase.h b/include/gui/ConsumerBase.h
index 1d51bc9..42b84cc 100644
--- a/include/gui/ConsumerBase.h
+++ b/include/gui/ConsumerBase.h
@@ -152,7 +152,8 @@
     // initialization that must take place the first time a buffer is assigned
     // to a slot.  If it is overridden the derived class's implementation must
     // call ConsumerBase::acquireBufferLocked.
-    virtual status_t acquireBufferLocked(BufferQueue::BufferItem *item);
+    virtual status_t acquireBufferLocked(BufferQueue::BufferItem *item,
+        nsecs_t presentWhen);
 
     // releaseBufferLocked relinquishes control over a buffer, returning that
     // control to the BufferQueue.
diff --git a/include/gui/CpuConsumer.h b/include/gui/CpuConsumer.h
index 3c178ef..5f1e369 100644
--- a/include/gui/CpuConsumer.h
+++ b/include/gui/CpuConsumer.h
@@ -28,6 +28,8 @@
 
 namespace android {
 
+class BufferQueue;
+
 /**
  * CpuConsumer is a BufferQueue consumer endpoint that allows direct CPU
  * access to the underlying gralloc buffers provided by BufferQueue. Multiple
@@ -64,7 +66,8 @@
 
     // Create a new CPU consumer. The maxLockedBuffers parameter specifies
     // how many buffers can be locked for user access at the same time.
-    CpuConsumer(uint32_t maxLockedBuffers, bool synchronousMode = true);
+    CpuConsumer(const sp<BufferQueue>& bq,
+            uint32_t maxLockedBuffers, bool synchronousMode = true);
 
     virtual ~CpuConsumer();
 
diff --git a/include/gui/GLConsumer.h b/include/gui/GLConsumer.h
index 031684e..65544bd 100644
--- a/include/gui/GLConsumer.h
+++ b/include/gui/GLConsumer.h
@@ -85,9 +85,9 @@
     // purely to allow a GLConsumer to be transferred from one consumer
     // context to another. If such a transfer is not needed there is no
     // requirement that either of these methods be called.
-    GLConsumer(GLuint tex, bool allowSynchronousMode = true,
-            GLenum texTarget = GL_TEXTURE_EXTERNAL_OES, bool useFenceSync = true,
-            const sp<BufferQueue> &bufferQueue = 0);
+    GLConsumer(const sp<BufferQueue>& bq,
+            GLuint tex, GLenum texTarget = GL_TEXTURE_EXTERNAL_OES,
+            bool useFenceSync = true);
 
     // updateTexImage acquires the most recently queued buffer, and sets the
     // image contents of the target texture to it.
@@ -237,7 +237,8 @@
 
     // acquireBufferLocked overrides the ConsumerBase method to update the
     // mEglSlots array in addition to the ConsumerBase behavior.
-    virtual status_t acquireBufferLocked(BufferQueue::BufferItem *item);
+    virtual status_t acquireBufferLocked(BufferQueue::BufferItem *item,
+        nsecs_t presentWhen);
 
     // releaseBufferLocked overrides the ConsumerBase method to update the
     // mEglSlots array in addition to the ConsumerBase.
diff --git a/include/input/IInputFlinger.h b/include/input/IInputFlinger.h
new file mode 100644
index 0000000..79ff12a
--- /dev/null
+++ b/include/input/IInputFlinger.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _LIBINPUT_IINPUT_FLINGER_H
+#define _LIBINPUT_IINPUT_FLINGER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <binder/IInterface.h>
+
+namespace android {
+
+/*
+ * This class defines the Binder IPC interface for accessing various
+ * InputFlinger features.
+ */
+class IInputFlinger : public IInterface {
+public:
+    DECLARE_META_INTERFACE(InputFlinger);
+
+    virtual status_t doSomething() = 0;
+};
+
+
+/**
+ * Binder implementation.
+ */
+class BnInputFlinger : public BnInterface<IInputFlinger> {
+public:
+    enum {
+        DO_SOMETHING_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
+    };
+
+    virtual status_t onTransact(uint32_t code, const Parcel& data,
+            Parcel* reply, uint32_t flags = 0);
+};
+
+} // namespace android
+
+#endif // _LIBINPUT_IINPUT_FLINGER_H
diff --git a/include/input/Input.h b/include/input/Input.h
index 6d49b18..e778076 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -28,10 +28,6 @@
 #include <utils/RefBase.h>
 #include <utils/String8.h>
 
-#ifdef HAVE_ANDROID_OS
-class SkMatrix;
-#endif
-
 /*
  * Additional private constants not defined in ndk/ui/input.h.
  */
@@ -529,9 +525,11 @@
 
     void scale(float scaleFactor);
 
-#ifdef HAVE_ANDROID_OS
-    void transform(const SkMatrix* matrix);
+    // Apply 3x3 perspective matrix transformation.
+    // Matrix is in row-major form and compatible with SkMatrix.
+    void transform(const float matrix[9]);
 
+#ifdef HAVE_ANDROID_OS
     status_t readFromParcel(Parcel* parcel);
     status_t writeToParcel(Parcel* parcel) const;
 #endif
diff --git a/include/input/KeycodeLabels.h b/include/input/KeycodeLabels.h
index c76ba12..c64c5d8 100644
--- a/include/input/KeycodeLabels.h
+++ b/include/input/KeycodeLabels.h
@@ -246,6 +246,7 @@
     { "ASSIST", 219 },
     { "BRIGHTNESS_DOWN", 220 },
     { "BRIGHTNESS_UP", 221 },
+    { "MEDIA_AUDIO_TRACK", 222 },
 
     // NOTE: If you add a new keycode here you must also add it to several other files.
     //       Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 5a38b95..5951a3f 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -362,12 +362,12 @@
     return err;
 }
 
-int IPCThreadState::getCallingPid()
+int IPCThreadState::getCallingPid() const
 {
     return mCallingPid;
 }
 
-int IPCThreadState::getCallingUid()
+int IPCThreadState::getCallingUid() const
 {
     return mCallingUid;
 }
diff --git a/libs/binder/MemoryBase.cpp b/libs/binder/MemoryBase.cpp
index 5c82330..033066b 100644
--- a/libs/binder/MemoryBase.cpp
+++ b/libs/binder/MemoryBase.cpp
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "MemoryBase"
 
 #include <stdlib.h>
 #include <stdint.h>
@@ -45,11 +44,3 @@
 
 // ---------------------------------------------------------------------------
 }; // namespace android
-
-// Backwards compatibility for libdatabase_sqlcipher (http://b/8253769).
-extern "C" void _ZN7android10MemoryBaseC1ERKNS_2spINS_11IMemoryHeapEEEij(void*, void*, ssize_t, size_t);
-extern "C" void _ZN7android10MemoryBaseC1ERKNS_2spINS_11IMemoryHeapEEElj(void* obj, void* h, long o, unsigned int size) {
-    _ZN7android10MemoryBaseC1ERKNS_2spINS_11IMemoryHeapEEEij(obj, h, o, size);
-    ALOGW("Using temporary compatibility workaround for usage of MemoryBase "
-          "private API. Please fix your application!");
-}
diff --git a/libs/gui/BufferItemConsumer.cpp b/libs/gui/BufferItemConsumer.cpp
index ba04bdf..f5b2c7e 100644
--- a/libs/gui/BufferItemConsumer.cpp
+++ b/libs/gui/BufferItemConsumer.cpp
@@ -29,9 +29,9 @@
 
 namespace android {
 
-BufferItemConsumer::BufferItemConsumer(uint32_t consumerUsage,
-        int bufferCount, bool synchronousMode) :
-    ConsumerBase(new BufferQueue(true) )
+BufferItemConsumer::BufferItemConsumer(const sp<BufferQueue>& bq,
+        uint32_t consumerUsage, int bufferCount, bool synchronousMode) :
+    ConsumerBase(bq)
 {
     mBufferQueue->setConsumerUsageBits(consumerUsage);
     mBufferQueue->setSynchronousMode(synchronousMode);
@@ -47,14 +47,15 @@
     mBufferQueue->setConsumerName(name);
 }
 
-status_t BufferItemConsumer::acquireBuffer(BufferItem *item, bool waitForFence) {
+status_t BufferItemConsumer::acquireBuffer(BufferItem *item,
+        nsecs_t presentWhen, bool waitForFence) {
     status_t err;
 
     if (!item) return BAD_VALUE;
 
     Mutex::Autolock _l(mMutex);
 
-    err = acquireBufferLocked(item);
+    err = acquireBufferLocked(item, presentWhen);
     if (err != OK) {
         if (err != NO_BUFFER_AVAILABLE) {
             BI_LOGE("Error acquiring buffer: %s (%d)", strerror(err), err);
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index 0dab864..8d4b174 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -807,7 +807,7 @@
     }
 }
 
-status_t BufferQueue::acquireBuffer(BufferItem *buffer) {
+status_t BufferQueue::acquireBuffer(BufferItem *buffer, nsecs_t presentWhen) {
     ATRACE_CALL();
     Mutex::Autolock _l(mMutex);
 
@@ -830,38 +830,68 @@
     // check if queue is empty
     // In asynchronous mode the list is guaranteed to be one buffer
     // deep, while in synchronous mode we use the oldest buffer.
-    if (!mQueue.empty()) {
-        Fifo::iterator front(mQueue.begin());
-        int buf = front->mBuf;
-        *buffer = *front;
-        ATRACE_BUFFER_INDEX(buf);
-
-        ST_LOGV("acquireBuffer: acquiring { slot=%d/%llu, buffer=%p }",
-                front->mBuf, front->mFrameNumber,
-                front->mGraphicBuffer->handle);
-        // if front buffer still being tracked update slot state
-        if (stillTracking(front)) {
-            mSlots[buf].mAcquireCalled = true;
-            mSlots[buf].mNeedsCleanupOnRelease = false;
-            mSlots[buf].mBufferState = BufferSlot::ACQUIRED;
-            mSlots[buf].mFence = Fence::NO_FENCE;
-        }
-
-        // If the buffer has previously been acquired by the consumer, set
-        // mGraphicBuffer to NULL to avoid unnecessarily remapping this
-        // buffer on the consumer side.
-        if (buffer->mAcquireCalled) {
-            buffer->mGraphicBuffer = NULL;
-        }
-
-        mQueue.erase(front);
-        mDequeueCondition.broadcast();
-
-        ATRACE_INT(mConsumerName.string(), mQueue.size());
-    } else {
+    if (mQueue.empty()) {
         return NO_BUFFER_AVAILABLE;
     }
 
+    Fifo::iterator front(mQueue.begin());
+    int buf = front->mBuf;
+
+    // Compare the buffer's desired presentation time to the predicted
+    // actual display time.
+    //
+    // The "presentWhen" argument indicates when the buffer is expected
+    // to be presented on-screen.  If the buffer's desired-present time
+    // is earlier (less) than presentWhen, meaning it'll be displayed
+    // on time or possibly late, we acquire and return it.  If we don't want
+    // to display it until after the presentWhen time, we return PRESENT_LATER
+    // without acquiring it.
+    //
+    // To be safe, we don't refuse to acquire the buffer if presentWhen is
+    // more than one second in the future beyond the desired present time
+    // (i.e. we'd be holding the buffer for a really long time).
+    const int MAX_FUTURE_NSEC = 1000000000ULL;
+    nsecs_t desiredPresent = front->mTimestamp;
+    if (presentWhen != 0 && desiredPresent > presentWhen &&
+            desiredPresent - presentWhen < MAX_FUTURE_NSEC)
+    {
+        ALOGV("pts defer: des=%lld when=%lld (%lld) now=%lld",
+                desiredPresent, presentWhen, desiredPresent - presentWhen,
+                systemTime(CLOCK_MONOTONIC));
+        return PRESENT_LATER;
+    }
+    if (presentWhen != 0) {
+        ALOGV("pts accept: %p[%d] sig=%lld des=%lld when=%lld (%lld)",
+                mSlots, buf, mSlots[buf].mFence->getSignalTime(),
+                desiredPresent, presentWhen, desiredPresent - presentWhen);
+    }
+
+    *buffer = *front;
+    ATRACE_BUFFER_INDEX(buf);
+
+    ST_LOGV("acquireBuffer: acquiring { slot=%d/%llu, buffer=%p }",
+            front->mBuf, front->mFrameNumber,
+            front->mGraphicBuffer->handle);
+    // if front buffer still being tracked update slot state
+    if (stillTracking(front)) {
+        mSlots[buf].mAcquireCalled = true;
+        mSlots[buf].mNeedsCleanupOnRelease = false;
+        mSlots[buf].mBufferState = BufferSlot::ACQUIRED;
+        mSlots[buf].mFence = Fence::NO_FENCE;
+    }
+
+    // If the buffer has previously been acquired by the consumer, set
+    // mGraphicBuffer to NULL to avoid unnecessarily remapping this
+    // buffer on the consumer side.
+    if (buffer->mAcquireCalled) {
+        buffer->mGraphicBuffer = NULL;
+    }
+
+    mQueue.erase(front);
+    mDequeueCondition.broadcast();
+
+    ATRACE_INT(mConsumerName.string(), mQueue.size());
+
     return NO_ERROR;
 }
 
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index fd9d153..deb2646 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -182,8 +182,9 @@
     }
 }
 
-status_t ConsumerBase::acquireBufferLocked(BufferQueue::BufferItem *item) {
-    status_t err = mBufferQueue->acquireBuffer(item);
+status_t ConsumerBase::acquireBufferLocked(BufferQueue::BufferItem *item,
+        nsecs_t presentWhen) {
+    status_t err = mBufferQueue->acquireBuffer(item, presentWhen);
     if (err != NO_ERROR) {
         return err;
     }
diff --git a/libs/gui/CpuConsumer.cpp b/libs/gui/CpuConsumer.cpp
index 123b470..adddfc2 100644
--- a/libs/gui/CpuConsumer.cpp
+++ b/libs/gui/CpuConsumer.cpp
@@ -30,8 +30,9 @@
 
 namespace android {
 
-CpuConsumer::CpuConsumer(uint32_t maxLockedBuffers, bool synchronousMode) :
-    ConsumerBase(new BufferQueue(true) ),
+CpuConsumer::CpuConsumer(const sp<BufferQueue>& bq,
+        uint32_t maxLockedBuffers, bool synchronousMode) :
+    ConsumerBase(bq),
     mMaxLockedBuffers(maxLockedBuffers),
     mCurrentLockedBuffers(0)
 {
@@ -79,7 +80,7 @@
 
     Mutex::Autolock _l(mMutex);
 
-    err = acquireBufferLocked(&b);
+    err = acquireBufferLocked(&b, 0);
     if (err != OK) {
         if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
             return BAD_VALUE;
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 6d29edc..07f27c3 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -78,9 +78,9 @@
 static void mtxMul(float out[16], const float a[16], const float b[16]);
 
 
-GLConsumer::GLConsumer(GLuint tex, bool allowSynchronousMode,
-        GLenum texTarget, bool useFenceSync, const sp<BufferQueue> &bufferQueue) :
-    ConsumerBase(bufferQueue == 0 ? new BufferQueue(allowSynchronousMode) : bufferQueue),
+GLConsumer::GLConsumer(const sp<BufferQueue>& bq, GLuint tex,
+        GLenum texTarget, bool useFenceSync) :
+    ConsumerBase(bq),
     mCurrentTransform(0),
     mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
     mCurrentFence(Fence::NO_FENCE),
@@ -139,7 +139,7 @@
     // Acquire the next buffer.
     // In asynchronous mode the list is guaranteed to be one buffer
     // deep, while in synchronous mode we use the oldest buffer.
-    err = acquireBufferLocked(&item);
+    err = acquireBufferLocked(&item, 0);
     if (err != NO_ERROR) {
         if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
             // We always bind the texture even if we don't update its contents.
@@ -165,8 +165,9 @@
     return bindTextureImageLocked();
 }
 
-status_t GLConsumer::acquireBufferLocked(BufferQueue::BufferItem *item) {
-    status_t err = ConsumerBase::acquireBufferLocked(item);
+status_t GLConsumer::acquireBufferLocked(BufferQueue::BufferItem *item,
+        nsecs_t presentWhen) {
+    status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen);
     if (err != NO_ERROR) {
         return err;
     }
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index f345df8..94f21b6 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -633,7 +633,8 @@
 
 sp<CpuConsumer> ScreenshotClient::getCpuConsumer() const {
     if (mCpuConsumer == NULL) {
-        mCpuConsumer = new CpuConsumer(1);
+        sp<BufferQueue> bq = new BufferQueue();
+        mCpuConsumer = new CpuConsumer(bq, 1);
         mCpuConsumer->setName(String8("ScreenshotClient"));
     }
     return mCpuConsumer;
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 62d215b..9682987 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -80,7 +80,7 @@
                     GRALLOC_USAGE_SW_READ_OFTEN));
         ASSERT_EQ(OK, mBQ->requestBuffer(slot, &buf));
         ASSERT_EQ(OK, mBQ->queueBuffer(slot, qbi, &qbo));
-        ASSERT_EQ(OK, mBQ->acquireBuffer(&item));
+        ASSERT_EQ(OK, mBQ->acquireBuffer(&item, 0));
     }
 
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
@@ -90,7 +90,7 @@
     ASSERT_EQ(OK, mBQ->queueBuffer(slot, qbi, &qbo));
 
     // Acquire the third buffer, which should fail.
-    ASSERT_EQ(INVALID_OPERATION, mBQ->acquireBuffer(&item));
+    ASSERT_EQ(INVALID_OPERATION, mBQ->acquireBuffer(&item, 0));
 }
 
 TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithIllegalValues_ReturnsError) {
diff --git a/libs/gui/tests/CpuConsumer_test.cpp b/libs/gui/tests/CpuConsumer_test.cpp
index 73fdd04..f8a35b4 100644
--- a/libs/gui/tests/CpuConsumer_test.cpp
+++ b/libs/gui/tests/CpuConsumer_test.cpp
@@ -66,7 +66,8 @@
                 test_info->name(),
                 params.width, params.height,
                 params.maxLockedBuffers, params.format);
-        mCC = new CpuConsumer(params.maxLockedBuffers);
+        sp<BufferQueue> bq = new BufferQueue();
+        mCC = new CpuConsumer(bq, params.maxLockedBuffers);
         String8 name("CpuConsumer_Under_Test");
         mCC->setName(name);
         mSTC = new Surface(mCC->getProducerInterface());
diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp
index 7376b4c..46bcb22 100644
--- a/libs/gui/tests/SurfaceTextureClient_test.cpp
+++ b/libs/gui/tests/SurfaceTextureClient_test.cpp
@@ -40,7 +40,8 @@
         ALOGV("Begin test: %s.%s", testInfo->test_case_name(),
                 testInfo->name());
 
-        mST = new GLConsumer(123);
+        sp<BufferQueue> bq = new BufferQueue();
+        mST = new GLConsumer(bq, 123);
         mSTC = new Surface(mST->getBufferQueue());
         mANW = mSTC;
 
@@ -715,7 +716,8 @@
         ASSERT_NE(EGL_NO_CONTEXT, mEglContext);
 
         for (int i = 0; i < NUM_SURFACE_TEXTURES; i++) {
-            sp<GLConsumer> st(new GLConsumer(i));
+            sp<BufferQueue> bq = new BufferQueue();
+            sp<GLConsumer> st(new GLConsumer(bq, i));
             sp<Surface> stc(new Surface(st->getBufferQueue()));
             mEglSurfaces[i] = eglCreateWindowSurface(mEglDisplay, myConfig,
                     static_cast<ANativeWindow*>(stc.get()), NULL);
diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp
index dd6c435..d97521a 100644
--- a/libs/gui/tests/SurfaceTexture_test.cpp
+++ b/libs/gui/tests/SurfaceTexture_test.cpp
@@ -385,7 +385,8 @@
 
     virtual void SetUp() {
         GLTest::SetUp();
-        mGlConsumer = new GLConsumer(TEX_ID);
+        sp<BufferQueue> bq = new BufferQueue();
+        mGlConsumer = new GLConsumer(bq, TEX_ID);
         mSurface = new Surface(mGlConsumer->getBufferQueue());
         mANW = mSurface.get();
 
@@ -479,7 +480,8 @@
 
     virtual void SetUp() {
         GLTest::SetUp();
-        mST = new GLConsumer(TEX_ID);
+        sp<BufferQueue> bq = new BufferQueue();
+        mST = new GLConsumer(bq, TEX_ID);
         mSTC = new Surface(mST->getBufferQueue());
         mANW = mSTC;
         mTextureRenderer = new TextureRenderer(TEX_ID, mST);
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 429becf..953f6f9 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -87,7 +87,8 @@
     sp<ANativeWindow> anw(mSurface);
 
     // Verify the screenshot works with no protected buffers.
-    sp<CpuConsumer> consumer = new CpuConsumer(1);
+    sp<BufferQueue> bq = new BufferQueue();
+    sp<CpuConsumer> consumer = new CpuConsumer(bq, 1);
     sp<ISurfaceComposer> sf(ComposerService::getComposerService());
     sp<IBinder> display(sf->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
     ASSERT_EQ(NO_ERROR, sf->captureScreen(display, consumer->getBufferQueue(),
diff --git a/libs/input/Android.mk b/libs/input/Android.mk
index 2a1e762..944ac7f 100644
--- a/libs/input/Android.mk
+++ b/libs/input/Android.mk
@@ -12,8 +12,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-ifneq ($(TARGET_BUILD_PDK),true)
-
 LOCAL_PATH:= $(call my-dir)
 
 # libinput is partially built for the host (used by build time keymap validation tool)
@@ -29,6 +27,7 @@
 
 deviceSources := \
     $(commonSources) \
+    IInputFlinger.cpp \
     InputTransport.cpp \
     VelocityControl.cpp \
     VelocityTracker.cpp
@@ -61,14 +60,7 @@
 	liblog \
 	libcutils \
 	libutils \
-	libbinder \
-	libskia \
-	libz
-
-LOCAL_C_INCLUDES := \
-    external/skia/include/core \
-    external/icu4c/common \
-	external/zlib
+	libbinder
 
 LOCAL_MODULE:= libinput
 
@@ -85,5 +77,3 @@
 ifeq (,$(ONE_SHOT_MAKEFILE))
 include $(call first-makefiles-under,$(LOCAL_PATH))
 endif
-
-endif #!PDK
diff --git a/libs/input/IInputFlinger.cpp b/libs/input/IInputFlinger.cpp
new file mode 100644
index 0000000..e009731
--- /dev/null
+++ b/libs/input/IInputFlinger.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+
+#include <input/IInputFlinger.h>
+
+
+namespace android {
+
+class BpInputFlinger : public BpInterface<IInputFlinger> {
+public:
+    BpInputFlinger(const sp<IBinder>& impl) :
+            BpInterface<IInputFlinger>(impl) { }
+
+    virtual status_t doSomething() {
+        Parcel data, reply;
+        data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor());
+        remote()->transact(BnInputFlinger::DO_SOMETHING_TRANSACTION, data, &reply);
+        return reply.readInt32();
+    }
+};
+
+IMPLEMENT_META_INTERFACE(InputFlinger, "android.input.IInputFlinger");
+
+
+status_t BnInputFlinger::onTransact(
+        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
+    switch(code) {
+    case DO_SOMETHING_TRANSACTION: {
+        CHECK_INTERFACE(IInputFlinger, data, reply);
+        reply->writeInt32(0);
+        break;
+    }
+    default:
+        return BBinder::onTransact(code, data, reply, flags);
+    }
+    return NO_ERROR;
+}
+
+};
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index 7a217c3..6f53996 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -24,10 +24,6 @@
 
 #ifdef HAVE_ANDROID_OS
 #include <binder/Parcel.h>
-
-#include "SkPoint.h"
-#include "SkMatrix.h"
-#include "SkScalar.h"
 #endif
 
 namespace android {
@@ -74,6 +70,7 @@
         case AKEYCODE_MUTE:
         case AKEYCODE_BRIGHTNESS_DOWN:
         case AKEYCODE_BRIGHTNESS_UP:
+        case AKEYCODE_MEDIA_AUDIO_TRACK:
             return true;
     }
     
@@ -112,6 +109,7 @@
         case AKEYCODE_SEARCH:
         case AKEYCODE_BRIGHTNESS_DOWN:
         case AKEYCODE_BRIGHTNESS_UP:
+        case AKEYCODE_MEDIA_AUDIO_TRACK:
             return true;
     }
     
@@ -421,17 +419,30 @@
     }
 }
 
-#ifdef HAVE_ANDROID_OS
-static inline float transformAngle(const SkMatrix* matrix, float angleRadians) {
+static void transformPoint(const float matrix[9], float x, float y, float *outX, float *outY) {
+    // Apply perspective transform like Skia.
+    float newX = matrix[0] * x + matrix[1] * y + matrix[2];
+    float newY = matrix[3] * x + matrix[4] * y + matrix[5];
+    float newZ = matrix[6] * x + matrix[7] * y + matrix[8];
+    if (newZ) {
+        newZ = 1.0f / newZ;
+    }
+    *outX = newX * newZ;
+    *outY = newY * newZ;
+}
+
+static float transformAngle(const float matrix[9], float angleRadians,
+        float originX, float originY) {
     // Construct and transform a vector oriented at the specified clockwise angle from vertical.
     // Coordinate system: down is increasing Y, right is increasing X.
-    SkPoint vector;
-    vector.fX = SkFloatToScalar(sinf(angleRadians));
-    vector.fY = SkFloatToScalar(-cosf(angleRadians));
-    matrix->mapVectors(& vector, 1);
+    float x = sinf(angleRadians);
+    float y = -cosf(angleRadians);
+    transformPoint(matrix, x, y, &x, &y);
+    x -= originX;
+    y -= originY;
 
     // Derive the transformed vector's clockwise angle from vertical.
-    float result = atan2f(SkScalarToFloat(vector.fX), SkScalarToFloat(-vector.fY));
+    float result = atan2f(x, -y);
     if (result < - M_PI_2) {
         result += M_PI;
     } else if (result > M_PI_2) {
@@ -440,25 +451,24 @@
     return result;
 }
 
-void MotionEvent::transform(const SkMatrix* matrix) {
-    float oldXOffset = mXOffset;
-    float oldYOffset = mYOffset;
-
+void MotionEvent::transform(const float matrix[9]) {
     // The tricky part of this implementation is to preserve the value of
     // rawX and rawY.  So we apply the transformation to the first point
-    // then derive an appropriate new X/Y offset that will preserve rawX and rawY.
-    SkPoint point;
+    // then derive an appropriate new X/Y offset that will preserve rawX
+     // and rawY for that point.
+    float oldXOffset = mXOffset;
+    float oldYOffset = mYOffset;
+    float newX, newY;
     float rawX = getRawX(0);
     float rawY = getRawY(0);
-    matrix->mapXY(SkFloatToScalar(rawX + oldXOffset), SkFloatToScalar(rawY + oldYOffset),
-            & point);
-    float newX = SkScalarToFloat(point.fX);
-    float newY = SkScalarToFloat(point.fY);
-    float newXOffset = newX - rawX;
-    float newYOffset = newY - rawY;
+    transformPoint(matrix, rawX + oldXOffset, rawY + oldYOffset, &newX, &newY);
+    mXOffset = newX - rawX;
+    mYOffset = newY - rawY;
 
-    mXOffset = newXOffset;
-    mYOffset = newYOffset;
+    // Determine how the origin is transformed by the matrix so that we
+    // can transform orientation vectors.
+    float originX, originY;
+    transformPoint(matrix, 0, 0, &originX, &originY);
 
     // Apply the transformation to all samples.
     size_t numSamples = mSamplePointerCoords.size();
@@ -466,15 +476,17 @@
         PointerCoords& c = mSamplePointerCoords.editItemAt(i);
         float x = c.getAxisValue(AMOTION_EVENT_AXIS_X) + oldXOffset;
         float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y) + oldYOffset;
-        matrix->mapXY(SkFloatToScalar(x), SkFloatToScalar(y), &point);
-        c.setAxisValue(AMOTION_EVENT_AXIS_X, SkScalarToFloat(point.fX) - newXOffset);
-        c.setAxisValue(AMOTION_EVENT_AXIS_Y, SkScalarToFloat(point.fY) - newYOffset);
+        transformPoint(matrix, x, y, &x, &y);
+        c.setAxisValue(AMOTION_EVENT_AXIS_X, x - mXOffset);
+        c.setAxisValue(AMOTION_EVENT_AXIS_Y, y - mYOffset);
 
         float orientation = c.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION);
-        c.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, transformAngle(matrix, orientation));
+        c.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION,
+                transformAngle(matrix, orientation, originX, originY));
     }
 }
 
+#ifdef HAVE_ANDROID_OS
 status_t MotionEvent::readFromParcel(Parcel* parcel) {
     size_t pointerCount = parcel->readInt32();
     size_t sampleCount = parcel->readInt32();
diff --git a/libs/input/tests/Android.mk b/libs/input/tests/Android.mk
index 4292741..c62dff1 100644
--- a/libs/input/tests/Android.mk
+++ b/libs/input/tests/Android.mk
@@ -14,8 +14,7 @@
     libutils \
     libbinder \
     libui \
-    libstlport \
-    libskia
+    libstlport
 
 static_libraries := \
     libgtest \
diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp
index ab1feb3..78ea98e 100644
--- a/libs/input/tests/InputEvent_test.cpp
+++ b/libs/input/tests/InputEvent_test.cpp
@@ -17,7 +17,6 @@
 #include <math.h>
 
 #include <binder/Parcel.h>
-#include <core/SkMatrix.h>
 #include <gtest/gtest.h>
 #include <input/Input.h>
 
@@ -519,6 +518,20 @@
     ASSERT_NO_FATAL_FAILURE(assertEqualsEventWithHistory(&outEvent));
 }
 
+static void setRotationMatrix(float matrix[9], float angle) {
+    float sin = sinf(angle);
+    float cos = cosf(angle);
+    matrix[0] = cos;
+    matrix[1] = -sin;
+    matrix[2] = 0;
+    matrix[3] = sin;
+    matrix[4] = cos;
+    matrix[5] = 0;
+    matrix[6] = 0;
+    matrix[7] = 0;
+    matrix[8] = 1.0f;
+}
+
 TEST_F(MotionEventTest, Transform) {
     // Generate some points on a circle.
     // Each point 'i' is a point on a circle of radius ROTATION centered at (3,2) at an angle
@@ -561,9 +574,9 @@
     ASSERT_NEAR(originalRawY, event.getRawY(0), 0.001);
 
     // Apply a rotation about the origin by ROTATION degrees clockwise.
-    SkMatrix matrix;
-    matrix.setRotate(ROTATION);
-    event.transform(&matrix);
+    float matrix[9];
+    setRotationMatrix(matrix, ROTATION * PI_180);
+    event.transform(matrix);
 
     // Check the points.
     for (size_t i = 0; i < pointerCount; i++) {
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index c02a85f..beaa560 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -1,16 +1,16 @@
-/* 
+/*
  ** Copyright 2007, The Android Open Source Project
  **
- ** Licensed under the Apache License, Version 2.0 (the "License"); 
- ** you may not use this file except in compliance with the License. 
- ** You may obtain a copy of the License at 
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
  **
- **     http://www.apache.org/licenses/LICENSE-2.0 
+ **     http://www.apache.org/licenses/LICENSE-2.0
  **
- ** Unless required by applicable law or agreed to in writing, software 
- ** distributed under the License is distributed on an "AS IS" BASIS, 
- ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
- ** See the License for the specific language governing permissions and 
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
  ** limitations under the License.
  */
 
@@ -56,9 +56,9 @@
  *
  * For backward compatibility and to facilitate the transition to
  * this new naming scheme, the loader will additionally look for:
- * 
+ *
  *      /{vendor|system}/lib/egl/lib{GLES | [EGL|GLESv1_CM|GLESv2]}_*.so
- * 
+ *
  */
 
 ANDROID_SINGLETON_STATIC_INSTANCE( Loader )
@@ -116,14 +116,14 @@
 
 // ----------------------------------------------------------------------------
 
-Loader::driver_t::driver_t(void* gles) 
+Loader::driver_t::driver_t(void* gles)
 {
     dso[0] = gles;
     for (size_t i=1 ; i<NELEM(dso) ; i++)
         dso[i] = 0;
 }
 
-Loader::driver_t::~driver_t() 
+Loader::driver_t::~driver_t()
 {
     for (size_t i=0 ; i<NELEM(dso) ; i++) {
         if (dso[i]) {
@@ -161,11 +161,17 @@
     GLTrace_stop();
 }
 
+static void* load_wrapper(const char* path) {
+    void* so = dlopen(path, RTLD_NOW | RTLD_LOCAL);
+    ALOGE_IF(!so, "dlopen(\"%s\") failed: %s", path, dlerror());
+    return so;
+}
+
 void* Loader::open(egl_connection_t* cnx)
 {
     void* dso;
     driver_t* hnd = 0;
-    
+
     dso = load_driver("GLES", cnx, EGL | GLESv1_CM | GLESv2);
     if (dso) {
         hnd = new driver_t(dso);
@@ -180,7 +186,12 @@
     }
 
     LOG_ALWAYS_FATAL_IF(!hnd, "couldn't find an OpenGL ES implementation");
-    
+
+    cnx->libGles2 = load_wrapper("/system/lib/libGLESv2.so");
+    cnx->libGles1 = load_wrapper("/system/lib/libGLESv1_CM.so");
+    LOG_ALWAYS_FATAL_IF(!cnx->libGles2 || !cnx->libGles1,
+            "couldn't load system OpenGL ES wrapper libraries");
+
     return (void*)hnd;
 }
 
@@ -191,16 +202,16 @@
     return NO_ERROR;
 }
 
-void Loader::init_api(void* dso, 
-        char const * const * api, 
-        __eglMustCastToProperFunctionPointerType* curr, 
-        getProcAddressType getProcAddress) 
+void Loader::init_api(void* dso,
+        char const * const * api,
+        __eglMustCastToProperFunctionPointerType* curr,
+        getProcAddressType getProcAddress)
 {
     const ssize_t SIZE = 256;
     char scrap[SIZE];
     while (*api) {
         char const * name = *api;
-        __eglMustCastToProperFunctionPointerType f = 
+        __eglMustCastToProperFunctionPointerType f =
             (__eglMustCastToProperFunctionPointerType)dlsym(dso, name);
         if (f == NULL) {
             // couldn't find the entry-point, use eglGetProcAddress()
@@ -360,7 +371,7 @@
     if (mask & EGL) {
         getProcAddress = (getProcAddressType)dlsym(dso, "eglGetProcAddress");
 
-        ALOGE_IF(!getProcAddress, 
+        ALOGE_IF(!getProcAddress,
                 "can't find eglGetProcAddress() in %s", driver_absolute_path);
 
 #ifdef SYSTEMUI_PBSIZE_HACK
@@ -398,7 +409,7 @@
         char const * const * api = egl_names;
         while (*api) {
             char const * name = *api;
-            __eglMustCastToProperFunctionPointerType f = 
+            __eglMustCastToProperFunctionPointerType f =
                 (__eglMustCastToProperFunctionPointerType)dlsym(dso, name);
             if (f == NULL) {
                 // couldn't find the entry-point, use eglGetProcAddress()
@@ -411,7 +422,7 @@
             api++;
         }
     }
-    
+
     if (mask & GLESv1_CM) {
         init_api(dso, gl_names,
             (__eglMustCastToProperFunctionPointerType*)
@@ -425,7 +436,7 @@
                 &cnx->hooks[egl_connection_t::GLESv2_INDEX]->gl,
             getProcAddress);
     }
-    
+
     return dso;
 }
 
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 0358fcc..015740a 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -16,6 +16,7 @@
 
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
+#include <dlfcn.h>
 #include <ctype.h>
 #include <stdlib.h>
 #include <string.h>
@@ -777,6 +778,20 @@
     return err;
 }
 
+static __eglMustCastToProperFunctionPointerType findBuiltinGLWrapper(
+        const char* procname) {
+    const egl_connection_t* cnx = &gEGLImpl;
+    void* proc = NULL;
+
+    proc = dlsym(cnx->libGles2, procname);
+    if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
+
+    proc = dlsym(cnx->libGles1, procname);
+    if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
+
+    return NULL;
+}
+
 __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
 {
     // eglGetProcAddress() could be the very first function called
@@ -798,6 +813,8 @@
     addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap));
     if (addr) return addr;
 
+    addr = findBuiltinGLWrapper(procname);
+    if (addr) return addr;
 
     // this protects accesses to sGLExtentionMap and sGLExtentionSlot
     pthread_mutex_lock(&sExtensionMapMutex);
diff --git a/opengl/libs/EGL/egldefs.h b/opengl/libs/EGL/egldefs.h
index 1cfe561..b905ea0 100644
--- a/opengl/libs/EGL/egldefs.h
+++ b/opengl/libs/EGL/egldefs.h
@@ -43,6 +43,9 @@
     EGLint              major;
     EGLint              minor;
     egl_t               egl;
+
+    void*               libGles1;
+    void*               libGles2;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/services/inputflinger/Android.mk b/services/inputflinger/Android.mk
new file mode 100644
index 0000000..7148db8
--- /dev/null
+++ b/services/inputflinger/Android.mk
@@ -0,0 +1,35 @@
+# Copyright (C) 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+    InputFlinger.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+    libbinder \
+    libcutils \
+    libinput \
+    liblog \
+    libutils
+
+LOCAL_CFLAGS += -fvisibility=hidden
+
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
+
+LOCAL_MODULE := libinputflinger
+
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/services/inputflinger/InputFlinger.cpp b/services/inputflinger/InputFlinger.cpp
new file mode 100644
index 0000000..9ea6ce5
--- /dev/null
+++ b/services/inputflinger/InputFlinger.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "InputFlinger"
+
+#include "InputFlinger.h"
+
+#include <stdint.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+
+#include <binder/IPCThreadState.h>
+#include <binder/PermissionCache.h>
+#include <cutils/log.h>
+#include <private/android_filesystem_config.h>
+
+namespace android {
+
+const String16 sAccessInputFlingerPermission("android.permission.ACCESS_INPUT_FLINGER");
+const String16 sDumpPermission("android.permission.DUMP");
+
+
+InputFlinger::InputFlinger() :
+        BnInputFlinger() {
+    ALOGI("InputFlinger is starting");
+}
+
+InputFlinger::~InputFlinger() {
+}
+
+status_t InputFlinger::onTransact(
+        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
+    switch (code) {
+    case DO_SOMETHING_TRANSACTION:
+        const IPCThreadState* ipc = IPCThreadState::self();
+        const int pid = ipc->getCallingPid();
+        const int uid = ipc->getCallingUid();
+        if (!PermissionCache::checkPermission(sAccessInputFlingerPermission, pid, uid)) {
+            ALOGE("Permission Denial: "
+                    "can't access InputFlinger from pid=%d, uid=%d", pid, uid);
+            return PERMISSION_DENIED;
+        }
+        break;
+    }
+
+    return BnInputFlinger::onTransact(code, data, reply, flags);
+}
+
+status_t InputFlinger::dump(int fd, const Vector<String16>& args) {
+    String8 result;
+    const IPCThreadState* ipc = IPCThreadState::self();
+    const int pid = ipc->getCallingPid();
+    const int uid = ipc->getCallingUid();
+    if ((uid != AID_SHELL)
+            && !PermissionCache::checkPermission(sDumpPermission, pid, uid)) {
+        result.appendFormat("Permission Denial: "
+                "can't dump SurfaceFlinger from pid=%d, uid=%d\n", pid, uid);
+    } else {
+        dumpInternal(result);
+    }
+    write(fd, result.string(), result.size());
+    return OK;
+}
+
+void InputFlinger::dumpInternal(String8& result) {
+    result.append("INPUT FLINGER (dumpsys inputflinger)\n");
+    result.append("... nothing here yet...\n");
+}
+
+status_t InputFlinger::doSomething() {
+    ALOGI("Did something...");
+    return OK;
+}
+
+}; // namespace android
diff --git a/services/inputflinger/InputFlinger.h b/services/inputflinger/InputFlinger.h
new file mode 100644
index 0000000..731ab17
--- /dev/null
+++ b/services/inputflinger/InputFlinger.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INPUT_FLINGER_H
+#define ANDROID_INPUT_FLINGER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <cutils/compiler.h>
+#include <input/IInputFlinger.h>
+#include <utils/String8.h>
+#include <utils/String16.h>
+
+namespace android {
+
+class InputFlinger : public BnInputFlinger {
+public:
+    static char const* getServiceName() ANDROID_API {
+        return "inputflinger";
+    }
+
+    InputFlinger() ANDROID_API;
+
+    // IBinder interface
+    virtual status_t onTransact(uint32_t code,
+            const Parcel& data, Parcel* reply, uint32_t flags);
+    virtual status_t dump(int fd, const Vector<String16>& args);
+
+    // IInputFlinger interface
+    virtual status_t doSomething();
+
+private:
+    virtual ~InputFlinger();
+
+    void dumpInternal(String8& result);
+};
+
+} // namespace android
+
+#endif // ANDROID_INPUT_FLINGER_H
diff --git a/services/sensorservice/BatteryService.cpp b/services/sensorservice/BatteryService.cpp
index 70b65ab..38dc749 100644
--- a/services/sensorservice/BatteryService.cpp
+++ b/services/sensorservice/BatteryService.cpp
@@ -33,7 +33,7 @@
 BatteryService::BatteryService() {
     const sp<IServiceManager> sm(defaultServiceManager());
     if (sm != NULL) {
-        const String16 name("batteryinfo");
+        const String16 name("batterystats");
         mBatteryStatService = sm->getService(name);
     }
 }
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index 18a1523..2fa5dbd 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -107,13 +107,10 @@
     return c;
 }
 
-status_t SensorDevice::resetStateWithoutActuatingHardware(void *ident, int handle)
-{
-    if (!mSensorDevice) return NO_INIT;
-    Info& info( mActivationCount.editValueFor(handle));
+void SensorDevice::autoDisable(void *ident, int handle) {
+    Info& info( mActivationCount.editValueFor(handle) );
     Mutex::Autolock _l(mLock);
     info.rates.removeItem(ident);
-    return NO_ERROR;
 }
 
 status_t SensorDevice::activate(void* ident, int handle, int enabled)
@@ -164,6 +161,15 @@
         ALOGE_IF(err, "Error %s sensor %d (%s)",
                 enabled ? "activating" : "disabling",
                 handle, strerror(-err));
+
+        if (err != NO_ERROR) {
+            // clean-up on failure
+            if (enabled) {
+                // failure when enabling the sensor
+                Mutex::Autolock _l(mLock);
+                info.rates.removeItem(ident);
+            }
+        }
     }
 
     { // scope for the lock
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index ca67ce2..b50e205 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -56,7 +56,7 @@
     ssize_t poll(sensors_event_t* buffer, size_t count);
     status_t activate(void* ident, int handle, int enabled);
     status_t setDelay(void* ident, int handle, int64_t ns);
-    status_t resetStateWithoutActuatingHardware(void *ident, int handle);
+    void autoDisable(void *ident, int handle);
     void dump(String8& result);
 };
 
diff --git a/services/sensorservice/SensorInterface.cpp b/services/sensorservice/SensorInterface.cpp
index cf0a11d..b483b75 100644
--- a/services/sensorservice/SensorInterface.cpp
+++ b/services/sensorservice/SensorInterface.cpp
@@ -54,8 +54,8 @@
     return mSensorDevice.setDelay(ident, handle, ns);
 }
 
-status_t HardwareSensor::resetStateWithoutActuatingHardware(void *ident, int handle) {
-    return mSensorDevice.resetStateWithoutActuatingHardware(ident, handle);
+void HardwareSensor::autoDisable(void *ident, int handle) {
+    mSensorDevice.autoDisable(ident, handle);
 }
 
 Sensor HardwareSensor::getSensor() const {
diff --git a/services/sensorservice/SensorInterface.h b/services/sensorservice/SensorInterface.h
index 2e709ae..2e14e57 100644
--- a/services/sensorservice/SensorInterface.h
+++ b/services/sensorservice/SensorInterface.h
@@ -40,11 +40,7 @@
     virtual status_t setDelay(void* ident, int handle, int64_t ns) = 0;
     virtual Sensor getSensor() const = 0;
     virtual bool isVirtual() const = 0;
-    virtual status_t resetStateWithoutActuatingHardware(void *ident, int handle) {
-        // Override when you want to clean up for sensors which auto disable
-        // after trigger, or when enabling sensors fail.
-        return INVALID_OPERATION;
-    }
+    virtual void autoDisable(void *ident, int handle) { }
 };
 
 // ---------------------------------------------------------------------------
@@ -66,7 +62,7 @@
     virtual status_t setDelay(void* ident, int handle, int64_t ns);
     virtual Sensor getSensor() const;
     virtual bool isVirtual() const { return false; }
-    virtual status_t resetStateWithoutActuatingHardware(void *ident, int handle);
+    virtual void autoDisable(void *ident, int handle);
 };
 
 
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 99993ba..e3d2a60 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -274,10 +274,8 @@
         if (type == SENSOR_TYPE_SIGNIFICANT_MOTION) {
             if (connection->hasSensor(handle)) {
                 sensor = mSensorMap.valueFor(handle);
-                err = sensor ?sensor->resetStateWithoutActuatingHardware(connection.get(), handle)
-                        : status_t(BAD_VALUE);
-                if (err != NO_ERROR) {
-                    ALOGE("Sensor Inteface: Resetting state failed with err: %d", err);
+                if (sensor != NULL) {
+                    sensor->autoDisable(connection.get(), handle);
                 }
                 cleanupWithoutDisable(connection, handle);
             }
@@ -509,8 +507,12 @@
     if (mInitCheck != NO_ERROR)
         return mInitCheck;
 
-    Mutex::Autolock _l(mLock);
     SensorInterface* sensor = mSensorMap.valueFor(handle);
+    if (sensor == NULL) {
+        return BAD_VALUE;
+    }
+
+    Mutex::Autolock _l(mLock);
     SensorRecord* rec = mActiveSensors.valueFor(handle);
     if (rec == 0) {
         rec = new SensorRecord(connection);
@@ -546,16 +548,11 @@
             handle, connection.get());
     }
 
-
     // we are setup, now enable the sensor.
-    status_t err = sensor ? sensor->activate(connection.get(), true) : status_t(BAD_VALUE);
-
+    status_t err = sensor->activate(connection.get(), true);
     if (err != NO_ERROR) {
-        // enable has failed, reset state in SensorDevice.
-        status_t resetErr = sensor ? sensor->resetStateWithoutActuatingHardware(connection.get(),
-                handle) : status_t(BAD_VALUE);
         // enable has failed, reset our state.
-        cleanupWithoutDisable(connection, handle);
+        cleanupWithoutDisableLocked(connection, handle);
     }
     return err;
 }
@@ -566,7 +563,8 @@
     if (mInitCheck != NO_ERROR)
         return mInitCheck;
 
-    status_t err = cleanupWithoutDisable(connection, handle);
+    Mutex::Autolock _l(mLock);
+    status_t err = cleanupWithoutDisableLocked(connection, handle);
     if (err == NO_ERROR) {
         SensorInterface* sensor = mSensorMap.valueFor(handle);
         err = sensor ? sensor->activate(connection.get(), false) : status_t(BAD_VALUE);
@@ -574,9 +572,14 @@
     return err;
 }
 
-status_t SensorService::cleanupWithoutDisable(const sp<SensorEventConnection>& connection,
-        int handle) {
+status_t SensorService::cleanupWithoutDisable(
+        const sp<SensorEventConnection>& connection, int handle) {
     Mutex::Autolock _l(mLock);
+    return cleanupWithoutDisableLocked(connection, handle);
+}
+
+status_t SensorService::cleanupWithoutDisableLocked(
+        const sp<SensorEventConnection>& connection, int handle) {
     SensorRecord* rec = mActiveSensors.valueFor(handle);
     if (rec) {
         // see if this connection becomes inactive
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 56b0a3e..69e5dbb 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -115,8 +115,10 @@
     static void sortEventBuffer(sensors_event_t* buffer, size_t count);
     Sensor registerSensor(SensorInterface* sensor);
     Sensor registerVirtualSensor(SensorInterface* sensor);
-    status_t cleanupWithoutDisable(const sp<SensorEventConnection>& connection,
-            int handle);
+    status_t cleanupWithoutDisable(
+            const sp<SensorEventConnection>& connection, int handle);
+    status_t cleanupWithoutDisableLocked(
+            const sp<SensorEventConnection>& connection, int handle);
     void cleanupAutoDisabledSensor(const sp<SensorEventConnection>& connection,
             sensors_event_t const* buffer, const int count);
 
diff --git a/services/surfaceflinger/DisplayHardware/FloatRect.h b/services/surfaceflinger/DisplayHardware/FloatRect.h
new file mode 100644
index 0000000..b08a951
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/FloatRect.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SF_FLOAT_RECT
+#define ANDROID_SF_FLOAT_RECT
+
+#include <utils/TypeHelpers.h>
+
+namespace android {
+
+class FloatRect
+{
+public:
+    float left;
+    float top;
+    float right;
+    float bottom;
+
+    inline FloatRect() { }
+    inline FloatRect(const Rect& other)
+        : left(other.left), top(other.top), right(other.right), bottom(other.bottom) { }
+
+    inline float getWidth() const { return right - left; }
+    inline float getHeight() const { return bottom - top; }
+};
+
+}; // namespace android
+
+#endif // ANDROID_SF_FLOAT_RECT
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 3f51345..7987da3 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -87,7 +87,7 @@
     Mutex::Autolock lock(mMutex);
 
     BufferQueue::BufferItem item;
-    status_t err = acquireBufferLocked(&item);
+    status_t err = acquireBufferLocked(&item, 0);
     if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
         outBuffer = mCurrentBuffer;
         return NO_ERROR;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index ca98133..f6256f9 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -21,6 +21,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
+#include <math.h>
 
 #include <utils/CallStack.h>
 #include <utils/Errors.h>
@@ -877,10 +878,25 @@
         getLayer()->transform = transform;
     }
     virtual void setFrame(const Rect& frame) {
-        reinterpret_cast<Rect&>(getLayer()->displayFrame) = frame;
+        getLayer()->displayFrame = reinterpret_cast<hwc_rect_t const&>(frame);
     }
-    virtual void setCrop(const Rect& crop) {
-        reinterpret_cast<Rect&>(getLayer()->sourceCrop) = crop;
+    virtual void setCrop(const FloatRect& crop) {
+        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
+            getLayer()->sourceCropf = reinterpret_cast<hwc_frect_t const&>(crop);
+        } else {
+            /*
+             * Since h/w composer didn't support a flot crop rect before version 1.3,
+             * using integer coordinates instead produces a different output from the GL code in
+             * Layer::drawWithOpenGL(). The difference can be large if the buffer crop to
+             * window size ratio is large and a window crop is defined
+             * (i.e.: if we scale the buffer a lot and we also crop it with a window crop).
+             */
+            hwc_rect_t& r = getLayer()->sourceCrop;
+            r.left  = int(ceilf(crop.left));
+            r.top   = int(ceilf(crop.top));
+            r.right = int(floorf(crop.right));
+            r.bottom= int(floorf(crop.bottom));
+        }
     }
     virtual void setVisibleRegionScreen(const Region& reg) {
         // Region::getSharedBuffer creates a reference to the underlying
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index a20da08..0462bcc 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -47,6 +47,7 @@
 
 class GraphicBuffer;
 class Fence;
+class FloatRect;
 class Region;
 class String8;
 class SurfaceFlinger;
@@ -158,7 +159,7 @@
         virtual void setBlending(uint32_t blending) = 0;
         virtual void setTransform(uint32_t transform) = 0;
         virtual void setFrame(const Rect& frame) = 0;
-        virtual void setCrop(const Rect& crop) = 0;
+        virtual void setCrop(const FloatRect& crop) = 0;
         virtual void setVisibleRegionScreen(const Region& reg) = 0;
         virtual void setBuffer(const sp<GraphicBuffer>& buffer) = 0;
         virtual void setAcquireFenceFd(int fenceFd) = 0;
diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h
index f6bd676..35ac0c8 100644
--- a/services/surfaceflinger/EventThread.h
+++ b/services/surfaceflinger/EventThread.h
@@ -104,7 +104,7 @@
     // protected by mLock
     SortedVector< wp<Connection> > mDisplayEventConnections;
     Vector< DisplayEventReceiver::Event > mPendingEvents;
-    DisplayEventReceiver::Event mVSyncEvent[HWC_DISPLAY_TYPES_SUPPORTED];
+    DisplayEventReceiver::Event mVSyncEvent[HWC_NUM_DISPLAY_TYPES];
     bool mUseSoftwareVSync;
 
     // for debugging
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 3605dd4..2962115 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -110,8 +110,8 @@
 {
     // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
     sp<BufferQueue> bq = new SurfaceTextureLayer(mFlinger);
-    mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(mTextureName, true,
-            GL_TEXTURE_EXTERNAL_OES, false, bq);
+    mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(bq, mTextureName,
+            GL_TEXTURE_EXTERNAL_OES, false);
 
     mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
     mSurfaceFlingerConsumer->setFrameAvailableListener(this);
@@ -257,10 +257,6 @@
     return crop;
 }
 
-uint32_t Layer::getContentTransform() const {
-    return mCurrentTransform;
-}
-
 static Rect reduce(const Rect& win, const Region& exclude) {
     if (CC_LIKELY(exclude.isEmpty())) {
         return win;
@@ -281,18 +277,10 @@
     return reduce(win, s.activeTransparentRegion);
 }
 
-Rect Layer::computeCrop(const sp<const DisplayDevice>& hw) const {
-    /*
-     * The way we compute the crop (aka. texture coordinates when we have a
-     * Layer) produces a different output from the GL code in
-     * drawWithOpenGL() due to HWC being limited to integers. The difference
-     * can be large if getContentTransform() contains a large scale factor.
-     * See comments in drawWithOpenGL() for more details.
-     */
-
+FloatRect Layer::computeCrop(const sp<const DisplayDevice>& hw) const {
     // the content crop is the area of the content that gets scaled to the
     // layer's size.
-    Rect crop(getContentCrop());
+    FloatRect crop(getContentCrop());
 
     // the active.crop is the area of the window that gets cropped, but not
     // scaled in any ways.
@@ -300,10 +288,10 @@
 
     // apply the projection's clipping to the window crop in
     // layerstack space, and convert-back to layer space.
-    // if there are no window scaling (or content scaling) involved,
-    // this operation will map to full pixels in the buffer.
-    // NOTE: should we revert to GL composition if a scaling is involved
-    // since it cannot be represented in the HWC API?
+    // if there are no window scaling involved, this operation will map to full
+    // pixels in the buffer.
+    // FIXME: the 3 lines below can produce slightly incorrect clipping when we have
+    // a viewport clipping and a window transform. we should use floating point to fix this.
     Rect activeCrop(s.transform.transform(s.active.crop));
     activeCrop.intersect(hw->getViewport(), &activeCrop);
     activeCrop = s.transform.inverse().transform(activeCrop);
@@ -319,7 +307,7 @@
         // Transform the window crop to match the buffer coordinate system,
         // which means using the inverse of the current transform set on the
         // SurfaceFlingerConsumer.
-        uint32_t invTransform = getContentTransform();
+        uint32_t invTransform = mCurrentTransform;
         int winWidth = s.active.w;
         int winHeight = s.active.h;
         if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
@@ -331,15 +319,14 @@
         const Rect winCrop = activeCrop.transform(
                 invTransform, s.active.w, s.active.h);
 
-        // the code below essentially performs a scaled intersection
-        // of crop and winCrop
-        float xScale = float(crop.width()) / float(winWidth);
-        float yScale = float(crop.height()) / float(winHeight);
+        // below, crop is intersected with winCrop expressed in crop's coordinate space
+        float xScale = crop.getWidth()  / float(winWidth);
+        float yScale = crop.getHeight() / float(winHeight);
 
-        int insetL = int(ceilf( winCrop.left                * xScale));
-        int insetT = int(ceilf( winCrop.top                 * yScale));
-        int insetR = int(ceilf((winWidth  - winCrop.right ) * xScale));
-        int insetB = int(ceilf((winHeight - winCrop.bottom) * yScale));
+        float insetL = winCrop.left                 * xScale;
+        float insetT = winCrop.top                  * yScale;
+        float insetR = (winWidth  - winCrop.right ) * xScale;
+        float insetB = (winHeight - winCrop.bottom) * yScale;
 
         crop.left   += insetL;
         crop.top    += insetT;
@@ -930,11 +917,6 @@
         const bool oldOpacity = isOpaque();
         sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
 
-        // signal another event if we have more frames pending
-        if (android_atomic_dec(&mQueuedFrames) > 1) {
-            mFlinger->signalLayerUpdate();
-        }
-
         struct Reject : public SurfaceFlingerConsumer::BufferRejecter {
             Layer::State& front;
             Layer::State& current;
@@ -1040,7 +1022,21 @@
 
         Reject r(mDrawingState, getCurrentState(), recomputeVisibleRegions);
 
-        if (mSurfaceFlingerConsumer->updateTexImage(&r) != NO_ERROR) {
+        status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r);
+        if (updateResult == BufferQueue::PRESENT_LATER) {
+            // Producer doesn't want buffer to be displayed yet.  Signal a
+            // layer update so we check again at the next opportunity.
+            mFlinger->signalLayerUpdate();
+            return outDirtyRegion;
+        }
+
+        // Decrement the queued-frames count.  Signal another event if we
+        // have more frames pending.
+        if (android_atomic_dec(&mQueuedFrames) > 1) {
+            mFlinger->signalLayerUpdate();
+        }
+
+        if (updateResult != NO_ERROR) {
             // something happened!
             recomputeVisibleRegions = true;
             return outDirtyRegion;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index e7e9585..0ceb15e 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -43,6 +43,7 @@
 #include "Transform.h"
 
 #include "DisplayHardware/HWComposer.h"
+#include "DisplayHardware/FloatRect.h"
 
 namespace android {
 
@@ -279,12 +280,6 @@
      */
     Rect getContentCrop() const;
 
-    /*
-     * returns the transform bits (90 rotation / h-flip / v-flip) of the
-     * layer's content
-     */
-    uint32_t getContentTransform() const;
-
     // -----------------------------------------------------------------------
 
     void clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip) const;
@@ -334,7 +329,7 @@
     bool needsFiltering(const sp<const DisplayDevice>& hw) const;
 
     uint32_t getEffectiveUsage(uint32_t usage) const;
-    Rect computeCrop(const sp<const DisplayDevice>& hw) const;
+    FloatRect computeCrop(const sp<const DisplayDevice>& hw) const;
     bool isCropped() const;
     static bool getOpacityForFormat(uint32_t format);
 
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
index 7ac5c60..b181b60 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
@@ -50,12 +50,14 @@
     // Acquire the next buffer.
     // In asynchronous mode the list is guaranteed to be one buffer
     // deep, while in synchronous mode we use the oldest buffer.
-    err = acquireBufferLocked(&item);
+    err = acquireBufferLocked(&item, computeExpectedPresent());
     if (err != NO_ERROR) {
         if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
             // This variant of updateTexImage does not guarantee that the
             // texture is bound, so no need to call glBindTexture.
             err = NO_ERROR;
+        } else if (err == BufferQueue::PRESENT_LATER) {
+            // return the error, without logging
         } else {
             ALOGE("updateTexImage: acquire failed: %s (%d)",
                 strerror(-err), err);
@@ -99,6 +101,48 @@
     return bindTextureImageLocked();
 }
 
+// We need to determine the time when a buffer acquired now will be
+// displayed.  This can be calculated:
+//   time when previous buffer's actual-present fence was signaled
+//    + current display refresh rate * HWC latency
+//    + a little extra padding
+//
+// Buffer producers are expected to set their desired presentation time
+// based on choreographer time stamps, which (coming from vsync events)
+// will be slightly later then the actual-present timing.  If we get a
+// desired-present time that is unintentionally a hair after the next
+// vsync, we'll hold the frame when we really want to display it.  We
+// want to use an expected-presentation time that is slightly late to
+// avoid this sort of edge case.
+nsecs_t SurfaceFlingerConsumer::computeExpectedPresent()
+{
+    // Don't yet have an easy way to get actual buffer flip time for
+    // the specific display, so use the current time.  This is typically
+    // 1.3ms past the vsync event time.
+    const nsecs_t prevVsync = systemTime(CLOCK_MONOTONIC);
+
+    // Given a SurfaceFlinger reference, and information about what display
+    // we're destined for, we could query the HWC for the refresh rate.  This
+    // could change over time, e.g. we could switch to 24fps for a movie.
+    // For now, assume 60fps.
+    //const nsecs_t vsyncPeriod =
+    //        getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
+    const nsecs_t vsyncPeriod = 16700000;
+
+    // The HWC doesn't currently have a way to report additional latency.
+    // Assume that whatever we submit now will appear on the next flip,
+    // i.e. 1 frame of latency w.r.t. the previous flip.
+    const uint32_t hwcLatency = 1;
+
+    // A little extra padding to compensate for slack between actual vsync
+    // time and vsync event receipt.  Currently not needed since we're
+    // using "now" instead of a vsync time.
+    const nsecs_t extraPadding = 0;
+
+    // Total it up.
+    return prevVsync + hwcLatency * vsyncPeriod + extraPadding;
+}
+
 // ---------------------------------------------------------------------------
 }; // namespace android
 
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.h b/services/surfaceflinger/SurfaceFlingerConsumer.h
index 22eec81..5de6d12 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.h
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.h
@@ -27,11 +27,10 @@
  */
 class SurfaceFlingerConsumer : public GLConsumer {
 public:
-    SurfaceFlingerConsumer(GLuint tex, bool allowSynchronousMode = true,
-            GLenum texTarget = GL_TEXTURE_EXTERNAL_OES, bool useFenceSync = true,
-            const sp<BufferQueue> &bufferQueue = 0)
-        : GLConsumer(tex, allowSynchronousMode, texTarget, useFenceSync,
-            bufferQueue)
+    SurfaceFlingerConsumer(const sp<BufferQueue>& bq, GLuint tex,
+            GLenum texTarget = GL_TEXTURE_EXTERNAL_OES,
+            bool useFenceSync = true)
+        : GLConsumer(bq, tex, texTarget, useFenceSync)
     {}
 
     class BufferRejecter {
@@ -51,6 +50,9 @@
 
     // See GLConsumer::bindTextureImageLocked().
     status_t bindTextureImage();
+
+private:
+    nsecs_t computeExpectedPresent();
 };
 
 // ----------------------------------------------------------------------------