Background full compaction for CC.

Invoke a full compaction with the CC collector when an app goes to the
background like the HSpace compaction for the CMS collector.

Bug: 31039431
Bug: 12687968
Test: test-art, Ritz EAAC, N9 libartd.so device boot with CC
Change-Id: I119aa26c1d3c167b12983fffcb16164929bf8f68
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 638c1d8..9e454ca 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -731,6 +731,7 @@
 }
 
 void Heap::DisableMovingGc() {
+  CHECK(!kUseReadBarrier);
   if (IsMovingGc(foreground_collector_type_)) {
     foreground_collector_type_ = kCollectorTypeCMS;
   }
@@ -970,7 +971,8 @@
       // Don't delay for debug builds since we may want to stress test the GC.
       // If background_collector_type_ is kCollectorTypeHomogeneousSpaceCompact then we have
       // special handling which does a homogenous space compaction once but then doesn't transition
-      // the collector.
+      // the collector. Similarly, we invoke a full compaction for kCollectorTypeCC but don't
+      // transition the collector.
       RequestCollectorTransition(background_collector_type_,
                                  kIsDebugBuild ? 0 : kCollectorTransitionWait);
     }
@@ -1384,6 +1386,16 @@
     } else {
       VLOG(gc) << "Homogeneous compaction ignored due to jank perceptible process state";
     }
+  } else if (desired_collector_type == kCollectorTypeCCBackground) {
+    DCHECK(kUseReadBarrier);
+    if (!CareAboutPauseTimes()) {
+      // Invoke CC full compaction.
+      CollectGarbageInternal(collector::kGcTypeFull,
+                             kGcCauseCollectorTransition,
+                             /*clear_soft_references*/false);
+    } else {
+      VLOG(gc) << "CC background compaction ignored due to jank perceptible process state";
+    }
   } else {
     TransitionCollector(desired_collector_type);
   }
@@ -1841,6 +1853,10 @@
         break;
       }
       case kAllocatorTypeNonMoving: {
+        if (kUseReadBarrier) {
+          // DisableMovingGc() isn't compatible with CC.
+          break;
+        }
         // Try to transition the heap if the allocation failure was due to the space being full.
         if (!IsOutOfMemoryOnAllocation<false>(allocator, alloc_size)) {
           // If we aren't out of memory then the OOM was probably from the non moving space being
@@ -2109,6 +2125,8 @@
 }
 
 void Heap::TransitionCollector(CollectorType collector_type) {
+  // Collector transition must not happen with CC
+  CHECK(!kUseReadBarrier);
   if (collector_type == collector_type_) {
     return;
   }
@@ -3798,6 +3816,12 @@
   if (desired_collector_type_ == collector_type_ || !CanAddHeapTask(self)) {
     return;
   }
+  if (collector_type_ == kCollectorTypeCC) {
+    // For CC, we invoke a full compaction when going to the background, but the collector type
+    // doesn't change.
+    DCHECK_EQ(desired_collector_type_, kCollectorTypeCCBackground);
+  }
+  DCHECK_NE(collector_type_, kCollectorTypeCCBackground);
   CollectorTransitionTask* added_task = nullptr;
   const uint64_t target_time = NanoTime() + delta_time;
   {