Merge "libfs_avb: adding two public APIs"
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index e684293..b69e773 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -85,6 +85,7 @@
 
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
 
+using android::base::Basename;
 using android::base::Realpath;
 using android::base::StartsWith;
 using android::base::unique_fd;
@@ -1576,65 +1577,41 @@
     return true;
 }
 
-bool fs_mgr_update_verity_state(
-        std::function<void(const std::string& mount_point, int mode)> callback) {
-    if (!callback) {
-        return false;
-    }
-
-    int mode;
-    if (!fs_mgr_load_verity_state(&mode)) {
-        return false;
-    }
-
-    Fstab fstab;
-    if (!ReadDefaultFstab(&fstab)) {
-        LERROR << "Failed to read default fstab";
+bool fs_mgr_is_verity_enabled(const FstabEntry& entry) {
+    if (!entry.fs_mgr_flags.verify && !entry.fs_mgr_flags.avb) {
         return false;
     }
 
     DeviceMapper& dm = DeviceMapper::Instance();
 
-    for (const auto& entry : fstab) {
-        if (!entry.fs_mgr_flags.verify && !entry.fs_mgr_flags.avb) {
-            continue;
-        }
-
-        std::string mount_point;
-        if (entry.mount_point == "/") {
-            // In AVB, the dm device name is vroot instead of system.
-            mount_point = entry.fs_mgr_flags.avb ? "vroot" : "system";
-        } else {
-            mount_point = basename(entry.mount_point.c_str());
-        }
-
-        if (dm.GetState(mount_point) == DmDeviceState::INVALID) {
-            PERROR << "Could not find verity device for mount point: " << mount_point;
-            continue;
-        }
-
-        const char* status;
-        std::vector<DeviceMapper::TargetInfo> table;
-        if (!dm.GetTableStatus(mount_point, &table) || table.empty() || table[0].data.empty()) {
-            if (!entry.fs_mgr_flags.verify_at_boot) {
-                PERROR << "Failed to query DM_TABLE_STATUS for " << mount_point;
-                continue;
-            }
-            status = "V";
-        } else {
-            status = table[0].data.c_str();
-        }
-
-        // To be consistent in vboot 1.0 and vboot 2.0 (AVB), change the mount_point
-        // back to 'system' for the callback. So it has property [partition.system.verified]
-        // instead of [partition.vroot.verified].
-        if (mount_point == "vroot") mount_point = "system";
-        if (*status == 'C' || *status == 'V') {
-            callback(mount_point, mode);
-        }
+    std::string mount_point;
+    if (entry.mount_point == "/") {
+        // In AVB, the dm device name is vroot instead of system.
+        mount_point = entry.fs_mgr_flags.avb ? "vroot" : "system";
+    } else {
+        mount_point = Basename(entry.mount_point);
     }
 
-    return true;
+    if (dm.GetState(mount_point) == DmDeviceState::INVALID) {
+        return false;
+    }
+
+    const char* status;
+    std::vector<DeviceMapper::TargetInfo> table;
+    if (!dm.GetTableStatus(mount_point, &table) || table.empty() || table[0].data.empty()) {
+        if (!entry.fs_mgr_flags.verify_at_boot) {
+            return false;
+        }
+        status = "V";
+    } else {
+        status = table[0].data.c_str();
+    }
+
+    if (*status == 'C' || *status == 'V') {
+        return true;
+    }
+
+    return false;
 }
 
 std::string fs_mgr_get_super_partition_name(int slot) {
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index df1e326..87729cd 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -272,15 +272,6 @@
     return false;
 }
 
-std::vector<std::string> fs_mgr_overlayfs_verity_enabled_list() {
-    std::vector<std::string> ret;
-    auto save_errno = errno;
-    fs_mgr_update_verity_state(
-            [&ret](const std::string& mount_point, int) { ret.emplace_back(mount_point); });
-    if ((errno == ENOENT) || (errno == ENXIO)) errno = save_errno;
-    return ret;
-}
-
 bool fs_mgr_wants_overlayfs(FstabEntry* entry) {
     // Don't check entries that are managed by vold.
     if (entry->fs_mgr_flags.vold_managed || entry->fs_mgr_flags.recovery_only) return false;
@@ -537,7 +528,6 @@
 
 std::vector<std::string> fs_mgr_candidate_list(Fstab* fstab, const char* mount_point = nullptr) {
     std::vector<std::string> mounts;
-    auto verity = fs_mgr_overlayfs_verity_enabled_list();
     for (auto& entry : *fstab) {
         if (!fs_mgr_overlayfs_already_mounted(entry.mount_point) &&
             !fs_mgr_wants_overlayfs(&entry)) {
@@ -545,10 +535,12 @@
         }
         std::string new_mount_point(fs_mgr_mount_point(entry.mount_point.c_str()));
         if (mount_point && (new_mount_point != mount_point)) continue;
-        if (std::find(verity.begin(), verity.end(), android::base::Basename(new_mount_point)) !=
-            verity.end()) {
-            continue;
-        }
+
+        auto saved_errno = errno;
+        auto verity_enabled = fs_mgr_is_verity_enabled(entry);
+        if (errno == ENOENT || errno == ENXIO) errno = saved_errno;
+        if (verity_enabled) continue;
+
         auto duplicate_or_more_specific = false;
         for (auto it = mounts.begin(); it != mounts.end();) {
             if ((*it == new_mount_point) ||
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 8af80a7..a3bb852 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef __CORE_FS_MGR_H
-#define __CORE_FS_MGR_H
+#pragma once
 
 #include <stdio.h>
 #include <stdint.h>
@@ -73,8 +72,8 @@
                         const std::string& mount_point = "");
 int fs_mgr_do_tmpfs_mount(const char *n_name);
 bool fs_mgr_load_verity_state(int* mode);
-bool fs_mgr_update_verity_state(
-        std::function<void(const std::string& mount_point, int mode)> callback);
+// Returns true if verity is enabled on this particular FstabEntry.
+bool fs_mgr_is_verity_enabled(const android::fs_mgr::FstabEntry& entry);
 bool fs_mgr_swapon_all(const android::fs_mgr::Fstab& fstab);
 bool fs_mgr_update_logical_partition(android::fs_mgr::FstabEntry* entry);
 
@@ -90,5 +89,3 @@
 // specified, the super partition for the corresponding metadata slot will be
 // returned. Otherwise, it will use the current slot.
 std::string fs_mgr_get_super_partition_name(int slot = -1);
-
-#endif /* __CORE_FS_MGR_H */
diff --git a/init/builtins.cpp b/init/builtins.cpp
index c8ceb0c..538ed00 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -75,6 +75,7 @@
 
 using namespace std::literals::string_literals;
 
+using android::base::Basename;
 using android::base::unique_fd;
 using android::fs_mgr::Fstab;
 using android::fs_mgr::ReadFstabFromFile;
@@ -749,11 +750,27 @@
 }
 
 static Result<Success> do_verity_update_state(const BuiltinArguments& args) {
-    if (!fs_mgr_update_verity_state([](const std::string& mount_point, int mode) {
-            property_set("partition." + mount_point + ".verified", std::to_string(mode));
-        })) {
-        return Error() << "fs_mgr_update_verity_state() failed";
+    int mode;
+    if (!fs_mgr_load_verity_state(&mode)) {
+        return Error() << "fs_mgr_load_verity_state() failed";
     }
+
+    Fstab fstab;
+    if (!ReadDefaultFstab(&fstab)) {
+        return Error() << "Failed to read default fstab";
+    }
+
+    for (const auto& entry : fstab) {
+        if (!fs_mgr_is_verity_enabled(entry)) {
+            continue;
+        }
+
+        // To be consistent in vboot 1.0 and vboot 2.0 (AVB), use "system" for the partition even
+        // for system as root, so it has property [partition.system.verified].
+        std::string partition = entry.mount_point == "/" ? "system" : Basename(entry.mount_point);
+        property_set("partition." + partition + ".verified", std::to_string(mode));
+    }
+
     return Success();
 }
 
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 91b7ddd..46e5e12 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -65,6 +65,7 @@
 
 using namespace std::literals;
 
+using android::base::GetProperty;
 using android::base::ReadFileToString;
 using android::base::Split;
 using android::base::StartsWith;
@@ -728,6 +729,110 @@
     property_set("ro.persistent_properties.ready", "true");
 }
 
+// If the ro.product.[brand|device|manufacturer|model|name] properties have not been explicitly
+// set, derive them from ro.product.${partition}.* properties
+static void property_initialize_ro_product_props() {
+    const char* RO_PRODUCT_PROPS_PREFIX = "ro.product.";
+    const char* RO_PRODUCT_PROPS[] = {
+            "brand", "device", "manufacturer", "model", "name",
+    };
+    const char* RO_PRODUCT_PROPS_ALLOWED_SOURCES[] = {
+            "odm", "product", "product_services", "system", "vendor",
+    };
+    const char* RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER =
+            "product,product_services,odm,vendor,system";
+    const std::string EMPTY = "";
+
+    std::string ro_product_props_source_order =
+            GetProperty("ro.product.property_source_order", EMPTY);
+
+    if (!ro_product_props_source_order.empty()) {
+        // Verify that all specified sources are valid
+        for (const auto& source : Split(ro_product_props_source_order, ",")) {
+            // Verify that the specified source is valid
+            bool is_allowed_source = false;
+            for (const auto& allowed_source : RO_PRODUCT_PROPS_ALLOWED_SOURCES) {
+                if (source == allowed_source) {
+                    is_allowed_source = true;
+                    break;
+                }
+            }
+            if (!is_allowed_source) {
+                LOG(ERROR) << "Found unexpected source in ro.product.property_source_order; "
+                              "using the default property source order";
+                ro_product_props_source_order = RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER;
+                break;
+            }
+        }
+    } else {
+        ro_product_props_source_order = RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER;
+    }
+
+    for (const auto& ro_product_prop : RO_PRODUCT_PROPS) {
+        std::string base_prop(RO_PRODUCT_PROPS_PREFIX);
+        base_prop += ro_product_prop;
+
+        std::string base_prop_val = GetProperty(base_prop, EMPTY);
+        if (!base_prop_val.empty()) {
+            continue;
+        }
+
+        for (const auto& source : Split(ro_product_props_source_order, ",")) {
+            std::string target_prop(RO_PRODUCT_PROPS_PREFIX);
+            target_prop += source;
+            target_prop += '.';
+            target_prop += ro_product_prop;
+
+            std::string target_prop_val = GetProperty(target_prop, EMPTY);
+            if (!target_prop_val.empty()) {
+                LOG(INFO) << "Setting product property " << base_prop << " to '" << target_prop_val
+                          << "' (from " << target_prop << ")";
+                std::string error;
+                uint32_t res = PropertySet(base_prop, target_prop_val, &error);
+                if (res != PROP_SUCCESS) {
+                    LOG(ERROR) << "Error setting product property " << base_prop << ": err=" << res
+                               << " (" << error << ")";
+                }
+                break;
+            }
+        }
+    }
+}
+
+// If the ro.build.fingerprint property has not been set, derive it from constituent pieces
+static void property_derive_build_fingerprint() {
+    std::string build_fingerprint = GetProperty("ro.build.fingerprint", "");
+    if (!build_fingerprint.empty()) {
+        return;
+    }
+
+    const std::string UNKNOWN = "unknown";
+    build_fingerprint = GetProperty("ro.product.brand", UNKNOWN);
+    build_fingerprint += '/';
+    build_fingerprint += GetProperty("ro.product.name", UNKNOWN);
+    build_fingerprint += '/';
+    build_fingerprint += GetProperty("ro.product.device", UNKNOWN);
+    build_fingerprint += ':';
+    build_fingerprint += GetProperty("ro.build.version.release", UNKNOWN);
+    build_fingerprint += '/';
+    build_fingerprint += GetProperty("ro.build.id", UNKNOWN);
+    build_fingerprint += '/';
+    build_fingerprint += GetProperty("ro.build.version.incremental", UNKNOWN);
+    build_fingerprint += ':';
+    build_fingerprint += GetProperty("ro.build.type", UNKNOWN);
+    build_fingerprint += '/';
+    build_fingerprint += GetProperty("ro.build.tags", UNKNOWN);
+
+    LOG(INFO) << "Setting property 'ro.build.fingerprint' to '" << build_fingerprint << "'";
+
+    std::string error;
+    uint32_t res = PropertySet("ro.build.fingerprint", build_fingerprint, &error);
+    if (res != PROP_SUCCESS) {
+        LOG(ERROR) << "Error setting property 'ro.build.fingerprint': err=" << res << " (" << error
+                   << ")";
+    }
+}
+
 void property_load_boot_defaults() {
     // TODO(b/117892318): merge prop.default and build.prop files into one
     // TODO(b/122864654): read the prop files from all partitions and then
@@ -749,6 +854,9 @@
     load_properties_from_file("/vendor/build.prop", NULL);
     load_properties_from_file("/factory/factory.prop", "ro.*");
 
+    property_initialize_ro_product_props();
+    property_derive_build_fingerprint();
+
     update_sys_usb_config();
 }
 
diff --git a/libnativebridge/Android.bp b/libnativebridge/Android.bp
index c54570e..10d42e4 100644
--- a/libnativebridge/Android.bp
+++ b/libnativebridge/Android.bp
@@ -1,5 +1,18 @@
+cc_defaults {
+    name: "libnativebridge-defaults",
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+    cppflags: [
+        "-fvisibility=protected",
+    ],
+    header_libs: ["libnativebridge-headers"],
+    export_header_lib_headers: ["libnativebridge-headers"],
+}
+
 cc_library_headers {
-    name: "libnativebridge-dummy-headers",
+    name: "libnativebridge-headers",
 
     host_supported: true,
     export_include_dirs: ["include"],
@@ -7,6 +20,7 @@
 
 cc_library {
     name: "libnativebridge",
+    defaults: ["libnativebridge-defaults"],
 
     host_supported: true,
     srcs: ["native_bridge.cc"],
@@ -16,6 +30,8 @@
     shared_libs: [
         "liblog",
     ],
+    // TODO(jiyong): remove this line after aosp/885921 lands
+    export_include_dirs: ["include"],
 
     target: {
         android: {
@@ -30,16 +46,16 @@
         symbol_file: "libnativebridge.map.txt",
         versions: ["1"],
     },
+}
 
-    export_include_dirs: ["include"],
+// TODO(b/124250621): eliminate the need for this library
+cc_library {
+    name: "libnativebridge_lazy",
+    defaults: ["libnativebridge-defaults"],
 
-    cflags: [
-        "-Werror",
-        "-Wall",
-    ],
-    cppflags: [
-        "-fvisibility=protected",
-    ],
+    host_supported: false,
+    srcs: ["native_bridge_lazy.cc"],
+    required: ["libnativebridge"],
 }
 
 subdirs = ["tests"]
diff --git a/libnativebridge/native_bridge_lazy.cc b/libnativebridge/native_bridge_lazy.cc
new file mode 100644
index 0000000..94c8084
--- /dev/null
+++ b/libnativebridge/native_bridge_lazy.cc
@@ -0,0 +1,167 @@
+/*
+ * 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.
+ */
+
+#include "nativebridge/native_bridge.h"
+#define LOG_TAG "nativebridge"
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <string.h>
+
+#include <log/log.h>
+
+namespace android {
+
+namespace {
+
+void* GetLibHandle() {
+  static void* handle = dlopen("libnativebridge.so", RTLD_NOW);
+  LOG_FATAL_IF(handle == nullptr, "Failed to load libnativebridge.so: %s", dlerror());
+  return handle;
+}
+
+template <typename FuncPtr>
+FuncPtr GetFuncPtr(const char* function_name) {
+  auto f = reinterpret_cast<FuncPtr>(dlsym(GetLibHandle(), function_name));
+  LOG_FATAL_IF(f == nullptr, "Failed to get address of %s: %s", function_name, dlerror());
+  return f;
+}
+
+#define GET_FUNC_PTR(name) GetFuncPtr<decltype(&name)>(#name)
+
+}  // namespace
+
+bool LoadNativeBridge(const char* native_bridge_library_filename,
+                      const struct NativeBridgeRuntimeCallbacks* runtime_callbacks) {
+  static auto f = GET_FUNC_PTR(LoadNativeBridge);
+  return f(native_bridge_library_filename, runtime_callbacks);
+}
+
+bool NeedsNativeBridge(const char* instruction_set) {
+  static auto f = GET_FUNC_PTR(NeedsNativeBridge);
+  return f(instruction_set);
+}
+
+bool PreInitializeNativeBridge(const char* app_data_dir, const char* instruction_set) {
+  static auto f = GET_FUNC_PTR(PreInitializeNativeBridge);
+  return f(app_data_dir, instruction_set);
+}
+
+bool InitializeNativeBridge(JNIEnv* env, const char* instruction_set) {
+  static auto f = GET_FUNC_PTR(InitializeNativeBridge);
+  return f(env, instruction_set);
+}
+
+void UnloadNativeBridge() {
+  static auto f = GET_FUNC_PTR(UnloadNativeBridge);
+  return f();
+}
+
+bool NativeBridgeAvailable() {
+  static auto f = GET_FUNC_PTR(NativeBridgeAvailable);
+  return f();
+}
+
+bool NativeBridgeInitialized() {
+  static auto f = GET_FUNC_PTR(NativeBridgeInitialized);
+  return f();
+}
+
+void* NativeBridgeLoadLibrary(const char* libpath, int flag) {
+  static auto f = GET_FUNC_PTR(NativeBridgeLoadLibrary);
+  return f(libpath, flag);
+}
+
+void* NativeBridgeGetTrampoline(void* handle, const char* name, const char* shorty, uint32_t len) {
+  static auto f = GET_FUNC_PTR(NativeBridgeGetTrampoline);
+  return f(handle, name, shorty, len);
+}
+
+bool NativeBridgeIsSupported(const char* libpath) {
+  static auto f = GET_FUNC_PTR(NativeBridgeIsSupported);
+  return f(libpath);
+}
+
+uint32_t NativeBridgeGetVersion() {
+  static auto f = GET_FUNC_PTR(NativeBridgeGetVersion);
+  return f();
+}
+
+NativeBridgeSignalHandlerFn NativeBridgeGetSignalHandler(int signal) {
+  static auto f = GET_FUNC_PTR(NativeBridgeGetSignalHandler);
+  return f(signal);
+}
+
+bool NativeBridgeError() {
+  static auto f = GET_FUNC_PTR(NativeBridgeError);
+  return f();
+}
+
+bool NativeBridgeNameAcceptable(const char* native_bridge_library_filename) {
+  static auto f = GET_FUNC_PTR(NativeBridgeNameAcceptable);
+  return f(native_bridge_library_filename);
+}
+
+int NativeBridgeUnloadLibrary(void* handle) {
+  static auto f = GET_FUNC_PTR(NativeBridgeUnloadLibrary);
+  return f(handle);
+}
+
+const char* NativeBridgeGetError() {
+  static auto f = GET_FUNC_PTR(NativeBridgeGetError);
+  return f();
+}
+
+bool NativeBridgeIsPathSupported(const char* path) {
+  static auto f = GET_FUNC_PTR(NativeBridgeIsPathSupported);
+  return f(path);
+}
+
+bool NativeBridgeInitAnonymousNamespace(const char* public_ns_sonames,
+                                        const char* anon_ns_library_path) {
+  static auto f = GET_FUNC_PTR(NativeBridgeInitAnonymousNamespace);
+  return f(public_ns_sonames, anon_ns_library_path);
+}
+
+struct native_bridge_namespace_t* NativeBridgeCreateNamespace(
+    const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type,
+    const char* permitted_when_isolated_path, struct native_bridge_namespace_t* parent_ns) {
+  static auto f = GET_FUNC_PTR(NativeBridgeCreateNamespace);
+  return f(name, ld_library_path, default_library_path, type, permitted_when_isolated_path,
+           parent_ns);
+}
+
+bool NativeBridgeLinkNamespaces(struct native_bridge_namespace_t* from,
+                                struct native_bridge_namespace_t* to,
+                                const char* shared_libs_sonames) {
+  static auto f = GET_FUNC_PTR(NativeBridgeLinkNamespaces);
+  return f(from, to, shared_libs_sonames);
+}
+
+void* NativeBridgeLoadLibraryExt(const char* libpath, int flag,
+                                 struct native_bridge_namespace_t* ns) {
+  static auto f = GET_FUNC_PTR(NativeBridgeLoadLibraryExt);
+  return f(libpath, flag, ns);
+}
+
+struct native_bridge_namespace_t* NativeBridgeGetVendorNamespace() {
+  static auto f = GET_FUNC_PTR(NativeBridgeGetVendorNamespace);
+  return f();
+}
+
+#undef GET_FUNC_PTR
+
+}  // namespace android
diff --git a/libnativebridge/tests/Android.bp b/libnativebridge/tests/Android.bp
index 744a4a8..2bb8467 100644
--- a/libnativebridge/tests/Android.bp
+++ b/libnativebridge/tests/Android.bp
@@ -23,7 +23,7 @@
         "-Wextra",
         "-Werror",
     ],
-    header_libs: ["libnativebridge-dummy-headers"],
+    header_libs: ["libnativebridge-headers"],
     cppflags: ["-fvisibility=protected"],
 }
 
@@ -46,9 +46,8 @@
 }
 
 // Build the unit tests.
-cc_test {
-    name: "libnativebridge-tests",
-    host_supported: true,
+cc_defaults {
+    name: "libnativebridge-tests-defaults",
     test_per_src: true,
 
     cflags: [
@@ -81,12 +80,24 @@
 
     shared_libs: [
         "liblog",
-        "libnativebridge",
         "libnativebridge-dummy",
     ],
     header_libs: ["libbase_headers"],
 }
 
+cc_test {
+    name: "libnativebridge-tests",
+    defaults: ["libnativebridge-tests-defaults"],
+    host_supported: true,
+    shared_libs: ["libnativebridge"],
+}
+
+cc_test {
+    name: "libnativebridge-lazy-tests",
+    defaults: ["libnativebridge-tests-defaults"],
+    shared_libs: ["libnativebridge_lazy"],
+}
+
 // Build the test for the C API.
 cc_test {
     name: "libnativebridge-api-tests",
@@ -95,5 +106,5 @@
     srcs: [
         "NativeBridgeApi.c",
     ],
-    header_libs: ["libnativebridge-dummy-headers"],
+    header_libs: ["libnativebridge-headers"],
 }
diff --git a/libnativeloader/Android.bp b/libnativeloader/Android.bp
index 1ec21e9..b806ae4 100644
--- a/libnativeloader/Android.bp
+++ b/libnativeloader/Android.bp
@@ -1,7 +1,21 @@
 // Shared library for target
 // ========================================================
+cc_defaults {
+    name: "libnativeloader-defaults",
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+    cppflags: [
+        "-fvisibility=hidden",
+    ],
+    header_libs: ["libnativeloader-headers"],
+    export_header_lib_headers: ["libnativeloader-headers"],
+}
+
 cc_library {
     name: "libnativeloader",
+    defaults: ["libnativeloader-defaults"],
     host_supported: true,
     srcs: ["native_loader.cpp"],
     shared_libs: [
@@ -11,14 +25,6 @@
         "libnativebridge",
         "libbase",
     ],
-    cflags: [
-        "-Werror",
-        "-Wall",
-    ],
-    cppflags: [
-        "-fvisibility=hidden",
-    ],
-    export_include_dirs: ["include"],
     required: [
         "llndk.libraries.txt",
         "vndksp.libraries.txt",
@@ -29,9 +35,25 @@
     },
 }
 
+// TODO(b/124250621) eliminate the need for this library
+cc_library {
+    name: "libnativeloader_lazy",
+    defaults: ["libnativeloader-defaults"],
+    host_supported: false,
+    srcs: ["native_loader_lazy.cpp"],
+    required: ["libnativeloader"],
+}
+
+cc_library_headers {
+    name: "libnativeloader-headers",
+    host_supported: true,
+    export_include_dirs: ["include"],
+}
+
+// TODO(jiyong) Remove this when its use in the internal master is
+// switched to libnativeloader-headers
 cc_library_headers {
     name: "libnativeloader-dummy-headers",
-
     host_supported: true,
     export_include_dirs: ["include"],
 }
diff --git a/libnativeloader/native_loader_lazy.cpp b/libnativeloader/native_loader_lazy.cpp
new file mode 100644
index 0000000..11ecc43
--- /dev/null
+++ b/libnativeloader/native_loader_lazy.cpp
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ */
+
+#include "nativeloader/native_loader.h"
+#define LOG_TAG "nativeloader"
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <string.h>
+
+#include <log/log.h>
+
+namespace android {
+
+namespace {
+
+void* GetLibHandle() {
+  static void* handle = dlopen("libnativeloader.so", RTLD_NOW);
+  LOG_FATAL_IF(handle == nullptr, "Failed to load libnativeloader.so: %s", dlerror());
+  return handle;
+}
+
+template <typename FuncPtr>
+FuncPtr GetFuncPtr(const char* function_name) {
+  auto f = reinterpret_cast<FuncPtr>(dlsym(GetLibHandle(), function_name));
+  LOG_FATAL_IF(f == nullptr, "Failed to get address of %s: %s", function_name, dlerror());
+  return f;
+}
+
+#define GET_FUNC_PTR(name) GetFuncPtr<decltype(&name)>(#name)
+
+}  // namespace
+
+void InitializeNativeLoader() {
+  static auto f = GET_FUNC_PTR(InitializeNativeLoader);
+  return f();
+}
+
+jstring CreateClassLoaderNamespace(JNIEnv* env, int32_t target_sdk_version, jobject class_loader,
+                                   bool is_shared, bool is_for_vendor, jstring library_path,
+                                   jstring permitted_path) {
+  static auto f = GET_FUNC_PTR(CreateClassLoaderNamespace);
+  return f(env, target_sdk_version, class_loader, is_shared, is_for_vendor, library_path,
+           permitted_path);
+}
+
+void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* path,
+                        jobject class_loader, const char* caller_location, jstring library_path,
+                        bool* needs_native_bridge, char** error_msg) {
+  static auto f = GET_FUNC_PTR(OpenNativeLibrary);
+  return f(env, target_sdk_version, path, class_loader, caller_location, library_path,
+           needs_native_bridge, error_msg);
+}
+
+bool CloseNativeLibrary(void* handle, const bool needs_native_bridge, char** error_msg) {
+  static auto f = GET_FUNC_PTR(CloseNativeLibrary);
+  return f(handle, needs_native_bridge, error_msg);
+}
+
+void NativeLoaderFreeErrorMessage(char* msg) {
+  static auto f = GET_FUNC_PTR(NativeLoaderFreeErrorMessage);
+  return f(msg);
+}
+
+struct android_namespace_t* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
+  static auto f = GET_FUNC_PTR(FindNamespaceByClassLoader);
+  return f(env, class_loader);
+}
+
+struct NativeLoaderNamespace* FindNativeLoaderNamespaceByClassLoader(JNIEnv* env,
+                                                                     jobject class_loader) {
+  static auto f = GET_FUNC_PTR(FindNativeLoaderNamespaceByClassLoader);
+  return f(env, class_loader);
+}
+
+void* OpenNativeLibraryInNamespace(struct NativeLoaderNamespace* ns, const char* path,
+                                   bool* needs_native_bridge, char** error_msg) {
+  static auto f = GET_FUNC_PTR(OpenNativeLibraryInNamespace);
+  return f(ns, path, needs_native_bridge, error_msg);
+}
+
+void ResetNativeLoader() {
+  static auto f = GET_FUNC_PTR(ResetNativeLoader);
+  return f();
+}
+
+#undef GET_FUNC_PTR
+
+}  // namespace android
diff --git a/libnativeloader/test/Android.bp b/libnativeloader/test/Android.bp
index 1464e39..4d5c53d 100644
--- a/libnativeloader/test/Android.bp
+++ b/libnativeloader/test/Android.bp
@@ -78,5 +78,5 @@
     srcs: [
         "api_test.c",
     ],
-    header_libs: ["libnativeloader-dummy-headers"],
+    header_libs: ["libnativeloader-headers"],
 }
diff --git a/libnetutils/OWNERS b/libnetutils/OWNERS
index e3ec950..8321de6 100644
--- a/libnetutils/OWNERS
+++ b/libnetutils/OWNERS
@@ -1,3 +1,2 @@
-# TODO: should this be in system/netd?
-ek@google.com
-lorenzo@google.com
+include platform/system/netd:/OWNERS
+
diff --git a/libvndksupport/Android.bp b/libvndksupport/Android.bp
index e73b366..bfa2508 100644
--- a/libvndksupport/Android.bp
+++ b/libvndksupport/Android.bp
@@ -10,6 +10,11 @@
     local_include_dirs: ["include/vndksupport"],
     export_include_dirs: ["include"],
     shared_libs: ["liblog"],
+    version_script: "libvndksupport.map.txt",
+    stubs: {
+        symbol_file: "libvndksupport.map.txt",
+        versions: ["29"],
+    },
 }
 
 llndk_library {
diff --git a/libvndksupport/libvndksupport.map.txt b/libvndksupport/libvndksupport.map.txt
index 16e38da..d3db10f 100644
--- a/libvndksupport/libvndksupport.map.txt
+++ b/libvndksupport/libvndksupport.map.txt
@@ -1,7 +1,7 @@
 LIBVNDKSUPPORT {
   global:
-    android_load_sphal_library; # vndk
-    android_unload_sphal_library; # vndk
+    android_load_sphal_library; # vndk apex
+    android_unload_sphal_library; # vndk apex
   local:
     *;
 };
diff --git a/rootdir/etc/ld.config.legacy.txt b/rootdir/etc/ld.config.legacy.txt
index 48ca998..e897d81 100644
--- a/rootdir/etc/ld.config.legacy.txt
+++ b/rootdir/etc/ld.config.legacy.txt
@@ -126,6 +126,7 @@
 namespace.resolv.link.default.shared_libs += libm.so
 namespace.resolv.link.default.shared_libs += libdl.so
 namespace.resolv.link.default.shared_libs += libbinder_ndk.so
+namespace.resolv.link.default.shared_libs += libvndksupport.so
 
 ###############################################################################
 # Namespace config for binaries under /postinstall.
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index 7aa097d..5e2d79c 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -200,6 +200,7 @@
 namespace.resolv.link.default.shared_libs += libm.so
 namespace.resolv.link.default.shared_libs += libdl.so
 namespace.resolv.link.default.shared_libs += libbinder_ndk.so
+namespace.resolv.link.default.shared_libs += libvndksupport.so
 
 ###############################################################################
 # "sphal" namespace
@@ -408,6 +409,7 @@
 
 # Keep in sync with ld.config.txt in the com.android.runtime APEX.
 namespace.runtime.search.paths = /apex/com.android.runtime/${LIB}
+namespace.runtime.asan.search.paths = /apex/com.android.runtime/${LIB}
 namespace.runtime.links = system
 # TODO(b/119867084): Restrict to Bionic dlopen dependencies and PALette library
 # when it exists.
diff --git a/rootdir/etc/ld.config.vndk_lite.txt b/rootdir/etc/ld.config.vndk_lite.txt
index 1904445..3c97a49 100644
--- a/rootdir/etc/ld.config.vndk_lite.txt
+++ b/rootdir/etc/ld.config.vndk_lite.txt
@@ -145,6 +145,7 @@
 namespace.resolv.link.default.shared_libs += libm.so
 namespace.resolv.link.default.shared_libs += libdl.so
 namespace.resolv.link.default.shared_libs += libbinder_ndk.so
+namespace.resolv.link.default.shared_libs += libvndksupport.so
 
 ###############################################################################
 # "sphal" namespace
@@ -305,11 +306,11 @@
 namespace.default.search.paths += /vendor/${LIB}/vndk-sp
 
 # Access to system libraries is allowed
-namespace.default.search.paths += /system/${LIB}/vndk%VNDK_VER%
 namespace.default.search.paths += /system/${LIB}/vndk-sp%VNDK_VER%
 namespace.default.search.paths += /system/${LIB}
 namespace.default.search.paths += /%PRODUCT%/${LIB}
 namespace.default.search.paths += /%PRODUCT_SERVICES%/${LIB}
+namespace.default.search.paths += /system/${LIB}/vndk%VNDK_VER%
 
 namespace.default.asan.search.paths  = /data/asan/odm/${LIB}
 namespace.default.asan.search.paths +=           /odm/${LIB}
@@ -323,8 +324,6 @@
 namespace.default.asan.search.paths +=           /vendor/${LIB}/vndk
 namespace.default.asan.search.paths += /data/asan/vendor/${LIB}/vndk-sp
 namespace.default.asan.search.paths +=           /vendor/${LIB}/vndk-sp
-namespace.default.asan.search.paths += /data/asan/system/${LIB}/vndk%VNDK_VER%
-namespace.default.asan.search.paths +=           /system/${LIB}/vndk%VNDK_VER%
 namespace.default.asan.search.paths += /data/asan/system/${LIB}/vndk-sp%VNDK_VER%
 namespace.default.asan.search.paths +=           /system/${LIB}/vndk-sp%VNDK_VER%
 namespace.default.asan.search.paths += /data/asan/system/${LIB}
@@ -333,6 +332,8 @@
 namespace.default.asan.search.paths +=           /%PRODUCT%/${LIB}
 namespace.default.asan.search.paths += /data/asan/product_services/${LIB}
 namespace.default.asan.search.paths +=           /%PRODUCT_SERVICES%/${LIB}
+namespace.default.asan.search.paths += /data/asan/system/${LIB}/vndk%VNDK_VER%
+namespace.default.asan.search.paths +=           /system/${LIB}/vndk%VNDK_VER%
 
 namespace.default.links = runtime
 namespace.default.link.runtime.shared_libs  = libdexfile_external.so
@@ -349,6 +350,7 @@
 
 # Keep in sync with ld.config.txt in the com.android.runtime APEX.
 namespace.runtime.search.paths = /apex/com.android.runtime/${LIB}
+namespace.runtime.asan.search.paths = /apex/com.android.runtime/${LIB}
 namespace.runtime.links = default
 # TODO(b/119867084): Restrict to Bionic dlopen dependencies and PALette library
 # when it exists.