Merge "HEVC Support Added HEVC enums and structures to OMX header files"
diff --git a/cmds/dumpstate/utils.c b/cmds/dumpstate/utils.c
index 577d31c..6b119c3 100644
--- a/cmds/dumpstate/utils.c
+++ b/cmds/dumpstate/utils.c
@@ -587,7 +587,7 @@
 
             /* wait for the writable-close notification from inotify */
             struct pollfd pfd = { ifd, POLLIN, 0 };
-            int ret = poll(&pfd, 1, 200);  /* 200 msec timeout */
+            int ret = poll(&pfd, 1, 5000);  /* 5 sec timeout */
             if (ret < 0) {
                 fprintf(stderr, "poll: %s\n", strerror(errno));
             } else if (ret == 0) {
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index 669f403..cfb80e3 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -387,7 +387,7 @@
     return data_disk_free() >= free_size ? 0 : -1;
 }
 
-int move_dex(const char *src, const char *dst)
+int move_dex(const char *src, const char *dst, const char *instruction_set)
 {
     char src_dex[PKG_PATH_MAX];
     char dst_dex[PKG_PATH_MAX];
@@ -395,8 +395,8 @@
     if (validate_apk_path(src)) return -1;
     if (validate_apk_path(dst)) return -1;
 
-    if (create_cache_path(src_dex, src)) return -1;
-    if (create_cache_path(dst_dex, dst)) return -1;
+    if (create_cache_path(src_dex, src, instruction_set)) return -1;
+    if (create_cache_path(dst_dex, dst, instruction_set)) return -1;
 
     ALOGV("move %s -> %s\n", src_dex, dst_dex);
     if (rename(src_dex, dst_dex) < 0) {
@@ -407,12 +407,12 @@
     }
 }
 
-int rm_dex(const char *path)
+int rm_dex(const char *path, const char *instruction_set)
 {
     char dex_path[PKG_PATH_MAX];
 
     if (validate_apk_path(path)) return -1;
-    if (create_cache_path(dex_path, path)) return -1;
+    if (create_cache_path(dex_path, path, instruction_set)) return -1;
 
     ALOGV("unlink %s\n", dex_path);
     if (unlink(dex_path) < 0) {
@@ -425,8 +425,8 @@
 
 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)
+             const char *instruction_set, int64_t *_codesize, int64_t *_datasize,
+             int64_t *_cachesize, int64_t* _asecsize)
 {
     DIR *d;
     int dfd;
@@ -456,7 +456,7 @@
         }
     }
         /* count the cached dexfile as code */
-    if (!create_cache_path(path, apkpath)) {
+    if (!create_cache_path(path, apkpath, instruction_set)) {
         if (stat(path, &s) == 0) {
             codesize += stat_size(&s);
         }
@@ -543,7 +543,7 @@
 }
 
 
-int create_cache_path(char path[PKG_PATH_MAX], const char *src)
+int create_cache_path(char path[PKG_PATH_MAX], const char *src, const char *instruction_set)
 {
     char *tmp;
     int srclen;
@@ -561,18 +561,20 @@
     }
 
     dstlen = srclen + strlen(DALVIK_CACHE_PREFIX) +
-        strlen(DALVIK_CACHE_POSTFIX) + 1;
+        strlen(instruction_set) +
+        strlen(DALVIK_CACHE_POSTFIX) + 2;
 
     if (dstlen > PKG_PATH_MAX) {
         return -1;
     }
 
-    sprintf(path,"%s%s%s",
+    sprintf(path,"%s%s/%s%s",
             DALVIK_CACHE_PREFIX,
+            instruction_set,
             src + 1, /* skip the leading / */
             DALVIK_CACHE_POSTFIX);
 
-    for(tmp = path + strlen(DALVIK_CACHE_PREFIX); *tmp; tmp++) {
+    for(tmp = path + strlen(DALVIK_CACHE_PREFIX) + strlen(instruction_set) + 1; *tmp; tmp++) {
         if (*tmp == '/') {
             *tmp = '@';
         }
@@ -604,7 +606,7 @@
 }
 
 static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name,
-    const char* output_file_name, const char *pkgname)
+    const char* output_file_name, const char *pkgname, const char *instruction_set)
 {
     char dex2oat_flags[PROPERTY_VALUE_MAX];
     property_get("dalvik.vm.dex2oat-flags", dex2oat_flags, "");
@@ -612,28 +614,38 @@
 
     static const char* DEX2OAT_BIN = "/system/bin/dex2oat";
     static const int MAX_INT_LEN = 12;      // '-'+10dig+'\0' -OR- 0x+8dig
+    static const unsigned int MAX_INSTRUCTION_SET_LEN = 32;
+
+    if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) {
+        ALOGE("Instruction set %s longer than max length of %d",
+              instruction_set, MAX_INSTRUCTION_SET_LEN);
+        return;
+    }
+
     char zip_fd_arg[strlen("--zip-fd=") + MAX_INT_LEN];
     char zip_location_arg[strlen("--zip-location=") + PKG_PATH_MAX];
     char oat_fd_arg[strlen("--oat-fd=") + MAX_INT_LEN];
     char oat_location_arg[strlen("--oat-name=") + PKG_PATH_MAX];
-    char profile_file[strlen("--profile-file=") + PKG_PATH_MAX];
+    char profile_file_arg[strlen("--profile-file=") + PKG_PATH_MAX];
+    char instruction_set_arg[strlen("--instruction-set=") + MAX_INSTRUCTION_SET_LEN];
 
     sprintf(zip_fd_arg, "--zip-fd=%d", zip_fd);
     sprintf(zip_location_arg, "--zip-location=%s", input_file_name);
     sprintf(oat_fd_arg, "--oat-fd=%d", oat_fd);
     sprintf(oat_location_arg, "--oat-location=%s", output_file_name);
+    sprintf(instruction_set_arg, "--instruction-set=%s", instruction_set);
     if (strcmp(pkgname, "*") != 0) {
-        snprintf(profile_file, sizeof(profile_file), "--profile-file=%s/%s",
+        snprintf(profile_file_arg, sizeof(profile_file_arg), "--profile-file=%s/%s",
                  DALVIK_CACHE_PREFIX "profiles", pkgname);
     } else {
-        strcpy(profile_file, "--no-profile-file");
+        strcpy(profile_file_arg, "--no-profile-file");
     }
 
     ALOGV("Running %s in=%s out=%s\n", DEX2OAT_BIN, input_file_name, output_file_name);
     execl(DEX2OAT_BIN, DEX2OAT_BIN,
           zip_fd_arg, zip_location_arg,
           oat_fd_arg, oat_location_arg,
-          profile_file,
+          profile_file_arg, instruction_set_arg,
           strlen(dex2oat_flags) > 0 ? dex2oat_flags : NULL,
           (char*) NULL);
     ALOGE("execl(%s) failed: %s\n", DEX2OAT_BIN, strerror(errno));
@@ -666,7 +678,7 @@
 }
 
 int dexopt(const char *apk_path, uid_t uid, int is_public,
-           const char *pkgname)
+           const char *pkgname, const char *instruction_set)
 {
     struct utimbuf ut;
     struct stat apk_stat, dex_stat;
@@ -685,12 +697,16 @@
     /* Before anything else: is there a .odex file?  If so, we have
      * precompiled the apk and there is nothing to do here.
      */
-    sprintf(out_path, "%s%s", apk_path, ".odex");
-    if (stat(out_path, &dex_stat) == 0) {
-        return 0;
+    strcpy(out_path, apk_path);
+    end = strrchr(out_path, '.');
+    if (end != NULL) {
+        strcpy(end, ".odex");
+        if (stat(out_path, &dex_stat) == 0) {
+            return 0;
+        }
     }
 
-    if (create_cache_path(out_path, apk_path)) {
+    if (create_cache_path(out_path, apk_path, instruction_set)) {
         return -1;
     }
 
@@ -758,7 +774,7 @@
         if (strncmp(persist_sys_dalvik_vm_lib, "libdvm", 6) == 0) {
             run_dexopt(zip_fd, out_fd, apk_path, out_path);
         } else if (strncmp(persist_sys_dalvik_vm_lib, "libart", 6) == 0) {
-            run_dex2oat(zip_fd, out_fd, apk_path, out_path, pkgname);
+            run_dex2oat(zip_fd, out_fd, apk_path, out_path, pkgname, instruction_set);
         } else {
             exit(69);   /* Unexpected persist.sys.dalvik.vm.lib value */
         }
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
index a078e1c..10bf5fa 100644
--- a/cmds/installd/installd.c
+++ b/cmds/installd/installd.c
@@ -38,18 +38,18 @@
 
 static int do_dexopt(char **arg, char reply[REPLY_MAX])
 {
-        /* apk_path, uid, is_public, pkgname */
-    return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3]);
+        /* apk_path, uid, is_public, pkgname, instruction_set */
+    return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3], arg[4]);
 }
 
 static int do_move_dex(char **arg, char reply[REPLY_MAX])
 {
-    return move_dex(arg[0], arg[1]); /* src, dst */
+    return move_dex(arg[0], arg[1], arg[2]); /* src, dst, instruction_set */
 }
 
 static int do_rm_dex(char **arg, char reply[REPLY_MAX])
 {
-    return rm_dex(arg[0]); /* pkgname */
+    return rm_dex(arg[0], arg[1]); /* pkgname, instruction_set */
 }
 
 static int do_remove(char **arg, char reply[REPLY_MAX])
