Merge "Revert "Move tests to postsubmit to reduce lab reporting load temporarily""
diff --git a/JavaLibrary.bp b/JavaLibrary.bp
index 51c194e..7425695 100644
--- a/JavaLibrary.bp
+++ b/JavaLibrary.bp
@@ -52,7 +52,6 @@
     ],
     path: "luni/src/main/java/",
     srcs: [
-        "luni/src/main/java/libcore/net/android.mime.types",
         "luni/src/main/java/java/util/logging/logging.properties",
         "luni/src/main/java/java/security/security.properties",
     ],
@@ -72,7 +71,6 @@
 core_resources = [
     ":core-luni-resources",
     ":core-ojluni-resources",
-    ":debian.mime.types",
 ]
 
 // The source files that go into core-oj.
@@ -114,6 +112,8 @@
 // The set of files for the core library that have been marked up with @hide
 // for the public SDK APIs. Used from frameworks/base/ to indicate the source
 // files for inclusion in the public SDK docs.
+//
+// Deprecated: Will be replaced by core-current-stubs-source.
 filegroup {
     name: "core_public_api_files",
     visibility: [
@@ -127,24 +127,42 @@
     ],
 }
 
-// The set of files for the core library that have been marked up with @hide and
-// API-related annotations. Note that this includes the intra-core and
-// core-platform APIs as well as the public APIs.
+// Contains the stubs source for the part of the Android SDK public API which
+// is provided by the core libraries.
+//
+// Currently is only a placeholder that creates an empty srcjar due to issues
+// caused by http://b/142113901.
+//
+// TODO(http://b/142113521) - Add stubs source for the core library modules.
+genrule {
+    name: "core-current-stubs-source",
+    visibility: [
+        "//frameworks/base",
+    ],
+    tools: [
+        "merge_zips",
+    ],
+    out: ["core-current-stubs-source.srcjar"],
+    cmd: "$(location merge_zips) $(out)",
+}
+
+// The set of files for the ART module that contribute to one or more API
+// surfaces. This includes files that are in the public API as well as those
+// that are not but which have been marked up with @hide plus one or more of
+// the API defining annotations.
 //
 // Some source files in :core_oj_api_files and :openjdk_mmodule_extra_files are
 // annotated by applying annotations to the .annotated.java stubs files in
 // ojluni/annotated/mmodules and rather than in the original source. See the comments
 // in openjdk_java_files.bp for more details.
 filegroup {
-    name: "core_api_files",
+    name: "art_module_api_files",
     visibility: [
         "//libcore:__subpackages__",
     ],
     srcs: [
-        ":android_icu4j_src_files",
         ":apache-xml_api_files",
         ":bouncycastle_java_files",
-        ":conscrypt_java_files",
         ":core_oj_api_files",
         ":core_libart_api_files",
         ":okhttp_api_files",
@@ -171,28 +189,18 @@
 // Build for the target (device).
 //
 
-// Visibility of core-all* build modules; we restrict visibility of core-all deliberately to
-// a small set of build modules that the core library team control. See core-all-system-modules
-// for more details.
-core_all_visibility = [
-    "//external/apache-harmony:__subpackages__",
-    "//external/apache-xml",
-    "//external/bouncycastle",
-    "//external/conscrypt",
-    "//external/icu/android_icu4j",
-    "//external/okhttp",
-    "//libcore:__subpackages__",
-]
-
 // A target used to bootstrap compilation for the core library.
+//
 // See core-all-system-modules for more details.
 java_library {
     name: "core-all",
-    visibility: core_all_visibility,
     defaults: ["libcore_java_defaults"],
 
     srcs: [
-        ":android_icu4j_src_files",
+        // Use the source code for the I18N module intra core API as using the
+        // compiled version does not work due to limitations in either soong or the javac
+        // toolchain. See http://b/142056316 for more details.
+        ":i18n-module-intra-core-api-stubs-source",
         ":core_oj_java_files",
         ":core_libart_java_files",
         ":openjdk_lambda_stub_files",
@@ -207,7 +215,6 @@
     },
 
     java_resources: core_resources,
-    static_libs: ["android_icu4j_resources_lib"],
     java_version: "1.9",
 
     installable: false,
@@ -225,11 +232,20 @@
 // core-libart as well as the lambda stubs needed to compile Java lambda code.
 // It does not contain other parts of core library like conscrypt, bouncycastle,
 // etc. This system_modules definition is used to bootstrap compilation for
-// other parts of the core library like core-oj, core-libart, core-icu4j, conscrypt,
+// other parts of the core library like core-oj, core-libart, conscrypt,
 // bouncycastle, etc.
 java_system_modules {
     name: "core-all-system-modules",
-    visibility: core_all_visibility,
+
+    // Visibility is deliberately restricted to a small set of build modules that
+    // the core library team control.
+    visibility: [
+        "//external/apache-harmony:__subpackages__",
+        "//external/apache-xml",
+        "//external/okhttp",
+        "//libcore:__subpackages__",
+    ],
+
     libs: ["core-all"],
 }
 
@@ -323,32 +339,6 @@
     },
 }
 
-// A separated core library that contains ICU4J because ICU4J will be in a different APEX module,
-// not in Runtime module.
-java_library {
-    name: "core-icu4j",
-    visibility: [
-        "//art/build/apex",
-        "//external/robolectric-shadows",
-        "//frameworks/layoutlib",
-    ],
-    defaults: ["libcore_java_defaults"],
-    installable: true,
-    hostdex: true,
-
-    srcs: [":android_icu4j_src_files"],
-    libs: ["libcore-unsupportedappusage-annotation"],
-    static_libs: ["android_icu4j_resources_lib_sdk_core_current"],
-
-    // We use art-module-public-api-stubs-system-modules when compiling core-icu4j as ICU4J does not
-    // use any internal or android specific code. If it ever did then it could depend on
-    // core-intra-stubs-system-modules (a superset) instead.
-    // It is important that core-icu4j is restricted to only use stable APIs from the ART module
-    // since it is in a different APEX module that can be updated independently.
-    sdk_version: "none",
-    system_modules: "art-module-public-api-stubs-system-modules",
-}
-
 // Provided solely to contribute information about which hidden parts of the
 // core-oj API are used by apps.
 //
@@ -386,7 +376,7 @@
 }
 
 //
-// Guaranteed unstripped versions of core-icu4j, core-oj and core-libart.
+// Guaranteed unstripped versions of core-oj and core-libart.
 //
 // The build system may or may not strip the core-oj and core-libart jars,
 // but these will not be stripped. See b/24535627.
@@ -419,18 +409,6 @@
     notice: "ojluni/NOTICE",
 }
 
-java_library {
-    name: "core-icu4j-testdex",
-    installable: true,
-    static_libs: ["core-icu4j"],
-    sdk_version: "none",
-    system_modules: "core-all-system-modules",
-    dxflags: ["--core-library"],
-    dex_preopt: {
-        enabled: false,
-    },
-}
-
 java_defaults {
     name: "core_lambda_stubs_defaults",
     defaults: ["libcore_java_defaults"],
@@ -770,6 +748,10 @@
 // A stubs target containing the parts of the public SDK API provided by the ART module.
 java_library {
     name: "art.module.public.api.stubs",
+    visibility: [
+        "//external/conscrypt",
+        "//external/icu/android_icu4j",
+    ],
     srcs: [":art-module-public-api-stubs-gen"],
     errorprone: {
         javacflags: [
@@ -784,9 +766,14 @@
 }
 
 // Used when compiling higher-level code against art.module.public.api.stubs.
+//
+// This is only intended for use within core libraries and must not be used
+// from outside.
 java_system_modules {
     name: "art-module-public-api-stubs-system-modules",
     visibility: [
+        "//external/conscrypt",
+        "//external/icu/android_icu4j",
         "//external/wycheproof",
     ],
     libs: [
@@ -799,65 +786,12 @@
         // tools.
         // See http://b/123891440.
         "core-generated-annotation-stubs",
-    ],
-}
 
-// Generates stubs for the parts of the public SDK API provided by the conscrypt module.
-//
-// Only for use by conscrypt.module.public.api.stubs target below.
-droidstubs {
-    name: "conscrypt-module-public-api-stubs-gen",
-    srcs: [
-        ":conscrypt_public_api_files",
+        // Ensure that core libraries that depend on the public API can access
+        // the UnsupportedAppUsage, CorePlatformApi and IntraCoreApi
+        // annotations.
+        "libcore-unsupportedappusage-annotation",
     ],
-    java_version: "1.9",
-    installable: false,
-    sdk_version: "none",
-    libs: [
-        "art.module.public.api.stubs",
-    ],
-}
-
-// A stubs target containing the parts of the public SDK API provided by the conscrypt module.
-java_library {
-    name: "conscrypt.module.public.api.stubs",
-    srcs: [":conscrypt-module-public-api-stubs-gen"],
-    errorprone: {
-        javacflags: [
-            "-Xep:MissingOverride:OFF",
-        ],
-    },
-    sdk_version: "none",
-    system_modules: "art-module-public-api-stubs-system-modules",
-}
-
-// Generates stubs for the parts of the public SDK API provided by the i18n module.
-//
-// Only for use by i18n.module.public.api.stubs target below.
-droidstubs {
-    name: "i18n-module-public-api-stubs-gen",
-    srcs: [
-        ":android_icu4j_src_files",
-    ],
-    java_version: "1.9",
-    installable: false,
-    sdk_version: "none",
-    libs: [
-        "art.module.public.api.stubs",
-    ],
-}
-
-// A stubs target containing the parts of the public SDK API provided by the i18n module.
-java_library {
-    name: "i18n.module.public.api.stubs",
-    srcs: [":i18n-module-public-api-stubs-gen"],
-    errorprone: {
-        javacflags: [
-            "-Xep:MissingOverride:OFF",
-        ],
-    },
-    sdk_version: "none",
-    system_modules: "art-module-public-api-stubs-system-modules",
 }
 
 // A stubs target containing the parts of the public SDK API provided by the
@@ -902,14 +836,14 @@
 
 // Target for validating nullability annotations for correctness and
 // completeness. To check that there are no nullability errors:
-//   make core-current-stubs-nullability-validation
+//   m art-module-public-api-stubs-nullability-validation
 // To check that there are only the expected nullability warnings:
-//   make core-current-stubs-nullability-validation-check-nullability-warnings
-// To update the the list of known expected nullability warnings:
-//   make core-current-stubs-nullability-validation-update-nullability-warnings
+//   m art-module-public-api-stubs-nullability-validation-check-nullability-warnings
+// (If that check fails, it will provide instructions on how to proceed,
+// including the command to run to update the expected warnings file.)
 droidstubs {
-    name: "core-current-stubs-nullability-validation",
-    srcs: [":core_api_files"],
+    name: "art-module-public-api-stubs-nullability-validation",
+    srcs: [":art_module_api_files"],
     installable: false,
     sdk_version: "none",
     annotations_enabled: true,
@@ -939,6 +873,15 @@
     srcs: [":timezone_host_files"],
 }
 
+// A special set of system modules for building the following library for use
+// in the art-module-public-api-system-modules.
+java_system_modules {
+    name: "api-annotations-system-modules",
+    libs: [
+        "art.module.public.api.stubs",
+    ],
+}
+
 // A library that contains annotations not retented in runtime and inline-able constants
 // that should not introduce any runtime dependency for compiling core libraries, e.g. core-icu4j,
 java_library {
@@ -948,7 +891,9 @@
     ],
 
     installable: false,
-    sdk_version: "core_current",
+    sdk_version: "none",
+    system_modules: "api-annotations-system-modules",
+    patch_module: "java.base",
 }
 
 // The source files that contain the UnsupportedAppUsage annotation and its dependencies.
diff --git a/luni/src/main/java/java/net/DefaultFileNameMap.java b/luni/src/main/java/java/net/DefaultFileNameMap.java
index d290ffe..cdd4214 100644
--- a/luni/src/main/java/java/net/DefaultFileNameMap.java
+++ b/luni/src/main/java/java/net/DefaultFileNameMap.java
@@ -16,10 +16,10 @@
 
 package java.net;
 
-import libcore.net.MimeMap;
+import libcore.content.type.MimeMap;
 
 /**
- * Implements {@link FileNameMap} in terms of {@link libcore.net.MimeMap}.
+ * Implements {@link FileNameMap} in terms of {@link MimeMap}.
  */
 class DefaultFileNameMap implements FileNameMap {
     public String getContentTypeFor(String filename) {
diff --git a/luni/src/main/java/libcore/content/type/MimeMap.java b/luni/src/main/java/libcore/content/type/MimeMap.java
new file mode 100644
index 0000000..51e792f
--- /dev/null
+++ b/luni/src/main/java/libcore/content/type/MimeMap.java
@@ -0,0 +1,408 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed 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.
+ */
+
+package libcore.content.type;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.Supplier;
+import libcore.api.CorePlatformApi;
+import libcore.util.NonNull;
+import libcore.util.Nullable;
+
+/**
+ * Maps from MIME types to file extensions and back.
+ *
+ * @hide
+ */
+@libcore.api.CorePlatformApi
+public final class MimeMap {
+
+    @CorePlatformApi
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    @CorePlatformApi
+    public Builder buildUpon() {
+        return new Builder(mimeToExt, extToMime);
+    }
+
+    // Contain only lowercase, valid keys/values.
+    private final Map<String, String> mimeToExt;
+    private final Map<String, String> extToMime;
+
+    /**
+     * A basic implementation of MimeMap used if a new default isn't explicitly
+     * {@link MimeMap#setDefaultSupplier(Supplier) installed}. Hard-codes enough
+     * mappings to satisfy libcore tests. Android framework code is expected to
+     * replace this implementation during runtime initialization.
+     */
+    private static volatile MemoizingSupplier<@NonNull MimeMap> instanceSupplier =
+            new MemoizingSupplier<>(
+                    () -> builder()
+                            .put("application/pdf", "pdf")
+                            .put("image/jpeg", "jpg")
+                            .put("image/x-ms-bmp", "bmp")
+                            .put("text/html", Arrays.asList("htm", "html"))
+                            .put("text/plain", Arrays.asList("text", "txt"))
+                            .put("text/x-java", "java")
+                            .build());
+
+    private MimeMap(Map<String, String> mimeToExt, Map<String, String> extToMime) {
+        this.mimeToExt = Objects.requireNonNull(mimeToExt);
+        this.extToMime = Objects.requireNonNull(extToMime);
+        for (Map.Entry<String, String> entry : this.mimeToExt.entrySet()) {
+            checkValidMimeType(entry.getKey());
+            checkValidExtension(entry.getValue());
+        }
+        for (Map.Entry<String, String> entry : this.extToMime.entrySet()) {
+            checkValidExtension(entry.getKey());
+            checkValidMimeType(entry.getValue());
+        }
+    }
+
+    /**
+     * @return The system's current default {@link MimeMap}.
+     */
+    @libcore.api.CorePlatformApi
+    public static @NonNull MimeMap getDefault() {
+        return Objects.requireNonNull(instanceSupplier.get());
+    }
+
+    /**
+     * Sets the {@link Supplier} of the {@link #getDefault() default MimeMap
+     * instance} to be used from now on.
+     *
+     * {@code mimeMapSupplier.get()} will be invoked only the first time that
+     * {@link #getDefault()} is called after this method call; that
+     * {@link MimeMap} instance is memoized such that subsequent calls to
+     * {@link #getDefault()} without an intervening call to
+     * {@link #setDefaultSupplier(Supplier)} will return that same instance
+     * without consulting {@code mimeMapSupplier} a second time.
+     */
+    @libcore.api.CorePlatformApi
+    public static void setDefaultSupplier(@NonNull Supplier<@NonNull MimeMap> mimeMapSupplier) {
+        instanceSupplier = new MemoizingSupplier<>(Objects.requireNonNull(mimeMapSupplier));
+    }
+
+    /**
+     * Returns whether the given case insensitive extension has a registered MIME type.
+     *
+     * @param extension A file extension without the leading '.'
+     * @return Whether a MIME type has been registered for the given case insensitive file
+     *         extension.
+     */
+    @libcore.api.CorePlatformApi
+    public final boolean hasExtension(@Nullable String extension) {
+        return guessMimeTypeFromExtension(extension) != null;
+    }
+
+    /**
+     * Returns the MIME type for the given case insensitive file extension, or null
+     * if the extension isn't mapped to any.
+     *
+     * @param extension A file extension without the leading '.'
+     * @return The lower-case MIME type registered for the given case insensitive file extension,
+     *         or null if there is none.
+     */
+    @libcore.api.CorePlatformApi
+    public final @Nullable String guessMimeTypeFromExtension(@Nullable String extension) {
+        if (extension == null) {
+            return null;
+        }
+        extension = toLowerCase(extension);
+        return extToMime.get(extension);
+    }
+
+    /**
+     * @param mimeType A MIME type (i.e. {@code "text/plain")
+     * @return Whether the given case insensitive MIME type is
+     *         {@link #guessMimeTypeFromExtension(String) mapped} to a file extension.
+     */
+    @libcore.api.CorePlatformApi
+    public final boolean hasMimeType(@Nullable String mimeType) {
+        return guessExtensionFromMimeType(mimeType) != null;
+    }
+
+    /**
+     * Returns the registered extension for the given case insensitive MIME type. Note that some
+     * MIME types map to multiple extensions. This call will return the most
+     * common extension for the given MIME type.
+     * @param mimeType A MIME type (i.e. text/plain)
+     * @return The lower-case file extension (without the leading "." that has been registered for
+     *         the given case insensitive MIME type, or null if there is none.
+     */
+    @libcore.api.CorePlatformApi
+    public final @Nullable String guessExtensionFromMimeType(@Nullable String mimeType) {
+        if (mimeType == null) {
+            return null;
+        }
+        mimeType = toLowerCase(mimeType);
+        return mimeToExt.get(mimeType);
+    }
+
+    /**
+     * Returns the set of MIME types that this {@link MimeMap}
+     * {@link #hasMimeType(String) maps to some extension}. Note that the
+     * reverse mapping might not exist.
+     *
+     * @hide
+     */
+    @libcore.api.CorePlatformApi
+    public @NonNull Set<String> mimeTypes() {
+        return Collections.unmodifiableSet(mimeToExt.keySet());
+    }
+
+    /**
+     * Returns the set of extensions that this {@link MimeMap}
+     * {@link #hasExtension(String) maps to some MIME type}. Note that the
+     * reverse mapping might not exist.
+     *
+     * @hide
+     */
+    @libcore.api.CorePlatformApi
+    public @NonNull Set<String> extensions() {
+        return Collections.unmodifiableSet(extToMime.keySet());
+    }
+
+    /**
+     * Returns the canonical (lowercase) form of the given extension or MIME type.
+     */
+    private static @NonNull String toLowerCase(@NonNull String s) {
+        return s.toLowerCase(Locale.ROOT);
+    }
+
+    private volatile int hashCode = 0;
+
+    @Override
+    public int hashCode() {
+        if (hashCode == 0) { // potentially uninitialized
+            hashCode = mimeToExt.hashCode() + 31 * extToMime.hashCode();
+        }
+        return hashCode;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof MimeMap)) {
+            return false;
+        }
+        MimeMap that = (MimeMap) obj;
+        if (hashCode() != that.hashCode()) {
+            return false;
+        }
+        return mimeToExt.equals(that.mimeToExt) && extToMime.equals(that.extToMime);
+    }
+
+    @Override
+    public String toString() {
+        return "MimeMap[" + mimeToExt + ", " + extToMime + "]";
+    }
+
+    /**
+     * @hide
+     */
+    @libcore.api.CorePlatformApi
+    public static final class Builder {
+        private final Map<String, String> mimeToExt;
+        private final Map<String, String> extToMime;
+
+        /**
+         * Constructs a Builder that starts with an empty mapping.
+         */
+        Builder() {
+            this.mimeToExt = new HashMap<>();
+            this.extToMime = new HashMap<>();
+        }
+
+        /**
+         * Constructs a Builder that starts with the given mapping.
+         * @param mimeToExt
+         * @param extToMime
+         */
+        Builder(Map<String, String> mimeToExt, Map<String, String> extToMime) {
+            this.mimeToExt = new HashMap<>(mimeToExt);
+            this.extToMime = new HashMap<>(extToMime);
+        }
+
+        /**
+         * An element of a *mime.types file.
+         */
+        static class Element {
+            final String mimeOrExt;
+            final boolean keepExisting;
+
+            /**
+             * @param spec A MIME type or an extension, with an optional
+             *        prefix of "?" (if not overriding an earlier value).
+             * @param isMimeSpec whether this Element denotes a MIME type (as opposed to an
+             *        extension).
+             */
+            private Element(String spec, boolean isMimeSpec) {
+                if (spec.startsWith("?")) {
+                    this.keepExisting = true;
+                    this.mimeOrExt = toLowerCase(spec.substring(1));
+                } else {
+                    this.keepExisting = false;
+                    this.mimeOrExt = toLowerCase(spec);
+                }
+                if (isMimeSpec) {
+                    checkValidMimeType(mimeOrExt);
+                } else {
+                    checkValidExtension(mimeOrExt);
+                }
+            }
+
+            public static Element ofMimeSpec(String s) { return new Element(s, true); }
+            public static Element ofExtensionSpec(String s) { return new Element(s, false); }
+        }
+
+        private static String maybePut(Map<String, String> map, Element keyElement, String value) {
+            if (keyElement.keepExisting) {
+                return map.putIfAbsent(keyElement.mimeOrExt, value);
+            } else {
+                return map.put(keyElement.mimeOrExt, value);
+            }
+        }
+
+        /**
+         * Puts the mapping {@quote mimeType -> first extension}, and also the mappings
+         * {@quote extension -> mimeType} for each given extension.
+         *
+         * The values passed to this function are carry an optional  prefix of {@quote "?"}
+         * which is stripped off in any case before any such key/value is added to a mapping.
+         * The prefix {@quote "?"} controls whether the mapping <i>from></i> the corresponding
+         * value is added via {@link Map#putIfAbsent} semantics ({@quote "?"}
+         * present) vs. {@link Map#put} semantics ({@quote "?" absent}),
+         *
+         * For example, {@code put("text/html", "?htm", "html")} would add the following
+         * mappings:
+         * <ol>
+         *   <li>MIME type "text/html" -> extension "htm", overwriting any earlier mapping
+         *       from MIME type "text/html" that might already have existed.</li>
+         *   <li>extension "htm" -> MIME type "text/html", but only if no earlier mapping
+         *       for extension "htm" existed.</li>
+         *   <li>extension "html" -> MIME type "text/html", overwriting any earlier mapping
+         *       from extension "html" that might already have existed.</li>
+         * </ol>
+         * {@code put("?text/html", "?htm", "html")} would have the same effect except
+         * that an earlier mapping from MIME type {@code "text/html"} would not be
+         * overwritten.
+         *
+         * @param mimeSpec A MIME type carrying an optional prefix of {@code "?"}. If present,
+         *                 the {@code "?"} is stripped off and mapping for the resulting MIME
+         *                 type is only added to the map if no mapping had yet existed for that
+         *                 type.
+         * @param extensionSpecs The extensions from which to add mappings back to
+         *                 the {@code "?"} is stripped off and mapping for the resulting extension
+         *                 is only added to the map if no mapping had yet existed for that
+         *                 extension.
+         *                 If {@code extensionSpecs} is empty, then calling this method has no
+         *                 effect on the mapping that is being constructed.
+         * @throws IllegalArgumentException if {@code mimeSpec} or any of the {@code extensionSpecs}
+         *                 are invalid (null, empty, contain ' ', or '?' after an initial '?' has
+         *                 been stripped off).
+         * @return This builder.
+         */
+        @CorePlatformApi
+        public Builder put(@NonNull String mimeSpec, @NonNull List<@NonNull String> extensionSpecs)
+        {
+            Element mimeElement = Element.ofMimeSpec(mimeSpec); // validate mimeSpec unconditionally
+            if (extensionSpecs.isEmpty()) {
+                return this;
+            }
+            Element firstExtensionElement = Element.ofExtensionSpec(extensionSpecs.get(0));
+            maybePut(mimeToExt, mimeElement, firstExtensionElement.mimeOrExt);
+            maybePut(extToMime, firstExtensionElement, mimeElement.mimeOrExt);
+            for (String spec : extensionSpecs.subList(1, extensionSpecs.size())) {
+                Element element = Element.ofExtensionSpec(spec);
+                maybePut(extToMime, element, mimeElement.mimeOrExt);
+            }
+            return this;
+        }
+
+        /**
+         * Convenience method.
+         *
+         * @hide
+         */
+        public Builder put(@NonNull String mimeSpec, @NonNull String extensionSpec) {
+            return put(mimeSpec, Collections.singletonList(extensionSpec));
+        }
+
+        @CorePlatformApi
+        public MimeMap build() {
+            return new MimeMap(mimeToExt, extToMime);
+        }
+
+        @Override
+        public String toString() {
+            return "MimeMap.Builder[" + mimeToExt + ", " + extToMime + "]";
+        }
+    }
+
+    private static boolean isValidMimeTypeOrExtension(String s) {
+        return s != null
+                && !s.isEmpty()
+                && s.indexOf('?') < 0
+                && s.indexOf(' ') < 0
+                && s.indexOf('\t') < 0
+                && s.equals(toLowerCase(s));
+    }
+
+    static void checkValidMimeType(String s) {
+        if (!isValidMimeTypeOrExtension(s) || s.indexOf('/') < 0) {
+            throw new IllegalArgumentException("Invalid MIME type: " + s);
+        }
+    }
+
+    static void checkValidExtension(String s) {
+        if (!isValidMimeTypeOrExtension(s) || s.indexOf('/') >= 0) {
+            throw new IllegalArgumentException("Invalid extension: " + s);
+        }
+    }
+
+    private static final class MemoizingSupplier<T> implements Supplier<T> {
+        private volatile Supplier<T> mDelegate;
+        private volatile T mInstance;
+        private volatile boolean mInitialized = false;
+
+        public MemoizingSupplier(Supplier<T> delegate) {
+            this.mDelegate = delegate;
+        }
+
+        @Override
+        public T get() {
+            if (!mInitialized) {
+                synchronized (this) {
+                    if (!mInitialized) {
+                        mInstance = mDelegate.get();
+                        mDelegate = null;
+                        mInitialized = true;
+                    }
+                }
+            }
+            return mInstance;
+        }
+    }
+}
diff --git a/luni/src/main/java/libcore/content/type/TEST_MAPPING b/luni/src/main/java/libcore/content/type/TEST_MAPPING
new file mode 100644
index 0000000..712f4a2
--- /dev/null
+++ b/luni/src/main/java/libcore/content/type/TEST_MAPPING
@@ -0,0 +1,15 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsLibcoreTestCases",
+      "options": [
+        {
+          "include-filter": "libcore.libcore.content.type"
+        }
+      ]
+    },
+    {
+      "name": "CtsMimeMapTestCases"
+    }
+  ]
+}
diff --git a/luni/src/main/java/libcore/icu/ICU.java b/luni/src/main/java/libcore/icu/ICU.java
index d8d878d..2114523 100644
--- a/luni/src/main/java/libcore/icu/ICU.java
+++ b/luni/src/main/java/libcore/icu/ICU.java
@@ -31,6 +31,7 @@
  * Makes ICU data accessible to Java.
  * @hide
  */
