blob: 0536d6abe684ef048c46e9f73fe77507793d01ab [file] [log] [blame]
Devin Moore133cb5e2020-07-07 16:31:22 -07001/*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#pragma once
18
Devin Mooreec271a72020-10-09 10:42:57 -070019#include <aidl/android/hardware/common/fmq/MQDescriptor.h>
20#include <aidl/android/hardware/common/fmq/SynchronizedReadWrite.h>
21#include <aidl/android/hardware/common/fmq/UnsynchronizedWrite.h>
Devin Moore133cb5e2020-07-07 16:31:22 -070022#include <cutils/native_handle.h>
23#include <fmq/AidlMQDescriptorShim.h>
24#include <fmq/MessageQueueBase.h>
25#include <utils/Log.h>
Devin Moore1b2d0a62020-09-22 17:20:54 +000026#include <type_traits>
Devin Moore133cb5e2020-07-07 16:31:22 -070027
Devin Moore7c04cfe2020-08-17 14:37:13 -070028namespace android {
29
Devin Mooreec271a72020-10-09 10:42:57 -070030using aidl::android::hardware::common::fmq::MQDescriptor;
31using aidl::android::hardware::common::fmq::SynchronizedReadWrite;
32using aidl::android::hardware::common::fmq::UnsynchronizedWrite;
Devin Moore133cb5e2020-07-07 16:31:22 -070033using android::details::AidlMQDescriptorShim;
34using android::hardware::MQFlavor;
35
Devin Moore1b2d0a62020-09-22 17:20:54 +000036template <typename T>
37struct FlavorTypeToValue;
38
39template <>
40struct FlavorTypeToValue<SynchronizedReadWrite> {
41 static constexpr MQFlavor value = hardware::kSynchronizedReadWrite;
42};
43
44template <>
45struct FlavorTypeToValue<UnsynchronizedWrite> {
46 static constexpr MQFlavor value = hardware::kUnsynchronizedWrite;
47};
48
Devin Moore133cb5e2020-07-07 16:31:22 -070049typedef uint64_t RingBufferPosition;
50
Devin Mooreb9280aa2020-09-18 16:40:51 -070051/*
52 * AIDL parcelables will have the typedef fixed_size. It is std::true_type when the
53 * parcelable is annotated with @FixedSize, and std::false_type when not. Other types
54 * should not have the fixed_size typedef, so they will always resolve to std::false_type.
55 */
56template <typename T, typename = void>
57struct has_typedef_fixed_size : std::false_type {};
58
59template <typename T>
60struct has_typedef_fixed_size<T, std::void_t<typename T::fixed_size>> : T::fixed_size {};
61
Devin Moore598bcc72020-10-13 10:49:36 -070062#define STATIC_AIDL_TYPE_CHECK(T) \
63 static_assert(has_typedef_fixed_size<T>::value == true || std::is_fundamental<T>::value || \
64 std::is_enum<T>::value, \
65 "Only fundamental types, enums, and AIDL parcelables annotated with @FixedSize " \
66 "and built for the NDK backend are supported as payload types(T).");
67
Devin Moore1b2d0a62020-09-22 17:20:54 +000068template <typename T, typename U>
69struct AidlMessageQueue final
70 : public MessageQueueBase<AidlMQDescriptorShim, T, FlavorTypeToValue<U>::value> {
Devin Moore598bcc72020-10-13 10:49:36 -070071 STATIC_AIDL_TYPE_CHECK(T);
Devin Moore1b2d0a62020-09-22 17:20:54 +000072 typedef AidlMQDescriptorShim<T, FlavorTypeToValue<U>::value> Descriptor;
Devin Moore133cb5e2020-07-07 16:31:22 -070073 /**
74 * This constructor uses the external descriptor used with AIDL interfaces.
75 * It will create an FMQ based on the descriptor that was obtained from
76 * another FMQ instance for communication.
77 *
78 * @param desc Descriptor from another FMQ that contains all of the
79 * information required to create a new instance of that queue.
80 * @param resetPointers Boolean indicating whether the read/write pointers
81 * should be reset or not.
82 */
Devin Moore1b2d0a62020-09-22 17:20:54 +000083 AidlMessageQueue(const MQDescriptor<T, U>& desc, bool resetPointers = true);
Devin Moore133cb5e2020-07-07 16:31:22 -070084 ~AidlMessageQueue() = default;
85
86 /**
87 * This constructor uses Ashmem shared memory to create an FMQ
88 * that can contain a maximum of 'numElementsInQueue' elements of type T.
89 *
90 * @param numElementsInQueue Capacity of the AidlMessageQueue in terms of T.
91 * @param configureEventFlagWord Boolean that specifies if memory should
92 * also be allocated and mapped for an EventFlag word.
Devin Moored7e702b2021-01-18 16:10:37 -080093 * @param bufferFd User-supplied file descriptor to map the memory for the ringbuffer
94 * By default, bufferFd=-1 means library will allocate ashmem region for ringbuffer.
95 * MessageQueue takes ownership of the file descriptor.
96 * @param bufferSize size of buffer in bytes that bufferFd represents. This
97 * size must be larger than or equal to (numElementsInQueue * sizeof(T)).
98 * Otherwise, operations will cause out-of-bounds memory access.
Devin Moore133cb5e2020-07-07 16:31:22 -070099 */
Devin Moored7e702b2021-01-18 16:10:37 -0800100 AidlMessageQueue(size_t numElementsInQueue, bool configureEventFlagWord,
101 android::base::unique_fd bufferFd, size_t bufferSize);
102
103 AidlMessageQueue(size_t numElementsInQueue, bool configureEventFlagWord = false)
104 : AidlMessageQueue(numElementsInQueue, configureEventFlagWord, android::base::unique_fd(),
105 0) {}
106
Devin Moore1b2d0a62020-09-22 17:20:54 +0000107 MQDescriptor<T, U> dupeDesc();
Devin Moore133cb5e2020-07-07 16:31:22 -0700108
109 private:
110 AidlMessageQueue(const AidlMessageQueue& other) = delete;
111 AidlMessageQueue& operator=(const AidlMessageQueue& other) = delete;
112 AidlMessageQueue() = delete;
113};
114
Devin Moore1b2d0a62020-09-22 17:20:54 +0000115template <typename T, typename U>
116AidlMessageQueue<T, U>::AidlMessageQueue(const MQDescriptor<T, U>& desc, bool resetPointers)
117 : MessageQueueBase<AidlMQDescriptorShim, T, FlavorTypeToValue<U>::value>(Descriptor(desc),
118 resetPointers) {}
Devin Moore133cb5e2020-07-07 16:31:22 -0700119
Devin Moore1b2d0a62020-09-22 17:20:54 +0000120template <typename T, typename U>
Devin Moored7e702b2021-01-18 16:10:37 -0800121AidlMessageQueue<T, U>::AidlMessageQueue(size_t numElementsInQueue, bool configureEventFlagWord,
122 android::base::unique_fd bufferFd, size_t bufferSize)
Devin Moore1b2d0a62020-09-22 17:20:54 +0000123 : MessageQueueBase<AidlMQDescriptorShim, T, FlavorTypeToValue<U>::value>(
Devin Moored7e702b2021-01-18 16:10:37 -0800124 numElementsInQueue, configureEventFlagWord, std::move(bufferFd), bufferSize) {}
Devin Moore133cb5e2020-07-07 16:31:22 -0700125
Devin Moore1b2d0a62020-09-22 17:20:54 +0000126template <typename T, typename U>
127MQDescriptor<T, U> AidlMessageQueue<T, U>::dupeDesc() {
128 auto* shim = MessageQueueBase<AidlMQDescriptorShim, T, FlavorTypeToValue<U>::value>::getDesc();
Devin Moore133cb5e2020-07-07 16:31:22 -0700129 if (shim) {
Devin Mooreec271a72020-10-09 10:42:57 -0700130 std::vector<aidl::android::hardware::common::fmq::GrantorDescriptor> grantors;
Devin Moore7c04cfe2020-08-17 14:37:13 -0700131 for (const auto& grantor : shim->grantors()) {
Devin Mooreec271a72020-10-09 10:42:57 -0700132 grantors.push_back(aidl::android::hardware::common::fmq::GrantorDescriptor{
Devin Moored7e702b2021-01-18 16:10:37 -0800133 .fdIndex = static_cast<int32_t>(grantor.fdIndex),
Devin Moore7c04cfe2020-08-17 14:37:13 -0700134 .offset = static_cast<int32_t>(grantor.offset),
135 .extent = static_cast<int64_t>(grantor.extent)});
136 }
Devin Moored7e702b2021-01-18 16:10:37 -0800137 std::vector<ndk::ScopedFileDescriptor> fds;
138 std::vector<int> ints;
139 int data_index = 0;
140 for (; data_index < shim->handle()->numFds; data_index++) {
141 fds.push_back(ndk::ScopedFileDescriptor(dup(shim->handle()->data[data_index])));
142 }
143 for (; data_index < shim->handle()->numFds + shim->handle()->numInts; data_index++) {
144 ints.push_back(shim->handle()->data[data_index]);
145 }
Devin Moore1b2d0a62020-09-22 17:20:54 +0000146 return MQDescriptor<T, U>{
Devin Moore133cb5e2020-07-07 16:31:22 -0700147 .quantum = static_cast<int32_t>(shim->getQuantum()),
Devin Moore7c04cfe2020-08-17 14:37:13 -0700148 .grantors = grantors,
149 .flags = static_cast<int32_t>(shim->getFlags()),
Devin Moored7e702b2021-01-18 16:10:37 -0800150 .handle = {std::move(fds), std::move(ints)},
Devin Moore133cb5e2020-07-07 16:31:22 -0700151 };
152 } else {
Devin Moore1b2d0a62020-09-22 17:20:54 +0000153 return MQDescriptor<T, U>();
Devin Moore133cb5e2020-07-07 16:31:22 -0700154 }
155}
156
157} // namespace android