@@ -87,7 +87,7 @@
 
         /* pkgdir, userid, apkpath */
     res = get_size(arg[0], atoi(arg[1]), arg[2], arg[3], arg[4], arg[5],
-            &codesize, &datasize, &cachesize, &asecsize);
+            arg[6], &codesize, &datasize, &cachesize, &asecsize);
 
     /*
      * Each int64_t can take up 22 characters printed out. Make sure it
@@ -144,15 +144,15 @@
 struct cmdinfo cmds[] = {
     { "ping",                 0, do_ping },
     { "install",              4, do_install },
-    { "dexopt",               4, do_dexopt },
-    { "movedex",              2, do_move_dex },
-    { "rmdex",                1, do_rm_dex },
+    { "dexopt",               5, do_dexopt },
+    { "movedex",              3, do_move_dex },
+    { "rmdex",                2, do_rm_dex },
     { "remove",               2, do_remove },
     { "rename",               2, do_rename },
     { "fixuid",               3, do_fixuid },
     { "freecache",            1, do_free_cache },
     { "rmcache",              2, do_rm_cache },
-    { "getsize",              6, do_get_size },
+    { "getsize",              7, do_get_size },
     { "rmuserdata",           2, do_rm_user_data },
     { "movefiles",            0, do_movefiles },
     { "linklib",              3, do_linklib },
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index 3e9caf3..0f7119d 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -152,7 +152,8 @@
 
 int is_valid_package_name(const char* pkgname);
 
-int create_cache_path(char path[PKG_PATH_MAX], const char *src);
+int create_cache_path(char path[PKG_PATH_MAX], const char *src,
+                      const char *instruction_set);
 
 int delete_dir_contents(const char *pathname,
                         int also_delete_dir,
@@ -202,14 +203,15 @@
 int make_user_data(const char *pkgname, uid_t uid, userid_t userid, const char* seinfo);
 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 move_dex(const char *src, const char *dst, const char *instruction_set);
+int rm_dex(const char *path, const char *instruction_set);
 int protect(char *pkgname, gid_t gid);
 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);
+             const char *fwdlock_apkpath, const char *asecpath, const char *instruction_set,
+             int64_t *codesize, int64_t *datasize, int64_t *cachesize, int64_t *asecsize);
 int free_cache(int64_t free_size);
-int dexopt(const char *apk_path, uid_t uid, int is_public, const char *pkgName);
+int dexopt(const char *apk_path, uid_t uid, int is_public, const char *pkgName,
+           const char *instruction_set);
 int movefiles();
 int linklib(const char* target, const char* source, int userId);
 int idmap(const char *target_path, const char *overlay_path, uid_t uid);
diff --git a/data/etc/wearable_core_hardware.xml b/data/etc/wearable_core_hardware.xml
index 215665f..e256742 100644
--- a/data/etc/wearable_core_hardware.xml
+++ b/data/etc/wearable_core_hardware.xml
@@ -21,9 +21,7 @@
      Wearable devices include watches, glasses, backpacks, and sweaters.
 -->
 <permissions>
-    <feature name="android.hardware.camera" />
     <feature name="android.hardware.location" />
-    <feature name="android.hardware.location.network" />
     <feature name="android.hardware.sensor.compass" />
     <feature name="android.hardware.sensor.accelerometer" />
     <feature name="android.hardware.bluetooth" />
@@ -34,11 +32,9 @@
 
     <!-- basic system services -->
     <feature name="android.software.home_screen" />
-    <feature name="android.software.input_methods" />
 
-    <!-- Feature to specify if the device supports adding device admins. -->
-    <feature name="android.software.device_admin" />
-
+    <!-- devices that support a device administrator policy must include
+         android.software.device_admin.xml -->
     <!-- devices with GPS must include android.hardware.location.gps.xml -->
     <!-- devices with an autofocus camera and/or flash must include either
          android.hardware.camera.autofocus.xml or
diff --git a/include/input/Input.h b/include/input/Input.h
index 077a03b..a4fa317 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -71,7 +71,7 @@
      * Constants for LEDs. Hidden from the API since we don't actually expose a way to interact
      * with LEDs to developers
      *
-     * NOTE: If you add LEDs here, you must also add them to KeycodeLabels.h
+     * NOTE: If you add LEDs here, you must also add them to InputEventLabels.h
      */
 
     ALED_NUM_LOCK = 0x00,