+@libcore.api.IntraCoreApi
 @libcore.api.CorePlatformApi
 public final class ICU {
 
@@ -266,34 +267,10 @@
     return availableLocalesCache.clone();
   }
 
-  public static Locale[] getAvailableBreakIteratorLocales() {
-    return localesFromStrings(getAvailableBreakIteratorLocalesNative());
-  }
-
-  public static Locale[] getAvailableCalendarLocales() {
-    return localesFromStrings(getAvailableCalendarLocalesNative());
-  }
-
   public static Locale[] getAvailableCollatorLocales() {
     return localesFromStrings(getAvailableCollatorLocalesNative());
   }
 
-  public static Locale[] getAvailableDateFormatLocales() {
-    return localesFromStrings(getAvailableDateFormatLocalesNative());
-  }
-
-  public static Locale[] getAvailableDateFormatSymbolsLocales() {
-    return getAvailableDateFormatLocales();
-  }
-
-  public static Locale[] getAvailableDecimalFormatSymbolsLocales() {
-    return getAvailableNumberFormatLocales();
-  }
-
-  public static Locale[] getAvailableNumberFormatLocales() {
-    return localesFromStrings(getAvailableNumberFormatLocalesNative());
-  }
-
   @UnsupportedAppUsage
   @libcore.api.CorePlatformApi
   public static String getBestDateTimePattern(String skeleton, Locale locale) {
@@ -363,6 +340,7 @@
   /**
    * Returns the icu4c version in use, such as "50.1.1".
    */
+  @libcore.api.IntraCoreApi
   public static native String getIcuVersion();
 
   /**
@@ -399,31 +377,11 @@
 
   // --- Native methods accessing ICU's database.
 
-  private static native String[] getAvailableBreakIteratorLocalesNative();
-  private static native String[] getAvailableCalendarLocalesNative();
   private static native String[] getAvailableCollatorLocalesNative();
-  private static native String[] getAvailableDateFormatLocalesNative();
   private static native String[] getAvailableLocalesNative();
-  private static native String[] getAvailableNumberFormatLocalesNative();
 
-  public static native String[] getAvailableCurrencyCodes();
   public static native String getCurrencyCode(String countryCode);
 
-  public static String getCurrencyDisplayName(Locale locale, String currencyCode) {
-    return getCurrencyDisplayName(locale.toLanguageTag(), currencyCode);
-  }
-
-  private static native String getCurrencyDisplayName(String languageTag, String currencyCode);
-
-  public static native int getCurrencyFractionDigits(String currencyCode);
-  public static native int getCurrencyNumericCode(String currencyCode);
-
-  public static String getCurrencySymbol(Locale locale, String currencyCode) {
-    return getCurrencySymbol(locale.toLanguageTag(), currencyCode);
-  }
-
-  private static native String getCurrencySymbol(String languageTag, String currencyCode);
-
   public static String getDisplayCountry(Locale targetLocale, Locale locale) {
     return getDisplayCountryNative(targetLocale.toLanguageTag(), locale.toLanguageTag());
   }
diff --git a/luni/src/main/java/libcore/net/MimeMap.java b/luni/src/main/java/libcore/net/MimeMap.java
deleted file mode 100644
index afb6cbd..0000000
--- a/luni/src/main/java/libcore/net/MimeMap.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed 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.
- */
-
-package libcore.net;
-
-import java.util.Locale;
-import java.util.Objects;
-import java.util.concurrent.atomic.AtomicReference;
-import libcore.util.NonNull;
-import libcore.util.Nullable;
-
-/**
- * Maps from MIME types to file extensions and back.
- * @hide
- */
-@libcore.api.CorePlatformApi
-public abstract class MimeMap {
-    private static AtomicReference<MimeMap> defaultHolder = new AtomicReference<>(
-            MimeMapImpl.parseFromResources("/mime.types", "android.mime.types"));
-
-    /**
-     * @return The system's current default {@link MimeMap}.
-     */
-    @libcore.api.CorePlatformApi
-    public static @NonNull MimeMap getDefault() {
-        return defaultHolder.get();
-    }
-
-    /**
-     * Atomically sets the system's default {@link MimeMap} to be {@code update} if the
-     * current value {@code == expect}.
-     *
-     * @param expect the expected current default {@link MimeMap}; must not be null.
-     * @param update the new default {@link MimeMap} to set; must not be null.
-     * @return whether the update was successful.
-     */
-    @libcore.api.CorePlatformApi
-    public static boolean compareAndSetDefault(@NonNull MimeMap expect, @NonNull MimeMap update) {
-        Objects.requireNonNull(expect);
-        Objects.requireNonNull(update);
-        return defaultHolder.compareAndSet(expect, update);
-    }
-
-    /**
-     * Returns whether the given case insensitive extension has a registered MIME type.
-     *
-     * @param extension A file extension without the leading '.'
-     * @return Whether a MIME type has been registered for the given case insensitive file
-     *         extension.
-     */
-    @libcore.api.CorePlatformApi
-    public final boolean hasExtension(@Nullable String extension) {
-        return guessMimeTypeFromExtension(extension) != null;
-    }
-
-    /**
-     * Returns the MIME type for the given case insensitive file extension.
-     * If {@code extension} is {@code null} or {@code ""}, then this method always returns
-     * {@code null}. Otherwise, it delegates to
-     * {@link #guessMimeTypeFromLowerCaseExtension(String)}.
-     *
-     * @param extension A file extension without the leading '.'
-     * @return The lower-case MIME type registered for the given case insensitive file extension,
-     *         or null if there is none.
-     */
-    @libcore.api.CorePlatformApi
-    public final @Nullable String guessMimeTypeFromExtension(@Nullable String extension) {
-        if (isNullOrEmpty(extension)) {
-            return null;
-        }
-        extension = toLowerCase(extension);
-        String result = guessMimeTypeFromLowerCaseExtension(extension);
-        if (result != null) {
-            result = toLowerCase(result);
-        }
-        return result;
-    }
-
-    /**
-     * @param extension A non-null, non-empty, lowercase file extension.
-     * @return The MIME type registered for the given file extension, or null if there is none.
-     */
-    @libcore.api.CorePlatformApi
-    protected abstract @Nullable String guessMimeTypeFromLowerCaseExtension(
-            @NonNull String extension);
-
-    /**
-     * @param mimeType A MIME type (i.e. {@code "text/plain")
-     * @return Whether the given case insensitive MIME type is
-     *         {@link #guessMimeTypeFromExtension(String) mapped} to a file extension.
-     */
-    @libcore.api.CorePlatformApi
-    public final boolean hasMimeType(@Nullable String mimeType) {
-        return guessExtensionFromMimeType(mimeType) != null;
-    }
-
-    /**
-     * Returns the registered extension for the given case insensitive MIME type. Note that some
-     * MIME types map to multiple extensions. This call will return the most
-     * common extension for the given MIME type.
-     * @param mimeType A MIME type (i.e. text/plain)
-     * @return The lower-case file extension (without the leading "." that has been registered for
-     *         the given case insensitive MIME type, or null if there is none.
-     */
-    @libcore.api.CorePlatformApi
-    public final @Nullable String guessExtensionFromMimeType(@Nullable String mimeType) {
-        if (isNullOrEmpty(mimeType)) {
-            return null;
-        }
-        mimeType = toLowerCase(mimeType);
-        String result = guessExtensionFromLowerCaseMimeType(mimeType);
-        if (result != null) {
-            result = toLowerCase(result);
-        }
-        return result;
-    }
-
-    /**
-     * @param mimeType A non-null, non-empty, lowercase file extension.
-     * @return The file extension (without the leading ".") for the given mimeType, or null if
-     *         there is none.
-     */
-    @libcore.api.CorePlatformApi
-    protected abstract @Nullable String guessExtensionFromLowerCaseMimeType(
-            @NonNull String mimeType);
-
-    /**
-     * Returns the canonical (lowercase) form of the given extension or MIME type.
-     */
-    static @NonNull String toLowerCase(@NonNull String s) {
-        return s.toLowerCase(Locale.ROOT);
-    }
-
-    static boolean isNullOrEmpty(@Nullable String s) {
-        return s == null || s.isEmpty();
-    }
-
-}
diff --git a/luni/src/main/java/libcore/net/MimeMapImpl.java b/luni/src/main/java/libcore/net/MimeMapImpl.java
deleted file mode 100644
index a10dd6a..0000000
--- a/luni/src/main/java/libcore/net/MimeMapImpl.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed 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.
- */
-
-package libcore.net;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.regex.Pattern;
-
-class MimeMapImpl extends MimeMap {
-
-    private static final Pattern splitPattern = Pattern.compile("\\s+");
-
-    /**
-     * Note: These maps only contain lowercase keys/values, regarded as the
-     * {@link #toLowerCase(String) canonical form}.
-     *
-     * <p>This is the case for both extensions and MIME types. The mime.types
-     * data file contains examples of mixed-case MIME types, but some applications
-     * use the lowercase version of these same types. RFC 2045 section 2 states
-     * that MIME types are case insensitive.
-     */
-    private final Map<String, String> mimeTypeToExtension;
-    private final Map<String, String> extensionToMimeType;
-
-    public MimeMapImpl(Map<String, String> mimeTypeToExtension,
-            Map<String, String> extensionToMimeType) {
-        this.mimeTypeToExtension = new HashMap<>(mimeTypeToExtension);
-        for (Map.Entry<String, String> entry : mimeTypeToExtension.entrySet()) {
-            checkValidMimeType(entry.getKey());
-            checkValidExtension(entry.getValue());
-        }
-        this.extensionToMimeType = new HashMap<>(extensionToMimeType);
-        for (Map.Entry<String, String> entry : extensionToMimeType.entrySet()) {
-            checkValidExtension(entry.getKey());
-            checkValidMimeType(entry.getValue());
-        }
-    }
-
-    private static void checkValidMimeType(String s) {
-        if (MimeMap.isNullOrEmpty(s) || !s.equals(MimeMap.toLowerCase(s))) {
-            throw new IllegalArgumentException("Invalid MIME type: " + s);
-        }
-    }
-
-    private static void checkValidExtension(String s) {
-        if (isNullOrEmpty(s) || !s.equals(toLowerCase(s))) {
-            throw new IllegalArgumentException("Invalid extension: " + s);
-        }
-    }
-
-    static MimeMapImpl parseFromResources(String... resourceNames) {
-        Map<String, String> mimeTypeToExtension = new HashMap<>();
-        Map<String, String> extensionToMimeType = new HashMap<>();
-        for (String resourceName : resourceNames) {
-            parseTypes(mimeTypeToExtension, extensionToMimeType, resourceName);
-        }
-        return new MimeMapImpl(mimeTypeToExtension, extensionToMimeType);
-    }
-
-    /**
-     * An element of a *mime.types file: A MIME type or an extension, with an optional
-     * prefix of "?" (if not overriding an earlier value).
-     */
-    private static class Element {
-        public final boolean keepExisting;
-        public final String s;
-
-        public Element(boolean keepExisting, String value) {
-            this.keepExisting = keepExisting;
-            this.s = toLowerCase(value);
-            if (value.isEmpty()) {
-                throw new IllegalArgumentException();
-            }
-        }
-
-        public String toString() {
-            return keepExisting ? ("?" + s) : s;
-        }
-    }
-
-    private static String maybePut(Map<String, String> map, Element keyElement, String value) {
-        if (keyElement.keepExisting) {
-            return map.putIfAbsent(keyElement.s, value);
-        } else {
-            return map.put(keyElement.s, value);
-        }
-    }
-
-    private static void parseTypes(Map<String, String> mimeTypeToExtension,
-            Map<String, String> extensionToMimeType, String resource) {
-        try (BufferedReader r = new BufferedReader(
-                new InputStreamReader(MimeMap.class.getResourceAsStream(resource)))) {
-            String line;
-            while ((line = r.readLine()) != null) {
-                int commentPos = line.indexOf('#');
-                if (commentPos >= 0) {
-                    line = line.substring(0, commentPos);
-                }
-                line = line.trim();
-                // The first time a MIME type is encountered it is mapped to the first extension
-                // listed in its line. The first time an extension is encountered it is mapped
-                // to the MIME type.
-                //
-                // When encountering a previously seen MIME type or extension, then by default
-                // the later ones override earlier mappings (put() semantics); however if a MIME
-                // type or extension is prefixed with '?' then any earlier mapping _from_ that
-                // MIME type / extension is kept (putIfAbsent() semantics).
-                final String[] split = splitPattern.split(line);
-                if (split.length <= 1) {
-                    // Need mimeType + at least one extension to make a mapping.
-                    // "mime.types" files may also contain lines with just a mimeType without
-                    // an extension but we skip them as they provide no mapping info.
-                    continue;
-                }
-                List<Element> lineElements = new ArrayList<>(split.length);
-                for (String s : split) {
-                    boolean keepExisting = s.startsWith("?");
-                    if (keepExisting) {
-                        s = s.substring(1);
-                    }
-                    if (s.isEmpty()) {
-                        throw new IllegalArgumentException("Invalid entry in '" + line + "'");
-                    }
-                    lineElements.add(new Element(keepExisting, s));
-                }
-
-                // MIME type -> first extension (one mapping)
-                // This will override any earlier mapping from this MIME type to another
-                // extension, unless this MIME type was prefixed with '?'.
-                Element mimeElement = lineElements.get(0);
-                List<Element> extensionElements = lineElements.subList(1, lineElements.size());
-                String firstExtension = extensionElements.get(0).s;
-                maybePut(mimeTypeToExtension, mimeElement, firstExtension);
-
-                // extension -> MIME type (one or more mappings).
-                // This will override any earlier mapping from this extension to another
-                // MIME type, unless this extension was prefixed with '?'.
-                for (Element extensionElement : extensionElements) {
-                    maybePut(extensionToMimeType, extensionElement, mimeElement.s);
-                }
-            }
-        } catch (IOException | RuntimeException e) {
-            throw new RuntimeException("Failed to parse " + resource, e);
-        }
-    }
-
-    @Override
-    protected String guessExtensionFromLowerCaseMimeType(String mimeType) {
-        return mimeTypeToExtension.get(mimeType);
-    }
-
-    @Override
-    protected String guessMimeTypeFromLowerCaseExtension(String extension) {
-        return extensionToMimeType.get(extension);
-    }
-}
diff --git a/luni/src/main/java/libcore/net/TEST_MAPPING b/luni/src/main/java/libcore/net/TEST_MAPPING
index 1bbd3cd..f31705e 100644
--- a/luni/src/main/java/libcore/net/TEST_MAPPING
+++ b/luni/src/main/java/libcore/net/TEST_MAPPING
@@ -12,4 +12,4 @@
       ]
     }
   ]
