Merge "Revert "Remove incorrect android_atomic_...64 use.""
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index c6a2a0d..c23a9e8 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -20,13 +20,13 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/capability.h>
+#include <sys/prctl.h>
 #include <sys/resource.h>
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/wait.h>
 #include <unistd.h>
-#include <sys/capability.h>
-#include <sys/prctl.h>
 
 #include <cutils/properties.h>
 
@@ -43,6 +43,36 @@
 
 static char screenshot_path[PATH_MAX] = "";
 
+#define TOMBSTONE_DIR "/data/tombstones"
+#define TOMBSTONE_FILE_PREFIX TOMBSTONE_DIR "/tombstone_"
+/* Can accomodate a tombstone number up to 9999. */
+#define TOMBSTONE_MAX_LEN (sizeof(TOMBSTONE_FILE_PREFIX) + 4)
+#define NUM_TOMBSTONES  10
+
+typedef struct {
+  char name[TOMBSTONE_MAX_LEN];
+  int fd;
+} tombstone_data_t;
+
+static tombstone_data_t tombstone_data[NUM_TOMBSTONES];
+
+/* Get the fds of any tombstone that was modified in the last half an hour. */
+static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) {
+    time_t thirty_minutes_ago = time(NULL) - 60*30;
+    for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
+        snprintf(data[i].name, sizeof(data[i].name), "%s%02zu", TOMBSTONE_FILE_PREFIX, i);
+        int fd = open(data[i].name, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
+        struct stat st;
+        if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode) &&
+                (time_t) st.st_mtime >= thirty_minutes_ago) {
+            data[i].fd = fd;
+        } else {
+            close(fd);
+            data[i].fd = -1;
+        }
+    }
+}
+
 /* dumps the current system state to stdout */
 static void dumpstate() {
     time_t now = time(NULL);
@@ -116,7 +146,6 @@
     run_command("EVENT LOG", 20, "logcat", "-b", "events", "-v", "threadtime", "-d", "*:v", NULL);
     run_command("RADIO LOG", 20, "logcat", "-b", "radio", "-v", "threadtime", "-d", "*:v", NULL);
 
-
     /* show the traces we collected in main(), if that was done */
     if (dump_traces_path != NULL) {
         dump_file("VM TRACES JUST NOW", dump_traces_path);
@@ -128,10 +157,13 @@
     property_get("dalvik.vm.stack-trace-file", anr_traces_path, "");
     if (!anr_traces_path[0]) {
         printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
-    } else if (stat(anr_traces_path, &st)) {
-        printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_path, strerror(errno));
     } else {
-        dump_file("VM TRACES AT LAST ANR", anr_traces_path);
+      int fd = open(anr_traces_path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
+      if (fd < 0) {
+          printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_path, strerror(errno));
+      } else {
+          dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_path, fd);
+      }
     }
 
     /* slow traces for slow operations */
@@ -152,6 +184,18 @@
         }
     }
 
+    int dumped = 0;
+    for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
+        if (tombstone_data[i].fd != -1) {
+            dumped = 1;
+            dump_file_from_fd("TOMBSTONE", tombstone_data[i].name, tombstone_data[i].fd);
+            tombstone_data[i].fd = -1;
+        }
+    }
+    if (!dumped) {
+        printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR);
+    }
+
     dump_file("NETWORK DEV INFO", "/proc/net/dev");
     dump_file("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
     dump_file("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
@@ -404,6 +448,9 @@
         return -1;
     }
 
+    /* Get the tombstone fds here while we are running as root. */
+    get_tombstone_fds(tombstone_data);
+
     /* switch to non-root user and group */
     gid_t groups[] = { AID_LOG, AID_SDCARD_R, AID_SDCARD_RW,
             AID_MOUNT, AID_INET, AID_NET_BW_STATS };
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 6906dcf..e75da2d 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -28,7 +28,10 @@
 typedef void (for_each_tid_func)(int, int, const char *);
 
 /* prints the contents of a file */
-int dump_file(const char *title, const char* path);
+int dump_file(const char *title, const char *path);
+
+/* prints the contents of the fd */
+int dump_file_from_fd(const char *title, const char *path, int fd);
 
 /* forks a command and waits for it to finish -- terminate args with NULL */
 int run_command(const char *title, int timeout_seconds, const char *command, ...);
@@ -64,7 +67,7 @@
 void dump_route_tables();
 
 /* Play a sound via Stagefright */
-void play_sound(const char* path);
+void play_sound(const char *path);
 
 /* Implemented by libdumpstate_board to dump board-specific info */
 void dumpstate_board();
diff --git a/cmds/dumpstate/utils.c b/cmds/dumpstate/utils.c
index 9451417..56287a0 100644
--- a/cmds/dumpstate/utils.c
+++ b/cmds/dumpstate/utils.c
@@ -210,8 +210,7 @@
 }
 
 /* prints the contents of a file */
