Desugar R8 part in R8 partial before trace references

The introduction of the desugar step breaks PartialShrinkingPreviewApiTest, since this test does not expect a CF-to-CF desugaring marker. This CL therefore also ensures that a single "R8Partial" marker is inserted when using R8Partial.

Fixes: b/388452773
Fixes: b/388763735
Fixes: b/389577597
Change-Id: Ifd42a258208028fe1484a6be5f96bd98e411480c
diff --git a/src/main/java/com/android/tools/r8/R8Partial.java b/src/main/java/com/android/tools/r8/R8Partial.java
index 1a21bec..c5a573f 100644
--- a/src/main/java/com/android/tools/r8/R8Partial.java
+++ b/src/main/java/com/android/tools/r8/R8Partial.java
@@ -17,9 +17,12 @@
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.partial.R8PartialD8DexResult;
 import com.android.tools.r8.partial.R8PartialDataResourceConsumer;
+import com.android.tools.r8.partial.R8PartialDesugarResult;
 import com.android.tools.r8.partial.R8PartialInput;
 import com.android.tools.r8.partial.R8PartialInputToDumpFlags;
 import com.android.tools.r8.partial.R8PartialR8Result;
+import com.android.tools.r8.partial.R8PartialSubCompilationConfiguration.R8PartialD8SubCompilationConfiguration;
+import com.android.tools.r8.partial.R8PartialSubCompilationConfiguration.R8PartialR8SubCompilationConfiguration;
 import com.android.tools.r8.partial.R8PartialTraceReferencesResult;
 import com.android.tools.r8.partial.R8PartialTraceResourcesResult;
 import com.android.tools.r8.partial.ResourceTracingCallback;
@@ -27,7 +30,6 @@
 import com.android.tools.r8.tracereferences.TraceReferencesBridge;
 import com.android.tools.r8.tracereferences.TraceReferencesCommand;
 import com.android.tools.r8.tracereferences.TraceReferencesKeepRules;
-import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.AndroidAppConsumers;
 import com.android.tools.r8.utils.ExceptionDiagnostic;
@@ -39,6 +41,7 @@
 import com.android.tools.r8.utils.ZipUtils;
 import com.android.tools.r8.utils.ZipUtils.ZipBuilder;
 import com.google.common.io.ByteStreams;
+import it.unimi.dsi.fastutil.ints.IntSets;
 import java.io.IOException;
 import java.nio.file.Path;
 import java.util.HashSet;
@@ -87,10 +90,13 @@
 
     R8PartialInput input = runProcessInputStep(app, timing);
     R8PartialD8DexResult d8DexResult = runD8DexStep(input, executor);
-    R8PartialTraceResourcesResult resourcesTraceResult = runTraceResourcesStep(d8DexResult);
-    R8PartialTraceReferencesResult traceReferencesResult = runTraceReferencesStep(input);
+    R8PartialTraceResourcesResult traceResourcesResult = runTraceResourcesStep(d8DexResult);
+    R8PartialDesugarResult desugarResult = runDesugarStep(input, executor);
+    R8PartialTraceReferencesResult traceReferencesResult =
+        runTraceReferencesStep(input, desugarResult);
     R8PartialR8Result r8Result =
-        runR8PartialStep(input, traceReferencesResult, resourcesTraceResult, executor);
+        runR8PartialStep(
+            input, desugarResult, traceReferencesResult, traceResourcesResult, executor);
     runD8MergeStep(input, d8DexResult, r8Result, executor);
 
     // Feed the data resource output by R8 to the output consumer. Keeping this at the end after the
@@ -101,6 +107,9 @@
 
   private R8PartialTraceResourcesResult runTraceResourcesStep(R8PartialD8DexResult d8DexResult)
       throws IOException {
+    if (options.androidResourceProvider == null) {
+      return new R8PartialTraceResourcesResult(IntSets.EMPTY_SET);
+    }
     // TODO(b/390135529): Consider tracing these in the enqueuer of R8.
     ResourceTracingCallback resourceTracingCallback = new ResourceTracingCallback();
     AndroidApp app = AndroidApp.builder().addProgramFile(d8DexResult.getOutputPath()).build();
@@ -174,6 +183,7 @@
   private R8PartialD8DexResult runD8DexStep(R8PartialInput input, ExecutorService executor)
       throws IOException {
     // Compile D8 input with D8.
+    // TODO(b/389575762): Consume the DexProgramClasses directly instead of writing to a zip.
     Path d8Output = resolveTmp("d8-output.zip");
     D8Command.Builder d8Builder =
         D8Command.builder(options.reporter)
@@ -191,8 +201,7 @@
     }
     InternalOptions d8Options = d8Command.getInternalOptions();
     options.partialCompilationConfiguration.d8DexOptionsConsumer.accept(d8Options);
-    assert d8Options.getMinApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.N)
-        : "Default interface methods not yet supported";
+    d8Options.partialSubCompilationConfiguration = new R8PartialD8SubCompilationConfiguration();
     D8.runInternal(d8App, d8Options, executor);
     if (d8OutputAppConsumer != null) {
       d8OutputAppConsumer.accept(d8OutputAppSink.build());
@@ -200,7 +209,32 @@
     return new R8PartialD8DexResult(d8Output);
   }
 
