blob: 6534ebe7ff29d754950f831d2669c329162619fa [file] [log] [blame]
Devin Moore598bcc72020-10-13 10:49:36 -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#pragma once
17
18#include <aidl/android/hardware/common/fmq/MQDescriptor.h>
19#include <aidl/android/hardware/common/fmq/SynchronizedReadWrite.h>
20#include <aidl/android/hardware/common/fmq/UnsynchronizedWrite.h>
21#include <cutils/native_handle.h>
22#include <fmq/AidlMessageQueue.h>
23#include <hidl/MQDescriptor.h>
24
25namespace android {
26using aidl::android::hardware::common::fmq::GrantorDescriptor;
27using aidl::android::hardware::common::fmq::MQDescriptor;
28using hardware::details::logError;
29
30/**
31 * This function converts a HIDL hardware::MQDescriptor to an AIDL
32 * aidl::android::hardware::common::fmq::MQDescriptor for Fast
33 * Message Queue.
34 *
35 * This is considered UNSAFE because it is not checking the offsets of each of the
36 * paylod types' fields. In order for these objects to be passed through shared memory safely,
37 * they must have the exact same memory layout. Same size, same alignment, and same
38 * offsets for each field. Make sure this is the case before using this!
39 * Same sized C++ fundamental types and enums with same sized backing types are OK.
40 * Ex 1: uint64_t is compatible with int64_t
41 * Ex 2:
42 * @FixedSize parcelable Foo {
43 * int a;
44 * long b;
45 * MyEnum c; // backed by int32_t
46 * }
47 * struct Bar {
48 * int a;
49 * long b;
50 * YourEnum c; // backed by uint32_t
51 * }
52 * The two types above are compatible with each other as long as the fields have
53 * the same offsets.
54 *
55 * Template params:
56 * HidlPayload - the type of the payload used for the HIDL MessageQueue
57 * AidlPayload - the type of the payload used for the AIDL AidlMessageQueue
58 * AidlFlavor - the flavor of the queues. Either SynchronizedReadWrite,
59 * or UnsynchronizedWrite
60 * Function params:
61 * hidlDesc - reference to the HIDL MQDescriptor to be copied from
62 * aidlDesc - pointer to the AIDL MQDescriptor to be copied to
63 */
64template <typename HidlPayload, typename AidlPayload, typename AidlFlavor>
65bool unsafeHidlToAidlMQDescriptor(
66 const hardware::MQDescriptor<HidlPayload, FlavorTypeToValue<AidlFlavor>::value>& hidlDesc,
67 MQDescriptor<AidlPayload, AidlFlavor>* aidlDesc) {
68 static_assert(sizeof(HidlPayload) == sizeof(AidlPayload),
69 "Payload types are definitely incompatible");
70 static_assert(alignof(HidlPayload) == alignof(AidlPayload),
71 "Payload types are definitely incompatible");
72 STATIC_AIDL_TYPE_CHECK(AidlPayload);
73 if (!aidlDesc->grantors.empty()) {
74 logError("Destination AIDL MQDescriptor should be empty, but already contains grantors.");
75 return false;
76 }
Devin Moore598bcc72020-10-13 10:49:36 -070077
78 for (const auto& grantor : hidlDesc.grantors()) {
Devin Moored7e702b2021-01-18 16:10:37 -080079 if (static_cast<int32_t>(grantor.offset) < 0 || static_cast<int64_t>(grantor.extent) < 0 ||
80 static_cast<int64_t>(grantor.fdIndex) < 0) {
Devin Moore598bcc72020-10-13 10:49:36 -070081 logError(
82 "Unsafe static_cast of grantor fields. Either the hardware::MQDescriptor is "
83 "invalid, or the MessageQueue is too large to be described by AIDL.");
84 return false;
85 }
Devin Moore598bcc72020-10-13 10:49:36 -070086 aidlDesc->grantors.push_back(
Devin Moored7e702b2021-01-18 16:10:37 -080087 GrantorDescriptor{.fdIndex = static_cast<int32_t>(grantor.fdIndex),
88 .offset = static_cast<int32_t>(grantor.offset),
Devin Moore598bcc72020-10-13 10:49:36 -070089 .extent = static_cast<int64_t>(grantor.extent)});
90 }
91
Devin Moored7e702b2021-01-18 16:10:37 -080092 std::vector<ndk::ScopedFileDescriptor> fds;
93 std::vector<int> ints;
94 int data_index = 0;
95 for (; data_index < hidlDesc.handle()->numFds; data_index++) {
96 fds.push_back(ndk::ScopedFileDescriptor(dup(hidlDesc.handle()->data[data_index])));
97 }
98 for (; data_index < hidlDesc.handle()->numFds + hidlDesc.handle()->numInts; data_index++) {
99 ints.push_back(hidlDesc.handle()->data[data_index]);
100 }
101
102 aidlDesc->handle = {std::move(fds), std::move(ints)};
Devin Moore598bcc72020-10-13 10:49:36 -0700103 if (static_cast<int32_t>(hidlDesc.getQuantum()) < 0 ||
104 static_cast<int32_t>(hidlDesc.getFlags()) < 0) {
105 logError(
106 "Unsafe static_cast of quantum or flags. Either the hardware::MQDescriptor is "
107 "invalid, or the MessageQueue is too large to be described by AIDL.");
108 return false;
109 }
110 if (hidlDesc.getFlags() != FlavorTypeToValue<AidlFlavor>::value) {
111 logError("hardware::MQDescriptor hidlDesc is invalid. Unexpected getFlags() value: " +
112 std::to_string(hidlDesc.getFlags()) +
113 ". Expected value: " + std::to_string(FlavorTypeToValue<AidlFlavor>::value));
114 return false;
115 }
116 aidlDesc->quantum = static_cast<int32_t>(hidlDesc.getQuantum());
117 aidlDesc->flags = static_cast<int32_t>(hidlDesc.getFlags());
118 return true;
119}
120
121} // namespace android