-}
\ No newline at end of file
+}
diff --git a/luni/src/main/java/libcore/net/android.mime.types b/luni/src/main/java/libcore/net/android.mime.types
deleted file mode 100644
index 1ca912e..0000000
--- a/luni/src/main/java/libcore/net/android.mime.types
+++ /dev/null
@@ -1,146 +0,0 @@
-
-###############################################################################
-#
-# Android-specific MIME type <-> extension mappings
-#
-# Each line below defines an mapping from one MIME type to the first of the
-# listed extensions, and from listed extension back to the MIME type.
-# A mapping overrides any previous mapping _from_ that same MIME type or
-# extension (put() semantics), unless that MIME type / extension is prefixed with '?'
-# (putIfAbsent() semantics).
-#
-#
-###############################################################################
-#
-# EXAMPLES
-#
-# A line of the form:
-#
-#    ?mime ext1 ?ext2 ext3
-#
-# affects the current mappings along the lines of the following pseudo code:
-#
-#    mimeToExt.putIfAbsent("mime", "ext1");
-#    extToMime.put("ext1", "mime");
-#    extToMime.putIfAbsent("ext2", "mime");
-#    extToMime.put("ext3", "mime");
-#
-# The line:
-#
-#     ?text/plain txt
-#
-# leaves any earlier mapping for "text/plain" untouched, or maps that MIME type
-# to the file extension ".txt" if there is no earlier mapping. The line also
-# sets the mapping from file extension ".txt" to be the MIME type "text/plain",
-# regardless of whether a previous mapping existed.
-#
-###############################################################################
-
-
-# File extensions that Android wants to override to point to the given MIME type.
-#
-# After processing a line of the form:
-# ?<mimeType> <extension1> <extension2>
-# If <mimeType> was not already mapped to an extension then it will be
-# mapped to <extension1>.
-# <extension1> and <extension2> are mapped (or remapped) to <mimeType>.
-
-?application/epub+zip epub
-?application/pkix-cert cer
-?application/rss+xml rss
-?application/vnd.android.ota ota
-?application/vnd.apple.mpegurl m3u8
-?application/vnd.ms-pki.stl stl
-?application/vnd.ms-powerpoint pot
-?application/vnd.ms-wpl wpl
-?application/vnd.stardivision.impress sdp
-?application/vnd.stardivision.writer vor
-?application/vnd.youtube.yt yt
-?application/x-android-drm-fl fl
-?application/x-flac flac
-?application/x-font pcf
-?application/x-mpegurl m3u m3u8
-?application/x-pem-file pem
-?application/x-pkcs12 p12 pfx
-?application/x-webarchive webarchive
-?application/x-webarchive-xml webarchivexml
-?application/x-x509-server-cert crt
-?application/x-x509-user-cert crt
-
-?audio/3gpp 3gpp
-?audio/aac-adts aac
-?audio/imelody imy
-?audio/midi rtttl xmf
-?audio/mobile-xmf mxmf
-?audio/mp4 m4a
-?audio/mpegurl m3u
-?audio/sp-midi smf
-?audio/x-matroska mka
-?audio/x-pn-realaudio ra
-
-?image/bmp bmp
-?image/heic heic
-?image/heic-sequence heics
-?image/heif heif hif
-?image/heif-sequence heifs
-?image/ico cur
-?image/webp webp
-?image/x-adobe-dng dng
-?image/x-fuji-raf raf
-?image/x-icon ico
-?image/x-nikon-nrw nrw
-?image/x-panasonic-rw2 rw2
-?image/x-pentax-pef pef
-?image/x-samsung-srw srw
-?image/x-sony-arw arw
-
-?text/comma-separated-values csv
-?text/plain diff po
-?text/rtf rtf
-?text/text phps
-?text/xml xml
-?text/x-vcard vcf
-
-?video/3gpp2 3gpp2 3g2
-?video/3gpp 3gpp
-?video/avi avi
-?video/m4v m4v
-?video/mp2p mpeg
-?video/mp2t m2ts mts
-?video/mp2ts ts
-?video/vnd.youtube.yt yt
-?video/x-webex wrf
-
-# Optional additions that should not override any previous mapping.
-
-?application/x-wifi-config ?xml
-
-# Special cases where Android has a strong opinion about mappings, so we
-# define them very last and make them override in both directions (no "?").
-#
-# Lines here are of the form:
-# <mimeType> <extension1> <extension2> ...
-#
-# After processing each line,
-#   <mimeType> is mapped to <extension1>
-#   <extension1>, <extension2>, ... are all mapped to <mimeType>
-# This overrides any mappings for this <mimeType> / for these extensions
-# that may have been defined earlier.
-
-application/pgp-signature pgp
-application/x-x509-ca-cert crt
-audio/aac aac
-audio/basic snd
-audio/flac flac
-audio/midi rtx
-audio/mpeg mp3 m4a m4r
-audio/x-mpegurl m3u m3u8
-image/jpeg jpg
-image/x-ms-bmp bmp
-text/plain txt
-text/x-c++hdr hpp
-text/x-c++src cpp
-video/3gpp 3gpp
-video/mpeg mpeg
-video/quicktime mov
-video/x-matroska mkv
diff --git a/luni/src/main/native/IcuUtilities.cpp b/luni/src/main/native/IcuUtilities.cpp
index ed10d04..0db59f9 100644
--- a/luni/src/main/native/IcuUtilities.cpp
+++ b/luni/src/main/native/IcuUtilities.cpp
@@ -29,28 +29,6 @@
 #include "unicode/ustring.h"
 #include "unicode/uloc.h"
 
