aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJooyung Han <jooyung@google.com>2021-11-17 01:41:11 +0900
committerJooyung Han <jooyung@google.com>2021-11-17 23:59:28 +0000
commit97be5845253b8a16d3448bd8cad2dd23b156732c (patch)
tree633478897d5b5955ee255f30cbe7587a50127fea
parent87c92e71f5edacb6c4424141d361f8d96e4ad440 (diff)
downloadaidl-97be5845253b8a16d3448bd8cad2dd23b156732c.tar.gz
Add @FixedSize union
@FixedSize union uses a custom implementation rather than std::variant so that its value can have a stable/fixed layout and be passed via FMQ. A custom implementation relies on the fact that @FixedSize union/parcelable should have "trivially copyable" fields. So we can't use it for union in general. It would be nice if we could replace std::variant with it and have the same implementation for union types. Maybe in the future. Bug: 206496560 Test: golden_test.sh check Test: aidl_integration_test (no regression) atest fmq_test fmq_unit_test Change-Id: I86351ecb1990818d0fe2faaad7c4b8c2c33881b5
-rw-r--r--Android.bp1
-rw-r--r--aidl_language.cpp5
-rw-r--r--aidl_to_cpp_common.cpp186
-rw-r--r--aidl_to_cpp_common.h3
-rw-r--r--generate_cpp.cpp5
-rw-r--r--generate_ndk.cpp3
-rw-r--r--tests/android/aidl/tests/FixedSize.aidl46
-rw-r--r--tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/FixedSize.cpp275
-rw-r--r--tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/FixedSize.cpp.d3
-rw-r--r--tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BnFixedSize.h1
-rw-r--r--tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BpFixedSize.h1
-rw-r--r--tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/FixedSize.h220
-rw-r--r--tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/FixedSize.java408
-rw-r--r--tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/FixedSize.java.d3
-rw-r--r--tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/FixedSize.cpp276
-rw-r--r--tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/FixedSize.cpp.d3
-rw-r--r--tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnFixedSize.h1
-rw-r--r--tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpFixedSize.h1
-rw-r--r--tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/FixedSize.h233
-rw-r--r--tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/FixedSize.rs224
-rw-r--r--tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/FixedSize.rs.d3
21 files changed, 1875 insertions, 26 deletions
diff --git a/Android.bp b/Android.bp
index c2bc2467..75678935 100644
--- a/Android.bp
+++ b/Android.bp
@@ -289,6 +289,7 @@ filegroup {
"tests/android/aidl/tests/DeprecatedEnum.aidl",
"tests/android/aidl/tests/DeprecatedParcelable.aidl",
"tests/android/aidl/tests/GenericStructuredParcelable.aidl",
+ "tests/android/aidl/tests/FixedSize.aidl",
"tests/android/aidl/tests/IDeprecated.aidl",
"tests/android/aidl/tests/INamedCallback.aidl",
"tests/android/aidl/tests/INewName.aidl",
diff --git a/aidl_language.cpp b/aidl_language.cpp
index b56e7ac5..e92086ae 100644
--- a/aidl_language.cpp
+++ b/aidl_language.cpp
@@ -160,7 +160,10 @@ const std::vector<AidlAnnotation::Schema>& AidlAnnotation::AllSchemas() {
CONTEXT_TYPE_STRUCTURED_PARCELABLE | CONTEXT_TYPE_UNION |
CONTEXT_TYPE_UNSTRUCTURED_PARCELABLE,
{}},
- {AidlAnnotation::Type::FIXED_SIZE, "FixedSize", CONTEXT_TYPE_STRUCTURED_PARCELABLE, {}},
+ {AidlAnnotation::Type::FIXED_SIZE,
+ "FixedSize",
+ CONTEXT_TYPE_STRUCTURED_PARCELABLE | CONTEXT_TYPE_UNION,
+ {}},
{AidlAnnotation::Type::DESCRIPTOR,
"Descriptor",
CONTEXT_TYPE_INTERFACE,
diff --git a/aidl_to_cpp_common.cpp b/aidl_to_cpp_common.cpp
index 3822f0e5..6a2f60ea 100644
--- a/aidl_to_cpp_common.cpp
+++ b/aidl_to_cpp_common.cpp
@@ -19,6 +19,7 @@
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
+#include <limits>
#include <set>
#include <unordered_map>
@@ -298,6 +299,39 @@ std::string TemplateDecl(const AidlParcelable& defined_type) {
void GenerateParcelableComparisonOperators(CodeWriter& out, const AidlParcelable& parcelable) {
std::set<string> operators{"<", ">", "==", ">=", "<=", "!="};
+
+ if (parcelable.AsUnionDeclaration() && parcelable.IsFixedSize()) {
+ auto name = parcelable.GetName();
+ auto max_tag = parcelable.GetFields().back()->GetName();
+ auto min_tag = parcelable.GetFields().front()->GetName();
+ auto tmpl = R"--(static int _cmp(const {name}& _lhs, const {name}& _rhs) {{
+ return _cmp_value(_lhs.getTag(), _rhs.getTag()) || _cmp_value_at<{max_tag}>(_lhs, _rhs);
+}}
+template <Tag _Tag>
+static int _cmp_value_at(const {name}& _lhs, const {name}& _rhs) {{
+ if constexpr (_Tag == {min_tag}) {{
+ return _cmp_value(_lhs.get<_Tag>(), _rhs.get<_Tag>());
+ }} else {{
+ return (_lhs.getTag() == _Tag)
+ ? _cmp_value(_lhs.get<_Tag>(), _rhs.get<_Tag>())
+ : _cmp_value_at<(Tag)(_Tag-1)>(_lhs, _rhs);
+ }}
+}}
+template <typename _Type>
+static int _cmp_value(const _Type& _lhs, const _Type& _rhs) {{
+ return (_lhs == _rhs) ? 0 : (_lhs < _rhs) ? -1 : 1;
+}}
+)--";
+ out << fmt::format(tmpl, fmt::arg("name", name), fmt::arg("min_tag", min_tag),
+ fmt::arg("max_tag", max_tag));
+ for (const auto& op : operators) {
+ out << "inline bool operator" << op << "(const " << name << "&_rhs) const {\n";
+ out << " return _cmp(*this, _rhs) " << op << " 0;\n";
+ out << "}\n";
+ }
+ return;
+ }
+
bool is_empty = false;
auto comparable = [&](const string& prefix) {
@@ -396,25 +430,94 @@ std::string GetDeprecatedAttribute(const AidlCommentable& type) {
return "";
}
-const vector<string> UnionWriter::headers{
- "cassert", // __assert for logging
- "type_traits", // std::is_same_v
- "utility", // std::mode/forward for value
- "variant", // std::variant for value
-};
+size_t AlignmentOf(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
+ static map<string, size_t> alignment = {
+ {"boolean", 1}, {"byte", 1}, {"char", 2}, {"double", 8},
+ {"float", 4}, {"int", 4}, {"long", 8},
+ };
+
+ string name = type.GetName();
+ if (auto enum_decl = typenames.GetEnumDeclaration(type); enum_decl) {
+ name = enum_decl->GetBackingType().GetName();
+ }
+ // default to 0 for parcelable types
+ return alignment[name];
+}
+
+std::set<std::string> UnionWriter::GetHeaders(const AidlUnionDecl& decl) {
+ std::set<std::string> union_headers = {
+ "cassert", // __assert for logging
+ "type_traits", // std::is_same_v
+ "utility", // std::mode/forward for value
+ "variant", // union's impl
+ };
+ if (decl.IsFixedSize()) {
+ union_headers.insert("tuple"); // fixed-sized union's typelist
+ }
+ return union_headers;
+}
+
+// fixed-sized union class looks like:
+// class Union {
+// public:
+// enum Tag : uint8_t {
+// field1 = 0,
+// field2,
+// };
+// ... methods ...
+// private:
+// Tag _tag;
+// union {
+// type1 field1;
+// type2 field2;
+// } _value;
+// };
void UnionWriter::PrivateFields(CodeWriter& out) const {
- vector<string> field_types;
- for (const auto& f : decl.GetFields()) {
- field_types.push_back(name_of(f->GetType(), typenames));
+ if (decl.IsFixedSize()) {
+ AIDL_FATAL_IF(decl.GetFields().empty(), decl) << "Union '" << decl.GetName() << "' is empty.";
+ const auto& first_field = decl.GetFields()[0];
+ const auto& default_name = first_field->GetName();
+ const auto& default_value = name_of(first_field->GetType(), typenames) + "(" +
+ first_field->ValueString(decorator) + ")";
+
+ out << "Tag _tag __attribute__((aligned (1))) = " << default_name << ";\n";
+ out << "union {\n";
+ out.Indent();
+ for (const auto& f : decl.GetFields()) {
+ const auto& fn = f->GetName();
+ out << name_of(f->GetType(), typenames) << " " << fn;
+ if (decl.IsFixedSize()) {
+ int alignment = AlignmentOf(f->GetType(), typenames);
+ if (alignment > 0) {
+ out << " __attribute__((aligned (" << std::to_string(alignment) << ")))";
+ }
+ }
+ if (fn == default_name) {
+ out << " = " << default_value;
+ }
+ out << ";\n";
+ }
+ out.Dedent();
+ out << "} _value;\n";
+ } else {
+ vector<string> field_types;
+ for (const auto& f : decl.GetFields()) {
+ field_types.push_back(name_of(f->GetType(), typenames));
+ }
+ out << "std::variant<" + Join(field_types, ", ") + "> _value;\n";
}
- out << "std::variant<" + Join(field_types, ", ") + "> _value;\n";
}
void UnionWriter::PublicFields(CodeWriter& out) const {
- auto tag_type = typenames.MakeResolvedType(AIDL_LOCATION_HERE, "int", /* is_array= */ false);
-
- out << "enum Tag : " << name_of(*tag_type, typenames) << " {\n";
+ std::string tag_type = "int32_t";
+ if (decl.IsFixedSize()) {
+ // For @FixedSize union, we use a smaller type for a tag to minimize the size overhead.
+ AIDL_FATAL_IF(decl.GetFields().size() > std::numeric_limits<uint8_t>::max(), decl)
+ << "Too many fields for @FixedSize";
+ tag_type = "uint8_t";
+ }
+ out << "enum Tag : " << tag_type << " {\n";
bool is_first = true;
for (const auto& f : decl.GetFields()) {
out << " " << f->GetName();
@@ -427,13 +530,49 @@ void UnionWriter::PublicFields(CodeWriter& out) const {
const auto& name = decl.GetName();
- AIDL_FATAL_IF(decl.GetFields().empty(), decl) << "Union '" << name << "' is empty.";
- const auto& first_field = decl.GetFields()[0];
- const auto& default_name = first_field->GetName();
- const auto& default_value =
- name_of(first_field->GetType(), typenames) + "(" + first_field->ValueString(decorator) + ")";
+ if (decl.IsFixedSize()) {
+ vector<string> field_types;
+ for (const auto& f : decl.GetFields()) {
+ field_types.push_back(name_of(f->GetType(), typenames));
+ }
+ auto typelist = Join(field_types, ", ");
+ auto tmpl = R"--(
+template <Tag _Tag>
+using _at = typename std::tuple_element<_Tag, std::tuple<{typelist}>>::type;
+template <Tag _Tag, typename _Type>
+static {name} make(_Type&& _arg) {{
+ {name} _inst;
+ _inst.set<_Tag>(std::forward<_Type>(_arg));
+ return _inst;
+}}
+constexpr Tag getTag() const {{
+ return _tag;
+}}
+template <Tag _Tag>
+const _at<_Tag>& get() const {{
+ if (_Tag != _tag) {{ __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, "bad access: a wrong tag"); }}
+ return *(_at<_Tag>*)(&_value);
+}}
+template <Tag _Tag>
+_at<_Tag>& get() {{
+ if (_Tag != _tag) {{ __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, "bad access: a wrong tag"); }}
+ return *(_at<_Tag>*)(&_value);
+}}
+template <Tag _Tag, typename _Type>
+void set(_Type&& _arg) {{
+ _tag = _Tag;
+ get<_Tag>() = std::forward<_Type>(_arg);
+}}
+)--";
+ out << fmt::format(tmpl, fmt::arg("name", name), fmt::arg("typelist", typelist));
+ } else {
+ AIDL_FATAL_IF(decl.GetFields().empty(), decl) << "Union '" << name << "' is empty.";
+ const auto& first_field = decl.GetFields()[0];
+ const auto& default_name = first_field->GetName();
+ const auto& default_value = name_of(first_field->GetType(), typenames) + "(" +
+ first_field->ValueString(decorator) + ")";
- auto tmpl = R"--(
+ auto tmpl = R"--(
template<typename _Tp>
static constexpr bool _not_self = !std::is_same_v<std::remove_cv_t<std::remove_reference_t<_Tp>>, {name}>;
@@ -480,11 +619,14 @@ void set(_Tp&&... _args) {{
}}
)--";
- out << fmt::format(tmpl, fmt::arg("name", name), fmt::arg("default_name", default_name),
- fmt::arg("default_value", default_value));
+ out << fmt::format(tmpl, fmt::arg("name", name), fmt::arg("default_name", default_name),
+ fmt::arg("default_value", default_value));
+ }
}
void UnionWriter::ReadFromParcel(CodeWriter& out, const ParcelWriterContext& ctx) const {
+ // Even though @FixedSize union may use a smaller type than int32_t, we need to read/write it
+ // as if it is int32_t for compatibility with other bckends.
auto tag_type = typenames.MakeResolvedType(AIDL_LOCATION_HERE, "int", /* is_array= */ false);
const string tag = "_aidl_tag";
@@ -527,6 +669,8 @@ void UnionWriter::ReadFromParcel(CodeWriter& out, const ParcelWriterContext& ctx
}
void UnionWriter::WriteToParcel(CodeWriter& out, const ParcelWriterContext& ctx) const {
+ // Even though @FixedSize union may use a smaller type than int32_t, we need to read/write it
+ // as if it is int32_t for compatibility with other bckends.
auto tag_type = typenames.MakeResolvedType(AIDL_LOCATION_HERE, "int", /* is_array= */ false);
const string tag = "_aidl_tag";
diff --git a/aidl_to_cpp_common.h b/aidl_to_cpp_common.h
index df657cee..e639a7c5 100644
--- a/aidl_to_cpp_common.h
+++ b/aidl_to_cpp_common.h
@@ -114,7 +114,8 @@ struct UnionWriter {
const AidlTypenames& typenames;
const std::function<std::string(const AidlTypeSpecifier&, const AidlTypenames&)> name_of;
const ::ConstantValueDecorator& decorator;
- static const std::vector<std::string> headers;
+
+ static std::set<std::string> GetHeaders(const AidlUnionDecl&);
void PrivateFields(CodeWriter& out) const;
void PublicFields(CodeWriter& out) const;
diff --git a/generate_cpp.cpp b/generate_cpp.cpp
index c7a36ae2..f3c29576 100644
--- a/generate_cpp.cpp
+++ b/generate_cpp.cpp
@@ -1229,9 +1229,10 @@ void GenerateHeaderIncludes(CodeWriter& out, const AidlDefinedType& defined_type
includes.insert("tuple"); // std::tie in comparison operators
}
- void Visit(const AidlUnionDecl&) override {
+ void Visit(const AidlUnionDecl& union_decl) override {
AddParcelableCommonHeaders();
- includes.insert(std::begin(UnionWriter::headers), std::end(UnionWriter::headers));
+ auto union_headers = cpp::UnionWriter::GetHeaders(union_decl);
+ includes.insert(std::begin(union_headers), std::end(union_headers));
}
void Visit(const AidlEnumDeclaration&) override {
diff --git a/generate_ndk.cpp b/generate_ndk.cpp
index 2af14a07..0863149f 100644
--- a/generate_ndk.cpp
+++ b/generate_ndk.cpp
@@ -310,7 +310,8 @@ void GenerateHeaderIncludes(CodeWriter& out, const AidlTypenames& types,
includes.insert("android/binder_interface_utils.h");
includes.insert("android/binder_parcelable_utils.h");
includes.insert("android/binder_to_string.h"); // used by toString()
- includes.insert(std::begin(cpp::UnionWriter::headers), std::end(cpp::UnionWriter::headers));
+ auto union_headers = cpp::UnionWriter::GetHeaders(union_decl);
+ includes.insert(std::begin(union_headers), std::end(union_headers));
}
void Visit(const AidlEnumDeclaration& enum_decl) override {
diff --git a/tests/android/aidl/tests/FixedSize.aidl b/tests/android/aidl/tests/FixedSize.aidl
new file mode 100644
index 00000000..295199f3
--- /dev/null
+++ b/tests/android/aidl/tests/FixedSize.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 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 android.aidl.tests;
+
+import android.aidl.tests.LongEnum;
+
+parcelable FixedSize {
+ @FixedSize
+ parcelable FixedParcelable {
+ boolean booleanValue;
+ byte byteValue;
+ char charValue;
+ int intValue;
+ long longValue;
+ float floatValue;
+ double doubleValue;
+ LongEnum enumValue = LongEnum.FOO;
+ FixedUnion parcelableValue;
+ }
+
+ @FixedSize
+ union FixedUnion {
+ boolean booleanValue = false;
+ byte byteValue;
+ char charValue;
+ int intValue;
+ long longValue;
+ float floatValue;
+ double doubleValue;
+ LongEnum enumValue;
+ }
+}
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/FixedSize.cpp b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/FixedSize.cpp
new file mode 100644
index 00000000..5ccbcee4
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/FixedSize.cpp
@@ -0,0 +1,275 @@
+#include <android/aidl/tests/FixedSize.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+::android::status_t FixedSize::readFromParcel(const ::android::Parcel* _aidl_parcel) {
+ ::android::status_t _aidl_ret_status = ::android::OK;
+ [[maybe_unused]] size_t _aidl_start_pos = _aidl_parcel->dataPosition();
+ int32_t _aidl_parcelable_raw_size = _aidl_parcel->readInt32();
+ if (_aidl_parcelable_raw_size < 0) return ::android::BAD_VALUE;
+ [[maybe_unused]] size_t _aidl_parcelable_size = static_cast<size_t>(_aidl_parcelable_raw_size);
+ if (_aidl_start_pos > SIZE_MAX - _aidl_parcelable_size) return ::android::BAD_VALUE;
+ _aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size);
+ return _aidl_ret_status;
+}
+::android::status_t FixedSize::writeToParcel(::android::Parcel* _aidl_parcel) const {
+ ::android::status_t _aidl_ret_status = ::android::OK;
+ auto _aidl_start_pos = _aidl_parcel->dataPosition();
+ _aidl_parcel->writeInt32(0);
+ auto _aidl_end_pos = _aidl_parcel->dataPosition();
+ _aidl_parcel->setDataPosition(_aidl_start_pos);
+ _aidl_parcel->writeInt32(_aidl_end_pos - _aidl_start_pos);
+ _aidl_parcel->setDataPosition(_aidl_end_pos);
+ return _aidl_ret_status;
+}
+} // namespace tests
+} // namespace aidl
+} // namespace android
+#include <android/aidl/tests/FixedSize.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+::android::status_t FixedSize::FixedParcelable::readFromParcel(const ::android::Parcel* _aidl_parcel) {
+ ::android::status_t _aidl_ret_status = ::android::OK;
+ [[maybe_unused]] size_t _aidl_start_pos = _aidl_parcel->dataPosition();
+ int32_t _aidl_parcelable_raw_size = _aidl_parcel->readInt32();
+ if (_aidl_parcelable_raw_size < 0) return ::android::BAD_VALUE;
+ [[maybe_unused]] size_t _aidl_parcelable_size = static_cast<size_t>(_aidl_parcelable_raw_size);
+ if (_aidl_start_pos > SIZE_MAX - _aidl_parcelable_size) return ::android::BAD_VALUE;
+ if (_aidl_parcel->dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) {
+ _aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size);
+ return _aidl_ret_status;
+ }
+ _aidl_ret_status = _aidl_parcel->readBool(&booleanValue);
+ if (((_aidl_ret_status) != (::android::OK))) {
+ return _aidl_ret_status;
+ }
+ if (_aidl_parcel->dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) {
+ _aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size);
+ return _aidl_ret_status;
+ }
+ _aidl_ret_status = _aidl_parcel->readByte(&byteValue);
+ if (((_aidl_ret_status) != (::android::OK))) {
+ return _aidl_ret_status;
+ }
+ if (_aidl_parcel->dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) {
+ _aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size);
+ return _aidl_ret_status;
+ }
+ _aidl_ret_status = _aidl_parcel->readChar(&charValue);
+ if (((_aidl_ret_status) != (::android::OK))) {
+ return _aidl_ret_status;
+ }
+ if (_aidl_parcel->dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) {
+ _aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size);
+ return _aidl_ret_status;
+ }
+ _aidl_ret_status = _aidl_parcel->readInt32(&intValue);
+ if (((_aidl_ret_status) != (::android::OK))) {
+ return _aidl_ret_status;
+ }
+ if (_aidl_parcel->dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) {
+ _aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size);
+ return _aidl_ret_status;
+ }
+ _aidl_ret_status = _aidl_parcel->readInt64(&longValue);
+ if (((_aidl_ret_status) != (::android::OK))) {
+ return _aidl_ret_status;
+ }
+ if (_aidl_parcel->dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) {
+ _aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size);
+ return _aidl_ret_status;
+ }
+ _aidl_ret_status = _aidl_parcel->readFloat(&floatValue);
+ if (((_aidl_ret_status) != (::android::OK))) {
+ return _aidl_ret_status;
+ }
+ if (_aidl_parcel->dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) {
+ _aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size);
+ return _aidl_ret_status;
+ }
+ _aidl_ret_status = _aidl_parcel->readDouble(&doubleValue);
+ if (((_aidl_ret_status) != (::android::OK))) {
+ return _aidl_ret_status;
+ }
+ if (_aidl_parcel->dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) {
+ _aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size);
+ return _aidl_ret_status;
+ }
+ _aidl_ret_status = _aidl_parcel->readInt64(reinterpret_cast<int64_t *>(&enumValue));
+ if (((_aidl_ret_status) != (::android::OK))) {
+ return _aidl_ret_status;
+ }
+ if (_aidl_parcel->dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) {
+ _aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size);
+ return _aidl_ret_status;
+ }
+ _aidl_ret_status = _aidl_parcel->readParcelable(&parcelableValue);
+ if (((_aidl_ret_status) != (::android::OK))) {
+ return _aidl_ret_status;
+ }
+ _aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size);
+ return _aidl_ret_status;
+}
+::android::status_t FixedSize::FixedParcelable::writeToParcel(::android::Parcel* _aidl_parcel) const {
+ ::android::status_t _aidl_ret_status = ::android::OK;
+ auto _aidl_start_pos = _aidl_parcel->dataPosition();
+ _aidl_parcel->writeInt32(0);
+ _aidl_ret_status = _aidl_parcel->writeBool(booleanValue);
+ if (((_aidl_ret_status) != (::android::OK))) {
+ return _aidl_ret_status;
+ }
+ _aidl_ret_status = _aidl_parcel->writeByte(byteValue);
+ if (((_aidl_ret_status) != (::android::OK))) {
+ return _aidl_ret_status;
+ }
+ _aidl_ret_status = _aidl_parcel->writeChar(charValue);
+ if (((_aidl_ret_status) != (::android::OK))) {
+ return _aidl_ret_status;
+ }
+ _aidl_ret_status = _aidl_parcel->writeInt32(intValue);
+ if (((_aidl_ret_status) != (::android::OK))) {
+ return _aidl_ret_status;
+ }
+ _aidl_ret_status = _aidl_parcel->writeInt64(longValue);
+ if (((_aidl_ret_status) != (::android::OK))) {
+ return _aidl_ret_status;
+ }
+ _aidl_ret_status = _aidl_parcel->writeFloat(floatValue);
+ if (((_aidl_ret_status) != (::android::OK))) {
+ return _aidl_ret_status;
+ }
+ _aidl_ret_status = _aidl_parcel->writeDouble(doubleValue);
+ if (((_aidl_ret_status) != (::android::OK))) {
+ return _aidl_ret_status;
+ }
+ _aidl_ret_status = _aidl_parcel->writeInt64(static_cast<int64_t>(enumValue));
+ if (((_aidl_ret_status) != (::android::OK))) {
+ return _aidl_ret_status;
+ }
+ _aidl_ret_status = _aidl_parcel->writeParcelable(parcelableValue);
+ if (((_aidl_ret_status) != (::android::OK))) {
+ return _aidl_ret_status;
+ }
+ auto _aidl_end_pos = _aidl_parcel->dataPosition();
+ _aidl_parcel->setDataPosition(_aidl_start_pos);
+ _aidl_parcel->writeInt32(_aidl_end_pos - _aidl_start_pos);
+ _aidl_parcel->setDataPosition(_aidl_end_pos);
+ return _aidl_ret_status;
+}
+} // namespace tests
+} // namespace aidl
+} // namespace android
+#include <android/aidl/tests/FixedSize.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+::android::status_t FixedSize::FixedUnion::readFromParcel(const ::android::Parcel* _aidl_parcel) {
+ ::android::status_t _aidl_ret_status;
+ int32_t _aidl_tag;
+ if ((_aidl_ret_status = _aidl_parcel->readInt32(&_aidl_tag)) != ::android::OK) return _aidl_ret_status;
+ switch (_aidl_tag) {
+ case booleanValue: {
+ bool _aidl_value;
+ if ((_aidl_ret_status = _aidl_parcel->readBool(&_aidl_value)) != ::android::OK) return _aidl_ret_status;
+ if constexpr (std::is_trivially_copyable_v<bool>) {
+ set<booleanValue>(_aidl_value);
+ } else {
+ // NOLINTNEXTLINE(performance-move-const-arg)
+ set<booleanValue>(std::move(_aidl_value));
+ }
+ return ::android::OK; }
+ case byteValue: {
+ int8_t _aidl_value;
+ if ((_aidl_ret_status = _aidl_parcel->readByte(&_aidl_value)) != ::android::OK) return _aidl_ret_status;
+ if constexpr (std::is_trivially_copyable_v<int8_t>) {
+ set<byteValue>(_aidl_value);
+ } else {
+ // NOLINTNEXTLINE(performance-move-const-arg)
+ set<byteValue>(std::move(_aidl_value));
+ }
+ return ::android::OK; }
+ case charValue: {
+ char16_t _aidl_value;
+ if ((_aidl_ret_status = _aidl_parcel->readChar(&_aidl_value)) != ::android::OK) return _aidl_ret_status;
+ if constexpr (std::is_trivially_copyable_v<char16_t>) {
+ set<charValue>(_aidl_value);
+ } else {
+ // NOLINTNEXTLINE(performance-move-const-arg)
+ set<charValue>(std::move(_aidl_value));
+ }
+ return ::android::OK; }
+ case intValue: {
+ int32_t _aidl_value;
+ if ((_aidl_ret_status = _aidl_parcel->readInt32(&_aidl_value)) != ::android::OK) return _aidl_ret_status;
+ if constexpr (std::is_trivially_copyable_v<int32_t>) {
+ set<intValue>(_aidl_value);
+ } else {
+ // NOLINTNEXTLINE(performance-move-const-arg)
+ set<intValue>(std::move(_aidl_value));
+ }
+ return ::android::OK; }
+ case longValue: {
+ int64_t _aidl_value;
+ if ((_aidl_ret_status = _aidl_parcel->readInt64(&_aidl_value)) != ::android::OK) return _aidl_ret_status;
+ if constexpr (std::is_trivially_copyable_v<int64_t>) {
+ set<longValue>(_aidl_value);
+ } else {
+ // NOLINTNEXTLINE(performance-move-const-arg)
+ set<longValue>(std::move(_aidl_value));
+ }
+ return ::android::OK; }
+ case floatValue: {
+ float _aidl_value;
+ if ((_aidl_ret_status = _aidl_parcel->readFloat(&_aidl_value)) != ::android::OK) return _aidl_ret_status;
+ if constexpr (std::is_trivially_copyable_v<float>) {
+ set<floatValue>(_aidl_value);
+ } else {
+ // NOLINTNEXTLINE(performance-move-const-arg)
+ set<floatValue>(std::move(_aidl_value));
+ }
+ return ::android::OK; }
+ case doubleValue: {
+ double _aidl_value;
+ if ((_aidl_ret_status = _aidl_parcel->readDouble(&_aidl_value)) != ::android::OK) return _aidl_ret_status;
+ if constexpr (std::is_trivially_copyable_v<double>) {
+ set<doubleValue>(_aidl_value);
+ } else {
+ // NOLINTNEXTLINE(performance-move-const-arg)
+ set<doubleValue>(std::move(_aidl_value));
+ }
+ return ::android::OK; }
+ case enumValue: {
+ ::android::aidl::tests::LongEnum _aidl_value;
+ if ((_aidl_ret_status = _aidl_parcel->readInt64(reinterpret_cast<int64_t *>(&_aidl_value))) != ::android::OK) return _aidl_ret_status;
+ if constexpr (std::is_trivially_copyable_v<::android::aidl::tests::LongEnum>) {
+ set<enumValue>(_aidl_value);
+ } else {
+ // NOLINTNEXTLINE(performance-move-const-arg)
+ set<enumValue>(std::move(_aidl_value));
+ }
+ return ::android::OK; }
+ }
+ return ::android::BAD_VALUE;
+}
+::android::status_t FixedSize::FixedUnion::writeToParcel(::android::Parcel* _aidl_parcel) const {
+ ::android::status_t _aidl_ret_status = _aidl_parcel->writeInt32(getTag());
+ if (_aidl_ret_status != ::android::OK) return _aidl_ret_status;
+ switch (getTag()) {
+ case booleanValue: return _aidl_parcel->writeBool(get<booleanValue>());
+ case byteValue: return _aidl_parcel->writeByte(get<byteValue>());
+ case charValue: return _aidl_parcel->writeChar(get<charValue>());
+ case intValue: return _aidl_parcel->writeInt32(get<intValue>());
+ case longValue: return _aidl_parcel->writeInt64(get<longValue>());
+ case floatValue: return _aidl_parcel->writeFloat(get<floatValue>());
+ case doubleValue: return _aidl_parcel->writeDouble(get<doubleValue>());
+ case enumValue: return _aidl_parcel->writeInt64(static_cast<int64_t>(get<enumValue>()));
+ }
+ __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, "can't reach here");
+}
+} // namespace tests
+} // namespace aidl
+} // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/FixedSize.cpp.d b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/FixedSize.cpp.d
new file mode 100644
index 00000000..b5640414
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/FixedSize.cpp.d
@@ -0,0 +1,3 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-cpp-source/gen/android/aidl/tests/FixedSize.cpp : \
+ system/tools/aidl/tests/android/aidl/tests/FixedSize.aidl \
+ system/tools/aidl/tests/android/aidl/tests/LongEnum.aidl
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BnFixedSize.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BnFixedSize.h
new file mode 100644
index 00000000..ce72aa31
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BnFixedSize.h
@@ -0,0 +1 @@
+#error TODO(b/111362593) parcelables do not have bn classes \ No newline at end of file
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BpFixedSize.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BpFixedSize.h
new file mode 100644
index 00000000..27af6b1c
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BpFixedSize.h
@@ -0,0 +1 @@
+#error TODO(b/111362593) parcelables do not have bp classes \ No newline at end of file
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/FixedSize.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/FixedSize.h
new file mode 100644
index 00000000..2c889e7b
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/FixedSize.h
@@ -0,0 +1,220 @@
+#pragma once
+
+#include <android/aidl/tests/FixedSize.h>
+#include <android/aidl/tests/LongEnum.h>
+#include <android/binder_to_string.h>
+#include <binder/Parcel.h>
+#include <binder/Status.h>
+#include <cassert>
+#include <cstdint>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+#include <utils/String16.h>
+#include <variant>
+
+#ifndef __BIONIC__
+#define __assert2(a,b,c,d) ((void)0)
+#endif
+
+namespace android {
+namespace aidl {
+namespace tests {
+class FixedSize : public ::android::Parcelable {
+public:
+ class FixedUnion : public ::android::Parcelable {
+ public:
+ enum Tag : uint8_t {
+ booleanValue = 0, // boolean booleanValue;
+ byteValue, // byte byteValue;
+ charValue, // char charValue;
+ intValue, // int intValue;
+ longValue, // long longValue;
+ floatValue, // float floatValue;
+ doubleValue, // double doubleValue;
+ enumValue, // android.aidl.tests.LongEnum enumValue;
+ };
+
+ template <Tag _Tag>
+ using _at = typename std::tuple_element<_Tag, std::tuple<bool, int8_t, char16_t, int32_t, int64_t, float, double, ::android::aidl::tests::LongEnum>>::type;
+ template <Tag _Tag, typename _Type>
+ static FixedUnion make(_Type&& _arg) {
+ FixedUnion _inst;
+ _inst.set<_Tag>(std::forward<_Type>(_arg));
+ return _inst;
+ }
+ constexpr Tag getTag() const {
+ return _tag;
+ }
+ template <Tag _Tag>
+ const _at<_Tag>& get() const {
+ if (_Tag != _tag) { __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, "bad access: a wrong tag"); }
+ return *(_at<_Tag>*)(&_value);
+ }
+ template <Tag _Tag>
+ _at<_Tag>& get() {
+ if (_Tag != _tag) { __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, "bad access: a wrong tag"); }
+ return *(_at<_Tag>*)(&_value);
+ }
+ template <Tag _Tag, typename _Type>
+ void set(_Type&& _arg) {
+ _tag = _Tag;
+ get<_Tag>() = std::forward<_Type>(_arg);
+ }
+ static int _cmp(const FixedUnion& _lhs, const FixedUnion& _rhs) {
+ return _cmp_value(_lhs.getTag(), _rhs.getTag()) || _cmp_value_at<enumValue>(_lhs, _rhs);
+ }
+ template <Tag _Tag>
+ static int _cmp_value_at(const FixedUnion& _lhs, const FixedUnion& _rhs) {
+ if constexpr (_Tag == booleanValue) {
+ return _cmp_value(_lhs.get<_Tag>(), _rhs.get<_Tag>());
+ } else {
+ return (_lhs.getTag() == _Tag)
+ ? _cmp_value(_lhs.get<_Tag>(), _rhs.get<_Tag>())
+ : _cmp_value_at<(Tag)(_Tag-1)>(_lhs, _rhs);
+ }
+ }
+ template <typename _Type>
+ static int _cmp_value(const _Type& _lhs, const _Type& _rhs) {
+ return (_lhs == _rhs) ? 0 : (_lhs < _rhs) ? -1 : 1;
+ }
+ inline bool operator!=(const FixedUnion&_rhs) const {
+ return _cmp(*this, _rhs) != 0;
+ }
+ inline bool operator<(const FixedUnion&_rhs) const {
+ return _cmp(*this, _rhs) < 0;
+ }
+ inline bool operator<=(const FixedUnion&_rhs) const {
+ return _cmp(*this, _rhs) <= 0;
+ }
+ inline bool operator==(const FixedUnion&_rhs) const {
+ return _cmp(*this, _rhs) == 0;
+ }
+ inline bool operator>(const FixedUnion&_rhs) const {
+ return _cmp(*this, _rhs) > 0;
+ }
+ inline bool operator>=(const FixedUnion&_rhs) const {
+ return _cmp(*this, _rhs) >= 0;
+ }
+ ::android::status_t readFromParcel(const ::android::Parcel* _aidl_parcel) final;
+ ::android::status_t writeToParcel(::android::Parcel* _aidl_parcel) const final;
+ static const ::android::String16& getParcelableDescriptor() {
+ static const ::android::StaticString16 DESCIPTOR (u"android.aidl.tests.FixedSize.FixedUnion");
+ return DESCIPTOR;
+ }
+ inline std::string toString() const {
+ std::ostringstream os;
+ os << "FixedUnion{";
+ switch (getTag()) {
+ case booleanValue: os << "booleanValue: " << ::android::internal::ToString(get<booleanValue>()); break;
+ case byteValue: os << "byteValue: " << ::android::internal::ToString(get<byteValue>()); break;
+ case charValue: os << "charValue: " << ::android::internal::ToString(get<charValue>()); break;
+ case intValue: os << "intValue: " << ::android::internal::ToString(get<intValue>()); break;
+ case longValue: os << "longValue: " << ::android::internal::ToString(get<longValue>()); break;
+ case floatValue: os << "floatValue: " << ::android::internal::ToString(get<floatValue>()); break;
+ case doubleValue: os << "doubleValue: " << ::android::internal::ToString(get<doubleValue>()); break;
+ case enumValue: os << "enumValue: " << ::android::internal::ToString(get<enumValue>()); break;
+ }
+ os << "}";
+ return os.str();
+ }
+ private:
+ Tag _tag __attribute__((aligned (1))) = booleanValue;
+ union {
+ bool booleanValue __attribute__((aligned (1))) = bool(false);
+ int8_t byteValue __attribute__((aligned (1)));
+ char16_t charValue __attribute__((aligned (2)));
+ int32_t intValue __attribute__((aligned (4)));
+ int64_t longValue __attribute__((aligned (8)));
+ float floatValue __attribute__((aligned (4)));
+ double doubleValue __attribute__((aligned (8)));
+ ::android::aidl::tests::LongEnum enumValue __attribute__((aligned (8)));
+ } _value;
+ }; // class FixedUnion
+ class FixedParcelable : public ::android::Parcelable {
+ public:
+ bool booleanValue = false;
+ int8_t byteValue = 0;
+ char16_t charValue;
+ int32_t intValue = 0;
+ int64_t longValue = 0L;
+ float floatValue = 0.000000f;
+ double doubleValue = 0.000000;
+ ::android::aidl::tests::LongEnum enumValue = ::android::aidl::tests::LongEnum::FOO;
+ ::android::aidl::tests::FixedSize::FixedUnion parcelableValue;
+ inline bool operator!=(const FixedParcelable& rhs) const {
+ return std::tie(booleanValue, byteValue, charValue, intValue, longValue, floatValue, doubleValue, enumValue, parcelableValue) != std::tie(rhs.booleanValue, rhs.byteValue, rhs.charValue, rhs.intValue, rhs.longValue, rhs.floatValue, rhs.doubleValue, rhs.enumValue, rhs.parcelableValue);
+ }
+ inline bool operator<(const FixedParcelable& rhs) const {
+ return std::tie(booleanValue, byteValue, charValue, intValue, longValue, floatValue, doubleValue, enumValue, parcelableValue) < std::tie(rhs.booleanValue, rhs.byteValue, rhs.charValue, rhs.intValue, rhs.longValue, rhs.floatValue, rhs.doubleValue, rhs.enumValue, rhs.parcelableValue);
+ }
+ inline bool operator<=(const FixedParcelable& rhs) const {
+ return std::tie(booleanValue, byteValue, charValue, intValue, longValue, floatValue, doubleValue, enumValue, parcelableValue) <= std::tie(rhs.booleanValue, rhs.byteValue, rhs.charValue, rhs.intValue, rhs.longValue, rhs.floatValue, rhs.doubleValue, rhs.enumValue, rhs.parcelableValue);
+ }
+ inline bool operator==(const FixedParcelable& rhs) const {
+ return std::tie(booleanValue, byteValue, charValue, intValue, longValue, floatValue, doubleValue, enumValue, parcelableValue) == std::tie(rhs.booleanValue, rhs.byteValue, rhs.charValue, rhs.intValue, rhs.longValue, rhs.floatValue, rhs.doubleValue, rhs.enumValue, rhs.parcelableValue);
+ }
+ inline bool operator>(const FixedParcelable& rhs) const {
+ return std::tie(booleanValue, byteValue, charValue, intValue, longValue, floatValue, doubleValue, enumValue, parcelableValue) > std::tie(rhs.booleanValue, rhs.byteValue, rhs.charValue, rhs.intValue, rhs.longValue, rhs.floatValue, rhs.doubleValue, rhs.enumValue, rhs.parcelableValue);
+ }
+ inline bool operator>=(const FixedParcelable& rhs) const {
+ return std::tie(booleanValue, byteValue, charValue, intValue, longValue, floatValue, doubleValue, enumValue, parcelableValue) >= std::tie(rhs.booleanValue, rhs.byteValue, rhs.charValue, rhs.intValue, rhs.longValue, rhs.floatValue, rhs.doubleValue, rhs.enumValue, rhs.parcelableValue);
+ }
+
+ ::android::status_t readFromParcel(const ::android::Parcel* _aidl_parcel) final;
+ ::android::status_t writeToParcel(::android::Parcel* _aidl_parcel) const final;
+ static const ::android::String16& getParcelableDescriptor() {
+ static const ::android::StaticString16 DESCIPTOR (u"android.aidl.tests.FixedSize.FixedParcelable");
+ return DESCIPTOR;
+ }
+ inline std::string toString() const {
+ std::ostringstream os;
+ os << "FixedParcelable{";
+ os << "booleanValue: " << ::android::internal::ToString(booleanValue);
+ os << ", byteValue: " << ::android::internal::ToString(byteValue);
+ os << ", charValue: " << ::android::internal::ToString(charValue);
+ os << ", intValue: " << ::android::internal::ToString(intValue);
+ os << ", longValue: " << ::android::internal::ToString(longValue);
+ os << ", floatValue: " << ::android::internal::ToString(floatValue);
+ os << ", doubleValue: " << ::android::internal::ToString(doubleValue);
+ os << ", enumValue: " << ::android::internal::ToString(enumValue);
+ os << ", parcelableValue: " << ::android::internal::ToString(parcelableValue);
+ os << "}";
+ return os.str();
+ }
+ }; // class FixedParcelable
+ inline bool operator!=(const FixedSize&) const {
+ return std::tie() != std::tie();
+ }
+ inline bool operator<(const FixedSize&) const {
+ return std::tie() < std::tie();
+ }
+ inline bool operator<=(const FixedSize&) const {
+ return std::tie() <= std::tie();
+ }
+ inline bool operator==(const FixedSize&) const {
+ return std::tie() == std::tie();
+ }
+ inline bool operator>(const FixedSize&) const {
+ return std::tie() > std::tie();
+ }
+ inline bool operator>=(const FixedSize&) const {
+ return std::tie() >= std::tie();
+ }
+
+ ::android::status_t readFromParcel(const ::android::Parcel* _aidl_parcel) final;
+ ::android::status_t writeToParcel(::android::Parcel* _aidl_parcel) const final;
+ static const ::android::String16& getParcelableDescriptor() {
+ static const ::android::StaticString16 DESCIPTOR (u"android.aidl.tests.FixedSize");
+ return DESCIPTOR;
+ }
+ inline std::string toString() const {
+ std::ostringstream os;
+ os << "FixedSize{";
+ os << "}";
+ return os.str();
+ }
+}; // class FixedSize
+} // namespace tests
+} // namespace aidl
+} // namespace android
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/FixedSize.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/FixedSize.java
new file mode 100644
index 00000000..43ae1252
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/FixedSize.java
@@ -0,0 +1,408 @@
+/*
+ * This file is auto-generated. DO NOT MODIFY.
+ */
+package android.aidl.tests;
+public class FixedSize implements android.os.Parcelable
+{
+ public static final android.os.Parcelable.Creator<FixedSize> CREATOR = new android.os.Parcelable.Creator<FixedSize>() {
+ @Override
+ public FixedSize createFromParcel(android.os.Parcel _aidl_source) {
+ FixedSize _aidl_out = new FixedSize();
+ _aidl_out.readFromParcel(_aidl_source);
+ return _aidl_out;
+ }
+ @Override
+ public FixedSize[] newArray(int _aidl_size) {
+ return new FixedSize[_aidl_size];
+ }
+ };
+ @Override public final void writeToParcel(android.os.Parcel _aidl_parcel, int _aidl_flag)
+ {
+ int _aidl_start_pos = _aidl_parcel.dataPosition();
+ _aidl_parcel.writeInt(0);
+ int _aidl_end_pos = _aidl_parcel.dataPosition();
+ _aidl_parcel.setDataPosition(_aidl_start_pos);
+ _aidl_parcel.writeInt(_aidl_end_pos - _aidl_start_pos);
+ _aidl_parcel.setDataPosition(_aidl_end_pos);
+ }
+ public final void readFromParcel(android.os.Parcel _aidl_parcel)
+ {
+ int _aidl_start_pos = _aidl_parcel.dataPosition();
+ int _aidl_parcelable_size = _aidl_parcel.readInt();
+ try {
+ if (_aidl_parcelable_size < 0) return;
+ } finally {
+ if (_aidl_start_pos > (Integer.MAX_VALUE - _aidl_parcelable_size)) {
+ throw new android.os.BadParcelableException("Overflow in the size of parcelable");
+ }
+ _aidl_parcel.setDataPosition(_aidl_start_pos + _aidl_parcelable_size);
+ }
+ }
+ @Override
+ public int describeContents() {
+ int _mask = 0;
+ return _mask;
+ }
+ public static class FixedParcelable implements android.os.Parcelable
+ {
+ public boolean booleanValue = false;
+ public byte byteValue = 0;
+ public char charValue;
+ public int intValue = 0;
+ public long longValue = 0L;
+ public float floatValue = 0.000000f;
+ public double doubleValue = 0.000000;
+ public long enumValue = android.aidl.tests.LongEnum.FOO;
+ public android.aidl.tests.FixedSize.FixedUnion parcelableValue;
+ public static final android.os.Parcelable.Creator<FixedParcelable> CREATOR = new android.os.Parcelable.Creator<FixedParcelable>() {
+ @Override
+ public FixedParcelable createFromParcel(android.os.Parcel _aidl_source) {
+ FixedParcelable _aidl_out = new FixedParcelable();
+ _aidl_out.readFromParcel(_aidl_source);
+ return _aidl_out;
+ }
+ @Override
+ public FixedParcelable[] newArray(int _aidl_size) {
+ return new FixedParcelable[_aidl_size];
+ }
+ };
+ @Override public final void writeToParcel(android.os.Parcel _aidl_parcel, int _aidl_flag)
+ {
+ int _aidl_start_pos = _aidl_parcel.dataPosition();
+ _aidl_parcel.writeInt(0);
+ _aidl_parcel.writeBoolean(booleanValue);
+ _aidl_parcel.writeByte(byteValue);
+ _aidl_parcel.writeInt(((int)charValue));
+ _aidl_parcel.writeInt(intValue);
+ _aidl_parcel.writeLong(longValue);
+ _aidl_parcel.writeFloat(floatValue);
+ _aidl_parcel.writeDouble(doubleValue);
+ _aidl_parcel.writeLong(enumValue);
+ _aidl_parcel.writeTypedObject(parcelableValue, 0);
+ int _aidl_end_pos = _aidl_parcel.dataPosition();
+ _aidl_parcel.setDataPosition(_aidl_start_pos);
+ _aidl_parcel.writeInt(_aidl_end_pos - _aidl_start_pos);
+ _aidl_parcel.setDataPosition(_aidl_end_pos);
+ }
+ public final void readFromParcel(android.os.Parcel _aidl_parcel)
+ {
+ int _aidl_start_pos = _aidl_parcel.dataPosition();
+ int _aidl_parcelable_size = _aidl_parcel.readInt();
+ try {
+ if (_aidl_parcelable_size < 0) return;
+ if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+ booleanValue = _aidl_parcel.readBoolean();
+ if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+ byteValue = _aidl_parcel.readByte();
+ if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+ charValue = (char)_aidl_parcel.readInt();
+ if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+ intValue = _aidl_parcel.readInt();
+ if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+ longValue = _aidl_parcel.readLong();
+ if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+ floatValue = _aidl_parcel.readFloat();
+ if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+ doubleValue = _aidl_parcel.readDouble();
+ if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+ enumValue = _aidl_parcel.readLong();
+ if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+ parcelableValue = _aidl_parcel.readTypedObject(android.aidl.tests.FixedSize.FixedUnion.CREATOR);
+ } finally {
+ if (_aidl_start_pos > (Integer.MAX_VALUE - _aidl_parcelable_size)) {
+ throw new android.os.BadParcelableException("Overflow in the size of parcelable");
+ }
+ _aidl_parcel.setDataPosition(_aidl_start_pos + _aidl_parcelable_size);
+ }
+ }
+ @Override
+ public int describeContents() {
+ int _mask = 0;
+ _mask |= describeContents(parcelableValue);
+ return _mask;
+ }
+ private int describeContents(Object _v) {
+ if (_v == null) return 0;
+ if (_v instanceof android.os.Parcelable) {
+ return ((android.os.Parcelable) _v).describeContents();
+ }
+ return 0;
+ }
+ }
+ public static final class FixedUnion implements android.os.Parcelable {
+ // tags for union fields
+ public final static int booleanValue = 0; // boolean booleanValue;
+ public final static int byteValue = 1; // byte byteValue;
+ public final static int charValue = 2; // char charValue;
+ public final static int intValue = 3; // int intValue;
+ public final static int longValue = 4; // long longValue;
+ public final static int floatValue = 5; // float floatValue;
+ public final static int doubleValue = 6; // double doubleValue;
+ public final static int enumValue = 7; // android.aidl.tests.LongEnum enumValue;
+
+ private int _tag;
+ private Object _value;
+
+ public FixedUnion() {
+ boolean _value = false;
+ this._tag = booleanValue;
+ this._value = _value;
+ }
+
+ private FixedUnion(android.os.Parcel _aidl_parcel) {
+ readFromParcel(_aidl_parcel);
+ }
+
+ private FixedUnion(int _tag, Object _value) {
+ this._tag = _tag;
+ this._value = _value;
+ }
+
+ public int getTag() {
+ return _tag;
+ }
+
+ // boolean booleanValue;
+
+ public static FixedUnion booleanValue(boolean _value) {
+ return new FixedUnion(booleanValue, _value);
+ }
+
+ public boolean getBooleanValue() {
+ _assertTag(booleanValue);
+ return (boolean) _value;
+ }
+
+ public void setBooleanValue(boolean _value) {
+ _set(booleanValue, _value);
+ }
+
+ // byte byteValue;
+
+ public static FixedUnion byteValue(byte _value) {
+ return new FixedUnion(byteValue, _value);
+ }
+
+ public byte getByteValue() {
+ _assertTag(byteValue);
+ return (byte) _value;
+ }
+
+ public void setByteValue(byte _value) {
+ _set(byteValue, _value);
+ }
+
+ // char charValue;
+
+ public static FixedUnion charValue(char _value) {
+ return new FixedUnion(charValue, _value);
+ }
+
+ public char getCharValue() {
+ _assertTag(charValue);
+ return (char) _value;
+ }
+
+ public void setCharValue(char _value) {
+ _set(charValue, _value);
+ }
+
+ // int intValue;
+
+ public static FixedUnion intValue(int _value) {
+ return new FixedUnion(intValue, _value);
+ }
+
+ public int getIntValue() {
+ _assertTag(intValue);
+ return (int) _value;
+ }
+
+ public void setIntValue(int _value) {
+ _set(intValue, _value);
+ }
+
+ // long longValue;
+
+ public static FixedUnion longValue(long _value) {
+ return new FixedUnion(longValue, _value);
+ }
+
+ public long getLongValue() {
+ _assertTag(longValue);
+ return (long) _value;
+ }
+
+ public void setLongValue(long _value) {
+ _set(longValue, _value);
+ }
+
+ // float floatValue;
+
+ public static FixedUnion floatValue(float _value) {
+ return new FixedUnion(floatValue, _value);
+ }
+
+ public float getFloatValue() {
+ _assertTag(floatValue);
+ return (float) _value;
+ }
+
+ public void setFloatValue(float _value) {
+ _set(floatValue, _value);
+ }
+
+ // double doubleValue;
+
+ public static FixedUnion doubleValue(double _value) {
+ return new FixedUnion(doubleValue, _value);
+ }
+
+ public double getDoubleValue() {
+ _assertTag(doubleValue);
+ return (double) _value;
+ }
+
+ public void setDoubleValue(double _value) {
+ _set(doubleValue, _value);
+ }
+
+ // android.aidl.tests.LongEnum enumValue;
+
+ public static FixedUnion enumValue(long _value) {
+ return new FixedUnion(enumValue, _value);
+ }
+
+ public long getEnumValue() {
+ _assertTag(enumValue);
+ return (long) _value;
+ }
+
+ public void setEnumValue(long _value) {
+ _set(enumValue, _value);
+ }
+
+ public static final android.os.Parcelable.Creator<FixedUnion> CREATOR = new android.os.Parcelable.Creator<FixedUnion>() {
+ @Override
+ public FixedUnion createFromParcel(android.os.Parcel _aidl_source) {
+ return new FixedUnion(_aidl_source);
+ }
+ @Override
+ public FixedUnion[] newArray(int _aidl_size) {
+ return new FixedUnion[_aidl_size];
+ }
+ };
+
+ @Override
+ public final void writeToParcel(android.os.Parcel _aidl_parcel, int _aidl_flag) {
+ _aidl_parcel.writeInt(_tag);
+ switch (_tag) {
+ case booleanValue:
+ _aidl_parcel.writeBoolean(getBooleanValue());
+ break;
+ case byteValue:
+ _aidl_parcel.writeByte(getByteValue());
+ break;
+ case charValue:
+ _aidl_parcel.writeInt(((int)getCharValue()));
+ break;
+ case intValue:
+ _aidl_parcel.writeInt(getIntValue());
+ break;
+ case longValue:
+ _aidl_parcel.writeLong(getLongValue());
+ break;
+ case floatValue:
+ _aidl_parcel.writeFloat(getFloatValue());
+ break;
+ case doubleValue:
+ _aidl_parcel.writeDouble(getDoubleValue());
+ break;
+ case enumValue:
+ _aidl_parcel.writeLong(getEnumValue());
+ break;
+ }
+ }
+
+ public void readFromParcel(android.os.Parcel _aidl_parcel) {
+ int _aidl_tag;
+ _aidl_tag = _aidl_parcel.readInt();
+ switch (_aidl_tag) {
+ case booleanValue: {
+ boolean _aidl_value;
+ _aidl_value = _aidl_parcel.readBoolean();
+ _set(_aidl_tag, _aidl_value);
+ return; }
+ case byteValue: {
+ byte _aidl_value;
+ _aidl_value = _aidl_parcel.readByte();
+ _set(_aidl_tag, _aidl_value);
+ return; }
+ case charValue: {
+ char _aidl_value;
+ _aidl_value = (char)_aidl_parcel.readInt();
+ _set(_aidl_tag, _aidl_value);
+ return; }
+ case intValue: {
+ int _aidl_value;
+ _aidl_value = _aidl_parcel.readInt();
+ _set(_aidl_tag, _aidl_value);
+ return; }
+ case longValue: {
+ long _aidl_value;
+ _aidl_value = _aidl_parcel.readLong();
+ _set(_aidl_tag, _aidl_value);
+ return; }
+ case floatValue: {
+ float _aidl_value;
+ _aidl_value = _aidl_parcel.readFloat();
+ _set(_aidl_tag, _aidl_value);
+ return; }
+ case doubleValue: {
+ double _aidl_value;
+ _aidl_value = _aidl_parcel.readDouble();
+ _set(_aidl_tag, _aidl_value);
+ return; }
+ case enumValue: {
+ long _aidl_value;
+ _aidl_value = _aidl_parcel.readLong();
+ _set(_aidl_tag, _aidl_value);
+ return; }
+ }
+ throw new IllegalArgumentException("union: unknown tag: " + _aidl_tag);
+ }
+
+ @Override
+ public int describeContents() {
+ int _mask = 0;
+ switch (getTag()) {
+ }
+ return _mask;
+ }
+
+ private void _assertTag(int tag) {
+ if (getTag() != tag) {
+ throw new IllegalStateException("bad access: " + _tagString(tag) + ", " + _tagString(getTag()) + " is available.");
+ }
+ }
+
+ private String _tagString(int _tag) {
+ switch (_tag) {
+ case booleanValue: return "booleanValue";
+ case byteValue: return "byteValue";
+ case charValue: return "charValue";
+ case intValue: return "intValue";
+ case longValue: return "longValue";
+ case floatValue: return "floatValue";
+ case doubleValue: return "doubleValue";
+ case enumValue: return "enumValue";
+ }
+ throw new IllegalStateException("unknown field: " + _tag);
+ }
+
+ private void _set(int _tag, Object _value) {
+ this._tag = _tag;
+ this._value = _value;
+ }
+ }
+}
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/FixedSize.java.d b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/FixedSize.java.d
new file mode 100644
index 00000000..74b092c2
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/FixedSize.java.d
@@ -0,0 +1,3 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-java-source/gen/android/aidl/tests/FixedSize.java : \
+ system/tools/aidl/tests/android/aidl/tests/FixedSize.aidl \
+ system/tools/aidl/tests/android/aidl/tests/LongEnum.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/FixedSize.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/FixedSize.cpp
new file mode 100644
index 00000000..1a80e55c
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/FixedSize.cpp
@@ -0,0 +1,276 @@
+#include "aidl/android/aidl/tests/FixedSize.h"
+
+#include <android/binder_parcel_utils.h>
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+const char* FixedSize::descriptor = "android.aidl.tests.FixedSize";
+
+binder_status_t FixedSize::readFromParcel(const AParcel* _aidl_parcel) {
+ int32_t _aidl_parcelable_size;
+ int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+ binder_status_t _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);
+ if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;
+ if (_aidl_parcelable_size < 0) return STATUS_BAD_VALUE;
+ if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+ AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos + _aidl_parcelable_size);
+ return _aidl_ret_status;
+}
+binder_status_t FixedSize::writeToParcel(AParcel* _aidl_parcel) const {
+ binder_status_t _aidl_ret_status;
+ size_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+ _aidl_ret_status = AParcel_writeInt32(_aidl_parcel, 0);
+ if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+ size_t _aidl_end_pos = AParcel_getDataPosition(_aidl_parcel);
+ AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos);
+ AParcel_writeInt32(_aidl_parcel, _aidl_end_pos - _aidl_start_pos);
+ AParcel_setDataPosition(_aidl_parcel, _aidl_end_pos);
+ return _aidl_ret_status;
+}
+
+} // namespace tests
+} // namespace aidl
+} // namespace android
+} // namespace aidl
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+const char* FixedSize::FixedParcelable::descriptor = "android.aidl.tests.FixedSize.FixedParcelable";
+
+binder_status_t FixedSize::FixedParcelable::readFromParcel(const AParcel* _aidl_parcel) {
+ int32_t _aidl_parcelable_size;
+ int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+ binder_status_t _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);
+ if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;
+ if (_aidl_parcelable_size < 0) return STATUS_BAD_VALUE;
+ if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+ if (AParcel_getDataPosition(_aidl_parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
+ AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos + _aidl_parcelable_size);
+ return _aidl_ret_status;
+ }
+ _aidl_ret_status = AParcel_readBool(_aidl_parcel, &booleanValue);
+ if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+ if (AParcel_getDataPosition(_aidl_parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
+ AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos + _aidl_parcelable_size);
+ return _aidl_ret_status;
+ }
+ _aidl_ret_status = AParcel_readByte(_aidl_parcel, &byteValue);
+ if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+ if (AParcel_getDataPosition(_aidl_parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
+ AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos + _aidl_parcelable_size);
+ return _aidl_ret_status;
+ }
+ _aidl_ret_status = AParcel_readChar(_aidl_parcel, &charValue);
+ if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+ if (AParcel_getDataPosition(_aidl_parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
+ AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos + _aidl_parcelable_size);
+ return _aidl_ret_status;
+ }
+ _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &intValue);
+ if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+ if (AParcel_getDataPosition(_aidl_parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
+ AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos + _aidl_parcelable_size);
+ return _aidl_ret_status;
+ }
+ _aidl_ret_status = AParcel_readInt64(_aidl_parcel, &longValue);
+ if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+ if (AParcel_getDataPosition(_aidl_parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
+ AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos + _aidl_parcelable_size);
+ return _aidl_ret_status;
+ }
+ _aidl_ret_status = AParcel_readFloat(_aidl_parcel, &floatValue);
+ if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+ if (AParcel_getDataPosition(_aidl_parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
+ AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos + _aidl_parcelable_size);
+ return _aidl_ret_status;
+ }
+ _aidl_ret_status = AParcel_readDouble(_aidl_parcel, &doubleValue);
+ if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+ if (AParcel_getDataPosition(_aidl_parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
+ AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos + _aidl_parcelable_size);
+ return _aidl_ret_status;
+ }
+ _aidl_ret_status = AParcel_readInt64(_aidl_parcel, reinterpret_cast<int64_t*>(&enumValue));
+ if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+ if (AParcel_getDataPosition(_aidl_parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
+ AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos + _aidl_parcelable_size);
+ return _aidl_ret_status;
+ }
+ _aidl_ret_status = ::ndk::AParcel_readParcelable(_aidl_parcel, &parcelableValue);
+ if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+ AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos + _aidl_parcelable_size);
+ return _aidl_ret_status;
+}
+binder_status_t FixedSize::FixedParcelable::writeToParcel(AParcel* _aidl_parcel) const {
+ binder_status_t _aidl_ret_status;
+ size_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+ _aidl_ret_status = AParcel_writeInt32(_aidl_parcel, 0);
+ if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+ _aidl_ret_status = AParcel_writeBool(_aidl_parcel, booleanValue);
+ if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+ _aidl_ret_status = AParcel_writeByte(_aidl_parcel, byteValue);
+ if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+ _aidl_ret_status = AParcel_writeChar(_aidl_parcel, charValue);
+ if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+ _aidl_ret_status = AParcel_writeInt32(_aidl_parcel, intValue);
+ if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+ _aidl_ret_status = AParcel_writeInt64(_aidl_parcel, longValue);
+ if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+ _aidl_ret_status = AParcel_writeFloat(_aidl_parcel, floatValue);
+ if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+ _aidl_ret_status = AParcel_writeDouble(_aidl_parcel, doubleValue);
+ if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+ _aidl_ret_status = AParcel_writeInt64(_aidl_parcel, static_cast<int64_t>(enumValue));
+ if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+ _aidl_ret_status = ::ndk::AParcel_writeParcelable(_aidl_parcel, parcelableValue);
+ if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+ size_t _aidl_end_pos = AParcel_getDataPosition(_aidl_parcel);
+ AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos);
+ AParcel_writeInt32(_aidl_parcel, _aidl_end_pos - _aidl_start_pos);
+ AParcel_setDataPosition(_aidl_parcel, _aidl_end_pos);
+ return _aidl_ret_status;
+}
+
+} // namespace tests
+} // namespace aidl
+} // namespace android
+} // namespace aidl
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+const char* FixedSize::FixedUnion::descriptor = "android.aidl.tests.FixedSize.FixedUnion";
+
+binder_status_t FixedSize::FixedUnion::readFromParcel(const AParcel* _parcel) {
+ binder_status_t _aidl_ret_status;
+ int32_t _aidl_tag;
+ if ((_aidl_ret_status = AParcel_readInt32(_parcel, &_aidl_tag)) != STATUS_OK) return _aidl_ret_status;
+ switch (_aidl_tag) {
+ case booleanValue: {
+ bool _aidl_value;
+ if ((_aidl_ret_status = AParcel_readBool(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+ if constexpr (std::is_trivially_copyable_v<bool>) {
+ set<booleanValue>(_aidl_value);
+ } else {
+ // NOLINTNEXTLINE(performance-move-const-arg)
+ set<booleanValue>(std::move(_aidl_value));
+ }
+ return STATUS_OK; }
+ case byteValue: {
+ int8_t _aidl_value;
+ if ((_aidl_ret_status = AParcel_readByte(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+ if constexpr (std::is_trivially_copyable_v<int8_t>) {
+ set<byteValue>(_aidl_value);
+ } else {
+ // NOLINTNEXTLINE(performance-move-const-arg)
+ set<byteValue>(std::move(_aidl_value));
+ }
+ return STATUS_OK; }
+ case charValue: {
+ char16_t _aidl_value;
+ if ((_aidl_ret_status = AParcel_readChar(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+ if constexpr (std::is_trivially_copyable_v<char16_t>) {
+ set<charValue>(_aidl_value);
+ } else {
+ // NOLINTNEXTLINE(performance-move-const-arg)
+ set<charValue>(std::move(_aidl_value));
+ }
+ return STATUS_OK; }
+ case intValue: {
+ int32_t _aidl_value;
+ if ((_aidl_ret_status = AParcel_readInt32(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+ if constexpr (std::is_trivially_copyable_v<int32_t>) {
+ set<intValue>(_aidl_value);
+ } else {
+ // NOLINTNEXTLINE(performance-move-const-arg)
+ set<intValue>(std::move(_aidl_value));
+ }
+ return STATUS_OK; }
+ case longValue: {
+ int64_t _aidl_value;
+ if ((_aidl_ret_status = AParcel_readInt64(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+ if constexpr (std::is_trivially_copyable_v<int64_t>) {
+ set<longValue>(_aidl_value);
+ } else {
+ // NOLINTNEXTLINE(performance-move-const-arg)
+ set<longValue>(std::move(_aidl_value));
+ }
+ return STATUS_OK; }
+ case floatValue: {
+ float _aidl_value;
+ if ((_aidl_ret_status = AParcel_readFloat(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+ if constexpr (std::is_trivially_copyable_v<float>) {
+ set<floatValue>(_aidl_value);
+ } else {
+ // NOLINTNEXTLINE(performance-move-const-arg)
+ set<floatValue>(std::move(_aidl_value));
+ }
+ return STATUS_OK; }
+ case doubleValue: {
+ double _aidl_value;
+ if ((_aidl_ret_status = AParcel_readDouble(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+ if constexpr (std::is_trivially_copyable_v<double>) {
+ set<doubleValue>(_aidl_value);
+ } else {
+ // NOLINTNEXTLINE(performance-move-const-arg)
+ set<doubleValue>(std::move(_aidl_value));
+ }
+ return STATUS_OK; }
+ case enumValue: {
+ ::aidl::android::aidl::tests::LongEnum _aidl_value;
+ if ((_aidl_ret_status = AParcel_readInt64(_parcel, reinterpret_cast<int64_t*>(&_aidl_value))) != STATUS_OK) return _aidl_ret_status;
+ if constexpr (std::is_trivially_copyable_v<::aidl::android::aidl::tests::LongEnum>) {
+ set<enumValue>(_aidl_value);
+ } else {
+ // NOLINTNEXTLINE(performance-move-const-arg)
+ set<enumValue>(std::move(_aidl_value));
+ }
+ return STATUS_OK; }
+ }
+ return STATUS_BAD_VALUE;
+}
+binder_status_t FixedSize::FixedUnion::writeToParcel(AParcel* _parcel) const {
+ binder_status_t _aidl_ret_status = AParcel_writeInt32(_parcel, getTag());
+ if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+ switch (getTag()) {
+ case booleanValue: return AParcel_writeBool(_parcel, get<booleanValue>());
+ case byteValue: return AParcel_writeByte(_parcel, get<byteValue>());
+ case charValue: return AParcel_writeChar(_parcel, get<charValue>());
+ case intValue: return AParcel_writeInt32(_parcel, get<intValue>());
+ case longValue: return AParcel_writeInt64(_parcel, get<longValue>());
+ case floatValue: return AParcel_writeFloat(_parcel, get<floatValue>());
+ case doubleValue: return AParcel_writeDouble(_parcel, get<doubleValue>());
+ case enumValue: return AParcel_writeInt64(_parcel, static_cast<int64_t>(get<enumValue>()));
+ }
+ __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, "can't reach here");
+}
+
+} // namespace tests
+} // namespace aidl
+} // namespace android
+} // namespace aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/FixedSize.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/FixedSize.cpp.d
new file mode 100644
index 00000000..b27ad3e7
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/FixedSize.cpp.d
@@ -0,0 +1,3 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/FixedSize.cpp : \
+ system/tools/aidl/tests/android/aidl/tests/FixedSize.aidl \
+ system/tools/aidl/tests/android/aidl/tests/LongEnum.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnFixedSize.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnFixedSize.h
new file mode 100644
index 00000000..42911089
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnFixedSize.h
@@ -0,0 +1 @@
+#error TODO(b/111362593) defined_types do not have bn classes
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpFixedSize.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpFixedSize.h
new file mode 100644
index 00000000..e8a0db3b
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpFixedSize.h
@@ -0,0 +1 @@
+#error TODO(b/111362593) defined_types do not have bp classes
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/FixedSize.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/FixedSize.h
new file mode 100644
index 00000000..91da0ce3
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/FixedSize.h
@@ -0,0 +1,233 @@
+#pragma once
+
+#include <cassert>
+#include <cstdint>
+#include <memory>
+#include <optional>
+#include <string>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+#include <variant>
+#include <vector>
+#include <android/binder_interface_utils.h>
+#include <android/binder_parcelable_utils.h>
+#include <android/binder_to_string.h>
+#include <aidl/android/aidl/tests/FixedSize.h>
+#include <aidl/android/aidl/tests/LongEnum.h>
+#ifdef BINDER_STABILITY_SUPPORT
+#include <android/binder_stability.h>
+#endif // BINDER_STABILITY_SUPPORT
+
+#ifndef __BIONIC__
+#define __assert2(a,b,c,d) ((void)0)
+#endif
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+class FixedSize {
+public:
+ typedef std::false_type fixed_size;
+ static const char* descriptor;
+
+ class FixedUnion {
+ public:
+ typedef std::true_type fixed_size;
+ static const char* descriptor;
+
+ enum Tag : uint8_t {
+ booleanValue = 0, // boolean booleanValue;
+ byteValue, // byte byteValue;
+ charValue, // char charValue;
+ intValue, // int intValue;
+ longValue, // long longValue;
+ floatValue, // float floatValue;
+ doubleValue, // double doubleValue;
+ enumValue, // android.aidl.tests.LongEnum enumValue;
+ };
+
+ template <Tag _Tag>
+ using _at = typename std::tuple_element<_Tag, std::tuple<bool, int8_t, char16_t, int32_t, int64_t, float, double, ::aidl::android::aidl::tests::LongEnum>>::type;
+ template <Tag _Tag, typename _Type>
+ static FixedUnion make(_Type&& _arg) {
+ FixedUnion _inst;
+ _inst.set<_Tag>(std::forward<_Type>(_arg));
+ return _inst;
+ }
+ constexpr Tag getTag() const {
+ return _tag;
+ }
+ template <Tag _Tag>
+ const _at<_Tag>& get() const {
+ if (_Tag != _tag) { __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, "bad access: a wrong tag"); }
+ return *(_at<_Tag>*)(&_value);
+ }
+ template <Tag _Tag>
+ _at<_Tag>& get() {
+ if (_Tag != _tag) { __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, "bad access: a wrong tag"); }
+ return *(_at<_Tag>*)(&_value);
+ }
+ template <Tag _Tag, typename _Type>
+ void set(_Type&& _arg) {
+ _tag = _Tag;
+ get<_Tag>() = std::forward<_Type>(_arg);
+ }
+ binder_status_t readFromParcel(const AParcel* _parcel);
+ binder_status_t writeToParcel(AParcel* _parcel) const;
+
+ static int _cmp(const FixedUnion& _lhs, const FixedUnion& _rhs) {
+ return _cmp_value(_lhs.getTag(), _rhs.getTag()) || _cmp_value_at<enumValue>(_lhs, _rhs);
+ }
+ template <Tag _Tag>
+ static int _cmp_value_at(const FixedUnion& _lhs, const FixedUnion& _rhs) {
+ if constexpr (_Tag == booleanValue) {
+ return _cmp_value(_lhs.get<_Tag>(), _rhs.get<_Tag>());
+ } else {
+ return (_lhs.getTag() == _Tag)
+ ? _cmp_value(_lhs.get<_Tag>(), _rhs.get<_Tag>())
+ : _cmp_value_at<(Tag)(_Tag-1)>(_lhs, _rhs);
+ }
+ }
+ template <typename _Type>
+ static int _cmp_value(const _Type& _lhs, const _Type& _rhs) {
+ return (_lhs == _rhs) ? 0 : (_lhs < _rhs) ? -1 : 1;
+ }
+ inline bool operator!=(const FixedUnion&_rhs) const {
+ return _cmp(*this, _rhs) != 0;
+ }
+ inline bool operator<(const FixedUnion&_rhs) const {
+ return _cmp(*this, _rhs) < 0;
+ }
+ inline bool operator<=(const FixedUnion&_rhs) const {
+ return _cmp(*this, _rhs) <= 0;
+ }
+ inline bool operator==(const FixedUnion&_rhs) const {
+ return _cmp(*this, _rhs) == 0;
+ }
+ inline bool operator>(const FixedUnion&_rhs) const {
+ return _cmp(*this, _rhs) > 0;
+ }
+ inline bool operator>=(const FixedUnion&_rhs) const {
+ return _cmp(*this, _rhs) >= 0;
+ }
+ static const ::ndk::parcelable_stability_t _aidl_stability = ::ndk::STABILITY_LOCAL;
+ inline std::string toString() const {
+ std::ostringstream os;
+ os << "FixedUnion{";
+ switch (getTag()) {
+ case booleanValue: os << "booleanValue: " << ::android::internal::ToString(get<booleanValue>()); break;
+ case byteValue: os << "byteValue: " << ::android::internal::ToString(get<byteValue>()); break;
+ case charValue: os << "charValue: " << ::android::internal::ToString(get<charValue>()); break;
+ case intValue: os << "intValue: " << ::android::internal::ToString(get<intValue>()); break;
+ case longValue: os << "longValue: " << ::android::internal::ToString(get<longValue>()); break;
+ case floatValue: os << "floatValue: " << ::android::internal::ToString(get<floatValue>()); break;
+ case doubleValue: os << "doubleValue: " << ::android::internal::ToString(get<doubleValue>()); break;
+ case enumValue: os << "enumValue: " << ::android::internal::ToString(get<enumValue>()); break;
+ }
+ os << "}";
+ return os.str();
+ }
+ private:
+ Tag _tag __attribute__((aligned (1))) = booleanValue;
+ union {
+ bool booleanValue __attribute__((aligned (1))) = bool(false);
+ int8_t byteValue __attribute__((aligned (1)));
+ char16_t charValue __attribute__((aligned (2)));
+ int32_t intValue __attribute__((aligned (4)));
+ int64_t longValue __attribute__((aligned (8)));
+ float floatValue __attribute__((aligned (4)));
+ double doubleValue __attribute__((aligned (8)));
+ ::aidl::android::aidl::tests::LongEnum enumValue __attribute__((aligned (8)));
+ } _value;
+ };
+ class FixedParcelable {
+ public:
+ typedef std::true_type fixed_size;
+ static const char* descriptor;
+
+ bool booleanValue __attribute__((aligned (1))) = false;
+ int8_t byteValue __attribute__((aligned (1))) = 0;
+ char16_t charValue __attribute__((aligned (2)));
+ int32_t intValue __attribute__((aligned (4))) = 0;
+ int64_t longValue __attribute__((aligned (8))) = 0L;
+ float floatValue __attribute__((aligned (4))) = 0.000000f;
+ double doubleValue __attribute__((aligned (8))) = 0.000000;
+ ::aidl::android::aidl::tests::LongEnum enumValue __attribute__((aligned (8))) = ::aidl::android::aidl::tests::LongEnum::FOO;
+ ::aidl::android::aidl::tests::FixedSize::FixedUnion parcelableValue;
+
+ binder_status_t readFromParcel(const AParcel* parcel);
+ binder_status_t writeToParcel(AParcel* parcel) const;
+
+ inline bool operator!=(const FixedParcelable& rhs) const {
+ return std::tie(booleanValue, byteValue, charValue, intValue, longValue, floatValue, doubleValue, enumValue, parcelableValue) != std::tie(rhs.booleanValue, rhs.byteValue, rhs.charValue, rhs.intValue, rhs.longValue, rhs.floatValue, rhs.doubleValue, rhs.enumValue, rhs.parcelableValue);
+ }
+ inline bool operator<(const FixedParcelable& rhs) const {
+ return std::tie(booleanValue, byteValue, charValue, intValue, longValue, floatValue, doubleValue, enumValue, parcelableValue) < std::tie(rhs.booleanValue, rhs.byteValue, rhs.charValue, rhs.intValue, rhs.longValue, rhs.floatValue, rhs.doubleValue, rhs.enumValue, rhs.parcelableValue);
+ }
+ inline bool operator<=(const FixedParcelable& rhs) const {
+ return std::tie(booleanValue, byteValue, charValue, intValue, longValue, floatValue, doubleValue, enumValue, parcelableValue) <= std::tie(rhs.booleanValue, rhs.byteValue, rhs.charValue, rhs.intValue, rhs.longValue, rhs.floatValue, rhs.doubleValue, rhs.enumValue, rhs.parcelableValue);
+ }
+ inline bool operator==(const FixedParcelable& rhs) const {
+ return std::tie(booleanValue, byteValue, charValue, intValue, longValue, floatValue, doubleValue, enumValue, parcelableValue) == std::tie(rhs.booleanValue, rhs.byteValue, rhs.charValue, rhs.intValue, rhs.longValue, rhs.floatValue, rhs.doubleValue, rhs.enumValue, rhs.parcelableValue);
+ }
+ inline bool operator>(const FixedParcelable& rhs) const {
+ return std::tie(booleanValue, byteValue, charValue, intValue, longValue, floatValue, doubleValue, enumValue, parcelableValue) > std::tie(rhs.booleanValue, rhs.byteValue, rhs.charValue, rhs.intValue, rhs.longValue, rhs.floatValue, rhs.doubleValue, rhs.enumValue, rhs.parcelableValue);
+ }
+ inline bool operator>=(const FixedParcelable& rhs) const {
+ return std::tie(booleanValue, byteValue, charValue, intValue, longValue, floatValue, doubleValue, enumValue, parcelableValue) >= std::tie(rhs.booleanValue, rhs.byteValue, rhs.charValue, rhs.intValue, rhs.longValue, rhs.floatValue, rhs.doubleValue, rhs.enumValue, rhs.parcelableValue);
+ }
+
+ static const ::ndk::parcelable_stability_t _aidl_stability = ::ndk::STABILITY_LOCAL;
+ inline std::string toString() const {
+ std::ostringstream os;
+ os << "FixedParcelable{";
+ os << "booleanValue: " << ::android::internal::ToString(booleanValue);
+ os << ", byteValue: " << ::android::internal::ToString(byteValue);
+ os << ", charValue: " << ::android::internal::ToString(charValue);
+ os << ", intValue: " << ::android::internal::ToString(intValue);
+ os << ", longValue: " << ::android::internal::ToString(longValue);
+ os << ", floatValue: " << ::android::internal::ToString(floatValue);
+ os << ", doubleValue: " << ::android::internal::ToString(doubleValue);
+ os << ", enumValue: " << ::android::internal::ToString(enumValue);
+ os << ", parcelableValue: " << ::android::internal::ToString(parcelableValue);
+ os << "}";
+ return os.str();
+ }
+ };
+
+ binder_status_t readFromParcel(const AParcel* parcel);
+ binder_status_t writeToParcel(AParcel* parcel) const;
+
+ inline bool operator!=(const FixedSize&) const {
+ return std::tie() != std::tie();
+ }
+ inline bool operator<(const FixedSize&) const {
+ return std::tie() < std::tie();
+ }
+ inline bool operator<=(const FixedSize&) const {
+ return std::tie() <= std::tie();
+ }
+ inline bool operator==(const FixedSize&) const {
+ return std::tie() == std::tie();
+ }
+ inline bool operator>(const FixedSize&) const {
+ return std::tie() > std::tie();
+ }
+ inline bool operator>=(const FixedSize&) const {
+ return std::tie() >= std::tie();
+ }
+
+ static const ::ndk::parcelable_stability_t _aidl_stability = ::ndk::STABILITY_LOCAL;
+ inline std::string toString() const {
+ std::ostringstream os;
+ os << "FixedSize{";
+ os << "}";
+ return os.str();
+ }
+};
+} // namespace tests
+} // namespace aidl
+} // namespace android
+} // namespace aidl
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/FixedSize.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/FixedSize.rs
new file mode 100644
index 00000000..1048f286
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/FixedSize.rs
@@ -0,0 +1,224 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
+#[derive(Debug)]
+pub struct FixedSize {
+}
+impl Default for FixedSize {
+ fn default() -> Self {
+ Self {
+ }
+ }
+}
+impl binder::parcel::Parcelable for FixedSize {
+ fn write_to_parcel(&self, parcel: &mut binder::parcel::BorrowedParcel) -> binder::Result<()> {
+ parcel.sized_write(|subparcel| {
+ Ok(())
+ })
+ }
+ fn read_from_parcel(&mut self, parcel: &binder::parcel::BorrowedParcel) -> binder::Result<()> {
+ parcel.sized_read(|subparcel| {
+ Ok(())
+ })
+ }
+}
+binder::impl_serialize_for_parcelable!(FixedSize);
+binder::impl_deserialize_for_parcelable!(FixedSize);
+impl binder::parcel::ParcelableMetadata for FixedSize {
+ fn get_descriptor() -> &'static str { "android.aidl.tests.FixedSize" }
+}
+pub mod FixedParcelable {
+ #[derive(Debug)]
+ pub struct FixedParcelable {
+ pub booleanValue: bool,
+ pub byteValue: i8,
+ pub charValue: u16,
+ pub intValue: i32,
+ pub longValue: i64,
+ pub floatValue: f32,
+ pub doubleValue: f64,
+ pub enumValue: crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum,
+ pub parcelableValue: crate::mangled::_7_android_4_aidl_5_tests_9_FixedSize_10_FixedUnion,
+ }
+ impl Default for FixedParcelable {
+ fn default() -> Self {
+ Self {
+ booleanValue: false,
+ byteValue: 0,
+ charValue: Default::default(),
+ intValue: 0,
+ longValue: 0,
+ floatValue: 0.000000f32,
+ doubleValue: 0.000000f64,
+ enumValue: crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum::FOO,
+ parcelableValue: Default::default(),
+ }
+ }
+ }
+ impl binder::parcel::Parcelable for FixedParcelable {
+ fn write_to_parcel(&self, parcel: &mut binder::parcel::BorrowedParcel) -> binder::Result<()> {
+ parcel.sized_write(|subparcel| {
+ subparcel.write(&self.booleanValue)?;
+ subparcel.write(&self.byteValue)?;
+ subparcel.write(&self.charValue)?;
+ subparcel.write(&self.intValue)?;
+ subparcel.write(&self.longValue)?;
+ subparcel.write(&self.floatValue)?;
+ subparcel.write(&self.doubleValue)?;
+ subparcel.write(&self.enumValue)?;
+ subparcel.write(&self.parcelableValue)?;
+ Ok(())
+ })
+ }
+ fn read_from_parcel(&mut self, parcel: &binder::parcel::BorrowedParcel) -> binder::Result<()> {
+ parcel.sized_read(|subparcel| {
+ if subparcel.has_more_data() {
+ self.booleanValue = subparcel.read()?;
+ }
+ if subparcel.has_more_data() {
+ self.byteValue = subparcel.read()?;
+ }
+ if subparcel.has_more_data() {
+ self.charValue = subparcel.read()?;
+ }
+ if subparcel.has_more_data() {
+ self.intValue = subparcel.read()?;
+ }
+ if subparcel.has_more_data() {
+ self.longValue = subparcel.read()?;
+ }
+ if subparcel.has_more_data() {
+ self.floatValue = subparcel.read()?;
+ }
+ if subparcel.has_more_data() {
+ self.doubleValue = subparcel.read()?;
+ }
+ if subparcel.has_more_data() {
+ self.enumValue = subparcel.read()?;
+ }
+ if subparcel.has_more_data() {
+ self.parcelableValue = subparcel.read()?;
+ }
+ Ok(())
+ })
+ }
+ }
+ binder::impl_serialize_for_parcelable!(FixedParcelable);
+ binder::impl_deserialize_for_parcelable!(FixedParcelable);
+ impl binder::parcel::ParcelableMetadata for FixedParcelable {
+ fn get_descriptor() -> &'static str { "android.aidl.tests.FixedSize.FixedParcelable" }
+ }
+}
+pub mod FixedUnion {
+ #[derive(Debug)]
+ pub enum FixedUnion {
+ BooleanValue(bool),
+ ByteValue(i8),
+ CharValue(u16),
+ IntValue(i32),
+ LongValue(i64),
+ FloatValue(f32),
+ DoubleValue(f64),
+ EnumValue(crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum),
+ }
+ impl Default for FixedUnion {
+ fn default() -> Self {
+ Self::BooleanValue(false)
+ }
+ }
+ impl binder::parcel::Parcelable for FixedUnion {
+ fn write_to_parcel(&self, parcel: &mut binder::parcel::BorrowedParcel) -> binder::Result<()> {
+ match self {
+ Self::BooleanValue(v) => {
+ parcel.write(&0i32)?;
+ parcel.write(v)
+ }
+ Self::ByteValue(v) => {
+ parcel.write(&1i32)?;
+ parcel.write(v)
+ }
+ Self::CharValue(v) => {
+ parcel.write(&2i32)?;
+ parcel.write(v)
+ }
+ Self::IntValue(v) => {
+ parcel.write(&3i32)?;
+ parcel.write(v)
+ }
+ Self::LongValue(v) => {
+ parcel.write(&4i32)?;
+ parcel.write(v)
+ }
+ Self::FloatValue(v) => {
+ parcel.write(&5i32)?;
+ parcel.write(v)
+ }
+ Self::DoubleValue(v) => {
+ parcel.write(&6i32)?;
+ parcel.write(v)
+ }
+ Self::EnumValue(v) => {
+ parcel.write(&7i32)?;
+ parcel.write(v)
+ }
+ }
+ }
+ fn read_from_parcel(&mut self, parcel: &binder::parcel::BorrowedParcel) -> binder::Result<()> {
+ let tag: i32 = parcel.read()?;
+ match tag {
+ 0 => {
+ let value: bool = parcel.read()?;
+ *self = Self::BooleanValue(value);
+ Ok(())
+ }
+ 1 => {
+ let value: i8 = parcel.read()?;
+ *self = Self::ByteValue(value);
+ Ok(())
+ }
+ 2 => {
+ let value: u16 = parcel.read()?;
+ *self = Self::CharValue(value);
+ Ok(())
+ }
+ 3 => {
+ let value: i32 = parcel.read()?;
+ *self = Self::IntValue(value);
+ Ok(())
+ }
+ 4 => {
+ let value: i64 = parcel.read()?;
+ *self = Self::LongValue(value);
+ Ok(())
+ }
+ 5 => {
+ let value: f32 = parcel.read()?;
+ *self = Self::FloatValue(value);
+ Ok(())
+ }
+ 6 => {
+ let value: f64 = parcel.read()?;
+ *self = Self::DoubleValue(value);
+ Ok(())
+ }
+ 7 => {
+ let value: crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum = parcel.read()?;
+ *self = Self::EnumValue(value);
+ Ok(())
+ }
+ _ => {
+ Err(binder::StatusCode::BAD_VALUE)
+ }
+ }
+ }
+ }
+ binder::impl_serialize_for_parcelable!(FixedUnion);
+ binder::impl_deserialize_for_parcelable!(FixedUnion);
+ impl binder::parcel::ParcelableMetadata for FixedUnion {
+ fn get_descriptor() -> &'static str { "android.aidl.tests.FixedSize.FixedUnion" }
+ }
+}
+pub(crate) mod mangled {
+ pub use super::FixedSize as _7_android_4_aidl_5_tests_9_FixedSize;
+ pub use super::FixedParcelable::FixedParcelable as _7_android_4_aidl_5_tests_9_FixedSize_15_FixedParcelable;
+ pub use super::FixedUnion::FixedUnion as _7_android_4_aidl_5_tests_9_FixedSize_10_FixedUnion;
+}
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/FixedSize.rs.d b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/FixedSize.rs.d
new file mode 100644
index 00000000..0635f5e0
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/FixedSize.rs.d
@@ -0,0 +1,3 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-rust-source/gen/android/aidl/tests/FixedSize.rs : \
+ system/tools/aidl/tests/android/aidl/tests/FixedSize.aidl \
+ system/tools/aidl/tests/android/aidl/tests/LongEnum.aidl