Migrate multidex to androidx

Bug: 74397601
Test: make
Change-Id: Iddea6f92cc7796125cf4d1ba86cf9b7425daef72
diff --git a/library/src/androidx/multidex/ZipUtil.java b/library/src/androidx/multidex/ZipUtil.java
new file mode 100644
index 0000000..fc33623
--- /dev/null
+++ b/library/src/androidx/multidex/ZipUtil.java
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/* Apache Harmony HEADER because the code in this class comes mostly from ZipFile, ZipEntry and
+ * ZipConstants from android libcore.
+ */
+
+package androidx.multidex;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.util.zip.CRC32;
+import java.util.zip.ZipException;
+
+/**
+ * Tools to build a quick partial crc of zip files.
+ */
+final class ZipUtil {
+    static class CentralDirectory {
+        long offset;
+        long size;
+    }
+
+    /* redefine those constant here because of bug 13721174 preventing to compile using the
+     * constants defined in ZipFile */
+    private static final int ENDHDR = 22;
+    private static final int ENDSIG = 0x6054b50;
+
+    /**
+     * Size of reading buffers.
+     */
+    private static final int BUFFER_SIZE = 0x4000;
+
+    /**
+     * Compute crc32 of the central directory of an apk. The central directory contains
+     * the crc32 of each entries in the zip so the computed result is considered valid for the whole
+     * zip file. Does not support zip64 nor multidisk but it should be OK for now since ZipFile does
+     * not either.
+     */
+    static long getZipCrc(File apk) throws IOException {
+        RandomAccessFile raf = new RandomAccessFile(apk, "r");
+        try {
+            CentralDirectory dir = findCentralDirectory(raf);
+
+            return computeCrcOfCentralDir(raf, dir);
+        } finally {
+            raf.close();
+        }
+    }
+
+    /* Package visible for testing */
+    static CentralDirectory findCentralDirectory(RandomAccessFile raf) throws IOException,
+            ZipException {
+        long scanOffset = raf.length() - ENDHDR;
+        if (scanOffset < 0) {
+            throw new ZipException("File too short to be a zip file: " + raf.length());
+        }
+
+        long stopOffset = scanOffset - 0x10000 /* ".ZIP file comment"'s max length */;
+        if (stopOffset < 0) {
+            stopOffset = 0;
+        }
+
+        int endSig = Integer.reverseBytes(ENDSIG);
+        while (true) {
+            raf.seek(scanOffset);
+            if (raf.readInt() == endSig) {
+                break;
+            }
+
+            scanOffset--;
+            if (scanOffset < stopOffset) {
+                throw new ZipException("End Of Central Directory signature not found");
+            }
+        }
+        // Read the End Of Central Directory. ENDHDR includes the signature
+        // bytes,
+        // which we've already read.
+
+        // Pull out the information we need.
+        raf.skipBytes(2); // diskNumber
+        raf.skipBytes(2); // diskWithCentralDir
+        raf.skipBytes(2); // numEntries
+        raf.skipBytes(2); // totalNumEntries
+        CentralDirectory dir = new CentralDirectory();
+        dir.size = Integer.reverseBytes(raf.readInt()) & 0xFFFFFFFFL;
+        dir.offset = Integer.reverseBytes(raf.readInt()) & 0xFFFFFFFFL;
+        return dir;
+    }
+
+    /* Package visible for testing */
+    static long computeCrcOfCentralDir(RandomAccessFile raf, CentralDirectory dir)
+            throws IOException {
+        CRC32 crc = new CRC32();
+        long stillToRead = dir.size;
+        raf.seek(dir.offset);
+        int length = (int) Math.min(BUFFER_SIZE, stillToRead);
+        byte[] buffer = new byte[BUFFER_SIZE];
+        length = raf.read(buffer, 0, length);
+        while (length != -1) {
+            crc.update(buffer, 0, length);
+            stillToRead -= length;
+            if (stillToRead == 0) {
+                break;
+            }
+            length = (int) Math.min(BUFFER_SIZE, stillToRead);
+            length = raf.read(buffer, 0, length);
+        }
+        return crc.getValue();
+    }
+}