-int dump_file(const char *title, const char* path) {
-    char buffer[32768];
+int dump_file(const char *title, const char *path) {
     int fd = open(path, O_RDONLY);
     if (fd < 0) {
         int err = errno;
@@ -220,6 +219,11 @@
         if (title) printf("\n");
         return -1;
     }
+    return dump_file_from_fd(title, path, fd);
+}
+
+int dump_file_from_fd(const char *title, const char *path, int fd) {
+    char buffer[32768];
 
     if (title) printf("------ %s (%s", title, path);
 
@@ -243,8 +247,8 @@
         }
         if (ret <= 0) break;
     }
-
     close(fd);
+
     if (!newline) printf("\n");
     if (title) printf("\n");
     return 0;
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index 41a8f30..c25af59 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -559,7 +559,6 @@
     return 0;
 }
 
-
 int create_cache_path(char path[PKG_PATH_MAX], const char *src, const char *instruction_set)
 {
     char *tmp;
@@ -622,6 +621,46 @@
     ALOGE("execl(%s) failed: %s\n", DEX_OPT_BIN, strerror(errno));
 }
 
+static void run_patchoat(int input_fd, int oat_fd, const char* input_file_name,
+    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 char* PATCHOAT_BIN = "/system/bin/patchoat";
+    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;
+    }
+
+    /* input_file_name/input_fd should be the .odex/.oat file that is precompiled. I think*/
+    char instruction_set_arg[strlen("--instruction-set=") + MAX_INSTRUCTION_SET_LEN];
+    char output_oat_fd_arg[strlen("--output-oat-fd=") + MAX_INT_LEN];
+    char input_oat_fd_arg[strlen("--input-oat-fd=") + MAX_INT_LEN];
+    const char* patched_image_location_arg = "--patched-image-location=/system/framework/boot.art";
+    // The caller has already gotten all the locks we need.
+    const char* no_lock_arg = "--no-lock-output";
+    sprintf(instruction_set_arg, "--instruction-set=%s", instruction_set);
+    sprintf(output_oat_fd_arg, "--output-oat-fd=%d", oat_fd);
+    sprintf(input_oat_fd_arg, "--input-oat-fd=%d", input_fd);
+    ALOGE("Running %s isa=%s in-fd=%d (%s) out-fd=%d (%s)\n",
+          PATCHOAT_BIN, instruction_set, input_fd, input_file_name, oat_fd, output_file_name);
+
+    /* patchoat, patched-image-location, no-lock, isa, input-fd, output-fd */
+    char* argv[7];
+    argv[0] = (char*) PATCHOAT_BIN;
+    argv[1] = (char*) patched_image_location_arg;
+    argv[2] = (char*) no_lock_arg;
+    argv[3] = instruction_set_arg;
+    argv[4] = output_oat_fd_arg;
+    argv[5] = input_oat_fd_arg;
+    argv[6] = NULL;
+
+    execv(PATCHOAT_BIN, (char* const *)argv);
+    ALOGE("execv(%s) failed: %s\n", PATCHOAT_BIN, strerror(errno));
+}
+
 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)
 {
@@ -634,10 +673,21 @@
     char dex2oat_Xmx_flag[PROPERTY_VALUE_MAX];
     bool have_dex2oat_Xmx_flag = property_get("dalvik.vm.dex2oat-Xmx", dex2oat_Xmx_flag, NULL) > 0;
 
+    char dex2oat_compiler_filter_flag[PROPERTY_VALUE_MAX];
+    bool have_dex2oat_compiler_filter_flag = property_get("dalvik.vm.dex2oat-filter",
+                                                          dex2oat_compiler_filter_flag, 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);
 
+    // If we booting without the real /data, don't spend time compiling.
+    char vold_decrypt[PROPERTY_VALUE_MAX];
+    bool have_vold_decrypt = property_get("vold.decrypt", vold_decrypt, "") > 0;
+    bool skip_compilation = (have_vold_decrypt &&
+                             (strcmp(vold_decrypt, "trigger_restart_min_framework") == 0 ||
+                             (strcmp(vold_decrypt, "1") == 0)));
+
     static const char* DEX2OAT_BIN = "/system/bin/dex2oat";
 
     static const char* RUNTIME_ARG = "--runtime-arg";
@@ -660,6 +710,7 @@
     char top_k_profile_threshold_arg[strlen("--top-k-profile-threshold=") + PROPERTY_VALUE_MAX];
     char dex2oat_Xms_arg[strlen("-Xms") + PROPERTY_VALUE_MAX];
     char dex2oat_Xmx_arg[strlen("-Xmx") + PROPERTY_VALUE_MAX];
+    char dex2oat_compiler_filter_arg[strlen("--compiler-filter=") + PROPERTY_VALUE_MAX];
 
     sprintf(zip_fd_arg, "--zip-fd=%d", zip_fd);
     sprintf(zip_location_arg, "--zip-location=%s", input_file_name);
@@ -691,6 +742,12 @@
     if (have_dex2oat_Xmx_flag) {
         sprintf(dex2oat_Xmx_arg, "-Xmx%s", dex2oat_Xmx_flag);
     }
+    if (skip_compilation) {
+        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);
+    }
 
     ALOGV("Running %s in=%s out=%s\n", DEX2OAT_BIN, input_file_name, output_file_name);
 
