Merge 'upstream/main' into 'main'
Change-Id: I8635f74165b24b9957a9889bbcffdb107d3ca0ef
Reviewed-on: https://fuchsia-review.googlesource.com/c/third_party/android.googlesource.com/platform/system/libfmq/+/1093250
Reviewed-by: Martin Puryear <mpuryear@google.com>
diff --git a/Android.bp b/Android.bp
index cd8c2b3..8b3a6e1 100644
--- a/Android.bp
+++ b/Android.bp
@@ -30,11 +30,7 @@
],
apex_available: [
"//apex_available:platform",
- "com.android.btservices",
- "com.android.media.swcodec",
- "com.android.neuralnetworks",
- "test_com.android.media.swcodec",
- "test_com.android.neuralnetworks",
+ "//apex_available:anyapex",
],
export_include_dirs: ["include"],
local_include_dirs: ["include"],
@@ -94,6 +90,7 @@
"-Werror",
],
vendor_available: true,
+ product_available: true,
min_sdk_version: "29",
host_supported: true,
}
@@ -104,6 +101,9 @@
crate_name: "fmq_bindgen",
edition: "2021",
host_supported: true,
+ vendor_available: true,
+ product_available: true,
+ visibility: [":__subpackages__"],
source_stem: "fmq",
bindgen_flags: [
"--no-recursive-allowlist",
@@ -184,9 +184,12 @@
],
}
-rust_library {
- name: "libfmq_rust",
+rust_defaults {
+ name: "libfmq_rust_defaults",
host_supported: true,
+ vendor_available: true,
+ product_available: true,
+ visibility: [":__subpackages__"],
crate_name: "fmq",
srcs: ["libfmq.rs"],
edition: "2021",
@@ -197,3 +200,16 @@
],
proc_macros: [],
}
+
+rust_library {
+ name: "libfmq_rust",
+ defaults: ["libfmq_rust_defaults"],
+}
+
+rust_test {
+ name: "libfmq_rust_unit_test",
+ defaults: ["libfmq_rust_defaults"],
+ test_options: {
+ unit_test: true,
+ },
+}
diff --git a/ErasedMessageQueue.cpp b/ErasedMessageQueue.cpp
index 7fb03aa..a0637fb 100644
--- a/ErasedMessageQueue.cpp
+++ b/ErasedMessageQueue.cpp
@@ -23,7 +23,7 @@
NativeHandle convertHandle(const int* fds, size_t n_fds, const int32_t* ints, size_t n_ints) {
std::vector<ndk::ScopedFileDescriptor> fdv;
for (size_t i = 0; i < n_fds; i++) {
- fdv.push_back(std::move(ndk::ScopedFileDescriptor(fds[i])));
+ fdv.push_back(std::move(ndk::ScopedFileDescriptor(dup(fds[i]))));
}
std::vector<int32_t> intv(ints, ints + n_ints);
@@ -112,6 +112,6 @@
return inner->commitRead(nMessages);
}
-ErasedMessageQueueDesc* ErasedMessageQueue::dupeDesc() {
+ErasedMessageQueueDesc* ErasedMessageQueue::dupeDesc() const {
return new ErasedMessageQueueDesc(inner->dupeDesc());
}
diff --git a/ErasedMessageQueue.hpp b/ErasedMessageQueue.hpp
index b3c4357..b4b5931 100644
--- a/ErasedMessageQueue.hpp
+++ b/ErasedMessageQueue.hpp
@@ -161,5 +161,5 @@
* @return ErasedMessageQueueDesc The copied descriptor, which must be freed
* by passing it to freeDesc.
*/
- ErasedMessageQueueDesc* dupeDesc();
+ ErasedMessageQueueDesc* dupeDesc() const;
};
diff --git a/benchmarks/Android.bp b/benchmarks/Android.bp
new file mode 100644
index 0000000..edb6701
--- /dev/null
+++ b/benchmarks/Android.bp
@@ -0,0 +1,43 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+ // See: http://go/android-license-faq
+ default_applicable_licenses: [
+ "Android-Apache-2.0",
+ ],
+ default_team: "trendy_team_testing",
+}
+
+cc_test {
+ name: "mq_benchmark_client",
+ srcs: ["msgq_benchmark_client.cpp"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ shared_libs: [
+ "android.hardware.tests.msgq@1.0",
+ "libbase",
+ "libcutils",
+ "libfmq",
+ "libhidlbase",
+ "libutils",
+ ],
+ required: [
+ "android.hardware.tests.msgq@1.0-impl",
+ ],
+}
diff --git a/benchmarks/Android.mk b/benchmarks/Android.mk
deleted file mode 100644
index 3cae117..0000000
--- a/benchmarks/Android.mk
+++ /dev/null
@@ -1,41 +0,0 @@
-#
-# Copyright (C) 2016 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := \
- msgq_benchmark_client.cpp
-
-LOCAL_CFLAGS := -Wall -Werror
-
-LOCAL_SHARED_LIBRARIES := \
- libbase \
- libcutils \
- libutils \
- libhidlbase
-
-LOCAL_REQUIRED_MODULES := android.hardware.tests.msgq@1.0-impl
-
-ifneq ($(TARGET_2ND_ARCH),)
-LOCAL_REQUIRED_MODULES += android.hardware.tests.msgq@1.0-impl:32
-endif
-
-LOCAL_SHARED_LIBRARIES += android.hardware.tests.msgq@1.0 libfmq
-LOCAL_MODULE := mq_benchmark_client
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-include $(BUILD_NATIVE_TEST)
diff --git a/include/fmq/AidlMessageQueue.h b/include/fmq/AidlMessageQueue.h
index 138760f..e4c3d84 100644
--- a/include/fmq/AidlMessageQueue.h
+++ b/include/fmq/AidlMessageQueue.h
@@ -115,7 +115,7 @@
android::base::unique_fd bufferFd, size_t bufferSize,
std::enable_if_t<std::is_same_v<V, MQErased>, size_t> quantum);
- MQDescriptor<T, U> dupeDesc();
+ MQDescriptor<T, U> dupeDesc() const;
private:
AidlMessageQueue(const AidlMessageQueue& other) = delete;
@@ -144,7 +144,7 @@
quantum) {}
template <typename T, typename U>
-MQDescriptor<T, U> AidlMessageQueue<T, U>::dupeDesc() {
+MQDescriptor<T, U> AidlMessageQueue<T, U>::dupeDesc() const {
auto* shim = MessageQueueBase<AidlMQDescriptorShim, T, FlavorTypeToValue<U>::value>::getDesc();
if (shim) {
std::vector<aidl::android::hardware::common::fmq::GrantorDescriptor> grantors;
diff --git a/libfmq.rs b/libfmq.rs
index a215a02..47c5c15 100644
--- a/libfmq.rs
+++ b/libfmq.rs
@@ -202,7 +202,7 @@
/// Obtain a copy of the MessageQueue's descriptor, which may be used to
/// access it remotely.
- pub fn dupe_desc(&mut self) -> MQDescriptor<T, SynchronizedReadWrite> {
+ pub fn dupe_desc(&self) -> MQDescriptor<T, SynchronizedReadWrite> {
// SAFETY: dupeDesc may be called on any valid ErasedMessageQueue; it
// simply forwards to dupeDesc on the inner AidlMessageQueue and wraps
// in a heap allocation.
@@ -242,10 +242,18 @@
// Calls to the descFoo accessors on erased_desc are sound because we know inner.dupeDesc
// returns a valid pointer to a new heap-allocated ErasedMessageQueueDesc.
let (grantors, fds, ints, quantum, flags) = unsafe {
- use std::slice::from_raw_parts;
- let grantors = from_raw_parts(descGrantors(erased_desc), descNumGrantors(erased_desc));
- let fds = from_raw_parts(descHandleFDs(erased_desc), descHandleNumFDs(erased_desc));
- let ints = from_raw_parts(descHandleInts(erased_desc), descHandleNumInts(erased_desc));
+ let grantors = slice_from_raw_parts_or_empty(
+ descGrantors(erased_desc),
+ descNumGrantors(erased_desc),
+ );
+ let fds = slice_from_raw_parts_or_empty(
+ descHandleFDs(erased_desc),
+ descHandleNumFDs(erased_desc),
+ );
+ let ints = slice_from_raw_parts_or_empty(
+ descHandleInts(erased_desc),
+ descHandleNumInts(erased_desc),
+ );
let quantum = descQuantum(erased_desc);
let flags = descFlags(erased_desc);
(grantors, fds, ints, quantum, flags)
@@ -290,6 +298,25 @@
}
}
+/// Forms a slice from a pointer and a length.
+///
+/// Returns an empty slice when `data` is a null pointer and `len` is zero.
+///
+/// # Safety
+///
+/// This function has the same safety requirements as [`std::slice::from_raw_parts`],
+/// but unlike that function, does not exhibit undefined behavior when `data` is a
+/// null pointer and `len` is zero. In this case, it returns an empty slice.
+unsafe fn slice_from_raw_parts_or_empty<'a, T>(data: *const T, len: usize) -> &'a [T] {
+ if data.is_null() && len == 0 {
+ &[]
+ } else {
+ // SAFETY: The caller must guarantee to satisfy the safety requirements
+ // of the standard library function [`std::slice::from_raw_parts`].
+ unsafe { std::slice::from_raw_parts(data, len) }
+ }
+}
+
#[inline(always)]
fn ptr<T: Share>(txn: &MemTransaction, idx: usize) -> *mut T {
let (base, region_idx) = if idx < txn.first.length {
@@ -433,3 +460,33 @@
unsafe { self.inner.beginRead(n, addr_of_mut!(txn)) }.then_some(txn)
}
}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn slice_from_raw_parts_or_empty_with_nonempty() {
+ const SLICE: &[u8] = &[1, 2, 3, 4, 5, 6];
+ // SAFETY: We are constructing a slice from the pointer and length of valid slice.
+ let from_raw_parts = unsafe {
+ let ptr = SLICE.as_ptr();
+ let len = SLICE.len();
+ slice_from_raw_parts_or_empty(ptr, len)
+ };
+ assert_eq!(SLICE, from_raw_parts);
+ }
+
+ #[test]
+ fn slice_from_raw_parts_or_empty_with_null_pointer_zero_length() {
+ // SAFETY: Calling `slice_from_raw_parts_or_empty` with a null pointer
+ // and a zero length is explicitly allowed by its safety requirements.
+ // In this case, `std::slice::from_raw_parts` has undefined behavior.
+ let empty_from_raw_parts = unsafe {
+ let ptr: *const u8 = std::ptr::null();
+ let len = 0;
+ slice_from_raw_parts_or_empty(ptr, len)
+ };
+ assert_eq!(&[] as &[u8], empty_from_raw_parts);
+ }
+}
diff --git a/tests/aidl/android/fmq/test/EventFlagBits.aidl b/tests/aidl/android/fmq/test/EventFlagBits.aidl
index 202a67c..1a9e44d 100644
--- a/tests/aidl/android/fmq/test/EventFlagBits.aidl
+++ b/tests/aidl/android/fmq/test/EventFlagBits.aidl
@@ -4,6 +4,6 @@
@Backing(type="int")
enum EventFlagBits {
- FMQ_NOT_EMPTY = 1 << 0,
- FMQ_NOT_FULL = 1 << 1,
+ FMQ_NOT_FULL = 1 << 0,
+ FMQ_NOT_EMPTY = 1 << 1,
}
diff --git a/tests/fmq_unit_tests.cpp b/tests/fmq_unit_tests.cpp
index e6774fd..c6b72ce 100644
--- a/tests/fmq_unit_tests.cpp
+++ b/tests/fmq_unit_tests.cpp
@@ -38,8 +38,8 @@
using android::hardware::kUnsynchronizedWrite;
enum EventFlagBits : uint32_t {
- kFmqNotEmpty = 1 << 0,
- kFmqNotFull = 1 << 1,
+ kFmqNotFull = 1 << 0,
+ kFmqNotEmpty = 1 << 1,
};
typedef android::AidlMessageQueue<uint8_t, SynchronizedReadWrite> AidlMessageQueueSync;
@@ -422,6 +422,8 @@
#if defined(__Fuchsia__)
GTEST_SKIP() << "This test counts fds using procfs, which does not exist on Fuchsia.";
#endif
+ // Write a log msg first to open the pmsg FD and socket to logd.
+ LOG(INFO) << "Nothin' to see here...";
// create/destroy a large number of queues that if we were leaking FDs
// we could detect it by looking at the number of FDs opened by the this
// test process.
diff --git a/tests/msgq_rust_test_client.rs b/tests/msgq_rust_test_client.rs
index bad57a7..a78000a 100644
--- a/tests/msgq_rust_test_client.rs
+++ b/tests/msgq_rust_test_client.rs
@@ -33,7 +33,7 @@
let num_elements_in_sync_queue: usize = (page_size - 16) / std::mem::size_of::<i32>();
/* Create a queue on the client side. */
- let mut mq = MessageQueue::<i32>::new(
+ let mq = MessageQueue::<i32>::new(
num_elements_in_sync_queue,
true, /* configure event flag word */
);
diff --git a/tests/msgq_test_client.cpp b/tests/msgq_test_client.cpp
index 53a971e..70de9dd 100644
--- a/tests/msgq_test_client.cpp
+++ b/tests/msgq_test_client.cpp
@@ -42,6 +42,12 @@
using ::aidl::android::fmq::test::FixedUnion;
using ::aidl::android::fmq::test::ITestAidlMsgQ;
using android::hardware::tests::msgq::V1_0::ITestMsgQ;
+static_assert(static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL) ==
+ static_cast<uint32_t>(EventFlagBits::FMQ_NOT_FULL),
+ "The AIDL and HIDL test interfaces must use the same values!");
+static_assert(static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY) ==
+ static_cast<uint32_t>(EventFlagBits::FMQ_NOT_EMPTY),
+ "The AIDL and HIDL test interfaces must use the same values!");
// libhidl
using android::hardware::isHidlSupported;