-  private R8PartialTraceReferencesResult runTraceReferencesStep(R8PartialInput input)
+  private R8PartialDesugarResult runDesugarStep(R8PartialInput input, ExecutorService executor)
+      throws IOException {
+    // TODO(b/389575762): Consume the DexProgramClasses instead of writing to a zip.
+    // TODO(b/389039057): This will desugar the entire R8 part. For build speed, look into if some
+    //  desugarings can be postponed to the R8 compilation, since we do not desugar dead code in R8.
+    //  As a simple example, it should be safe to postpone backporting to the R8 compilation.
+    // TODO(b/389039057): This runs a full D8 compilation. For build speed, consider if the various
+    //  passes in D8 can be disabled when the `partialSubCompilationConfiguration` is set.
+    Path desugarOutput = resolveTmp("desugar-output.zip");
+    D8Command.Builder d8Builder =
+        D8Command.builder(options.reporter).setOutput(desugarOutput, OutputMode.ClassFile);
+    // TODO(b/390327883): This should enable intermediate mode.
+    input.configureDesugar(d8Builder);
+    d8Builder.validate();
+    D8Command d8Command = d8Builder.makeCommand();
+    AndroidApp d8App = d8Command.getInputApp();
+    InternalOptions d8Options = d8Command.getInternalOptions();
+    options.partialCompilationConfiguration.d8DesugarOptionsConsumer.accept(d8Options);
+    d8Options.partialSubCompilationConfiguration = new R8PartialD8SubCompilationConfiguration();
+    D8.runInternal(d8App, d8Options, executor);
+    return new R8PartialDesugarResult(desugarOutput);
+  }
+
+  // TODO(b/389031823): Parallelize trace references.
+  private R8PartialTraceReferencesResult runTraceReferencesStep(
+      R8PartialInput input, R8PartialDesugarResult desugarResult)
       throws IOException, ResourceException {
     // Run trace references to produce keep rules for the D8 compiled part.
     // TODO(b/309743298): Do not emit keep rules into a file.
@@ -210,7 +244,9 @@
             .setOutputConsumer(new FileConsumer(traceReferencesRules))
             .build();
     TraceReferencesCommand.Builder trBuilder =
-        TraceReferencesCommand.builder().setConsumer(keepRulesConsumer);
+        TraceReferencesCommand.builder()
+            .addTargetFiles(desugarResult.getOutputPath())
+            .setConsumer(keepRulesConsumer);
     input.configure(trBuilder);
     TraceReferencesCommand tr = TraceReferencesBridge.makeCommand(trBuilder);
     TraceReferencesBridge.runInternal(tr);
@@ -219,8 +255,9 @@
 
   private R8PartialR8Result runR8PartialStep(
       R8PartialInput input,
+      R8PartialDesugarResult desugarResult,
       R8PartialTraceReferencesResult traceReferencesResult,
-      R8PartialTraceResourcesResult resourcesTraceResult,
+      R8PartialTraceResourcesResult traceResourcesResult,
       ExecutorService executor)
       throws IOException {
     // Compile R8 input with R8 using the keep rules from trace references.
@@ -238,8 +275,10 @@
             return super.modifyDiagnosticsLevel(level, diagnostic);
           }
         };
+    // TODO(b/390389764): Disable desugaring.
     R8Command.Builder r8Builder =
         R8Command.builder(r8DiagnosticsHandler)
+            .addProgramFiles(desugarResult.getOutputPath())
             .addProguardConfigurationFiles(traceReferencesResult.getOutputPath())
             .enableLegacyFullModeForKeepRules(true)
             .setProgramConsumer(
@@ -262,12 +301,13 @@
     }
     InternalOptions r8Options = r8Command.getInternalOptions();
     options.partialCompilationConfiguration.r8OptionsConsumer.accept(r8Options);
+    r8Options.partialSubCompilationConfiguration =
+        new R8PartialR8SubCompilationConfiguration(traceResourcesResult.getResourceIdsToTrace());
     r8Options.mapConsumer = options.mapConsumer;
     if (options.androidResourceProvider != null) {
       r8Options.androidResourceProvider = options.androidResourceProvider;
       r8Options.androidResourceConsumer = options.androidResourceConsumer;
       r8Options.resourceShrinkerConfiguration = options.resourceShrinkerConfiguration;
-      r8Options.d8TracedResourceIDs = resourcesTraceResult.getResourceIdsToTrace();
     }
     R8.runInternal(r8App, r8Options, executor);
     if (r8OutputAppConsumer != null) {
@@ -293,6 +333,7 @@
     AndroidApp mergeApp = mergeCommand.getInputApp();
     InternalOptions mergeOptions = mergeCommand.getInternalOptions();
     options.partialCompilationConfiguration.d8MergeOptionsConsumer.accept(mergeOptions);
+    mergeOptions.partialSubCompilationConfiguration = new R8PartialD8SubCompilationConfiguration();
     D8.runInternal(mergeApp, mergeOptions, executor);
   }
 
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
index e03f7fb..53712e7 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
@@ -468,26 +468,35 @@
       allMarkers.addAll(previousMarkers);
     }
     DexItemFactory factory = appView.dexItemFactory();
-    currentMarker.ifPresent(
-        marker -> {
-          if (willComputeProguardMap()) {
-            lazyDexStrings.add(
-                new LazyDexString() {
+    currentMarker
+        .filter(this::includeMarker)
+        .ifPresent(
+            marker -> {
+              if (willComputeProguardMap()) {
+                lazyDexStrings.add(
+                    new LazyDexString() {
 
-                  @Override
-                  public DexString internalCompute() {
-                    marker.setPgMapId(delayedProguardMapId.get().getId());
-                    return marker.toDexString(factory);
-                  }
-                });
-          } else {
-            allMarkers.add(marker);
-          }
-        });
+                      @Override
+                      public DexString internalCompute() {
+                        marker.setPgMapId(delayedProguardMapId.get().getId());
+                        return marker.toDexString(factory);
+                      }
+                    });
+              } else {
+                allMarkers.add(marker);
+              }
+            });
     allMarkers.sort(Comparator.comparing(Marker::toString));
     markerStrings = ListUtils.map(allMarkers, marker -> marker.toDexString(factory));
   }
 
