Merge "Create primary profile file together with app data folders" into nyc-dev
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 613f9df..1add346 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -77,6 +77,7 @@
 /* Can accomodate a tombstone number up to 9999. */
 #define TOMBSTONE_MAX_LEN (sizeof(TOMBSTONE_FILE_PREFIX) + 4)
 #define NUM_TOMBSTONES  10
+#define WLUTIL "/vendor/xbin/wlutil"
 
 typedef struct {
   char name[TOMBSTONE_MAX_LEN];
@@ -798,6 +799,7 @@
 
     run_command("ARP CACHE", 10, "ip", "-4", "neigh", "show", NULL);
     run_command("IPv6 ND CACHE", 10, "ip", "-6", "neigh", "show", NULL);
+    run_command("MULTICAST ADDRESSES", 10, "ip", "maddr", NULL);
 
     run_command("IPTABLES", 10, SU_PATH, "root", "iptables", "-L", "-nvx", NULL);
     run_command("IP6TABLES", 10, SU_PATH, "root", "ip6tables", "-L", "-nvx", NULL);
@@ -811,13 +813,13 @@
 
 #ifdef FWDUMP_bcmdhd
     run_command("ND OFFLOAD TABLE", 5,
-            SU_PATH, "root", "wlutil", "nd_hostip", NULL);
+            SU_PATH, "root", WLUTIL, "nd_hostip", NULL);
 
     run_command("DUMP WIFI INTERNAL COUNTERS (1)", 20,
-            SU_PATH, "root", "wlutil", "counters", NULL);
+            SU_PATH, "root", WLUTIL, "counters", NULL);
 
     run_command("ND OFFLOAD STATUS (1)", 5,
-            SU_PATH, "root", "wlutil", "nd_status", NULL);
+            SU_PATH, "root", WLUTIL, "nd_status", NULL);
 
 #endif
     dump_file("INTERRUPTS (1)", "/proc/interrupts");
@@ -829,10 +831,10 @@
             SU_PATH, "root", "dhdutil", "-i", "wlan0", "dump", NULL);
 
     run_command("DUMP WIFI INTERNAL COUNTERS (2)", 20,
-            SU_PATH, "root", "wlutil", "counters", NULL);
+            SU_PATH, "root", WLUTIL, "counters", NULL);
 
     run_command("ND OFFLOAD STATUS (2)", 5,
-            SU_PATH, "root", "wlutil", "nd_status", NULL);
+            SU_PATH, "root", WLUTIL, "nd_status", NULL);
 #endif
     dump_file("INTERRUPTS (2)", "/proc/interrupts");
 
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index 7ae664d..c0c91da 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -29,6 +29,7 @@
 #include <unistd.h>
 
 #include <android-base/stringprintf.h>
+#include <android-base/strings.h>
 #include <android-base/logging.h>
 #include <android-base/unique_fd.h>
 #include <cutils/fs.h>
@@ -1091,7 +1092,7 @@
 static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_IO = 3;
 static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING = 4;
 
-static void run_profman(const std::vector<fd_t>& profiles_fd, fd_t reference_profile_fd) {
+static void run_profman_merge(const std::vector<fd_t>& profiles_fd, fd_t reference_profile_fd) {
     static const size_t MAX_INT_LEN = 32;
     static const char* PROFMAN_BIN = "/system/bin/profman";
 
@@ -1139,13 +1140,13 @@
         return false;
     }
 
-    ALOGV("PROFMAN: --- BEGIN '%s' ---\n", pkgname);
+    ALOGV("PROFMAN (MERGE): --- BEGIN '%s' ---\n", pkgname);
 
     pid_t pid = fork();
     if (pid == 0) {
         /* child -- drop privileges before continuing */
         drop_capabilities(uid);
-        run_profman(profiles_fd, reference_profile_fd);
+        run_profman_merge(profiles_fd, reference_profile_fd);
         exit(68);   /* only get here on exec failure */
     }
     /* parent */
@@ -1205,6 +1206,110 @@
     return need_to_compile;
 }
 
