Merge "Add HardwarePropertiesManager constants to native layer."
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 258a99f..e809bac 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -951,6 +951,13 @@
         }
     }
 
+    /* read /proc/cmdline before dropping root */
+    FILE *cmdline = fopen("/proc/cmdline", "re");
+    if (cmdline) {
+        fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
+        fclose(cmdline);
+    }
+
     print_header();
 
     /* open the vibrator before dropping root */
@@ -983,13 +990,6 @@
         }
     }
 
-    /* read /proc/cmdline before dropping root */
-    FILE *cmdline = fopen("/proc/cmdline", "re");
-    if (cmdline) {
-        fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
-        fclose(cmdline);
-    }
-
     /* collect stack traces from Dalvik and native processes (needs root) */
     dump_traces_path = dump_traces();
 
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index 6b00429..fad5ce6 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -51,12 +51,15 @@
 
 static const char* kCpPath = "/system/bin/cp";
 
+#define MIN_RESTRICTED_HOME_SDK_VERSION 24 // > M
+
 int create_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags,
-        appid_t appid, const char* seinfo) {
+        appid_t appid, const char* seinfo, int target_sdk_version) {
     uid_t uid = multiuser_get_uid(userid, appid);
+    int target_mode = target_sdk_version >= MIN_RESTRICTED_HOME_SDK_VERSION ? 0700 : 0751;
     if (flags & FLAG_CE_STORAGE) {
         auto path = create_data_user_package_path(uuid, userid, pkgname);
-        if (fs_prepare_dir_strict(path.c_str(), 0751, uid, uid) != 0) {
+        if (fs_prepare_dir_strict(path.c_str(), target_mode, uid, uid) != 0) {
             PLOG(ERROR) << "Failed to prepare " << path;
             return -1;
         }
@@ -67,13 +70,15 @@
     }
     if (flags & FLAG_DE_STORAGE) {
         auto path = create_data_user_de_package_path(uuid, userid, pkgname);
-        if (fs_prepare_dir_strict(path.c_str(), 0751, uid, uid) == -1) {
+        if (fs_prepare_dir_strict(path.c_str(), target_mode, uid, uid) == -1) {
             PLOG(ERROR) << "Failed to prepare " << path;
-            return -1;
+            // TODO: include result once 25796509 is fixed
+            return 0;
         }
         if (selinux_android_setfilecon(path.c_str(), pkgname, seinfo, uid) < 0) {
             PLOG(ERROR) << "Failed to setfilecon " << path;
-            return -1;
+            // TODO: include result once 25796509 is fixed
+            return 0;
         }
     }
     return 0;
@@ -97,7 +102,8 @@
     if (flags & FLAG_DE_STORAGE) {
         auto path = create_data_user_de_package_path(uuid, userid, pkgname) + suffix;
         if (access(path.c_str(), F_OK) == 0) {
-            res |= delete_dir_contents(path);
+            // TODO: include result once 25796509 is fixed
+            delete_dir_contents(path);
         }
     }
     return res;
@@ -110,14 +116,15 @@
                 create_data_user_package_path(uuid, userid, pkgname));
     }
     if (flags & FLAG_DE_STORAGE) {
-        res |= delete_dir_contents_and_dir(
+        // TODO: include result once 25796509 is fixed
+        delete_dir_contents_and_dir(
                 create_data_user_de_package_path(uuid, userid, pkgname));
     }
     return res;
 }
 
 int move_complete_app(const char *from_uuid, const char *to_uuid, const char *package_name,
-        const char *data_app_name, appid_t appid, const char* seinfo) {
+        const char *data_app_name, appid_t appid, const char* seinfo, int target_sdk_version) {
     std::vector<userid_t> users = get_known_users(from_uuid);
 
     // Copy app
@@ -172,7 +179,7 @@
         }
 
         if (create_app_data(to_uuid, package_name, user, FLAG_CE_STORAGE | FLAG_DE_STORAGE,
-                appid, seinfo) != 0) {
+                appid, seinfo, target_sdk_version) != 0) {
             LOG(ERROR) << "Failed to create package target " << to;
             goto fail;
         }
@@ -243,7 +250,8 @@
     std::string media_path(create_data_media_path(uuid, userid));
 
     res |= delete_dir_contents_and_dir(data_path);
-    res |= delete_dir_contents_and_dir(data_de_path);
+    // TODO: include result once 25796509 is fixed
+    delete_dir_contents_and_dir(data_de_path);
     res |= delete_dir_contents_and_dir(media_path);
 
     // Config paths only exist on internal storage
@@ -592,8 +600,8 @@
 
 static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name,
     const char* output_file_name, int swap_fd, const char *instruction_set,
-    bool vm_safe_mode, bool debuggable, bool post_bootcomplete, bool use_jit)
-{
+    bool vm_safe_mode, bool debuggable, bool post_bootcomplete, bool extract_only,
+    const std::vector<int>& profile_files_fd, const std::vector<int>& reference_profile_files_fd) {
     static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
 
     if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) {
@@ -602,6 +610,12 @@
         return;
     }
 
+    if (profile_files_fd.size() != reference_profile_files_fd.size()) {
+        ALOGE("Invalid configuration of profile files: pf_size (%zu) != rpf_size (%zu)",
+              profile_files_fd.size(), reference_profile_files_fd.size());
+        return;
+    }
+
     char dex2oat_Xms_flag[kPropertyValueMax];
     bool have_dex2oat_Xms_flag = get_property("dalvik.vm.dex2oat-Xms", dex2oat_Xms_flag, NULL) > 0;
 
@@ -683,8 +697,6 @@
         sprintf(dex2oat_swap_fd, "--swap-fd=%d", swap_fd);
     }
 
-    // use the JIT if either it's specified as a dexopt flag or if the property is set
-    use_jit = use_jit || check_boolean_property("debug.usejit");
     if (have_dex2oat_Xms_flag) {
         sprintf(dex2oat_Xms_arg, "-Xms%s", dex2oat_Xms_flag);
     }
