Merge "Separate out libkeyutils and mini_keyctl."
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/fs_mgr/libsnapshot/android/snapshot/snapshot.proto b/fs_mgr/libsnapshot/android/snapshot/snapshot.proto
index e902fa4..1ebc29f 100644
--- a/fs_mgr/libsnapshot/android/snapshot/snapshot.proto
+++ b/fs_mgr/libsnapshot/android/snapshot/snapshot.proto
@@ -162,7 +162,7 @@
MergePhase merge_phase = 6;
}
-// Next: 7
+// Next: 9
message SnapshotMergeReport {
// Status of the update after the merge attempts.
UpdateState state = 1;
@@ -182,4 +182,10 @@
// Sum of the estimated COW fields in the OTA manifest.
uint64 estimated_cow_size_bytes = 6;
+
+ // Time from boot to sys.boot_completed, in milliseconds.
+ uint32 boot_complete_time_ms = 7;
+
+ // Time from sys.boot_completed to merge start, in milliseconds.
+ uint32 boot_complete_to_merge_start_time_ms = 8;
}
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stats.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stats.h
index 3eeae64..e617d7a 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stats.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stats.h
@@ -32,9 +32,13 @@
virtual void set_cow_file_size(uint64_t cow_file_size) = 0;
virtual void set_total_cow_size_bytes(uint64_t bytes) = 0;
virtual void set_estimated_cow_size_bytes(uint64_t bytes) = 0;
+ virtual void set_boot_complete_time_ms(uint32_t ms) = 0;
+ virtual void set_boot_complete_to_merge_start_time_ms(uint32_t ms) = 0;
virtual uint64_t cow_file_size() = 0;
virtual uint64_t total_cow_size_bytes() = 0;
virtual uint64_t estimated_cow_size_bytes() = 0;
+ virtual uint32_t boot_complete_time_ms() = 0;
+ virtual uint32_t boot_complete_to_merge_start_time_ms() = 0;
// Called when merge ends. Properly clean up permanent storage.
class Result {
@@ -62,6 +66,10 @@
void set_estimated_cow_size_bytes(uint64_t bytes) override;
uint64_t total_cow_size_bytes() override;
uint64_t estimated_cow_size_bytes() override;
+ void set_boot_complete_time_ms(uint32_t ms) override;
+ uint32_t boot_complete_time_ms() override;
+ void set_boot_complete_to_merge_start_time_ms(uint32_t ms) override;
+ uint32_t boot_complete_to_merge_start_time_ms() override;
std::unique_ptr<Result> Finish() override;
private:
diff --git a/fs_mgr/libsnapshot/snapshot_stats.cpp b/fs_mgr/libsnapshot/snapshot_stats.cpp
index 35e2d92..7fcfcea 100644
--- a/fs_mgr/libsnapshot/snapshot_stats.cpp
+++ b/fs_mgr/libsnapshot/snapshot_stats.cpp
@@ -114,6 +114,22 @@
return report_.estimated_cow_size_bytes();
}
+void SnapshotMergeStats::set_boot_complete_time_ms(uint32_t ms) {
+ report_.set_boot_complete_time_ms(ms);
+}
+
+uint32_t SnapshotMergeStats::boot_complete_time_ms() {
+ return report_.boot_complete_time_ms();
+}
+
+void SnapshotMergeStats::set_boot_complete_to_merge_start_time_ms(uint32_t ms) {
+ report_.set_boot_complete_to_merge_start_time_ms(ms);
+}
+
+uint32_t SnapshotMergeStats::boot_complete_to_merge_start_time_ms() {
+ return report_.boot_complete_to_merge_start_time_ms();
+}
+
class SnapshotMergeStatsResultImpl : public SnapshotMergeStats::Result {
public:
SnapshotMergeStatsResultImpl(const SnapshotMergeReport& report,
diff --git a/fs_mgr/libsnapshot/snapshot_stub.cpp b/fs_mgr/libsnapshot/snapshot_stub.cpp
index 079e606..43825cc 100644
--- a/fs_mgr/libsnapshot/snapshot_stub.cpp
+++ b/fs_mgr/libsnapshot/snapshot_stub.cpp
@@ -131,6 +131,10 @@
void set_estimated_cow_size_bytes(uint64_t) override {}
uint64_t total_cow_size_bytes() override { return 0; }
uint64_t estimated_cow_size_bytes() override { return 0; }
+ void set_boot_complete_time_ms(uint32_t) override {}
+ uint32_t boot_complete_time_ms() override { return 0; }
+ void set_boot_complete_to_merge_start_time_ms(uint32_t) override {}
+ uint32_t boot_complete_to_merge_start_time_ms() override { return 0; }
};
ISnapshotMergeStats* SnapshotManagerStub::GetSnapshotMergeStatsInstance() {
diff --git a/init/init.cpp b/init/init.cpp
index 70d6809..7264b22 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -518,11 +518,9 @@
if (!android::base::GetBoolProperty("ro.oem_unlock_supported", false)) {
return;
}
- ImportKernelCmdline([](const std::string& key, const std::string& value) {
- if (key == "androidboot.verifiedbootstate") {
- SetProperty("ro.boot.flash.locked", value == "orange" ? "0" : "1");
- }
- });
+ SetProperty(
+ "ro.boot.flash.locked",
+ android::base::GetProperty("ro.boot.verifiedbootstate", "") == "orange" ? "0" : "1");
}
static Result<void> property_enable_triggers_action(const BuiltinArguments& args) {
diff --git a/init/selinux.cpp b/init/selinux.cpp
index 47686b8..62c4586 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -63,6 +63,7 @@
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/parseint.h>
+#include <android-base/result.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <fs_avb/fs_avb.h>
@@ -222,8 +223,8 @@
return true;
}
-bool FindPrecompiledSplitPolicy(std::string* file) {
- file->clear();
+Result<std::string> FindPrecompiledSplitPolicy() {
+ std::string precompiled_sepolicy;
// If there is an odm partition, precompiled_sepolicy will be in
// odm/etc/selinux. Otherwise it will be in vendor/etc/selinux.
static constexpr const char vendor_precompiled_sepolicy[] =
@@ -231,62 +232,49 @@
static constexpr const char odm_precompiled_sepolicy[] =
"/odm/etc/selinux/precompiled_sepolicy";
if (access(odm_precompiled_sepolicy, R_OK) == 0) {
- *file = odm_precompiled_sepolicy;
+ precompiled_sepolicy = odm_precompiled_sepolicy;
} else if (access(vendor_precompiled_sepolicy, R_OK) == 0) {
- *file = vendor_precompiled_sepolicy;
+ precompiled_sepolicy = vendor_precompiled_sepolicy;
} else {
- PLOG(INFO) << "No precompiled sepolicy";
- return false;
- }
- std::string actual_plat_id;
- if (!ReadFirstLine("/system/etc/selinux/plat_sepolicy_and_mapping.sha256", &actual_plat_id)) {
- PLOG(INFO) << "Failed to read "
- "/system/etc/selinux/plat_sepolicy_and_mapping.sha256";
- return false;
- }
- std::string actual_system_ext_id;
- if (!ReadFirstLine("/system_ext/etc/selinux/system_ext_sepolicy_and_mapping.sha256",
- &actual_system_ext_id)) {
- PLOG(INFO) << "Failed to read "
- "/system_ext/etc/selinux/system_ext_sepolicy_and_mapping.sha256";
- return false;
- }
- std::string actual_product_id;
- if (!ReadFirstLine("/product/etc/selinux/product_sepolicy_and_mapping.sha256",
- &actual_product_id)) {
- PLOG(INFO) << "Failed to read "
- "/product/etc/selinux/product_sepolicy_and_mapping.sha256";
- return false;
+ return ErrnoError() << "No precompiled sepolicy at " << vendor_precompiled_sepolicy;
}
- std::string precompiled_plat_id;
- std::string precompiled_plat_sha256 = *file + ".plat_sepolicy_and_mapping.sha256";
- if (!ReadFirstLine(precompiled_plat_sha256.c_str(), &precompiled_plat_id)) {
- PLOG(INFO) << "Failed to read " << precompiled_plat_sha256;
- file->clear();
- return false;
+ // Use precompiled sepolicy only when all corresponding hashes are equal.
+ // plat_sepolicy is always checked, while system_ext and product are checked only when they
+ // exist.
+ std::vector<std::pair<std::string, std::string>> sepolicy_hashes{
+ {"/system/etc/selinux/plat_sepolicy_and_mapping.sha256",
+ precompiled_sepolicy + ".plat_sepolicy_and_mapping.sha256"},
+ };
+
+ if (access("/system_ext/etc/selinux/system_ext_sepolicy.cil", F_OK) == 0) {
+ sepolicy_hashes.emplace_back(
+ "/system_ext/etc/selinux/system_ext_sepolicy_and_mapping.sha256",
+ precompiled_sepolicy + ".system_ext_sepolicy_and_mapping.sha256");
}
- std::string precompiled_system_ext_id;
- std::string precompiled_system_ext_sha256 = *file + ".system_ext_sepolicy_and_mapping.sha256";
- if (!ReadFirstLine(precompiled_system_ext_sha256.c_str(), &precompiled_system_ext_id)) {
- PLOG(INFO) << "Failed to read " << precompiled_system_ext_sha256;
- file->clear();
- return false;
+
+ if (access("/product/etc/selinux/product_sepolicy.cil", F_OK) == 0) {
+ sepolicy_hashes.emplace_back("/product/etc/selinux/product_sepolicy_and_mapping.sha256",
+ precompiled_sepolicy + ".product_sepolicy_and_mapping.sha256");
}
- std::string precompiled_product_id;
- std::string precompiled_product_sha256 = *file + ".product_sepolicy_and_mapping.sha256";
- if (!ReadFirstLine(precompiled_product_sha256.c_str(), &precompiled_product_id)) {
- PLOG(INFO) << "Failed to read " << precompiled_product_sha256;
- file->clear();
- return false;
+
+ for (const auto& [actual_id_path, precompiled_id_path] : sepolicy_hashes) {
+ std::string actual_id;
+ if (!ReadFirstLine(actual_id_path.c_str(), &actual_id)) {
+ return ErrnoError() << "Failed to read " << actual_id_path;
+ }
+
+ std::string precompiled_id;
+ if (!ReadFirstLine(precompiled_id_path.c_str(), &precompiled_id)) {
+ return ErrnoError() << "Failed to read " << precompiled_id_path;
+ }
+
+ if (actual_id.empty() || actual_id != precompiled_id) {
+ return Error() << actual_id_path << " and " << precompiled_id_path << " differ";
+ }
}
- if (actual_plat_id.empty() || actual_plat_id != precompiled_plat_id ||
- actual_system_ext_id.empty() || actual_system_ext_id != precompiled_system_ext_id ||
- actual_product_id.empty() || actual_product_id != precompiled_product_id) {
- file->clear();
- return false;
- }
- return true;
+
+ return precompiled_sepolicy;
}
bool GetVendorMappingVersion(std::string* plat_vers) {
@@ -333,15 +321,18 @@
// Load precompiled policy from vendor image, if a matching policy is found there. The policy
// must match the platform policy on the system image.
- std::string precompiled_sepolicy_file;
// use_userdebug_policy requires compiling sepolicy with userdebug_plat_sepolicy.cil.
// Thus it cannot use the precompiled policy from vendor image.
- if (!use_userdebug_policy && FindPrecompiledSplitPolicy(&precompiled_sepolicy_file)) {
- unique_fd fd(open(precompiled_sepolicy_file.c_str(), O_RDONLY | O_CLOEXEC | O_BINARY));
- if (fd != -1) {
- policy_file->fd = std::move(fd);
- policy_file->path = std::move(precompiled_sepolicy_file);
- return true;
+ if (!use_userdebug_policy) {
+ if (auto res = FindPrecompiledSplitPolicy(); res.ok()) {
+ unique_fd fd(open(res->c_str(), O_RDONLY | O_CLOEXEC | O_BINARY));
+ if (fd != -1) {
+ policy_file->fd = std::move(fd);
+ policy_file->path = std::move(*res);
+ return true;
+ }
+ } else {
+ LOG(INFO) << res.error();
}
}
// No suitable precompiled policy could be loaded
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/etc/linker.config.json b/rootdir/etc/linker.config.json
index 2faf608..83cb6ff 100644
--- a/rootdir/etc/linker.config.json
+++ b/rootdir/etc/linker.config.json
@@ -6,6 +6,7 @@
"libnativebridge.so",
"libnativehelper.so",
"libnativeloader.so",
+ "libsigchain.so",
"libandroidicu.so",
"libicu.so",
// TODO(b/122876336): Remove libpac.so once it's migrated to Webview
@@ -26,4 +27,4 @@
"libadb_pairing_connection.so",
"libadb_pairing_server.so"
]
-}
\ No newline at end of file
+}
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 58e161d..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
@@ -1074,7 +1078,7 @@
chown root radio /proc/cmdline
# Define default initial receive window size in segments.
- setprop net.tcp.default_init_rwnd 60
+ setprop net.tcp_def_init_rwnd 60
# Start standard binderized HAL daemons
class_start hal
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);