-jobjectArray fromStringEnumeration(JNIEnv* env, UErrorCode& status, const char* provider, icu::StringEnumeration* se) {
-  if (maybeThrowIcuException(env, provider, status)) {
-    return NULL;
-  }
-
-  int32_t count = se->count(status);
-  if (maybeThrowIcuException(env, "StringEnumeration::count", status)) {
-    return NULL;
-  }
-
-  jobjectArray result = env->NewObjectArray(count, JniConstants::GetStringClass(env), NULL);
-  for (int32_t i = 0; i < count; ++i) {
-    const icu::UnicodeString* string = se->snext(status);
-    if (maybeThrowIcuException(env, "StringEnumeration::snext", status)) {
-      return NULL;
-    }
-    ScopedLocalRef<jstring> javaString(env, jniCreateString(env, string->getBuffer(), string->length()));
-    env->SetObjectArrayElement(result, i, javaString.get());
-  }
-  return result;
-}
-
 bool maybeThrowIcuException(JNIEnv* env, const char* function, UErrorCode error) {
   if (U_SUCCESS(error)) {
     return false;
diff --git a/luni/src/main/native/IcuUtilities.h b/luni/src/main/native/IcuUtilities.h
index c64de30..451dc32 100644
--- a/luni/src/main/native/IcuUtilities.h
+++ b/luni/src/main/native/IcuUtilities.h
@@ -18,10 +18,8 @@
 #define ICU_UTILITIES_H_included
 
 #include "jni.h"
-#include "ustrenum.h" // For UStringEnumeration.
 #include "unicode/utypes.h" // For UErrorCode.
 
-extern jobjectArray fromStringEnumeration(JNIEnv* env, UErrorCode& status, const char* provider, icu::StringEnumeration*);
 bool maybeThrowIcuException(JNIEnv* env, const char* function, UErrorCode error);
 
 #endif  // ICU_UTILITIES_H_included
diff --git a/luni/src/main/native/libcore_icu_ICU.cpp b/luni/src/main/native/libcore_icu_ICU.cpp
index 2cbf40f..58ca587b 100644
--- a/luni/src/main/native/libcore_icu_ICU.cpp
+++ b/luni/src/main/native/libcore_icu_ICU.cpp
@@ -113,25 +113,6 @@
   return env->NewStringUTF(icuLocale.locale().getScript());
 }
 
-static jint ICU_getCurrencyFractionDigits(JNIEnv* env, jclass, jstring javaCurrencyCode) {
-  ScopedJavaUnicodeString currencyCode(env, javaCurrencyCode);
-  if (!currencyCode.valid()) {
-    return 0;
-  }
-  icu::UnicodeString icuCurrencyCode(currencyCode.unicodeString());
-  UErrorCode status = U_ZERO_ERROR;
-  return ucurr_getDefaultFractionDigits(icuCurrencyCode.getTerminatedBuffer(), &status);
-}
-
-static jint ICU_getCurrencyNumericCode(JNIEnv* env, jclass, jstring javaCurrencyCode) {
-  ScopedJavaUnicodeString currencyCode(env, javaCurrencyCode);
-  if (!currencyCode.valid()) {
-    return 0;
-  }
-  icu::UnicodeString icuCurrencyCode(currencyCode.unicodeString());
-  return ucurr_getNumericCode(icuCurrencyCode.getTerminatedBuffer());
-}
-
 // TODO: rewrite this with int32_t ucurr_forLocale(const char* locale, UChar* buff, int32_t buffCapacity, UErrorCode* ec)...
 static jstring ICU_getCurrencyCode(JNIEnv* env, jclass, jstring javaCountryCode) {
     UErrorCode status = U_ZERO_ERROR;
@@ -207,14 +188,6 @@
   return (charCount == 0) ? NULL : jniCreateString(env, chars, charCount);
 }
 
-static jstring ICU_getCurrencyDisplayName(JNIEnv* env, jclass, jstring javaLanguageTag, jstring javaCurrencyCode) {
-  return getCurrencyName(env, javaLanguageTag, javaCurrencyCode, UCURR_LONG_NAME);
-}
-
-static jstring ICU_getCurrencySymbol(JNIEnv* env, jclass, jstring javaLanguageTag, jstring javaCurrencyCode) {
-  return getCurrencyName(env, javaLanguageTag, javaCurrencyCode, UCURR_SYMBOL_NAME);
-}
-
 static jstring ICU_getDisplayCountryNative(JNIEnv* env, jclass, jstring javaTargetLanguageTag, jstring javaLanguageTag) {
   ScopedIcuLocale icuLocale(env, javaLanguageTag);
   if (!icuLocale.valid()) {
@@ -303,26 +276,10 @@
     return toStringArray(env, uloc_countAvailable, uloc_getAvailable);
 }
 
-static jobjectArray ICU_getAvailableBreakIteratorLocalesNative(JNIEnv* env, jclass) {
-    return toStringArray(env, ubrk_countAvailable, ubrk_getAvailable);
-}
-
-static jobjectArray ICU_getAvailableCalendarLocalesNative(JNIEnv* env, jclass) {
-    return toStringArray(env, ucal_countAvailable, ucal_getAvailable);
-}
-
 static jobjectArray ICU_getAvailableCollatorLocalesNative(JNIEnv* env, jclass) {
     return toStringArray(env, ucol_countAvailable, ucol_getAvailable);
 }
 
-static jobjectArray ICU_getAvailableDateFormatLocalesNative(JNIEnv* env, jclass) {
-    return toStringArray(env, udat_countAvailable, udat_getAvailable);
-}
-
-static jobjectArray ICU_getAvailableNumberFormatLocalesNative(JNIEnv* env, jclass) {
-    return toStringArray(env, unum_countAvailable, unum_getAvailable);
-}
-
 static bool setIntegerField(JNIEnv* env, jobject obj, const char* fieldName, int value) {
     ScopedLocalRef<jobject> integerValue(env, integerValueOf(env, value));
     if (integerValue.get() == NULL) return false;
@@ -681,7 +638,7 @@
 
     jstring currencySymbol = NULL;
     if (internationalCurrencySymbol != NULL) {
-        currencySymbol = ICU_getCurrencySymbol(env, NULL, javaLanguageTag, internationalCurrencySymbol);
+        currencySymbol = getCurrencyName(env, javaLanguageTag, internationalCurrencySymbol, UCURR_SYMBOL_NAME);
     } else {
         internationalCurrencySymbol = env->NewStringUTF("XXX");
     }
@@ -759,12 +716,6 @@
   return env->NewStringUTF(version);
 }
 
-static jobjectArray ICU_getAvailableCurrencyCodes(JNIEnv* env, jclass) {
-  UErrorCode status = U_ZERO_ERROR;
-  icu::UStringEnumeration e(ucurr_openISOCurrencies(UCURR_COMMON|UCURR_NON_DEPRECATED, &status));
-  return fromStringEnumeration(env, status, "ucurr_openISOCurrencies", &e);
-}
-
 static jstring ICU_getBestDateTimePatternNative(JNIEnv* env, jclass, jstring javaSkeleton, jstring javaLanguageTag) {
   ScopedIcuLocale icuLocale(env, javaLanguageTag);
   if (!icuLocale.valid()) {
@@ -806,20 +757,11 @@
 
 static JNINativeMethod gMethods[] = {
     NATIVE_METHOD(ICU, addLikelySubtags, "(Ljava/lang/String;)Ljava/lang/String;"),
-    NATIVE_METHOD(ICU, getAvailableBreakIteratorLocalesNative, "()[Ljava/lang/String;"),
-    NATIVE_METHOD(ICU, getAvailableCalendarLocalesNative, "()[Ljava/lang/String;"),
     NATIVE_METHOD(ICU, getAvailableCollatorLocalesNative, "()[Ljava/lang/String;"),
-    NATIVE_METHOD(ICU, getAvailableCurrencyCodes, "()[Ljava/lang/String;"),
-    NATIVE_METHOD(ICU, getAvailableDateFormatLocalesNative, "()[Ljava/lang/String;"),
     NATIVE_METHOD(ICU, getAvailableLocalesNative, "()[Ljava/lang/String;"),
-    NATIVE_METHOD(ICU, getAvailableNumberFormatLocalesNative, "()[Ljava/lang/String;"),
     NATIVE_METHOD(ICU, getBestDateTimePatternNative, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"),
     NATIVE_METHOD(ICU, getCldrVersion, "()Ljava/lang/String;"),
     NATIVE_METHOD(ICU, getCurrencyCode, "(Ljava/lang/String;)Ljava/lang/String;"),
-    NATIVE_METHOD(ICU, getCurrencyDisplayName, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"),
-    NATIVE_METHOD(ICU, getCurrencyFractionDigits, "(Ljava/lang/String;)I"),
-    NATIVE_METHOD(ICU, getCurrencyNumericCode, "(Ljava/lang/String;)I"),
-    NATIVE_METHOD(ICU, getCurrencySymbol, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"),
     NATIVE_METHOD(ICU, getDefaultLocale, "()Ljava/lang/String;"),
     NATIVE_METHOD(ICU, getDisplayCountryNative, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"),
     NATIVE_METHOD(ICU, getDisplayLanguageNative, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"),
diff --git a/luni/src/main/native/libcore_icu_NativeConverter.cpp b/luni/src/main/native/libcore_icu_NativeConverter.cpp
index 9ccfabd..480c07a 100644
--- a/luni/src/main/native/libcore_icu_NativeConverter.cpp
+++ b/luni/src/main/native/libcore_icu_NativeConverter.cpp
@@ -33,6 +33,7 @@
 #include "IcuUtilities.h"
 #include "JniConstants.h"
 #include "JniException.h"
+#include "ustrenum.h"
 #include "unicode/ucnv.h"
 #include "unicode/ucnv_cb.h"
 #include "unicode/uniset.h"
diff --git a/luni/src/test/java/libcore/java/lang/invoke/MethodHandlesTest.java b/luni/src/test/java/libcore/java/lang/invoke/MethodHandlesTest.java
index fc18ab8..8e08a59 100644
--- a/luni/src/test/java/libcore/java/lang/invoke/MethodHandlesTest.java
+++ b/luni/src/test/java/libcore/java/lang/invoke/MethodHandlesTest.java
@@ -29,6 +29,7 @@
 import java.lang.reflect.Method;
 import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
+import java.util.function.Consumer;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -299,6 +300,18 @@
         public static final Lookup lookup = MethodHandles.lookup();
     }
 
+    public interface F {
+        public default void callInner(Consumer<Class<?>> c) {
+            c.accept(F.class);
+        }
+    }
+
+    public class G implements F {
+        public void callInner(Consumer<Class<?>> c) {
+            c.accept(G.class);
+        }
+    }
+
     public void testfindSpecial_invokeSuperBehaviour() throws Throwable {
         // This is equivalent to an invoke-super instruction where the referrer
         // is B.class.
@@ -364,6 +377,41 @@
         } catch (NoSuchMethodException e) {}
     }
 
+    public void testfindSpecial_invokeSuperInterfaceBehaviour() throws Throwable {
+        // Check interface invoke super on unrelated lookup (with some private access).
+        Class<?>[] res = new Class<?>[2];
+        MethodHandle mh = MethodHandles.lookup().findSpecial(F.class /* refC */, "callInner",
+                  MethodType.methodType(void.class, Consumer.class), G.class /* specialCaller */);
+        G g = new G();
+        Consumer<Class<?>> oc = (Class<?> c) -> { res[0] = c; };
+        mh.invokeExact(g, oc);
+        g.callInner((Class<?> c) -> { res[1] = c; });
+        // Make sure the method-handle calls the default implementatoin
+        assertTrue(res[0] == F.class);
+        // Make sure the normal one works as we expect.
+        assertTrue(res[1] == G.class);
+
+        // Check findSpecial always fails if the lookup has only public access
+        try {
+          MethodHandles.publicLookup().findSpecial(F.class /* refC */, "callInner",
+                  MethodType.methodType(void.class, Consumer.class), G.class /* specialCaller */);
+          fail();
+        } catch (IllegalAccessException e) {}
+
+        // Check doing invokeSpecial on abstract interface methods gets appropriate errors. We
+        // expect it to throw an IllegalAccessError.
+        MethodHandle mh2 =
+            MethodHandles.lookup().findSpecial(
+                    Foo.class /* refC */,
+                    "foo",
+                    MethodType.methodType(String.class),
+                    Bar.class /* specialCaller */);
+        try {
+          mh2.invoke(new BarImpl());
+          fail();
+        } catch (IllegalAccessException e) {}
+    }
+
     public void testfindSpecial_invokeDirectBehaviour() throws Throwable {
         D dInstance = new D();
 
diff --git a/luni/src/test/java/libcore/libcore/content/type/MimeMapTest.java b/luni/src/test/java/libcore/libcore/content/type/MimeMapTest.java
new file mode 100644
index 0000000..f7bb140
--- /dev/null
+++ b/luni/src/test/java/libcore/libcore/content/type/MimeMapTest.java
@@ -0,0 +1,456 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed 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.
+ */
+
+package libcore.libcore.content.type;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import libcore.content.type.MimeMap;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * Tests {@link MimeMap} and {@link MimeMap.Builder}.
+ */
+public class MimeMapTest {
+
+    private MimeMap mimeMap;
+    private MimeMap emptyMap;
+
+    @Before public void setUp() {
+        mimeMap = MimeMap.getDefault();
+        emptyMap = MimeMap.builder().build();
+    }
+
+    @After public void tearDown() {
+        mimeMap = null;
+    }
+
+    @Test public void lookup_invalidExtension() {
+        assertNull(mimeMap.guessMimeTypeFromExtension(null));
+        assertNull(mimeMap.guessMimeTypeFromExtension(""));
+        assertFalse(mimeMap.hasExtension(null));
+        assertFalse(mimeMap.hasExtension(""));
+    }
+
+    @Test public void lookup_invalidMimeType() {
+        assertNull(mimeMap.guessExtensionFromMimeType(null));
+        assertNull(mimeMap.guessExtensionFromMimeType(""));
+        assertFalse(mimeMap.hasMimeType(null));
+        assertFalse(mimeMap.hasMimeType(""));
+    }
+
+    @Test public void caseNormalization_key() {
+        mimeMap = MimeMap.builder()
+                .put("application/msWord", Arrays.asList("Doc"))
+                .build();
+        assertEquals("application/msword", mimeMap.guessMimeTypeFromExtension("dOc"));
+        assertEquals("doc", mimeMap.guessExtensionFromMimeType("appliCATion/mSWOrd"));
+        assertTrue(mimeMap.hasMimeType("application/msword"));
+        assertTrue(mimeMap.hasMimeType("Application/mSWord"));
+
+        assertTrue(mimeMap.hasExtension("doc"));
+        assertTrue(mimeMap.hasExtension("DOC"));
+        assertTrue(mimeMap.hasExtension("dOc"));
+    }
+
+    @Test public void caseNormalization_value() {
+        // Default map
+        for (String extension : mimeMap.extensions()) {
+            assertLowerCase(mimeMap.guessMimeTypeFromExtension(extension));
+        }
+        for (String mimeType : mimeMap.mimeTypes()) {
+            assertLowerCase(mimeMap.guessExtensionFromMimeType(mimeType));
+        }
+
+        // Known keys for a custom map
+        mimeMap = MimeMap.builder()
+                .put("application/msWord", Arrays.asList("Doc"))
+                .build();
+        assertEquals("doc", mimeMap.guessExtensionFromMimeType("Application/mSWord"));
+        assertEquals("application/msword", mimeMap.guessMimeTypeFromExtension("DoC"));
+    }
+
+    private static void assertLowerCase(String s) {
+        assertEquals(s.toLowerCase(Locale.ROOT), s);
+    }
+
+    @Test public void unmapped() {
+        mimeMap = MimeMap.builder()
+                .put("mime/test", Arrays.asList("test", "tst"))
+                .build();
+        assertNull(mimeMap.guessExtensionFromMimeType("mime/unknown"));
+        assertFalse(mimeMap.hasMimeType("mime/unknown"));
+
+        assertNull(mimeMap.guessMimeTypeFromExtension("absent"));
+        assertFalse(mimeMap.hasExtension("absent"));
+    }
+
+    @Test public void getDefault_returnsSameInstance() {
+        assertSame(MimeMap.getDefault(), MimeMap.getDefault());
+    }
+
+    @Test public void getDefault_afterSetDefaultSupplier() {
+        MimeMap originalDefault = MimeMap.getDefault();
+        try {
+            // Constructs a new instance every time it is called
+            MimeMap.setDefaultSupplier(() -> MimeMap.builder().put("mime/sup", "sup").build());
+            // Same instance is returned both times
+            assertSame(MimeMap.getDefault(), MimeMap.getDefault());
+            // Check that the supplier is in effect
+            assertTrue(originalDefault != MimeMap.getDefault());
+            assertEquals("mime/sup", MimeMap.getDefault().guessMimeTypeFromExtension("sup"));
+        } finally {
+            MimeMap.setDefaultSupplier(() -> originalDefault);
+        }
+        assertSame(originalDefault, MimeMap.getDefault());
+    }
+
+    @Test public void setDefaultSupplier_returningNull() {
+        MimeMap originalDefault = MimeMap.getDefault();
+        try {
+            // A Supplier that returns null is invalid, but we only notice during getDefault().
+            MimeMap.setDefaultSupplier(() -> null);
+            try {
+                MimeMap.getDefault();
+                fail();
+            } catch (NullPointerException expected) {
+            }
+        } finally {
+            MimeMap.setDefaultSupplier(() -> originalDefault);
+        }
+    }
+
+    @Test public void buildUpon() {
+        mimeMap = MimeMap.builder()
+                .build();
+        assertMap(
+                makeMap(),
+                makeMap(),
+                mimeMap);
+
+        mimeMap = mimeMap.buildUpon()
+                .build();
+        assertMap(
+                makeMap(),
+                makeMap(),
+                mimeMap);
+
+        mimeMap = mimeMap.buildUpon()
+                .put("text/plain", "txt")
+                .build();
+        assertMap(
+                makeMap("text/plain", "txt"),
+                makeMap("txt", "text/plain"),
+                mimeMap);
+
+        mimeMap = mimeMap.buildUpon()
+                .put("audio/mpeg", Arrays.asList("mp2", "mp3"))
+                .build();
+        assertMap(
+                makeMap("audio/mpeg", "mp2",
+                        "text/plain", "txt"),
+                makeMap("mp2", "audio/mpeg",
+                        "mp3", "audio/mpeg",
+                        "txt", "text/plain"),
+                mimeMap);
+
+        mimeMap = mimeMap.buildUpon()
+                .put("text/plain", "text")
+                .build();
+        assertMap(
+                makeMap("audio/mpeg", "mp2",
+                        "text/plain", "text"),
+                makeMap("mp2", "audio/mpeg",
+                        "mp3", "audio/mpeg",
+                        "text", "text/plain",
+                        "txt", "text/plain"),
+                mimeMap);
+    }
+
+    @Test public void put() {
+        MimeMap a = MimeMap.builder()
+                .put("text/plain", Arrays.asList("txt", "text"))
+                .put("application/msword", "doc")
+                .build();
+        MimeMap b = MimeMap.builder()
+                .put("text/plain", Arrays.asList("txt", "text"))
+                .put("application/msword", "doc")
+                .build();
+        assertEqualsButNotSame(a, b);
+        assertEqualsButNotSame(a, a.buildUpon().build());
+        assertMap(
+                makeMap(
+                        "text/plain", "txt",
+                        "application/msword", "doc"),
+                makeMap("txt", "text/plain",
+                        "text", "text/plain",
+                        "doc", "application/msword"),
+                a);
+    }
+
+    @Test public void put_noExtensions() {
+        checkPut_noExtensions(emptyMap);
+        checkPut_noExtensions(MimeMap.builder().put("text/plain", "txt").build());
+        checkPut_noExtensions(mimeMap);
+    }
+
+    /**
+     * Checks that put(String, emptyList()) doesn't change or add any mappings.
+     */
+    private static void checkPut_noExtensions(MimeMap baseMap) {
+        MimeMap mimeMap = baseMap.buildUpon()
+                .put("mime/type", Collections.emptyList())
+                .build();
+        assertEquals(baseMap, mimeMap);
+    }
+
+    @Test public void put_String_List_nullOrEmpty() {
+        // We still check mimeType for validity even if no extensions are specified
+        assertPutThrowsNpe(null);
+        assertPutThrowsIae("");
+
+        // null or "" are not allowed for either MIME type or extension
+        assertPutThrowsNpe(null, "ext");
+        assertPutThrowsIae("", "ext");
+        assertPutThrowsNpe("mime/type", null);
+        assertPutThrowsIae("mime/type", "");
+
+        assertPutThrowsNpe("mime/type", "ext", null);
+        assertPutThrowsIae("mime/type", "ext", "");
+    }
+
+    @Test public void put_String_String_nullOrEmpty() {
+        assertThrowsNpe(() -> MimeMap.builder().put(null, "ext"));
+        assertThrowsIae(() -> MimeMap.builder().put("", "ext"));
+
+        assertThrowsNpe(() -> MimeMap.builder().put("mime/type", (String) null));
+        assertThrowsIae(() -> MimeMap.builder().put("mime/type", ""));
+    }
+
+    /**
+     * Tests put() arguments that have a prefix {@code "?"} which leads to putIfAbsent semantics.
+     */
+    @Test public void putIfAbsent() {
+        // Starting from an empty mapping, add a bunch more, some with and some without '?'.
+        mimeMap = MimeMap.builder()
+                .put("?text/plain", "?txt")
+                .put("audio/mpeg", Arrays.asList("mpga", "mpega", "?mp2", "mp3"))
+                .build();
+        assertEquals("txt", mimeMap.guessExtensionFromMimeType("text/plain"));
+        assertEquals("text/plain", mimeMap.guessMimeTypeFromExtension("txt"));
+        assertEquals("mpga", mimeMap.guessExtensionFromMimeType("audio/mpeg"));
+        assertEquals("audio/mpeg", mimeMap.guessMimeTypeFromExtension("mp2"));
+        assertEquals("audio/mpeg", mimeMap.guessMimeTypeFromExtension("mp3"));
+
+        // Override a ext -> MIME mapping without overriding the MIME -> ext mapping.
+        mimeMap = mimeMap.buildUpon()
+                .put("?audio/mpeg", "m4a")
+                .build();
+        assertEquals("mpga", mimeMap.guessExtensionFromMimeType("audio/mpeg"));
+        assertEquals("audio/mpeg", mimeMap.guessMimeTypeFromExtension("m4a"));
+
+        // Override a MIME -> ext mapping without overriding the ext -> MIME mapping.
+        mimeMap = mimeMap.buildUpon()
+                .put("audio/mpeg", "?txt")
+                .build();
+        assertEquals("txt", mimeMap.guessExtensionFromMimeType("audio/mpeg"));
+        assertEquals("text/plain", mimeMap.guessMimeTypeFromExtension("txt"));
+
+
+        // Check final state
+        assertMap(
+                makeMap(
+                        "text/plain", "txt",
+                        "audio/mpeg", "txt"
+                        ),
+                makeMap(
+                        "txt", "text/plain",
+                        "m4a", "audio/mpeg",
+                        "mp2", "audio/mpeg",
+                        "mp3", "audio/mpeg",
+                        "mpega", "audio/mpeg",
+                        "mpga", "audio/mpeg"
+                ),
+                mimeMap
+        );
+    }
+
+    @Test public void extensions() {
+        assertEquals(Collections.emptySet(), emptyMap.extensions());
+        mimeMap = MimeMap.builder()
+                .put("text/plain", Arrays.asList("txt", "text"))
+                .put("audi/mpeg", "m4a")
+                .put("application/msword", "doc")
+                .put("text/plain", "tx")
+                .build();
+        Set<String> extensions = new HashSet<>(Arrays.asList(
+                "txt", "text", "m4a", "doc", "tx"));
+        assertEquals(extensions, mimeMap.extensions());
+        // Check that the extensions() view is unmodifiable
+        try {
+            mimeMap.extensions().add("ext");
+            fail();
+        } catch (UnsupportedOperationException expected) {
+        }
+    }
+
+    @Test public void mimeTypes() {
+        assertEquals(Collections.emptySet(), emptyMap.mimeTypes());
+        mimeMap = MimeMap.builder()
+                .put("text/plain", Arrays.asList("txt", "text"))
+                .put("audio/mpeg", "m4a")
+                .put("application/msword", "doc")
+                .put("text/plain", "tx")
+                .build();
+        Set<String> mimeTypes = new HashSet<>(Arrays.asList(
+                "text/plain",
+                "audio/mpeg",
+                "application/msword"));
+        assertEquals(mimeTypes, mimeMap.mimeTypes());
+        // Check that the mimeTypes() view is unmodifiable
+        try {
+            mimeMap.mimeTypes().add("foo/bar");
+            fail();
+        } catch (UnsupportedOperationException expected) {
+        }
+    }
+
+    /**
+     * Tests invalid put() invocations that have '?' in additional/invalid places.
+     */
+    @Test public void put_invalid_additionalQuestionMarks() {
+        // Potentially we could tolerate additional ? as a prefix in future, but right now we don't.
+        assertPutThrowsIae("??text/plain", "txt");
+        assertPutThrowsIae("text/p?lain", "txt");
+        assertPutThrowsIae("text/plain", "txt", "t?ext");
+        assertPutThrowsIae("text/plain", "??txt");
+        assertPutThrowsIae("text/plain", "t?xt");
+    }
+
+    /** Checks that MIME types must have a '/', while extensions must not. */
+    @Test public void put_invalid_slash() {
+        assertPutThrowsIae("mime/type", "invalid/ext");
+        assertPutThrowsIae("invalidmime", "ext");
+
+        // During lookups, wrong arguments return null rather than throwing.
+        mimeMap = MimeMap.builder().put("mime/type", "ext").build();
+        assertNull(mimeMap.guessExtensionFromMimeType("ext")); // ext is no mime type
+        assertNull(mimeMap.guessMimeTypeFromExtension("mime/type")); // mime/type is no extension
+    }
+
+    private static void assertPutThrowsNpe(String mime, String... exts) {
+        assertThrowsNpe(() -> MimeMap.builder().put(mime, Arrays.asList(exts)));
+    }
+
+    private static void assertPutThrowsIae(final String mime, final String... exts) {
+        assertThrowsIae(() -> MimeMap.builder().put(mime, Arrays.asList(exts)));
+    }
+
+    private static void assertThrowsNpe(Runnable runnable) {
+        try {
+            runnable.run();
+            fail();
+        } catch (NullPointerException expected) {
+        }
+    }
+
+    private static void assertThrowsIae(Runnable runnable) {
+        try {
+            runnable.run();
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    @Test public void hashCodeValue() {
+        assertEquals(0, emptyMap.hashCode());
+        MimeMap a = MimeMap.builder().put("mime/test", "test").build();
+        MimeMap b = a.buildUpon().put("foo/bar", "baz").build();
+        assertTrue(0 != a.hashCode());
+        assertTrue((a.hashCode() != b.hashCode()));
+    }
+
+    @Test public void empty_copies() {
+        assertEqualsButNotSame(emptyMap, MimeMap.builder().build());
+        assertEqualsButNotSame(emptyMap, emptyMap.buildUpon().build());
+    }
+
+    /** Creates a map from alternating key/value arguments, useful for test assertions. */
+    private static Map<String, String> makeMap(String... keysAndValues) {
+        if (keysAndValues.length % 2 != 0) {
+            throw new IllegalArgumentException(
+                    "Invalid length " + keysAndValues.length + ": " + keysAndValues);
+        }
+        Map<String, String> result = new HashMap<>();
+        for (int i = 0; i < keysAndValues.length; i += 2) {
+            String key = keysAndValues[i];
+            String value = keysAndValues[i + 1];
+            result.put(key, value);
+        }
+        return result;
+
+    }
+
+    /**
+     * Asserts that the given {@code MimeMap} has exactly the given mime -> ext and ext -> mime
+     * mappings, but no others.
+     */
+    private static<T> void assertMap(
+            Map<String, String> expectedMimeToExt,
+            Map<String, String> expectedExtToMime,
+            MimeMap mimeMap)
+    {
+        MimeMap.Builder expectedBuilder = MimeMap.builder();
+        for (Map.Entry<String, String> entry : expectedExtToMime.entrySet()) {
+            String ext = entry.getKey();
+            String mime = entry.getValue();
+            assertEquals(ext + ": " + mimeMap, mime, mimeMap.guessMimeTypeFromExtension(ext));
+            expectedBuilder.put("?" + mime, ext);
+        }
+        for (Map.Entry<String, String> entry : expectedMimeToExt.entrySet()) {
+            String mime = entry.getKey();
+            String ext = entry.getValue();
+            assertEquals(mime + ": "  + mimeMap, ext, mimeMap.guessExtensionFromMimeType(mime));
+            expectedBuilder.put(mime, "?" + ext);
+        }
+        // Check that there are no unexpected additional mappings.
+        assertEqualsButNotSame(expectedBuilder.build(), mimeMap);
+    }
+
+    private static<T> void assertEqualsButNotSame(T a, T b) {
+        assertEquals(a, b);
+        assertEquals(b, a);
+        assertNotSame(a, b);
+        assertEquals(a.hashCode(), b.hashCode());
+    }
+
+}
diff --git a/luni/src/test/java/libcore/libcore/icu/ICUTest.java b/luni/src/test/java/libcore/libcore/icu/ICUTest.java
index e67e9a1..a7b4e4b 100644
--- a/luni/src/test/java/libcore/libcore/icu/ICUTest.java
+++ b/luni/src/test/java/libcore/libcore/icu/ICUTest.java
@@ -220,38 +220,4 @@
     assertTrue(c.compare("AF", "af") < 0);
   }
 
-  // Test for the behavior of currency symbol lookup when an unrecognized locale has been set as the
-  // default.
-  public void testIcuDefaultAffectsCurrencySymbol() {
-    // A locale that is not going to be recognized by ICU and should fallback to "root" for the
-    // currency symbol.
-    final Locale unrecognizedLocale = new Locale("xy", "KR");
-
-    // A known locale with a relatively stable representation for its currency symbol.
-    final Locale enUsLocale = new Locale("en", "US");
-    final String usDollar = "USD";
-
-    String initialDefaultLocale = ICU.getDefaultLocale();
-    try {
-      // Confirm the "$" symbol for USD in en-US.
-      assertEquals("$", ICU.getCurrencySymbol(enUsLocale, usDollar));
-
-      // Set the default so this will be used as fallback for the unrecognized locale symbol lookup.
-      ICU.setDefaultLocale(enUsLocale.toLanguageTag());
-
-      // Demonstrate the USD symbol is reported as "$" for the unrecognized locale (which is using
-      // the default).
-      assertEquals("$", ICU.getCurrencySymbol(unrecognizedLocale, usDollar));
-
-      // Change the default.
-      ICU.setDefaultLocale(unrecognizedLocale.toLanguageTag());
-
-      String currencySymbolAfterDefaultChange = ICU.getCurrencySymbol(unrecognizedLocale, usDollar);
-      // "$US" is the value from root. With an unrecognized locale argument, and an unrecognized
-      // locale as the default, ICU has returns the value in root.
-      assertEquals("US$", currencySymbolAfterDefaultChange);
-    } finally {
-      ICU.setDefaultLocale(initialDefaultLocale);
-    }
-  }
 }
diff --git a/luni/src/test/java/libcore/libcore/net/MimeMapTest.java b/luni/src/test/java/libcore/libcore/net/MimeMapTest.java
deleted file mode 100644
index de98309..0000000
--- a/luni/src/test/java/libcore/libcore/net/MimeMapTest.java
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed 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.
- */
-
-package libcore.libcore.net;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.util.Locale;
-import java.util.Objects;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.when;
-import static org.mockito.Mockito.verify;
-
-import libcore.net.MimeMap;
-import libcore.util.NonNull;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-
-public class MimeMapTest {
-
-    /** Exposes {@link MimeMap}'s protected methods publicly so that mock calls can be verified. */
-    public static abstract class TestMimeMap extends MimeMap {
-        @Override
-        public abstract String guessMimeTypeFromLowerCaseExtension(@NonNull String extension);
-
-        @Override
-        public abstract String guessExtensionFromLowerCaseMimeType(@NonNull String mimeType);
-    }
-
-    private TestMimeMap mimeMap;
-    private MimeMap defaultMimeMap;
-
-    @Before public void setUp() {
-        mimeMap = mock(TestMimeMap.class);
-        defaultMimeMap = MimeMap.getDefault();
-    }
-
-    @After public void tearDown() {
-        mimeMap = null;
-    }
-
-    @Test public void invalidExtension() {
-        assertNull(mimeMap.guessMimeTypeFromExtension(null));
-        assertNull(mimeMap.guessMimeTypeFromExtension(""));
-        assertFalse(mimeMap.hasExtension(null));
-        assertFalse(mimeMap.hasExtension(""));
-
-        verify(mimeMap, never()).guessExtensionFromLowerCaseMimeType(anyString());
-        verify(mimeMap, never()).guessMimeTypeFromLowerCaseExtension(anyString());
-
-    }
-
-    @Test public void invalidMimeType() {
-        assertNull(mimeMap.guessExtensionFromMimeType(null));
-        assertNull(mimeMap.guessExtensionFromMimeType(""));
-        assertFalse(mimeMap.hasMimeType(null));
-        assertFalse(mimeMap.hasMimeType(""));
-
-        verify(mimeMap, never()).guessExtensionFromLowerCaseMimeType(anyString());
-        verify(mimeMap, never()).guessMimeTypeFromLowerCaseExtension(anyString());
-    }
-
-    @Test public void caseNormalization() {
-        when(mimeMap.guessExtensionFromLowerCaseMimeType("application/msword")).thenReturn("DoC");
-        when(mimeMap.guessMimeTypeFromLowerCaseExtension("doc")).thenReturn("APPLication/msWORD");
-
-        assertEquals("application/msword", mimeMap.guessMimeTypeFromExtension("dOc"));
-        assertEquals("doc", mimeMap.guessExtensionFromMimeType("appliCATion/mSWOrd"));
-    }
-
-    @Test public void unmapped() {
-        assertNull(mimeMap.guessExtensionFromMimeType("test/mime"));
-        assertFalse(mimeMap.hasMimeType("test/mime"));
-
-        assertNull(mimeMap.guessMimeTypeFromExtension("test"));
-        assertFalse(mimeMap.hasExtension("test"));
-
-        verify(mimeMap, times(2)).guessExtensionFromLowerCaseMimeType("test/mime");
-        verify(mimeMap, times(2)).guessMimeTypeFromLowerCaseExtension("test");
-    }
-
-    @Test public void compareAndSetDefault() {
-        MimeMap otherMimeMap = mock(TestMimeMap.class);
-        MimeMap defaultMimeMap = MimeMap.getDefault();
-        assertTrue(MimeMap.compareAndSetDefault(defaultMimeMap, mimeMap));
-        try {
-            assertNotNull(defaultMimeMap);
-            assertEquals(mimeMap, MimeMap.getDefault());
-            assertFalse(MimeMap.compareAndSetDefault(defaultMimeMap, otherMimeMap));
-        } finally {
-            assertTrue(MimeMap.compareAndSetDefault(mimeMap, defaultMimeMap));
-        }
-    }
-
-    @Test public void compareAndSetDefault_null() {
-        MimeMap defaultMimeMap = MimeMap.getDefault();
-        try {
-            MimeMap.compareAndSetDefault(defaultMimeMap, null);
-            fail();
-        } catch (NullPointerException expected) {
-        }
-
-        try {
-            MimeMap.compareAndSetDefault(null, defaultMimeMap);
-            fail();
-        } catch (NullPointerException expected) {
-        }
-
-        // For comparison, this does not throw (but has no effect):
-        MimeMap.compareAndSetDefault(defaultMimeMap, defaultMimeMap);
-        assertEquals(defaultMimeMap, MimeMap.getDefault());
-    }
-
-    @Test public void defaultMap_15715370() {
-        assertEquals("audio/flac", defaultMimeMap.guessMimeTypeFromExtension("flac"));
-        assertEquals("flac", defaultMimeMap.guessExtensionFromMimeType("audio/flac"));
-        assertEquals("flac", defaultMimeMap.guessExtensionFromMimeType("application/x-flac"));
-    }
-
-    // https://code.google.com/p/android/issues/detail?id=78909
-    @Test public void defaultMap_78909() {
-        assertEquals("mka", defaultMimeMap.guessExtensionFromMimeType("audio/x-matroska"));
-        assertEquals("mkv", defaultMimeMap.guessExtensionFromMimeType("video/x-matroska"));
-    }
-
-    @Test public void defaultMap_16978217() {
-        assertEquals("image/x-ms-bmp", defaultMimeMap.guessMimeTypeFromExtension("bmp"));
-        assertEquals("image/x-icon", defaultMimeMap.guessMimeTypeFromExtension("ico"));
-        assertEquals("video/mp2ts", defaultMimeMap.guessMimeTypeFromExtension("ts"));
-    }
-
-    @Test public void testCommon() {
-        assertEquals("audio/mpeg", defaultMimeMap.guessMimeTypeFromExtension("mp3"));
-        assertEquals("image/png", defaultMimeMap.guessMimeTypeFromExtension("png"));
-        assertEquals("application/zip", defaultMimeMap.guessMimeTypeFromExtension("zip"));
-
-        assertEquals("mp3", defaultMimeMap.guessExtensionFromMimeType("audio/mpeg"));
-        assertEquals("png", defaultMimeMap.guessExtensionFromMimeType("image/png"));
-        assertEquals("zip", defaultMimeMap.guessExtensionFromMimeType("application/zip"));
-    }
-
-    @Test public void defaultMap_18390752() {
-        assertEquals("jpg", defaultMimeMap.guessExtensionFromMimeType("image/jpeg"));
-    }
-
-    @Test public void defaultMap_30207891() {
-        assertTrue(defaultMimeMap.hasMimeType("IMAGE/PNG"));
-        assertTrue(defaultMimeMap.hasMimeType("IMAGE/png"));
-        assertFalse(defaultMimeMap.hasMimeType(""));
-        assertEquals("png", defaultMimeMap.guessExtensionFromMimeType("IMAGE/PNG"));
-        assertEquals("png", defaultMimeMap.guessExtensionFromMimeType("IMAGE/png"));
-        assertNull(defaultMimeMap.guessMimeTypeFromExtension(""));
-        assertNull(defaultMimeMap.guessMimeTypeFromExtension("doesnotexist"));
-        assertTrue(defaultMimeMap.hasExtension("PNG"));
-        assertTrue(defaultMimeMap.hasExtension("PnG"));
-        assertFalse(defaultMimeMap.hasExtension(""));
-        assertFalse(defaultMimeMap.hasExtension(".png"));
-        assertEquals("image/png", defaultMimeMap.guessMimeTypeFromExtension("PNG"));
-        assertEquals("image/png", defaultMimeMap.guessMimeTypeFromExtension("PnG"));
-        assertNull(defaultMimeMap.guessMimeTypeFromExtension(".png"));
-        assertNull(defaultMimeMap.guessMimeTypeFromExtension(""));
-        assertNull(defaultMimeMap.guessExtensionFromMimeType("doesnotexist"));
-    }
-
-    @Test public void defaultMap_30793548() {
-        assertEquals("video/3gpp", defaultMimeMap.guessMimeTypeFromExtension("3gpp"));
-        assertEquals("video/3gpp", defaultMimeMap.guessMimeTypeFromExtension("3gp"));
-        assertEquals("video/3gpp2", defaultMimeMap.guessMimeTypeFromExtension("3gpp2"));
-        assertEquals("video/3gpp2", defaultMimeMap.guessMimeTypeFromExtension("3g2"));
-    }
-
-    @Test public void defaultMap_37167977() {
-        // https://tools.ietf.org/html/rfc5334#section-10.1
-        assertEquals("audio/ogg", defaultMimeMap.guessMimeTypeFromExtension("ogg"));
-        assertEquals("audio/ogg", defaultMimeMap.guessMimeTypeFromExtension("oga"));
-        assertEquals("audio/ogg", defaultMimeMap.guessMimeTypeFromExtension("spx"));
-        assertEquals("video/ogg", defaultMimeMap.guessMimeTypeFromExtension("ogv"));
-    }
-
-    @Test public void defaultMap_70851634_mimeTypeFromExtension() {
-        assertEquals("video/vnd.youtube.yt", defaultMimeMap.guessMimeTypeFromExtension("yt"));
-    }
-
-    @Test public void defaultMap_70851634_extensionFromMimeType() {
-        assertEquals("yt", defaultMimeMap.guessExtensionFromMimeType("video/vnd.youtube.yt"));
-        assertEquals("yt", defaultMimeMap.guessExtensionFromMimeType("application/vnd.youtube.yt"));
-    }
-
-    @Test public void defaultMap_112162449_audio() {
-        // According to https://en.wikipedia.org/wiki/M3U#Internet_media_types
-        // this is a giant mess, so we pick "audio/x-mpegurl" because a similar
-        // playlist format uses "audio/x-scpls".
-        assertMimeTypeFromExtension("audio/x-mpegurl", "m3u");
-        assertMimeTypeFromExtension("audio/x-mpegurl", "m3u8");
-        assertExtensionFromMimeType("m3u", "audio/x-mpegurl");
-
-        assertExtensionFromMimeType("m4a", "audio/mp4");
-        assertMimeTypeFromExtension("audio/mpeg", "m4a");
-
-        assertBidirectional("audio/aac", "aac");
-    }
-
-    @Test public void defaultMap_112162449_video() {
-        assertBidirectional("video/x-flv", "flv");
-        assertBidirectional("video/quicktime", "mov");
-        assertBidirectional("video/mpeg", "mpeg");
-    }
-
-    @Test public void defaultMap_112162449_image() {
-        assertBidirectional("image/heif", "heif");
-        assertBidirectional("image/heif-sequence", "heifs");
-        assertBidirectional("image/heic", "heic");
-        assertBidirectional("image/heic-sequence", "heics");
-        assertMimeTypeFromExtension("image/heif", "hif");
-
-        assertBidirectional("image/x-adobe-dng", "dng");
-        assertBidirectional("image/x-photoshop", "psd");
-
-        assertBidirectional("image/jp2", "jp2");
-        assertMimeTypeFromExtension("image/jp2", "jpg2");
-    }
-
-    @Test public void defaultMap_120135571_audio() {
-        assertMimeTypeFromExtension("audio/mpeg", "m4r");
-    }
-
-    @Test public void defaultMap_136096979_ota() {
-        assertMimeTypeFromExtension("application/vnd.android.ota", "ota");
-    }
-
-    @Test public void defaultMap_wifiConfig_xml() {
-        assertExtensionFromMimeType("xml", "application/x-wifi-config");
-        assertMimeTypeFromExtension("text/xml", "xml");
-    }
-
-    // http://b/122734564
-    @Test public void defaultMap_NonLowercaseMimeType() {
-        // A mixed-case mimeType that appears in mime.types; we expect guessMimeTypeFromExtension()
-        // to return it in lowercase because MimeMap considers lowercase to be the canonical form.
-        String mimeType = "application/vnd.ms-word.document.macroEnabled.12".toLowerCase(Locale.US);
-        assertBidirectional(mimeType, "docm");
-    }
-
-    // Check that the keys given for lookups in either direction are not case sensitive
-    @Test public void defaultMap_CaseInsensitiveKeys() {
-        String mimeType = defaultMimeMap.guessMimeTypeFromExtension("apk");
-        assertNotNull(mimeType);
-
-        assertEquals(mimeType, defaultMimeMap.guessMimeTypeFromExtension("APK"));
-        assertEquals(mimeType, defaultMimeMap.guessMimeTypeFromExtension("aPk"));
-
-        assertEquals("apk", defaultMimeMap.guessExtensionFromMimeType(mimeType));
-        assertEquals("apk", defaultMimeMap.guessExtensionFromMimeType(
-                mimeType.toUpperCase(Locale.US)));
-        assertEquals("apk", defaultMimeMap.guessExtensionFromMimeType(
-                mimeType.toLowerCase(Locale.US)));
-    }
-
-    @Test public void defaultMap_invalid_empty() {
-        checkInvalidExtension("");
-        checkInvalidMimeType("");
-    }
-
-    @Test public void defaultMap_invalid_null() {
-        checkInvalidExtension(null);
-        checkInvalidMimeType(null);
-    }
-
-    @Test public void defaultMap_invalid() {
-        checkInvalidMimeType("invalid mime type");
-        checkInvalidExtension("invalid extension");
-    }
-
-    private void checkInvalidExtension(String s) {
-        assertFalse(defaultMimeMap.hasExtension(s));
-        assertNull(defaultMimeMap.guessMimeTypeFromExtension(s));
-    }
-
-    private void checkInvalidMimeType(String s) {
-        assertFalse(defaultMimeMap.hasMimeType(s));
-        assertNull(defaultMimeMap.guessExtensionFromMimeType(s));
-    }
-
-    private void assertMimeTypeFromExtension(String mimeType, String extension) {
-        final String actual = defaultMimeMap.guessMimeTypeFromExtension(extension);
-        if (!Objects.equals(mimeType, actual)) {
-            fail("Expected " + mimeType + " but was " + actual + " for extension " + extension);
-        }
-    }
-
-    private void assertExtensionFromMimeType(String extension, String mimeType) {
-        final String actual = defaultMimeMap.guessExtensionFromMimeType(mimeType);
-        if (!Objects.equals(extension, actual)) {
-            fail("Expected " + extension + " but was " + actual + " for type " + mimeType);
-        }
-    }
-
-    private void assertBidirectional(String mimeType, String extension) {
-        assertMimeTypeFromExtension(mimeType, extension);
-        assertExtensionFromMimeType(extension, mimeType);
-    }
-}
diff --git a/mmodules/core_platform_api/Android.bp b/mmodules/core_platform_api/Android.bp
index de165d5..b82cc13 100644
--- a/mmodules/core_platform_api/Android.bp
+++ b/mmodules/core_platform_api/Android.bp
@@ -12,16 +12,24 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Build rules for the APIs that various core libraries provide to other parts
-// of the Android software stack: these include the public SDK APIs plus some
-// "core platform APIs" that only the Android software stack can use.
-
-// Generates stub source files for the {public SDK + core platform} API of the
-// core jars.
+// Generates stub source files for the core platform API of the ART module.
+// i.e. every class/member that is either in the public API or annotated with
+// @CorePlatformApi.
+//
+// The API specification .txt files managed by this only contain the additional
+// classes/members that are in the intra-core API but which are not in the public
+// API.
 droidstubs {
-    name: "core-platform-api-stubs",
-    srcs: [":core_api_files"],
+    name: "art-module-platform-api-stubs-source",
+    srcs: [
+        ":art_module_api_files",
+    ],
     sdk_version: "none",
+    libs: [
+        // Needed to break the cycle in the platform api caused by
+        // b/141747409.
+        "i18n.module.intra.core.api.stubs",
+    ],
 
     installable: false,
     args: "--hide-annotation libcore.api.Hide " +
@@ -45,12 +53,55 @@
     },
 }
 
+// A special set of system modules that is needed to break the cycle in the
+// platform api caused by b/141747409.
+java_system_modules {
+    name: "break-cycle-in-core-platform-system-modules",
+    libs: [
+        "art.module.intra.core.api.stubs",
+        "i18n.module.intra.core.api.stubs",
+    ],
+}
+
+// A library containing the core platform API stubs of the ART module.
+//
+// Core platform APIs are only intended for use of other parts of the platform, not the
+// core library modules.
+java_library {
+    name: "art.module.platform.api.stubs",
+    visibility: [
+        "//external/conscrypt",
+        "//external/icu/android_icu4j",
+    ],
+    srcs: [
+        ":art-module-platform-api-stubs-source",
+    ],
+    hostdex: true,
+
+    sdk_version: "none",
+    system_modules: "break-cycle-in-core-platform-system-modules",
+    patch_module: "java.base",
+}
+
+// Used when compiling higher-level code against core.platform.api.stubs.
+java_system_modules {
+    name: "art-module-platform-api-stubs-system-modules",
+    visibility: [
+        "//external/conscrypt",
+        "//external/icu/android_icu4j",
+        "//external/wycheproof",
+    ],
+    libs: [
+        "art.module.platform.api.stubs",
+    ],
+}
+
 // Ideally this should be a restricted whitelist but there are hundreds of modules that depend on
 // this.
 // TODO(http://b/134561230) - limit the number of dependents on this.
 core_platform_visibility = ["//visibility:public"]
 
-// A library containing the {public SDK + core platform} API stubs for the core jars.
+// A library containing the core platform API stubs for the core libraries.
 //
 // Although this stubs library is primarily used by the Java compiler / build to indicate
 // the core platform API surface area, compile_dex: true is used so that the Core Platform
@@ -59,12 +110,16 @@
 java_library {
     name: "core.platform.api.stubs",
     visibility: core_platform_visibility,
-    srcs: [":core-platform-api-stubs"],
     hostdex: true,
     compile_dex: true,
 
     sdk_version: "none",
     system_modules: "none",
+    static_libs: [
+        "art.module.platform.api.stubs",
+        "conscrypt.module.platform.api.stubs",
+        "i18n.module.platform.api.stubs",
+    ],
     patch_module: "java.base",
 }
 
diff --git a/mmodules/core_platform_api/api/platform/current-api.txt b/mmodules/core_platform_api/api/platform/current-api.txt
index e8de539..662ac70 100644
--- a/mmodules/core_platform_api/api/platform/current-api.txt
+++ b/mmodules/core_platform_api/api/platform/current-api.txt
@@ -29,57 +29,6 @@
 
 }
 
-package android.icu.impl {
-
-  public class CalendarAstronomer {
-    ctor public CalendarAstronomer(double, double);
-    method public long getSunRiseSet(boolean);
-    method public void setTime(long);
-  }
-
-  public class TimeZoneAdapter extends java.util.TimeZone {
-    method public static java.util.TimeZone wrap(android.icu.util.TimeZone);
-  }
-
-}
-
-package android.icu.text {
-
-  public final class StringPrep {
-    method public static android.icu.text.StringPrep getInstance(int);
-    method public String prepare(String, int) throws android.icu.text.StringPrepParseException;
-    field public static final int DEFAULT = 0; // 0x0
-    field public static final int RFC3920_RESOURCEPREP = 8; // 0x8
-  }
-
-}
-
-package android.icu.util {
-
-  public abstract class BasicTimeZone extends android.icu.util.TimeZone {
-    method public abstract android.icu.util.TimeZoneTransition getNextTransition(long, boolean);
-  }
-
-  public class Region implements java.lang.Comparable<android.icu.util.Region> {
-    method public static java.util.Set<android.icu.util.Region> getAvailable(android.icu.util.Region.RegionType);
-  }
-
-  public enum Region.RegionType {
-    enum_constant public static final android.icu.util.Region.RegionType TERRITORY;
-  }
-
-  public abstract class TimeZoneRule implements java.io.Serializable {
-    method public int getDSTSavings();
-  }
-
-  public class TimeZoneTransition {
-    method public android.icu.util.TimeZoneRule getFrom();
-    method public long getTime();
-    method public android.icu.util.TimeZoneRule getTo();
-  }
-
-}
-
 package android.system {
 
   public class Int32Ref {
@@ -540,105 +489,6 @@
 
 }
 
-package com.android.org.conscrypt {
-
-  public interface CertPinManager {
-  }
-
-  public final class ClientSessionContext implements javax.net.ssl.SSLSessionContext {
-    method public final java.util.Enumeration<byte[]> getIds();
-    method public final javax.net.ssl.SSLSession getSession(byte[]);
-    method public final int getSessionCacheSize();
-    method public final int getSessionTimeout();
-    method @dalvik.annotation.compat.UnsupportedAppUsage public void setPersistentCache(com.android.org.conscrypt.SSLClientSessionCache);
-    method public final void setSessionCacheSize(int) throws java.lang.IllegalArgumentException;
-    method public final void setSessionTimeout(int) throws java.lang.IllegalArgumentException;
-  }
-
-  public final class Conscrypt {
-    method public static javax.net.ssl.X509TrustManager getDefaultX509TrustManager() throws java.security.KeyManagementException;
-  }
-
-  public interface ConscryptCertStore {
-  }
-
-  public final class FileClientSessionCache {
-    method @dalvik.annotation.compat.UnsupportedAppUsage public static com.android.org.conscrypt.SSLClientSessionCache usingDirectory(java.io.File) throws java.io.IOException;
-  }
-
-  public final class OpenSSLProvider extends java.security.Provider {
-    ctor @dalvik.annotation.compat.UnsupportedAppUsage public OpenSSLProvider();
-  }
-
-  public abstract class OpenSSLSocketImpl extends javax.net.ssl.SSLSocket {
-    method public void addHandshakeCompletedListener(javax.net.ssl.HandshakeCompletedListener);
-    method public final void connect(java.net.SocketAddress) throws java.io.IOException;
-    method public final void connect(java.net.SocketAddress, int) throws java.io.IOException;
-    method @Deprecated @dalvik.annotation.compat.UnsupportedAppUsage(maxTargetSdk=dalvik.system.VersionCodes.Q, publicAlternatives="Use {@link javax.net.ssl.SSLSocket#getApplicationProtocol()}.") public final byte[] getAlpnSelectedProtocol();
-    method @Deprecated @dalvik.annotation.compat.UnsupportedAppUsage public final byte[] getNpnSelectedProtocol();
-    method public final int getPort();
-    method public final int getSoTimeout() throws java.net.SocketException;
-    method public void removeHandshakeCompletedListener(javax.net.ssl.HandshakeCompletedListener);
-    method public final void sendUrgentData(int) throws java.io.IOException;
-    method @Deprecated @dalvik.annotation.compat.UnsupportedAppUsage(maxTargetSdk=dalvik.system.VersionCodes.Q, publicAlternatives="Use {@link javax.net.ssl.SSLParameters#setApplicationProtocols(java.lang.String[])}.") public final void setAlpnProtocols(byte[]);
-    method @dalvik.annotation.compat.UnsupportedAppUsage public abstract void setChannelIdPrivateKey(java.security.PrivateKey);
-    method @dalvik.annotation.compat.UnsupportedAppUsage public void setHandshakeTimeout(int) throws java.net.SocketException;
-    method @dalvik.annotation.compat.UnsupportedAppUsage(maxTargetSdk=dalvik.system.VersionCodes.Q, publicAlternatives="Use {@link javax.net.ssl.SSLParameters#setServerNames}.") public void setHostname(String);
-    method @Deprecated @dalvik.annotation.compat.UnsupportedAppUsage public final void setNpnProtocols(byte[]);
-    method public final void setOOBInline(boolean) throws java.net.SocketException;
-    method public final void setSoTimeout(int) throws java.net.SocketException;
-    method @dalvik.annotation.compat.UnsupportedAppUsage public void setSoWriteTimeout(int) throws java.net.SocketException;
-    method @dalvik.annotation.compat.UnsupportedAppUsage(maxTargetSdk=dalvik.system.VersionCodes.Q, publicAlternatives="Use {@link android.net.ssl.SSLSockets#setUseSessionTickets}.") public abstract void setUseSessionTickets(boolean);
-  }
-
-  public interface SSLClientSessionCache {
-  }
-
-  public final class TrustManagerImpl extends javax.net.ssl.X509ExtendedTrustManager {
-    ctor @dalvik.annotation.compat.UnsupportedAppUsage public TrustManagerImpl(java.security.KeyStore);
-    ctor public TrustManagerImpl(java.security.KeyStore, com.android.org.conscrypt.CertPinManager, com.android.org.conscrypt.ConscryptCertStore);
-    method public void checkClientTrusted(java.security.cert.X509Certificate[], String) throws java.security.cert.CertificateException;
-    method public void checkClientTrusted(java.security.cert.X509Certificate[], String, java.net.Socket) throws java.security.cert.CertificateException;
-    method public void checkClientTrusted(java.security.cert.X509Certificate[], String, javax.net.ssl.SSLEngine) throws java.security.cert.CertificateException;
-    method @dalvik.annotation.compat.UnsupportedAppUsage public java.util.List<java.security.cert.X509Certificate> checkServerTrusted(java.security.cert.X509Certificate[], String, String) throws java.security.cert.CertificateException;
-    method public java.util.List<java.security.cert.X509Certificate> getTrustedChainForServer(java.security.cert.X509Certificate[], String, java.net.Socket) throws java.security.cert.CertificateException;
-    method public java.util.List<java.security.cert.X509Certificate> getTrustedChainForServer(java.security.cert.X509Certificate[], String, javax.net.ssl.SSLEngine) throws java.security.cert.CertificateException;
-    method public void handleTrustStorageUpdate();
-  }
-
-  public final class TrustedCertificateIndex {
-    ctor public TrustedCertificateIndex();
-    method public java.util.Set<java.security.cert.TrustAnchor> findAllByIssuerAndSignature(java.security.cert.X509Certificate);
-    method public java.security.cert.TrustAnchor findByIssuerAndSignature(java.security.cert.X509Certificate);
-    method public java.security.cert.TrustAnchor findBySubjectAndPublicKey(java.security.cert.X509Certificate);
-    method public java.security.cert.TrustAnchor index(java.security.cert.X509Certificate);
-  }
-
-  public class TrustedCertificateStore implements com.android.org.conscrypt.ConscryptCertStore {
-    ctor @dalvik.annotation.compat.UnsupportedAppUsage public TrustedCertificateStore();
-    method public java.util.Set<java.lang.String> aliases();
-    method public java.util.Set<java.lang.String> allSystemAliases();
-    method public boolean containsAlias(String);
-    method public void deleteCertificateEntry(String) throws java.security.cert.CertificateException, java.io.IOException;
-    method public java.util.Set<java.security.cert.X509Certificate> findAllIssuers(java.security.cert.X509Certificate);
-    method public java.security.cert.X509Certificate findIssuer(java.security.cert.X509Certificate);
-    method public java.security.cert.Certificate getCertificate(String);
-    method public java.security.cert.Certificate getCertificate(String, boolean);
-    method public String getCertificateAlias(java.security.cert.Certificate);
-    method public String getCertificateAlias(java.security.cert.Certificate, boolean);
-    method @dalvik.annotation.compat.UnsupportedAppUsage public java.util.List<java.security.cert.X509Certificate> getCertificateChain(java.security.cert.X509Certificate) throws java.security.cert.CertificateException;
-    method public java.io.File getCertificateFile(java.io.File, java.security.cert.X509Certificate);
-    method public java.util.Date getCreationDate(String);
-    method public java.security.cert.X509Certificate getTrustAnchor(java.security.cert.X509Certificate);
-    method public void installCertificate(java.security.cert.X509Certificate) throws java.security.cert.CertificateException, java.io.IOException;
-    method public static final boolean isUser(String);
-    method public boolean isUserAddedCertificate(java.security.cert.X509Certificate);
-    method public static void setDefaultUserDirectory(java.io.File);
-    method public java.util.Set<java.lang.String> userAliases();
-  }
-
-}
-
 package dalvik.annotation.codegen {
 
   @java.lang.annotation.Repeatable(CovariantReturnType.CovariantReturnTypes.class) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD}) public @interface CovariantReturnType {
@@ -1075,6 +925,28 @@
 
 }
 
+package libcore.content.type {
+
+  public final class MimeMap {
+    method public libcore.content.type.MimeMap.Builder buildUpon();
+    method public static libcore.content.type.MimeMap.Builder builder();
+    method @NonNull public java.util.Set<java.lang.String> extensions();
+    method @NonNull public static libcore.content.type.MimeMap getDefault();
+    method @Nullable public String guessExtensionFromMimeType(@Nullable String);
+    method @Nullable public String guessMimeTypeFromExtension(@Nullable String);
+    method public boolean hasExtension(@Nullable String);
+    method public boolean hasMimeType(@Nullable String);
+    method @NonNull public java.util.Set<java.lang.String> mimeTypes();
+    method public static void setDefaultSupplier(@NonNull java.util.function.Supplier<libcore.content.type.MimeMap>);
+  }
+
+  public static final class MimeMap.Builder {
+    method public libcore.content.type.MimeMap build();
+    method public libcore.content.type.MimeMap.Builder put(@NonNull String, @NonNull java.util.List<java.lang.String>);
+  }
+
+}
+
 package libcore.icu {
 
   public final class DateIntervalFormat {
@@ -1202,17 +1074,6 @@
     method public static java.net.InetAddress parseNumericAddress(String);
   }
 
-  public abstract class MimeMap {
-    method public static boolean compareAndSetDefault(@NonNull libcore.net.MimeMap, @NonNull libcore.net.MimeMap);
-    method @NonNull public static libcore.net.MimeMap getDefault();
-    method @Nullable protected abstract String guessExtensionFromLowerCaseMimeType(@NonNull String);
-    method @Nullable public final String guessExtensionFromMimeType(@Nullable String);
-    method @Nullable public final String guessMimeTypeFromExtension(@Nullable String);
-    method @Nullable protected abstract String guessMimeTypeFromLowerCaseExtension(@NonNull String);
-    method public final boolean hasExtension(@Nullable String);
-    method public final boolean hasMimeType(@Nullable String);
-  }
-
   public abstract class NetworkSecurityPolicy {
     ctor public NetworkSecurityPolicy();
     method public static libcore.net.NetworkSecurityPolicy getInstance();
diff --git a/mmodules/intracoreapi/Android.bp b/mmodules/intracoreapi/Android.bp
index cb40d94..6775980 100644
--- a/mmodules/intracoreapi/Android.bp
+++ b/mmodules/intracoreapi/Android.bp
@@ -12,17 +12,19 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Build rules for the APIs that the various core libraries can depend on from
-// each other: public SDK APIs and "intra-core" APIs. Intra-core APIs are not
-// for use by other parts of the Android software stack.
-
-// Generates stub source files for the {public SDK + intra-core} API
-// of the core jars.
+// Generates stub source files for the intra-core API of the ART module.
+// i.e. every class/member that is either in the public API or annotated with
+// @IntraCoreApi.
+//
+// The API specification .txt files managed by this only contain the additional
+// classes/members that are in the intra-core API but which are not in the public
+// API.
 droidstubs {
-    name: "core-intra-stubs",
-    srcs: [":core_api_files"],
+    name: "art-module-intra-core-api-stubs-source",
+    srcs: [
+        ":art_module_api_files",
+    ],
     sdk_version: "none",
-    libs: ["core-all"],
 
     installable: false,
     args: "--hide-annotation libcore.api.Hide " +
@@ -45,53 +47,36 @@
     },
 }
 
-// A library containing the {public SDK + intra-core} API stubs for the
-// core jars.
+// A library containing the intra-core API stubs of the ART module.
+//
+// Intra-core APIs are only intended for the use of other core library modules.
 java_library {
-    name: "core.intra.stubs",
-    srcs: [":core-intra-stubs"],
-
-    sdk_version: "none",
-    libs: ["core-all"],
-    system_modules: "core-all-system-modules",
-    openjdk9: {
-        javacflags: ["--patch-module=java.base=."],
-    },
-}
-
-// Used when compiling against core.intra.stubs.
-java_system_modules {
-    name: "core-intra-stubs-system-modules",
+    name: "art.module.intra.core.api.stubs",
     visibility: [
         "//external/conscrypt",
+        "//external/icu/android_icu4j",
+        "//libcore/mmodules/core_platform_api",
     ],
-    libs: ["core.intra.stubs"],
-}
-
-// A rule that checks we can build core-libart and core-oj using only
-// the source for core-libart and core-oj and the APIs in core-intra-stubs.
-// This proves we don't actually depend on things from (for example) conscrypt and icu4j
-// we haven't added to the intra-core API.
-java_library {
-    name: "core-libart-oj.depscheck",
     srcs: [
-        ":core_libart_java_files",
-        ":core_oj_java_files",
+        ":art-module-intra-core-api-stubs-source",
+        ":openjdk_lambda_stub_files",
+        ":openjdk_generated_annotation_stub_files",
     ],
-    errorprone: {
-        javacflags: [
-            "-Xep:MissingOverride:OFF", // Ignore missing @Override.
-            "-Xep:ConstantOverflow:WARN", // Known constant overflow in SplittableRandom
-        ],
-    },
-
-    installable: false,
 
     sdk_version: "none",
-    libs: ["core.intra.stubs"],
-    system_modules: "core-intra-stubs-system-modules",
-    java_version: "1.9",
+    system_modules: "none",
     openjdk9: {
         javacflags: ["--patch-module=java.base=."],
     },
 }
+
+// Used when compiling against art.module.intra.core.api.stubs.
+java_system_modules {
+    name: "art-module-intra-core-api-stubs-system-modules",
+    visibility: [
+        "//external/bouncycastle",
+        "//external/conscrypt",
+        "//external/icu/android_icu4j",
+    ],
+    libs: ["art.module.intra.core.api.stubs"],
+}
diff --git a/mmodules/intracoreapi/api/intra/current-api.txt b/mmodules/intracoreapi/api/intra/current-api.txt
index 390b72f..5e914d2 100644
--- a/mmodules/intracoreapi/api/intra/current-api.txt
+++ b/mmodules/intracoreapi/api/intra/current-api.txt
@@ -22,604 +22,6 @@
 
 }
 
-package android.icu.impl {
-
-  @libcore.api.IntraCoreApi public abstract class CacheValue<V> {
-    method @libcore.api.IntraCoreApi public static void setStrength(android.icu.impl.CacheValue.Strength);
-  }
-
-  @libcore.api.IntraCoreApi public enum CacheValue.Strength {
-    enum_constant @libcore.api.IntraCoreApi public static final android.icu.impl.CacheValue.Strength SOFT;
-    enum_constant @libcore.api.IntraCoreApi public static final android.icu.impl.CacheValue.Strength STRONG;
-  }
-
-  @libcore.api.IntraCoreApi public final class ICUData {
-    field @libcore.api.IntraCoreApi public static final String ICU_BASE_NAME = "android/icu/impl/data/icudt64b";
-  }
-
-  @libcore.api.IntraCoreApi public class ICUResourceBundle extends android.icu.util.UResourceBundle {
-    method @libcore.api.IntraCoreApi public String getStringWithFallback(String) throws java.util.MissingResourceException;
-    method @dalvik.annotation.compat.UnsupportedAppUsage @libcore.api.IntraCoreApi public android.icu.impl.ICUResourceBundle getWithFallback(String) throws java.util.MissingResourceException;
-  }
-
-  @libcore.api.IntraCoreApi public class JavaTimeZone extends android.icu.util.TimeZone {
-    ctor @libcore.api.IntraCoreApi public JavaTimeZone(java.util.TimeZone, String);
-  }
-
-  @libcore.api.IntraCoreApi public final class ZoneMeta {
-    method @libcore.api.IntraCoreApi public static String getCanonicalCLDRID(String);
-  }
-
-}
-
-package android.icu.impl.number {
-
-  @libcore.api.IntraCoreApi public class DecimalFormatProperties implements java.lang.Cloneable java.io.Serializable {
-  }
-
-  @libcore.api.IntraCoreApi public enum DecimalFormatProperties.ParseMode {
-    enum_constant @libcore.api.IntraCoreApi public static final android.icu.impl.number.DecimalFormatProperties.ParseMode COMPATIBILITY;
-  }
-
-}
-
-package android.icu.text {
-
-  public class DateFormatSymbols implements java.lang.Cloneable java.io.Serializable {
-    ctor @Deprecated @libcore.api.IntraCoreApi public DateFormatSymbols(android.icu.util.ULocale, String);
-    method @libcore.api.IntraCoreApi public String[] getNarrowEras();
-  }
-
-  public class DateTimePatternGenerator implements java.lang.Cloneable android.icu.util.Freezable<android.icu.text.DateTimePatternGenerator> {
-    method @Deprecated @libcore.api.IntraCoreApi public static android.icu.text.DateTimePatternGenerator getFrozenInstance(android.icu.util.ULocale);
-  }
-
-  public class DecimalFormat extends android.icu.text.NumberFormat {
-    method @libcore.api.IntraCoreApi public void setParseStrictMode(android.icu.impl.number.DecimalFormatProperties.ParseMode);
-  }
-
-  public abstract class IDNA {
-    method @Deprecated @libcore.api.IntraCoreApi public static StringBuffer convertIDNToASCII(String, int) throws android.icu.text.StringPrepParseException;
-    method @Deprecated @libcore.api.IntraCoreApi public static StringBuffer convertIDNToUnicode(String, int) throws android.icu.text.StringPrepParseException;
-  }
-
-  public final class Normalizer implements java.lang.Cloneable {
-    method @Deprecated @libcore.api.IntraCoreApi public static boolean isNormalized(String, android.icu.text.Normalizer.Mode, int);
-    method @Deprecated @libcore.api.IntraCoreApi public static String normalize(String, android.icu.text.Normalizer.Mode);
-    field @Deprecated @libcore.api.IntraCoreApi public static final android.icu.text.Normalizer.Mode NFC;
-    field @Deprecated @libcore.api.IntraCoreApi public static final android.icu.text.Normalizer.Mode NFD;
-    field @Deprecated @libcore.api.IntraCoreApi public static final android.icu.text.Normalizer.Mode NFKC;
-    field @Deprecated @libcore.api.IntraCoreApi public static final android.icu.text.Normalizer.Mode NFKD;
-  }
-
-  @Deprecated @libcore.api.IntraCoreApi public abstract static class Normalizer.Mode {
-  }
-
-  public abstract class TimeZoneNames implements java.io.Serializable {
-    method @libcore.api.IntraCoreApi public java.util.Collection<android.icu.text.TimeZoneNames.MatchInfo> find(CharSequence, int, java.util.EnumSet<android.icu.text.TimeZoneNames.NameType>);
-    method @Deprecated @libcore.api.IntraCoreApi public void getDisplayNames(String, android.icu.text.TimeZoneNames.NameType[], long, String[], int);
-  }
-
-  @libcore.api.IntraCoreApi public static class TimeZoneNames.MatchInfo {
-    method @libcore.api.IntraCoreApi public int matchLength();
-    method @libcore.api.IntraCoreApi public String mzID();
-    method @libcore.api.IntraCoreApi public android.icu.text.TimeZoneNames.NameType nameType();
-    method @libcore.api.IntraCoreApi public String tzID();
-  }
-
-}
-
-package android.icu.util {
-
-  @libcore.api.IntraCoreApi public class AnnualTimeZoneRule extends android.icu.util.TimeZoneRule {
-    method @libcore.api.IntraCoreApi public int getEndYear();
-    method @libcore.api.IntraCoreApi public android.icu.util.DateTimeRule getRule();
-    field @libcore.api.IntraCoreApi public static final int MAX_YEAR = 2147483647; // 0x7fffffff
-  }
-
-  @libcore.api.IntraCoreApi @libcore.api.CorePlatformApi public abstract class BasicTimeZone extends android.icu.util.TimeZone {
-    method @libcore.api.IntraCoreApi @libcore.api.CorePlatformApi public abstract android.icu.util.TimeZoneTransition getNextTransition(long, boolean);
-    method @libcore.api.IntraCoreApi public abstract android.icu.util.TimeZoneRule[] getTimeZoneRules();
-  }
-
-  public abstract class Calendar implements java.lang.Cloneable java.lang.Comparable<android.icu.util.Calendar> java.io.Serializable {
-    method @libcore.api.IntraCoreApi public static String getDateTimeFormatString(android.icu.util.ULocale, String, int, int);
-  }
-
-  @libcore.api.IntraCoreApi public class DateTimeRule implements java.io.Serializable {
-    method @libcore.api.IntraCoreApi public int getDateRuleType();
-    method @libcore.api.IntraCoreApi public int getRuleDayOfMonth();
-    method @libcore.api.IntraCoreApi public int getRuleDayOfWeek();
-    method @libcore.api.IntraCoreApi public int getRuleMillisInDay();
-    method @libcore.api.IntraCoreApi public int getRuleMonth();
-    method @libcore.api.IntraCoreApi public int getTimeRuleType();
-    field @libcore.api.IntraCoreApi public static final int DOM = 0; // 0x0
-    field @libcore.api.IntraCoreApi public static final int DOW = 1; // 0x1
-    field @libcore.api.IntraCoreApi public static final int DOW_GEQ_DOM = 2; // 0x2
-    field @libcore.api.IntraCoreApi public static final int DOW_LEQ_DOM = 3; // 0x3
-    field @libcore.api.IntraCoreApi public static final int STANDARD_TIME = 1; // 0x1
-    field @libcore.api.IntraCoreApi public static final int UTC_TIME = 2; // 0x2
-    field @libcore.api.IntraCoreApi public static final int WALL_TIME = 0; // 0x0
-  }
-
-  @libcore.api.IntraCoreApi public class InitialTimeZoneRule extends android.icu.util.TimeZoneRule {
-  }
-
-  public abstract class TimeZone implements java.lang.Cloneable android.icu.util.Freezable<android.icu.util.TimeZone> java.io.Serializable {
-    method @Deprecated @libcore.api.IntraCoreApi public static void setICUDefault(android.icu.util.TimeZone);
-  }
-
-  @libcore.api.IntraCoreApi @libcore.api.CorePlatformApi public abstract class TimeZoneRule implements java.io.Serializable {
-    method @libcore.api.IntraCoreApi @libcore.api.CorePlatformApi public int getDSTSavings();
-    method @libcore.api.IntraCoreApi public int getRawOffset();
-  }
-
-  @libcore.api.IntraCoreApi @libcore.api.CorePlatformApi public class TimeZoneTransition {
-    method @libcore.api.IntraCoreApi @libcore.api.CorePlatformApi public android.icu.util.TimeZoneRule getFrom();
-    method @libcore.api.IntraCoreApi @libcore.api.CorePlatformApi public long getTime();
-    method @libcore.api.IntraCoreApi @libcore.api.CorePlatformApi public android.icu.util.TimeZoneRule getTo();
-  }
-
-  public final class ULocale implements java.lang.Comparable<android.icu.util.ULocale> java.io.Serializable {
-    method @Deprecated @libcore.api.IntraCoreApi public static String getRegionForSupplementalData(android.icu.util.ULocale, boolean);
-  }
-
-  @libcore.api.IntraCoreApi public abstract class UResourceBundle extends java.util.ResourceBundle {
-    ctor @libcore.api.IntraCoreApi public UResourceBundle();
-    method @libcore.api.IntraCoreApi public static android.icu.util.UResourceBundle getBundleInstance(String, java.util.Locale);
-    method @libcore.api.IntraCoreApi public String[] getStringArray();
-  }
-
-}
-
-package com.android.org.conscrypt {
-
-  @libcore.api.IntraCoreApi public class DESEDESecretKeyFactory extends javax.crypto.SecretKeyFactorySpi {
-    ctor @libcore.api.IntraCoreApi public DESEDESecretKeyFactory();
-  }
-
-  @libcore.api.IntraCoreApi public class DefaultSSLContextImpl extends com.android.org.conscrypt.OpenSSLContextImpl {
-  }
-
-  @libcore.api.IntraCoreApi public static final class DefaultSSLContextImpl.TLSv12 extends com.android.org.conscrypt.DefaultSSLContextImpl {
-    ctor @libcore.api.IntraCoreApi public DefaultSSLContextImpl.TLSv12() throws java.security.GeneralSecurityException, java.io.IOException;
-  }
-
-  @libcore.api.IntraCoreApi public static final class DefaultSSLContextImpl.TLSv13 extends com.android.org.conscrypt.DefaultSSLContextImpl {
-    ctor @libcore.api.IntraCoreApi public DefaultSSLContextImpl.TLSv13() throws java.security.GeneralSecurityException, java.io.IOException;
-  }
-
-  @libcore.api.IntraCoreApi public class ECParameters extends java.security.AlgorithmParametersSpi {
-    ctor @libcore.api.IntraCoreApi public ECParameters();
-  }
-
-  @libcore.api.IntraCoreApi public final class GCMParameters extends java.security.AlgorithmParametersSpi {
-    ctor @libcore.api.IntraCoreApi public GCMParameters();
-  }
-
-  @libcore.api.IntraCoreApi public class IvParameters extends java.security.AlgorithmParametersSpi {
-    ctor @libcore.api.IntraCoreApi public IvParameters();
-  }
-
-  @libcore.api.IntraCoreApi public static class IvParameters.AES extends com.android.org.conscrypt.IvParameters {
-    ctor @libcore.api.IntraCoreApi public IvParameters.AES();
-  }
-
-  @libcore.api.IntraCoreApi public static class IvParameters.ChaCha20 extends com.android.org.conscrypt.IvParameters {
-    ctor @libcore.api.IntraCoreApi public IvParameters.ChaCha20();
-  }
-
-  @libcore.api.IntraCoreApi public static class IvParameters.DESEDE extends com.android.org.conscrypt.IvParameters {
-    ctor @libcore.api.IntraCoreApi public IvParameters.DESEDE();
-  }
-
-  @libcore.api.IntraCoreApi public abstract class KeyGeneratorImpl extends javax.crypto.KeyGeneratorSpi {
-  }
-
-  @libcore.api.IntraCoreApi public static final class KeyGeneratorImpl.AES extends com.android.org.conscrypt.KeyGeneratorImpl {
-    ctor @libcore.api.IntraCoreApi public KeyGeneratorImpl.AES();
-  }
-
-  @libcore.api.IntraCoreApi public static final class KeyGeneratorImpl.ARC4 extends com.android.org.conscrypt.KeyGeneratorImpl {
-    ctor @libcore.api.IntraCoreApi public KeyGeneratorImpl.ARC4();
-  }
-
-  @libcore.api.IntraCoreApi public static final class KeyGeneratorImpl.ChaCha20 extends com.android.org.conscrypt.KeyGeneratorImpl {
-    ctor @libcore.api.IntraCoreApi public KeyGeneratorImpl.ChaCha20();
-  }
-
-  @libcore.api.IntraCoreApi public static final class KeyGeneratorImpl.DESEDE extends com.android.org.conscrypt.KeyGeneratorImpl {
-    ctor @libcore.api.IntraCoreApi public KeyGeneratorImpl.DESEDE();
-  }
-
-  @libcore.api.IntraCoreApi public static final class KeyGeneratorImpl.HmacMD5 extends com.android.org.conscrypt.KeyGeneratorImpl {
-    ctor @libcore.api.IntraCoreApi public KeyGeneratorImpl.HmacMD5();
-  }
-
-  @libcore.api.IntraCoreApi public static final class KeyGeneratorImpl.HmacSHA1 extends com.android.org.conscrypt.KeyGeneratorImpl {
-    ctor @libcore.api.IntraCoreApi public KeyGeneratorImpl.HmacSHA1();
-  }
-
-  @libcore.api.IntraCoreApi public static final class KeyGeneratorImpl.HmacSHA224 extends com.android.org.conscrypt.KeyGeneratorImpl {
-    ctor @libcore.api.IntraCoreApi public KeyGeneratorImpl.HmacSHA224();
-  }
-
-  @libcore.api.IntraCoreApi public static final class KeyGeneratorImpl.HmacSHA256 extends com.android.org.conscrypt.KeyGeneratorImpl {
-    ctor @libcore.api.IntraCoreApi public KeyGeneratorImpl.HmacSHA256();
-  }
-
-  @libcore.api.IntraCoreApi public static final class KeyGeneratorImpl.HmacSHA384 extends com.android.org.conscrypt.KeyGeneratorImpl {
-    ctor @libcore.api.IntraCoreApi public KeyGeneratorImpl.HmacSHA384();
-  }
-
-  @libcore.api.IntraCoreApi public static final class KeyGeneratorImpl.HmacSHA512 extends com.android.org.conscrypt.KeyGeneratorImpl {
-    ctor @libcore.api.IntraCoreApi public KeyGeneratorImpl.HmacSHA512();
-  }
-
-  @libcore.api.IntraCoreApi public class OAEPParameters extends java.security.AlgorithmParametersSpi {
-    ctor @libcore.api.IntraCoreApi public OAEPParameters();
-  }
-
-  @libcore.api.IntraCoreApi public abstract class OpenSSLAeadCipher extends com.android.org.conscrypt.OpenSSLCipher {
-  }
-
-  @libcore.api.IntraCoreApi public abstract class OpenSSLAeadCipherAES extends com.android.org.conscrypt.OpenSSLAeadCipher {
-  }
-
-  @libcore.api.IntraCoreApi public static class OpenSSLAeadCipherAES.GCM extends com.android.org.conscrypt.OpenSSLAeadCipherAES {
-    ctor @libcore.api.IntraCoreApi public OpenSSLAeadCipherAES.GCM();
-  }
-
-  @libcore.api.IntraCoreApi public static class OpenSSLAeadCipherAES.GCM.AES_128 extends com.android.org.conscrypt.OpenSSLAeadCipherAES.GCM {
-    ctor @libcore.api.IntraCoreApi public OpenSSLAeadCipherAES.GCM.AES_128();
-  }
-
-  @libcore.api.IntraCoreApi public static class OpenSSLAeadCipherAES.GCM.AES_256 extends com.android.org.conscrypt.OpenSSLAeadCipherAES.GCM {
-    ctor @libcore.api.IntraCoreApi public OpenSSLAeadCipherAES.GCM.AES_256();
-  }
-
-  @libcore.api.IntraCoreApi public static class OpenSSLAeadCipherAES.GCM_SIV extends com.android.org.conscrypt.OpenSSLAeadCipherAES {
-    ctor @libcore.api.IntraCoreApi public OpenSSLAeadCipherAES.GCM_SIV();
-  }
-
-  @libcore.api.IntraCoreApi public static class OpenSSLAeadCipherAES.GCM_SIV.AES_128 extends com.android.org.conscrypt.OpenSSLAeadCipherAES.GCM_SIV {
-    ctor @libcore.api.IntraCoreApi public OpenSSLAeadCipherAES.GCM_SIV.AES_128();
-  }
-
-  @libcore.api.IntraCoreApi public static class OpenSSLAeadCipherAES.GCM_SIV.AES_256 extends com.android.org.conscrypt.OpenSSLAeadCipherAES.GCM_SIV {
-    ctor @libcore.api.IntraCoreApi public OpenSSLAeadCipherAES.GCM_SIV.AES_256();
-  }
-
-  @libcore.api.IntraCoreApi public class OpenSSLAeadCipherChaCha20 extends com.android.org.conscrypt.OpenSSLAeadCipher {
-    ctor @libcore.api.IntraCoreApi public OpenSSLAeadCipherChaCha20();
-  }
-
-  @libcore.api.IntraCoreApi public abstract class OpenSSLCipher extends javax.crypto.CipherSpi {
-  }
-
-  @libcore.api.IntraCoreApi public class OpenSSLCipherChaCha20 extends com.android.org.conscrypt.OpenSSLCipher {
-    ctor @libcore.api.IntraCoreApi public OpenSSLCipherChaCha20();
-  }
-
-  @libcore.api.IntraCoreApi public abstract class OpenSSLCipherRSA extends javax.crypto.CipherSpi {
-  }
-
-  @libcore.api.IntraCoreApi public static class OpenSSLCipherRSA.OAEP extends com.android.org.conscrypt.OpenSSLCipherRSA {
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLCipherRSA.OAEP.SHA1 extends com.android.org.conscrypt.OpenSSLCipherRSA.OAEP {
-    ctor @libcore.api.IntraCoreApi public OpenSSLCipherRSA.OAEP.SHA1();
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLCipherRSA.OAEP.SHA224 extends com.android.org.conscrypt.OpenSSLCipherRSA.OAEP {
-    ctor @libcore.api.IntraCoreApi public OpenSSLCipherRSA.OAEP.SHA224();
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLCipherRSA.OAEP.SHA256 extends com.android.org.conscrypt.OpenSSLCipherRSA.OAEP {
-    ctor @libcore.api.IntraCoreApi public OpenSSLCipherRSA.OAEP.SHA256();
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLCipherRSA.OAEP.SHA384 extends com.android.org.conscrypt.OpenSSLCipherRSA.OAEP {
-    ctor @libcore.api.IntraCoreApi public OpenSSLCipherRSA.OAEP.SHA384();
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLCipherRSA.OAEP.SHA512 extends com.android.org.conscrypt.OpenSSLCipherRSA.OAEP {
-    ctor @libcore.api.IntraCoreApi public OpenSSLCipherRSA.OAEP.SHA512();
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLCipherRSA.PKCS1 extends com.android.org.conscrypt.OpenSSLCipherRSA {
-    ctor @libcore.api.IntraCoreApi public OpenSSLCipherRSA.PKCS1();
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLCipherRSA.Raw extends com.android.org.conscrypt.OpenSSLCipherRSA {
-    ctor @libcore.api.IntraCoreApi public OpenSSLCipherRSA.Raw();
-  }
-
-  @libcore.api.IntraCoreApi public abstract class OpenSSLContextImpl extends javax.net.ssl.SSLContextSpi {
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLContextImpl.TLSv1 extends com.android.org.conscrypt.OpenSSLContextImpl {
-    ctor @libcore.api.IntraCoreApi public OpenSSLContextImpl.TLSv1();
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLContextImpl.TLSv11 extends com.android.org.conscrypt.OpenSSLContextImpl {
-    ctor @libcore.api.IntraCoreApi public OpenSSLContextImpl.TLSv11();
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLContextImpl.TLSv12 extends com.android.org.conscrypt.OpenSSLContextImpl {
-    ctor @dalvik.annotation.compat.UnsupportedAppUsage @libcore.api.IntraCoreApi public OpenSSLContextImpl.TLSv12();
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLContextImpl.TLSv13 extends com.android.org.conscrypt.OpenSSLContextImpl {
-    ctor @libcore.api.IntraCoreApi public OpenSSLContextImpl.TLSv13();
-  }
-
-  @libcore.api.IntraCoreApi public final class OpenSSLECDHKeyAgreement extends javax.crypto.KeyAgreementSpi {
-    ctor @libcore.api.IntraCoreApi public OpenSSLECDHKeyAgreement();
-  }
-
-  @libcore.api.IntraCoreApi public final class OpenSSLECKeyFactory extends java.security.KeyFactorySpi {
-    ctor @libcore.api.IntraCoreApi public OpenSSLECKeyFactory();
-  }
-
-  @libcore.api.IntraCoreApi public final class OpenSSLECKeyPairGenerator extends java.security.KeyPairGenerator {
-    ctor @libcore.api.IntraCoreApi public OpenSSLECKeyPairGenerator();
-  }
-
-  @libcore.api.IntraCoreApi public abstract class OpenSSLEvpCipher extends com.android.org.conscrypt.OpenSSLCipher {
-  }
-
-  @libcore.api.IntraCoreApi public abstract class OpenSSLEvpCipherAES extends com.android.org.conscrypt.OpenSSLEvpCipher {
-  }
-
-  @libcore.api.IntraCoreApi public static class OpenSSLEvpCipherAES.AES extends com.android.org.conscrypt.OpenSSLEvpCipherAES {
-  }
-
-  @libcore.api.IntraCoreApi public static class OpenSSLEvpCipherAES.AES.CBC extends com.android.org.conscrypt.OpenSSLEvpCipherAES.AES {
-  }
-
-  @libcore.api.IntraCoreApi public static class OpenSSLEvpCipherAES.AES.CBC.NoPadding extends com.android.org.conscrypt.OpenSSLEvpCipherAES.AES.CBC {
-    ctor @libcore.api.IntraCoreApi public OpenSSLEvpCipherAES.AES.CBC.NoPadding();
-  }
-
-  @libcore.api.IntraCoreApi public static class OpenSSLEvpCipherAES.AES.CBC.PKCS5Padding extends com.android.org.conscrypt.OpenSSLEvpCipherAES.AES.CBC {
-    ctor @libcore.api.IntraCoreApi public OpenSSLEvpCipherAES.AES.CBC.PKCS5Padding();
-  }
-
-  @libcore.api.IntraCoreApi public static class OpenSSLEvpCipherAES.AES.CTR extends com.android.org.conscrypt.OpenSSLEvpCipherAES.AES {
-    ctor @libcore.api.IntraCoreApi public OpenSSLEvpCipherAES.AES.CTR();
-  }
-
-  @libcore.api.IntraCoreApi public static class OpenSSLEvpCipherAES.AES.ECB extends com.android.org.conscrypt.OpenSSLEvpCipherAES.AES {
-  }
-
-  @libcore.api.IntraCoreApi public static class OpenSSLEvpCipherAES.AES.ECB.NoPadding extends com.android.org.conscrypt.OpenSSLEvpCipherAES.AES.ECB {
-    ctor @libcore.api.IntraCoreApi public OpenSSLEvpCipherAES.AES.ECB.NoPadding();
-  }
-
-  @libcore.api.IntraCoreApi public static class OpenSSLEvpCipherAES.AES.ECB.PKCS5Padding extends com.android.org.conscrypt.OpenSSLEvpCipherAES.AES.ECB {
-    ctor @libcore.api.IntraCoreApi public OpenSSLEvpCipherAES.AES.ECB.PKCS5Padding();
-  }
-
-  @libcore.api.IntraCoreApi public static class OpenSSLEvpCipherAES.AES_128 extends com.android.org.conscrypt.OpenSSLEvpCipherAES {
-  }
-
-  @libcore.api.IntraCoreApi public static class OpenSSLEvpCipherAES.AES_128.CBC extends com.android.org.conscrypt.OpenSSLEvpCipherAES.AES_128 {
-  }
-
-  @libcore.api.IntraCoreApi public static class OpenSSLEvpCipherAES.AES_128.CBC.NoPadding extends com.android.org.conscrypt.OpenSSLEvpCipherAES.AES_128.CBC {
-    ctor @libcore.api.IntraCoreApi public OpenSSLEvpCipherAES.AES_128.CBC.NoPadding();
-  }
-
-  @libcore.api.IntraCoreApi public static class OpenSSLEvpCipherAES.AES_128.CBC.PKCS5Padding extends com.android.org.conscrypt.OpenSSLEvpCipherAES.AES_128.CBC {
-    ctor @libcore.api.IntraCoreApi public OpenSSLEvpCipherAES.AES_128.CBC.PKCS5Padding();
-  }
-
-  @libcore.api.IntraCoreApi public static class OpenSSLEvpCipherAES.AES_128.ECB extends com.android.org.conscrypt.OpenSSLEvpCipherAES.AES_128 {
-  }
-
-  @libcore.api.IntraCoreApi public static class OpenSSLEvpCipherAES.AES_128.ECB.NoPadding extends com.android.org.conscrypt.OpenSSLEvpCipherAES.AES_128.ECB {
-    ctor @libcore.api.IntraCoreApi public OpenSSLEvpCipherAES.AES_128.ECB.NoPadding();
-  }
-
-  @libcore.api.IntraCoreApi public static class OpenSSLEvpCipherAES.AES_128.ECB.PKCS5Padding extends com.android.org.conscrypt.OpenSSLEvpCipherAES.AES_128.ECB {
-    ctor @libcore.api.IntraCoreApi public OpenSSLEvpCipherAES.AES_128.ECB.PKCS5Padding();
-  }
-
-  @libcore.api.IntraCoreApi public static class OpenSSLEvpCipherAES.AES_256 extends com.android.org.conscrypt.OpenSSLEvpCipherAES {
-  }
-
-  @libcore.api.IntraCoreApi public static class OpenSSLEvpCipherAES.AES_256.CBC extends com.android.org.conscrypt.OpenSSLEvpCipherAES.AES_256 {
-  }
-
-  @libcore.api.IntraCoreApi public static class OpenSSLEvpCipherAES.AES_256.CBC.NoPadding extends com.android.org.conscrypt.OpenSSLEvpCipherAES.AES_256.CBC {
-    ctor @libcore.api.IntraCoreApi public OpenSSLEvpCipherAES.AES_256.CBC.NoPadding();
-  }
-
-  @libcore.api.IntraCoreApi public static class OpenSSLEvpCipherAES.AES_256.CBC.PKCS5Padding extends com.android.org.conscrypt.OpenSSLEvpCipherAES.AES_256.CBC {
-    ctor @libcore.api.IntraCoreApi public OpenSSLEvpCipherAES.AES_256.CBC.PKCS5Padding();
-  }
-
-  @libcore.api.IntraCoreApi public static class OpenSSLEvpCipherAES.AES_256.ECB extends com.android.org.conscrypt.OpenSSLEvpCipherAES.AES_256 {
-  }
-
-  @libcore.api.IntraCoreApi public static class OpenSSLEvpCipherAES.AES_256.ECB.NoPadding extends com.android.org.conscrypt.OpenSSLEvpCipherAES.AES_256.ECB {
-    ctor @libcore.api.IntraCoreApi public OpenSSLEvpCipherAES.AES_256.ECB.NoPadding();
-  }
-
-  @libcore.api.IntraCoreApi public static class OpenSSLEvpCipherAES.AES_256.ECB.PKCS5Padding extends com.android.org.conscrypt.OpenSSLEvpCipherAES.AES_256.ECB {
-    ctor @libcore.api.IntraCoreApi public OpenSSLEvpCipherAES.AES_256.ECB.PKCS5Padding();
-  }
-
-  @libcore.api.IntraCoreApi public class OpenSSLEvpCipherARC4 extends com.android.org.conscrypt.OpenSSLEvpCipher {
-    ctor @libcore.api.IntraCoreApi public OpenSSLEvpCipherARC4();
-  }
-
-  @libcore.api.IntraCoreApi public abstract class OpenSSLEvpCipherDESEDE extends com.android.org.conscrypt.OpenSSLEvpCipher {
-  }
-
-  @libcore.api.IntraCoreApi public static class OpenSSLEvpCipherDESEDE.CBC extends com.android.org.conscrypt.OpenSSLEvpCipherDESEDE {
-  }
-
-  @libcore.api.IntraCoreApi public static class OpenSSLEvpCipherDESEDE.CBC.NoPadding extends com.android.org.conscrypt.OpenSSLEvpCipherDESEDE.CBC {
-    ctor @libcore.api.IntraCoreApi public OpenSSLEvpCipherDESEDE.CBC.NoPadding();
-  }
-
-  @libcore.api.IntraCoreApi public static class OpenSSLEvpCipherDESEDE.CBC.PKCS5Padding extends com.android.org.conscrypt.OpenSSLEvpCipherDESEDE.CBC {
-    ctor @libcore.api.IntraCoreApi public OpenSSLEvpCipherDESEDE.CBC.PKCS5Padding();
-  }
-
-  @libcore.api.IntraCoreApi public abstract class OpenSSLMac extends javax.crypto.MacSpi {
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLMac.HmacMD5 extends com.android.org.conscrypt.OpenSSLMac {
-    ctor @libcore.api.IntraCoreApi public OpenSSLMac.HmacMD5();
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLMac.HmacSHA1 extends com.android.org.conscrypt.OpenSSLMac {
-    ctor @libcore.api.IntraCoreApi public OpenSSLMac.HmacSHA1();
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLMac.HmacSHA224 extends com.android.org.conscrypt.OpenSSLMac {
-    ctor @libcore.api.IntraCoreApi public OpenSSLMac.HmacSHA224() throws java.security.NoSuchAlgorithmException;
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLMac.HmacSHA256 extends com.android.org.conscrypt.OpenSSLMac {
-    ctor @libcore.api.IntraCoreApi public OpenSSLMac.HmacSHA256() throws java.security.NoSuchAlgorithmException;
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLMac.HmacSHA384 extends com.android.org.conscrypt.OpenSSLMac {
-    ctor @libcore.api.IntraCoreApi public OpenSSLMac.HmacSHA384() throws java.security.NoSuchAlgorithmException;
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLMac.HmacSHA512 extends com.android.org.conscrypt.OpenSSLMac {
-    ctor @libcore.api.IntraCoreApi public OpenSSLMac.HmacSHA512();
-  }
-
-  @libcore.api.IntraCoreApi public class OpenSSLMessageDigestJDK extends java.security.MessageDigestSpi implements java.lang.Cloneable {
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLMessageDigestJDK.MD5 extends com.android.org.conscrypt.OpenSSLMessageDigestJDK {
-    ctor @libcore.api.IntraCoreApi public OpenSSLMessageDigestJDK.MD5() throws java.security.NoSuchAlgorithmException;
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLMessageDigestJDK.SHA1 extends com.android.org.conscrypt.OpenSSLMessageDigestJDK {
-    ctor @libcore.api.IntraCoreApi public OpenSSLMessageDigestJDK.SHA1() throws java.security.NoSuchAlgorithmException;
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLMessageDigestJDK.SHA224 extends com.android.org.conscrypt.OpenSSLMessageDigestJDK {
-    ctor @libcore.api.IntraCoreApi public OpenSSLMessageDigestJDK.SHA224() throws java.security.NoSuchAlgorithmException;
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLMessageDigestJDK.SHA256 extends com.android.org.conscrypt.OpenSSLMessageDigestJDK {
-    ctor @libcore.api.IntraCoreApi public OpenSSLMessageDigestJDK.SHA256() throws java.security.NoSuchAlgorithmException;
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLMessageDigestJDK.SHA384 extends com.android.org.conscrypt.OpenSSLMessageDigestJDK {
-    ctor @libcore.api.IntraCoreApi public OpenSSLMessageDigestJDK.SHA384() throws java.security.NoSuchAlgorithmException;
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLMessageDigestJDK.SHA512 extends com.android.org.conscrypt.OpenSSLMessageDigestJDK {
-    ctor @libcore.api.IntraCoreApi public OpenSSLMessageDigestJDK.SHA512() throws java.security.NoSuchAlgorithmException;
-  }
-
-  @libcore.api.IntraCoreApi public final class OpenSSLRSAKeyFactory extends java.security.KeyFactorySpi {
-    ctor @libcore.api.IntraCoreApi public OpenSSLRSAKeyFactory();
-  }
-
-  @libcore.api.IntraCoreApi public final class OpenSSLRSAKeyPairGenerator extends java.security.KeyPairGeneratorSpi {
-    ctor @libcore.api.IntraCoreApi public OpenSSLRSAKeyPairGenerator();
-  }
-
-  @libcore.api.IntraCoreApi public final class OpenSSLRandom extends java.security.SecureRandomSpi implements java.io.Serializable {
-    ctor @dalvik.annotation.compat.UnsupportedAppUsage @libcore.api.IntraCoreApi public OpenSSLRandom();
-  }
-
-  @libcore.api.IntraCoreApi public class OpenSSLSignature extends java.security.SignatureSpi {
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLSignature.MD5RSA extends com.android.org.conscrypt.OpenSSLSignature {
-    ctor @libcore.api.IntraCoreApi public OpenSSLSignature.MD5RSA();
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLSignature.SHA1ECDSA extends com.android.org.conscrypt.OpenSSLSignature {
-    ctor @libcore.api.IntraCoreApi public OpenSSLSignature.SHA1ECDSA();
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLSignature.SHA1RSA extends com.android.org.conscrypt.OpenSSLSignature {
-    ctor @libcore.api.IntraCoreApi public OpenSSLSignature.SHA1RSA();
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLSignature.SHA1RSAPSS extends com.android.org.conscrypt.OpenSSLSignature {
-    ctor @libcore.api.IntraCoreApi public OpenSSLSignature.SHA1RSAPSS();
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLSignature.SHA224ECDSA extends com.android.org.conscrypt.OpenSSLSignature {
-    ctor @libcore.api.IntraCoreApi public OpenSSLSignature.SHA224ECDSA();
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLSignature.SHA224RSA extends com.android.org.conscrypt.OpenSSLSignature {
-    ctor @libcore.api.IntraCoreApi public OpenSSLSignature.SHA224RSA();
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLSignature.SHA224RSAPSS extends com.android.org.conscrypt.OpenSSLSignature {
-    ctor @libcore.api.IntraCoreApi public OpenSSLSignature.SHA224RSAPSS();
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLSignature.SHA256ECDSA extends com.android.org.conscrypt.OpenSSLSignature {
-    ctor @libcore.api.IntraCoreApi public OpenSSLSignature.SHA256ECDSA();
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLSignature.SHA256RSA extends com.android.org.conscrypt.OpenSSLSignature {
-    ctor @libcore.api.IntraCoreApi public OpenSSLSignature.SHA256RSA();
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLSignature.SHA256RSAPSS extends com.android.org.conscrypt.OpenSSLSignature {
-    ctor @libcore.api.IntraCoreApi public OpenSSLSignature.SHA256RSAPSS();
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLSignature.SHA384ECDSA extends com.android.org.conscrypt.OpenSSLSignature {
-    ctor @libcore.api.IntraCoreApi public OpenSSLSignature.SHA384ECDSA();
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLSignature.SHA384RSA extends com.android.org.conscrypt.OpenSSLSignature {
-    ctor @libcore.api.IntraCoreApi public OpenSSLSignature.SHA384RSA();
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLSignature.SHA384RSAPSS extends com.android.org.conscrypt.OpenSSLSignature {
-    ctor @libcore.api.IntraCoreApi public OpenSSLSignature.SHA384RSAPSS();
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLSignature.SHA512ECDSA extends com.android.org.conscrypt.OpenSSLSignature {
-    ctor @libcore.api.IntraCoreApi public OpenSSLSignature.SHA512ECDSA();
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLSignature.SHA512RSA extends com.android.org.conscrypt.OpenSSLSignature {
-    ctor @libcore.api.IntraCoreApi public OpenSSLSignature.SHA512RSA();
-  }
-
-  @libcore.api.IntraCoreApi public static final class OpenSSLSignature.SHA512RSAPSS extends com.android.org.conscrypt.OpenSSLSignature {
-    ctor @libcore.api.IntraCoreApi public OpenSSLSignature.SHA512RSAPSS();
-  }
-
-  @libcore.api.IntraCoreApi public class OpenSSLSignatureRawECDSA extends java.security.SignatureSpi {
-    ctor @libcore.api.IntraCoreApi public OpenSSLSignatureRawECDSA();
-  }
-
-  @libcore.api.IntraCoreApi public final class OpenSSLSignatureRawRSA extends java.security.SignatureSpi {
-    ctor @libcore.api.IntraCoreApi public OpenSSLSignatureRawRSA();
-  }
-
-  @libcore.api.IntraCoreApi public class OpenSSLX509CertificateFactory extends java.security.cert.CertificateFactorySpi {
-    ctor @libcore.api.IntraCoreApi public OpenSSLX509CertificateFactory();
-  }
-
-  @libcore.api.IntraCoreApi public class PSSParameters extends java.security.AlgorithmParametersSpi {
-    ctor @libcore.api.IntraCoreApi public PSSParameters();
-  }
-
-}
-
 package dalvik.annotation.compat {
 
   @java.lang.annotation.Repeatable(UnsupportedAppUsage.Container.class) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.TYPE}) @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public @interface UnsupportedAppUsage {
@@ -688,6 +90,14 @@
 
 }
 
+package libcore.icu {
+
+  @libcore.api.IntraCoreApi @libcore.api.CorePlatformApi public final class ICU {
+    method @libcore.api.IntraCoreApi public static String getIcuVersion();
+  }
+
+}
+
 package libcore.net {
 
   @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public abstract class NetworkSecurityPolicy {
diff --git a/non_openjdk_java_files.bp b/non_openjdk_java_files.bp
index 61e891e..c080fcf 100644
--- a/non_openjdk_java_files.bp
+++ b/non_openjdk_java_files.bp
@@ -212,6 +212,7 @@
         "luni/src/main/java/libcore/api/CorePlatformApi.java",
         "luni/src/main/java/libcore/api/Hide.java",
         "luni/src/main/java/libcore/api/IntraCoreApi.java",
+        "luni/src/main/java/libcore/content/type/MimeMap.java",
         "luni/src/main/java/libcore/icu/DateIntervalFormat.java",
         "luni/src/main/java/libcore/icu/ICU.java",
         "luni/src/main/java/libcore/icu/LocaleData.java",
@@ -226,8 +227,6 @@
         "luni/src/main/java/libcore/io/Os.java",
         "luni/src/main/java/libcore/io/Streams.java",
         "luni/src/main/java/libcore/net/InetAddressUtils.java",
-        "luni/src/main/java/libcore/net/MimeMap.java",
-        "luni/src/main/java/libcore/net/MimeMapImpl.java",
         "luni/src/main/java/libcore/net/NetworkSecurityPolicy.java",
         "luni/src/main/java/libcore/net/event/NetworkEventDispatcher.java",
         "luni/src/main/java/libcore/timezone/CountryTimeZones.java",
diff --git a/ojluni/src/main/java/java/lang/invoke/MethodHandles.java b/ojluni/src/main/java/java/lang/invoke/MethodHandles.java
index 17c5f57..3b39fbd 100644
--- a/ojluni/src/main/java/java/lang/invoke/MethodHandles.java
+++ b/ojluni/src/main/java/java/lang/invoke/MethodHandles.java
@@ -1129,7 +1129,8 @@
 
             // Make sure that the special caller is identical to the lookup class or that we have
             // private access.
-            checkSpecialCaller(specialCaller);
+            // Android-changed: Also allow access to any interface methods.
+            checkSpecialCaller(specialCaller, refc);
 
             // Even though constructors are invoked using a "special" invoke, handles to them can't
             // be created using findSpecial. Callers must use findConstructor instead. Similarly,
@@ -1655,7 +1656,9 @@
             }
 
             if (!m.isAccessible()) {
-                checkSpecialCaller(specialCaller);
+                // Android-changed: Match Java language 9 behavior where unreflectSpecial continues
+                // to require exact caller lookupClass match.
+                checkSpecialCaller(specialCaller, null);
             }
 
             final MethodType methodType = MethodType.methodType(m.getReturnType(),
@@ -1937,13 +1940,19 @@
         //
         // private static final boolean ALLOW_NESTMATE_ACCESS = false;
 
-        private void checkSpecialCaller(Class<?> specialCaller) throws IllegalAccessException {
+        // Android-changed: Match java language 9 behavior allowing special access if the reflected
+        // class (called 'refc', the class from which the method is being accessed) is an interface
+        // and is implemented by the caller.
+        private void checkSpecialCaller(Class<?> specialCaller, Class<?> refc) throws IllegalAccessException {
             // Android-changed: No support for TRUSTED lookups. Also construct the
             // IllegalAccessException by hand because the upstream code implicitly assumes
             // that the lookupClass == specialCaller.
             //
             // if (allowedModes == TRUSTED)  return;
-            if (!hasPrivateAccess() || (specialCaller != lookupClass())) {
+            boolean isInterfaceLookup = (refc != null &&
+                                         refc.isInterface() &&
+                                         refc.isAssignableFrom(specialCaller));
+            if (!hasPrivateAccess() || (specialCaller != lookupClass() && !isInterfaceLookup)) {
                 throw new IllegalAccessException("no private access for invokespecial : "
                         + specialCaller + ", from" + this);
             }
diff --git a/ojluni/src/main/java/sun/nio/fs/MimeTypesFileTypeDetector.java b/ojluni/src/main/java/sun/nio/fs/MimeTypesFileTypeDetector.java
index b77b082..585b673 100644
--- a/ojluni/src/main/java/sun/nio/fs/MimeTypesFileTypeDetector.java
+++ b/ojluni/src/main/java/sun/nio/fs/MimeTypesFileTypeDetector.java
@@ -37,7 +37,7 @@
 import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
-import libcore.net.MimeMap;
+import libcore.content.type.MimeMap;
 
 /**
  * File type detector that uses a file extension to look up its MIME type
@@ -46,7 +46,7 @@
 
 class MimeTypesFileTypeDetector extends AbstractFileTypeDetector {
 
-    // BEGIN Android-removed: Delegate to libcore.net.MimeMap.
+    // BEGIN Android-removed: Delegate to libcore.content.type.MimeMap.
     /*
     // path to mime.types file
     private final Path mimeTypesFile;
@@ -61,7 +61,7 @@
         mimeTypesFile = filePath;
     }
     */
-    // END Android-removed: Delegate to libcore.net.MimeMap.
+    // END Android-removed: Delegate to libcore.content.type.MimeMap.
 
 
     @Override
@@ -74,7 +74,7 @@
         if (ext.isEmpty())
             return null;  // no extension
 
-        // Android-removed: Delegate to libcore.net.MimeMap.
+        // Android-removed: Delegate to libcore.content.type.MimeMap.
         // loadMimeTypes();
         // if (mimeTypeMap == null || mimeTypeMap.isEmpty())
         //    return null;
@@ -82,10 +82,10 @@
         // Case-sensitive search
         String mimeType;
         do {
-            // BEGIN Android-changed: Delegate to libcore.net.MimeMap.
+            // BEGIN Android-changed: Delegate to libcore.content.type.MimeMap.
             // mimeType = mimeTypeMap.get(ext);
             mimeType = MimeMap.getDefault().guessMimeTypeFromExtension(ext);
-            // END Android-changed: Delegate to libcore.net.MimeMap.
+            // END Android-changed: Delegate to libcore.content.type.MimeMap.
             if (mimeType == null)
                 ext = getExtension(ext);
         } while (mimeType == null && !ext.isEmpty());
@@ -105,7 +105,7 @@
         return ext;
     }
 
-    // BEGIN Android-removed: Delegate to libcore.net.MimeMap.
+    // BEGIN Android-removed: Delegate to libcore.content.type.MimeMap.
     /*
     /**
      * Parse the mime types file, and store the type-extension mappings into
@@ -218,5 +218,5 @@
         }
     }
     */
-    // END Android-removed: Delegate to libcore.net.MimeMap.
+    // END Android-removed: Delegate to libcore.content.type.MimeMap.
 }
diff --git a/openjdk_java_files.bp b/openjdk_java_files.bp
index 28d7af8..885517b1 100644
--- a/openjdk_java_files.bp
+++ b/openjdk_java_files.bp
@@ -1359,6 +1359,9 @@
 // any of these classes.
 filegroup {
     name: "openjdk_lambda_stub_files",
+    visibility: [
+        "//libcore:__subpackages__",
+    ],
     srcs: [
         "ojluni/src/lambda/java/java/lang/invoke/LambdaMetafactory.java",
         "ojluni/src/lambda/java/java/lang/invoke/SerializedLambda.java",
@@ -1383,6 +1386,9 @@
 // See http://b/123891440.
 filegroup {
     name: "openjdk_generated_annotation_stub_files",
+    visibility: [
+        "//libcore:__subpackages__",
+    ],
     srcs: [
         "ojluni/src/generated-annotation/java/javax/annotation/processing/Generated.java",
     ],