Merge "Migrate net.tcp.default_init_rwnd to net.tcp_def_init_rwnd"
diff --git a/debuggerd/crasher/Android.bp b/debuggerd/crasher/Android.bp
index 7975a3a..23b106e 100644
--- a/debuggerd/crasher/Android.bp
+++ b/debuggerd/crasher/Android.bp
@@ -13,7 +13,6 @@
         "-Werror",
         "-O0",
         "-fstack-protector-all",
-        "-Wno-free-nonheap-object",
         "-Wno-date-time",
     ],
     srcs: ["crasher.cpp"],
diff --git a/debuggerd/crasher/crasher.cpp b/debuggerd/crasher/crasher.cpp
index a2b13a3..db30b8f 100644
--- a/debuggerd/crasher/crasher.cpp
+++ b/debuggerd/crasher/crasher.cpp
@@ -134,10 +134,14 @@
     return a*2;
 }
 
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wfree-nonheap-object"
+
 noinline void abuse_heap() {
     char buf[16];
     free(buf); // GCC is smart enough to warn about this, but we're doing it deliberately.
 }
+#pragma clang diagnostic pop
 
 noinline void leak() {
     while (true) {
diff --git a/debuggerd/libdebuggerd/test/sys/system_properties.h b/debuggerd/libdebuggerd/test/sys/system_properties.h
deleted file mode 100644
index 1f4f58a..0000000
--- a/debuggerd/libdebuggerd/test/sys/system_properties.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef _DEBUGGERD_TEST_SYS_SYSTEM_PROPERTIES_H
-#define _DEBUGGERD_TEST_SYS_SYSTEM_PROPERTIES_H
-
-// This is just enough to get the property code to compile on
-// the host.
-
-#define PROP_VALUE_MAX  92
-
-#endif // _DEBUGGERD_TEST_SYS_SYSTEM_PROPERTIES_H
diff --git a/libstats/OWNERS b/libstats/OWNERS
index 7855774..d391679 100644
--- a/libstats/OWNERS
+++ b/libstats/OWNERS
@@ -1,6 +1,7 @@
-joeo@google.com
+jeffreyhuang@google.com
+jtnguyen@google.com
 muhammadq@google.com
-ruchirr@google.com
+sharaienko@google.com
 singhtejinder@google.com
 tsaichristine@google.com
 yaochen@google.com
diff --git a/libstats/pull_lazy/Android.bp b/libstats/pull_lazy/Android.bp
new file mode 100644
index 0000000..b1d098b
--- /dev/null
+++ b/libstats/pull_lazy/Android.bp
@@ -0,0 +1,44 @@
+// Lazy loading version of libstatspull that can be used by code
+// that is running before the statsd APEX is mounted and
+// libstatspull.so is available.
+cc_library_static {
+    name: "libstatspull_lazy",
+    header_libs: [
+        "libstatspull_headers",
+        "libstatssocket_headers",
+    ],
+    export_header_lib_headers: [
+        "libstatspull_headers",
+    ],
+    apex_available: ["//apex_available:platform"],
+    srcs: ["libstatspull_lazy.cpp"],
+}
+
+cc_test {
+    name: "libstatspull_lazy_test",
+    srcs: [
+        "tests/libstatspull_lazy_test.cpp",
+    ],
+    static_libs: [
+        "libstatspull_lazy",
+        "libstatssocket_lazy",
+    ],
+    shared_libs: ["liblog"],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    test_suites: ["device-tests", "mts-statsd"],
+    test_config: "libstatspull_lazy_test.xml",
+    // TODO(b/153588990): Remove when the build system properly separates.
+    // 32bit and 64bit architectures.
+    compile_multilib: "both",
+    multilib: {
+        lib64: {
+            suffix: "64",
+        },
+        lib32: {
+            suffix: "32",
+        },
+    },
+}
\ No newline at end of file
diff --git a/libstats/pull_lazy/TEST_MAPPING b/libstats/pull_lazy/TEST_MAPPING
new file mode 100644
index 0000000..89b8c2a
--- /dev/null
+++ b/libstats/pull_lazy/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit" : [
+    {
+      "name" : "libstatspull_lazy_test"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/libstats/pull_lazy/libstatspull_lazy.cpp b/libstats/pull_lazy/libstatspull_lazy.cpp
new file mode 100644
index 0000000..b11fcee
--- /dev/null
+++ b/libstats/pull_lazy/libstatspull_lazy.cpp
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2021 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 "libstatspull_lazy.h"
+
+#include <mutex>
+
+#include <dlfcn.h>
+#include <stdatomic.h>
+
+#include "log/log.h"
+
+#include "stats_pull_atom_callback.h"
+
+// This file provides a lazy interface to libstatspull.so to address early boot dependencies.
+// Specifically bootanimation, surfaceflinger, and lmkd run before the statsd APEX is loaded and
+// libstatspull.so is in the statsd APEX.
+
+// Method pointers to libstatspull methods are held in an array which simplifies checking
+// all pointers are initialized.
+enum MethodIndex {
+    // PullAtomMetadata APIs in stats_pull_atom_callback.h.
+    k_AStatsManager_PullAtomMetadata_obtain,
+    k_AStatsManager_PullAtomMetadata_release,
+    k_AStatsManager_PullAtomMetadata_setCoolDownMillis,
+    k_AStatsManager_PullAtomMetadata_getCoolDownMillis,
+    k_AStatsManager_PullAtomMetadata_setTimeoutMillis,
+    k_AStatsManager_PullAtomMetadata_getTimeoutMillis,
+    k_AStatsManager_PullAtomMetadata_setAdditiveFields,
+    k_AStatsManager_PullAtomMetadata_getNumAdditiveFields,
+    k_AStatsManager_PullAtomMetadata_getAdditiveFields,
+
+    // AStatsEventList APIs in stats_pull_atom_callback.h
+    k_AStatsEventList_addStatsEvent,
+
+    // PullAtomCallback APIs in stats_pull_atom_callback.h
+    k_AStatsManager_setPullAtomCallback,
+    k_AStatsManager_clearPullAtomCallback,
+
+    // Marker for count of methods
+    k_MethodCount
+};
+
+// Table of methods pointers in libstatspull APIs.
+static void* g_Methods[k_MethodCount];
+
+//
+// Libstatspull lazy loading.
+//
+
+static atomic_bool gPreventLibstatspullLoading = false;  // Allows tests to block loading.
+
+void PreventLibstatspullLazyLoadingForTests() {
+    gPreventLibstatspullLoading.store(true);
+}
+
+static void* LoadLibstatspull(int dlopen_flags) {
+    if (gPreventLibstatspullLoading.load()) {
+        return nullptr;
+    }
+    return dlopen("libstatspull.so", dlopen_flags);
+}
+
+//
+// Initialization and symbol binding.
+
+static void BindSymbol(void* handle, const char* name, enum MethodIndex index) {
+    void* symbol = dlsym(handle, name);
+    LOG_ALWAYS_FATAL_IF(symbol == nullptr, "Failed to find symbol '%s' in libstatspull.so: %s",
+                        name, dlerror());
+    g_Methods[index] = symbol;
+}
+
+static void InitializeOnce() {
+    void* handle = LoadLibstatspull(RTLD_NOW);
+    LOG_ALWAYS_FATAL_IF(handle == nullptr, "Failed to load libstatspull.so: %s", dlerror());
+
+#undef BIND_SYMBOL
+#define BIND_SYMBOL(name) BindSymbol(handle, #name, k_##name);
+    // PullAtomMetadata APIs in stats_pull_atom_callback.h.
+    BIND_SYMBOL(AStatsManager_PullAtomMetadata_obtain);
+    BIND_SYMBOL(AStatsManager_PullAtomMetadata_release);
+    BIND_SYMBOL(AStatsManager_PullAtomMetadata_setCoolDownMillis);
+    BIND_SYMBOL(AStatsManager_PullAtomMetadata_getCoolDownMillis);
+    BIND_SYMBOL(AStatsManager_PullAtomMetadata_setTimeoutMillis);
+    BIND_SYMBOL(AStatsManager_PullAtomMetadata_getTimeoutMillis);
+    BIND_SYMBOL(AStatsManager_PullAtomMetadata_setAdditiveFields);
+    BIND_SYMBOL(AStatsManager_PullAtomMetadata_getNumAdditiveFields);
+    BIND_SYMBOL(AStatsManager_PullAtomMetadata_getAdditiveFields);
+
+    // AStatsEventList APIs in stats_pull_atom_callback.h
+    BIND_SYMBOL(AStatsEventList_addStatsEvent);
+
+    // PullAtomCallback APIs in stats_pull_atom_callback.h
+    BIND_SYMBOL(AStatsManager_setPullAtomCallback);
+    BIND_SYMBOL(AStatsManager_clearPullAtomCallback);
+
+#undef BIND_SYMBOL
+
+    // Check every symbol is bound.
+    for (int i = 0; i < k_MethodCount; ++i) {
+        LOG_ALWAYS_FATAL_IF(g_Methods[i] == nullptr,
+                            "Uninitialized method in libstatspull_lazy at index: %d", i);
+    }
+}
+
+static void EnsureInitialized() {
+    static std::once_flag initialize_flag;
+    std::call_once(initialize_flag, InitializeOnce);
+}
+
+#define INVOKE_METHOD(name, args...)                            \
+    do {                                                        \
+        EnsureInitialized();                                    \
+        void* method = g_Methods[k_##name];                     \
+        return reinterpret_cast<decltype(&name)>(method)(args); \
+    } while (0)
+
+//
+// Forwarding for methods in stats_pull_atom_callback.h.
+//
+
+AStatsManager_PullAtomMetadata* AStatsManager_PullAtomMetadata_obtain() {
+    INVOKE_METHOD(AStatsManager_PullAtomMetadata_obtain);
+}
+
+void AStatsManager_PullAtomMetadata_release(AStatsManager_PullAtomMetadata* metadata) {
+    INVOKE_METHOD(AStatsManager_PullAtomMetadata_release, metadata);
+}
+
+void AStatsManager_PullAtomMetadata_setCoolDownMillis(AStatsManager_PullAtomMetadata* metadata,
+                                                      int64_t cool_down_millis) {
+    INVOKE_METHOD(AStatsManager_PullAtomMetadata_setCoolDownMillis, metadata, cool_down_millis);
+}
+
+int64_t AStatsManager_PullAtomMetadata_getCoolDownMillis(AStatsManager_PullAtomMetadata* metadata) {
+    INVOKE_METHOD(AStatsManager_PullAtomMetadata_getCoolDownMillis, metadata);
+}
+
+void AStatsManager_PullAtomMetadata_setTimeoutMillis(AStatsManager_PullAtomMetadata* metadata,
+                                                     int64_t timeout_millis) {
+    INVOKE_METHOD(AStatsManager_PullAtomMetadata_setTimeoutMillis, metadata, timeout_millis);
+}
+
+int64_t AStatsManager_PullAtomMetadata_getTimeoutMillis(AStatsManager_PullAtomMetadata* metadata) {
+    INVOKE_METHOD(AStatsManager_PullAtomMetadata_getTimeoutMillis, metadata);
+}
+
+void AStatsManager_PullAtomMetadata_setAdditiveFields(AStatsManager_PullAtomMetadata* metadata,
+                                                      int32_t* additive_fields,
+                                                      int32_t num_fields) {
+    INVOKE_METHOD(AStatsManager_PullAtomMetadata_setAdditiveFields, metadata, additive_fields,
+                  num_fields);
+}
+
+int32_t AStatsManager_PullAtomMetadata_getNumAdditiveFields(
+        AStatsManager_PullAtomMetadata* metadata) {
+    INVOKE_METHOD(AStatsManager_PullAtomMetadata_getNumAdditiveFields, metadata);
+}
+
+void AStatsManager_PullAtomMetadata_getAdditiveFields(AStatsManager_PullAtomMetadata* metadata,
+                                                      int32_t* fields) {
+    INVOKE_METHOD(AStatsManager_PullAtomMetadata_getAdditiveFields, metadata, fields);
+}
+
+AStatsEvent* AStatsEventList_addStatsEvent(AStatsEventList* pull_data) {
+    INVOKE_METHOD(AStatsEventList_addStatsEvent, pull_data);
+}
+
+void AStatsManager_setPullAtomCallback(int32_t atom_tag, AStatsManager_PullAtomMetadata* metadata,
+                                       AStatsManager_PullAtomCallback callback, void* cookie) {
+    INVOKE_METHOD(AStatsManager_setPullAtomCallback, atom_tag, metadata, callback, cookie);
+}
+
+void AStatsManager_clearPullAtomCallback(int32_t atom_tag) {
+    INVOKE_METHOD(AStatsManager_clearPullAtomCallback, atom_tag);
+}
diff --git a/libstats/pull_lazy/libstatspull_lazy.h b/libstats/pull_lazy/libstatspull_lazy.h
new file mode 100644
index 0000000..2edddc7
--- /dev/null
+++ b/libstats/pull_lazy/libstatspull_lazy.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#pragma once
+
+extern "C" void PreventLibstatspullLazyLoadingForTests();
\ No newline at end of file
diff --git a/libstats/pull_lazy/libstatspull_lazy_test.xml b/libstats/pull_lazy/libstatspull_lazy_test.xml
new file mode 100644
index 0000000..1b619af
--- /dev/null
+++ b/libstats/pull_lazy/libstatspull_lazy_test.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+<configuration description="Runs libstatspull_lazy_test.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
+    <option name="test-suite-tag" value="mts" />
+
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="cleanup" value="true" />
+        <option name="push" value="libstatspull_lazy_test->/data/local/tmp/libstatspull_lazy_test" />
+        <option name="append-bitness" value="true" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="libstatspull_lazy_test" />
+    </test>
+
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+        <option name="mainline-module-package-name" value="com.google.android.os.statsd" />
+    </object>
+</configuration>
\ No newline at end of file
diff --git a/libstats/pull_lazy/tests/libstatspull_lazy_test.cpp b/libstats/pull_lazy/tests/libstatspull_lazy_test.cpp
new file mode 100644
index 0000000..41f82d0
--- /dev/null
+++ b/libstats/pull_lazy/tests/libstatspull_lazy_test.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2021 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 "../libstatspull_lazy.h"
+
+#include <gtest/gtest.h>
+
+#include "stats_pull_atom_callback.h"
+//#include "stats_event.h"
+
+// The tests here are just for the case when libstatspull.so cannot be loaded by
+// libstatspull_lazy.
+class LibstatspullLazyTest : public ::testing::Test {
+  protected:
+    virtual void SetUp() {
+        ::testing::Test::SetUp();
+        PreventLibstatspullLazyLoadingForTests();
+    }
+};
+
+static const char* kLoadFailed = "Failed to load libstatspull.so";
+
+TEST_F(LibstatspullLazyTest, NoLibstatspullForPullAtomMetadata) {
+    AStatsManager_PullAtomMetadata* metadata = NULL;
+    EXPECT_DEATH(AStatsManager_PullAtomMetadata_obtain(), kLoadFailed);
+    EXPECT_DEATH(AStatsManager_PullAtomMetadata_release(metadata), kLoadFailed);
+    EXPECT_DEATH(AStatsManager_PullAtomMetadata_setCoolDownMillis(metadata, 0), kLoadFailed);
+    EXPECT_DEATH(AStatsManager_PullAtomMetadata_getCoolDownMillis(metadata), kLoadFailed);
+    EXPECT_DEATH(AStatsManager_PullAtomMetadata_setTimeoutMillis(metadata, 0), kLoadFailed);
+    EXPECT_DEATH(AStatsManager_PullAtomMetadata_getTimeoutMillis(metadata), kLoadFailed);
+    EXPECT_DEATH(AStatsManager_PullAtomMetadata_setAdditiveFields(metadata, NULL, 0), kLoadFailed);
+    EXPECT_DEATH(AStatsManager_PullAtomMetadata_getNumAdditiveFields(metadata), kLoadFailed);
+    EXPECT_DEATH(AStatsManager_PullAtomMetadata_getAdditiveFields(metadata, NULL), kLoadFailed);
+}
+
+TEST_F(LibstatspullLazyTest, NoLibstatspullForAStatsEventList) {
+    AStatsEventList* event_list = NULL;
+    EXPECT_DEATH(AStatsEventList_addStatsEvent(event_list), kLoadFailed);
+}
+
+TEST_F(LibstatspullLazyTest, NoLibstatspullForPullAtomCallback) {
+    AStatsManager_PullAtomCallback callback = NULL;
+    EXPECT_DEATH(AStatsManager_setPullAtomCallback(0, NULL, callback, NULL), kLoadFailed);
+    EXPECT_DEATH(AStatsManager_clearPullAtomCallback(0), kLoadFailed);
+}
\ No newline at end of file
diff --git a/libstats/socket_lazy/Android.bp b/libstats/socket_lazy/Android.bp
new file mode 100644
index 0000000..ad6b4e0
--- /dev/null
+++ b/libstats/socket_lazy/Android.bp
@@ -0,0 +1,40 @@
+// Lazy loading version of libstatssocket that can be used by code
+// that is running before the statsd APEX is mounted and
+// libstatssocket.so is available.
+cc_library_static {
+    name: "libstatssocket_lazy",
+    header_libs: [
+        "libstatssocket_headers",
+    ],
+    export_header_lib_headers: [
+        "libstatssocket_headers",
+    ],
+    apex_available: ["//apex_available:platform"],
+    srcs: ["libstatssocket_lazy.cpp"],
+}
+
+cc_test {
+    name: "libstatssocket_lazy_test",
+    srcs: [
+        "tests/libstatssocket_lazy_test.cpp",
+    ],
+    static_libs: ["libstatssocket_lazy"],
+    shared_libs: ["liblog"],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    test_suites: ["device-tests", "mts-statsd"],
+    test_config: "libstatssocket_lazy_test.xml",
+    // TODO(b/153588990): Remove when the build system properly separates.
+    // 32bit and 64bit architectures.
+    compile_multilib: "both",
+    multilib: {
+        lib64: {
+            suffix: "64",
+        },
+        lib32: {
+            suffix: "32",
+        },
+    },
+}
\ No newline at end of file
diff --git a/libstats/socket_lazy/TEST_MAPPING b/libstats/socket_lazy/TEST_MAPPING
new file mode 100644
index 0000000..13afc00
--- /dev/null
+++ b/libstats/socket_lazy/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit" : [
+    {
+      "name" : "libstatssocket_lazy_test"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/libstats/socket_lazy/libstatssocket_lazy.cpp b/libstats/socket_lazy/libstatssocket_lazy.cpp
new file mode 100644
index 0000000..dd93eeb
--- /dev/null
+++ b/libstats/socket_lazy/libstatssocket_lazy.cpp
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2021 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 "libstatssocket_lazy.h"
+
+#include <mutex>
+
+#include <dlfcn.h>
+#include <stdatomic.h>
+
+#include "log/log.h"
+
+#include "stats_event.h"
+#include "stats_socket.h"
+
+// This file provides a lazy interface to libstatssocket.so to address early boot dependencies.
+// Specifically bootanimation, surfaceflinger, and lmkd run before the statsd APEX is loaded and
+// libstatssocket.so is in the statsd APEX.
+
+// Method pointers to libstatssocket methods are held in an array which simplifies checking
+// all pointers are initialized.
+enum MethodIndex {
+    // Stats Event APIs in stats_event.h.
+    k_AStatsEvent_obtain,
+    k_AStatsEvent_build,
+    k_AStatsEvent_write,
+    k_AStatsEvent_release,
+    k_AStatsEvent_setAtomId,
+    k_AStatsEvent_writeInt32,
+    k_AStatsEvent_writeInt64,
+    k_AStatsEvent_writeFloat,
+    k_AStatsEvent_writeBool,
+    k_AStatsEvent_writeByteArray,
+    k_AStatsEvent_writeString,
+    k_AStatsEvent_writeAttributionChain,
+    k_AStatsEvent_addBoolAnnotation,
+    k_AStatsEvent_addInt32Annotation,
+
+    // Stats Socket APIs in stats_socket.h.
+    k_AStatsSocket_close,
+
+    // Marker for count of methods
+    k_MethodCount
+};
+
+// Table of methods pointers in libstatssocket APIs.
+static void* g_Methods[k_MethodCount];
+
+//
+// Libstatssocket lazy loading.
+//
+
+static atomic_bool gPreventLibstatssocketLoading = false;  // Allows tests to block loading.
+
+void PreventLibstatssocketLazyLoadingForTests() {
+    gPreventLibstatssocketLoading.store(true);
+}
+
+static void* LoadLibstatssocket(int dlopen_flags) {
+    if (gPreventLibstatssocketLoading.load()) {
+        return nullptr;
+    }
+    return dlopen("libstatssocket.so", dlopen_flags);
+}
+
+//
+// Initialization and symbol binding.
+
+static void BindSymbol(void* handle, const char* name, enum MethodIndex index) {
+    void* symbol = dlsym(handle, name);
+    LOG_ALWAYS_FATAL_IF(symbol == nullptr, "Failed to find symbol '%s' in libstatssocket.so: %s",
+                        name, dlerror());
+    g_Methods[index] = symbol;
+}
+
+static void InitializeOnce() {
+    void* handle = LoadLibstatssocket(RTLD_NOW);
+    LOG_ALWAYS_FATAL_IF(handle == nullptr, "Failed to load libstatssocket.so: %s", dlerror());
+
+#undef BIND_SYMBOL
+#define BIND_SYMBOL(name) BindSymbol(handle, #name, k_##name);
+    // Methods in stats_event.h.
+    BIND_SYMBOL(AStatsEvent_obtain);
+    BIND_SYMBOL(AStatsEvent_build);
+    BIND_SYMBOL(AStatsEvent_write);
+    BIND_SYMBOL(AStatsEvent_release);
+    BIND_SYMBOL(AStatsEvent_setAtomId);
+    BIND_SYMBOL(AStatsEvent_writeInt32);
+    BIND_SYMBOL(AStatsEvent_writeInt64);
+    BIND_SYMBOL(AStatsEvent_writeFloat);
+    BIND_SYMBOL(AStatsEvent_writeBool);
+    BIND_SYMBOL(AStatsEvent_writeByteArray);
+    BIND_SYMBOL(AStatsEvent_writeString);
+    BIND_SYMBOL(AStatsEvent_writeAttributionChain);
+    BIND_SYMBOL(AStatsEvent_addBoolAnnotation);
+    BIND_SYMBOL(AStatsEvent_addInt32Annotation);
+
+    // Methods in stats_socket.h.
+    BIND_SYMBOL(AStatsSocket_close);
+#undef BIND_SYMBOL
+
+    // Check every symbol is bound.
+    for (int i = 0; i < k_MethodCount; ++i) {
+        LOG_ALWAYS_FATAL_IF(g_Methods[i] == nullptr,
+                            "Uninitialized method in libstatssocket_lazy at index: %d", i);
+    }
+}
+
+static void EnsureInitialized() {
+    static std::once_flag initialize_flag;
+    std::call_once(initialize_flag, InitializeOnce);
+}
+
+#define INVOKE_METHOD(name, args...)                            \
+    do {                                                        \
+        EnsureInitialized();                                    \
+        void* method = g_Methods[k_##name];                     \
+        return reinterpret_cast<decltype(&name)>(method)(args); \
+    } while (0)
+
+//
+// Forwarding for methods in stats_event.h.
+//
+
+AStatsEvent* AStatsEvent_obtain() {
+    INVOKE_METHOD(AStatsEvent_obtain);
+}
+
+void AStatsEvent_build(AStatsEvent* event) {
+    INVOKE_METHOD(AStatsEvent_build, event);
+}
+
+int AStatsEvent_write(AStatsEvent* event) {
+    INVOKE_METHOD(AStatsEvent_write, event);
+}
+
+void AStatsEvent_release(AStatsEvent* event) {
+    INVOKE_METHOD(AStatsEvent_release, event);
+}
+
+void AStatsEvent_setAtomId(AStatsEvent* event, uint32_t atomId) {
+    INVOKE_METHOD(AStatsEvent_setAtomId, event, atomId);
+}
+
+void AStatsEvent_writeInt32(AStatsEvent* event, int32_t value) {
+    INVOKE_METHOD(AStatsEvent_writeInt32, event, value);
+}
+
+void AStatsEvent_writeInt64(AStatsEvent* event, int64_t value) {
+    INVOKE_METHOD(AStatsEvent_writeInt64, event, value);
+}
+
+void AStatsEvent_writeFloat(AStatsEvent* event, float value) {
+    INVOKE_METHOD(AStatsEvent_writeFloat, event, value);
+}
+
+void AStatsEvent_writeBool(AStatsEvent* event, bool value) {
+    INVOKE_METHOD(AStatsEvent_writeBool, event, value);
+}
+
+void AStatsEvent_writeByteArray(AStatsEvent* event, const uint8_t* buf, size_t numBytes) {
+    INVOKE_METHOD(AStatsEvent_writeByteArray, event, buf, numBytes);
+}
+
+void AStatsEvent_writeString(AStatsEvent* event, const char* value) {
+    INVOKE_METHOD(AStatsEvent_writeString, event, value);
+}
+
+void AStatsEvent_writeAttributionChain(AStatsEvent* event, const uint32_t* uids,
+                                       const char* const* tags, uint8_t numNodes) {
+    INVOKE_METHOD(AStatsEvent_writeAttributionChain, event, uids, tags, numNodes);
+}
+
+void AStatsEvent_addBoolAnnotation(AStatsEvent* event, uint8_t annotationId, bool value) {
+    INVOKE_METHOD(AStatsEvent_addBoolAnnotation, event, annotationId, value);
+}
+
+void AStatsEvent_addInt32Annotation(AStatsEvent* event, uint8_t annotationId, int32_t value) {
+    INVOKE_METHOD(AStatsEvent_addInt32Annotation, event, annotationId, value);
+}
+
+//
+// Forwarding for methods in stats_socket.h.
+//
+
+void AStatsSocket_close() {
+    INVOKE_METHOD(AStatsSocket_close);
+}
\ No newline at end of file
diff --git a/libstats/socket_lazy/libstatssocket_lazy.h b/libstats/socket_lazy/libstatssocket_lazy.h
new file mode 100644
index 0000000..3ff87cb
--- /dev/null
+++ b/libstats/socket_lazy/libstatssocket_lazy.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#pragma once
+
+extern "C" void PreventLibstatssocketLazyLoadingForTests();
\ No newline at end of file
diff --git a/libstats/socket_lazy/libstatssocket_lazy_test.xml b/libstats/socket_lazy/libstatssocket_lazy_test.xml
new file mode 100644
index 0000000..ca6339b
--- /dev/null
+++ b/libstats/socket_lazy/libstatssocket_lazy_test.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+<configuration description="Runs libstatssocket_lazy_test.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
+    <option name="test-suite-tag" value="mts" />
+
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="cleanup" value="true" />
+        <option name="push" value="libstatssocket_lazy_test->/data/local/tmp/libstatssocket_lazy_test" />
+        <option name="append-bitness" value="true" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="libstatssocket_lazy_test" />
+    </test>
+
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+        <option name="mainline-module-package-name" value="com.google.android.os.statsd" />
+    </object>
+</configuration>
\ No newline at end of file
diff --git a/libstats/socket_lazy/tests/libstatssocket_lazy_test.cpp b/libstats/socket_lazy/tests/libstatssocket_lazy_test.cpp
new file mode 100644
index 0000000..fe13598
--- /dev/null
+++ b/libstats/socket_lazy/tests/libstatssocket_lazy_test.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2021 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 "../libstatssocket_lazy.h"
+
+#include <gtest/gtest.h>
+
+#include "stats_event.h"
+#include "stats_socket.h"
+
+// The tests here are just for the case when libstatssocket.so cannot be loaded by
+// libstatssocket_lazy.
+class LibstatssocketLazyTest : public ::testing::Test {
+  protected:
+    virtual void SetUp() {
+        ::testing::Test::SetUp();
+        PreventLibstatssocketLazyLoadingForTests();
+    }
+};
+
+static const char* kLoadFailed = "Failed to load libstatssocket.so";
+
+TEST_F(LibstatssocketLazyTest, NoLibstatssocketForStatsEvent) {
+    AStatsEvent* event = NULL;
+    EXPECT_DEATH(AStatsEvent_obtain(), kLoadFailed);
+    EXPECT_DEATH(AStatsEvent_build(event), kLoadFailed);
+    EXPECT_DEATH(AStatsEvent_write(event), kLoadFailed);
+    EXPECT_DEATH(AStatsEvent_release(event), kLoadFailed);
+
+    EXPECT_DEATH(AStatsEvent_setAtomId(event, 0), kLoadFailed);
+    EXPECT_DEATH(AStatsEvent_writeInt32(event, 0), kLoadFailed);
+    EXPECT_DEATH(AStatsEvent_writeInt64(event, 0), kLoadFailed);
+    EXPECT_DEATH(AStatsEvent_writeFloat(event, 0), kLoadFailed);
+    EXPECT_DEATH(AStatsEvent_writeBool(event, false), kLoadFailed);
+    EXPECT_DEATH(AStatsEvent_writeByteArray(event, NULL, 0), kLoadFailed);
+    EXPECT_DEATH(AStatsEvent_writeString(event, NULL), kLoadFailed);
+    EXPECT_DEATH(AStatsEvent_writeAttributionChain(event, NULL, NULL, 0), kLoadFailed);
+
+    EXPECT_DEATH(AStatsEvent_addBoolAnnotation(event, 0, false), kLoadFailed);
+    EXPECT_DEATH(AStatsEvent_addInt32Annotation(event, 0, 0), kLoadFailed);
+}
+
+TEST_F(LibstatssocketLazyTest, NoLibstatssocketForStatsSocket) {
+    EXPECT_DEATH(AStatsSocket_close(), kLoadFailed);
+}
\ No newline at end of file
diff --git a/llkd/README.md b/llkd/README.md
index 6f92f14..9bcf806 100644
--- a/llkd/README.md
+++ b/llkd/README.md
@@ -207,7 +207,7 @@
 
 The `llkd` does not monitor the specified subset of processes for live lock stack
 signatures. Default is process names
-`init,lmkd.llkd,llkd,keystore,ueventd,apexd,logd`. Prevents the sepolicy
+`init,lmkd.llkd,llkd,keystore,keystore2,ueventd,apexd,logd`. Prevents the sepolicy
 violation associated with processes that block `ptrace` (as these can't be
 checked). **Active only on userdebug and eng builds**. For details on build
 types, refer to [Building Android](/setup/build/building#choose-a-target).
diff --git a/llkd/include/llkd.h b/llkd/include/llkd.h
index 4b20a56..0822a3e 100644
--- a/llkd/include/llkd.h
+++ b/llkd/include/llkd.h
@@ -60,7 +60,7 @@
 #define LLK_IGNORELIST_UID_PROPERTY     "ro.llk.ignorelist.uid"
 #define LLK_IGNORELIST_UID_DEFAULT      ""
 #define LLK_IGNORELIST_STACK_PROPERTY   "ro.llk.ignorelist.process.stack"
-#define LLK_IGNORELIST_STACK_DEFAULT    "init,lmkd.llkd,llkd,keystore,ueventd,apexd"
+#define LLK_IGNORELIST_STACK_DEFAULT    "init,lmkd.llkd,llkd,keystore,keystore2,ueventd,apexd"
 /* clang-format on */
 
 __END_DECLS
diff --git a/llkd/libllkd.cpp b/llkd/libllkd.cpp
index 9f3e218..b3101f4 100644
--- a/llkd/libllkd.cpp
+++ b/llkd/libllkd.cpp
@@ -115,8 +115,8 @@
 // list of uids, and uid names, to skip, default nothing
 std::unordered_set<std::string> llkIgnorelistUid;
 #ifdef __PTRACE_ENABLED__
-// list of names to skip stack checking. "init", "lmkd", "llkd", "keystore" or
-// "logd" (if not userdebug).
+// list of names to skip stack checking. "init", "lmkd", "llkd", "keystore",
+// "keystore2", or "logd" (if not userdebug).
 std::unordered_set<std::string> llkIgnorelistStack;
 #endif
 
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 11b3da7..6b8868b 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -884,9 +884,12 @@
     wait_for_prop apexd.status activated
     perform_apex_config
 
-    # Export *CLASSPATH variables from /etc/classpath
-    # TODO(b/180105615): export from the generated file instead.
-    load_exports /etc/classpath
+    # Define and export *CLASSPATH variables
+    mkdir /data/system/environ 0700 system system
+    # Must start before 'odsign', as odsign depends on *CLASSPATH variables
+    exec_start derive_classpath
+    load_exports /data/system/environ/classpath
+    rm /data/system/environ/classpath
 
     # Special-case /data/media/obb per b/64566063
     mkdir /data/media 0770 media_rw media_rw encryption=None
@@ -902,6 +905,7 @@
 
     # Start the on-device signing daemon, and wait for it to finish, to ensure
     # ART artifacts are generated if needed.
+    # Must start after 'derive_classpath' to have *CLASSPATH variables set.
     exec_start odsign
 
     # After apexes are mounted, tell keymaster early boot has ended, so it will
diff --git a/trusty/fuzz/tipc_fuzzer.cpp b/trusty/fuzz/tipc_fuzzer.cpp
index 24b0f98..3258944 100644
--- a/trusty/fuzz/tipc_fuzzer.cpp
+++ b/trusty/fuzz/tipc_fuzzer.cpp
@@ -51,13 +51,21 @@
         exit(-1);
     }
 
+    /* Make sure lazy-loaded TAs have started and connected to coverage service. */
+    TrustyApp ta(TIPC_DEV, TRUSTY_APP_PORT);
+    auto ret = ta.Connect();
+    if (!ret.ok()) {
+        std::cerr << ret.error() << std::endl;
+        exit(-1);
+    }
+
     record = std::make_unique<CoverageRecord>(TIPC_DEV, &module_uuid, TRUSTY_APP_FILENAME);
     if (!record) {
         std::cerr << "Failed to allocate coverage record" << std::endl;
         exit(-1);
     }
 
-    auto ret = record->Open();
+    ret = record->Open();
     if (!ret.ok()) {
         std::cerr << ret.error() << std::endl;
         exit(-1);