+static void run_profman_dump(const std::vector<fd_t>& profile_fds,
+                             fd_t reference_profile_fd,
+                             const std::vector<std::string>& code_locations,
+                             const std::vector<fd_t>& code_location_fds,
+                             fd_t output_fd) {
+    static const char* PROFMAN_BIN = "/system/bin/profman";
+    const bool has_reference_profile = (reference_profile_fd != -1);
+    // program name
+    // --dump-only
+    // --dump-output-to-fd=<output_fd>
+    // (optionally, --reference-profile-file-fd=<reference_profile_fd>)
+    const size_t fixed_args = (has_reference_profile ? 4 : 3);
+    // Fixed arguments, profiles, code paths, code path fds, and final NULL.
+    const size_t argc = fixed_args + profile_fds.size() + code_locations.size() +
+        code_location_fds.size() + 1;
+    const char **argv = new const char*[argc];
+    int i = 0;
+    argv[i++] = PROFMAN_BIN;
+    argv[i++] = "--dump-only";
+    std::string dump_output = StringPrintf("--dump-output-to-fd=%d", output_fd);
+    argv[i++] = dump_output.c_str();
+    if (has_reference_profile) {
+        std::string reference =
+            StringPrintf("--reference-profile-file-fd=%d", reference_profile_fd);
+        argv[i++] = reference.c_str();
+    }
+    for (fd_t profile_fd : profile_fds) {
+        std::string profile_arg = StringPrintf("--profile-file-fd=%d", profile_fd);
+        argv[i++] = strdup(profile_arg.c_str());
+    }
+    for (const std::string& code_location : code_locations) {
+        std::string path_str = StringPrintf("--code-location=%s", code_location.c_str());
+        argv[i++] = strdup(path_str.c_str());
+    }
+    for (fd_t code_location_fd : code_location_fds) {
+        std::string fd_str = StringPrintf("--code-location-fd=%d", code_location_fd);
+        argv[i++] = strdup(fd_str.c_str());
+    }
+    argv[i] = NULL;
+    assert(i == argc - 1);
+
+    execv(PROFMAN_BIN, (char * const *)argv);
+    ALOGE("execv(%s) failed: %s\n", PROFMAN_BIN, strerror(errno));
+    exit(68);   /* only get here on exec failure */
+}
+
+// Dumps the contents of a profile file, using pkgname's dex files for pretty
+// printing the result.
+bool dump_profile(uid_t uid, const char* pkgname, const char* code_path_string) {
+    std::vector<fd_t> profile_fds;
+    fd_t reference_profile_fd = -1;
+    std::string out_file_name = StringPrintf("/data/misc/profman/%s.txt", pkgname);
+
+    ALOGV("PROFMAN (DUMP): --- BEGIN '%s' ---\n", pkgname);
+
+    open_profile_files(uid, pkgname, &profile_fds, &reference_profile_fd);
+
+    const bool has_reference_profile = (reference_profile_fd != -1);
+    const bool has_profiles = !profile_fds.empty();
+
+    if (!has_reference_profile && !has_profiles) {
+        ALOGE("profman dump: no profiles to dump for '%s'", pkgname);
+        return false;
+    }
+
+    fd_t output_fd = open(out_file_name.c_str(), O_WRONLY | O_CREAT | O_NOFOLLOW);
+    if (fchmod(output_fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) {
+        ALOGE("installd cannot chmod '%s' dump_profile\n", out_file_name.c_str());
+        return false;
+    }
+    std::vector<std::string> code_locations = base::Split(code_path_string, ";");
+    std::vector<fd_t> code_location_fds;
+    for (const std::string& code_location : code_locations) {
+        fd_t code_location_fd = open(code_location.c_str(), O_RDONLY | O_NOFOLLOW);
+        if (code_location_fd == -1) {
+            ALOGE("installd cannot open '%s'\n", code_location.c_str());
+            return false;
+        }
+        code_location_fds.push_back(code_location_fd);
+    }
+
+    pid_t pid = fork();
+    if (pid == 0) {
+        /* child -- drop privileges before continuing */
+        drop_capabilities(uid);
+        run_profman_dump(profile_fds, reference_profile_fd, code_locations,
+                         code_location_fds, output_fd);
+        exit(68);   /* only get here on exec failure */
+    }
+    /* parent */
+    close_all_fds(code_location_fds, "code_location_fds");
+    close_all_fds(profile_fds, "profile_fds");
+    if (close(reference_profile_fd) != 0) {
+        PLOG(WARNING) << "Failed to close fd for reference profile";
+    }
+    int return_code = wait_child(pid);
+    if (!WIFEXITED(return_code)) {
+        LOG(WARNING) << "profman failed for package " << pkgname << ": "
+                << return_code;
+        return false;
+    }
+    return true;
+}
+
 static void trim_extension(char* path) {
   // Trim the extension.
   int pos = strlen(path);
diff --git a/cmds/installd/commands.h b/cmds/installd/commands.h
index 41cc209..7a42c5c 100644
--- a/cmds/installd/commands.h
+++ b/cmds/installd/commands.h
@@ -54,6 +54,8 @@
 
 bool merge_profiles(uid_t uid, const char *pkgname);
 
+bool dump_profile(uid_t uid, const char *pkgname, const char *dex_files);
+
 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* compiler_filter,
            const char* volume_uuid, const char* shared_libraries);
diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp
index e8fce91..061359e 100644
--- a/cmds/installd/installd.cpp
+++ b/cmds/installd/installd.cpp
@@ -282,6 +282,19 @@
     return 0;
 }
 