@@ -146,18 +146,12 @@
  */
 enum {
     /* These flags originate in RawEvents and are generally set in the key map.
-     * NOTE: If you edit these flags, also edit labels in KeycodeLabels.h. */
+     * NOTE: If you want a flag to be able to set in a keylayout file, then you must add it to
+     * InputEventLabels.h as well. */
 
     POLICY_FLAG_WAKE = 0x00000001,
-    POLICY_FLAG_WAKE_DROPPED = 0x00000002,
-    POLICY_FLAG_SHIFT = 0x00000004,
-    POLICY_FLAG_CAPS_LOCK = 0x00000008,
-    POLICY_FLAG_ALT = 0x00000010,
-    POLICY_FLAG_ALT_GR = 0x00000020,
-    POLICY_FLAG_MENU = 0x00000040,
-    POLICY_FLAG_LAUNCHER = 0x00000080,
-    POLICY_FLAG_VIRTUAL = 0x00000100,
-    POLICY_FLAG_FUNCTION = 0x00000200,
+    POLICY_FLAG_VIRTUAL = 0x00000002,
+    POLICY_FLAG_FUNCTION = 0x00000004,
 
     POLICY_FLAG_RAW_MASK = 0x0000ffff,
 
@@ -312,13 +306,8 @@
 
     inline nsecs_t getEventTime() const { return mEventTime; }
 
-    // Return true if this event may have a default action implementation.
-    static bool hasDefaultAction(int32_t keyCode);
-    bool hasDefaultAction() const;
-
-    // Return true if this event represents a system key.
-    static bool isSystemKey(int32_t keyCode);
-    bool isSystemKey() const;
+    static const char* getLabel(int32_t keyCode);
+    static int32_t getKeyCodeFromLabel(const char* label);
     
     void initialize(
             int32_t deviceId,
@@ -578,6 +567,9 @@
             return mSamplePointerCoords.array();
     }
 
+    static const char* getLabel(int32_t axis);
+    static int32_t getAxisFromLabel(const char* label);
+
 protected:
     int32_t mAction;
     int32_t mFlags;
diff --git a/include/input/InputEventLabels.h b/include/input/InputEventLabels.h
new file mode 100644
index 0000000..c6eef9b
--- /dev/null
+++ b/include/input/InputEventLabels.h
@@ -0,0 +1,396 @@
+/*
+ * Copyright (C) 2008 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_INPUT_EVENT_LABELS_H
+#define _LIBINPUT_INPUT_EVENT_LABELS_H
+
+#include <input/Input.h>
+#include <android/keycodes.h>
+
+#define DEFINE_KEYCODE(key) { #key, AKEYCODE_##key }
+#define DEFINE_AXIS(axis) { #axis, AMOTION_EVENT_AXIS_##axis }
+#define DEFINE_LED(led) { #led, ALED_##led }
+#define DEFINE_FLAG(flag) { #flag, POLICY_FLAG_##flag }
+
+namespace android {
+
+template<typename T, size_t N>
+size_t size(T (&)[N]) { return N; }
+
+struct InputEventLabel {
+    const char *literal;
+    int value;
+};
+
+
+static const InputEventLabel KEYCODES[] = {
+    // 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.
+    DEFINE_KEYCODE(UNKNOWN),
+    DEFINE_KEYCODE(SOFT_LEFT),
+    DEFINE_KEYCODE(SOFT_RIGHT),
+    DEFINE_KEYCODE(HOME),
+    DEFINE_KEYCODE(BACK),
+    DEFINE_KEYCODE(CALL),
+    DEFINE_KEYCODE(ENDCALL),
+    DEFINE_KEYCODE(0),
+    DEFINE_KEYCODE(1),
+    DEFINE_KEYCODE(2),
+    DEFINE_KEYCODE(3),
+    DEFINE_KEYCODE(4),
+    DEFINE_KEYCODE(5),
+    DEFINE_KEYCODE(6),
+    DEFINE_KEYCODE(7),
+    DEFINE_KEYCODE(8),
+    DEFINE_KEYCODE(9),
+    DEFINE_KEYCODE(STAR),
+    DEFINE_KEYCODE(POUND),
+    DEFINE_KEYCODE(DPAD_UP),
+    DEFINE_KEYCODE(DPAD_DOWN),
+    DEFINE_KEYCODE(DPAD_LEFT),
+    DEFINE_KEYCODE(DPAD_RIGHT),
+    DEFINE_KEYCODE(DPAD_CENTER),
+    DEFINE_KEYCODE(VOLUME_UP),
+    DEFINE_KEYCODE(VOLUME_DOWN),
+    DEFINE_KEYCODE(POWER),
+    DEFINE_KEYCODE(CAMERA),
+    DEFINE_KEYCODE(CLEAR),
+    DEFINE_KEYCODE(A),
+    DEFINE_KEYCODE(B),
+    DEFINE_KEYCODE(C),
+    DEFINE_KEYCODE(D),
+    DEFINE_KEYCODE(E),
+    DEFINE_KEYCODE(F),
+    DEFINE_KEYCODE(G),
+    DEFINE_KEYCODE(H),
+    DEFINE_KEYCODE(I),
+    DEFINE_KEYCODE(J),
+    DEFINE_KEYCODE(K),
+    DEFINE_KEYCODE(L),
+    DEFINE_KEYCODE(M),
+    DEFINE_KEYCODE(N),
+    DEFINE_KEYCODE(O),
+    DEFINE_KEYCODE(P),
+    DEFINE_KEYCODE(Q),
+    DEFINE_KEYCODE(R),
+    DEFINE_KEYCODE(S),
+    DEFINE_KEYCODE(T),
+    DEFINE_KEYCODE(U),
+    DEFINE_KEYCODE(V),
+    DEFINE_KEYCODE(W),
+    DEFINE_KEYCODE(X),
+    DEFINE_KEYCODE(Y),
+    DEFINE_KEYCODE(Z),
+    DEFINE_KEYCODE(COMMA),
+    DEFINE_KEYCODE(PERIOD),
+    DEFINE_KEYCODE(ALT_LEFT),
+    DEFINE_KEYCODE(ALT_RIGHT),
+    DEFINE_KEYCODE(SHIFT_LEFT),
+    DEFINE_KEYCODE(SHIFT_RIGHT),
+    DEFINE_KEYCODE(TAB),
+    DEFINE_KEYCODE(SPACE),
+    DEFINE_KEYCODE(SYM),
+    DEFINE_KEYCODE(EXPLORER),
+    DEFINE_KEYCODE(ENVELOPE),
+    DEFINE_KEYCODE(ENTER),
+    DEFINE_KEYCODE(DEL),
+    DEFINE_KEYCODE(GRAVE),
+    DEFINE_KEYCODE(MINUS),
+    DEFINE_KEYCODE(EQUALS),
+    DEFINE_KEYCODE(LEFT_BRACKET),
+    DEFINE_KEYCODE(RIGHT_BRACKET),
+    DEFINE_KEYCODE(BACKSLASH),
+    DEFINE_KEYCODE(SEMICOLON),
+    DEFINE_KEYCODE(APOSTROPHE),
+    DEFINE_KEYCODE(SLASH),
+    DEFINE_KEYCODE(AT),
+    DEFINE_KEYCODE(NUM),
+    DEFINE_KEYCODE(HEADSETHOOK),
+    DEFINE_KEYCODE(FOCUS),   // *Camera* focus
+    DEFINE_KEYCODE(PLUS),
+    DEFINE_KEYCODE(MENU),
+    DEFINE_KEYCODE(NOTIFICATION),
+    DEFINE_KEYCODE(SEARCH),
+    DEFINE_KEYCODE(MEDIA_PLAY_PAUSE),
+    DEFINE_KEYCODE(MEDIA_STOP),
+    DEFINE_KEYCODE(MEDIA_NEXT),
+    DEFINE_KEYCODE(MEDIA_PREVIOUS),
+    DEFINE_KEYCODE(MEDIA_REWIND),
+    DEFINE_KEYCODE(MEDIA_FAST_FORWARD),
+    DEFINE_KEYCODE(MUTE),
+    DEFINE_KEYCODE(PAGE_UP),
+    DEFINE_KEYCODE(PAGE_DOWN),
+    DEFINE_KEYCODE(PICTSYMBOLS),
+    DEFINE_KEYCODE(SWITCH_CHARSET),
+    DEFINE_KEYCODE(BUTTON_A),
+    DEFINE_KEYCODE(BUTTON_B),
+    DEFINE_KEYCODE(BUTTON_C),
+    DEFINE_KEYCODE(BUTTON_X),
+    DEFINE_KEYCODE(BUTTON_Y),
+    DEFINE_KEYCODE(BUTTON_Z),
+    DEFINE_KEYCODE(BUTTON_L1),
+    DEFINE_KEYCODE(BUTTON_R1),
+    DEFINE_KEYCODE(BUTTON_L2),
+    DEFINE_KEYCODE(BUTTON_R2),
+    DEFINE_KEYCODE(BUTTON_THUMBL),
+    DEFINE_KEYCODE(BUTTON_THUMBR),
+    DEFINE_KEYCODE(BUTTON_START),
+    DEFINE_KEYCODE(BUTTON_SELECT),
+    DEFINE_KEYCODE(BUTTON_MODE),
+    DEFINE_KEYCODE(ESCAPE),
+    DEFINE_KEYCODE(FORWARD_DEL),
+    DEFINE_KEYCODE(CTRL_LEFT),
+    DEFINE_KEYCODE(CTRL_RIGHT),
+    DEFINE_KEYCODE(CAPS_LOCK),
+    DEFINE_KEYCODE(SCROLL_LOCK),
+    DEFINE_KEYCODE(META_LEFT),
+    DEFINE_KEYCODE(META_RIGHT),
+    DEFINE_KEYCODE(FUNCTION),
+    DEFINE_KEYCODE(SYSRQ),
+    DEFINE_KEYCODE(BREAK),
+    DEFINE_KEYCODE(MOVE_HOME),
+    DEFINE_KEYCODE(MOVE_END),
+    DEFINE_KEYCODE(INSERT),
+    DEFINE_KEYCODE(FORWARD),
+    DEFINE_KEYCODE(MEDIA_PLAY),
+    DEFINE_KEYCODE(MEDIA_PAUSE),
+    DEFINE_KEYCODE(MEDIA_CLOSE),
+    DEFINE_KEYCODE(MEDIA_EJECT),
+    DEFINE_KEYCODE(MEDIA_RECORD),
+    DEFINE_KEYCODE(F1),
+    DEFINE_KEYCODE(F2),
+    DEFINE_KEYCODE(F3),
+    DEFINE_KEYCODE(F4),
+    DEFINE_KEYCODE(F5),
+    DEFINE_KEYCODE(F6),
+    DEFINE_KEYCODE(F7),
+    DEFINE_KEYCODE(F8),
+    DEFINE_KEYCODE(F9),
+    DEFINE_KEYCODE(F10),
+    DEFINE_KEYCODE(F11),
+    DEFINE_KEYCODE(F12),
+    DEFINE_KEYCODE(NUM_LOCK),
+    DEFINE_KEYCODE(NUMPAD_0),
+    DEFINE_KEYCODE(NUMPAD_1),
+    DEFINE_KEYCODE(NUMPAD_2),
+    DEFINE_KEYCODE(NUMPAD_3),
+    DEFINE_KEYCODE(NUMPAD_4),
+    DEFINE_KEYCODE(NUMPAD_5),
+    DEFINE_KEYCODE(NUMPAD_6),
+    DEFINE_KEYCODE(NUMPAD_7),
+    DEFINE_KEYCODE(NUMPAD_8),
+    DEFINE_KEYCODE(NUMPAD_9),
+    DEFINE_KEYCODE(NUMPAD_DIVIDE),
+    DEFINE_KEYCODE(NUMPAD_MULTIPLY),
+    DEFINE_KEYCODE(NUMPAD_SUBTRACT),
+    DEFINE_KEYCODE(NUMPAD_ADD),
+    DEFINE_KEYCODE(NUMPAD_DOT),
+    DEFINE_KEYCODE(NUMPAD_COMMA),
+    DEFINE_KEYCODE(NUMPAD_ENTER),
+    DEFINE_KEYCODE(NUMPAD_EQUALS),
+    DEFINE_KEYCODE(NUMPAD_LEFT_PAREN),
+    DEFINE_KEYCODE(NUMPAD_RIGHT_PAREN),
+    DEFINE_KEYCODE(VOLUME_MUTE),
+    DEFINE_KEYCODE(INFO),
+    DEFINE_KEYCODE(CHANNEL_UP),
+    DEFINE_KEYCODE(CHANNEL_DOWN),
+    DEFINE_KEYCODE(ZOOM_IN),
+    DEFINE_KEYCODE(ZOOM_OUT),
+    DEFINE_KEYCODE(TV),
+    DEFINE_KEYCODE(WINDOW),
+    DEFINE_KEYCODE(GUIDE),
+    DEFINE_KEYCODE(DVR),
+    DEFINE_KEYCODE(BOOKMARK),
+    DEFINE_KEYCODE(CAPTIONS),
+    DEFINE_KEYCODE(SETTINGS),
+    DEFINE_KEYCODE(TV_POWER),
+    DEFINE_KEYCODE(TV_INPUT),
+    DEFINE_KEYCODE(STB_POWER),
+    DEFINE_KEYCODE(STB_INPUT),
+    DEFINE_KEYCODE(AVR_POWER),
+    DEFINE_KEYCODE(AVR_INPUT),
+    DEFINE_KEYCODE(PROG_RED),
+    DEFINE_KEYCODE(PROG_GREEN),
+    DEFINE_KEYCODE(PROG_YELLOW),
+    DEFINE_KEYCODE(PROG_BLUE),
+    DEFINE_KEYCODE(APP_SWITCH),
+    DEFINE_KEYCODE(BUTTON_1),
+    DEFINE_KEYCODE(BUTTON_2),
+    DEFINE_KEYCODE(BUTTON_3),
+    DEFINE_KEYCODE(BUTTON_4),
+    DEFINE_KEYCODE(BUTTON_5),
+    DEFINE_KEYCODE(BUTTON_6),
+    DEFINE_KEYCODE(BUTTON_7),
+    DEFINE_KEYCODE(BUTTON_8),
+    DEFINE_KEYCODE(BUTTON_9),
+    DEFINE_KEYCODE(BUTTON_10),
+    DEFINE_KEYCODE(BUTTON_11),
+    DEFINE_KEYCODE(BUTTON_12),
+    DEFINE_KEYCODE(BUTTON_13),
+    DEFINE_KEYCODE(BUTTON_14),
+    DEFINE_KEYCODE(BUTTON_15),
+    DEFINE_KEYCODE(BUTTON_16),
+    DEFINE_KEYCODE(LANGUAGE_SWITCH),
+    DEFINE_KEYCODE(MANNER_MODE),
+    DEFINE_KEYCODE(3D_MODE),
+    DEFINE_KEYCODE(CONTACTS),
+    DEFINE_KEYCODE(CALENDAR),
+    DEFINE_KEYCODE(MUSIC),
+    DEFINE_KEYCODE(CALCULATOR),
+    DEFINE_KEYCODE(ZENKAKU_HANKAKU),
+    DEFINE_KEYCODE(EISU),
+    DEFINE_KEYCODE(MUHENKAN),
+    DEFINE_KEYCODE(HENKAN),
+    DEFINE_KEYCODE(KATAKANA_HIRAGANA),
+    DEFINE_KEYCODE(YEN),
+    DEFINE_KEYCODE(RO),
+    DEFINE_KEYCODE(KANA),
+    DEFINE_KEYCODE(ASSIST),
+    DEFINE_KEYCODE(BRIGHTNESS_DOWN),
+    DEFINE_KEYCODE(BRIGHTNESS_UP),
+    DEFINE_KEYCODE(MEDIA_AUDIO_TRACK),
+    DEFINE_KEYCODE(SLEEP),
+    DEFINE_KEYCODE(WAKEUP),
+
+    { NULL, 0 }
+};
+
+static const InputEventLabel AXES[] = {
+    DEFINE_AXIS(X),
+    DEFINE_AXIS(Y),
+    DEFINE_AXIS(PRESSURE),
+    DEFINE_AXIS(SIZE),
+    DEFINE_AXIS(TOUCH_MAJOR),
+    DEFINE_AXIS(TOUCH_MINOR),
+    DEFINE_AXIS(TOOL_MAJOR),
+    DEFINE_AXIS(TOOL_MINOR),
+    DEFINE_AXIS(ORIENTATION),
+    DEFINE_AXIS(VSCROLL),
+    DEFINE_AXIS(HSCROLL),
+    DEFINE_AXIS(Z),
+    DEFINE_AXIS(RX),
+    DEFINE_AXIS(RY),
+    DEFINE_AXIS(RZ),
+    DEFINE_AXIS(HAT_X),
+    DEFINE_AXIS(HAT_Y),
+    DEFINE_AXIS(LTRIGGER),
+    DEFINE_AXIS(RTRIGGER),
+    DEFINE_AXIS(THROTTLE),
+    DEFINE_AXIS(RUDDER),
+    DEFINE_AXIS(WHEEL),
+    DEFINE_AXIS(GAS),
+    DEFINE_AXIS(BRAKE),
+    DEFINE_AXIS(DISTANCE),
+    DEFINE_AXIS(TILT),
+    DEFINE_AXIS(GENERIC_1),
+    DEFINE_AXIS(GENERIC_2),
+    DEFINE_AXIS(GENERIC_3),
+    DEFINE_AXIS(GENERIC_4),
+    DEFINE_AXIS(GENERIC_5),
+    DEFINE_AXIS(GENERIC_6),
+    DEFINE_AXIS(GENERIC_7),
+    DEFINE_AXIS(GENERIC_8),
+    DEFINE_AXIS(GENERIC_9),
+    DEFINE_AXIS(GENERIC_10),
+    DEFINE_AXIS(GENERIC_11),
+    DEFINE_AXIS(GENERIC_12),
+    DEFINE_AXIS(GENERIC_13),
+    DEFINE_AXIS(GENERIC_14),
+    DEFINE_AXIS(GENERIC_15),
+    DEFINE_AXIS(GENERIC_16),
+
+    // NOTE: If you add a new axis here you must also add it to several other files.
+    //       Refer to frameworks/base/core/java/android/view/MotionEvent.java for the full list.
+    { NULL, 0 }
+};
+
+static const InputEventLabel LEDS[] = {
+    DEFINE_LED(NUM_LOCK),
+    DEFINE_LED(CAPS_LOCK),
+    DEFINE_LED(SCROLL_LOCK),
+    DEFINE_LED(COMPOSE),
+    DEFINE_LED(KANA),
+    DEFINE_LED(SLEEP),
+    DEFINE_LED(SUSPEND),
+    DEFINE_LED(MUTE),
+    DEFINE_LED(MISC),
+    DEFINE_LED(MAIL),
+    DEFINE_LED(CHARGING),
+    DEFINE_LED(CONTROLLER_1),
+    DEFINE_LED(CONTROLLER_2),
+    DEFINE_LED(CONTROLLER_3),
+    DEFINE_LED(CONTROLLER_4),
+
+    // NOTE: If you add new LEDs here, you must also add them to Input.h
+    { NULL, 0 }
+};
+
+static const InputEventLabel FLAGS[] = {
+    DEFINE_FLAG(FUNCTION),
+
+    { NULL, 0 }
+};
+
+static int lookupValueByLabel(const char* literal, const InputEventLabel *list) {
+    while (list->literal) {
+        if (strcmp(literal, list->literal) == 0) {
+            return list->value;
+        }
+        list++;
+    }
+    return list->value;
+}
+
+static const char* lookupLabelByValue(int value, const InputEventLabel* list) {
+    while (list->literal) {
+        if (list->value == value) {
+            return list->literal;
+        }
+        list++;
+    }
+    return NULL;
+}
+
+static int32_t getKeyCodeByLabel(const char* label) {
+    return int32_t(lookupValueByLabel(label, KEYCODES));
+}
+
+static const char* getLabelByKeyCode(int32_t keyCode) {
+    if (keyCode >= 0 && keyCode < size(KEYCODES)) {
+        return KEYCODES[keyCode].literal;
+    }
+    return NULL;
+}
+
+static uint32_t getKeyFlagByLabel(const char* label) {
+    return uint32_t(lookupValueByLabel(label, FLAGS));
+}
+
+static int32_t getAxisByLabel(const char* label) {
+    return int32_t(lookupValueByLabel(label, AXES));
+}
+
+static const char* getAxisLabel(int32_t axisId) {
+    return lookupLabelByValue(axisId, AXES);
+}
+
+static int32_t getLedByLabel(const char* label) {
+    return int32_t(lookupValueByLabel(label, LEDS));
+}
+
+
+} // namespace android
+#endif // _LIBINPUT_INPUT_EVENT_LABELS_H
diff --git a/include/input/Keyboard.h b/include/input/Keyboard.h
index 25b2f07..519bb22 100644
--- a/include/input/Keyboard.h
+++ b/include/input/Keyboard.h
@@ -19,6 +19,7 @@
 
 #include <input/Input.h>
 #include <input/InputDevice.h>
+#include <input/InputEventLabels.h>
 #include <utils/Errors.h>
 #include <utils/String8.h>
 #include <utils/PropertyMap.h>
@@ -82,36 +83,6 @@
         const PropertyMap* deviceConfiguration, const KeyMap* keyMap);
 
 /**
- * Gets a key code by its short form label, eg. "HOME".
- * Returns 0 if unknown.
- */
-extern int32_t getKeyCodeByLabel(const char* label);
-
-/**
- * Gets a key flag by its short form label, eg. "WAKE".
- * Returns 0 if unknown.
- */
-extern uint32_t getKeyFlagByLabel(const char* label);
-
-/**
- * Gets an axis by its short form label, eg. "X".
- * Returns -1 if unknown.
- */
-extern int32_t getAxisByLabel(const char* label);
-
-/**
- * Gets an axis label by its id.
- * Returns NULL if unknown.
- */
-extern const char* getAxisLabel(int32_t axisId);
-
-/**
- * Gets an LED by its short form label, eg. "CAPS_LOCK".
- * Returns -1 if unknown.
- */
-extern int32_t getLedByLabel(const char* label);
-
-/**
  * Updates a meta state field when a key is pressed or released.
  */
 extern int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState);
