Support @nullable(heap) for recursive types
@nullable(heap=true) marks a parcelable field to be held in a heap
allocated wrapper like unique_ptr<T> in C++ and Box<T> in Rust.
This enables recursive parcelable types like following:
parcelable Recursive {
@nullable(heap=true) Recursive r;
}
Note `r` is represented in Option<Box<Recursive>> in Rust because Box<T>
should hold a value always.
Bug: 188690695
Test: aidl_integration_test
Change-Id: Ic9b209da73c1395785c078aeecd34fda74e42e7d
diff --git a/aidl_language.cpp b/aidl_language.cpp
index 76277fd..0cbef0b 100644
--- a/aidl_language.cpp
+++ b/aidl_language.cpp
@@ -98,7 +98,10 @@
const std::vector<AidlAnnotation::Schema>& AidlAnnotation::AllSchemas() {
static const std::vector<Schema> kSchemas{
- {AidlAnnotation::Type::NULLABLE, "nullable", CONTEXT_TYPE_SPECIFIER, {}},
+ {AidlAnnotation::Type::NULLABLE,
+ "nullable",
+ CONTEXT_TYPE_SPECIFIER,
+ {{"heap", kBooleanType}}},
{AidlAnnotation::Type::UTF8_IN_CPP, "utf8InCpp", CONTEXT_TYPE_SPECIFIER, {}},
{AidlAnnotation::Type::SENSITIVE_DATA, "SensitiveData", CONTEXT_TYPE_INTERFACE, {}},
{AidlAnnotation::Type::VINTF_STABILITY, "VintfStability", CONTEXT_TYPE, {}},
@@ -344,6 +347,14 @@
return GetAnnotation(annotations_, AidlAnnotation::Type::NULLABLE);
}
+bool AidlAnnotatable::IsHeapNullable() const {
+ auto annot = GetAnnotation(annotations_, AidlAnnotation::Type::NULLABLE);
+ if (annot) {
+ return annot->ParamValue<bool>("heap").value_or(false);
+ }
+ return false;
+}
+
bool AidlAnnotatable::IsUtf8InCpp() const {
return GetAnnotation(annotations_, AidlAnnotation::Type::UTF8_IN_CPP);
}
@@ -635,6 +646,12 @@
AIDL_ERROR(this) << "ParcelableHolder cannot be nullable.";
return false;
}
+ if (IsHeapNullable()) {
+ if (!defined_type || IsArray() || !defined_type->AsParcelable()) {
+ AIDL_ERROR(this) << "@nullable(heap=true) is available to parcelables.";
+ return false;
+ }
+ }
}
return true;
}