Add more detail to rosalloc fragmentation OOME

Also include total number of free page bytes, space footprint, and
space max capacity.

Sample output:
Throwing OutOfMemoryError "Failed to allocate a 7012 byte allocation
with 103464 free bytes and 101KB until OOM; failed due to
fragmentation (required continguous free 8192 bytes, largest
contiguous free 4096 bytes, total free pages 4096 bytes, space
footprint 268435456 bytes, space max capacity 268435456 bytes)

Added a basic test to ensure the allocator coalesces properly.

Bug: 32997082

Test: test-art-host

Change-Id: I642b6ad34b98f6d98c10f242a6f6e926e0b42acc
diff --git a/runtime/gc/allocator/rosalloc.cc b/runtime/gc/allocator/rosalloc.cc
index 40186f8..2e4475f 100644
--- a/runtime/gc/allocator/rosalloc.cc
+++ b/runtime/gc/allocator/rosalloc.cc
@@ -2068,26 +2068,30 @@
   size_t largest_continuous_free_pages = 0;
   WriterMutexLock wmu(self, bulk_free_lock_);
   MutexLock mu(self, lock_);
+  uint64_t total_free = 0;
   for (FreePageRun* fpr : free_page_runs_) {
     largest_continuous_free_pages = std::max(largest_continuous_free_pages,
                                              fpr->ByteSize(this));
+    total_free += fpr->ByteSize(this);
   }
+  size_t required_bytes = 0;
+  const char* new_buffer_msg = "";
   if (failed_alloc_bytes > kLargeSizeThreshold) {
     // Large allocation.
-    size_t required_bytes = RoundUp(failed_alloc_bytes, kPageSize);
-    if (required_bytes > largest_continuous_free_pages) {
-      os << "; failed due to fragmentation (required continguous free "
-         << required_bytes << " bytes where largest contiguous free "
-         <<  largest_continuous_free_pages << " bytes)";
-    }
+    required_bytes = RoundUp(failed_alloc_bytes, kPageSize);
   } else {
     // Non-large allocation.
-    size_t required_bytes = numOfPages[SizeToIndex(failed_alloc_bytes)] * kPageSize;
-    if (required_bytes > largest_continuous_free_pages) {
-      os << "; failed due to fragmentation (required continguous free "
-         << required_bytes << " bytes for a new buffer where largest contiguous free "
-         <<  largest_continuous_free_pages << " bytes)";
-    }
+    required_bytes = numOfPages[SizeToIndex(failed_alloc_bytes)] * kPageSize;
+    new_buffer_msg = " for a new buffer";
+  }
+  if (required_bytes > largest_continuous_free_pages) {
+    os << "; failed due to fragmentation ("
+       << "required contiguous free " << required_bytes << " bytes" << new_buffer_msg
+       << ", largest contiguous free " << largest_continuous_free_pages << " bytes"
+       << ", total free pages " << total_free << " bytes"
+       << ", space footprint " << footprint_ << " bytes"
+       << ", space max capacity " << max_capacity_ << " bytes"
+       << ")" << std::endl;
   }
 }