Merge "Remove NOTICE file; use global Android-Apache-2.0"
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index c8612bf..a52f719 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -153,14 +153,14 @@
}
struct timeval tv = {
- .tv_sec = 1 * android::base::TimeoutMultiplier(),
+ .tv_sec = 1 * android::base::HwTimeoutMultiplier(),
.tv_usec = 0,
};
if (setsockopt(amfd.get(), SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) == -1) {
PLOG(ERROR) << "failed to set send timeout on activity manager socket";
return false;
}
- tv.tv_sec = 3 * android::base::TimeoutMultiplier(); // 3 seconds on handshake read
+ tv.tv_sec = 3 * android::base::HwTimeoutMultiplier(); // 3 seconds on handshake read
if (setsockopt(amfd.get(), SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) {
PLOG(ERROR) << "failed to set receive timeout on activity manager socket";
return false;
@@ -448,7 +448,7 @@
//
// Note: processes with many threads and minidebug-info can take a bit to
// unwind, do not make this too small. b/62828735
- alarm(30 * android::base::TimeoutMultiplier());
+ alarm(30 * android::base::HwTimeoutMultiplier());
// Get the process name (aka cmdline).
std::string process_name = get_process_name(g_target_thread);
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/debuggerd/tombstoned/intercept_manager.cpp b/debuggerd/tombstoned/intercept_manager.cpp
index 4d4646a..613e6f5 100644
--- a/debuggerd/tombstoned/intercept_manager.cpp
+++ b/debuggerd/tombstoned/intercept_manager.cpp
@@ -163,7 +163,7 @@
event_assign(intercept->intercept_event, intercept_manager->base, sockfd, EV_READ | EV_TIMEOUT,
intercept_close_cb, arg);
- struct timeval timeout = {.tv_sec = 10 * android::base::TimeoutMultiplier(), .tv_usec = 0};
+ struct timeval timeout = {.tv_sec = 10 * android::base::HwTimeoutMultiplier(), .tv_usec = 0};
event_add(intercept->intercept_event, &timeout);
}
@@ -179,7 +179,7 @@
intercept->intercept_manager = static_cast<InterceptManager*>(arg);
intercept->sockfd.reset(sockfd);
- struct timeval timeout = {1 * android::base::TimeoutMultiplier(), 0};
+ struct timeval timeout = {1 * android::base::HwTimeoutMultiplier(), 0};
event_base* base = evconnlistener_get_base(listener);
event* intercept_event =
event_new(base, sockfd, EV_TIMEOUT | EV_READ, intercept_request_cb, intercept);
diff --git a/debuggerd/tombstoned/tombstoned.cpp b/debuggerd/tombstoned/tombstoned.cpp
index bc2d33d..0b87b7a 100644
--- a/debuggerd/tombstoned/tombstoned.cpp
+++ b/debuggerd/tombstoned/tombstoned.cpp
@@ -320,7 +320,7 @@
}
// TODO: Make this configurable by the interceptor?
- struct timeval timeout = {10 * android::base::TimeoutMultiplier(), 0};
+ struct timeval timeout = {10 * android::base::HwTimeoutMultiplier(), 0};
event_base* base = event_get_base(crash->crash_event);
@@ -340,7 +340,7 @@
// TODO: Make sure that only java crashes come in on the java socket
// and only native crashes on the native socket.
- struct timeval timeout = {1 * android::base::TimeoutMultiplier(), 0};
+ struct timeval timeout = {1 * android::base::HwTimeoutMultiplier(), 0};
event* crash_event = event_new(base, sockfd, EV_TIMEOUT | EV_READ, crash_request_cb, crash);
crash->crash_socket_fd.reset(sockfd);
crash->crash_event = crash_event;
diff --git a/libkeyutils/Android.bp b/libkeyutils/Android.bp
index 9848cd8..86f68fb 100644
--- a/libkeyutils/Android.bp
+++ b/libkeyutils/Android.bp
@@ -2,25 +2,10 @@
default_applicable_licenses: ["system_core_libkeyutils_license"],
}
-// Added automatically by a large-scale-change that took the approach of
-// 'apply every license found to every target'. While this makes sure we respect
-// every license restriction, it may not be entirely correct.
-//
-// e.g. GPL in an MIT project might only apply to the contrib/ directory.
-//
-// Please consider splitting the single license below into multiple licenses,
-// taking care not to lose any license_kind information, and overriding the
-// default license using the 'licenses: [...]' property on targets as needed.
-//
-// For unused files, consider creating a 'fileGroup' with "//visibility:private"
-// to attach the license to, and including a comment whether the files may be
-// used in the current project.
-// See: http://go/android-license-faq
license {
name: "system_core_libkeyutils_license",
visibility: [":__subpackages__"],
license_kinds: [
- "SPDX-license-identifier-Apache-2.0",
"SPDX-license-identifier-BSD",
],
// large-scale-change unable to identify any license_text files
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..c4c58ee 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
@@ -962,7 +962,8 @@
//
// This alarm is effectively the live lock detection of llkd, as
// we understandably can not monitor ourselves otherwise.
- ::alarm(duration_cast<seconds>(llkTimeoutMs * 2 * android::base::TimeoutMultiplier()).count());
+ ::alarm(duration_cast<seconds>(llkTimeoutMs * 2 * android::base::HwTimeoutMultiplier())
+ .count());
// kernel jiffy precision fastest acquisition
static timespec last;
diff --git a/libkeyutils/mini_keyctl/Android.bp b/mini_keyctl/Android.bp
similarity index 100%
rename from libkeyutils/mini_keyctl/Android.bp
rename to mini_keyctl/Android.bp
diff --git a/libkeyutils/mini_keyctl/mini_keyctl.cpp b/mini_keyctl/mini_keyctl.cpp
similarity index 100%
rename from libkeyutils/mini_keyctl/mini_keyctl.cpp
rename to mini_keyctl/mini_keyctl.cpp
diff --git a/libkeyutils/mini_keyctl/mini_keyctl_utils.cpp b/mini_keyctl/mini_keyctl_utils.cpp
similarity index 100%
rename from libkeyutils/mini_keyctl/mini_keyctl_utils.cpp
rename to mini_keyctl/mini_keyctl_utils.cpp
diff --git a/libkeyutils/mini_keyctl/mini_keyctl_utils.h b/mini_keyctl/mini_keyctl_utils.h
similarity index 100%
rename from libkeyutils/mini_keyctl/mini_keyctl_utils.h
rename to mini_keyctl/mini_keyctl_utils.h
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);
diff --git a/trusty/utils/acvp/Android.bp b/trusty/utils/acvp/Android.bp
new file mode 100644
index 0000000..6fe193e
--- /dev/null
+++ b/trusty/utils/acvp/Android.bp
@@ -0,0 +1,36 @@
+// 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.
+
+cc_binary {
+ name: "trusty_acvp_modulewrapper",
+ vendor: true,
+
+ srcs: [
+ "trusty_modulewrapper.cpp",
+ ],
+ static_libs: [
+ "libacvp_modulewrapper",
+ ],
+ shared_libs: [
+ "libbase",
+ "libc",
+ "libdmabufheap",
+ "liblog",
+ "libtrusty",
+ "libssl",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+}
diff --git a/trusty/utils/acvp/acvp_ipc.h b/trusty/utils/acvp/acvp_ipc.h
new file mode 100644
index 0000000..8b48ae3
--- /dev/null
+++ b/trusty/utils/acvp/acvp_ipc.h
@@ -0,0 +1,77 @@
+/*
+ * 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
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ACVP_PORT "com.android.trusty.acvp"
+
+/*
+ * Maximum number of arguments
+ */
+#define ACVP_MAX_NUM_ARGUMENTS 8
+
+/*
+ * Maximum length of an algorithm name
+ */
+#define ACVP_MAX_NAME_LENGTH 30
+
+/*
+ * Maximum length of an ACVP request message
+ */
+#define ACVP_MAX_MESSAGE_LENGTH sizeof(struct acvp_req)
+
+/*
+ * Minimum length of the shared memory buffer
+ *
+ * This must be at least as long as the longest reply from the ACVP service
+ * (currently the reply from getConfig()).
+ */
+#define ACVP_MIN_SHARED_MEMORY 16384
+
+/**
+ * acvp_req - Request for the Trusty ACVP app
+ * @num_args: Number of acvp_arg structures following this struct
+ * @buffer_size: Total size of shared memory buffer
+ * @lengths: Length of each argument in the shared memory buffer
+ *
+ * @num_args copies of the acvp_arg struct follow this structure.
+ */
+struct acvp_req {
+ uint32_t num_args;
+ uint32_t buffer_size;
+ uint32_t lengths[ACVP_MAX_NUM_ARGUMENTS];
+};
+
+/**
+ * acvp_resp - Response to a ACVP request
+ *
+ * @num_spans: Number of response sections
+ * @lengths: Length of each response section
+ */
+struct acvp_resp {
+ uint32_t num_spans;
+ uint32_t lengths[ACVP_MAX_NUM_ARGUMENTS];
+};
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/trusty/utils/acvp/trusty_modulewrapper.cpp b/trusty/utils/acvp/trusty_modulewrapper.cpp
new file mode 100644
index 0000000..70ffb52
--- /dev/null
+++ b/trusty/utils/acvp/trusty_modulewrapper.cpp
@@ -0,0 +1,235 @@
+/*
+ * Copyright 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.
+ */
+
+#define LOG_TAG "TrustyAcvpModulewrapper"
+
+#include <BufferAllocator/BufferAllocator.h>
+#include <android-base/file.h>
+#include <android-base/result.h>
+#include <android-base/unique_fd.h>
+#include <errno.h>
+#include <log/log.h>
+#include <modulewrapper.h>
+#include <openssl/span.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <trusty/tipc.h>
+#include <unistd.h>
+#include <iostream>
+
+#include "acvp_ipc.h"
+
+constexpr const char kTrustyDeviceName[] = "/dev/trusty-ipc-dev0";
+
+using android::base::ErrnoError;
+using android::base::Error;
+using android::base::Result;
+using android::base::unique_fd;
+using android::base::WriteFully;
+
+static inline size_t AlignUpToPage(size_t size) {
+ return (size + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
+}
+
+namespace {
+
+class ModuleWrapper {
+ private:
+ static const char* kAcvpPort_;
+ static const char* kTrustyDeviceName_;
+
+ public:
+ ModuleWrapper();
+ ~ModuleWrapper();
+
+ Result<void> SendMessage(bssl::Span<const bssl::Span<const uint8_t>>);
+
+ Result<void> ForwardResponse();
+
+ private:
+ // Connection to the Trusty ACVP service
+ int tipc_fd_ = -1;
+
+ // Shared memory DMA buf
+ unique_fd dmabuf_fd_;
+
+ // Size of shared memory mapping
+ size_t shm_size_ = 0;
+
+ // Shared memory mapping
+ uint8_t* shm_buffer_ = nullptr;
+};
+
+} // namespace
+
+const char* ModuleWrapper::kAcvpPort_ = ACVP_PORT;
+const char* ModuleWrapper::kTrustyDeviceName_ = kTrustyDeviceName;
+
+ModuleWrapper::ModuleWrapper() {
+ tipc_fd_ = tipc_connect(kTrustyDeviceName_, kAcvpPort_);
+ if (tipc_fd_ < 0) {
+ fprintf(stderr, "Failed to connect to Trusty ACVP test app: %s\n", strerror(-tipc_fd_));
+ }
+}
+
+ModuleWrapper::~ModuleWrapper() {
+ if (tipc_fd_ >= 0) {
+ tipc_close(tipc_fd_);
+ }
+
+ if (shm_buffer_) {
+ munmap(shm_buffer_, shm_size_);
+ }
+}
+
+Result<void> ModuleWrapper::SendMessage(bssl::Span<const bssl::Span<const uint8_t>> args) {
+ assert(args.size() < ACVP_MAX_NUM_ARGUMENTS);
+ assert(args[0].size() < ACVP_MAX_NAME_LENGTH);
+
+ struct acvp_req request;
+ request.num_args = args.size();
+
+ size_t total_args_size = 0;
+ for (auto arg : args) {
+ total_args_size += arg.size();
+ }
+
+ shm_size_ = ACVP_MIN_SHARED_MEMORY;
+ if (total_args_size > shm_size_) {
+ shm_size_ = AlignUpToPage(total_args_size);
+ }
+ request.buffer_size = shm_size_;
+
+ struct iovec iov = {
+ .iov_base = &request,
+ .iov_len = sizeof(struct acvp_req),
+ };
+
+ BufferAllocator alloc;
+ dmabuf_fd_.reset(alloc.Alloc(kDmabufSystemHeapName, shm_size_));
+ if (!dmabuf_fd_.ok()) {
+ return ErrnoError() << "Error creating dmabuf";
+ }
+
+ shm_buffer_ = (uint8_t*)mmap(0, shm_size_, PROT_READ | PROT_WRITE, MAP_SHARED, dmabuf_fd_, 0);
+ if (shm_buffer_ == MAP_FAILED) {
+ return ErrnoError() << "Failed to map shared memory dmabuf";
+ }
+
+ size_t cur_offset = 0;
+ for (int i = 0; i < args.size(); ++i) {
+ request.lengths[i] = args[i].size();
+ memcpy(shm_buffer_ + cur_offset, args[i].data(), args[i].size());
+ cur_offset += args[i].size();
+ }
+
+ struct trusty_shm shm = {
+ .fd = dmabuf_fd_.get(),
+ .transfer = TRUSTY_SHARE,
+ };
+
+ int rc = tipc_send(tipc_fd_, &iov, 1, &shm, 1);
+ if (rc != sizeof(struct acvp_req)) {
+ return ErrnoError() << "Failed to send request to Trusty ACVP service";
+ }
+
+ return {};
+}
+
+Result<void> ModuleWrapper::ForwardResponse() {
+ struct acvp_resp resp;
+ int bytes_read = read(tipc_fd_, &resp, sizeof(struct acvp_resp));
+ if (bytes_read < 0) {
+ return ErrnoError() << "Failed to read response from Trusty ACVP service";
+ }
+
+ if (bytes_read != sizeof(struct acvp_resp)) {
+ return Error() << "Trusty ACVP response overflowed expected size";
+ }
+
+ size_t total_args_size = 0;
+ for (size_t i = 0; i < resp.num_spans; i++) {
+ total_args_size += resp.lengths[i];
+ }
+
+ iovec iovs[2];
+ iovs[0].iov_base = &resp;
+ iovs[0].iov_len = sizeof(uint32_t) * (1 + resp.num_spans);
+
+ iovs[1].iov_base = shm_buffer_;
+ iovs[1].iov_len = total_args_size;
+
+ size_t iov_done = 0;
+ while (iov_done < 2) {
+ ssize_t r;
+ do {
+ r = writev(STDOUT_FILENO, &iovs[iov_done], 2 - iov_done);
+ } while (r == -1 && errno == EINTR);
+
+ if (r <= 0) {
+ return Error() << "Failed to write ACVP response to standard out";
+ }
+
+ size_t written = r;
+ for (size_t i = iov_done; i < 2 && written > 0; i++) {
+ iovec& iov = iovs[i];
+
+ size_t done = written;
+ if (done > iov.iov_len) {
+ done = iov.iov_len;
+ }
+
+ iov.iov_base = reinterpret_cast<uint8_t*>(iov.iov_base) + done;
+ iov.iov_len -= done;
+ written -= done;
+
+ if (iov.iov_len == 0) {
+ iov_done++;
+ }
+ }
+
+ assert(written == 0);
+ }
+
+ return {};
+}
+
+int main() {
+ for (;;) {
+ auto buffer = bssl::acvp::RequestBuffer::New();
+ auto args = bssl::acvp::ParseArgsFromFd(STDIN_FILENO, buffer.get());
+ if (args.empty()) {
+ ALOGE("Could not parse arguments\n");
+ return EXIT_FAILURE;
+ }
+
+ ModuleWrapper wrapper;
+ auto res = wrapper.SendMessage(args);
+ if (!res.ok()) {
+ std::cerr << res.error() << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ res = wrapper.ForwardResponse();
+ if (!res.ok()) {
+ std::cerr << res.error() << std::endl;
+ return EXIT_FAILURE;
+ }
+ }
+
+ return EXIT_SUCCESS;
+};