@@ -699,6 +756,7 @@
                + (have_top_k_profile_threshold ? 1 : 0)
                + (have_dex2oat_Xms_flag ? 2 : 0)
                + (have_dex2oat_Xmx_flag ? 2 : 0)
+               + (have_dex2oat_compiler_filter_flag ? 1 : 0)
                + (have_dex2oat_flags ? 1 : 0)];
     int i = 0;
     argv[i++] = (char*)DEX2OAT_BIN;
@@ -721,6 +779,9 @@
         argv[i++] = (char*)RUNTIME_ARG;
         argv[i++] = dex2oat_Xmx_arg;
     }
+    if (have_dex2oat_compiler_filter_flag) {
+        argv[i++] = dex2oat_compiler_filter_arg;
+    }
     if (have_dex2oat_flags) {
         argv[i++] = dex2oat_flags;
     }
@@ -758,14 +819,17 @@
 }
 
 int dexopt(const char *apk_path, uid_t uid, int is_public,
-           const char *pkgname, const char *instruction_set)
+           const char *pkgname, const char *instruction_set,
+           int is_patchoat)
 {
     struct utimbuf ut;
-    struct stat apk_stat, dex_stat;
+    struct stat input_stat, dex_stat;
     char out_path[PKG_PATH_MAX];
     char persist_sys_dalvik_vm_lib[PROPERTY_VALUE_MAX];
     char *end;
-    int res, zip_fd=-1, out_fd=-1;
+    const char *input_file;
+    char in_odex_path[PKG_PATH_MAX];
+    int res, input_fd=-1, out_fd=-1;
 
     if (strlen(apk_path) >= (PKG_PATH_MAX - 8)) {
         return -1;
@@ -774,12 +838,20 @@
     /* The command to run depend on the value of persist.sys.dalvik.vm.lib */
     property_get("persist.sys.dalvik.vm.lib.2", persist_sys_dalvik_vm_lib, "libart.so");
 
+    if (is_patchoat && strncmp(persist_sys_dalvik_vm_lib, "libart", 6) != 0) {
+        /* We may only patch if we are libart */
+        ALOGE("Patching is only supported in libart\n");
+        return -1;
+    }
+
     /* Before anything else: is there a .odex file?  If so, we have
      * precompiled the apk and there is nothing to do here.
+     *
+     * We skip this if we are doing a patchoat.
      */
     strcpy(out_path, apk_path);
     end = strrchr(out_path, '.');
-    if (end != NULL) {
+    if (end != NULL && !is_patchoat) {
         strcpy(end, ".odex");
         if (stat(out_path, &dex_stat) == 0) {
             return 0;
@@ -790,12 +862,33 @@
         return -1;
     }
 
-    memset(&apk_stat, 0, sizeof(apk_stat));
-    stat(apk_path, &apk_stat);
+    if (is_patchoat) {
+        /* /system/framework/whatever.jar -> /system/framework/<isa>/whatever.odex */
+        strcpy(in_odex_path, apk_path);
+        end = strrchr(in_odex_path, '/');
+        if (end == NULL) {
+            ALOGE("apk_path '%s' has no '/'s in it?!\n", apk_path);
+            return -1;
+        }
+        const char *apk_end = apk_path + (end - in_odex_path); // strrchr(apk_path, '/');
+        strcpy(end + 1, instruction_set); // in_odex_path now is /system/framework/<isa>\0
+        strcat(in_odex_path, apk_end);
+        end = strrchr(in_odex_path, '.');
+        if (end == NULL) {
+            return -1;
+        }
+        strcpy(end + 1, "odex");
+        input_file = in_odex_path;
+    } else {
+        input_file = apk_path;
+    }
 
-    zip_fd = open(apk_path, O_RDONLY, 0);
-    if (zip_fd < 0) {
-        ALOGE("installd cannot open '%s' for input during dexopt\n", apk_path);
+    memset(&input_stat, 0, sizeof(input_stat));
+    stat(input_file, &input_stat);
+
+    input_fd = open(input_file, O_RDONLY, 0);
+    if (input_fd < 0) {
+        ALOGE("installd cannot open '%s' for input during dexopt\n", input_file);
         return -1;
     }
 
@@ -822,7 +915,7 @@
     }
 
 
-    ALOGV("DexInv: --- BEGIN '%s' ---\n", apk_path);
+    ALOGV("DexInv: --- BEGIN '%s' ---\n", input_file);
 
     pid_t pid;
     pid = fork();
@@ -852,9 +945,13 @@
         }
 
         if (strncmp(persist_sys_dalvik_vm_lib, "libdvm", 6) == 0) {
-            run_dexopt(zip_fd, out_fd, apk_path, out_path);
+            run_dexopt(input_fd, out_fd, input_file, out_path);
         } else if (strncmp(persist_sys_dalvik_vm_lib, "libart", 6) == 0) {
-            run_dex2oat(zip_fd, out_fd, apk_path, out_path, pkgname, instruction_set);
+            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);
+            }
         } else {
             exit(69);   /* Unexpected persist.sys.dalvik.vm.lib value */
         }
@@ -862,19 +959,19 @@
     } else {
         res = wait_child(pid);
         if (res == 0) {
-            ALOGV("DexInv: --- END '%s' (success) ---\n", apk_path);
+            ALOGV("DexInv: --- END '%s' (success) ---\n", input_file);
         } else {
-            ALOGE("DexInv: --- END '%s' --- status=0x%04x, process failed\n", apk_path, res);
+            ALOGE("DexInv: --- END '%s' --- status=0x%04x, process failed\n", input_file, res);
             goto fail;
         }
     }
 
