Merge "Add support for max res decode" into lmp-dev
diff --git a/cmds/dumpstate/utils.c b/cmds/dumpstate/utils.c
index 85c353e..c8ee75e 100644
--- a/cmds/dumpstate/utils.c
+++ b/cmds/dumpstate/utils.c
@@ -296,7 +296,7 @@
 /* forks a command and waits for it to finish */
 int run_command(const char *title, int timeout_seconds, const char *command, ...) {
     fflush(stdout);
-    clock_t start = clock();
+    time_t start = time(NULL);
     pid_t pid = fork();
 
     /* handle error case */
@@ -340,19 +340,19 @@
     for (;;) {
         int status;
         pid_t p = waitpid(pid, &status, WNOHANG);
-        float elapsed = (float) (clock() - start) / CLOCKS_PER_SEC;
+        time_t elapsed = time(NULL) - start;
         if (p == pid) {
             if (WIFSIGNALED(status)) {
                 printf("*** %s: Killed by signal %d\n", command, WTERMSIG(status));
             } else if (WIFEXITED(status) && WEXITSTATUS(status) > 0) {
                 printf("*** %s: Exit code %d\n", command, WEXITSTATUS(status));
             }
-            if (title) printf("[%s: %.1fs elapsed]\n\n", command, elapsed);
+            if (title) printf("[%s: %ds elapsed]\n\n", command, (int) elapsed);
             return status;
         }
 
         if (timeout_seconds && elapsed > timeout_seconds) {
-            printf("*** %s: Timed out after %.1fs (killing pid %d)\n", command, elapsed, pid);
+            printf("*** %s: Timed out after %ds (killing pid %d)\n", command, (int) elapsed, pid);
             kill(pid, SIGTERM);
             return -1;
         }
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index 26edb5f..fc3972e 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -177,10 +177,6 @@
     return 0;
 }
 
-static int lib_dir_matcher(const char* file_name, const int is_dir) {
-  return is_dir && !strcmp(file_name, "lib");
-}
-
 int delete_user_data(const char *pkgname, userid_t userid)
 {
     char pkgdir[PKG_PATH_MAX];
@@ -188,8 +184,7 @@
     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_dir_matcher);
+    return delete_dir_contents(pkgdir, 0, NULL);
 }
 
 int make_user_data(const char *pkgname, uid_t uid, userid_t userid, const char* seinfo)
@@ -318,10 +313,16 @@
 int delete_code_cache(const char *pkgname, userid_t userid)
 {
     char codecachedir[PKG_PATH_MAX];
+    struct stat s;
 
     if (create_pkg_path(codecachedir, pkgname, CODE_CACHE_DIR_POSTFIX, userid))
         return -1;
 
+    /* it's okay if code cache is missing */
+    if (lstat(codecachedir, &s) == -1 && errno == ENOENT) {
+        return 0;
+    }
+
     /* delete contents, not the directory, no exceptions */
     return delete_dir_contents(codecachedir, 0, NULL);
 }
@@ -421,8 +422,14 @@
     char src_dex[PKG_PATH_MAX];
     char dst_dex[PKG_PATH_MAX];
 
-    if (validate_apk_path(src)) return -1;
-    if (validate_apk_path(dst)) return -1;
+    if (validate_apk_path(src)) {
+        ALOGE("invalid apk path '%s' (bad prefix)\n", src);
+        return -1;
+    }
+    if (validate_apk_path(dst)) {
+        ALOGE("invalid apk path '%s' (bad prefix)\n", 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;
@@ -440,12 +447,18 @@
 {
     char dex_path[PKG_PATH_MAX];
 
-    if (validate_apk_path(path)) return -1;
+    if (validate_apk_path(path) && validate_system_app_path(path)) {
+        ALOGE("invalid apk path '%s' (bad prefix)\n", 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) {
-        ALOGE("Couldn't unlink %s: %s\n", dex_path, strerror(errno));
+        if (errno != ENOENT) {
+            ALOGE("Couldn't unlink %s: %s\n", dex_path, strerror(errno));
+        }
         return -1;
     } else {
         return 0;
@@ -637,7 +650,7 @@
     const char* output_file_name, const char *pkgname, const char *instruction_set)
 {
     static const int MAX_INT_LEN = 12;      // '-'+10dig+'\0' -OR- 0x+8dig
-    static const unsigned int MAX_INSTRUCTION_SET_LEN = 32;
+    static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
 
     static const char* PATCHOAT_BIN = "/system/bin/patchoat";
     if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) {
@@ -674,8 +687,17 @@
 }
 
 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 *instruction_set)
+    const char* output_file_name, const char *pkgname, const char *instruction_set,
+    bool vm_safe_mode)
 {
+    static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
+
+    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 prop_buf[PROPERTY_VALUE_MAX];
     bool profiler = (property_get("dalvik.vm.profiler", prop_buf, "0") > 0) && (prop_buf[0] == '1');
 
@@ -689,6 +711,12 @@
     bool have_dex2oat_compiler_filter_flag = property_get("dalvik.vm.dex2oat-filter",
                                                           dex2oat_compiler_filter_flag, NULL) > 0;
 
+    char dex2oat_isa_features_key[PROPERTY_KEY_MAX];
+    sprintf(dex2oat_isa_features_key, "dalvik.vm.isa.%s.features", instruction_set);
+    char dex2oat_isa_features[PROPERTY_VALUE_MAX];
+    bool have_dex2oat_isa_features = property_get(dex2oat_isa_features_key,
+                                                  dex2oat_isa_features, NULL) > 0;
+
     char dex2oat_flags[PROPERTY_VALUE_MAX];
     bool have_dex2oat_flags = property_get("dalvik.vm.dex2oat-flags", dex2oat_flags, NULL) > 0;
     ALOGV("dalvik.vm.dex2oat-flags=%s\n", dex2oat_flags);
@@ -705,19 +733,13 @@
     static const char* RUNTIME_ARG = "--runtime-arg";
 
     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-location=") + PKG_PATH_MAX];
     char instruction_set_arg[strlen("--instruction-set=") + MAX_INSTRUCTION_SET_LEN];
+    char instruction_set_features_arg[strlen("--instruction-set-features=") + PROPERTY_VALUE_MAX];
     char profile_file_arg[strlen("--profile-file=") + PKG_PATH_MAX];
     char top_k_profile_threshold_arg[strlen("--top-k-profile-threshold=") + PROPERTY_VALUE_MAX];
     char dex2oat_Xms_arg[strlen("-Xms") + PROPERTY_VALUE_MAX];
@@ -729,6 +751,7 @@
     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);
+    sprintf(instruction_set_features_arg, "--instruction-set-features=%s", dex2oat_isa_features);
 
     bool have_profile_file = false;
     bool have_top_k_profile_threshold = false;
@@ -757,6 +780,9 @@
     if (skip_compilation) {
         strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=verify-none");
         have_dex2oat_compiler_filter_flag = true;
+    } else if (vm_safe_mode) {
+        strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=interpret-only");
+        have_dex2oat_compiler_filter_flag = true;
     } else if (have_dex2oat_compiler_filter_flag) {
         sprintf(dex2oat_compiler_filter_arg, "--compiler-filter=%s", dex2oat_compiler_filter_flag);
     }
@@ -764,6 +790,7 @@
     ALOGV("Running %s in=%s out=%s\n", DEX2OAT_BIN, input_file_name, output_file_name);
 
     char* argv[7  // program name, mandatory arguments and the final NULL
+               + (have_dex2oat_isa_features ? 1 : 0)
                + (have_profile_file ? 1 : 0)
                + (have_top_k_profile_threshold ? 1 : 0)
                + (have_dex2oat_Xms_flag ? 2 : 0)
@@ -777,6 +804,9 @@
     argv[i++] = oat_fd_arg;
     argv[i++] = oat_location_arg;
     argv[i++] = instruction_set_arg;
+    if (have_dex2oat_isa_features) {
+        argv[i++] = instruction_set_features_arg;
+    }
     if (have_profile_file) {
         argv[i++] = profile_file_arg;
     }
@@ -830,9 +860,9 @@
     }
 }
 
-int dexopt(const char *apk_path, uid_t uid, int is_public,
+int dexopt(const char *apk_path, uid_t uid, bool is_public,
            const char *pkgname, const char *instruction_set,
-           int is_patchoat)
+           bool vm_safe_mode, bool is_patchoat)
 {
     struct utimbuf ut;
     struct stat input_stat, dex_stat;
@@ -966,7 +996,8 @@
             if (is_patchoat) {
                 run_patchoat(input_fd, out_fd, input_file, out_path, pkgname, instruction_set);
             } else {
-                run_dex2oat(input_fd, out_fd, input_file, out_path, pkgname, instruction_set);
+                run_dex2oat(input_fd, out_fd, input_file, out_path, pkgname, instruction_set,
+                            vm_safe_mode);
             }
         } else {
             exit(69);   /* Unexpected persist.sys.dalvik.vm.lib value */
@@ -1524,50 +1555,3 @@
     return ret;
 }
 
-static int prune_dex_exclusion_predicate(const char *file_name, const int is_dir)
-{
-    // Exclude all directories. The top level command will be
-    // given a list of ISA specific directories that are assumed
-    // to be flat.
-    if (is_dir) {
-      return 1;
-    }
-
-
-    // Don't exclude regular files that start with the list
-    // of prefixes.
-    static const char data_app_prefix[] = "data@app@";
-    static const char data_priv_app_prefix[] = "data@priv-app@";
-    if (!strncmp(file_name, data_app_prefix, sizeof(data_app_prefix) - 1) ||
-        !strncmp(file_name, data_priv_app_prefix, sizeof(data_priv_app_prefix) - 1)) {
-      return 0;
-    }
-
-    // Exclude all regular files that don't start with the prefix "data@app@" or
-    // "data@priv-app@".
-    return 1;
-}
-
-int prune_dex_cache(const char* subdir) {
-    // "." is handled as a special case, and refers to
-    // DALVIK_CACHE_PREFIX (usually /data/dalvik-cache).
-    const bool is_dalvik_cache_root = !strcmp(subdir, ".");
-
-    // Don't allow the path to contain "." or ".." except for the
-    // special case above. This is much stricter than we need to be,
-    // but there's no good reason to support them.
-    if (strchr(subdir, '.' ) != NULL && !is_dalvik_cache_root) {
-        return -1;
-    }
-
-    if (!is_dalvik_cache_root) {
-        char full_path[PKG_PATH_MAX];
-        snprintf(full_path, sizeof(full_path), "%s%s", DALVIK_CACHE_PREFIX, subdir);
-        return delete_dir_contents(full_path, 0, &prune_dex_exclusion_predicate);
-    }
-
-
-    // When subdir == ".", clean the contents of the top level
-    // dalvik-cache directory.
-    return delete_dir_contents(DALVIK_CACHE_PREFIX, 0, &prune_dex_exclusion_predicate);
-}
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
index 746ce57..3078f20 100644
--- a/cmds/installd/installd.c
+++ b/cmds/installd/installd.c
@@ -38,8 +38,8 @@
 
 static int do_dexopt(char **arg, char reply[REPLY_MAX])
 {
-        /* apk_path, uid, is_public, pkgname, instruction_set */
-    return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3], arg[4], 0);
+    /* apk_path, uid, is_public, pkgname, instruction_set, vm_safe_mode, should_relocate */
+    return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3], arg[4], atoi(arg[5]), 0);
 }
 
 static int do_move_dex(char **arg, char reply[REPLY_MAX])