diff --git a/include/input/KeycodeLabels.h b/include/input/KeycodeLabels.h
deleted file mode 100644
index a8d63da..0000000
--- a/include/input/KeycodeLabels.h
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * Copyright (C) 2008 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_KEYCODE_LABELS_H
-#define _LIBINPUT_KEYCODE_LABELS_H
-
-#include <android/keycodes.h>
-
-struct KeycodeLabel {
-    const char *literal;
-    int value;
-};
-
-static const KeycodeLabel KEYCODES[] = {
-    { "SOFT_LEFT", 1 },
-    { "SOFT_RIGHT", 2 },
-    { "HOME", 3 },
-    { "BACK", 4 },
-    { "CALL", 5 },
-    { "ENDCALL", 6 },
-    { "0", 7 },
-    { "1", 8 },
-    { "2", 9 },
-    { "3", 10 },
-    { "4", 11 },
-    { "5", 12 },
-    { "6", 13 },
-    { "7", 14 },
-    { "8", 15 },
-    { "9", 16 },
-    { "STAR", 17 },
-    { "POUND", 18 },
-    { "DPAD_UP", 19 },
-    { "DPAD_DOWN", 20 },
-    { "DPAD_LEFT", 21 },
-    { "DPAD_RIGHT", 22 },
-    { "DPAD_CENTER", 23 },
-    { "VOLUME_UP", 24 },
-    { "VOLUME_DOWN", 25 },
-    { "POWER", 26 },
-    { "CAMERA", 27 },
-    { "CLEAR", 28 },
-    { "A", 29 },
-    { "B", 30 },
-    { "C", 31 },
-    { "D", 32 },
-    { "E", 33 },
-    { "F", 34 },
-    { "G", 35 },
-    { "H", 36 },
-    { "I", 37 },
-    { "J", 38 },
-    { "K", 39 },
-    { "L", 40 },
-    { "M", 41 },
-    { "N", 42 },
-    { "O", 43 },
-    { "P", 44 },
-    { "Q", 45 },
-    { "R", 46 },
-    { "S", 47 },
-    { "T", 48 },
-    { "U", 49 },
-    { "V", 50 },
-    { "W", 51 },
-    { "X", 52 },
-    { "Y", 53 },
-    { "Z", 54 },
-    { "COMMA", 55 },
-    { "PERIOD", 56 },
-    { "ALT_LEFT", 57 },
-    { "ALT_RIGHT", 58 },
-    { "SHIFT_LEFT", 59 },
-    { "SHIFT_RIGHT", 60 },
-    { "TAB", 61 },
-    { "SPACE", 62 },
-    { "SYM", 63 },
-    { "EXPLORER", 64 },
-    { "ENVELOPE", 65 },
-    { "ENTER", 66 },
-    { "DEL", 67 },
-    { "GRAVE", 68 },
-    { "MINUS", 69 },
-    { "EQUALS", 70 },
-    { "LEFT_BRACKET", 71 },
-    { "RIGHT_BRACKET", 72 },
-    { "BACKSLASH", 73 },
-    { "SEMICOLON", 74 },
-    { "APOSTROPHE", 75 },
-    { "SLASH", 76 },
-    { "AT", 77 },
-    { "NUM", 78 },
-    { "HEADSETHOOK", 79 },
-    { "FOCUS", 80 },
-    { "PLUS", 81 },
-    { "MENU", 82 },
-    { "NOTIFICATION", 83 },
-    { "SEARCH", 84 },
-    { "MEDIA_PLAY_PAUSE", 85 },
-    { "MEDIA_STOP", 86 },
-    { "MEDIA_NEXT", 87 },
-    { "MEDIA_PREVIOUS", 88 },
-    { "MEDIA_REWIND", 89 },
-    { "MEDIA_FAST_FORWARD", 90 },
-    { "MUTE", 91 },
-    { "PAGE_UP", 92 },
-    { "PAGE_DOWN", 93 },
-    { "PICTSYMBOLS", 94 },
-    { "SWITCH_CHARSET", 95 },
-    { "BUTTON_A", 96 },
-    { "BUTTON_B", 97 },
-    { "BUTTON_C", 98 },
-    { "BUTTON_X", 99 },
-    { "BUTTON_Y", 100 },
-    { "BUTTON_Z", 101 },
-    { "BUTTON_L1", 102 },
-    { "BUTTON_R1", 103 },
-    { "BUTTON_L2", 104 },
-    { "BUTTON_R2", 105 },
-    { "BUTTON_THUMBL", 106 },
-    { "BUTTON_THUMBR", 107 },
-    { "BUTTON_START", 108 },
-    { "BUTTON_SELECT", 109 },
-    { "BUTTON_MODE", 110 },
-    { "ESCAPE", 111 },
-    { "FORWARD_DEL", 112 },
-    { "CTRL_LEFT", 113 },
-    { "CTRL_RIGHT", 114 },
-    { "CAPS_LOCK", 115 },
-    { "SCROLL_LOCK", 116 },
-    { "META_LEFT", 117 },
-    { "META_RIGHT", 118 },
-    { "FUNCTION", 119 },
-    { "SYSRQ", 120 },
-    { "BREAK", 121 },
-    { "MOVE_HOME", 122 },
-    { "MOVE_END", 123 },
-    { "INSERT", 124 },
-    { "FORWARD", 125 },
-    { "MEDIA_PLAY", 126 },
-    { "MEDIA_PAUSE", 127 },
-    { "MEDIA_CLOSE", 128 },
-    { "MEDIA_EJECT", 129 },
-    { "MEDIA_RECORD", 130 },
-    { "F1", 131 },
-    { "F2", 132 },
-    { "F3", 133 },
-    { "F4", 134 },
-    { "F5", 135 },
-    { "F6", 136 },
-    { "F7", 137 },
-    { "F8", 138 },
-    { "F9", 139 },
-    { "F10", 140 },
-    { "F11", 141 },
-    { "F12", 142 },
-    { "NUM_LOCK", 143 },
-    { "NUMPAD_0", 144 },
-    { "NUMPAD_1", 145 },
-    { "NUMPAD_2", 146 },
-    { "NUMPAD_3", 147 },
-    { "NUMPAD_4", 148 },
-    { "NUMPAD_5", 149 },
-    { "NUMPAD_6", 150 },
-    { "NUMPAD_7", 151 },
-    { "NUMPAD_8", 152 },
-    { "NUMPAD_9", 153 },
-    { "NUMPAD_DIVIDE", 154 },
-    { "NUMPAD_MULTIPLY", 155 },
-    { "NUMPAD_SUBTRACT", 156 },
-    { "NUMPAD_ADD", 157 },
-    { "NUMPAD_DOT", 158 },
-    { "NUMPAD_COMMA", 159 },
-    { "NUMPAD_ENTER", 160 },
-    { "NUMPAD_EQUALS", 161 },
-    { "NUMPAD_LEFT_PAREN", 162 },
-    { "NUMPAD_RIGHT_PAREN", 163 },
-    { "VOLUME_MUTE", 164 },
-    { "INFO", 165 },
-    { "CHANNEL_UP", 166 },
-    { "CHANNEL_DOWN", 167 },
-    { "ZOOM_IN", 168 },
-    { "ZOOM_OUT", 169 },
-    { "TV", 170 },
-    { "WINDOW", 171 },
-    { "GUIDE", 172 },
-    { "DVR", 173 },
-    { "BOOKMARK", 174 },
-    { "CAPTIONS", 175 },
-    { "SETTINGS", 176 },
-    { "TV_POWER", 177 },
-    { "TV_INPUT", 178 },
-    { "STB_POWER", 179 },
-    { "STB_INPUT", 180 },
-    { "AVR_POWER", 181 },
-    { "AVR_INPUT", 182 },
-    { "PROG_RED", 183 },
-    { "PROG_GREEN", 184 },
-    { "PROG_YELLOW", 185 },
-    { "PROG_BLUE", 186 },
-    { "APP_SWITCH", 187 },
-    { "BUTTON_1", 188 },
-    { "BUTTON_2", 189 },
-    { "BUTTON_3", 190 },
-    { "BUTTON_4", 191 },
-    { "BUTTON_5", 192 },
-    { "BUTTON_6", 193 },
-    { "BUTTON_7", 194 },
-    { "BUTTON_8", 195 },
-    { "BUTTON_9", 196 },
-    { "BUTTON_10", 197 },
-    { "BUTTON_11", 198 },
-    { "BUTTON_12", 199 },
-    { "BUTTON_13", 200 },
-    { "BUTTON_14", 201 },
-    { "BUTTON_15", 202 },
-    { "BUTTON_16", 203 },
-    { "LANGUAGE_SWITCH", 204 },
-    { "MANNER_MODE", 205 },
-    { "3D_MODE", 206 },
-    { "CONTACTS", 207 },
-    { "CALENDAR", 208 },
-    { "MUSIC", 209 },
-    { "CALCULATOR", 210 },
-    { "ZENKAKU_HANKAKU", 211 },
-    { "EISU", 212 },
-    { "MUHENKAN", 213 },
-    { "HENKAN", 214 },
-    { "KATAKANA_HIRAGANA", 215 },
-    { "YEN", 216 },
-    { "RO", 217 },
-    { "KANA", 218 },
-    { "ASSIST", 219 },
-    { "BRIGHTNESS_DOWN", 220 },
-    { "BRIGHTNESS_UP", 221 },
-    { "MEDIA_AUDIO_TRACK", 222 },
-    { "SLEEP", 223 },
-    { "WAKEUP", 224 },
-
-    // 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.
-
-    { NULL, 0 }
-};
-
-// NOTE: If you edit these flags, also edit policy flags in Input.h.
-static const KeycodeLabel FLAGS[] = {
-    { "WAKE", 0x00000001 },
-    { "WAKE_DROPPED", 0x00000002 },
-    { "SHIFT", 0x00000004 },
-    { "CAPS_LOCK", 0x00000008 },
-    { "ALT", 0x00000010 },
-    { "ALT_GR", 0x00000020 },
-    { "MENU", 0x00000040 },
-    { "LAUNCHER", 0x00000080 },
-    { "VIRTUAL", 0x00000100 },
-    { "FUNCTION", 0x00000200 },
-    { NULL, 0 }
-};
-
-static const KeycodeLabel AXES[] = {
-    { "X", 0 },
-    { "Y", 1 },
-    { "PRESSURE", 2 },
-    { "SIZE", 3 },
-    { "TOUCH_MAJOR", 4 },
-    { "TOUCH_MINOR", 5 },
-    { "TOOL_MAJOR", 6 },
-    { "TOOL_MINOR", 7 },
-    { "ORIENTATION", 8 },
-    { "VSCROLL", 9 },
-    { "HSCROLL", 10 },
-    { "Z", 11 },
-    { "RX", 12 },
-    { "RY", 13 },
-    { "RZ", 14 },
-    { "HAT_X", 15 },
-    { "HAT_Y", 16 },
-    { "LTRIGGER", 17 },
-    { "RTRIGGER", 18 },
-    { "THROTTLE", 19 },
-    { "RUDDER", 20 },
-    { "WHEEL", 21 },
-    { "GAS", 22 },
-    { "BRAKE", 23 },
-    { "DISTANCE", 24 },
-    { "TILT", 25 },
-    { "GENERIC_1", 32 },
-    { "GENERIC_2", 33 },
-    { "GENERIC_3", 34 },
-    { "GENERIC_4", 35 },
-    { "GENERIC_5", 36 },
-    { "GENERIC_6", 37 },
-    { "GENERIC_7", 38 },
-    { "GENERIC_8", 39 },
-    { "GENERIC_9", 40 },
-    { "GENERIC_10", 41 },
-    { "GENERIC_11", 42 },
-    { "GENERIC_12", 43 },
-    { "GENERIC_13", 44 },
-    { "GENERIC_14", 45 },
-    { "GENERIC_15", 46 },
-    { "GENERIC_16", 47 },
-
-    // NOTE: If you add a new axis here you must also add it to several other files.
-    //       Refer to frameworks/base/core/java/android/view/MotionEvent.java for the full list.
-
-    { NULL, -1 }
-};
-
-static const KeycodeLabel LEDS[] = {
-    { "NUM_LOCK", 0x00 },
-    { "CAPS_LOCK", 0x01 },
-    { "SCROLL_LOCK", 0x02 },
-    { "COMPOSE", 0x03 },
-    { "KANA", 0x04 },
-    { "SLEEP", 0x05 },
-    { "SUSPEND", 0x06 },
-    { "MUTE", 0x07 },
-    { "MISC", 0x08 },
-    { "MAIL", 0x09 },
-    { "CHARGING", 0x0a },
-    { "CONTROLLER_1", 0x10 },
-    { "CONTROLLER_2", 0x11 },
-    { "CONTROLLER_3", 0x12 },
-    { "CONTROLLER_4", 0x13 },
-
-    // NOTE: If you add new LEDs here, you must also add them to Input.h
-
-    { NULL, -1 }
-};
-
-#endif // _LIBINPUT_KEYCODE_LABELS_H
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 4298522..52fff82 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -25,6 +25,7 @@
 #include <binder/ProcessState.h>
 #include <binder/TextOutput.h>
 