-    ut.actime = apk_stat.st_atime;
-    ut.modtime = apk_stat.st_mtime;
+    ut.actime = input_stat.st_atime;
+    ut.modtime = input_stat.st_mtime;
     utime(out_path, &ut);
 
     close(out_fd);
-    close(zip_fd);
+    close(input_fd);
     return 0;
 
 fail:
@@ -882,8 +979,8 @@
         close(out_fd);
         unlink(out_path);
     }
-    if (zip_fd >= 0) {
-        close(zip_fd);
+    if (input_fd >= 0) {
+        close(input_fd);
     }
     return -1;
 }
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
index 35fba42..682aaff 100644
--- a/cmds/installd/installd.c
+++ b/cmds/installd/installd.c
@@ -39,7 +39,7 @@
 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]);
+    return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3], arg[4], 0);
 }
 
 static int do_move_dex(char **arg, char reply[REPLY_MAX])
@@ -146,6 +146,10 @@
     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);
+}
+
 struct cmdinfo {
     const char *name;
     unsigned numargs;
@@ -173,6 +177,7 @@
     { "idmap",                3, do_idmap },
     { "restorecondata",       3, do_restorecon_data },
     { "prunedexcache",        1, do_prune_dex_cache },
+    { "patchoat",             5, do_patchoat },
 };
 
 static int readx(int s, void *_buf, int count)
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index 258647a..1ddfc66 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -215,7 +215,7 @@
              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);
