Merge "Fix native stats_event logging"
diff --git a/adb/apex/Android.bp b/adb/apex/Android.bp
index 75c4ed9..a6b1e78 100644
--- a/adb/apex/Android.bp
+++ b/adb/apex/Android.bp
@@ -21,7 +21,7 @@
 }
 
 // adbd apex with INT_MAX version code, to allow for upgrade/rollback testing.
-apex {
+apex_test {
     name: "test_com.android.adbd",
     defaults: ["com.android.adbd-defaults"],
     manifest: "test_apex_manifest.json",
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index c5fc154..9ffe5dd 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -32,6 +32,8 @@
 #include <memory>
 #include <regex>
 #include <string>
+#include <string_view>
+#include <unordered_map>
 #include <utility>
 #include <vector>
 
@@ -50,16 +52,133 @@
 
 namespace {
 
+struct AtomInfo {
+  int32_t atom;
+  int32_t event;
+};
+
+// Maps BootEvent used inside bootstat into statsd atom defined in
+// frameworks/base/cmds/statsd/src/atoms.proto.
+const std::unordered_map<std::string_view, AtomInfo> kBootEventToAtomInfo = {
+    // ELAPSED_TIME
+    {"ro.boottime.init",
+     {android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
+      android::util::BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__ANDROID_INIT_STAGE_1}},
+    {"boot_complete",
+     {android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
+      android::util::BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__BOOT_COMPLETE}},
+    {"boot_decryption_complete",
+     {android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
+      android::util::BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__BOOT_COMPLETE_ENCRYPTION}},
+    {"boot_complete_no_encryption",
+     {android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
+      android::util::BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__BOOT_COMPLETE_NO_ENCRYPTION}},
+    {"boot_complete_post_decrypt",
+     {android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
+      android::util::BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__BOOT_COMPLETE_POST_DECRYPT}},
+    {"factory_reset_boot_complete",
+     {android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
+      android::util::BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__FACTORY_RESET_BOOT_COMPLETE}},
+    {"factory_reset_boot_complete_no_encryption",
+     {android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
+      android::util::
+          BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__FACTORY_RESET_BOOT_COMPLETE_NO_ENCRYPTION}},
+    {"factory_reset_boot_complete_post_decrypt",
+     {android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
+      android::util::
+          BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__FACTORY_RESET_BOOT_COMPLETE_POST_DECRYPT}},
+    {"ota_boot_complete",
+     {android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
+      android::util::BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__OTA_BOOT_COMPLETE}},
+    {"ota_boot_complete_no_encryption",
+     {android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
+      android::util::BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__OTA_BOOT_COMPLETE_NO_ENCRYPTION}},
+    {"ota_boot_complete_post_decrypt",
+     {android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
+      android::util::BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__OTA_BOOT_COMPLETE_POST_DECRYPT}},
+    {"post_decrypt_time_elapsed",
+     {android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
+      android::util::BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__POST_DECRYPT}},
+    // DURATION
+    {"absolute_boot_time",
+     {android::util::BOOT_TIME_EVENT_DURATION_REPORTED,
+      android::util::BOOT_TIME_EVENT_DURATION__EVENT__ABSOLUTE_BOOT_TIME}},
+    {"boottime.bootloader.1BLE",
+     {android::util::BOOT_TIME_EVENT_DURATION_REPORTED,
+      android::util::BOOT_TIME_EVENT_DURATION__EVENT__BOOTLOADER_FIRST_STAGE_EXEC}},
+    {"boottime.bootloader.1BLL",
+     {android::util::BOOT_TIME_EVENT_DURATION_REPORTED,
+      android::util::BOOT_TIME_EVENT_DURATION__EVENT__BOOTLOADER_FIRST_STAGE_LOAD}},
+    {"boottime.bootloader.KL",
+     {android::util::BOOT_TIME_EVENT_DURATION_REPORTED,
+      android::util::BOOT_TIME_EVENT_DURATION__EVENT__BOOTLOADER_KERNEL_LOAD}},
+    {"boottime.bootloader.2BLE",
+     {android::util::BOOT_TIME_EVENT_DURATION_REPORTED,
+      android::util::BOOT_TIME_EVENT_DURATION__EVENT__BOOTLOADER_SECOND_STAGE_EXEC}},
+    {"boottime.bootloader.2BLL",
+     {android::util::BOOT_TIME_EVENT_DURATION_REPORTED,
+      android::util::BOOT_TIME_EVENT_DURATION__EVENT__BOOTLOADER_SECOND_STAGE_LOAD}},
+    {"boottime.bootloader.SW",
+     {android::util::BOOT_TIME_EVENT_DURATION_REPORTED,
+      android::util::BOOT_TIME_EVENT_DURATION__EVENT__BOOTLOADER_UI_WAIT}},
+    {"boottime.bootloader.total",
+     {android::util::BOOT_TIME_EVENT_DURATION_REPORTED,
+      android::util::BOOT_TIME_EVENT_DURATION__EVENT__BOOTLOADER_TOTAL}},
+    {"boottime.init.cold_boot_wait",
+     {android::util::BOOT_TIME_EVENT_DURATION_REPORTED,
+      android::util::BOOT_TIME_EVENT_DURATION__EVENT__COLDBOOT_WAIT}},
+    {"time_since_factory_reset",
+     {android::util::BOOT_TIME_EVENT_DURATION_REPORTED,
+      android::util::BOOT_TIME_EVENT_DURATION__EVENT__FACTORY_RESET_TIME_SINCE_RESET}},
+    {"ro.boottime.init.first_stage",
+     {android::util::BOOT_TIME_EVENT_DURATION_REPORTED,
+      android::util::BOOT_TIME_EVENT_DURATION__EVENT__ANDROID_INIT_STAGE_1}},
+    {"ro.boottime.init.selinux",
+     {android::util::BOOT_TIME_EVENT_DURATION_REPORTED,
+      android::util::BOOT_TIME_EVENT_DURATION__EVENT__SELINUX_INIT}},
+    // UTC_TIME
+    {"factory_reset",
+     {android::util::BOOT_TIME_EVENT_UTC_TIME_REPORTED,
+      android::util::BOOT_TIME_EVENT_UTC_TIME__EVENT__FACTORY_RESET_RESET_TIME}},
+    {"factory_reset_current_time",
+     {android::util::BOOT_TIME_EVENT_UTC_TIME_REPORTED,
+      android::util::BOOT_TIME_EVENT_UTC_TIME__EVENT__FACTORY_RESET_CURRENT_TIME}},
+    {"factory_reset_record_value",
+     {android::util::BOOT_TIME_EVENT_UTC_TIME_REPORTED,
+      android::util::BOOT_TIME_EVENT_UTC_TIME__EVENT__FACTORY_RESET_RECORD_VALUE}},
+    // ERROR_CODE
+    {"factory_reset_current_time_failure",
+     {android::util::BOOT_TIME_EVENT_ERROR_CODE_REPORTED,
+      android::util::BOOT_TIME_EVENT_ERROR_CODE__EVENT__FACTORY_RESET_CURRENT_TIME_FAILURE}},
+};
+
 // Scans the boot event record store for record files and logs each boot event
 // via EventLog.
 void LogBootEvents() {
   BootEventRecordStore boot_event_store;
-
   auto events = boot_event_store.GetAllBootEvents();
-  // TODO(b/148575354): Replace with statsd.
-  // for (auto i = events.cbegin(); i != events.cend(); ++i) {
-  //   android::metricslogger::LogHistogram(i->first, i->second);
-  // }
+  std::vector<std::string_view> notSupportedEvents;
+  for (const auto& event : events) {
+    const auto& name = event.first;
+    const auto& info = kBootEventToAtomInfo.find(name);
+    if (info != kBootEventToAtomInfo.end()) {
+      if (info->second.atom == android::util::BOOT_TIME_EVENT_ERROR_CODE_REPORTED) {
+        android::util::stats_write(static_cast<int32_t>(info->second.atom),
+                                   static_cast<int32_t>(info->second.event),
+                                   static_cast<int32_t>(event.second));
+      } else {
+        android::util::stats_write(static_cast<int32_t>(info->second.atom),
+                                   static_cast<int32_t>(info->second.event),
+                                   static_cast<int64_t>(event.second));
+      }
+    } else {
+      notSupportedEvents.push_back(name);
+    }
+  }
+  if (!notSupportedEvents.empty()) {
+    LOG(WARNING) << "LogBootEvents, atomInfo not defined for events:"
+                 << android::base::Join(notSupportedEvents, ',');
+  }
 }
 
 // Records the named boot |event| to the record store. If |value| is non-empty
@@ -1250,11 +1369,13 @@
   time_t current_time_utc = time(nullptr);
 
   if (current_time_utc < 0) {
-    // TODO(b/148575354): Replace with statsd.
     // UMA does not display negative values in buckets, so convert to positive.
     // Logging via BootEventRecordStore.
-    // android::metricslogger::LogHistogram("factory_reset_current_time_failure",
-    //                                      std::abs(current_time_utc));
+    android::util::stats_write(
+        static_cast<int32_t>(android::util::BOOT_TIME_EVENT_ERROR_CODE_REPORTED),
+        static_cast<int32_t>(
+            android::util::BOOT_TIME_EVENT_ERROR_CODE__EVENT__FACTORY_RESET_CURRENT_TIME_FAILURE),
+        static_cast<int32_t>(std::abs(current_time_utc)));
 
     // Logging via BootEventRecordStore to see if using android::metricslogger::LogHistogram
     // is losing records somehow.
@@ -1262,8 +1383,11 @@
                                            std::abs(current_time_utc));
     return;
   } else {
-    // TODO(b/148575354): Replace with statsd.
-    // android::metricslogger::LogHistogram("factory_reset_current_time", current_time_utc);
+    android::util::stats_write(
+        static_cast<int32_t>(android::util::BOOT_TIME_EVENT_UTC_TIME_REPORTED),
+        static_cast<int32_t>(
+            android::util::BOOT_TIME_EVENT_UTC_TIME__EVENT__FACTORY_RESET_CURRENT_TIME),
+        static_cast<int64_t>(current_time_utc));
 
     // Logging via BootEventRecordStore to see if using android::metricslogger::LogHistogram
     // is losing records somehow.
@@ -1283,8 +1407,11 @@
   // Calculate and record the difference in time between now and the
   // factory_reset time.
   time_t factory_reset_utc = record.second;
-  // TODO(b/148575354): Replace with statsd.
-  // android::metricslogger::LogHistogram("factory_reset_record_value", factory_reset_utc);
+  android::util::stats_write(
+      static_cast<int32_t>(android::util::BOOT_TIME_EVENT_UTC_TIME_REPORTED),
+      static_cast<int32_t>(
+          android::util::BOOT_TIME_EVENT_UTC_TIME__EVENT__FACTORY_RESET_RECORD_VALUE),
+      static_cast<int64_t>(factory_reset_utc));
 
   // Logging via BootEventRecordStore to see if using android::metricslogger::LogHistogram
   // is losing records somehow.
diff --git a/fs_mgr/TEST_MAPPING b/fs_mgr/TEST_MAPPING
index de38ff6..60e3226 100644
--- a/fs_mgr/TEST_MAPPING
+++ b/fs_mgr/TEST_MAPPING
@@ -5,6 +5,12 @@
     },
     {
       "name": "liblp_test"
+    },
+    {
+      "name": "fiemap_image_test_presubmit"
+    },
+    {
+      "name": "fiemap_writer_test"
     }
   ]
 }
