Merge "Make the extra profile lib available for all apex."
diff --git a/libfec/fec_read.cpp b/libfec/fec_read.cpp
index 889f990..28a7c89 100644
--- a/libfec/fec_read.cpp
+++ b/libfec/fec_read.cpp
@@ -325,8 +325,12 @@
 
         /* copy raw data without error correction */
         if (!raw_pread(f->fd, data, FEC_BLOCKSIZE, curr_offset)) {
-            error("failed to read: %s", strerror(errno));
-            return -1;
+            if (errno == EIO) {
+                warn("I/O error encounter when reading, attempting to recover using fec");
+            } else {
+                error("failed to read: %s", strerror(errno));
+                return -1;
+            }
         }
 
         if (likely(f->hashtree().check_block_hash_with_index(curr, data))) {
diff --git a/memory_replay/Alloc.cpp b/memory_replay/Alloc.cpp
index af94ee5..a624710 100644
--- a/memory_replay/Alloc.cpp
+++ b/memory_replay/Alloc.cpp
@@ -14,72 +14,15 @@
  * limitations under the License.
  */
 
-#include <err.h>
-#include <inttypes.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <unistd.h>
 
-#include <string>
-
 #include "Alloc.h"
+#include "AllocParser.h"
 #include "Pointers.h"
 #include "Utils.h"
 
-void AllocGetData(const std::string& line, AllocEntry* entry) {
-  int line_pos = 0;
-  char name[128];
-  // All lines have this format:
-  //   TID: ALLOCATION_TYPE POINTER
-  // where
-  //   TID is the thread id of the thread doing the operation.
-  //   ALLOCATION_TYPE is one of malloc, calloc, memalign, realloc, free, thread_done
-  //   POINTER is the hex value of the actual pointer
-  if (sscanf(line.c_str(), "%d: %127s %" SCNx64 " %n", &entry->tid, name, &entry->ptr, &line_pos) !=
-      3) {
-    errx(1, "File Error: Failed to process %s", line.c_str());
-  }
-  const char* line_end = &line[line_pos];
-  std::string type(name);
-  if (type == "malloc") {
-    // Format:
-    //   TID: malloc POINTER SIZE_OF_ALLOCATION
-    if (sscanf(line_end, "%zu", &entry->size) != 1) {
-      errx(1, "File Error: Failed to read malloc data %s", line.c_str());
-    }
-    entry->type = MALLOC;
-  } else if (type == "free") {
-    // Format:
-    //   TID: free POINTER
-    entry->type = FREE;
-  } else if (type == "calloc") {
-    // Format:
-    //   TID: calloc POINTER ITEM_COUNT ITEM_SIZE
-    if (sscanf(line_end, "%" SCNd64 " %zu", &entry->u.n_elements, &entry->size) != 2) {
-      errx(1, "File Error: Failed to read calloc data %s", line.c_str());
-    }
-    entry->type = CALLOC;
-  } else if (type == "realloc") {
-    // Format:
-    //   TID: calloc POINTER NEW_SIZE OLD_POINTER
-    if (sscanf(line_end, "%" SCNx64 " %zu", &entry->u.old_ptr, &entry->size) != 2) {
-      errx(1, "File Error: Failed to read realloc data %s", line.c_str());
-    }
-    entry->type = REALLOC;
-  } else if (type == "memalign") {
-    // Format:
-    //   TID: memalign POINTER ALIGNMENT SIZE
-    if (sscanf(line_end, "%" SCNd64 " %zu", &entry->u.align, &entry->size) != 2) {
-      errx(1, "File Error: Failed to read memalign data %s", line.c_str());
-    }
-    entry->type = MEMALIGN;
-  } else if (type == "thread_done") {
-    entry->type = THREAD_DONE;
-  } else {
-    errx(1, "File Error: Unknown type %s", type.c_str());
-  }
-}
-
 bool AllocDoesFree(const AllocEntry& entry) {
   switch (entry.type) {
     case MALLOC:
diff --git a/memory_replay/Alloc.h b/memory_replay/Alloc.h
index d590fcb..f4dcc83 100644
--- a/memory_replay/Alloc.h
+++ b/memory_replay/Alloc.h
@@ -16,34 +16,11 @@
 
 #pragma once
 
-#include <string>
+#include "AllocParser.h"
 
 // Forward Declarations.
 class Pointers;
 
-enum AllocEnum : uint8_t {
-  MALLOC = 0,
-  CALLOC,
-  MEMALIGN,
-  REALLOC,
-  FREE,
-  THREAD_DONE,
-};
-
-struct AllocEntry {
-  pid_t tid;
-  AllocEnum type;
-  uint64_t ptr = 0;
-  size_t size = 0;
-  union {
-    uint64_t old_ptr = 0;
-    uint64_t n_elements;
-    uint64_t align;
-  } u;
-};
-
-void AllocGetData(const std::string& line, AllocEntry* entry);
-
 bool AllocDoesFree(const AllocEntry& entry);
 
 uint64_t AllocExecute(const AllocEntry& entry, Pointers* pointers);
diff --git a/memory_replay/AllocParser.cpp b/memory_replay/AllocParser.cpp
new file mode 100644
index 0000000..ac6664a
--- /dev/null
+++ b/memory_replay/AllocParser.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2022 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 <err.h>
+#include <inttypes.h>
+#include <stdio.h>
+
+#include "AllocParser.h"
+
+#include <iostream>
+
+void AllocGetData(const std::string& line, AllocEntry* entry) {
+    int op_prefix_pos = 0;
+    char name[128];
+    // All lines have this format:
+    //   TID: ALLOCATION_TYPE POINTER
+    // where
+    //   TID is the thread id of the thread doing the operation.
+    //   ALLOCATION_TYPE is one of malloc, calloc, memalign, realloc, free, thread_done
+    //   POINTER is the hex value of the actual pointer
+    if (sscanf(line.c_str(), "%d: %127s %" SCNx64 " %n", &entry->tid, name, &entry->ptr,
+               &op_prefix_pos) != 3) {
+        errx(1, "File Error: Failed to process %s", line.c_str());
+    }
+    std::string type(name);
+    if (type == "thread_done") {
+        entry->type = THREAD_DONE;
+    } else {
+        int args_offset = 0;
+        const char* args_beg = &line[op_prefix_pos];
+        if (type == "malloc") {
+            // Format:
+            //   TID: malloc POINTER SIZE_OF_ALLOCATION
+            if (sscanf(args_beg, "%zu%n", &entry->size, &args_offset) != 1) {
+                errx(1, "File Error: Failed to read malloc data %s", line.c_str());
+            }
+            entry->type = MALLOC;
+        } else if (type == "free") {
+            // Format:
+            //   TID: free POINTER
+            entry->type = FREE;
+        } else if (type == "calloc") {
+            // Format:
+            //   TID: calloc POINTER ITEM_COUNT ITEM_SIZE
+            if (sscanf(args_beg, "%" SCNd64 " %zu%n", &entry->u.n_elements, &entry->size,
+                       &args_offset) != 2) {
+                errx(1, "File Error: Failed to read calloc data %s", line.c_str());
+            }
+            entry->type = CALLOC;
+        } else if (type == "realloc") {
+            // Format:
+            //   TID: realloc POINTER OLD_POINTER NEW_SIZE
+            if (sscanf(args_beg, "%" SCNx64 " %zu%n", &entry->u.old_ptr, &entry->size,
+                       &args_offset) != 2) {
+                errx(1, "File Error: Failed to read realloc data %s", line.c_str());
+            }
+            entry->type = REALLOC;
+        } else if (type == "memalign") {
+            // Format:
+            //   TID: memalign POINTER ALIGNMENT SIZE
+            if (sscanf(args_beg, "%" SCNd64 " %zu%n", &entry->u.align, &entry->size,
+                       &args_offset) != 2) {
+                errx(1, "File Error: Failed to read memalign data %s", line.c_str());
+            }
+            entry->type = MEMALIGN;
+        } else {
+            errx(1, "File Error: Unknown type %s", type.c_str());
+        }
+
+        const char* timestamps_beg = &args_beg[args_offset];
+
+        // Timestamps come after the alloc args if present, for example,
+        //   TID: malloc POINTER SIZE_OF_ALLOCATION START_TIME END_TIME
+        int n_match = sscanf(timestamps_beg, "%" SCNd64 " %" SCNd64, &entry->st, &entry->et);
+        if (n_match != EOF && n_match != 2) {
+            errx(1, "File Error: Failed to read timestamps %s", line.c_str());
+        }
+    }
+}
diff --git a/memory_replay/AllocParser.h b/memory_replay/AllocParser.h
new file mode 100644
index 0000000..e58be48
--- /dev/null
+++ b/memory_replay/AllocParser.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#pragma once
+
+#include <sys/types.h>
+
+#include <string>
+
+enum AllocEnum : uint8_t {
+    MALLOC = 0,
+    CALLOC,
+    MEMALIGN,
+    REALLOC,
+    FREE,
+    THREAD_DONE,
+};
+
+struct AllocEntry {
+    pid_t tid;
+    AllocEnum type;
+    uint64_t ptr = 0;
+    size_t size = 0;
+    union {
+        uint64_t old_ptr = 0;
+        uint64_t n_elements;
+        uint64_t align;
+    } u;
+    uint64_t st = 0;
+    uint64_t et = 0;
+};
+
+void AllocGetData(const std::string& line, AllocEntry* entry);
diff --git a/memory_replay/Android.bp b/memory_replay/Android.bp
index 8fb9dbc..bdcde1b 100644
--- a/memory_replay/Android.bp
+++ b/memory_replay/Android.bp
@@ -44,6 +44,17 @@
     compile_multilib: "both",
 }
 
+cc_library_static {
+    name: "liballoc_parser",
+    host_supported: true,
+    defaults: ["memory_flag_defaults"],
+
+    export_include_dirs: ["."],
+    srcs: [
+        "AllocParser.cpp",
+    ],
+}
+
 cc_defaults {
     name: "memory_replay_defaults",
     defaults: ["memory_flag_defaults"],
@@ -63,6 +74,7 @@
     ],
 
     static_libs: [
+        "liballoc_parser",
         "libasync_safe",
     ],
 }
@@ -126,6 +138,10 @@
         "libziparchive",
     ],
 