+#include <errno.h>
 #include <utils/Debug.h>
 #include <utils/Log.h>
 #include <utils/String8.h>
@@ -1284,7 +1285,11 @@
     status_t err = NO_ERROR;
     for (size_t i=0 ; i<fd_count && err==NO_ERROR ; i++) {
         fds[i] = dup(this->readFileDescriptor());
-        if (fds[i] < 0) err = BAD_VALUE;
+        if (fds[i] < 0) {
+            err = BAD_VALUE;
+            ALOGE("dup() failed in Parcel::read, i is %d, fds[i] is %d, fd_count is %d, error: %s",
+                i, fds[i], fd_count, strerror(errno));
+        }
     }
 
     if (err == NO_ERROR) {
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index d9f22e9..3a7afe9 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -21,6 +21,7 @@
 #include <limits.h>
 
 #include <input/Input.h>
+#include <input/InputEventLabels.h>
 
 #ifdef HAVE_ANDROID_OS
 #include <binder/Parcel.h>
@@ -42,82 +43,12 @@
 
 // --- KeyEvent ---
 
-bool KeyEvent::hasDefaultAction(int32_t keyCode) {
-    switch (keyCode) {
-        case AKEYCODE_HOME:
-        case AKEYCODE_BACK:
-        case AKEYCODE_CALL:
-        case AKEYCODE_ENDCALL:
-        case AKEYCODE_VOLUME_UP:
-        case AKEYCODE_VOLUME_DOWN:
-        case AKEYCODE_VOLUME_MUTE:
-        case AKEYCODE_POWER:
-        case AKEYCODE_CAMERA:
-        case AKEYCODE_HEADSETHOOK:
-        case AKEYCODE_MENU:
-        case AKEYCODE_NOTIFICATION:
-        case AKEYCODE_FOCUS:
-        case AKEYCODE_SEARCH:
-        case AKEYCODE_MEDIA_PLAY:
-        case AKEYCODE_MEDIA_PAUSE:
-        case AKEYCODE_MEDIA_PLAY_PAUSE:
-        case AKEYCODE_MEDIA_STOP:
-        case AKEYCODE_MEDIA_NEXT:
-        case AKEYCODE_MEDIA_PREVIOUS:
-        case AKEYCODE_MEDIA_REWIND:
-        case AKEYCODE_MEDIA_RECORD:
-        case AKEYCODE_MEDIA_FAST_FORWARD:
-        case AKEYCODE_MUTE:
-        case AKEYCODE_BRIGHTNESS_DOWN:
-        case AKEYCODE_BRIGHTNESS_UP:
-        case AKEYCODE_MEDIA_AUDIO_TRACK:
-            return true;
-    }
-    
-    return false;
+const char* KeyEvent::getLabel(int32_t keyCode) {
+    return getLabelByKeyCode(keyCode);
 }
 
-bool KeyEvent::hasDefaultAction() const {
-    return hasDefaultAction(getKeyCode());
-}
-
-bool KeyEvent::isSystemKey(int32_t keyCode) {
-    switch (keyCode) {
-        case AKEYCODE_MENU:
-        case AKEYCODE_SOFT_RIGHT:
-        case AKEYCODE_HOME:
-        case AKEYCODE_BACK:
-        case AKEYCODE_CALL:
-        case AKEYCODE_ENDCALL:
-        case AKEYCODE_VOLUME_UP:
-        case AKEYCODE_VOLUME_DOWN:
-        case AKEYCODE_VOLUME_MUTE:
-        case AKEYCODE_MUTE:
-        case AKEYCODE_POWER:
-        case AKEYCODE_HEADSETHOOK:
-        case AKEYCODE_MEDIA_PLAY:
-        case AKEYCODE_MEDIA_PAUSE:
-        case AKEYCODE_MEDIA_PLAY_PAUSE:
-        case AKEYCODE_MEDIA_STOP:
-        case AKEYCODE_MEDIA_NEXT:
-        case AKEYCODE_MEDIA_PREVIOUS:
-        case AKEYCODE_MEDIA_REWIND:
-        case AKEYCODE_MEDIA_RECORD:
-        case AKEYCODE_MEDIA_FAST_FORWARD:
-        case AKEYCODE_CAMERA:
-        case AKEYCODE_FOCUS:
-        case AKEYCODE_SEARCH:
-        case AKEYCODE_BRIGHTNESS_DOWN:
-        case AKEYCODE_BRIGHTNESS_UP:
-        case AKEYCODE_MEDIA_AUDIO_TRACK:
-            return true;
-    }
-    
-    return false;
-}
-
-bool KeyEvent::isSystemKey() const {
-    return isSystemKey(getKeyCode());
+int32_t KeyEvent::getKeyCodeFromLabel(const char* label) {
+    return getKeyCodeByLabel(label);
 }
 
 void KeyEvent::initialize(
@@ -591,6 +522,14 @@
     return false;
 }
 
+const char* MotionEvent::getLabel(int32_t axis) {
+    return getAxisLabel(axis);
+}
+
+int32_t MotionEvent::getAxisFromLabel(const char* label) {
+    return getAxisByLabel(label);
+}
+
 
 // --- PooledInputEventFactory ---
 
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 09b2e7c..a73780d 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -312,7 +312,7 @@
     }
 
     if (pointerCount > MAX_POINTERS || pointerCount < 1) {
-        ALOGE("channel '%s' publisher ~ Invalid number of pointers provided: %d.",
+        ALOGE("channel '%s' publisher ~ Invalid number of pointers provided: %zu.",
                 mChannel->getName().string(), pointerCount);
         return BAD_VALUE;
     }
diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp
index 15a877447..b03e01e 100644
--- a/libs/input/KeyCharacterMap.cpp
+++ b/libs/input/KeyCharacterMap.cpp
@@ -24,6 +24,7 @@
 #endif
 
 #include <android/keycodes.h>
+#include <input/InputEventLabels.h>
 #include <input/Keyboard.h>
 #include <input/KeyCharacterMap.h>
 
diff --git a/libs/input/KeyLayoutMap.cpp b/libs/input/KeyLayoutMap.cpp
index 0800a31..2b2f13e 100644
--- a/libs/input/KeyLayoutMap.cpp
+++ b/libs/input/KeyLayoutMap.cpp
@@ -19,6 +19,7 @@
 #include <stdlib.h>
 
 #include <android/keycodes.h>
+#include <input/InputEventLabels.h>
 #include <input/Keyboard.h>
 #include <input/KeyLayoutMap.h>
 #include <utils/Log.h>
diff --git a/libs/input/Keyboard.cpp b/libs/input/Keyboard.cpp
index 7d4ac92..f4d9507 100644
--- a/libs/input/Keyboard.cpp
+++ b/libs/input/Keyboard.cpp
@@ -21,7 +21,7 @@
 #include <limits.h>
 
 #include <input/Keyboard.h>
-#include <input/KeycodeLabels.h>
+#include <input/InputEventLabels.h>
 #include <input/KeyLayoutMap.h>
 #include <input/KeyCharacterMap.h>
 #include <input/InputDevice.h>
@@ -167,46 +167,6 @@
     return strstr(deviceIdentifier.name.string(), "-keypad");
 }
 
-static int lookupValueByLabel(const char* literal, const KeycodeLabel *list) {
-    while (list->literal) {
-        if (strcmp(literal, list->literal) == 0) {
-            return list->value;
-        }
-        list++;
-    }
-    return list->value;
-}
-
-static const char* lookupLabelByValue(int value, const KeycodeLabel *list) {
-    while (list->literal) {
-        if (list->value == value) {
-            return list->literal;
-        }
-        list++;
-    }
-    return NULL;
-}
-
-int32_t getKeyCodeByLabel(const char* label) {
-    return int32_t(lookupValueByLabel(label, KEYCODES));
-}
-
-uint32_t getKeyFlagByLabel(const char* label) {
-    return uint32_t(lookupValueByLabel(label, FLAGS));
-}
-
-int32_t getAxisByLabel(const char* label) {
-    return int32_t(lookupValueByLabel(label, AXES));
-}
-
-const char* getAxisLabel(int32_t axisId) {
-    return lookupLabelByValue(axisId, AXES);
-}
-
-int32_t getLedByLabel(const char* label) {
-    return int32_t(lookupValueByLabel(label, LEDS));
-}
-
 static int32_t setEphemeralMetaState(int32_t mask, bool down, int32_t oldMetaState) {
     int32_t newMetaState;
     if (down) {
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index f219f95..0bae399 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -2360,18 +2360,6 @@
         policyFlags |= POLICY_FLAG_VIRTUAL;
         flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
     }
-    if (policyFlags & POLICY_FLAG_ALT) {
-        metaState |= AMETA_ALT_ON | AMETA_ALT_LEFT_ON;
-    }
-    if (policyFlags & POLICY_FLAG_ALT_GR) {
-        metaState |= AMETA_ALT_ON | AMETA_ALT_RIGHT_ON;
-    }
-    if (policyFlags & POLICY_FLAG_SHIFT) {
-        metaState |= AMETA_SHIFT_ON | AMETA_SHIFT_LEFT_ON;
-    }
-    if (policyFlags & POLICY_FLAG_CAPS_LOCK) {
-        metaState |= AMETA_CAPS_LOCK_ON;
-    }
     if (policyFlags & POLICY_FLAG_FUNCTION) {
         metaState |= AMETA_FUNCTION_ON;
     }
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index f27ba96..8295c4c 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -2167,9 +2167,8 @@
     // For internal keyboards, the key layout file should specify the policy flags for
     // each wake key individually.
     // TODO: Use the input device configuration to control this behavior more finely.
-    if (down && getDevice()->isExternal()
-            && !(policyFlags & (POLICY_FLAG_WAKE | POLICY_FLAG_WAKE_DROPPED))) {
-        policyFlags |= POLICY_FLAG_WAKE_DROPPED;
+    if (down && getDevice()->isExternal()) {
+        policyFlags |= POLICY_FLAG_WAKE;
     }
 
     if (mParameters.handlesKeyRepeat) {
@@ -2510,7 +2509,7 @@
     // TODO: Use the input device configuration to control this behavior more finely.
     uint32_t policyFlags = 0;
     if ((buttonsPressed || moved || scrolled) && getDevice()->isExternal()) {
-        policyFlags |= POLICY_FLAG_WAKE_DROPPED;
+        policyFlags |= POLICY_FLAG_WAKE;
     }
 
     // Synthesize key down from buttons if needed.
@@ -3787,7 +3786,7 @@
             }
 
             if (mParameters.wake) {
-                policyFlags |= POLICY_FLAG_WAKE_DROPPED;
+                policyFlags |= POLICY_FLAG_WAKE;
             }
         }
 
diff --git a/services/inputflinger/InputWindow.cpp b/services/inputflinger/InputWindow.cpp
index da59159..fda3ffa 100644
--- a/services/inputflinger/InputWindow.cpp
+++ b/services/inputflinger/InputWindow.cpp
@@ -43,6 +43,7 @@
 bool InputWindowInfo::isTrustedOverlay() const {
     return layoutParamsType == TYPE_INPUT_METHOD
             || layoutParamsType == TYPE_INPUT_METHOD_DIALOG
+            || layoutParamsType == TYPE_MAGNIFICATION_OVERLAY
             || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY;
 }
 
diff --git a/services/inputflinger/InputWindow.h b/services/inputflinger/InputWindow.h
index 9618ffe..5879c84 100644
--- a/services/inputflinger/InputWindow.h
+++ b/services/inputflinger/InputWindow.h
@@ -106,6 +106,7 @@
         TYPE_NAVIGATION_BAR     = FIRST_SYSTEM_WINDOW+19,
         TYPE_VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW+20,
         TYPE_BOOT_PROGRESS = FIRST_SYSTEM_WINDOW+21,
+        TYPE_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW+22,
         LAST_SYSTEM_WINDOW      = 2999,
     };
 
diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp
index 602f20a..fd46822 100644
--- a/services/surfaceflinger/DispSync.cpp
+++ b/services/surfaceflinger/DispSync.cpp
@@ -61,7 +61,10 @@
 public:
 
     DispSyncThread():
+            mLowPowerMode(false),
             mStop(false),
+            mLastVsyncSent(false),
+            mLastBufferFull(false),
             mPeriod(0),
             mPhase(0),
             mWakeupLatency(0) {
@@ -145,7 +148,18 @@
             }
 
             if (callbackInvocations.size() > 0) {
-                fireCallbackInvocations(callbackInvocations);
+                if (mLowPowerMode) {
+                    if (!mLastVsyncSent || !mLastBufferFull) {
+                        fireCallbackInvocations(callbackInvocations);
+                        mLastVsyncSent = true;
+                    } else
+                        mLastVsyncSent = false;
+                } else {
+                    fireCallbackInvocations(callbackInvocations);
+                }
+                mLastBufferFull = true;
+            } else {
+                mLastBufferFull = false;
             }
         }
 
@@ -200,6 +214,7 @@
         return !mEventListeners.empty();
     }
 