@@ -698,7 +710,7 @@
     } else if (vm_safe_mode) {
         strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=interpret-only");
         have_dex2oat_compiler_filter_flag = true;
-    } else if (use_jit) {
+    } else if (extract_only) {
         strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=verify-at-runtime");
         have_dex2oat_compiler_filter_flag = true;
     } else if (have_dex2oat_compiler_filter_flag) {
@@ -712,6 +724,17 @@
                 (get_property("dalvik.vm.always_debuggable", prop_buf, "0") > 0) &&
                 (prop_buf[0] == '1');
     }
+    std::vector<std::string> profile_file_args(profile_files_fd.size());
+    std::vector<std::string> reference_profile_file_args(profile_files_fd.size());
+    // "reference-profile-file-fd" is longer than "profile-file-fd" so we can
+    // use it to set the max length.
+    char profile_buf[strlen("--reference-profile-file-fd=") + MAX_INT_LEN];
+    for (size_t k = 0; k < profile_files_fd.size(); k++) {
+        sprintf(profile_buf, "--profile-file-fd=%d", profile_files_fd[k]);
+        profile_file_args[k].assign(profile_buf);
+        sprintf(profile_buf, "--reference-profile-file-fd=%d", reference_profile_files_fd[k]);
+        reference_profile_file_args[k].assign(profile_buf);
+    }
 
     ALOGV("Running %s in=%s out=%s\n", DEX2OAT_BIN, input_file_name, output_file_name);
 
@@ -726,7 +749,9 @@
                      + (have_dex2oat_relocation_skip_flag ? 2 : 0)
                      + (generate_debug_info ? 1 : 0)
                      + (debuggable ? 1 : 0)
-                     + dex2oat_flags_count];
+                     + dex2oat_flags_count
+                     + profile_files_fd.size()
+                     + reference_profile_files_fd.size()];
     int i = 0;
     argv[i++] = DEX2OAT_BIN;
     argv[i++] = zip_fd_arg;
@@ -770,6 +795,10 @@
         argv[i++] = RUNTIME_ARG;
         argv[i++] = dex2oat_norelocation;
     }
+    for (size_t k = 0; k < profile_file_args.size(); k++) {
+        argv[i++] = profile_file_args[k].c_str();
+        argv[i++] = reference_profile_file_args[k].c_str();
+    }
     // Do not add after dex2oat_flags, they should override others for debugging.
     argv[i] = NULL;
 
@@ -836,8 +865,108 @@
     }
 }
 
