[MemInit] Remove old API, introduce new MemInit API.

Introduces new heap-zero-init API. We've realised that it's better to be
able to individually control MTE and heap zero-init. Having
heap-zero-init not be controllable without affecting MTE affects our
ability to turn off heap-zero-init in zygote-forked applications.

Bug: 135772972
Test: On FVP: atest -s localhost:5555 malloc#zero_init \
Test: malloc#disable_mte heap_tagging_level
Change-Id: I8c6722502733259934c699f4f1269eaf1641a09f
diff --git a/tests/malloc_test.cpp b/tests/malloc_test.cpp
index b35bba9..3a09258 100644
--- a/tests/malloc_test.cpp
+++ b/tests/malloc_test.cpp
@@ -32,8 +32,10 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
+#include <algorithm>
 #include <atomic>
 #include <thread>
+#include <vector>
 
 #include <tinyxml2.h>
 
@@ -1256,7 +1258,67 @@
 #endif
 }
 
-TEST(malloc, disable_memory_mitigations) {
+void TestHeapZeroing(int num_iterations, int (*get_alloc_size)(int iteration)) {
+  std::vector<void*> allocs;
+  constexpr int kMaxBytesToCheckZero = 64;
+  const char kBlankMemory[kMaxBytesToCheckZero] = {};
+
+  for (int i = 0; i < num_iterations; ++i) {
+    int size = get_alloc_size(i);
+    allocs.push_back(malloc(size));
+    memset(allocs.back(), 'X', std::min(size, kMaxBytesToCheckZero));
+  }
+
+  for (void* alloc : allocs) {
+    free(alloc);
+  }
+  allocs.clear();
+
+  for (int i = 0; i < num_iterations; ++i) {
+    int size = get_alloc_size(i);
+    allocs.push_back(malloc(size));
+    ASSERT_EQ(0, memcmp(allocs.back(), kBlankMemory, std::min(size, kMaxBytesToCheckZero)));
+  }
+
+  for (void* alloc : allocs) {
+    free(alloc);
+  }
+}
+
+TEST(malloc, zero_init) {
+#if defined(__BIONIC__)
+  SKIP_WITH_HWASAN << "hwasan does not implement mallopt";
+  bool allocator_scudo;
+  GetAllocatorVersion(&allocator_scudo);
+  if (!allocator_scudo) {
+    GTEST_SKIP() << "scudo allocator only test";
+  }
+
+  mallopt(M_BIONIC_ZERO_INIT, 1);
+
+  // Test using a block of 4K small (1-32 byte) allocations.
+  TestHeapZeroing(/* num_iterations */ 0x1000, [](int iteration) -> int {
+    return 1 + iteration % 32;
+  });
+
+  // Also test large allocations that land in the scudo secondary, as this is
+  // the only part of Scudo that's changed by enabling zero initialization with
+  // MTE. Uses 32 allocations, totalling 60MiB memory. Decay time (time to
+  // release secondary allocations back to the OS) was modified to 0ms/1ms by
+  // mallopt_decay. Ensure that we delay for at least a second before releasing
+  // pages to the OS in order to avoid implicit zeroing by the kernel.
+  mallopt(M_DECAY_TIME, 1000);
+  TestHeapZeroing(/* num_iterations */ 32, [](int iteration) -> int {
+    return 1 << (19 + iteration % 4);
+  });
+
+#else
+  GTEST_SKIP() << "bionic-only test";
+#endif
+}
+
+// Note that MTE is enabled on cc_tests on devices that support MTE.
+TEST(malloc, disable_mte) {
 #if defined(__BIONIC__)
   if (!mte_supported()) {
     GTEST_SKIP() << "This function can only be tested with MTE";
@@ -1275,7 +1337,7 @@
                    },
                    &sem));
 
-  ASSERT_EQ(1, mallopt(M_BIONIC_DISABLE_MEMORY_MITIGATIONS, 0));
+  ASSERT_EQ(1, mallopt(M_BIONIC_SET_HEAP_TAGGING_LEVEL, M_HEAP_TAGGING_LEVEL_NONE));
   ASSERT_EQ(0, sem_post(&sem));
 
   int my_tagged_addr_ctrl = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);