+    bool mLowPowerMode;
 private:
 
     struct EventListener {
@@ -272,6 +287,8 @@
     }
 
     bool mStop;
+    bool mLastVsyncSent;
+    bool mLastBufferFull;
 
     nsecs_t mPeriod;
     nsecs_t mPhase;
@@ -395,6 +412,10 @@
     return mThread->addEventListener(phase, callback);
 }
 
+void DispSync::setLowPowerMode(bool enabled) {
+    mThread->mLowPowerMode = enabled;
+}
+
 status_t DispSync::removeEventListener(const sp<Callback>& callback) {
     Mutex::Autolock lock(mMutex);
     return mThread->removeEventListener(callback);
@@ -487,4 +508,9 @@
     }
 }
 
+nsecs_t DispSync::computeNextRefresh(int periodOffset) const {
+    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+    return (((now - mPhase) / mPeriod) + periodOffset + 1) * mPeriod + mPhase;
+}
+
 } // namespace android
diff --git a/services/surfaceflinger/DispSync.h b/services/surfaceflinger/DispSync.h
index c4280aa..5826a78 100644
--- a/services/surfaceflinger/DispSync.h
+++ b/services/surfaceflinger/DispSync.h
@@ -83,11 +83,14 @@
     bool addResyncSample(nsecs_t timestamp);
     void endResync();
 