+static int do_dump_profiles(char **arg, char reply[REPLY_MAX])
+{
+    uid_t uid = static_cast<uid_t>(atoi(arg[0]));
+    const char* pkgname = arg[1];
+    const char* dex_files = arg[2];
+    if (dump_profile(uid, pkgname, dex_files)) {
+        strncpy(reply, "true", REPLY_MAX);
+    } else {
+        strncpy(reply, "false", REPLY_MAX);
+    }
+    return 0;
+}
+
 static int do_mark_boot_complete(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
 {
     return mark_boot_complete(arg[0] /* instruction set */);
@@ -428,6 +441,7 @@
     { "linkfile",             3, do_link_file },
     { "move_ab",              3, do_move_ab },
     { "merge_profiles",       2, do_merge_profiles },
+    { "dump_profiles",        3, do_dump_profiles },
 };
 
 static int readx(int s, void *_buf, int count)
diff --git a/cmds/servicemanager/binder.c b/cmds/servicemanager/binder.c
index 01218c9..27c461a 100644
--- a/cmds/servicemanager/binder.c
+++ b/cmds/servicemanager/binder.c
@@ -181,13 +181,18 @@
 
 void binder_send_reply(struct binder_state *bs,
                        struct binder_io *reply,
+                       binder_uintptr_t buffer_to_free,
                        int status)
 {
     struct {
+        uint32_t cmd_free;
+        binder_uintptr_t buffer;
         uint32_t cmd_reply;
         struct binder_transaction_data txn;
     } __attribute__((packed)) data;
 
+    data.cmd_free = BC_FREE_BUFFER;
+    data.buffer = buffer_to_free;
     data.cmd_reply = BC_REPLY;
     data.txn.target.ptr = 0;
     data.txn.cookie = 0;
@@ -250,9 +255,11 @@
                 bio_init(&reply, rdata, sizeof(rdata), 4);
                 bio_init_from_txn(&msg, txn);
                 res = func(bs, txn, &msg, &reply);
-                binder_free_buffer(bs, txn->data.ptr.buffer);
-                if ((txn->flags & TF_ONE_WAY) == 0)
-                    binder_send_reply(bs, &reply, res);
+                if (txn->flags & TF_ONE_WAY) {
+                    binder_free_buffer(bs, txn->data.ptr.buffer);
+                } else {
+                    binder_send_reply(bs, &reply, txn->data.ptr.buffer, res);
+                }
             }
             ptr += sizeof(*txn);
             break;
diff --git a/services/inputflinger/InputWindow.cpp b/services/inputflinger/InputWindow.cpp
index 1b913c5..d7b514b 100644
--- a/services/inputflinger/InputWindow.cpp
+++ b/services/inputflinger/InputWindow.cpp
@@ -46,7 +46,8 @@
             || layoutParamsType == TYPE_MAGNIFICATION_OVERLAY
             || layoutParamsType == TYPE_STATUS_BAR
             || layoutParamsType == TYPE_NAVIGATION_BAR
-            || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY;
+            || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY
+            || layoutParamsType == TYPE_DOCK_DIVIDER;
 }
 
 bool InputWindowInfo::supportsSplitTouch() const {
diff --git a/services/inputflinger/InputWindow.h b/services/inputflinger/InputWindow.h
index 0ac7fce..e243637 100644
--- a/services/inputflinger/InputWindow.h
+++ b/services/inputflinger/InputWindow.h
@@ -102,6 +102,7 @@
         TYPE_VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW+20,
         TYPE_BOOT_PROGRESS = FIRST_SYSTEM_WINDOW+21,
         TYPE_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW+22,
+        TYPE_DOCK_DIVIDER = FIRST_SYSTEM_WINDOW+34,
         LAST_SYSTEM_WINDOW      = 2999,
     };
 
diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp
index 8053668..b699fe9 100644
--- a/vulkan/libvulkan/api.cpp
+++ b/vulkan/libvulkan/api.cpp
@@ -602,6 +602,13 @@
         new (&layers_[layer_count_++]) ActiveLayer{GetLayerRef(l), {}};
     }
 
+    // this may happen when all layers are non-global ones
+    if (!layer_count_) {
+        get_instance_proc_addr_ = driver::GetInstanceProcAddr;
+        get_device_proc_addr_ = driver::GetDeviceProcAddr;
+        return VK_SUCCESS;
+    }
+
     SetupLayerLinks();
 
     return VK_SUCCESS;