-int dexopt(const char *apk_path, uid_t uid, const char *pkgname, const char *instruction_set,
-           int dexopt_needed, const char* oat_dir, int dexopt_flags)
+constexpr const char* PROFILE_FILE_EXTENSION = ".prof";
+constexpr const char* REFERENCE_PROFILE_FILE_EXTENSION = ".prof.ref";
+
+static void close_all_fds(const std::vector<int>& fds, const char* description) {
+    for (size_t i = 0; i < fds.size(); i++) {
+        if (close(fds[i]) != 0) {
+            PLOG(WARNING) << "Failed to close fd for " << description << " at index " << i;
+        }
+    }
+}
+
+static int open_code_cache_for_user(userid_t user, const char* volume_uuid, const char* pkgname) {
+    std::string code_cache_path =
+        create_data_user_package_path(volume_uuid, user, pkgname) + CODE_CACHE_DIR_POSTFIX;
+
+    struct stat buffer;
+    // Check that the code cache exists. If not, return and don't log an error.
+    if (TEMP_FAILURE_RETRY(lstat(code_cache_path.c_str(), &buffer)) == -1) {
+        if (errno != ENOENT) {
+            PLOG(ERROR) << "Failed to lstat code_cache: " << code_cache_path;
+            return -1;
+        }
+    }
+
+    int code_cache_fd = open(code_cache_path.c_str(),
+            O_PATH | O_CLOEXEC | O_DIRECTORY | O_NOFOLLOW);
+    if (code_cache_fd < 0) {
+        PLOG(ERROR) << "Failed to open code_cache: " << code_cache_path;
+    }
+    return code_cache_fd;
+}
+
+// Keep profile paths in sync with ActivityThread.
+static void open_profile_files_for_user(uid_t uid, const char* pkgname, int code_cache_fd,
+            /*out*/ int* profile_fd, /*out*/ int* reference_profile_fd) {
+    *profile_fd = -1;
+    *reference_profile_fd = -1;
+    std::string profile_file(pkgname);
+    profile_file += PROFILE_FILE_EXTENSION;
+
+    // Check if the profile exists. If not, early return and don't log an error.
+    struct stat buffer;
+    if (TEMP_FAILURE_RETRY(fstatat(
+            code_cache_fd, profile_file.c_str(), &buffer, AT_SYMLINK_NOFOLLOW)) == -1) {
+        if (errno != ENOENT) {
+            PLOG(ERROR) << "Failed to fstatat profile file: " << profile_file;
+            return;
+        }
+    }
+
+    // Open in read-write to allow transfer of information from the current profile
+    // to the reference profile.
+    *profile_fd = openat(code_cache_fd, profile_file.c_str(), O_RDWR | O_NOFOLLOW);
+    if (*profile_fd < 0) {
+        PLOG(ERROR) << "Failed to open profile file: " << profile_file;
+        return;
+    }
+
+    std::string reference_profile(pkgname);
+    reference_profile += REFERENCE_PROFILE_FILE_EXTENSION;
+    // Give read-write permissions just for the user (changed with fchown after opening).
+    // We need write permission because dex2oat will update the reference profile files
+    // with the content of the corresponding current profile files.
+    *reference_profile_fd = openat(code_cache_fd, reference_profile.c_str(),
+            O_CREAT | O_RDWR | O_NOFOLLOW, S_IWUSR | S_IRUSR);
+    if (*reference_profile_fd < 0) {
+        close(*profile_fd);
+        return;
+    }
+    if (fchown(*reference_profile_fd, uid, uid) < 0) {
+        PLOG(ERROR) << "Cannot change reference profile file owner: " << reference_profile;
+        close(*profile_fd);
+        *profile_fd = -1;
+        *reference_profile_fd = -1;
+    }
+}
+
+static void open_profile_files(const char* volume_uuid, uid_t uid, const char* pkgname,
+            std::vector<int>* profile_fds, std::vector<int>* reference_profile_fds) {
+    std::vector<userid_t> users = get_known_users(volume_uuid);
+    for (auto user : users) {
+        int code_cache_fd  = open_code_cache_for_user(user, volume_uuid, pkgname);
+        if (code_cache_fd < 0) {
+            continue;
+        }
+        int profile_fd = -1;
+        int reference_profile_fd = -1;
+        open_profile_files_for_user(
+            uid, pkgname, code_cache_fd, &profile_fd, &reference_profile_fd);
+        close(code_cache_fd);
+
+        // Add to the lists only if both fds are valid.
+        if ((profile_fd >= 0) && (reference_profile_fd >= 0)) {
+            profile_fds->push_back(profile_fd);
+            reference_profile_fds->push_back(reference_profile_fd);
+        }
+    }
+}
+
+int dexopt(const char* apk_path, uid_t uid, const char* pkgname, const char* instruction_set,
+           int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* volume_uuid,
+           bool use_profiles)
 {
     struct utimbuf ut;
     struct stat input_stat;
@@ -850,7 +979,17 @@
     bool vm_safe_mode = (dexopt_flags & DEXOPT_SAFEMODE) != 0;
     bool debuggable = (dexopt_flags & DEXOPT_DEBUGGABLE) != 0;
     bool boot_complete = (dexopt_flags & DEXOPT_BOOTCOMPLETE) != 0;
-    bool use_jit = (dexopt_flags & DEXOPT_USEJIT) != 0;
+    bool extract_only = (dexopt_flags & DEXOPT_EXTRACTONLY) != 0;
+    std::vector<int> profile_files_fd;
+    std::vector<int> reference_profile_files_fd;
+    if (use_profiles) {
+        open_profile_files(volume_uuid, uid, pkgname,
+                &profile_files_fd, &reference_profile_files_fd);
+        if (profile_files_fd.empty()) {
+            // Skip profile guided compilation because no profiles were found.
+            return 0;
+        }
+    }
 
     if ((dexopt_flags & ~DEXOPT_MASK) != 0) {
         LOG_FATAL("dexopt flags contains unknown fields\n");
@@ -982,14 +1121,9 @@
             || dexopt_needed == DEXOPT_SELF_PATCHOAT_NEEDED) {
             run_patchoat(input_fd, out_fd, input_file, out_path, pkgname, instruction_set);
         } else if (dexopt_needed == DEXOPT_DEX2OAT_NEEDED) {
-            const char *input_file_name = strrchr(input_file, '/');
-            if (input_file_name == NULL) {
-                input_file_name = input_file;
-            } else {
-                input_file_name++;
-            }
-            run_dex2oat(input_fd, out_fd, input_file_name, out_path, swap_fd,
-                        instruction_set, vm_safe_mode, debuggable, boot_complete, use_jit);
+            run_dex2oat(input_fd, out_fd, input_file, out_path, swap_fd,
+                        instruction_set, vm_safe_mode, debuggable, boot_complete, extract_only,
+                        profile_files_fd, reference_profile_files_fd);
         } else {
             ALOGE("Invalid dexopt needed: %d\n", dexopt_needed);
             exit(73);
@@ -1014,6 +1148,10 @@
     if (swap_fd != -1) {
         close(swap_fd);
     }
+    if (use_profiles != 0) {
+        close_all_fds(profile_files_fd, "profile_files_fd");
+        close_all_fds(reference_profile_files_fd, "reference_profile_files_fd");
+    }
     return 0;
 
 fail:
@@ -1024,6 +1162,10 @@
     if (input_fd >= 0) {
         close(input_fd);
     }
+    if (use_profiles != 0) {
+        close_all_fds(profile_files_fd, "profile_files_fd");
+        close_all_fds(reference_profile_files_fd, "reference_profile_files_fd");
+    }
     return -1;
 }
 
diff --git a/cmds/installd/commands.h b/cmds/installd/commands.h
index 5510e7b..6dfc42b 100644
--- a/cmds/installd/commands.h
+++ b/cmds/installd/commands.h
@@ -29,14 +29,14 @@
 namespace installd {
 
 int create_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags,
-        appid_t appid, const char* seinfo);
+        appid_t appid, const char* seinfo, int target_sdk_version);
 int restorecon_app_data(const char* uuid, const char* pkgName, userid_t userid, int flags,
         appid_t appid, const char* seinfo);
 int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags);
 int destroy_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags);
 
 int move_complete_app(const char* from_uuid, const char *to_uuid, const char *package_name,
-        const char *data_app_name, appid_t appid, const char* seinfo);
+        const char *data_app_name, appid_t appid, const char* seinfo, int target_sdk_version);
 
 int get_app_size(const char *uuid, const char *pkgname, int userid, int flags,
         const char *apkpath, const char *libdirpath, const char *fwdlock_apkpath,
@@ -48,7 +48,8 @@
 int rm_dex(const char *path, const char *instruction_set);
 int free_cache(const char *uuid, int64_t free_size);
 int dexopt(const char *apk_path, uid_t uid, const char *pkgName, const char *instruction_set,
-           int dexopt_needed, const char* oat_dir, int dexopt_flags);
+           int dexopt_needed, const char* oat_dir, int dexopt_flags,
+           const char* volume_uuid, bool use_profiles);
 int mark_boot_complete(const char *instruction_set);
 int movefiles();
 int linklib(const char* uuid, const char* pkgname, const char* asecLibDir, int userId);
diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp
index 8542c4a..09f2c26 100644
--- a/cmds/installd/installd.cpp
+++ b/cmds/installd/installd.cpp
@@ -45,8 +45,6 @@
 #define TOKEN_MAX     16    /* max number of arguments in buffer */
 #define REPLY_MAX     256   /* largest reply allowed */
 
-#define DEBUG_FBE 0
-
 namespace android {
 namespace installd {
 
@@ -192,8 +190,9 @@
 
 static int do_create_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
     /* const char *uuid, const char *pkgname, userid_t userid, int flags,
-            appid_t appid, const char* seinfo */
-    return create_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atoi(arg[4]), arg[5]);
+            appid_t appid, const char* seinfo, int target_sdk_version */
+    return create_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]),
+                           atoi(arg[4]), arg[5], atoi(arg[6]));
 }
 
 static int do_restorecon_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
@@ -214,9 +213,10 @@
 
 static int do_dexopt(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
 {
-    /* apk_path, uid, pkgname, instruction_set, dexopt_needed, oat_dir, dexopt_flags */
+    /* apk_path, uid, pkgname, instruction_set, dexopt_needed, oat_dir, dexopt_flags, volume_uuid,
+            use_profiles */
     return dexopt(arg[0], atoi(arg[1]), arg[2], arg[3], atoi(arg[4]),
-                  arg[5], atoi(arg[6]));
+                  arg[5], atoi(arg[6]), parse_null(arg[7]), (atoi(arg[8]) == 0 ? false : true));
 }
 
 static int do_mark_boot_complete(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
@@ -258,8 +258,10 @@
 
 static int do_move_complete_app(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
     /* const char* from_uuid, const char *to_uuid, const char *package_name,
-            const char *data_app_name, appid_t appid, const char* seinfo */
-    return move_complete_app(parse_null(arg[0]), parse_null(arg[1]), arg[2], arg[3], atoi(arg[4]), arg[5]);
+            const char *data_app_name, appid_t appid, const char* seinfo,
+            int target_sdk_version */
+    return move_complete_app(parse_null(arg[0]), parse_null(arg[1]), arg[2], arg[3],
+                             atoi(arg[4]), arg[5], atoi(arg[6]));
 }
 
 static int do_mk_user_config(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
@@ -314,14 +316,14 @@
 struct cmdinfo cmds[] = {
     { "ping",                 0, do_ping },
 
-    { "create_app_data",      6, do_create_app_data },
+    { "create_app_data",      7, do_create_app_data },
     { "restorecon_app_data",  6, do_restorecon_app_data },
     { "clear_app_data",       4, do_clear_app_data },
     { "destroy_app_data",     4, do_destroy_app_data },
-    { "move_complete_app",    6, do_move_complete_app },
+    { "move_complete_app",    7, do_move_complete_app },
     { "get_app_size",         9, do_get_app_size },
 
-    { "dexopt",               7, do_dexopt },
+    { "dexopt",               9, do_dexopt },
     { "markbootcomplete",     1, do_mark_boot_complete },
     { "rmdex",                2, do_rm_dex },
     { "freecache",            2, do_free_cache },
@@ -465,139 +467,11 @@
     }
     int version = oldVersion;
 
-    // /data/user
-    char *user_data_dir = build_string2(android_data_dir.path, SECONDARY_USER_PREFIX);
-    // /data/data
-    char *legacy_data_dir = build_string2(android_data_dir.path, PRIMARY_USER_PREFIX);
-    // /data/user/0
-    char *primary_data_dir = build_string3(android_data_dir.path, SECONDARY_USER_PREFIX, "0");
-    if (!user_data_dir || !legacy_data_dir || !primary_data_dir) {
-        goto fail;
-    }
-
-    // Make the /data/user directory if necessary
-    if (access(user_data_dir, R_OK) < 0) {
-        if (mkdir(user_data_dir, 0711) < 0) {
-            goto fail;
-        }
-        if (chown(user_data_dir, AID_SYSTEM, AID_SYSTEM) < 0) {
-            goto fail;
-        }
-        if (chmod(user_data_dir, 0711) < 0) {
-            goto fail;
-        }
-    }
-    // Make the /data/user/0 symlink to /data/data if necessary
-    if (access(primary_data_dir, R_OK) < 0) {
-        if (symlink(legacy_data_dir, primary_data_dir)) {
-            goto fail;
-        }
-    }
-
-    if (version == 0) {
-        // Introducing multi-user, so migrate /data/media contents into /data/media/0
-        ALOGD("Upgrading /data/media for multi-user");
-
-        // Ensure /data/media
-        if (fs_prepare_dir(android_media_dir.path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
-            goto fail;
-        }
-
-        // /data/media.tmp
-        char media_tmp_dir[PATH_MAX];
-        snprintf(media_tmp_dir, PATH_MAX, "%smedia.tmp", android_data_dir.path);
-
-        // Only copy when upgrade not already in progress
-        if (access(media_tmp_dir, F_OK) == -1) {
-            if (rename(android_media_dir.path, media_tmp_dir) == -1) {
-                ALOGE("Failed to move legacy media path: %s", strerror(errno));
-                goto fail;
-            }
-        }
-
-        // Create /data/media again
-        if (fs_prepare_dir(android_media_dir.path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
-            goto fail;
-        }
-
-        if (selinux_android_restorecon(android_media_dir.path, 0)) {
-            goto fail;
-        }
-
-        // /data/media/0
-        char owner_media_dir[PATH_MAX];
-        snprintf(owner_media_dir, PATH_MAX, "%s0", android_media_dir.path);
-
-        // Move any owner data into place
-        if (access(media_tmp_dir, F_OK) == 0) {
-            if (rename(media_tmp_dir, owner_media_dir) == -1) {
-                ALOGE("Failed to move owner media path: %s", strerror(errno));
-                goto fail;
-            }
-        }
-
-        // Ensure media directories for any existing users
-        DIR *dir;
-        struct dirent *dirent;
-        char user_media_dir[PATH_MAX];
-
-        dir = opendir(user_data_dir);
-        if (dir != NULL) {
-            while ((dirent = readdir(dir))) {
-                if (dirent->d_type == DT_DIR) {
-                    const char *name = dirent->d_name;
-
-                    // skip "." and ".."
-                    if (name[0] == '.') {
-                        if (name[1] == 0) continue;
-                        if ((name[1] == '.') && (name[2] == 0)) continue;
-                    }
-
-                    // /data/media/<user_id>
-                    snprintf(user_media_dir, PATH_MAX, "%s%s", android_media_dir.path, name);
-                    if (fs_prepare_dir(user_media_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
-                        goto fail;
-                    }
-                }
-            }
-            closedir(dir);
-        }
-
-        version = 1;
-    }
-
-    // /data/media/obb
-    char media_obb_dir[PATH_MAX];
-    snprintf(media_obb_dir, PATH_MAX, "%sobb", android_media_dir.path);
-
-    if (version == 1) {
-        // Introducing /data/media/obb for sharing OBB across users; migrate
-        // any existing OBB files from owner.
-        ALOGD("Upgrading to shared /data/media/obb");
-
-        // /data/media/0/Android/obb
-        char owner_obb_path[PATH_MAX];
-        snprintf(owner_obb_path, PATH_MAX, "%s0/Android/obb", android_media_dir.path);
-
-        // Only move if target doesn't already exist
-        if (access(media_obb_dir, F_OK) != 0 && access(owner_obb_path, F_OK) == 0) {
-            if (rename(owner_obb_path, media_obb_dir) == -1) {
-                ALOGE("Failed to move OBB from owner: %s", strerror(errno));
-                goto fail;
-            }
-        }
-
+    if (version < 2) {
+        SLOGD("Assuming that device has multi-user storage layout; upgrade no longer supported");
         version = 2;
     }
 
-    if (ensure_media_user_dirs(nullptr, 0) == -1) {
-        ALOGE("Failed to setup media for user 0");
-        goto fail;
-    }
-    if (fs_prepare_dir(media_obb_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
-        goto fail;
-    }
-
     if (ensure_config_user_dirs(0) == -1) {
         ALOGE("Failed to setup misc for user 0");
         goto fail;
@@ -617,7 +491,7 @@
 
         DIR *dir;
         struct dirent *dirent;
-        dir = opendir(user_data_dir);
+        dir = opendir("/data/user");
         if (dir != NULL) {
             while ((dirent = readdir(dir))) {
                 const char *name = dirent->d_name;
@@ -679,9 +553,6 @@
     res = 0;
 
 fail:
-    free(user_data_dir);
-    free(legacy_data_dir);
-    free(primary_data_dir);
     return res;
 }
 
@@ -748,12 +619,6 @@
     }
     fcntl(lsocket, F_SETFD, FD_CLOEXEC);
 
-    // Perform all filesystem access as system so that FBE emulation mode
-    // can block access using chmod 000.
-#if DEBUG_FBE
-    setfsuid(AID_SYSTEM);
-#endif
-
     for (;;) {
         alen = sizeof(addr);
         s = accept(lsocket, &addr, &alen);
diff --git a/cmds/installd/installd_constants.h b/cmds/installd/installd_constants.h
index 220de9a..f128c26 100644
--- a/cmds/installd/installd_constants.h
+++ b/cmds/installd/installd_constants.h
@@ -75,7 +75,7 @@
 constexpr int DEXOPT_SAFEMODE     = 1 << 2;
 constexpr int DEXOPT_DEBUGGABLE   = 1 << 3;
 constexpr int DEXOPT_BOOTCOMPLETE = 1 << 4;
-constexpr int DEXOPT_USEJIT       = 1 << 5;
+constexpr int DEXOPT_EXTRACTONLY  = 1 << 5;
 
 /* all known values for dexopt flags */
 constexpr int DEXOPT_MASK =
@@ -83,7 +83,7 @@
     | DEXOPT_SAFEMODE
     | DEXOPT_DEBUGGABLE
     | DEXOPT_BOOTCOMPLETE
-    | DEXOPT_USEJIT;
+    | DEXOPT_EXTRACTONLY;
 
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
 
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 92a9565..d25bf71 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -1168,16 +1168,6 @@
     return result;
 }
 
-/* Ensure that /data/media directories are prepared for given user. */
-int ensure_media_user_dirs(const char* uuid, userid_t userid) {
-    std::string media_user_path(create_data_media_path(uuid, userid));
-    if (fs_prepare_dir(media_user_path.c_str(), 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
-        return -1;
-    }
-
-    return 0;
-}
-
 int ensure_config_user_dirs(userid_t userid) {
     char config_user_path[PATH_MAX];
 
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index 4d6b66e..2d9573e 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -135,7 +135,6 @@
 char *build_string3(const char *s1, const char *s2, const char *s3);
 
 int ensure_dir(const char* path, mode_t mode, uid_t uid, gid_t gid);
-int ensure_media_user_dirs(const char* uuid, userid_t userid);
 int ensure_config_user_dirs(userid_t userid);
 
 int wait_child(pid_t pid);
diff --git a/data/etc/android.hardware.nfc.hcef.xml b/data/etc/android.hardware.nfc.hcef.xml
new file mode 100644
index 0000000..0d03023
--- /dev/null
+++ b/data/etc/android.hardware.nfc.hcef.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- This feature indicates that the device supports host-based
+     NFC-F card emulation -->
+<permissions>
+    <feature name="android.hardware.nfc.hcef" />
+</permissions>
diff --git a/data/etc/android.hardware.wifi.nan.xml b/data/etc/android.hardware.wifi.nan.xml
new file mode 100644
index 0000000..e557610
--- /dev/null
+++ b/data/etc/android.hardware.wifi.nan.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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 includes WiFi NAN. -->
+<permissions>
+    <feature name="android.hardware.wifi.nan" />
+</permissions>
diff --git a/include/android/choreographer.h b/include/android/choreographer.h
new file mode 100644
index 0000000..0239e2f
--- /dev/null
+++ b/include/android/choreographer.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+/**
+ * @addtogroup Choreographer
+ * @{
+ */
+
+/**
+ * @file choreographer.h
+ */
+
+#ifndef ANDROID_CHOREOGRAPHER_H
+#define ANDROID_CHOREOGRAPHER_H
+
+__BEGIN_DECLS
+
+struct AChoreographer;
+typedef struct AChoreographer AChoreographer;
+
+/**
+ * Prototype of the function that is called when a new frame is being rendered.
+ * It's passed the time that the frame is being rendered as nanoseconds in the
+ * CLOCK_MONOTONIC time base, as well as the data pointer provided by the
+ * application that registered a callback. All callbacks that run as part of
+ * rendering a frame will observe the same frame time, so it should be used
+ * whenever events need to be synchronized (e.g. animations).
+ */
+typedef void (*AChoreographer_frameCallback)(long frameTimeNanos, void* data);
+
+/**
+ * Get the AChoreographer instance for the current thread. This must be called
+ * on an ALooper thread.
+ */
+AChoreographer* AChoreographer_getInstance();
+
+/**
+ * Post a callback to be run on the next frame. The data pointer provided will
+ * be passed to the callback function when it's called.
+ */
+void AChoreographer_postFrameCallback(AChoreographer* choreographer,
+                AChoreographer_frameCallback callback, void* data);
+/**
+ * Post a callback to be run on the frame following the specified delay. The
+ * data pointer provided will be passed to the callback function when it's
+ * called.
+ */
+void AChoreographer_postFrameCallbackDelayed(AChoreographer* choreographer,
+                AChoreographer_frameCallback callback, void* data, long delayMillis);
+__END_DECLS
+
+#endif // ANDROID_CHOREOGRAPHER_H
+
+/** @} */
diff --git a/include/android/input.h b/include/android/input.h
index fd9fa98..95d25d3 100644
--- a/include/android/input.h
+++ b/include/android/input.h
@@ -644,13 +644,6 @@
      */
     AMOTION_EVENT_AXIS_TILT = 25,
     /**
-     * Axis constant:  Generic scroll axis of a motion event.
-     *
-     * - This is used for scroll axis motion events that can't be classified as strictly
-     *   vertical or horizontal. The movement of a rotating scroller is an example of this.
-     */
-    AMOTION_EVENT_AXIS_SCROLL = 26,
-    /**
      * Axis constant: The movement of x position of a motion event.
      *
      * - For a mouse, reports a difference of x position between the previous position.
@@ -839,8 +832,6 @@
     AINPUT_SOURCE_TOUCH_NAVIGATION = 0x00200000 | AINPUT_SOURCE_CLASS_NONE,
     /** joystick */
     AINPUT_SOURCE_JOYSTICK = 0x01000000 | AINPUT_SOURCE_CLASS_JOYSTICK,
-    /** rotary encoder */
-    AINPUT_SOURCE_ROTARY_ENCODER = 0x00400000 | AINPUT_SOURCE_CLASS_NONE,
 
     /** any */
     AINPUT_SOURCE_ANY = 0xffffff00,
diff --git a/include/binder/IMediaResourceMonitor.h b/include/binder/IMediaResourceMonitor.h
new file mode 100644
index 0000000..b7b9c50
--- /dev/null
+++ b/include/binder/IMediaResourceMonitor.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_I_MEDIA_RESOURCE_MONITOR_H
+#define ANDROID_I_MEDIA_RESOURCE_MONITOR_H
+
+#include <binder/IInterface.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------
+
+class IMediaResourceMonitor : public IInterface {
+public:
+    DECLARE_META_INTERFACE(MediaResourceMonitor);
+
+    virtual void notifyResourceGranted(/*in*/ int32_t pid, /*in*/ const String16& type,
+            /*in*/ const String16& subType, /*in*/ int64_t value) = 0;
+
+    enum {
+        NOTIFY_RESOURCE_GRANTED = IBinder::FIRST_CALL_TRANSACTION,
+    };
+};
+
+// ----------------------------------------------------------------------
+
+class BnMediaResourceMonitor : public BnInterface<IMediaResourceMonitor> {
+public:
+    virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+            uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_I_MEDIA_RESOURCE_MONITOR_H
diff --git a/include/media/openmax/OMX_AsString.h b/include/media/openmax/OMX_AsString.h
index ae8430d..c3145c9 100644
--- a/include/media/openmax/OMX_AsString.h
+++ b/include/media/openmax/OMX_AsString.h
@@ -714,6 +714,7 @@
         case OMX_VIDEO_CodingVP8:        return "VP8";
         case OMX_VIDEO_CodingVP9:        return "VP9";
         case OMX_VIDEO_CodingHEVC:       return "HEVC";
+        case OMX_VIDEO_CodingDolbyVision:return "DolbyVision";
         default:                         return def;
     }
 }
diff --git a/include/media/openmax/OMX_Video.h b/include/media/openmax/OMX_Video.h
index decc410..ca85cf1 100644
--- a/include/media/openmax/OMX_Video.h
+++ b/include/media/openmax/OMX_Video.h
@@ -88,6 +88,7 @@
     OMX_VIDEO_CodingVP8,        /**< Google VP8, formerly known as On2 VP8 */
     OMX_VIDEO_CodingVP9,        /**< Google VP9 */
     OMX_VIDEO_CodingHEVC,       /**< ITU H.265/HEVC */
+    OMX_VIDEO_CodingDolbyVision,/**< Dolby Vision */
     OMX_VIDEO_CodingKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_VIDEO_CodingVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_VIDEO_CodingMax = 0x7FFFFFFF
diff --git a/libs/binder/Android.mk b/libs/binder/Android.mk
index 41bf618..14be920 100644
--- a/libs/binder/Android.mk
+++ b/libs/binder/Android.mk
@@ -23,6 +23,7 @@
     IAppOpsService.cpp \
     IBatteryStats.cpp \
     IInterface.cpp \
+    IMediaResourceMonitor.cpp \
     IMemory.cpp \
     IPCThreadState.cpp \
     IPermissionController.cpp \
diff --git a/libs/binder/IMediaResourceMonitor.cpp b/libs/binder/IMediaResourceMonitor.cpp
new file mode 100644
index 0000000..e8deb4a
--- /dev/null
+++ b/libs/binder/IMediaResourceMonitor.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <binder/IMediaResourceMonitor.h>
+#include <binder/Parcel.h>
+#include <utils/Errors.h>
+#include <sys/types.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------
+
+class BpMediaResourceMonitor : public BpInterface<IMediaResourceMonitor> {
+public:
+    BpMediaResourceMonitor(const sp<IBinder>& impl)
+        : BpInterface<IMediaResourceMonitor>(impl) {}
+
+    virtual void notifyResourceGranted(/*in*/ int32_t pid, /*in*/ const String16& type,
+            /*in*/ const String16& subType, /*in*/ int64_t value)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaResourceMonitor::getInterfaceDescriptor());
+        data.writeInt32(pid);
+        data.writeString16(type);
+        data.writeString16(subType);
+        data.writeInt64(value);
+        remote()->transact(NOTIFY_RESOURCE_GRANTED, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(MediaResourceMonitor, "android.media.IMediaResourceMonitor");
+
+// ----------------------------------------------------------------------
+
+status_t BnMediaResourceMonitor::onTransact( uint32_t code, const Parcel& data, Parcel* reply,
+        uint32_t flags) {
+    switch(code) {
+        case NOTIFY_RESOURCE_GRANTED: {
+            CHECK_INTERFACE(IMediaResourceMonitor, data, reply);
+            int32_t pid = data.readInt32();
+            const String16 type = data.readString16();
+            const String16 subType = data.readString16();
+            int64_t value = data.readInt64();
+            notifyResourceGranted(/*in*/ pid, /*in*/ type, /*in*/ subType, /*in*/ value);
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------
+
+}; // namespace android
diff --git a/libs/gui/IGraphicBufferConsumer.cpp b/libs/gui/IGraphicBufferConsumer.cpp
index d2f482e..a75569f 100644
--- a/libs/gui/IGraphicBufferConsumer.cpp
+++ b/libs/gui/IGraphicBufferConsumer.cpp
@@ -304,7 +304,7 @@
             CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
             sp<GraphicBuffer> buffer = new GraphicBuffer();
             data.read(*buffer.get());
-            int slot;
+            int slot = -1;
             int result = attachBuffer(&slot, buffer);
             reply->writeInt32(slot);
             reply->writeInt32(result);
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 0cca58d..2478601 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -466,6 +466,7 @@
             QueueBufferOutput* const output =
                     reinterpret_cast<QueueBufferOutput *>(
                             reply->writeInplace(sizeof(QueueBufferOutput)));
+            memset(output, 0, sizeof(QueueBufferOutput));
             status_t result = queueBuffer(buf, input, output);
             reply->writeInt32(result);
             return NO_ERROR;
diff --git a/services/inputflinger/EventHub.cpp b/services/inputflinger/EventHub.cpp
index 2a53dec..5859606 100644
--- a/services/inputflinger/EventHub.cpp
+++ b/services/inputflinger/EventHub.cpp
@@ -1191,15 +1191,6 @@
         device->classes |= INPUT_DEVICE_CLASS_CURSOR;
     }
 
-    // See if this is a rotary encoder type device.
-    String8 deviceType = String8();
-    if (device->configuration &&
-        device->configuration->tryGetProperty(String8("device.type"), deviceType)) {
-            if (!deviceType.compare(String8("rotaryEncoder"))) {
-                device->classes |= INPUT_DEVICE_CLASS_ROTARY_ENCODER;
-            }
-    }
-
     // See if this is a touch pad.
     // Is this a new modern multi-touch driver?
     if (test_bit(ABS_MT_POSITION_X, device->absBitmask)
diff --git a/services/inputflinger/EventHub.h b/services/inputflinger/EventHub.h
index 6869253..0f94c77 100644
--- a/services/inputflinger/EventHub.h
+++ b/services/inputflinger/EventHub.h
@@ -137,9 +137,6 @@
     /* The input device is an external stylus (has data we want to fuse with touch data). */
     INPUT_DEVICE_CLASS_EXTERNAL_STYLUS = 0x00000800,
 
-    /* The input device has a rotary encoder */
-    INPUT_DEVICE_CLASS_ROTARY_ENCODER = 0x00001000,
-
     /* The input device is virtual (not a real device, not part of UI configuration). */
     INPUT_DEVICE_CLASS_VIRTUAL       = 0x40000000,
 
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 8556c23..debd142 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -450,11 +450,6 @@
         device->addMapper(new SwitchInputMapper(device));
     }
 
-    // Scroll wheel-like devices.
-    if (classes & INPUT_DEVICE_CLASS_ROTARY_ENCODER) {
-        device->addMapper(new RotaryEncoderInputMapper(device));
-    }
-
     // Vibrator-like devices.
     if (classes & INPUT_DEVICE_CLASS_VIBRATOR) {
         device->addMapper(new VibratorInputMapper(device));
@@ -2735,103 +2730,6 @@
     }
 }
 
-// --- RotaryEncoderInputMapper ---
-
-RotaryEncoderInputMapper::RotaryEncoderInputMapper(InputDevice* device) :
-        InputMapper(device) {
-    mSource = AINPUT_SOURCE_ROTARY_ENCODER;
-}
-
-RotaryEncoderInputMapper::~RotaryEncoderInputMapper() {
-}
-
-uint32_t RotaryEncoderInputMapper::getSources() {
-    return mSource;
-}
-
-void RotaryEncoderInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
-    InputMapper::populateDeviceInfo(info);
-
-    if (mRotaryEncoderScrollAccumulator.haveRelativeVWheel()) {
-        float res = 0.0f;
-        if (!mDevice->getConfiguration().tryGetProperty(String8("device.res"), res)) {
-            ALOGW("Rotary Encoder device configuration file didn't specify resolution!\n");
-        }
-        if (!mDevice->getConfiguration().tryGetProperty(String8("device.scalingFactor"),
-            mScalingFactor)) {
-            ALOGW("Rotary Encoder device configuration file didn't specify scaling factor,"
-              "default to 1.0!\n");
-            mScalingFactor = 1.0f;
-        }
-        info->addMotionRange(AMOTION_EVENT_AXIS_SCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
-            res * mScalingFactor);
-    }
-}
-
-void RotaryEncoderInputMapper::dump(String8& dump) {
-    dump.append(INDENT2 "Rotary Encoder Input Mapper:\n");
-    dump.appendFormat(INDENT3 "HaveWheel: %s\n",
-            toString(mRotaryEncoderScrollAccumulator.haveRelativeVWheel()));
-}
-
-void RotaryEncoderInputMapper::configure(nsecs_t when,
-        const InputReaderConfiguration* config, uint32_t changes) {
-    InputMapper::configure(when, config, changes);
-    if (!changes) {
-        mRotaryEncoderScrollAccumulator.configure(getDevice());
-    }
-}
-
-void RotaryEncoderInputMapper::reset(nsecs_t when) {
-    mRotaryEncoderScrollAccumulator.reset(getDevice());
-
-    InputMapper::reset(when);
-}
-
-void RotaryEncoderInputMapper::process(const RawEvent* rawEvent) {
-    mRotaryEncoderScrollAccumulator.process(rawEvent);
-
-    if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
-        sync(rawEvent->when);
-    }
-}
-
-void RotaryEncoderInputMapper::sync(nsecs_t when) {
-    PointerCoords pointerCoords;
-    pointerCoords.clear();
-
-    PointerProperties pointerProperties;
-    pointerProperties.clear();
-    pointerProperties.id = 0;
-    pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
-
-    float scroll = mRotaryEncoderScrollAccumulator.getRelativeVWheel();
-    bool scrolled = scroll != 0;
-
-    // This is not a pointer, so it's not associated with a display.
-    int32_t displayId = ADISPLAY_ID_NONE;
-
-    // Moving the rotary encoder should wake the device (if specified).
-    uint32_t policyFlags = 0;
-    if (scrolled && getDevice()->isExternal()) {
-        policyFlags |= POLICY_FLAG_WAKE;
-    }
-
-    // Send motion event.
-    if (scrolled) {
-        int32_t metaState = mContext->getGlobalMetaState();
-        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_SCROLL, scroll * mScalingFactor);
-
-        NotifyMotionArgs scrollArgs(when, getDeviceId(), mSource, policyFlags,
-                AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, 0,
-                AMOTION_EVENT_EDGE_FLAG_NONE,
-                displayId, 1, &pointerProperties, &pointerCoords,
-                0, 0, 0);
-        getListener()->notifyMotion(&scrollArgs);
-    }
-
-    mRotaryEncoderScrollAccumulator.finishSync();
-}
 
 // --- TouchInputMapper ---
 
diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h
index e554e57..3a5c76f 100644
--- a/services/inputflinger/InputReader.h
+++ b/services/inputflinger/InputReader.h
@@ -1231,27 +1231,6 @@
 };
 
 
-class RotaryEncoderInputMapper : public InputMapper {
-public:
-    RotaryEncoderInputMapper(InputDevice* device);
-    virtual ~RotaryEncoderInputMapper();
-
-    virtual uint32_t getSources();
-    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
-    virtual void dump(String8& dump);
-    virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
-    virtual void reset(nsecs_t when);
-    virtual void process(const RawEvent* rawEvent);
-
-private:
-    CursorScrollAccumulator mRotaryEncoderScrollAccumulator;
-
-    int32_t mSource;
-    float mScalingFactor;
-
-    void sync(nsecs_t when);
-};
-
 class TouchInputMapper : public InputMapper {
 public:
     TouchInputMapper(InputDevice* device);
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 17ca10e..d70b069 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -124,6 +124,10 @@
 
 LOCAL_INIT_RC := surfaceflinger.rc
 
+ifneq ($(ENABLE_CPUSETS),)
+    LOCAL_CFLAGS += -DENABLE_CPUSETS
+endif
+
 LOCAL_SRC_FILES := \
     main_surfaceflinger.cpp
 
diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp
index ca81aaa..4cd7aeb 100644
--- a/services/surfaceflinger/main_surfaceflinger.cpp
+++ b/services/surfaceflinger/main_surfaceflinger.cpp
@@ -42,6 +42,13 @@
 
     set_sched_policy(0, SP_FOREGROUND);
 
+#ifdef ENABLE_CPUSETS
+    // Put most SurfaceFlinger threads in the system-background cpuset
+    // Keeps us from unnecessarily using big cores
+    // Do this after the binder thread pool init
+    set_cpuset_policy(0, SP_SYSTEM);
+#endif
+
     // initialize before clients can connect
     flinger->init();
 
diff --git a/services/surfaceflinger/surfaceflinger.rc b/services/surfaceflinger/surfaceflinger.rc
index 1d6e20f..2b4ea2a 100644
--- a/services/surfaceflinger/surfaceflinger.rc
+++ b/services/surfaceflinger/surfaceflinger.rc
@@ -3,4 +3,4 @@
     user system
     group graphics drmrpc readproc
     onrestart restart zygote
-    writepid /dev/cpuset/system-background/tasks /sys/fs/cgroup/stune/foreground/tasks
+    writepid /sys/fs/cgroup/stune/foreground/tasks