Update DEX container generation

Include container size in the header of each section.

Bug: b/249922554
Change-Id: Ie34fb729abc04cf7245e4bf544584017f3cc7173
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationReader.java b/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
index eda00f9..b58107d 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
@@ -390,7 +390,7 @@
         assert tmp.getDexVersion() == DexVersion.V41;
         assert dexReader.getUint(offset + Constants.HEADER_SIZE_OFFSET)
             == Constants.TYPE_HEADER_ITEM_SIZE_V41;
-        assert dexReader.getUint(offset + Constants.HEADER_OFF_OFFSET) == offset;
+        assert dexReader.getUint(offset + Constants.CONTAINER_OFF_OFFSET) == offset;
         int dataSize = dexReader.getUint(offset + Constants.DATA_SIZE_OFFSET);
         int dataOffset = dexReader.getUint(offset + Constants.DATA_OFF_OFFSET);
         int file_size = dexReader.getUint(offset + Constants.FILE_SIZE_OFFSET);
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationWriterExperimental.java b/src/main/java/com/android/tools/r8/dex/ApplicationWriterExperimental.java
index 0a81bd2..853d01e 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriterExperimental.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriterExperimental.java
@@ -183,7 +183,11 @@
     DexContainerSection lastSection = ListUtils.last(sections);
     int stringIdsSize = lastSection.getFileWriter().getMixedSectionOffsets().getStringData().size();
     int stringIdsOffset = lastSection.getLayout().stringIdsOffset;
+    int containerSize = lastSection.getLayout().getEndOfFile();
     for (DexContainerSection section : sections) {
+      // Update container size in all sections.
+      dexOutputBuffer.moveTo(section.getLayout().headerOffset + Constants.CONTAINER_SIZE_OFFSET);
+      dexOutputBuffer.putInt(containerSize);
       if (section != lastSection) {
         // Update the string_ids size and offset in the header.
         dexOutputBuffer.moveTo(section.getLayout().headerOffset + Constants.STRING_IDS_SIZE_OFFSET);
diff --git a/src/main/java/com/android/tools/r8/dex/Constants.java b/src/main/java/com/android/tools/r8/dex/Constants.java
index 912f4f1..9de8120 100644
--- a/src/main/java/com/android/tools/r8/dex/Constants.java
+++ b/src/main/java/com/android/tools/r8/dex/Constants.java
@@ -45,14 +45,15 @@
   public static final int CLASS_DEFS_OFF_OFFSET = CLASS_DEFS_SIZE_OFFSET + 4;
   public static final int DATA_SIZE_OFFSET = CLASS_DEFS_OFF_OFFSET + 4;
   public static final int DATA_OFF_OFFSET = DATA_SIZE_OFFSET + 4;
-  public static final int HEADER_OFF_OFFSET = DATA_OFF_OFFSET + 4;
+  public static final int CONTAINER_SIZE_OFFSET = DATA_OFF_OFFSET + 4;
+  public static final int CONTAINER_OFF_OFFSET = CONTAINER_SIZE_OFFSET + 4;
 
   public static final int ENDIAN_CONSTANT = 0x12345678;
   public static final int REVERSE_ENDIAN_CONSTANT = 0x78563412;
 
   public static final int TYPE_HEADER_ITEM = 0x0;
   public static final int TYPE_HEADER_ITEM_SIZE = 0x70;
-  public static final int TYPE_HEADER_ITEM_SIZE_V41 = 0x74;
+  public static final int TYPE_HEADER_ITEM_SIZE_V41 = 0x78;
   public static final int TYPE_STRING_ID_ITEM = 0x0001;
   public static final int TYPE_STRING_ID_ITEM_SIZE = 0x04;
   public static final int TYPE_TYPE_ID_ITEM = 0x0002;
diff --git a/src/main/java/com/android/tools/r8/dex/FileWriter.java b/src/main/java/com/android/tools/r8/dex/FileWriter.java
index 25d19b0..8c6f33a 100644
--- a/src/main/java/com/android/tools/r8/dex/FileWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/FileWriter.java
@@ -825,9 +825,11 @@
     dest.putInt(numberOfClasses);
     dest.putInt(numberOfClasses == 0 ? 0 : layout.classDefsOffset);
     if (layout.isContainerSection()) {
-      dest.putInt(0);
-      dest.putInt(0);
-      dest.putInt(layout.headerOffset);
+      // Fields data_size and data_off are zero for all sections in a container DEX.
+      dest.putInt(0); // data_size
+      dest.putInt(0); // data_off
+      dest.putInt(0); // container_size will be updated in final pass.
+      dest.putInt(layout.headerOffset); // container_off
     } else {
       dest.putInt(layout.getDataSectionSize());
       dest.putInt(layout.dataSectionOffset);
diff --git a/src/test/java/com/android/tools/r8/dex/container/DexContainerFormatBasicTest.java b/src/test/java/com/android/tools/r8/dex/container/DexContainerFormatBasicTest.java
index 25b028a..81d709c9 100644
--- a/src/test/java/com/android/tools/r8/dex/container/DexContainerFormatBasicTest.java
+++ b/src/test/java/com/android/tools/r8/dex/container/DexContainerFormatBasicTest.java
@@ -4,11 +4,12 @@
 package com.android.tools.r8.dex.container;
 
 import static com.android.tools.r8.dex.Constants.CHECKSUM_OFFSET;
+import static com.android.tools.r8.dex.Constants.CONTAINER_OFF_OFFSET;
+import static com.android.tools.r8.dex.Constants.CONTAINER_SIZE_OFFSET;
 import static com.android.tools.r8.dex.Constants.DATA_OFF_OFFSET;
 import static com.android.tools.r8.dex.Constants.DATA_SIZE_OFFSET;
 import static com.android.tools.r8.dex.Constants.DEX_MAGIC_SIZE;
 import static com.android.tools.r8.dex.Constants.FILE_SIZE_OFFSET;
-import static com.android.tools.r8.dex.Constants.HEADER_OFF_OFFSET;
 import static com.android.tools.r8.dex.Constants.HEADER_SIZE_OFFSET;
 import static com.android.tools.r8.dex.Constants.MAP_OFF_OFFSET;
 import static com.android.tools.r8.dex.Constants.SIGNATURE_OFFSET;
@@ -260,7 +261,8 @@
       assertEquals(0, buffer.getInt(offset + DATA_SIZE_OFFSET));
       assertEquals(0, buffer.getInt(offset + DATA_OFF_OFFSET));
       // Additional header field from V41.
-      assertEquals(offset, buffer.getInt(offset + HEADER_OFF_OFFSET));
+      assertEquals(buffer.capacity(), buffer.getInt(offset + CONTAINER_SIZE_OFFSET));
+      assertEquals(offset, buffer.getInt(offset + CONTAINER_OFF_OFFSET));
     }
     assertEquals(stringIdsSize, getSizeFromMap(TYPE_STRING_ID_ITEM, buffer, offset));
     assertEquals(stringIdsOffset, getOffsetFromMap(TYPE_STRING_ID_ITEM, buffer, offset));