diff --git a/fs_mgr/libfiemap/Android.bp b/fs_mgr/libfiemap/Android.bp
index 1bf457f..2fd463c 100644
--- a/fs_mgr/libfiemap/Android.bp
+++ b/fs_mgr/libfiemap/Android.bp
@@ -104,4 +104,34 @@
     srcs: [
         "image_test.cpp",
     ],
+    test_suites: ["device-tests"],
+    auto_gen_config: true,
+    require_root: true,
+}
+
+/* BUG(148874852) temporary test */
+cc_test {
+    name: "fiemap_image_test_presubmit",
+    cppflags: [
+        "-DSKIP_TEST_IN_PRESUBMIT",
+    ],
+    static_libs: [
+        "libdm",
+        "libext4_utils",
+        "libfs_mgr",
+        "liblp",
+    ],
+    shared_libs: [
+        "libbase",
+        "libcrypto",
+        "libcrypto_utils",
+        "libcutils",
+        "liblog",
+    ],
+    srcs: [
+        "image_test.cpp",
+    ],
+    test_suites: ["device-tests"],
+    auto_gen_config: true,
+    require_root: true,
 }
diff --git a/fs_mgr/libfiemap/fiemap_writer.cpp b/fs_mgr/libfiemap/fiemap_writer.cpp
index b911234..4dd4bcc 100644
--- a/fs_mgr/libfiemap/fiemap_writer.cpp
+++ b/fs_mgr/libfiemap/fiemap_writer.cpp
@@ -526,11 +526,7 @@
 }
 
 static bool IsLastExtent(const fiemap_extent* extent) {
-    if (!(extent->fe_flags & FIEMAP_EXTENT_LAST)) {
-        LOG(ERROR) << "Extents are being received out-of-order";
-        return false;
-    }
-    return true;
+    return !!(extent->fe_flags & FIEMAP_EXTENT_LAST);
 }
 
 static bool FiemapToExtents(struct fiemap* fiemap, std::vector<struct fiemap_extent>* extents,
@@ -552,7 +548,10 @@
         fiemap_extent* next = &fiemap->fm_extents[i];
 
         // Make sure extents are returned in order
-        if (next != last_extent && IsLastExtent(next)) return false;
+        if (next != last_extent && IsLastExtent(next)) {
+            LOG(ERROR) << "Extents are being received out-of-order";
+            return false;
+        }
 
         // Check if extent's flags are valid
         if (!IsValidExtent(next, file_path)) return false;
@@ -592,8 +591,7 @@
         return false;
     }
 
-    uint64_t fiemap_size =
-            sizeof(struct fiemap_extent) + num_extents * sizeof(struct fiemap_extent);
+    uint64_t fiemap_size = sizeof(struct fiemap) + num_extents * sizeof(struct fiemap_extent);
     auto buffer = std::unique_ptr<void, decltype(&free)>(calloc(1, fiemap_size), free);
     if (buffer == nullptr) {
         LOG(ERROR) << "Failed to allocate memory for fiemap";
diff --git a/fs_mgr/libfiemap/image_test.cpp b/fs_mgr/libfiemap/image_test.cpp
index 80c340f..5388b44 100644
--- a/fs_mgr/libfiemap/image_test.cpp
+++ b/fs_mgr/libfiemap/image_test.cpp
@@ -212,6 +212,9 @@
 }
 
 TEST_F(ImageTest, IndirectMount) {
+#ifdef SKIP_TEST_IN_PRESUBMIT
+    GTEST_SKIP() << "WIP failure b/148874852";
+#endif
     // Create a simple wrapper around the base device that we'll mount from
     // instead. This will simulate the code paths for dm-crypt/default-key/bow
     // and force us to use device-mapper rather than loop devices.