@@ -145,14 +145,9 @@
                              /* pkgName, seinfo, uid*/
 }
 
-static int do_prune_dex_cache(char **arg __attribute__((unused)),
-                              char reply[REPLY_MAX] __attribute__((unused)))
-{
-    return prune_dex_cache(arg[0] /* subdirectory name */);
-}
-
 static int do_patchoat(char **arg, char reply[REPLY_MAX]) {
-    return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3], arg[4], 1);
+    /* apk_path, uid, is_public, pkgname, instruction_set, vm_safe_mode, should_relocate */
+    return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3], arg[4], 0, 1);
 }
 
 struct cmdinfo {
@@ -164,7 +159,7 @@
 struct cmdinfo cmds[] = {
     { "ping",                 0, do_ping },
     { "install",              4, do_install },
-    { "dexopt",               5, do_dexopt },
+    { "dexopt",               6, do_dexopt },
     { "movedex",              3, do_move_dex },
     { "rmdex",                2, do_rm_dex },
     { "remove",               2, do_remove },
@@ -182,7 +177,6 @@
     { "rmuser",               1, do_rm_user },
     { "idmap",                3, do_idmap },
     { "restorecondata",       3, do_restorecon_data },
-    { "prunedexcache",        1, do_prune_dex_cache },
     { "patchoat",             5, do_patchoat },
 };
 
@@ -334,7 +328,7 @@
     }
 
     // Take note of the system and vendor directories.
-    android_system_dirs.count = 2;
+    android_system_dirs.count = 4;
 
     android_system_dirs.dirs = calloc(android_system_dirs.count, sizeof(dir_rec_t));
     if (android_system_dirs.dirs == NULL) {
@@ -342,22 +336,24 @@
         return -1;
     }
 
-    // system
-    if (get_path_from_env(&android_system_dirs.dirs[0], "ANDROID_ROOT") < 0) {
-        free_globals();
+    dir_rec_t android_root_dir;
+    if (get_path_from_env(&android_root_dir, "ANDROID_ROOT") < 0) {
+        ALOGE("Missing ANDROID_ROOT; aborting\n");
         return -1;
     }
 
-    // append "app/" to dirs[0]
-    char *system_app_path = build_string2(android_system_dirs.dirs[0].path, APP_SUBDIR);
-    android_system_dirs.dirs[0].path = system_app_path;
-    android_system_dirs.dirs[0].len = strlen(system_app_path);
+    android_system_dirs.dirs[0].path = build_string2(android_root_dir.path, APP_SUBDIR);
+    android_system_dirs.dirs[0].len = strlen(android_system_dirs.dirs[0].path);
 
-    // vendor
-    // TODO replace this with an environment variable (doesn't exist yet)
-    android_system_dirs.dirs[1].path = "/vendor/app/";
+    android_system_dirs.dirs[1].path = build_string2(android_root_dir.path, PRIV_APP_SUBDIR);
     android_system_dirs.dirs[1].len = strlen(android_system_dirs.dirs[1].path);
 
+    android_system_dirs.dirs[2].path = "/vendor/app/";
+    android_system_dirs.dirs[2].len = strlen(android_system_dirs.dirs[2].path);
+
+    android_system_dirs.dirs[3].path = "/oem/app/";
+    android_system_dirs.dirs[3].len = strlen(android_system_dirs.dirs[3].path);
+
     return 0;
 }
 
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index 9d420bd..a5cad45 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -62,6 +62,7 @@
 #define CODE_CACHE_DIR_POSTFIX "/code_cache"
 
 #define APP_SUBDIR             "app/" // sub-directory under ANDROID_DATA
+#define PRIV_APP_SUBDIR        "priv-app/" // sub-directory under ANDROID_DATA
 
 #define APP_LIB_SUBDIR         "app-lib/" // sub-directory under ANDROID_DATA
 
@@ -216,10 +217,9 @@
              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,
-           const char *instruction_set, int should_relocate);
+int dexopt(const char *apk_path, uid_t uid, bool is_public, const char *pkgName,
+           const char *instruction_set, bool vm_safe_mode, bool should_relocate);
 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);
 int restorecon_data();
-int prune_dex_cache(const char* subdir);
diff --git a/cmds/installd/utils.c b/cmds/installd/utils.c
index 8cd1168..60d20de 100644
--- a/cmds/installd/utils.c
+++ b/cmds/installd/utils.c
@@ -952,7 +952,6 @@
     } else if (!strncmp(path, android_asec_dir.path, android_asec_dir.len)) {
         dir = &android_asec_dir;
     } else {
-        ALOGE("invalid apk path '%s' (bad prefix)\n", path);
         return -1;
     }
 