-    // The setPreiod method sets the vsync event model's period to a specific
+    // The setPeriod method sets the vsync event model's period to a specific
     // value.  This should be used to prime the model when a display is first
     // turned on.  It should NOT be used after that.
     void setPeriod(nsecs_t period);
 
+    // Setting the low power mode reduces the frame rate to half of the default
+    void setLowPowerMode(bool enabled);
+
     // addEventListener registers a callback to be called repeatedly at the
     // given phase offset from the hardware vsync events.  The callback is
     // called from a separate thread and it should return reasonably quickly
@@ -99,6 +102,12 @@
     // DispSync object.
     status_t removeEventListener(const sp<Callback>& callback);
 
+    // computeNextRefresh computes when the next refresh is expected to begin.
+    // The periodOffset value can be used to move forward or backward; an
+    // offset of zero is the next refresh, -1 is the previous refresh, 1 is
+    // the refresh after next. etc.
+    nsecs_t computeNextRefresh(int periodOffset) const;
+
 private:
 
     void updateModelLocked();
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index c4ea8cc..2d63bde 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -821,7 +821,7 @@
     return NO_ERROR;
 }
 
-sp<Fence> HWComposer::getLastRetireFence(int32_t id) {
+sp<Fence> HWComposer::getLastRetireFence(int32_t id) const {
     if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
         return Fence::NO_FENCE;
     return mDisplayData[id].lastRetireFence;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 9218bf6..e93bb7e 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -142,7 +142,7 @@
     // signal when the h/w composer is completely finished with the frame.
     // For physical displays, it is no longer being displayed. For virtual
     // displays, writes to the output buffer are complete.
-    sp<Fence> getLastRetireFence(int32_t id);
+    sp<Fence> getLastRetireFence(int32_t id) const;
 
     /*
      * Interface to hardware composer's layers functionality.
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 1362ae8..c415560 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -302,7 +302,12 @@
         }
     }
     if (result & BUFFER_NEEDS_REALLOCATION) {
-        mSource[source]->requestBuffer(*sslot, &mProducerBuffers[pslot]);
+        result = mSource[source]->requestBuffer(*sslot, &mProducerBuffers[pslot]);
+        if (result < 0) {
+            mProducerBuffers[pslot].clear();
+            mSource[source]->cancelBuffer(*sslot, *fence);
+            return result;
+        }
         VDS_LOGV("dequeueBuffer(%s): buffers[%d]=%p fmt=%d usage=%#x",
                 dbgSourceStr(source), pslot, mProducerBuffers[pslot].get(),
                 mProducerBuffers[pslot]->getPixelFormat(),
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 1b86204..63bc257 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1095,7 +1095,8 @@
 
         Reject r(mDrawingState, getCurrentState(), recomputeVisibleRegions);
 
-        status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r);
+        status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r,
+                mFlinger->mPrimaryDispSync);
         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.
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a346520..7bd8d38 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2371,6 +2371,15 @@
     result.append(SyncFeatures::getInstance().toString());
     result.append("\n");
 
+    colorizer.bold(result);
+    result.append("DispSync configuration: ");
+    colorizer.reset(result);
+    result.appendFormat("app phase %"PRId64" ns, sf phase %"PRId64" ns, "
+            "present offset %d ns (refresh %"PRId64" ns)",
+        vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs, PRESENT_TIME_OFFSET_FROM_VSYNC_NS,
+        mHwc->getRefreshPeriod(HWC_DISPLAY_PRIMARY));
+    result.append("\n");
+
     /*
      * Dump the visible layer list
      */
@@ -2643,6 +2652,16 @@
                 repaintEverything();
                 return NO_ERROR;
             }
+            // This is an experimental interface
+            // Needs to be shifted to proper binder interface when we productize
+            case 1016: {
+                mPrimaryDispSync.setLowPowerMode(true);
+                return NO_ERROR;
+            }
+            case 1017: {
+                mPrimaryDispSync.setLowPowerMode(false);
+                return NO_ERROR;
+            }
         }
     }
     return err;
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
index a412543..7de6ac4 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
@@ -29,7 +29,8 @@
 
 // ---------------------------------------------------------------------------
 