+  private boolean includeMarker(Marker marker) {
+    if (options.partialSubCompilationConfiguration != null) {
+      return options.partialSubCompilationConfiguration.includeMarker();
+    }
+    return true;
+  }
+
   private OriginalSourceFiles computeSourceFileString(
       Box<ProguardMapId> delayedProguardMapId, List<LazyDexString> lazyDexStrings) {
     if (options.sourceFileProvider == null) {
diff --git a/src/main/java/com/android/tools/r8/dex/Marker.java b/src/main/java/com/android/tools/r8/dex/Marker.java
index f0bd037..f7414d9 100644
--- a/src/main/java/com/android/tools/r8/dex/Marker.java
+++ b/src/main/java/com/android/tools/r8/dex/Marker.java
@@ -34,6 +34,7 @@
     GlobalSyntheticsGenerator,
     L8,
     R8,
+    R8Partial,
     Relocator,
     TraceReferences;
 
@@ -51,6 +52,7 @@
   private static final String PREFIX = "~~";
   private static final String D8_PREFIX = PREFIX + Tool.D8 + "{";
   private static final String R8_PREFIX = PREFIX + Tool.R8 + "{";
+  private static final String R8_PARTIAL_PREFIX = PREFIX + Tool.R8Partial + "{";
   private static final String L8_PREFIX = PREFIX + Tool.L8 + "{";
   private static final String RELOCATOR_PREFIX = PREFIX + Tool.Relocator + "{";
 
@@ -287,6 +289,9 @@
       if (str.startsWith(R8_PREFIX)) {
         return internalParse(Tool.R8, str.substring(R8_PREFIX.length() - 1));
       }
+      if (str.startsWith(R8_PARTIAL_PREFIX)) {
+        return internalParse(Tool.R8Partial, str.substring(R8_PARTIAL_PREFIX.length() - 1));
+      }
       if (str.startsWith(L8_PREFIX)) {
         return internalParse(Tool.L8, str.substring(L8_PREFIX.length() - 1));
       }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringSyntheticHelper.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringSyntheticHelper.java
index 4fff3f5..02a8d72 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringSyntheticHelper.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringSyntheticHelper.java
@@ -62,7 +62,7 @@
 
   // Use InterfaceDesugaringForTesting for public accesses in tests.
   static final String COMPANION_CLASS_NAME_SUFFIX = "$-CC";
-  static final String DEFAULT_METHOD_PREFIX = "$default$";
+  public static final String DEFAULT_METHOD_PREFIX = "$default$";
   public static final String PRIVATE_METHOD_PREFIX = "$private$";
 
   private final AppView<?> appView;
diff --git a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
index 3abb2cc..d2c9f54 100644
--- a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
@@ -133,6 +133,9 @@
     if (marker.isRelocator()) {
       return false;
     }
+    if (options.partialSubCompilationConfiguration != null) {
+      return options.partialSubCompilationConfiguration.includeMarker();
+    }
     assert marker.isCfBackend() || marker.isDexBackend();
     if (options.desugarSpecificOptions().noCfMarkerForDesugaredCode) {
       return !marker.isCfBackend() || !marker.isDesugared();
diff --git a/src/main/java/com/android/tools/r8/partial/R8PartialDesugarResult.java b/src/main/java/com/android/tools/r8/partial/R8PartialDesugarResult.java
new file mode 100644
index 0000000..6885303
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/partial/R8PartialDesugarResult.java
@@ -0,0 +1,19 @@
+// Copyright (c) 2025, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.partial;
+
+import java.nio.file.Path;
+
+public class R8PartialDesugarResult {
+
+  private final Path outputPath;
+
+  public R8PartialDesugarResult(Path outputPath) {
+    this.outputPath = outputPath;
+  }
+
+  public Path getOutputPath() {
+    return outputPath;
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/partial/R8PartialInput.java b/src/main/java/com/android/tools/r8/partial/R8PartialInput.java
index 3f07cd0..0c0bd91 100644
--- a/src/main/java/com/android/tools/r8/partial/R8PartialInput.java
+++ b/src/main/java/com/android/tools/r8/partial/R8PartialInput.java
@@ -10,6 +10,7 @@
 import com.android.tools.r8.R8Command;
 import com.android.tools.r8.dump.CompilerDump;
 import com.android.tools.r8.tracereferences.TraceReferencesCommand;
+import com.android.tools.r8.utils.ArchiveDataResourceProvider;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -32,6 +33,11 @@
     commandBuilder.addProgramFiles(d8Program).addClasspathFiles(r8Program);
   }
 
+  public void configureDesugar(D8Command.Builder commandBuilder) throws IOException {
+    configureBase(commandBuilder);
+    commandBuilder.addProgramFiles(r8Program).addClasspathFiles(d8Program);
+  }
+
   public void configureMerge(D8Command.Builder commandBuilder) throws IOException {
     configureBase(commandBuilder);
   }
@@ -40,16 +46,13 @@
     configureBase(commandBuilder);
     configureDesugaredLibrary(commandBuilder);
     commandBuilder
-        .addProgramFiles(r8Program)
+        .addProgramResourceProvider(new ArchiveDataResourceProvider(r8Program))
         .addClasspathFiles(d8Program)
         .addProguardConfigurationFiles(dump.getProguardConfigFile());
   }
 
   public void configure(TraceReferencesCommand.Builder commandBuilder) throws IOException {
-    commandBuilder
-        .addLibraryFiles(dump.getLibraryArchive())
-        .addSourceFiles(d8Program)
-        .addTargetFiles(r8Program);
+    commandBuilder.addLibraryFiles(dump.getLibraryArchive()).addSourceFiles(d8Program);
   }
 
   private void configureBase(BaseCompilerCommand.Builder<?, ?> commandBuilder) throws IOException {
diff --git a/src/main/java/com/android/tools/r8/partial/R8PartialR8Result.java b/src/main/java/com/android/tools/r8/partial/R8PartialR8Result.java
index 1823257..865c21f 100644
--- a/src/main/java/com/android/tools/r8/partial/R8PartialR8Result.java
+++ b/src/main/java/com/android/tools/r8/partial/R8PartialR8Result.java
@@ -33,6 +33,7 @@
   }
 
   private void supplyDataResourceConsumer(DataResourceConsumer consumer, Reporter reporter) {
+    if (consumer == null) return;
     for (DataResource dataResource : outputDataResources) {
       if (dataResource instanceof DataDirectoryResource) {
         consumer.accept((DataDirectoryResource) dataResource, reporter);
diff --git a/src/main/java/com/android/tools/r8/partial/R8PartialSubCompilationConfiguration.java b/src/main/java/com/android/tools/r8/partial/R8PartialSubCompilationConfiguration.java
new file mode 100644
index 0000000..ee13cc8
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/partial/R8PartialSubCompilationConfiguration.java
@@ -0,0 +1,42 @@
+// Copyright (c) 2025, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.partial;
+
+import it.unimi.dsi.fastutil.ints.IntSet;
+import it.unimi.dsi.fastutil.ints.IntSets;
+
+public abstract class R8PartialSubCompilationConfiguration {
+
+  public IntSet getD8TracedResourceIds() {
+    return IntSets.EMPTY_SET;
+  }
+
+  public boolean includeMarker() {
+    return false;
+  }
+
+  // Currently shared by all D8 compilations in R8 partial (i.e., dexing, desugaring, merging).
+  public static class R8PartialD8SubCompilationConfiguration
+      extends R8PartialSubCompilationConfiguration {}
+
+  public static class R8PartialR8SubCompilationConfiguration
+      extends R8PartialSubCompilationConfiguration {
+
+    public final IntSet d8TracedResourceIds;
+
+    public R8PartialR8SubCompilationConfiguration(IntSet d8TracedResourceIds) {
+      this.d8TracedResourceIds = d8TracedResourceIds;
+    }
+
+    @Override
+    public IntSet getD8TracedResourceIds() {
+      return d8TracedResourceIds;
+    }
+
+    @Override
+    public boolean includeMarker() {
+      return true;
+    }
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index 6348333..61596b5 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -3973,8 +3973,11 @@
     if (options.isOptimizedResourceShrinking()) {
       timing.begin("Trace AndroidManifest.xml files");
       appView.getResourceShrinkerState().traceKeepXmlAndManifest();
-      for (int d8TracedResourceID : options.d8TracedResourceIDs) {
-        appView.getResourceShrinkerState().trace(d8TracedResourceID, "Non shrunken dex code");
+      if (options.partialSubCompilationConfiguration != null) {
+        for (int d8TracedResourceId :
+            options.partialSubCompilationConfiguration.getD8TracedResourceIds()) {
+          appView.getResourceShrinkerState().trace(d8TracedResourceId, "Non shrunken dex code");
+        }
       }
       timing.end();
     }
diff --git a/src/main/java/com/android/tools/r8/utils/ArchiveDataResourceProvider.java b/src/main/java/com/android/tools/r8/utils/ArchiveDataResourceProvider.java
new file mode 100644
index 0000000..b93663e
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/utils/ArchiveDataResourceProvider.java
@@ -0,0 +1,23 @@
+// Copyright (c) 2025, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.utils;
+
+import com.android.tools.r8.ProgramResource;
+import com.android.tools.r8.ResourceException;
+import com.android.tools.r8.shaking.FilteredClassPath;
+import java.nio.file.Path;
+import java.util.Collection;
+import java.util.Collections;
+
+public class ArchiveDataResourceProvider extends ArchiveResourceProvider {
+
+  public ArchiveDataResourceProvider(Path archive) {
+    super(FilteredClassPath.unfiltered(archive), false);
+  }
+
+  @Override
+  public Collection<ProgramResource> getProgramResources() throws ResourceException {
+    return Collections.emptyList();
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index b2044f1..09c90d1 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -88,6 +88,7 @@
 import com.android.tools.r8.optimize.redundantbridgeremoval.RedundantBridgeRemovalOptions;
 import com.android.tools.r8.optimize.singlecaller.SingleCallerInlinerOptions;
 import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.partial.R8PartialSubCompilationConfiguration;
 import com.android.tools.r8.position.Position;
 import com.android.tools.r8.profile.art.ArtProfileOptions;
 import com.android.tools.r8.profile.startup.StartupOptions;
@@ -116,8 +117,6 @@
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
-import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
-import it.unimi.dsi.fastutil.ints.IntSet;
 import java.io.IOException;
 import java.nio.file.Paths;
 import java.util.ArrayList;
@@ -199,7 +198,6 @@
   public AndroidResourceProvider androidResourceProvider = null;
   public AndroidResourceConsumer androidResourceConsumer = null;
   public List<String> androidResourceProguardMapStrings = null;
-  public IntSet d8TracedResourceIDs = new IntOpenHashSet();
 
   public ResourceShrinkerConfiguration resourceShrinkerConfiguration =
       ResourceShrinkerConfiguration.DEFAULT_CONFIGURATION;
@@ -555,11 +553,18 @@
   }
 
   public Marker getMarker() {
-    assert tool != null;
     if (hasMarker) {
       return marker;
     }
-    return createMarker(tool);
+    return createMarker(getMarkerTool());
+  }
+
+  public Tool getMarkerTool() {
+    assert tool != null;
+    if (partialSubCompilationConfiguration != null && tool == Tool.R8) {
+      return Tool.R8Partial;
+    }
+    return tool;
   }
 
   // Compute the marker to be placed in the main dex file.
@@ -1024,6 +1029,7 @@
       R8PartialCompilationConfiguration.fromIncludeExcludePatterns(
           System.getProperty("com.android.tools.r8.experimentalPartialShrinkingIncludePatterns"),
           System.getProperty("com.android.tools.r8.experimentalPartialShrinkingExcludePatterns"));
+  public R8PartialSubCompilationConfiguration partialSubCompilationConfiguration = null;
   public final TestingOptions testing = new TestingOptions();
 
   public List<ProguardConfigurationRule> mainDexKeepRules = ImmutableList.of();
diff --git a/src/main/java/com/android/tools/r8/utils/R8PartialCompilationConfiguration.java b/src/main/java/com/android/tools/r8/utils/R8PartialCompilationConfiguration.java
index 4adb654..5156353 100644
--- a/src/main/java/com/android/tools/r8/utils/R8PartialCompilationConfiguration.java
+++ b/src/main/java/com/android/tools/r8/utils/R8PartialCompilationConfiguration.java
@@ -30,6 +30,7 @@
   public Consumer<AndroidApp> d8OutputAppConsumer;
 
   public Consumer<InternalOptions> d8DexOptionsConsumer = ConsumerUtils.emptyConsumer();
+  public Consumer<InternalOptions> d8DesugarOptionsConsumer = ConsumerUtils.emptyConsumer();
   public Consumer<InternalOptions> d8MergeOptionsConsumer = ConsumerUtils.emptyConsumer();
   public Consumer<InternalOptions> r8OptionsConsumer = ConsumerUtils.emptyConsumer();
 
diff --git a/src/test/java/com/android/tools/r8/benchmarks/appdumps/AppDumpBenchmarkBuilder.java b/src/test/java/com/android/tools/r8/benchmarks/appdumps/AppDumpBenchmarkBuilder.java
index bfe2cd6..0c74460 100644
--- a/src/test/java/com/android/tools/r8/benchmarks/appdumps/AppDumpBenchmarkBuilder.java
+++ b/src/test/java/com/android/tools/r8/benchmarks/appdumps/AppDumpBenchmarkBuilder.java
@@ -10,6 +10,7 @@
 import com.android.tools.r8.LibraryDesugaringTestConfiguration;
 import com.android.tools.r8.R8FullTestBuilder;
 import com.android.tools.r8.R8PartialTestBuilder;
+import com.android.tools.r8.R8PartialTestCompileResult;
 import com.android.tools.r8.R8TestBuilder;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestBase.Backend;
@@ -32,7 +33,6 @@
 import com.android.tools.r8.keepanno.annotations.KeepEdge;
 import com.android.tools.r8.keepanno.annotations.KeepItemKind;
 import com.android.tools.r8.keepanno.annotations.KeepTarget;
-import com.android.tools.r8.utils.AndroidApiLevel;
 import com.google.common.collect.ImmutableSet;
 import java.io.IOException;
 import java.lang.annotation.RetentionPolicy;
@@ -152,12 +152,18 @@
 
   public BenchmarkConfig buildR8WithPartialShrinking(
       ThrowableConsumer<? super R8PartialTestBuilder> configuration) {
+    return buildR8WithPartialShrinking(configuration, ThrowableConsumer.empty());
+  }
+
+  public BenchmarkConfig buildR8WithPartialShrinking(
+      ThrowableConsumer<? super R8PartialTestBuilder> configuration,
+      ThrowableConsumer<? super R8PartialTestCompileResult> compileResultConsumer) {
     verify();
     return BenchmarkConfig.builder()
         .setName(name)
         .setTarget(BenchmarkTarget.R8)
         .setSuite(BenchmarkSuite.OPENSOURCE_BENCHMARKS)
-        .setMethod(runR8WithPartialShrinking(this, configuration))
+        .setMethod(runR8WithPartialShrinking(this, configuration, compileResultConsumer))
         .setFromRevision(fromRevision)
         .addDependency(dumpDependency)
         .measureRunTime()
@@ -314,8 +320,9 @@
 
   private static BenchmarkMethod runR8WithPartialShrinking(
       AppDumpBenchmarkBuilder builder,
-      ThrowableConsumer<? super R8PartialTestBuilder> configuration) {
-    return internalRunR8Partial(builder, configuration);
+      ThrowableConsumer<? super R8PartialTestBuilder> configuration,
+      ThrowableConsumer<? super R8PartialTestCompileResult> compileResultConsumer) {
+    return internalRunR8Partial(builder, configuration, compileResultConsumer);
   }
 
   private static BenchmarkMethod runR8WithResourceShrinking(
@@ -383,7 +390,8 @@
 
   private static BenchmarkMethod internalRunR8Partial(
       AppDumpBenchmarkBuilder builder,
-      ThrowableConsumer<? super R8PartialTestBuilder> configuration) {
+      ThrowableConsumer<? super R8PartialTestBuilder> configuration,
+      ThrowableConsumer<? super R8PartialTestCompileResult> compileResultConsumer) {
     return environment ->
         BenchmarkBase.runner(environment)
             .setWarmupIterations(1)
@@ -406,8 +414,7 @@
                       .addProgramFiles(dump.getProgramArchive())
                       .addLibraryFiles(dump.getLibraryArchive())
                       .addKeepRuleFiles(dump.getProguardConfigFile())
-                      // TODO(b/388452773): Fix support for default interface methods.
-                      .setMinApi(Math.max(dumpProperties.getMinApi(), AndroidApiLevel.N.getLevel()))
+                      .setMinApi(dumpProperties.getMinApi())
                       .setR8PartialConfiguration(
                           b -> {
                             if (builder.programPackages.isEmpty()) {
@@ -431,7 +438,8 @@
                                   .benchmarkDexSegmentsCodeSize(results)
                                   .benchmarkDex2OatCodeSize(
                                       results,
-                                      environment.getConfig().isDex2OatVerificationEnabled()));
+                                      environment.getConfig().isDex2OatVerificationEnabled())
+                                  .apply(compileResultConsumer));
                 });
   }
 
diff --git a/src/test/java/com/android/tools/r8/benchmarks/appdumps/ComposeSamplesBenchmarks.java b/src/test/java/com/android/tools/r8/benchmarks/appdumps/ComposeSamplesBenchmarks.java
index 14b8f7e..931a36c 100644
--- a/src/test/java/com/android/tools/r8/benchmarks/appdumps/ComposeSamplesBenchmarks.java
+++ b/src/test/java/com/android/tools/r8/benchmarks/appdumps/ComposeSamplesBenchmarks.java
@@ -3,12 +3,19 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.benchmarks.appdumps;
 
+import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
+import static com.android.tools.r8.DiagnosticsMatcher.diagnosticType;
+import static org.hamcrest.CoreMatchers.allOf;
+import static org.hamcrest.CoreMatchers.containsString;
+
 import com.android.tools.r8.R8FullTestBuilder;
 import com.android.tools.r8.R8PartialTestBuilder;
+import com.android.tools.r8.R8PartialTestCompileResult;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.benchmarks.BenchmarkBase;
 import com.android.tools.r8.benchmarks.BenchmarkConfig;
+import com.android.tools.r8.errors.InterfaceDesugarMissingTypeDiagnostic;
 import com.google.common.collect.ImmutableList;
 import java.nio.file.Path;
 import java.nio.file.Paths;
@@ -75,7 +82,9 @@
             .setName("JetCasterAppPartial")
             .setDumpDependencyPath(dir.resolve("jetcaster"))
             .setFromRevision(16457)
-            .buildR8WithPartialShrinking(ComposeSamplesBenchmarks::configureJetCasterAppPartial),
+            .buildR8WithPartialShrinking(
+                ComposeSamplesBenchmarks::configureJetCasterAppPartial,
+                ComposeSamplesBenchmarks::inspectJetCasterAppPartial),
         AppDumpBenchmarkBuilder.builder()
             .setName("JetChatApp")
             .setDumpDependencyPath(dir.resolve("jetchat"))
@@ -85,7 +94,9 @@
             .setName("JetChatAppPartial")
             .setDumpDependencyPath(dir.resolve("jetchat"))
             .setFromRevision(16457)
-            .buildR8WithPartialShrinking(ComposeSamplesBenchmarks::configureJetChatAppPartial),
+            .buildR8WithPartialShrinking(
+                ComposeSamplesBenchmarks::configureJetChatAppPartial,
+                ComposeSamplesBenchmarks::inspectJetChatAppPartial),
         AppDumpBenchmarkBuilder.builder()
             .setName("JetSnackApp")
             .setDumpDependencyPath(dir.resolve("jetsnack"))
@@ -143,10 +154,47 @@
 
   private static void configureJetCasterAppPartial(R8PartialTestBuilder testBuilder) {
     testBuilder
-        .allowDiagnosticInfoMessages()
+        .allowDiagnosticMessages()
         .allowUnnecessaryDontWarnWildcards()
         .allowUnusedDontWarnPatterns()
-        .allowUnusedProguardConfigurationRules();
+        .allowUnusedProguardConfigurationRules()
+        .addR8PartialOptionsModification(
+            options -> options.getOpenClosedInterfacesOptions().disallowOpenInterfaces());
+  }
+
+  private static void inspectJetCasterAppPartial(R8PartialTestCompileResult compileResult) {
+    compileResult.inspectDiagnosticMessages(
+        diagnostics ->
+            diagnostics
+                .assertWarningsMatch(
+                    allOf(
+                        diagnosticType(InterfaceDesugarMissingTypeDiagnostic.class),
+                        diagnosticMessage(
+                            containsString("androidx.compose.animation.tooling.ComposeAnimation"))),
+                    allOf(
+                        diagnosticType(InterfaceDesugarMissingTypeDiagnostic.class),
+                        diagnosticMessage(containsString("androidx.paging.PositionalDataSource"))),
+                    allOf(
+                        diagnosticType(InterfaceDesugarMissingTypeDiagnostic.class),
+                        diagnosticMessage(
+                            containsString("java.lang.instrument.ClassFileTransformer"))),
+                    allOf(
+                        diagnosticType(InterfaceDesugarMissingTypeDiagnostic.class),
+                        diagnosticMessage(
+                            containsString("org.conscrypt.ConscryptHostnameVerifier"))),
+                    allOf(
+                        diagnosticType(InterfaceDesugarMissingTypeDiagnostic.class),
+                        diagnosticMessage(containsString("org.jaxen.DefaultNavigator"))),
+                    allOf(
+                        diagnosticType(InterfaceDesugarMissingTypeDiagnostic.class),
+                        diagnosticMessage(containsString("org.jaxen.NamespaceContext"))),
+                    allOf(
+                        diagnosticType(InterfaceDesugarMissingTypeDiagnostic.class),
+                        diagnosticMessage(containsString("org.jaxen.VariableContext"))),
+                    allOf(
+                        diagnosticType(InterfaceDesugarMissingTypeDiagnostic.class),
+                        diagnosticMessage(containsString("sun.misc.SignalHandler"))))
+                .assertNoErrors());
   }
 
   private static void configureJetChatApp(R8FullTestBuilder testBuilder) {
@@ -159,12 +207,31 @@
 
   private static void configureJetChatAppPartial(R8PartialTestBuilder testBuilder) {
     testBuilder
-        .allowDiagnosticInfoMessages()
+        .allowDiagnosticMessages()
         .allowUnnecessaryDontWarnWildcards()
         .allowUnusedDontWarnPatterns()
         .allowUnusedProguardConfigurationRules();
   }
 
+  private static void inspectJetChatAppPartial(R8PartialTestCompileResult compileResult) {
+    compileResult.inspectDiagnosticMessages(
+        diagnostics ->
+            diagnostics
+                .assertWarningsMatch(
+                    allOf(
+                        diagnosticType(InterfaceDesugarMissingTypeDiagnostic.class),
+                        diagnosticMessage(
+                            containsString("androidx.compose.animation.tooling.ComposeAnimation"))),
+                    allOf(
+                        diagnosticType(InterfaceDesugarMissingTypeDiagnostic.class),
+                        diagnosticMessage(
+                            containsString("java.lang.instrument.ClassFileTransformer"))),
+                    allOf(
+                        diagnosticType(InterfaceDesugarMissingTypeDiagnostic.class),
+                        diagnosticMessage(containsString("sun.misc.SignalHandler"))))
+                .assertNoErrors());
+  }
+
   @Ignore
   @Test
   @Override
diff --git a/src/test/java/com/android/tools/r8/partial/PartialCompilationBasicPreviewPatternsTest.java b/src/test/java/com/android/tools/r8/partial/PartialCompilationBasicPreviewPatternsTest.java
index b6c55e9..791d1ee 100644
--- a/src/test/java/com/android/tools/r8/partial/PartialCompilationBasicPreviewPatternsTest.java
+++ b/src/test/java/com/android/tools/r8/partial/PartialCompilationBasicPreviewPatternsTest.java
@@ -8,13 +8,11 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.ToolHelper.DexVm;
 import com.android.tools.r8.partial.pkg1.A1;
 import com.android.tools.r8.partial.pkg1.A2;
 import com.android.tools.r8.partial.pkg1.subpkg.B;
 import com.android.tools.r8.partial.pkg2.C1;
 import com.android.tools.r8.partial.pkg2.C2;
-import com.android.tools.r8.utils.AndroidApiLevel;
 import com.google.common.collect.ImmutableList;
 import java.util.List;
 import org.junit.Test;
@@ -38,12 +36,8 @@
   public TestParameters parameters;
 
   @Parameters(name = "{0}")
-  // Test with min API level 24.
   public static TestParametersCollection data() {
-    return getTestParameters()
-        .withDexRuntime(DexVm.Version.V7_0_0)
-        .withApiLevel(AndroidApiLevel.N)
-        .build();
+    return getTestParameters().withDexRuntimesAndAllApiLevels().build();
   }
 
   private static final List<Class<?>> ALL_CLASSES =
diff --git a/src/test/java/com/android/tools/r8/partial/PartialCompilationBasicTest.java b/src/test/java/com/android/tools/r8/partial/PartialCompilationBasicTest.java
index e55a8d5..c718f5c 100644
--- a/src/test/java/com/android/tools/r8/partial/PartialCompilationBasicTest.java
+++ b/src/test/java/com/android/tools/r8/partial/PartialCompilationBasicTest.java
@@ -10,8 +10,6 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.ToolHelper.DexVm;
-import com.android.tools.r8.utils.AndroidApiLevel;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -25,12 +23,8 @@
   public TestParameters parameters;
 
   @Parameters(name = "{0}")
-  // Test with min API level 24.
   public static TestParametersCollection data() {
-    return getTestParameters()
-        .withDexRuntime(DexVm.Version.V7_0_0)
-        .withApiLevel(AndroidApiLevel.N)
-        .build();
+    return getTestParameters().withDexRuntimesAndAllApiLevels().build();
   }
 
   @Test
diff --git a/src/test/java/com/android/tools/r8/partial/PartialCompilationClassAnnotatedInD8Test.java b/src/test/java/com/android/tools/r8/partial/PartialCompilationClassAnnotatedInD8Test.java
index be3c872..a350f1b 100644
--- a/src/test/java/com/android/tools/r8/partial/PartialCompilationClassAnnotatedInD8Test.java
+++ b/src/test/java/com/android/tools/r8/partial/PartialCompilationClassAnnotatedInD8Test.java
@@ -9,8 +9,6 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.ToolHelper.DexVm;
-import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.StringUtils;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -29,12 +27,8 @@
   public TestParameters parameters;
 
   @Parameters(name = "{0}")
-  // Test with min API level 24.
   public static TestParametersCollection data() {
-    return getTestParameters()
-        .withDexRuntimesStartingFromIncluding(DexVm.Version.V7_0_0)
-        .withApiLevel(AndroidApiLevel.N)
-        .build();
+    return getTestParameters().withDexRuntimesAndAllApiLevels().build();
   }
 
   @Test
diff --git a/src/test/java/com/android/tools/r8/partial/PartialCompilationDataResourcesTest.java b/src/test/java/com/android/tools/r8/partial/PartialCompilationDataResourcesTest.java
index 1cd7ceb..d562f6a 100644
--- a/src/test/java/com/android/tools/r8/partial/PartialCompilationDataResourcesTest.java
+++ b/src/test/java/com/android/tools/r8/partial/PartialCompilationDataResourcesTest.java
@@ -15,7 +15,6 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.ToolHelper.DexVm;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import java.io.InputStream;
@@ -34,11 +33,11 @@
   public TestParameters parameters;
 
   @Parameters(name = "{0}")
-  // Test with min API level 24.
   public static TestParametersCollection data() {
+    // This test uses StandardCharsets which was first introduced in API level 19.
     return getTestParameters()
-        .withDexRuntime(DexVm.Version.V7_0_0)
-        .withApiLevel(AndroidApiLevel.N)
+        .withDexRuntimes()
+        .withApiLevelsStartingAtIncluding(AndroidApiLevel.K)
         .build();
   }
 
diff --git a/src/test/java/com/android/tools/r8/partial/PartialCompilationDemoTest.java b/src/test/java/com/android/tools/r8/partial/PartialCompilationDemoTest.java
index 43ad334..c7dc4dc 100644
--- a/src/test/java/com/android/tools/r8/partial/PartialCompilationDemoTest.java
+++ b/src/test/java/com/android/tools/r8/partial/PartialCompilationDemoTest.java
@@ -19,7 +19,6 @@
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
 import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.ToolHelper.DexVm;
 import com.android.tools.r8.desugar.desugaredlibrary.jdk11.DesugaredLibraryJDK11Undesugarer;
 import com.android.tools.r8.dump.CompilerDump;
 import com.android.tools.r8.tracereferences.TraceReferences;
@@ -66,14 +65,8 @@
   public TestParameters parameters;
 
   @Parameters(name = "{0}")
-  // Test with min API level 24 where default interface methods are supported instead fo using
-  // dump.getBuildProperties().getMinApi(). Tivi has min API 23 and there are currently trace
-  // references issues with CC classes for default interface methods.
   public static TestParametersCollection data() {
-    return getTestParameters()
-        .withDexRuntime(DexVm.Version.V7_0_0)
-        .withApiLevel(AndroidApiLevel.N)
-        .build();
+    return getTestParameters().withDexRuntimesAndAllApiLevels().build();
   }
 
   private void configureDesugaredLibrary(
diff --git a/src/test/java/com/android/tools/r8/partial/PartialCompilationFieldAnnotatedInD8Test.java b/src/test/java/com/android/tools/r8/partial/PartialCompilationFieldAnnotatedInD8Test.java
index e0140e0..e400faf 100644
--- a/src/test/java/com/android/tools/r8/partial/PartialCompilationFieldAnnotatedInD8Test.java
+++ b/src/test/java/com/android/tools/r8/partial/PartialCompilationFieldAnnotatedInD8Test.java
@@ -9,9 +9,7 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.ToolHelper.DexVm.Version;
 import com.android.tools.r8.references.Reference;
-import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.StringUtils;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -30,12 +28,8 @@
   public TestParameters parameters;
 
   @Parameters(name = "{0}")
-  // Test with min API level 24.
   public static TestParametersCollection data() {
-    return getTestParameters()
-        .withDexRuntimesStartingFromIncluding(Version.V7_0_0)
-        .withApiLevel(AndroidApiLevel.N)
-        .build();
+    return getTestParameters().withDexRuntimesAndAllApiLevels().build();
   }
 
   @Test
diff --git a/src/test/java/com/android/tools/r8/partial/PartialCompilationMarkerTest.java b/src/test/java/com/android/tools/r8/partial/PartialCompilationMarkerTest.java
new file mode 100644
index 0000000..634b016
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/partial/PartialCompilationMarkerTest.java
@@ -0,0 +1,52 @@
+// Copyright (c) 2025, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.partial;
+
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.dex.Marker;
+import com.android.tools.r8.dex.Marker.Tool;
+import java.util.Collection;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class PartialCompilationMarkerTest extends TestBase {
+
+  @Parameter(0)
+  public TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withDexRuntimesAndAllApiLevels().build();
+  }
+
+  @Test
+  public void test() throws Exception {
+    testForR8Partial(parameters.getBackend())
+        .addR8IncludedClasses(Foo.class)
+        .addR8ExcludedClasses(Bar.class)
+        .addKeepClassAndMembersRules(Foo.class)
+        .setMinApi(parameters)
+        .compile()
+        .inspect(
+            inspector -> {
+              Collection<Marker> markers = inspector.getMarkers();
+              assertEquals(1, markers.size());
+
+              Marker marker = markers.iterator().next();
+              assertEquals(Tool.R8Partial, marker.getTool());
+            });
+  }
+
+  static class Foo {}
+
+  static class Bar {}
+}
diff --git a/src/test/java/com/android/tools/r8/partial/PartialCompilationMethodAnnotatedInD8Test.java b/src/test/java/com/android/tools/r8/partial/PartialCompilationMethodAnnotatedInD8Test.java
index 2d0f94b..943616f 100644
--- a/src/test/java/com/android/tools/r8/partial/PartialCompilationMethodAnnotatedInD8Test.java
+++ b/src/test/java/com/android/tools/r8/partial/PartialCompilationMethodAnnotatedInD8Test.java
@@ -9,9 +9,7 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.ToolHelper.DexVm.Version;
 import com.android.tools.r8.references.Reference;
-import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.StringUtils;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -30,12 +28,8 @@
   public TestParameters parameters;
 
   @Parameters(name = "{0}")
-  // Test with min API level 24.
   public static TestParametersCollection data() {
-    return getTestParameters()
-        .withDexRuntimesStartingFromIncluding(Version.V7_0_0)
-        .withApiLevel(AndroidApiLevel.N)
-        .build();
+    return getTestParameters().withDexRuntimesAndAllApiLevels().build();
   }
 
   @Test
diff --git a/src/test/java/com/android/tools/r8/partial/PartialCompilationWithDefaultInterfaceMethodTest.java b/src/test/java/com/android/tools/r8/partial/PartialCompilationWithDefaultInterfaceMethodTest.java
index 9d07e01..cf98f60 100644
--- a/src/test/java/com/android/tools/r8/partial/PartialCompilationWithDefaultInterfaceMethodTest.java
+++ b/src/test/java/com/android/tools/r8/partial/PartialCompilationWithDefaultInterfaceMethodTest.java
@@ -3,11 +3,19 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.partial;
 
-import static org.junit.Assume.assumeTrue;
+import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.DEFAULT_METHOD_PREFIX;
+import static com.android.tools.r8.utils.codeinspector.CodeMatchers.invokesMethod;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbstract;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
 
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -27,13 +35,41 @@
 
   @Test
   public void test() throws Exception {
-    // TODO(b/388763735): Enable for all API levels.
-    assumeTrue(parameters.canUseDefaultAndStaticInterfaceMethods());
     testForR8Partial(parameters.getBackend())
         .addR8IncludedClasses(I.class, J.class)
         .addR8ExcludedClasses(Main.class, A.class)
         .setMinApi(parameters)
         .compile()
+        .inspect(
+            inspector -> {
+              if (parameters.canUseDefaultAndStaticInterfaceMethods()) {
+                // Verify that the default interface method was kept.
+                ClassSubject jClassSubject = inspector.clazz(J.class);
+                assertThat(jClassSubject, isPresent());
+
+                MethodSubject jMethodSubject = jClassSubject.uniqueMethodWithOriginalName("m");
+                assertThat(jMethodSubject, isPresent());
+                assertThat(jMethodSubject, not(isAbstract()));
+              } else {
+                // Verify that a bridge was inserted in the D8 part that calls the companion class
+                // method in the R8 part.
+                ClassSubject jCompanionClassSubject =
+                    inspector.clazz(SyntheticItemsTestUtils.syntheticCompanionClass(J.class));
+                assertThat(jCompanionClassSubject, isPresent());
+
+                MethodSubject jCompanionMethodSubject =
+                    jCompanionClassSubject.uniqueMethodWithOriginalName(
+                        DEFAULT_METHOD_PREFIX + "m");
+                assertThat(jCompanionMethodSubject, isPresent());
+
+                ClassSubject aClassSubject = inspector.clazz(A.class);
+                assertThat(aClassSubject, isPresent());
+
+                MethodSubject aMethodSubject = aClassSubject.uniqueMethodWithOriginalName("m");
+                assertThat(aMethodSubject, isPresent());
+                assertThat(aMethodSubject, invokesMethod(jCompanionMethodSubject));
+              }
+            })
         .run(parameters.getRuntime(), Main.class)
         .assertSuccessWithOutputLines("Hello, world!");
   }
diff --git a/src/test/java/com/android/tools/r8/partial/PartialShrinkingPreviewApiTest.java b/src/test/java/com/android/tools/r8/partial/PartialShrinkingPreviewApiTest.java
index f5784c5..ed3093b 100644
--- a/src/test/java/com/android/tools/r8/partial/PartialShrinkingPreviewApiTest.java
+++ b/src/test/java/com/android/tools/r8/partial/PartialShrinkingPreviewApiTest.java
@@ -3,10 +3,14 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.partial;
 
+import static com.android.tools.r8.MarkerMatcher.markerBackend;
+import static com.android.tools.r8.MarkerMatcher.markerCompilationMode;
 import static com.android.tools.r8.MarkerMatcher.markerMinApi;
-import static com.android.tools.r8.MarkerMatcher.markerR8Mode;
+import static com.android.tools.r8.MarkerMatcher.markerTool;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
 
+import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.DexIndexedConsumer;
 import com.android.tools.r8.ProgramConsumer;
 import com.android.tools.r8.R8;
@@ -14,11 +18,14 @@
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.compilerapi.CompilerApiTest;
 import com.android.tools.r8.compilerapi.CompilerApiTestRunner;
+import com.android.tools.r8.dex.Marker;
+import com.android.tools.r8.dex.Marker.Tool;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.ThrowingConsumer;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import java.nio.file.Path;
+import java.util.Collection;
 import org.hamcrest.CoreMatchers;
 import org.junit.Test;
 
@@ -44,12 +51,17 @@
   private void runTest(ThrowingConsumer<ProgramConsumer, Exception> test) throws Exception {
     Path output = temp.newFolder().toPath().resolve("out.jar");
     test.accept(new DexIndexedConsumer.ArchiveConsumer(output));
+
+    Collection<Marker> markers = new CodeInspector(output).getMarkers();
+    assertEquals(1, markers.size());
     assertThat(
-        new CodeInspector(output).getMarkers(),
+        markers,
         CoreMatchers.everyItem(
             CoreMatchers.allOf(
+                markerBackend(Backend.DEX),
+                markerCompilationMode(CompilationMode.RELEASE),
                 markerMinApi(AndroidApiLevel.getAndroidApiLevel(MIN_API_LEVEL)),
-                markerR8Mode("full"))));
+                markerTool(Tool.R8Partial))));
   }
 
   public static class ApiTest extends CompilerApiTest {
diff --git a/src/test/testbase/java/com/android/tools/r8/TestBaseResult.java b/src/test/testbase/java/com/android/tools/r8/TestBaseResult.java
index b643e54..3cd499e 100644
--- a/src/test/testbase/java/com/android/tools/r8/TestBaseResult.java
+++ b/src/test/testbase/java/com/android/tools/r8/TestBaseResult.java
@@ -19,7 +19,7 @@
     return fn.applyWithRuntimeException(self());
   }
 
-  public <T extends Throwable> CR apply(ThrowableConsumer<CR> fn) {
+  public <T extends Throwable> CR apply(ThrowableConsumer<? super CR> fn) {
     fn.acceptWithRuntimeException(self());
     return self();
   }
diff --git a/src/test/testbase/java/com/android/tools/r8/TestCompilerBuilder.java b/src/test/testbase/java/com/android/tools/r8/TestCompilerBuilder.java
index ed19826..4ba36aa 100644
--- a/src/test/testbase/java/com/android/tools/r8/TestCompilerBuilder.java
+++ b/src/test/testbase/java/com/android/tools/r8/TestCompilerBuilder.java
@@ -176,6 +176,8 @@
           DEFAULT_OPTIONS.andThen(
               options -> {
                 options.partialCompilationConfiguration.d8DexOptionsConsumer = DEFAULT_D8_OPTIONS;
+                options.partialCompilationConfiguration.d8DesugarOptionsConsumer =
+                    DEFAULT_D8_OPTIONS;
                 options.partialCompilationConfiguration.d8MergeOptionsConsumer = DEFAULT_D8_OPTIONS;
                 options.partialCompilationConfiguration.r8OptionsConsumer = DEFAULT_R8_OPTIONS;
               });