diff --git a/data/etc/android.hardware.audio.output.xml b/data/etc/android.hardware.audio.output.xml
new file mode 100644
index 0000000..6ea1234
--- /dev/null
+++ b/data/etc/android.hardware.audio.output.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- This is the standard feature indicating audio output support of the device,
+     as specified in the CDD. ONLY devices that meet the CDD's requirements may
+     declare this feature. -->
+<permissions>
+    <feature name="android.hardware.audio.output" />
+</permissions>
diff --git a/data/etc/android.hardware.gamepad.xml b/data/etc/android.hardware.gamepad.xml
new file mode 100644
index 0000000..98d8d42
--- /dev/null
+++ b/data/etc/android.hardware.gamepad.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- This is the standard feature indicating that the device is a compatible gamepad or includes
+     one in the box. -->
+<permissions>
+    <feature name="android.hardware.gamepad" />
+</permissions>
+
diff --git a/data/etc/android.software.live_tv.xml b/data/etc/android.software.live_tv.xml
new file mode 100644
index 0000000..431acb0
--- /dev/null
+++ b/data/etc/android.software.live_tv.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<permissions>
+    <feature name="android.software.live_tv" />
+</permissions>
diff --git a/data/etc/handheld_core_hardware.xml b/data/etc/handheld_core_hardware.xml
index f18e4b1..7d70a5d 100644
--- a/data/etc/handheld_core_hardware.xml
+++ b/data/etc/handheld_core_hardware.xml
@@ -23,6 +23,7 @@
      devices.
 -->
 <permissions>
+    <feature name="andriod.hardware.audio.output" />
     <feature name="android.hardware.camera" />
     <feature name="android.hardware.location" />
     <feature name="android.hardware.location.network" />
diff --git a/data/etc/tablet_core_hardware.xml b/data/etc/tablet_core_hardware.xml
index 4db2e57..321b2af 100644
--- a/data/etc/tablet_core_hardware.xml
+++ b/data/etc/tablet_core_hardware.xml
@@ -23,6 +23,7 @@
      devices.
 -->
 <permissions>
+    <feature name="android.hardware.audio.output" />
     <feature name="android.hardware.location" />
     <feature name="android.hardware.location.network" />
     <feature name="android.hardware.sensor.compass" />
diff --git a/data/etc/wearable_core_hardware.xml b/data/etc/wearable_core_hardware.xml
index 09a064a..a9314d2 100644
--- a/data/etc/wearable_core_hardware.xml
+++ b/data/etc/wearable_core_hardware.xml
@@ -60,4 +60,6 @@
     <!-- Devices that have low-latency audio stacks suitable for apps like
          VoIP may include android.hardware.audio.low_latency.xml. ONLY apps
          that meet the requirements specified in the CDD may include this. -->
+    <!-- devices that have audio output capability as specified in the CDD must
+         also include android.hardware.audio.output.xml -->
 </permissions>
diff --git a/include/android/keycodes.h b/include/android/keycodes.h
index 813d411..75d0ab6 100644
--- a/include/android/keycodes.h
+++ b/include/android/keycodes.h
@@ -274,7 +274,35 @@
     AKEYCODE_12              = 228,
     AKEYCODE_LAST_CHANNEL    = 229,
     AKEYCODE_TV_DATA_SERVICE = 230,
-    AKEYCODE_VOICE_ASSIST    = 231
+    AKEYCODE_VOICE_ASSIST    = 231,
+    AKEYCODE_TV_RADIO_SERVICE = 232,
+    AKEYCODE_TV_TELETEXT     = 233,
+    AKEYCODE_TV_NUMBER_ENTRY = 234,
+    AKEYCODE_TV_TERRESTRIAL_ANALOG = 235,
+    AKEYCODE_TV_TERRESTRIAL_DIGITAL = 236,
+    AKEYCODE_TV_SATELLITE    = 237,
+    AKEYCODE_TV_SATELLITE_BS = 238,
+    AKEYCODE_TV_SATELLITE_CS = 239,
+    AKEYCODE_TV_SATELLITE_SERVICE = 240,
+    AKEYCODE_TV_NETWORK      = 241,
+    AKEYCODE_TV_ANTENNA_CABLE = 242,
+    AKEYCODE_TV_INPUT_HDMI_1 = 243,
+    AKEYCODE_TV_INPUT_HDMI_2 = 244,
+    AKEYCODE_TV_INPUT_HDMI_3 = 245,
+    AKEYCODE_TV_INPUT_HDMI_4 = 246,
+    AKEYCODE_TV_INPUT_COMPOSITE_1 = 247,
+    AKEYCODE_TV_INPUT_COMPOSITE_2 = 248,
+    AKEYCODE_TV_INPUT_COMPONENT_1 = 249,
+    AKEYCODE_TV_INPUT_COMPONENT_2 = 250,
+    AKEYCODE_TV_INPUT_VGA_1  = 251,
+    AKEYCODE_TV_AUDIO_DESCRIPTION = 252,
+    AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP = 253,
+    AKEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN = 254,
+    AKEYCODE_TV_ZOOM_MODE    = 255,
+    AKEYCODE_TV_CONTENTS_MENU = 256,
+    AKEYCODE_TV_MEDIA_CONTEXT_MENU = 257,
+    AKEYCODE_TV_TIMER_PROGRAMMING = 258,
+    AKEYCODE_HELP            = 259
 
     // 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/Binder.h b/include/binder/Binder.h
index ba3ac4b..86628a0 100644
--- a/include/binder/Binder.h
+++ b/include/binder/Binder.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_BINDER_H
 #define ANDROID_BINDER_H
 
+#include <stdatomic.h>
+#include <stdint.h>
 #include <binder/IBinder.h>
 
 // ---------------------------------------------------------------------------
@@ -69,7 +71,7 @@
 
     class Extras;
 
-            Extras*     mExtras;
+    atomic_uintptr_t    mExtras;  // should be atomic<Extras *>
             void*       mReserved0;
 };
 
diff --git a/include/gui/GLConsumer.h b/include/gui/GLConsumer.h
index 37530db..f91fe46 100644
--- a/include/gui/GLConsumer.h
+++ b/include/gui/GLConsumer.h
@@ -287,7 +287,9 @@
 
         // createIfNeeded creates an EGLImage if required (we haven't created
         // one yet, or the EGLDisplay or crop-rect has changed).
-        status_t createIfNeeded(EGLDisplay display, const Rect& cropRect);
+        status_t createIfNeeded(EGLDisplay display,
+                                const Rect& cropRect,
+                                bool forceCreate = false);
 
         // This calls glEGLImageTargetTexture2DOES to bind the image to the
         // texture in the specified texture target.
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h
index 9f1937b..742fc83 100644
--- a/include/gui/ISurfaceComposer.h
+++ b/include/gui/ISurfaceComposer.h
@@ -62,6 +62,13 @@
         eDisplayIdHdmi = 1
     };
 
+    enum Rotation {
+        eRotateNone = 0,
+        eRotate90   = 1,
+        eRotate180  = 2,
+        eRotate270  = 3
+    };
+
     /* create connection with surface flinger, requires
      * ACCESS_SURFACE_FLINGER permission
      */
@@ -130,7 +137,8 @@
             const sp<IGraphicBufferProducer>& producer,
             Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
             uint32_t minLayerZ, uint32_t maxLayerZ,