+    static_libs: [
+        "liballoc_parser",
+    ],
+
     data: [
         "traces/*.zip",
     ],
diff --git a/memory_replay/File.cpp b/memory_replay/File.cpp
index 8bcd904..e44c500 100644
--- a/memory_replay/File.cpp
+++ b/memory_replay/File.cpp
@@ -29,6 +29,7 @@
 #include <ziparchive/zip_archive.h>
 
 #include "Alloc.h"
+#include "AllocParser.h"
 #include "File.h"
 
 std::string ZipGetContents(const char* filename) {
diff --git a/profcollectd/Android.bp b/profcollectd/Android.bp
index 122e4f6..787ca22 100644
--- a/profcollectd/Android.bp
+++ b/profcollectd/Android.bp
@@ -31,9 +31,21 @@
     ],
 }
 
+rust_defaults {
+    name: "profcollectd_defaults",
+    arch: {
+        riscv64: {
+            // libprofcollectd doesn't build for riscv64
+            enabled: false,
+        },
+    },
+}
+
 rust_binary {
     name: "profcollectctl",
 
+    defaults: ["profcollectd_defaults"],
+
     srcs: ["profcollectctl.rs"],
 
     rustlibs: [
@@ -45,6 +57,8 @@
 rust_binary {
     name: "profcollectd",
 
+    defaults: ["profcollectd_defaults"],
+
     srcs: ["profcollectd.rs"],
 
     rustlibs: [