+           const char *instruction_set, int 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);
diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk
index 6b90243..cc5d544 100644
--- a/opengl/libs/Android.mk
+++ b/opengl/libs/Android.mk
@@ -112,21 +112,16 @@
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 LOCAL_CFLAGS += -fvisibility=hidden
 
-include $(BUILD_SHARED_LIBRARY)
-
 # Symlink libGLESv3.so -> libGLESv2.so
 # Platform modules should link against libGLESv2.so (-lGLESv2), but NDK apps
 # will be linked against libGLESv3.so.
-LIBGLESV2 := $(LOCAL_INSTALLED_MODULE)
-LIBGLESV3 := $(subst libGLESv2,libGLESv3,$(LIBGLESV2))
-$(LIBGLESV3): $(LIBGLESV2)
-	@echo "Symlink: $@ -> $(notdir $<)"
-	@mkdir -p $(dir $@)
-	$(hide) ln -sf $(notdir $<) $@
-ALL_MODULES.$(LOCAL_MODULE).INSTALLED := \
-	$(ALL_MODULES.$(LOCAL_MODULE).INSTALLED) $(LIBGLESV3)
-LIBGLESV2 :=
-LIBGLESV3 :=
+# Note we defer the evaluation of the LOCAL_POST_INSTALL_CMD,
+# so $(LOCAL_INSTALLED_MODULE) will be expanded to correct value,
+# even for both 32-bit and 64-bit installed files in multilib build.
+LOCAL_POST_INSTALL_CMD = \
+    $(hide) ln -sf $(notdir $(LOCAL_INSTALLED_MODULE)) $(dir $(LOCAL_INSTALLED_MODULE))libGLESv3.so
+
+include $(BUILD_SHARED_LIBRARY)
 
 ###############################################################################
 # Build the ETC1 host static library
diff --git a/opengl/libs/GLES2/gl2.cpp b/opengl/libs/GLES2/gl2.cpp
index e112fec..ad9af9f 100644
--- a/opengl/libs/GLES2/gl2.cpp
+++ b/opengl/libs/GLES2/gl2.cpp
@@ -183,7 +183,7 @@
     const GLubyte * ret = egl_get_string_for_current_context(name);
     if (ret == NULL) {
         gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;
-        ret = _c->glGetString(name);
+        if(_c) ret = _c->glGetString(name);
     }
     return ret;
 }