1/*
2 * Copyright (C) 2016 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#include "FmqType.h"
18
19#include "HidlTypeAssertion.h"
20
21#include <hidl-util/Formatter.h>
22#include <android-base/logging.h>
23
24namespace android {
25
26FmqType::FmqType(const char *nsp, const char *name)
27    : mNamespace(nsp), mName(name) {
28}
29
30void FmqType::addNamedTypesToSet(std::set<const FQName> &) const {
31    // do nothing
32}
33
34std::string FmqType::fullName() const {
35    return mNamespace +
36            (mNamespace.empty() ? "" : "::") +
37            mName + "<" + mElementType->getCppStackType(true) + ">";
38}
39
40std::string FmqType::getCppType(
41        StorageMode mode,
42        bool) const {
43
44    const std::string base = fullName();
45
46    switch (mode) {
47        case StorageMode_Stack:
48            return base;
49
50        case StorageMode_Argument:
51            return "const " + base + "&";
52
53        case StorageMode_Result:
54            return "const " + base + "*";
55    }
56}
57
58void FmqType::emitReaderWriter(
59        Formatter &out,
60        const std::string &name,
61        const std::string &parcelObj,
62        bool parcelObjIsPointer,
63        bool isReader,
64        ErrorMode mode) const {
65    const std::string parentName = "_hidl_" + name + "_parent";
66
67    out << "size_t " << parentName << ";\n\n";
68
69    const std::string parcelObjDeref =
70        parcelObj + (parcelObjIsPointer ? "->" : ".");
71
72    if (isReader) {
73        out << "_hidl_err = "
74            << parcelObjDeref
75            << "readBuffer("
76            << "sizeof(*"
77            << name
78            << "), &"
79            << parentName
80            << ", "
81            << " reinterpret_cast<const void **>("
82            << "&" << name
83            << "));\n\n";
84
85        handleError(out, mode);
86    } else {
87        out << "_hidl_err = "
88            << parcelObjDeref
89            << "writeBuffer(&"
90            << name
91            << ", sizeof("
92            << name
93            << "), &"
94            << parentName
95            << ");\n";
96
97        handleError(out, mode);
98    }
99
100    emitReaderWriterEmbedded(
101            out,
102            0 /* depth */,
103            name,
104            name /* sanitizedName */,
105            isReader /* nameIsPointer */,
106            parcelObj,
107            parcelObjIsPointer,
108            isReader,
109            mode,
110            parentName,
111            "0 /* parentOffset */");
112}
113
114void FmqType::emitReaderWriterEmbedded(
115        Formatter &out,
116        size_t /* depth */,
117        const std::string &name,
118        const std::string & /* sanitizedName */,
119        bool nameIsPointer,
120        const std::string &parcelObj,
121        bool parcelObjIsPointer,
122        bool isReader,
123        ErrorMode mode,
124        const std::string &parentName,
125        const std::string &offsetText) const {
126    emitReaderWriterEmbeddedForTypeName(
127            out,
128            name,
129            nameIsPointer,
130            parcelObj,
131            parcelObjIsPointer,
132            isReader,
133            mode,
134            parentName,
135            offsetText,
136            fullName(),
137            "" /* childName */,
138            mNamespace);
139}
140
141bool FmqType::isJavaCompatible() const {
142    return false;
143}
144
145// All MQDescriptor<T, flavor> have the same size.
146static HidlTypeAssertion assertion(
147        "MQDescriptor<char, ::android::hardware::kSynchronizedReadWrite>", 32);
148
149void FmqType::getAlignmentAndSize(
150        size_t *align, size_t *size) const {
151    *align = 8;  // MQDescriptor<>
152    *size = assertion.size();
153}
154
155bool FmqType::needsEmbeddedReadWrite() const {
156    return true;
157}
158
159bool FmqType::resultNeedsDeref() const {
160    return true;
161}
162
163bool FmqType::isCompatibleElementType(Type *elementType) const {
164    return (!elementType->isInterface() && !elementType->needsEmbeddedReadWrite());
165}
166
167std::string FmqType::getVtsType() const {
168    if (mName == "MQDescriptorSync") {
169        return "TYPE_FMQ_SYNC";
170    } else if (mName == "MQDescriptorUnsync") {
171        return "TYPE_FMQ_UNSYNC";
172    } else {
173        LOG(ERROR) << "Invalid fmq type name.\n";
174    }
175    return "";
176}
177
178std::string FmqType::getVtsValueName() const {
179    return "fmq_value";
180}
181}  // namespace android
182
183