-status_t SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter)
+status_t SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter,
+        const DispSync& dispSync)
 {
     ATRACE_CALL();
     ALOGV("updateTexImage");
@@ -51,7 +52,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, computeExpectedPresent());
+    err = acquireBufferLocked(&item, computeExpectedPresent(dispSync));
     if (err != NO_ERROR) {
         if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
             err = NO_ERROR;
@@ -128,35 +129,41 @@
 // 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()
+// need to take the offset between actual-present and reported-vsync
+// into account.
+//
+// If the system is configured without a DispSync phase offset for the app,
+// we also want to throw in a bit of padding to avoid edge cases where we
+// just barely miss.  We want to do it here, not in every app.  A major
+// source of trouble is the app's use of the display's ideal refresh time
+// (via Display.getRefreshRate()), which could be off of the actual refresh
+// by a few percent, with the error multiplied by the number of frames
+// between now and when the buffer should be displayed.
+//
+// If the refresh reported to the app has a phase offset, we shouldn't need
+// to tweak anything here.
+nsecs_t SurfaceFlingerConsumer::computeExpectedPresent(const DispSync& dispSync)
 {
-    // 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;
+    // Assume that whatever we submit now will appear right after the flip.
+    // For a smart panel this might be 1.  This is expressed in frames,
+    // rather than time, because we expect to have a constant frame delay
+    // regardless of the refresh rate.
+    const uint32_t hwcLatency = 0;
 
-    // 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;
+    // Ask DispSync when the next refresh will be (CLOCK_MONOTONIC).
+    const nsecs_t nextRefresh = dispSync.computeNextRefresh(hwcLatency);
 
-    // Total it up.
-    return prevVsync + hwcLatency * vsyncPeriod + extraPadding;
+    // The DispSync time is already adjusted for the difference between
+    // vsync and reported-vsync (PRESENT_TIME_OFFSET_FROM_VSYNC_NS), so
+    // we don't need to factor that in here.  Pad a little to avoid
+    // weird effects if apps might be requesting times right on the edge.
+    nsecs_t extraPadding = 0;
+    if (VSYNC_EVENT_PHASE_OFFSET_NS == 0) {
+        extraPadding = 1000000;        // 1ms (6% of 60Hz)
+    }
+
+    return nextRefresh + extraPadding;
 }
 
 void SurfaceFlingerConsumer::setContentsChangedListener(
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.h b/services/surfaceflinger/SurfaceFlingerConsumer.h
index 0f1bf35..ed307c2 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.h
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.h
@@ -17,6 +17,7 @@
 #ifndef ANDROID_SURFACEFLINGERCONSUMER_H
 #define ANDROID_SURFACEFLINGERCONSUMER_H
 
+#include "DispSync.h"
 #include <gui/GLConsumer.h>
 
 namespace android {
@@ -33,7 +34,8 @@
 
     SurfaceFlingerConsumer(const sp<IGraphicBufferConsumer>& consumer,
             uint32_t tex)
-        : GLConsumer(consumer, tex, GLConsumer::TEXTURE_EXTERNAL, false)
+        : GLConsumer(consumer, tex, GLConsumer::TEXTURE_EXTERNAL, false),
+          mTransformToDisplayInverse(false)
     {}
 
     class BufferRejecter {
@@ -51,7 +53,7 @@
     // reject the newly acquired buffer.  Unlike the GLConsumer version,
     // this does not guarantee that the buffer has been bound to the GL
     // texture.
-    status_t updateTexImage(BufferRejecter* rejecter);
+    status_t updateTexImage(BufferRejecter* rejecter, const DispSync& dispSync);
 
     // See GLConsumer::bindTextureImageLocked().
     status_t bindTextureImage();
@@ -66,7 +68,7 @@
     sp<NativeHandle> getSidebandStream() const;
 
 private:
-    nsecs_t computeExpectedPresent();
+    nsecs_t computeExpectedPresent(const DispSync& dispSync);
 
     virtual void onSidebandStreamChanged();