-            bool useIdentityTransform) = 0;
+            bool useIdentityTransform,
+            Rotation rotation = eRotateNone) = 0;
 
     /* Clears the frame statistics for animations.
      *
diff --git a/include/gui/SensorEventQueue.h b/include/gui/SensorEventQueue.h
index 019308d..5402f37 100644
--- a/include/gui/SensorEventQueue.h
+++ b/include/gui/SensorEventQueue.h
@@ -27,7 +27,7 @@
 #include <gui/BitTube.h>
 
 // ----------------------------------------------------------------------------
-#define WAKE_UP_SENSOR_EVENT_NEEDS_ACK (1U << 31)
+#define WAKE_UP_SENSOR_EVENT_NEEDS_ACK (1U << 30)
 struct ALooper;
 struct ASensorEvent;
 
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h
index c73ef70..4cbfc09 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -209,6 +209,10 @@
             Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
             uint32_t minLayerZ, uint32_t maxLayerZ,
             bool useIdentityTransform);
+    status_t update(const sp<IBinder>& display,
+            Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+            uint32_t minLayerZ, uint32_t maxLayerZ,
+            bool useIdentityTransform, uint32_t rotation);
 
     sp<CpuConsumer> getCpuConsumer() const;
 
diff --git a/include/input/InputEventLabels.h b/include/input/InputEventLabels.h
index 279ac40..df50237 100644
--- a/include/input/InputEventLabels.h
+++ b/include/input/InputEventLabels.h
@@ -271,6 +271,34 @@
     DEFINE_KEYCODE(LAST_CHANNEL),
     DEFINE_KEYCODE(TV_DATA_SERVICE),
     DEFINE_KEYCODE(VOICE_ASSIST),
+    DEFINE_KEYCODE(TV_RADIO_SERVICE),
+    DEFINE_KEYCODE(TV_TELETEXT),
+    DEFINE_KEYCODE(TV_NUMBER_ENTRY),
+    DEFINE_KEYCODE(TV_TERRESTRIAL_ANALOG),
+    DEFINE_KEYCODE(TV_TERRESTRIAL_DIGITAL),
+    DEFINE_KEYCODE(TV_SATELLITE),
+    DEFINE_KEYCODE(TV_SATELLITE_BS),
+    DEFINE_KEYCODE(TV_SATELLITE_CS),
+    DEFINE_KEYCODE(TV_SATELLITE_SERVICE),
+    DEFINE_KEYCODE(TV_NETWORK),
+    DEFINE_KEYCODE(TV_ANTENNA_CABLE),
+    DEFINE_KEYCODE(TV_INPUT_HDMI_1),
+    DEFINE_KEYCODE(TV_INPUT_HDMI_2),
+    DEFINE_KEYCODE(TV_INPUT_HDMI_3),
+    DEFINE_KEYCODE(TV_INPUT_HDMI_4),
+    DEFINE_KEYCODE(TV_INPUT_COMPOSITE_1),
+    DEFINE_KEYCODE(TV_INPUT_COMPOSITE_2),
+    DEFINE_KEYCODE(TV_INPUT_COMPONENT_1),
+    DEFINE_KEYCODE(TV_INPUT_COMPONENT_2),
+    DEFINE_KEYCODE(TV_INPUT_VGA_1),
+    DEFINE_KEYCODE(TV_AUDIO_DESCRIPTION),
+    DEFINE_KEYCODE(TV_AUDIO_DESCRIPTION_MIX_UP),
+    DEFINE_KEYCODE(TV_AUDIO_DESCRIPTION_MIX_DOWN),
+    DEFINE_KEYCODE(TV_ZOOM_MODE),
+    DEFINE_KEYCODE(TV_CONTENTS_MENU),
+    DEFINE_KEYCODE(TV_MEDIA_CONTEXT_MENU),
+    DEFINE_KEYCODE(TV_TIMER_PROGRAMMING),
+    DEFINE_KEYCODE(HELP),
 
     { NULL, 0 }
 };
diff --git a/include/powermanager/IPowerManager.h b/include/powermanager/IPowerManager.h
index 511797a..91ecc5a 100644
--- a/include/powermanager/IPowerManager.h
+++ b/include/powermanager/IPowerManager.h
@@ -31,12 +31,15 @@
 public:
     DECLARE_META_INTERFACE(PowerManager);
 
+    // FIXME remove the bool isOneWay parameters as they are not oneway in the .aidl
     virtual status_t acquireWakeLock(int flags, const sp<IBinder>& lock, const String16& tag,
-            const String16& packageName) = 0;
+            const String16& packageName, bool isOneWay = false) = 0;
     virtual status_t acquireWakeLockWithUid(int flags, const sp<IBinder>& lock, const String16& tag,
-            const String16& packageName, int uid) = 0;
-    virtual status_t releaseWakeLock(const sp<IBinder>& lock, int flags) = 0;
-    virtual status_t updateWakeLockUids(const sp<IBinder>& lock, int len, const int *uids) = 0;
+            const String16& packageName, int uid, bool isOneWay = false) = 0;
+    virtual status_t releaseWakeLock(const sp<IBinder>& lock, int flags, bool isOneWay = false) = 0;
+    virtual status_t updateWakeLockUids(const sp<IBinder>& lock, int len, const int *uids,
+            bool isOneWay = false) = 0;
+    // oneway in the .aidl
     virtual status_t powerHint(int hintId, int data) = 0;
 };
 
diff --git a/include/ui/mat4.h b/include/ui/mat4.h
index d9647cc..4fd1eff 100644
--- a/include/ui/mat4.h
+++ b/include/ui/mat4.h
@@ -322,6 +322,7 @@
         r[ 1] =  xy*nc + zs;    r[ 5] = y*y*nc +  c;    r[ 9] =  yz*nc - xs;
         r[ 2] =  zx*nc - ys;    r[ 6] =  yz*nc + xs;    r[10] = z*z*nc +  c;
     }
+    return rotation;
 }
 
 // ----------------------------------------------------------------------------------------
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index 71e62ab..2554351 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -16,7 +16,7 @@
 
 #include <binder/Binder.h>
 
-#include <utils/Atomic.h>
+#include <stdatomic.h>
 #include <utils/misc.h>
 #include <binder/BpBinder.h>
 #include <binder/IInterface.h>
@@ -71,8 +71,8 @@
 // ---------------------------------------------------------------------------
 
 BBinder::BBinder()
-    : mExtras(NULL)
 {
+    atomic_init(&mExtras, 0);
 }
 
 bool BBinder::isBinderAlive() const
@@ -139,19 +139,19 @@
     const void* objectID, void* object, void* cleanupCookie,
     object_cleanup_func func)
 {
-    Extras* e = mExtras;
+    Extras* e = reinterpret_cast<Extras*>(
+                    atomic_load_explicit(&mExtras, memory_order_acquire));
 
     if (!e) {
         e = new Extras;
-#ifdef __LP64__
-        if (android_atomic_release_cas64(0, reinterpret_cast<int64_t>(e),
-                reinterpret_cast<volatile int64_t*>(&mExtras)) != 0) {
-#else
-        if (android_atomic_cmpxchg(0, reinterpret_cast<int32_t>(e),
-                reinterpret_cast<volatile int32_t*>(&mExtras)) != 0) {
-#endif
+        uintptr_t expected = 0;
+        if (!atomic_compare_exchange_strong_explicit(
+                                        &mExtras, &expected,
+                                        reinterpret_cast<uintptr_t>(e),
+                                        memory_order_release,
+                                        memory_order_acquire)) {
             delete e;
-            e = mExtras;
+            e = reinterpret_cast<Extras*>(expected);  // Filled in by CAS
         }
         if (e == 0) return; // out of memory
     }
@@ -162,7 +162,8 @@
 
 void* BBinder::findObject(const void* objectID) const
 {
-    Extras* e = mExtras;
+    Extras* e = reinterpret_cast<Extras*>(
+                    atomic_load_explicit(&mExtras, memory_order_acquire));
     if (!e) return NULL;
 
     AutoMutex _l(e->mLock);
@@ -171,7 +172,8 @@
 
 void BBinder::detachObject(const void* objectID)
 {
-    Extras* e = mExtras;
+    Extras* e = reinterpret_cast<Extras*>(
+                    atomic_load_explicit(&mExtras, memory_order_acquire));
     if (!e) return;
 
     AutoMutex _l(e->mLock);
@@ -185,7 +187,9 @@
 
 BBinder::~BBinder()
 {
-    if (mExtras) delete mExtras;
+    Extras* e = reinterpret_cast<Extras*>(
+                    atomic_load_explicit(&mExtras, memory_order_relaxed));
+    if (e) delete e;
 }
 
 
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 939c4a9..ccafe81 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -462,24 +462,37 @@
     }
 
     status_t err = mCurrentTextureImage->createIfNeeded(mEglDisplay,
-                                                      mCurrentCrop);
-
+                                                        mCurrentCrop);
     if (err != NO_ERROR) {
         ST_LOGW("bindTextureImage: can't create image on display=%p slot=%d",
                 mEglDisplay, mCurrentTexture);
         return UNKNOWN_ERROR;
     }
-
     mCurrentTextureImage->bindToTextureTarget(mTexTarget);
 
-    while ((error = glGetError()) != GL_NO_ERROR) {
-        ST_LOGE("bindTextureImage: error binding external image: %#04x", error);
-        return UNKNOWN_ERROR;
+    // In the rare case that the display is terminated and then initialized
+    // again, we can't detect that the display changed (it didn't), but the
+    // image is invalid. In this case, repeat the exact same steps while
+    // forcing the creation of a new image.
+    if ((error = glGetError()) != GL_NO_ERROR) {
+        glBindTexture(mTexTarget, mTexName);
+        status_t err = mCurrentTextureImage->createIfNeeded(mEglDisplay,
+                                                            mCurrentCrop,
+                                                            true);
+        if (err != NO_ERROR) {
+            ST_LOGW("bindTextureImage: can't create image on display=%p slot=%d",
+                    mEglDisplay, mCurrentTexture);
+            return UNKNOWN_ERROR;
+        }
+        mCurrentTextureImage->bindToTextureTarget(mTexTarget);
+        if ((error = glGetError()) != GL_NO_ERROR) {
+            ST_LOGE("bindTextureImage: error binding external image: %#04x", error);
+            return UNKNOWN_ERROR;
+        }
     }
 
     // Wait for the new buffer to be ready.
     return doGLFenceWaitLocked();
-
 }
 
 status_t GLConsumer::checkAndUpdateEglStateLocked(bool contextCheck) {
@@ -1056,12 +1069,13 @@
 }
 
 status_t GLConsumer::EglImage::createIfNeeded(EGLDisplay eglDisplay,
-                                              const Rect& cropRect) {
+                                              const Rect& cropRect,
+                                              bool forceCreation) {
     // If there's an image and it's no longer valid, destroy it.
     bool haveImage = mEglImage != EGL_NO_IMAGE_KHR;
     bool displayInvalid = mEglDisplay != eglDisplay;
     bool cropInvalid = hasEglAndroidImageCrop() && mCropRect != cropRect;
-    if (haveImage && (displayInvalid || cropInvalid)) {
+    if (haveImage && (displayInvalid || cropInvalid || forceCreation)) {
         if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
            ALOGE("createIfNeeded: eglDestroyImageKHR failed");
         }
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 4680168..4d65c56 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -106,7 +106,8 @@
             const sp<IGraphicBufferProducer>& producer,
             Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
             uint32_t minLayerZ, uint32_t maxLayerZ,
-            bool useIdentityTransform)
+            bool useIdentityTransform,
+            ISurfaceComposer::Rotation rotation)
     {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
@@ -118,6 +119,7 @@
         data.writeInt32(minLayerZ);
         data.writeInt32(maxLayerZ);
         data.writeInt32(static_cast<int32_t>(useIdentityTransform));
+        data.writeInt32(static_cast<int32_t>(rotation));
         remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply);
         return reply.readInt32();
     }
@@ -329,10 +331,12 @@
             uint32_t minLayerZ = data.readInt32();
             uint32_t maxLayerZ = data.readInt32();
             bool useIdentityTransform = static_cast<bool>(data.readInt32());
+            uint32_t rotation = data.readInt32();
 
             status_t res = captureScreen(display, producer,
                     sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
-                    useIdentityTransform);
+                    useIdentityTransform,
+                    static_cast<ISurfaceComposer::Rotation>(rotation));
             reply->writeInt32(res);
             return NO_ERROR;
         }
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 6e13207..6446926 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -717,7 +717,7 @@
 status_t ScreenshotClient::update(const sp<IBinder>& display,
         Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
         uint32_t minLayerZ, uint32_t maxLayerZ,
-        bool useIdentityTransform) {
+        bool useIdentityTransform, uint32_t rotation) {
     sp<ISurfaceComposer> s(ComposerService::getComposerService());
     if (s == NULL) return NO_INIT;
     sp<CpuConsumer> cpuConsumer = getCpuConsumer();
@@ -729,7 +729,8 @@
     }
 
     status_t err = s->captureScreen(display, mProducer, sourceCrop,
-            reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform);
+            reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform,
+            static_cast<ISurfaceComposer::Rotation>(rotation));
 
     if (err == NO_ERROR) {
         err = mCpuConsumer->lockNextBuffer(&mBuffer);
@@ -740,16 +741,25 @@
     return err;
 }
 
+status_t ScreenshotClient::update(const sp<IBinder>& display,
+        Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+        uint32_t minLayerZ, uint32_t maxLayerZ,
+        bool useIdentityTransform) {
+
+    return ScreenshotClient::update(display, sourceCrop, reqWidth, reqHeight,
+            minLayerZ, maxLayerZ, useIdentityTransform, ISurfaceComposer::eRotateNone);
+}
+
 status_t ScreenshotClient::update(const sp<IBinder>& display, Rect sourceCrop,
         bool useIdentityTransform) {
     return ScreenshotClient::update(display, sourceCrop, 0, 0, 0, -1UL,
-            useIdentityTransform);
+            useIdentityTransform, ISurfaceComposer::eRotateNone);
 }
 
 status_t ScreenshotClient::update(const sp<IBinder>& display, Rect sourceCrop,
         uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform) {
     return ScreenshotClient::update(display, sourceCrop, reqWidth, reqHeight,
-            0, -1UL, useIdentityTransform);
+            0, -1UL, useIdentityTransform, ISurfaceComposer::eRotateNone);
 }
 
 void ScreenshotClient::release() {
diff --git a/libs/gui/tests/SurfaceTextureMultiContextGL_test.cpp b/libs/gui/tests/SurfaceTextureMultiContextGL_test.cpp
index 115a47d..1cd101e 100644
--- a/libs/gui/tests/SurfaceTextureMultiContextGL_test.cpp
+++ b/libs/gui/tests/SurfaceTextureMultiContextGL_test.cpp
@@ -386,4 +386,59 @@
     ASSERT_EQ(OK, mST->updateTexImage());
 }
 
+TEST_F(SurfaceTextureMultiContextGLTest,
+       AttachAfterDisplayTerminatedSucceeds) {
+    ASSERT_EQ(NO_ERROR, mST->setDefaultMaxBufferCount(2));
+
+    // produce two frames and consume them both on the primary context
+    ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
+    mFW->waitForFrame();
+    ASSERT_EQ(OK, mST->updateTexImage());
+
+    ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
+    mFW->waitForFrame();
+    ASSERT_EQ(OK, mST->updateTexImage());
+
+    // produce one more frame
+    ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
+
+    // Detach from the primary context.
+    ASSERT_EQ(OK, mST->releaseTexImage());
+    ASSERT_EQ(OK, mST->detachFromContext());
+
+    // Terminate and then initialize the display. All contexts, surfaces
+    // and images are invalid at this point.
+    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay);
+    EGLint majorVersion = 0;
+    EGLint minorVersion = 0;
+    EXPECT_TRUE(eglTerminate(display));
+    EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion));
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+    // The surface is invalid so create it again.
+    EGLint pbufferAttribs[] = {
+        EGL_WIDTH, 64,
+        EGL_HEIGHT, 64,
+        EGL_NONE };
+    mEglSurface = eglCreatePbufferSurface(mEglDisplay, mGlConfig,
+            pbufferAttribs);
+
+    // The second context is invalid so create it again.
+    mSecondEglContext = eglCreateContext(mEglDisplay, mGlConfig,
+            EGL_NO_CONTEXT, getContextAttribs());
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    ASSERT_NE(EGL_NO_CONTEXT, mSecondEglContext);
+
+    ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
+            mSecondEglContext));
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+    // Now attach to and consume final frame on secondary context.
+    ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID));
+    mFW->waitForFrame();
+    ASSERT_EQ(OK, mST->updateTexImage());
+}
+
+
 } // namespace android
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 8295c4c..8634e42 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -1815,7 +1815,7 @@
 // --- SwitchInputMapper ---
 
 SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
-        InputMapper(device), mUpdatedSwitchValues(0), mUpdatedSwitchMask(0) {
+        InputMapper(device), mSwitchValues(0), mUpdatedSwitchMask(0) {
 }
 
 SwitchInputMapper::~SwitchInputMapper() {
@@ -1841,7 +1841,9 @@
 void SwitchInputMapper::processSwitch(int32_t switchCode, int32_t switchValue) {
     if (switchCode >= 0 && switchCode < 32) {
         if (switchValue) {
-            mUpdatedSwitchValues |= 1 << switchCode;
+            mSwitchValues |= 1 << switchCode;
+        } else {
+            mSwitchValues &= ~(1 << switchCode);
         }
         mUpdatedSwitchMask |= 1 << switchCode;
     }
@@ -1849,10 +1851,10 @@
 
 void SwitchInputMapper::sync(nsecs_t when) {
     if (mUpdatedSwitchMask) {
-        NotifySwitchArgs args(when, 0, mUpdatedSwitchValues, mUpdatedSwitchMask);
+        uint32_t updatedSwitchValues = mSwitchValues & mUpdatedSwitchMask;
+        NotifySwitchArgs args(when, 0, updatedSwitchValues, mUpdatedSwitchMask);
         getListener()->notifySwitch(&args);
 
-        mUpdatedSwitchValues = 0;
         mUpdatedSwitchMask = 0;
     }
 }
@@ -1861,6 +1863,10 @@
     return getEventHub()->getSwitchState(getDeviceId(), switchCode);
 }
 
+void SwitchInputMapper::dump(String8& dump) {
+    dump.append(INDENT2 "Switch Input Mapper:\n");
+    dump.appendFormat(INDENT3 "SwitchValues: %x\n", mSwitchValues);
+}
 
 // --- VibratorInputMapper ---
 
diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h
index 9e36e35..c5896d4 100644
--- a/services/inputflinger/InputReader.h
+++ b/services/inputflinger/InputReader.h
@@ -999,9 +999,10 @@
     virtual void process(const RawEvent* rawEvent);
 
     virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
+    virtual void dump(String8& dump);
 
 private:
-    uint32_t mUpdatedSwitchValues;
+    uint32_t mSwitchValues;
     uint32_t mUpdatedSwitchMask;
 
     void processSwitch(int32_t switchCode, int32_t switchValue);
diff --git a/services/powermanager/IPowerManager.cpp b/services/powermanager/IPowerManager.cpp
index ee730d6..ec864ee 100644
--- a/services/powermanager/IPowerManager.cpp
+++ b/services/powermanager/IPowerManager.cpp
@@ -45,7 +45,7 @@
     }
 
     virtual status_t acquireWakeLock(int flags, const sp<IBinder>& lock, const String16& tag,
-            const String16& packageName)
+            const String16& packageName, bool isOneWay)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IPowerManager::getInterfaceDescriptor());
@@ -56,11 +56,12 @@
         data.writeString16(packageName);
         data.writeInt32(0); // no WorkSource
         data.writeString16(NULL, 0); // no history tag
-        return remote()->transact(ACQUIRE_WAKE_LOCK, data, &reply);
+        return remote()->transact(ACQUIRE_WAKE_LOCK, data, &reply,
+                isOneWay ? IBinder::FLAG_ONEWAY : 0);
     }
 
     virtual status_t acquireWakeLockWithUid(int flags, const sp<IBinder>& lock, const String16& tag,
-            const String16& packageName, int uid)
+            const String16& packageName, int uid, bool isOneWay)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IPowerManager::getInterfaceDescriptor());
@@ -70,26 +71,28 @@
         data.writeString16(tag);
         data.writeString16(packageName);
         data.writeInt32(uid); // uid to blame for the work
-        return remote()->transact(ACQUIRE_WAKE_LOCK_UID, data, &reply);
+        return remote()->transact(ACQUIRE_WAKE_LOCK_UID, data, &reply,
+                isOneWay ? IBinder::FLAG_ONEWAY : 0);
     }
 
-    virtual status_t releaseWakeLock(const sp<IBinder>& lock, int flags)
+    virtual status_t releaseWakeLock(const sp<IBinder>& lock, int flags, bool isOneWay)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IPowerManager::getInterfaceDescriptor());
         data.writeStrongBinder(lock);
         data.writeInt32(flags);
-        return remote()->transact(RELEASE_WAKE_LOCK, data, &reply);
+        return remote()->transact(RELEASE_WAKE_LOCK, data, &reply,
+                isOneWay ? IBinder::FLAG_ONEWAY : 0);
     }
 
-    virtual status_t updateWakeLockUids(const sp<IBinder>& lock, int len, const int *uids) {
+    virtual status_t updateWakeLockUids(const sp<IBinder>& lock, int len, const int *uids,
+            bool isOneWay) {
         Parcel data, reply;
         data.writeInterfaceToken(IPowerManager::getInterfaceDescriptor());
         data.writeStrongBinder(lock);
         data.writeInt32Array(len, uids);
-        // We don't really care too much if this succeeds (there's nothing we can do if it doesn't)
-        // but it should return ASAP
-        return remote()->transact(UPDATE_WAKE_LOCK_UIDS, data, &reply, IBinder::FLAG_ONEWAY);
+        return remote()->transact(UPDATE_WAKE_LOCK_UIDS, data, &reply,
+                isOneWay ? IBinder::FLAG_ONEWAY : 0);
     }
 
     virtual status_t powerHint(int hintId, int param)
@@ -98,6 +101,7 @@
         data.writeInterfaceToken(IPowerManager::getInterfaceDescriptor());
         data.writeInt32(hintId);
         data.writeInt32(param);
+        // This FLAG_ONEWAY is in the .aidl, so there is no way to disable it
         return remote()->transact(POWER_HINT, data, &reply, IBinder::FLAG_ONEWAY);
     }
 };
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 6c3144b..ef87e5c 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -807,29 +807,36 @@
     return sensor->setDelay(connection.get(), handle, ns);
 }
 
-status_t SensorService::flushSensor(const sp<SensorEventConnection>& connection,
-                                    int handle) {
+status_t SensorService::flushSensor(const sp<SensorEventConnection>& connection) {
     if (mInitCheck != NO_ERROR) return mInitCheck;
-    SensorInterface* sensor = mSensorMap.valueFor(handle);
-    if (sensor == NULL) {
-        return BAD_VALUE;
+    SensorDevice& dev(SensorDevice::getInstance());
+    const int halVersion = dev.getHalDeviceVersion();
+    status_t err(NO_ERROR);
+    Mutex::Autolock _l(mLock);
+    // Loop through all sensors for this connection and call flush on each of them.
+    for (size_t i = 0; i < connection->mSensorInfo.size(); ++i) {
+        const int handle = connection->mSensorInfo.keyAt(i);
+        SensorInterface* sensor = mSensorMap.valueFor(handle);
+        if (sensor->getSensor().getReportingMode() == AREPORTING_MODE_ONE_SHOT) {
+            ALOGE("flush called on a one-shot sensor");
+            err = INVALID_OPERATION;
+            continue;
+        }
+        SensorEventConnection::FlushInfo& flushInfo = connection->mSensorInfo.editValueFor(handle);
+        if (halVersion < SENSORS_DEVICE_API_VERSION_1_1 || isVirtualSensor(handle)) {
+            // For older devices just increment pending flush count which will send a trivial
+            // flush complete event.
+            flushInfo.mPendingFlushEventsToSend++;
+        } else {
+            status_t err_flush = sensor->flush(connection.get(), handle);
+            if (err_flush == NO_ERROR) {
+                SensorRecord* rec = mActiveSensors.valueFor(handle);
+                if (rec != NULL) rec->addPendingFlushConnection(connection);
+            }
+            err = (err_flush != NO_ERROR) ? err_flush : err;
+        }
     }
-
-    if (!verifyCanAccessSensor(sensor->getSensor(), "Tried flushing")) {
-        return BAD_VALUE;
-    }
-
-    if (sensor->getSensor().getReportingMode() == AREPORTING_MODE_ONE_SHOT) {
-        ALOGE("flush called on a one-shot sensor");
-        return INVALID_OPERATION;
-    }
-
-    status_t ret = sensor->flush(connection.get(), handle);
-    if (ret == NO_ERROR) {
-        SensorRecord* rec = mActiveSensors.valueFor(handle);
-        if (rec != NULL) rec->addPendingFlushConnection(connection);
-    }
-    return ret;
+    return err;
 }
 
 bool SensorService::canAccessSensor(const Sensor& sensor) {
@@ -1034,7 +1041,7 @@
 }
 
 status_t SensorService::SensorEventConnection::sendEvents(
-        sensors_event_t const* buffer, size_t numEvents,
+        sensors_event_t* buffer, size_t numEvents,
         sensors_event_t* scratch) {
     // filter out events not for this connection
     size_t count = 0;
@@ -1042,10 +1049,16 @@
     if (scratch) {
         size_t i=0;
         while (i<numEvents) {
+            // Flush complete events can be invalidated. If this event has been invalidated
+            // before, ignore and proceed to the next event.
+            if (buffer[i].flags & SENSOR_EVENT_INVALID_FLAG) {
+                ++i;
+                continue;
+            }
             int32_t sensor_handle = buffer[i].sensor;
             if (buffer[i].type == SENSOR_TYPE_META_DATA) {
                 ALOGD_IF(DEBUG_CONNECTIONS, "flush complete event sensor==%d ",
-                         buffer[i].meta_data.sensor);
+                        buffer[i].meta_data.sensor);
                 // Setting sensor_handle to the correct sensor to ensure the sensor events per connection are
                 // filtered correctly. buffer[i].sensor is zero for meta_data events.
                 sensor_handle = buffer[i].meta_data.sensor;
@@ -1065,9 +1078,12 @@
                 if (rec && rec->getFirstPendingFlushConnection() == this) {
                     rec->removeFirstPendingFlushConnection();
                     flushInfo.mFirstFlushPending = false;
-                    ++i;
+                    // Invalidate this flush_complete_event so that it cannot be used by other
+                    // connections.
+                    buffer[i].flags |= SENSOR_EVENT_INVALID_FLAG;
                     ALOGD_IF(DEBUG_CONNECTIONS, "First flush event for sensor==%d ",
-                                                    buffer[i].meta_data.sensor);
+                            buffer[i].meta_data.sensor);
+                    ++i;
                     continue;
                 }
             }
@@ -1080,13 +1096,20 @@
             }
 
             do {
+                if (buffer[i].flags & SENSOR_EVENT_INVALID_FLAG) {
+                    ++i;
+                    continue;
+                }
                 if (buffer[i].type == SENSOR_TYPE_META_DATA) {
-                   // Check if this connection has called flush() on this sensor. Only if
-                   // a flush() has been explicitly called, send a flush_complete_event.
-                   SensorService::SensorRecord *rec = mService->getSensorRecord(sensor_handle);
-                   if (rec && rec->getFirstPendingFlushConnection() == this) {
+                    // Check if this connection has called flush() on this sensor. Only if
+                    // a flush() has been explicitly called, send a flush_complete_event.
+                    SensorService::SensorRecord *rec = mService->getSensorRecord(sensor_handle);
+                    if (rec && rec->getFirstPendingFlushConnection() == this) {
                         rec->removeFirstPendingFlushConnection();
                         scratch[count++] = buffer[i];
+                        // Invalidate this flush_complete_event so that it cannot be used by
+                        // other connections.
+                        buffer[i].flags |= SENSOR_EVENT_INVALID_FLAG;
                     }
                     ++i;
                 } else {
@@ -1333,27 +1356,7 @@
 }
 
 status_t  SensorService::SensorEventConnection::flush() {
-    SensorDevice& dev(SensorDevice::getInstance());
-    const int halVersion = dev.getHalDeviceVersion();
-    Mutex::Autolock _l(mConnectionLock);
-    status_t err(NO_ERROR);
-    // Loop through all sensors for this connection and call flush on each of them.
-    for (size_t i = 0; i < mSensorInfo.size(); ++i) {
-        const int handle = mSensorInfo.keyAt(i);
-        FlushInfo& flushInfo = mSensorInfo.editValueFor(handle);
-        if (halVersion < SENSORS_DEVICE_API_VERSION_1_1 || mService->isVirtualSensor(handle)) {
-            // For older devices just increment pending flush count which will send a trivial
-            // flush complete event.
-            flushInfo.mPendingFlushEventsToSend++;
-        } else {
-            status_t err_flush = mService->flushSensor(this, handle);
-            if (err_flush != NO_ERROR) {
-                ALOGE("Flush error handle=%d %s", handle, strerror(-err_flush));
-            }
-            err = (err_flush != NO_ERROR) ? err_flush : err;
-        }
-    }
-    return err;
+    return  mService->flushSensor(this);
 }
 
 int SensorService::SensorEventConnection::handleEvent(int fd, int events, void* data) {
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 3717fcb..0887f28 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -45,6 +45,14 @@
 // For older HALs which don't support batching, use a smaller socket buffer size.
 #define SOCKET_BUFFER_SIZE_NON_BATCHED 4 * 1024
 
+// Flags for sensors_event_t.flag. Using only the most significant two bits for flags.
+// MSB is to invalidate a sensor_event (typically a flush_complete_event) so that
+// it won't be used by other connections.
+// MSB 2nd bit is used to indicate whether the event needs to be acknowledged or not.
+// This is typically used for WAKE_UP sensors. WAKE_UP_SENSOR_EVENT_NEEDS_ACK is defined
+// in SensorEveneQueue.h
+#define SENSOR_EVENT_INVALID_FLAG     (1U << 31)
+
 struct sensors_poll_device_t;
 struct sensors_module_t;
 
@@ -148,7 +156,7 @@
     public:
         SensorEventConnection(const sp<SensorService>& service, uid_t uid);
 
-        status_t sendEvents(sensors_event_t const* buffer, size_t count,
+        status_t sendEvents(sensors_event_t* buffer, size_t count,
                 sensors_event_t* scratch);
         bool hasSensor(int32_t handle) const;
         bool hasAnySensor() const;
@@ -229,7 +237,6 @@
     DefaultKeyedVector<int, SensorInterface*> mActiveVirtualSensors;
     SortedVector< wp<SensorEventConnection> > mActiveConnections;
     bool mWakeLockAcquired;
-
     // The size of this vector is constant, only the items are mutable
     KeyedVector<int32_t, sensors_event_t> mLastEventSeen;
 
@@ -239,7 +246,7 @@
                     nsecs_t samplingPeriodNs,  nsecs_t maxBatchReportLatencyNs, int reservedFlags);
     status_t disable(const sp<SensorEventConnection>& connection, int handle);
     status_t setEventRate(const sp<SensorEventConnection>& connection, int handle, nsecs_t ns);
-    status_t flushSensor(const sp<SensorEventConnection>& connection, int handle);
+    status_t flushSensor(const sp<SensorEventConnection>& connection);
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index bf42b77..564f974 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -288,7 +288,8 @@
     size_t w = mDisplayWidth;
     size_t h = mDisplayHeight;
     Rect sourceCrop(0, 0, w, h);
-    mFlinger->getRenderEngine().setViewportAndProjection(w, h, sourceCrop, h, false);
+    mFlinger->getRenderEngine().setViewportAndProjection(w, h, sourceCrop, h,
+        false, Transform::ROT_0);
 }
 
 // ----------------------------------------------------------------------------
diff --git a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp
index d1e324c..c2768f3 100644
--- a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp
@@ -21,6 +21,7 @@
 
 #include <utils/String8.h>
 #include <cutils/compiler.h>
+#include <gui/ISurfaceComposer.h>
 
 #include "GLES11RenderEngine.h"
 #include "Mesh.h"
@@ -74,7 +75,8 @@
 }
 
 void GLES11RenderEngine::setViewportAndProjection(
-        size_t vpw, size_t vph, Rect sourceCrop, size_t hwh, bool yswap) {
+        size_t vpw, size_t vph, Rect sourceCrop, size_t hwh, bool yswap,
+        Transform::orientation_flags rotation) {
     glViewport(0, 0, vpw, vph);
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
@@ -91,6 +93,23 @@
     } else {
         glOrthof(l, r, b, t, 0, 1);
     }
+
+    switch (rotation) {
+        case Transform::ROT_0:
+            break;
+        case Transform::ROT_90:
+            glRotatef(90, 0, 0, 1);
+            break;
+        case Transform::ROT_180:
+            glRotatef(180, 0, 0, 1);
+            break;
+        case Transform::ROT_270:
+            glRotatef(270, 0, 0, 1);
+            break;
+        default:
+            break;
+    }
+
     glMatrixMode(GL_MODELVIEW);
 }
 
diff --git a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h
index 1a94592..87eb3e4 100644
--- a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h
@@ -22,6 +22,7 @@
 #include <sys/types.h>
 
 #include <GLES/gl.h>
+#include <Transform.h>
 
 #include "RenderEngine.h"
 
@@ -50,7 +51,7 @@
 
     virtual void dump(String8& result);
     virtual void setViewportAndProjection(size_t vpw, size_t vph,
-            Rect sourceCrop, size_t hwh, bool yswap);
+            Rect sourceCrop, size_t hwh, bool yswap, Transform::orientation_flags rotation);
     virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, int alpha);
     virtual void setupDimLayerBlending(int alpha);
     virtual void setupLayerTexturing(const Texture& texture);
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
index 8c1f04e..8ebafbc 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
@@ -25,6 +25,8 @@
 #include <utils/Trace.h>
 
 #include <cutils/compiler.h>
+#include <gui/ISurfaceComposer.h>
+#include <math.h>
 
 #include "GLES20RenderEngine.h"
 #include "Program.h"
@@ -80,7 +82,8 @@
 }
 
 void GLES20RenderEngine::setViewportAndProjection(
-        size_t vpw, size_t vph, Rect sourceCrop, size_t hwh, bool yswap) {
+        size_t vpw, size_t vph, Rect sourceCrop, size_t hwh, bool yswap,
+        Transform::orientation_flags rotation) {
 
     size_t l = sourceCrop.left;
     size_t r = sourceCrop.right;
@@ -96,6 +99,24 @@
         m = mat4::ortho(l, r, b, t, 0, 1);
     }
 
+    // Apply custom rotation to the projection.
+    float rot90InRadians = 2.0f * static_cast<float>(M_PI) / 4.0f;
+    switch (rotation) {
+        case Transform::ROT_0:
+            break;
+        case Transform::ROT_90:
+            m = mat4::rotate(rot90InRadians, vec3(0,0,1)) * m;
+            break;
+        case Transform::ROT_180:
+            m = mat4::rotate(rot90InRadians * 2.0f, vec3(0,0,1)) * m;
+            break;
+        case Transform::ROT_270:
+            m = mat4::rotate(rot90InRadians * 3.0f, vec3(0,0,1)) * m;
+            break;
+        default:
+            break;
+    }
+
     glViewport(0, 0, vpw, vph);
     mState.setProjectionMatrix(m);
     mVpWidth = vpw;
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
index b6d32fc..3d6243e 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
@@ -22,6 +22,7 @@
 #include <sys/types.h>
 
 #include <GLES2/gl2.h>
+#include <Transform.h>
 
 #include "RenderEngine.h"
 #include "ProgramCache.h"
@@ -65,7 +66,7 @@
 
     virtual void dump(String8& result);
     virtual void setViewportAndProjection(size_t vpw, size_t vph,
-            Rect sourceCrop, size_t hwh, bool yswap);
+            Rect sourceCrop, size_t hwh, bool yswap, Transform::orientation_flags rotation);
     virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, int alpha);
     virtual void setupDimLayerBlending(int alpha);
     virtual void setupLayerTexturing(const Texture& texture);
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index a2d8242..acbff9b 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -24,6 +24,7 @@
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 #include <ui/mat4.h>
+#include <Transform.h>
 
 #define EGL_NO_CONFIG ((EGLConfig)0)
 
@@ -90,7 +91,7 @@
     // set-up
     virtual void checkErrors() const;
     virtual void setViewportAndProjection(size_t vpw, size_t vph,
-            Rect sourceCrop, size_t hwh, bool yswap) = 0;
+            Rect sourceCrop, size_t hwh, bool yswap, Transform::orientation_flags rotation) = 0;
     virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, int alpha) = 0;
     virtual void setupDimLayerBlending(int alpha) = 0;
     virtual void setupLayerTexturing(const Texture& texture) = 0;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 4070f03..043b075 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2938,7 +2938,7 @@
         const sp<IGraphicBufferProducer>& producer,
         Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
         uint32_t minLayerZ, uint32_t maxLayerZ,
-        bool useIdentityTransform) {
+        bool useIdentityTransform, ISurfaceComposer::Rotation rotation) {
 
     if (CC_UNLIKELY(display == 0))
         return BAD_VALUE;
@@ -2958,6 +2958,27 @@
         }
     }
 
+    // Convert to surfaceflinger's internal rotation type.
+    Transform::orientation_flags rotationFlags;
+    switch (rotation) {
+        case ISurfaceComposer::eRotateNone:
+            rotationFlags = Transform::ROT_0;
+            break;
+        case ISurfaceComposer::eRotate90:
+            rotationFlags = Transform::ROT_90;
+            break;
+        case ISurfaceComposer::eRotate180:
+            rotationFlags = Transform::ROT_180;
+            break;
+        case ISurfaceComposer::eRotate270:
+            rotationFlags = Transform::ROT_270;
+            break;
+        default:
+            rotationFlags = Transform::ROT_0;
+            ALOGE("Invalid rotation passed to captureScreen(): %d\n", rotation);
+            break;
+    }
+
     class MessageCaptureScreen : public MessageBase {
         SurfaceFlinger* flinger;
         sp<IBinder> display;
@@ -2966,6 +2987,7 @@
         uint32_t reqWidth, reqHeight;
         uint32_t minLayerZ,maxLayerZ;
         bool useIdentityTransform;
+        Transform::orientation_flags rotation;
         status_t result;
     public:
         MessageCaptureScreen(SurfaceFlinger* flinger,
@@ -2973,11 +2995,12 @@
                 const sp<IGraphicBufferProducer>& producer,
                 Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
                 uint32_t minLayerZ, uint32_t maxLayerZ,
-                bool useIdentityTransform)
+                bool useIdentityTransform, Transform::orientation_flags rotation)
             : flinger(flinger), display(display), producer(producer),
               sourceCrop(sourceCrop), reqWidth(reqWidth), reqHeight(reqHeight),
               minLayerZ(minLayerZ), maxLayerZ(maxLayerZ),
               useIdentityTransform(useIdentityTransform),
+              rotation(rotation),
               result(PERMISSION_DENIED)
         {
         }
@@ -2989,7 +3012,7 @@
             sp<const DisplayDevice> hw(flinger->getDisplayDevice(display));
             result = flinger->captureScreenImplLocked(hw, producer,
                     sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
-                    useIdentityTransform);
+                    useIdentityTransform, rotation);
             static_cast<GraphicProducerWrapper*>(producer->asBinder().get())->exit(result);
             return true;
         }
@@ -3012,7 +3035,7 @@
     sp<MessageBase> msg = new MessageCaptureScreen(this,
             display, IGraphicBufferProducer::asInterface( wrapper ),
             sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
-            useIdentityTransform);
+            useIdentityTransform, rotationFlags);
 
     status_t res = postMessageAsync(msg);
     if (res == NO_ERROR) {
@@ -3026,7 +3049,7 @@
         const sp<const DisplayDevice>& hw,
         Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
         uint32_t minLayerZ, uint32_t maxLayerZ,
-        bool yswap, bool useIdentityTransform)
+        bool yswap, bool useIdentityTransform, Transform::orientation_flags rotation)
 {
     ATRACE_CALL();
     RenderEngine& engine(getRenderEngine());
@@ -3061,7 +3084,8 @@
     engine.checkErrors();
 
     // set-up our viewport
-    engine.setViewportAndProjection(reqWidth, reqHeight, sourceCrop, hw_h, yswap);
+    engine.setViewportAndProjection(
+        reqWidth, reqHeight, sourceCrop, hw_h, yswap, rotation);
     engine.disableTexturing();
 
     // redraw the screen entirely...
@@ -3094,7 +3118,7 @@
         const sp<IGraphicBufferProducer>& producer,
         Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
         uint32_t minLayerZ, uint32_t maxLayerZ,
-        bool useIdentityTransform)
+        bool useIdentityTransform, Transform::orientation_flags rotation)
 {
     ATRACE_CALL();
 
@@ -3148,8 +3172,9 @@
                         // via an FBO, which means we didn't have to create
                         // an EGLSurface and therefore we're not
                         // dependent on the context's EGLConfig.
-                        renderScreenImplLocked(hw, sourceCrop, reqWidth, reqHeight,
-                                minLayerZ, maxLayerZ, true, useIdentityTransform);
+                        renderScreenImplLocked(
+                            hw, sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, true,
+                            useIdentityTransform, rotation);
 
                         // Attempt to create a sync khr object that can produce a sync point. If that
                         // isn't available, create a non-dupable sync object in the fallback path and
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index d5547b3..26f0acf 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -205,7 +205,7 @@
             const sp<IGraphicBufferProducer>& producer,
             Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
             uint32_t minLayerZ, uint32_t maxLayerZ,
-            bool useIdentityTransform);
+            bool useIdentityTransform, ISurfaceComposer::Rotation rotation);
     virtual status_t getDisplayConfigs(const sp<IBinder>& display,
             Vector<DisplayInfo>* configs);
     virtual int getActiveConfig(const sp<IBinder>& display);
@@ -313,14 +313,14 @@
             const sp<const DisplayDevice>& hw,
             Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
             uint32_t minLayerZ, uint32_t maxLayerZ,
-            bool yswap, bool useIdentityTransform);
+            bool yswap, bool useIdentityTransform, Transform::orientation_flags rotation);
 
     status_t captureScreenImplLocked(
             const sp<const DisplayDevice>& hw,
             const sp<IGraphicBufferProducer>& producer,
             Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
             uint32_t minLayerZ, uint32_t maxLayerZ,
-            bool useIdentityTransform);
+            bool useIdentityTransform, Transform::orientation_flags rotation);
 
     /* ------------------------------------------------------------------------
      * EGL