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;