Snap for 6533464 from 68f9f84932f0f0dbbbb9dbf0b0a3c25bce75ef45 to sdk-release
Change-Id: I04283d9a07dad943f22fc246b1c4fa46e1feb1bf
diff --git a/Android.bp b/Android.bp
index 373c402..fd46e81 100644
--- a/Android.bp
+++ b/Android.bp
@@ -221,6 +221,18 @@
test_suites: ["device-tests"],
}
+// Header-only library used for atrace in platform NDK builds
+cc_library_headers {
+ name: "libandroid_aidltrace",
+ host_supported: true,
+ vendor_available: true,
+ export_include_dirs: ["trace"],
+ apex_available: [
+ "//apex_available:platform",
+ "//apex_available:anyapex",
+ ],
+}
+
// Could consider simplifying this test by removing this.
cc_test {
name: "aidl_test_sentinel_searcher",
@@ -244,6 +256,7 @@
name: "libaidl-integration-test",
defaults: ["aidl_test_defaults"],
aidl: {
+ generate_traces: true,
export_aidl_headers: true,
local_include_dirs: ["tests"],
include_dirs: ["frameworks/native/aidl/binder"],
@@ -258,15 +271,14 @@
name: "aidl_test_service",
gtest: false,
defaults: ["aidl_test_defaults"],
- static_libs: ["libaidl-integration-test"],
+ static_libs: ["libaidl-integration-test", "libcutils"],
srcs: ["tests/aidl_test_service.cpp"],
}
cc_test {
name: "aidl_test_client",
- gtest: false,
defaults: ["aidl_test_defaults"],
- static_libs: ["libaidl-integration-test"],
+ static_libs: ["libaidl-integration-test", "libcutils"],
srcs: [
"tests/aidl_test_client.cpp",
"tests/aidl_test_client_file_descriptors.cpp",
@@ -310,6 +322,7 @@
"system/tools/aidl/tests/",
"frameworks/native/aidl/binder",
],
+ generate_traces: true,
},
test_suites: ["device-tests"],
}
@@ -333,5 +346,8 @@
ndk: {
gen_log: true,
},
+ java: {
+ platform_apis: true,
+ }
},
}
diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2
deleted file mode 100644
index e69de29..0000000
--- a/MODULE_LICENSE_APACHE2
+++ /dev/null
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..02409cb
--- /dev/null
+++ b/README.md
@@ -0,0 +1,3 @@
+Documentation for this project is currently maintained here:
+
+https://source.android.com/devices/architecture/aidl/overview
diff --git a/aidl.cpp b/aidl.cpp
index 47e806c..0c10cdb 100644
--- a/aidl.cpp
+++ b/aidl.cpp
@@ -481,7 +481,7 @@
}
string import_path = import_resolver.FindImportFile(import);
if (import_path.empty()) {
- if (typenames->ResolveTypename(import).second) {
+ if (typenames->ResolveTypename(import).is_resolved) {
// Couldn't find the *.aidl file for the type from the include paths, but we
// have the type already resolved. This could happen when the type is
// from the preprocessed aidl file. In that case, use the type from the
@@ -574,7 +574,7 @@
CHECK(defined_type != nullptr);
// Language specific validation
- if (!defined_type->LanguageSpecificCheckValid(options.TargetLanguage())) {
+ if (!defined_type->LanguageSpecificCheckValid(*typenames, options.TargetLanguage())) {
return AidlError::BAD_TYPE;
}
@@ -703,6 +703,35 @@
AIDL_ERROR(type) << type.GetCanonicalName()
<< " does not have VINTF level stability, but this interface requires it.";
}
+
+ // Ensure that untyped List/Map is not used in stable AIDL.
+ if (options.IsStructured()) {
+ const AidlInterface* iface = type.AsInterface();
+ const AidlStructuredParcelable* parcelable = type.AsStructuredParcelable();
+
+ auto check = [&err](const AidlTypeSpecifier& type, const AidlNode* node) {
+ if (!type.IsGeneric() && (type.GetName() == "List" || type.GetName() == "Map")) {
+ err = AidlError::BAD_TYPE;
+ AIDL_ERROR(node)
+ << "Encountered an untyped List or Map. The use of untyped List/Map is prohibited "
+ << "because it is not guaranteed that the objects in the list are recognizable in "
+ << "the receiving side. Consider switching to an array or a generic List/Map.";
+ }
+ };
+
+ if (iface != nullptr) {
+ for (const auto& method : iface->GetMethods()) {
+ check(method->GetType(), method.get());
+ for (const auto& arg : method->GetArguments()) {
+ check(arg->GetType(), method.get());
+ }
+ }
+ } else if (parcelable != nullptr) {
+ for (const auto& field : parcelable->GetFields()) {
+ check(field->GetType(), field.get());
+ }
+ }
+ }
});
if (err != AidlError::OK) {
diff --git a/aidl_checkapi.cpp b/aidl_checkapi.cpp
index 2ae2247..72577ca 100644
--- a/aidl_checkapi.cpp
+++ b/aidl_checkapi.cpp
@@ -34,12 +34,35 @@
using std::string;
using std::vector;
+static set<AidlAnnotation> get_strict_annotations(const AidlAnnotatable& node) {
+ // This must be symmetrical (if you can add something, you must be able to
+ // remove it). The reason is that we have no way of knowing which interface a
+ // server serves and which interface a client serves (e.g. a callback
+ // interface). Note that this is being overly lenient. It makes sense for
+ // newer code to start accepting nullable things. However, here, we don't know
+ // if the client of an interface or the server of an interface is newer.
+ //
+ // Here are two examples to demonstrate this:
+ // - a new implementation might change so that it no longer returns null
+ // values (remove @nullable)
+ // - a new implementation might start accepting null values (add @nullable)
+ static const set<AidlAnnotation::Type> kIgnoreAnnotations{
+ AidlAnnotation::Type::NULLABLE,
+ };
+ set<AidlAnnotation> annotations;
+ for (const AidlAnnotation& annotation : node.GetAnnotations()) {
+ if (kIgnoreAnnotations.find(annotation.GetType()) == kIgnoreAnnotations.end()) {
+ annotations.insert(annotation);
+ }
+ }
+ return annotations;
+}
+
static bool have_compatible_annotations(const AidlAnnotatable& older,
const AidlAnnotatable& newer) {
- set<AidlAnnotation> olderAnnotations(older.GetAnnotations().begin(),
- older.GetAnnotations().end());
- set<AidlAnnotation> newerAnnotations(newer.GetAnnotations().begin(),
- newer.GetAnnotations().end());
+ set<AidlAnnotation> olderAnnotations = get_strict_annotations(older);
+ set<AidlAnnotation> newerAnnotations = get_strict_annotations(newer);
+
if (olderAnnotations != newerAnnotations) {
const string from = older.ToString().empty() ? "(empty)" : older.ToString();
const string to = newer.ToString().empty() ? "(empty)" : newer.ToString();
@@ -142,6 +165,19 @@
return compatible;
}
+// returns whether the given type when defaulted will be accepted by
+// unmarshalling code
+static bool has_usable_nil_type(const AidlTypeSpecifier& specifier) {
+ // TODO(b/155238508): fix for primitives
+
+ // This technically only applies in C++, but even if both the client and the
+ // server of an interface are in Java at a particular point in time, where
+ // null is currently always acceptable, we want to make sure that versions
+ // of this service can work in native and future backends without a problem.
+ // Also, in that case, adding nullable does not hurt.
+ return specifier.IsNullable();
+}
+
static bool are_compatible_parcelables(const AidlStructuredParcelable& older,
const AidlStructuredParcelable& newer) {
const auto& old_fields = older.GetFields();
@@ -159,19 +195,62 @@
const auto& new_field = new_fields.at(i);
compatible &= are_compatible_types(old_field->GetType(), new_field->GetType());
- // Note: unlike method argument names, field name change is an incompatible
- // change, otherwise, we can't detect
- // parcelable Point {int x; int y;} -> parcelable Point {int y; int x;}
- if (old_field->GetName() != new_field->GetName()) {
- AIDL_ERROR(newer) << "Renamed field: " << old_field->GetName() << " to "
- << new_field->GetName() << ".";
- compatible = false;
- }
-
const string old_value = old_field->ValueString(AidlConstantValueDecorator);
const string new_value = new_field->ValueString(AidlConstantValueDecorator);
if (old_value != new_value) {
- AIDL_ERROR(newer) << "Changed default value: " << old_value << " to " << new_value << ".";
+ AIDL_ERROR(new_field) << "Changed default value: " << old_value << " to " << new_value << ".";
+ compatible = false;
+ }
+ }
+
+ // Reordering of fields is an incompatible change.
+ for (size_t i = 0; i < new_fields.size(); i++) {
+ const auto& new_field = new_fields.at(i);
+ auto found = std::find_if(old_fields.begin(), old_fields.end(), [&new_field](const auto& f) {
+ return new_field->GetName() == f->GetName();
+ });
+ if (found != old_fields.end()) {
+ size_t old_index = std::distance(old_fields.begin(), found);
+ if (old_index != i) {
+ AIDL_ERROR(new_field) << "Reordered " << new_field->GetName() << " from " << old_index
+ << " to " << i << ".";
+ compatible = false;
+ }
+ }
+ }
+
+ for (size_t i = old_fields.size(); i < new_fields.size(); i++) {
+ const auto& new_field = new_fields.at(i);
+ if (!new_field->GetDefaultValue() && !has_usable_nil_type(new_field->GetType())) {
+ // Old API versions may suffer from the issue presented here. There is
+ // only a finite number in Android, which we must allow indefinitely.
+ struct HistoricalException {
+ std::string canonical;
+ std::string field;
+ };
+ static std::vector<HistoricalException> exceptions = {
+ {"android.net.DhcpResultsParcelable", "serverHostName"},
+ {"android.net.ProvisioningConfigurationParcelable", "enablePreconnection"},
+ {"android.net.ResolverParamsParcel", "resolverOptions"},
+ };
+ bool excepted = false;
+ for (const HistoricalException& exception : exceptions) {
+ if (older.GetCanonicalName() == exception.canonical &&
+ new_field->GetName() == exception.field) {
+ excepted = true;
+ break;
+ }
+ }
+ if (excepted) continue;
+
+ AIDL_ERROR(new_field)
+ << "Field '" << new_field->GetName()
+ << "' does not have a useful default in some backends. Please either provide a default "
+ "value for this field or mark the field as @nullable. This value or a null value will "
+ "be used automatically when an old version of this parcelable is sent to a process "
+ "which understands a new version of this parcelable. In order to make sure your code "
+ "continues to be backwards compatible, make sure the default or null value does not "
+ "cause a semantic change to this parcelable.";
compatible = false;
}
}
diff --git a/aidl_language.cpp b/aidl_language.cpp
index e08142a..dd726d6 100644
--- a/aidl_language.cpp
+++ b/aidl_language.cpp
@@ -200,7 +200,7 @@
if (parameter_mapping_it == schema_.supported_parameters.end()) {
std::ostringstream stream;
stream << "Parameter " << param_name << " not supported ";
- stream << "for annotation " << GetName() << ".";
+ stream << "for annotation " << GetName() << ". ";
stream << "It must be one of:";
for (const auto& kv : schema_.supported_parameters) {
stream << " " << kv.first;
@@ -226,13 +226,23 @@
for (const auto& name_and_param : parameters_) {
const std::string& param_name = name_and_param.first;
const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;
+ if (schema_.supported_parameters.find(param_name) == schema_.supported_parameters.end()) {
+ std::ostringstream stream;
+ stream << "Parameter " << param_name << " not supported ";
+ stream << "for annotation " << GetName() << ". ";
+ stream << "It must be one of:";
+ for (const auto& kv : schema_.supported_parameters) {
+ stream << " " << kv.first;
+ }
+ AIDL_ERROR(this) << stream.str();
+ continue;
+ }
AidlTypeSpecifier type{AIDL_LOCATION_HERE, schema_.supported_parameters.at(param_name), false,
nullptr, ""};
if (!param->CheckValid()) {
AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
<< GetName() << ".";
- raw_params.clear();
- return raw_params;
+ continue;
}
raw_params.emplace(param_name, param->ValueString(type, decorator));
@@ -396,12 +406,12 @@
bool AidlTypeSpecifier::Resolve(const AidlTypenames& typenames) {
CHECK(!IsResolved());
- pair<string, bool> result = typenames.ResolveTypename(unresolved_name_);
- if (result.second) {
- fully_qualified_name_ = result.first;
+ AidlTypenames::ResolvedTypename result = typenames.ResolveTypename(unresolved_name_);
+ if (result.is_resolved) {
+ fully_qualified_name_ = result.canonical_name;
split_name_ = Split(fully_qualified_name_, ".");
}
- return result.second;
+ return result.is_resolved;
}
std::set<AidlAnnotation::Type> AidlTypeSpecifier::GetSupportedAnnotations() const {
@@ -822,7 +832,24 @@
}
// TODO: we should treat every backend all the same in future.
-bool AidlTypeSpecifier::LanguageSpecificCheckValid(Options::Language lang) const {
+bool AidlTypeSpecifier::LanguageSpecificCheckValid(const AidlTypenames& typenames,
+ Options::Language lang) const {
+ if (lang == Options::Language::NDK && IsArray() && GetName() == "IBinder") {
+ AIDL_ERROR(this) << "The NDK backend does not support array of IBinder";
+ return false;
+ }
+ if (lang == Options::Language::NDK && IsArray() && IsNullable()) {
+ if (GetName() == "ParcelFileDescriptor") {
+ AIDL_ERROR(this) << "The NDK backend does not support nullable array of ParcelFileDescriptor";
+ return false;
+ }
+
+ const auto defined_type = typenames.TryGetDefinedType(GetName());
+ if (defined_type != nullptr && defined_type->AsParcelable() != nullptr) {
+ AIDL_ERROR(this) << "The NDK backend does not support nullable array of parcelable";
+ return false;
+ }
+ }
if (lang != Options::Language::JAVA) {
if (this->GetName() == "List" && !this->IsGeneric()) {
AIDL_ERROR(this) << "Currently, only the Java backend supports non-generic List.";
@@ -881,7 +908,8 @@
}
// TODO: we should treat every backend all the same in future.
-bool AidlParcelable::LanguageSpecificCheckValid(Options::Language lang) const {
+bool AidlParcelable::LanguageSpecificCheckValid(const AidlTypenames& /*typenames*/,
+ Options::Language lang) const {
if (lang != Options::Language::JAVA) {
const AidlParcelable* unstructured_parcelable = this->AsUnstructuredParcelable();
if (unstructured_parcelable != nullptr) {
@@ -896,12 +924,13 @@
}
// TODO: we should treat every backend all the same in future.
-bool AidlStructuredParcelable::LanguageSpecificCheckValid(Options::Language lang) const {
- if (!AidlParcelable::LanguageSpecificCheckValid(lang)) {
+bool AidlStructuredParcelable::LanguageSpecificCheckValid(const AidlTypenames& typenames,
+ Options::Language lang) const {
+ if (!AidlParcelable::LanguageSpecificCheckValid(typenames, lang)) {
return false;
}
for (const auto& v : this->GetFields()) {
- if (!v->GetType().LanguageSpecificCheckValid(lang)) {
+ if (!v->GetType().LanguageSpecificCheckValid(typenames, lang)) {
return false;
}
}
@@ -997,13 +1026,14 @@
}
// TODO: we should treat every backend all the same in future.
-bool AidlInterface::LanguageSpecificCheckValid(Options::Language lang) const {
+bool AidlInterface::LanguageSpecificCheckValid(const AidlTypenames& typenames,
+ Options::Language lang) const {
for (const auto& m : this->GetMethods()) {
- if (!m->GetType().LanguageSpecificCheckValid(lang)) {
+ if (!m->GetType().LanguageSpecificCheckValid(typenames, lang)) {
return false;
}
for (const auto& arg : m->GetArguments()) {
- if (!arg->GetType().LanguageSpecificCheckValid(lang)) {
+ if (!arg->GetType().LanguageSpecificCheckValid(typenames, lang)) {
return false;
}
}
diff --git a/aidl_language.h b/aidl_language.h
index 44c8078..2d388e8 100644
--- a/aidl_language.h
+++ b/aidl_language.h
@@ -356,7 +356,7 @@
std::set<AidlAnnotation::Type> GetSupportedAnnotations() const override;
bool CheckValid(const AidlTypenames& typenames) const override;
- bool LanguageSpecificCheckValid(Options::Language lang) const;
+ bool LanguageSpecificCheckValid(const AidlTypenames& typenames, Options::Language lang) const;
const AidlNode& AsAidlNode() const override { return *this; }
private:
@@ -706,7 +706,8 @@
virtual const AidlInterface* AsInterface() const { return nullptr; }
virtual const AidlParameterizable<std::string>* AsParameterizable() const { return nullptr; }
bool CheckValid(const AidlTypenames& typenames) const override;
- virtual bool LanguageSpecificCheckValid(Options::Language lang) const = 0;
+ virtual bool LanguageSpecificCheckValid(const AidlTypenames& typenames,
+ Options::Language lang) const = 0;
AidlStructuredParcelable* AsStructuredParcelable() {
return const_cast<AidlStructuredParcelable*>(
const_cast<const AidlDefinedType*>(this)->AsStructuredParcelable());
@@ -761,7 +762,8 @@
std::set<AidlAnnotation::Type> GetSupportedAnnotations() const override;
bool CheckValid(const AidlTypenames& typenames) const override;
- bool LanguageSpecificCheckValid(Options::Language lang) const override;
+ bool LanguageSpecificCheckValid(const AidlTypenames& typenames,
+ Options::Language lang) const override;
const AidlParcelable* AsParcelable() const override { return this; }
const AidlParameterizable<std::string>* AsParameterizable() const override { return this; }
const AidlNode& AsAidlNode() const override { return *this; }
@@ -793,7 +795,8 @@
std::set<AidlAnnotation::Type> GetSupportedAnnotations() const override;
bool CheckValid(const AidlTypenames& typenames) const override;
- bool LanguageSpecificCheckValid(Options::Language lang) const override;
+ bool LanguageSpecificCheckValid(const AidlTypenames& typenames,
+ Options::Language lang) const override;
private:
const std::vector<std::unique_ptr<AidlVariableDeclaration>> variables_;
@@ -840,7 +843,10 @@
bool Autofill();
std::set<AidlAnnotation::Type> GetSupportedAnnotations() const override;
bool CheckValid(const AidlTypenames& typenames) const override;
- bool LanguageSpecificCheckValid(Options::Language) const override { return true; }
+ bool LanguageSpecificCheckValid(const AidlTypenames& /*typenames*/,
+ Options::Language) const override {
+ return true;
+ }
std::string GetPreprocessDeclarationName() const override { return "enum"; }
void Dump(CodeWriter* writer) const override;
@@ -875,7 +881,8 @@
std::set<AidlAnnotation::Type> GetSupportedAnnotations() const override;
bool CheckValid(const AidlTypenames& typenames) const override;
- bool LanguageSpecificCheckValid(Options::Language lang) const override;
+ bool LanguageSpecificCheckValid(const AidlTypenames& typenames,
+ Options::Language lang) const override;
private:
std::vector<std::unique_ptr<AidlMethod>> methods_;
diff --git a/aidl_language_y.yy b/aidl_language_y.yy
index 3a1fda9..9784625 100644
--- a/aidl_language_y.yy
+++ b/aidl_language_y.yy
@@ -116,7 +116,7 @@
%token '(' ')' ',' '=' '[' ']' '.' '{' '}' ';'
%token UNKNOWN "unrecognized character"
-%token CPP_HEADER "cpp_header"
+%token CPP_HEADER "cpp_header (which can also be used as an identifier)"
%token IMPORT "import"
%token IN "in"
%token INOUT "inout"
diff --git a/aidl_to_ndk.cpp b/aidl_to_ndk.cpp
index 8b4bc1c..e5ac195 100644
--- a/aidl_to_ndk.cpp
+++ b/aidl_to_ndk.cpp
@@ -364,15 +364,18 @@
if (aidl.IsArray()) {
if (aidl.IsNullable()) {
- AIDL_FATAL_IF(info.nullable_array == nullptr, aidl) << "Unsupported type in NDK Backend.";
+ AIDL_FATAL_IF(info.nullable_array == nullptr, aidl)
+ << "Unsupported type in NDK Backend: " << aidl.ToString();
return *info.nullable_array;
}
- AIDL_FATAL_IF(info.array == nullptr, aidl) << "Unsupported type in NDK Backend.";
+ AIDL_FATAL_IF(info.array == nullptr, aidl)
+ << "Unsupported type in NDK Backend: " << aidl.ToString();
return *info.array;
}
if (aidl.IsNullable()) {
- AIDL_FATAL_IF(info.nullable == nullptr, aidl) << "Unsupported type in NDK Backend.";
+ AIDL_FATAL_IF(info.nullable == nullptr, aidl)
+ << "Unsupported type in NDK Backend: " << aidl.ToString();
return *info.nullable;
}
diff --git a/aidl_typenames.cpp b/aidl_typenames.cpp
index ad89c1c..349ccbe 100644
--- a/aidl_typenames.cpp
+++ b/aidl_typenames.cpp
@@ -64,21 +64,30 @@
// in Java and C++. Using these names will eventually cause compilation error,
// so checking this here is not a must have, but early detection of errors
// is always better.
-static const set<string> kInvalidNames = {
+static const set<string> kCppOrJavaReservedWord = {
"break", "case", "catch", "char", "class", "continue", "default",
"do", "double", "else", "enum", "false", "float", "for",
"goto", "if", "int", "long", "new", "private", "protected",
"public", "return", "short", "static", "switch", "this", "throw",
"true", "try", "void", "volatile", "while"};
-static bool IsValidName(const string& name) {
- vector<string> pieces = Split(name, ".");
- for (const auto& piece : pieces) {
- if (kInvalidNames.find(piece) != kInvalidNames.end()) {
- return false;
+static bool HasValidNameComponents(const AidlDefinedType& defined) {
+ bool success = true;
+ vector<string> pieces = Split(defined.GetCanonicalName(), ".");
+ for (const string& piece : pieces) {
+ if (kCppOrJavaReservedWord.find(piece) != kCppOrJavaReservedWord.end()) {
+ AIDL_ERROR(defined) << defined.GetCanonicalName() << " is an invalid name because '" << piece
+ << "' is a Java or C++ identifier.";
+ success = false;
+ }
+ // not checking kJavaLikeTypeToAidl, since that wouldn't make sense here
+ if (kBuiltinTypes.find(piece) != kBuiltinTypes.end()) {
+ AIDL_ERROR(defined) << defined.GetCanonicalName() << " is an invalid name because '" << piece
+ << "' is a built-in AIDL type.";
+ success = false;
}
}
- return true;
+ return success;
}
bool AidlTypenames::IsIgnorableImport(const string& import) const {
@@ -99,7 +108,7 @@
if (defined_types_.find(name) != defined_types_.end()) {
return false;
}
- if (!IsValidName(type->GetPackage()) || !IsValidName(type->GetName())) {
+ if (!HasValidNameComponents(*type)) {
return false;
}
defined_types_.emplace(name, std::move(type));
@@ -111,7 +120,7 @@
if (preprocessed_types_.find(name) != preprocessed_types_.end()) {
return false;
}
- if (!IsValidName(type->GetPackage()) || !IsValidName(type->GetName())) {
+ if (!HasValidNameComponents(*type)) {
return false;
}
preprocessed_types_.insert(make_pair(name, std::move(type)));
@@ -161,19 +170,19 @@
return DefinedImplResult(nullptr, false);
}
-pair<string, bool> AidlTypenames::ResolveTypename(const string& type_name) const {
+AidlTypenames::ResolvedTypename AidlTypenames::ResolveTypename(const string& type_name) const {
if (IsBuiltinTypename(type_name)) {
auto found = kJavaLikeTypeToAidlType.find(type_name);
if (found != kJavaLikeTypeToAidlType.end()) {
- return make_pair(found->second, true);
+ return {found->second, true};
}
- return make_pair(type_name, true);
+ return {type_name, true};
}
const AidlDefinedType* defined_type = TryGetDefinedType(type_name);
if (defined_type != nullptr) {
- return make_pair(defined_type->GetCanonicalName(), true);
+ return {defined_type->GetCanonicalName(), true};
} else {
- return make_pair(type_name, false);
+ return {type_name, false};
}
}
diff --git a/aidl_typenames.h b/aidl_typenames.h
index 78b996f..3b01ada 100644
--- a/aidl_typenames.h
+++ b/aidl_typenames.h
@@ -58,7 +58,12 @@
static bool IsBuiltinTypename(const string& type_name);
static bool IsPrimitiveTypename(const string& type_name);
const AidlDefinedType* TryGetDefinedType(const string& type_name) const;
- pair<string, bool> ResolveTypename(const string& type_name) const;
+
+ struct ResolvedTypename {
+ std::string canonical_name;
+ bool is_resolved;
+ };
+ ResolvedTypename ResolveTypename(const string& type_name) const;
bool CanBeOutParameter(const AidlTypeSpecifier& type) const;
bool IsIgnorableImport(const string& import) const;
// Returns the AidlEnumDeclaration of the given type, or nullptr if the type
diff --git a/aidl_unittest.cpp b/aidl_unittest.cpp
index 99f8cdc..6266ee3 100644
--- a/aidl_unittest.cpp
+++ b/aidl_unittest.cpp
@@ -20,6 +20,7 @@
#include <vector>
#include <android-base/stringprintf.h>
+#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "aidl.h"
@@ -451,6 +452,24 @@
EXPECT_NE(nullptr, Parse("a/IFoo.aidl", oneway_method, typenames_, GetLanguage()));
}
+TEST_P(AidlTest, AnnotationsInMultiplePlaces) {
+ const string oneway_method =
+ "package a; interface IFoo { @UnsupportedAppUsage oneway @Hide void f(int a); }";
+ const AidlDefinedType* defined = Parse("a/IFoo.aidl", oneway_method, typenames_, GetLanguage());
+ ASSERT_NE(nullptr, defined);
+ const AidlInterface* iface = defined->AsInterface();
+ ASSERT_NE(nullptr, iface);
+
+ const auto& methods = iface->GetMethods();
+ ASSERT_EQ(1u, methods.size());
+ const auto& method = methods[0];
+ const AidlTypeSpecifier& ret_type = method->GetType();
+
+ // TODO(b/151102494): these annotations should be on the method
+ ASSERT_NE(nullptr, ret_type.UnsupportedAppUsage());
+ ASSERT_TRUE(ret_type.IsHide());
+}
+
TEST_P(AidlTest, WritesComments) {
string foo_interface =
"package a; /* foo */ interface IFoo {"
@@ -471,20 +490,20 @@
TEST_F(AidlTest, ParsesPreprocessedFile) {
string simple_content = "parcelable a.Foo;\ninterface b.IBar;";
io_delegate_.SetFileContents("path", simple_content);
- EXPECT_FALSE(typenames_.ResolveTypename("a.Foo").second);
+ EXPECT_FALSE(typenames_.ResolveTypename("a.Foo").is_resolved);
EXPECT_TRUE(parse_preprocessed_file(io_delegate_, "path", &typenames_));
- EXPECT_TRUE(typenames_.ResolveTypename("a.Foo").second);
- EXPECT_TRUE(typenames_.ResolveTypename("b.IBar").second);
+ EXPECT_TRUE(typenames_.ResolveTypename("a.Foo").is_resolved);
+ EXPECT_TRUE(typenames_.ResolveTypename("b.IBar").is_resolved);
}
TEST_F(AidlTest, ParsesPreprocessedFileWithWhitespace) {
string simple_content = "parcelable a.Foo;\n interface b.IBar ;\t";
io_delegate_.SetFileContents("path", simple_content);
- EXPECT_FALSE(typenames_.ResolveTypename("a.Foo").second);
+ EXPECT_FALSE(typenames_.ResolveTypename("a.Foo").is_resolved);
EXPECT_TRUE(parse_preprocessed_file(io_delegate_, "path", &typenames_));
- EXPECT_TRUE(typenames_.ResolveTypename("a.Foo").second);
- EXPECT_TRUE(typenames_.ResolveTypename("b.IBar").second);
+ EXPECT_TRUE(typenames_.ResolveTypename("a.Foo").is_resolved);
+ EXPECT_TRUE(typenames_.ResolveTypename("b.IBar").is_resolved);
}
TEST_P(AidlTest, PreferImportToPreprocessed) {
@@ -498,8 +517,8 @@
EXPECT_NE(nullptr, parse_result);
// We expect to know about both kinds of IBar
- EXPECT_TRUE(typenames_.ResolveTypename("one.IBar").second);
- EXPECT_TRUE(typenames_.ResolveTypename("another.IBar").second);
+ EXPECT_TRUE(typenames_.ResolveTypename("one.IBar").is_resolved);
+ EXPECT_TRUE(typenames_.ResolveTypename("another.IBar").is_resolved);
// But if we request just "IBar" we should get our imported one.
AidlTypeSpecifier ambiguous_type(AIDL_LOCATION_HERE, "IBar", false, nullptr, "");
ambiguous_type.Resolve(typenames_);
@@ -520,8 +539,8 @@
EXPECT_NE(nullptr, parse_result);
// We expect to know about both kinds of IBar
- EXPECT_TRUE(typenames_.ResolveTypename("one.IBar").second);
- EXPECT_TRUE(typenames_.ResolveTypename("another.IBar").second);
+ EXPECT_TRUE(typenames_.ResolveTypename("one.IBar").is_resolved);
+ EXPECT_TRUE(typenames_.ResolveTypename("another.IBar").is_resolved);
// But if we request just "IBar" we should get our imported one.
AidlTypeSpecifier ambiguous_type(AIDL_LOCATION_HERE, "IBar", false, nullptr, "");
ambiguous_type.Resolve(typenames_);
@@ -761,8 +780,7 @@
auto parse_result = Parse(input_path, input, typenames_, GetLanguage());
EXPECT_NE(nullptr, parse_result);
- auto pair = typenames_.ResolveTypename("p.Outer.Inner");
- EXPECT_TRUE(pair.second);
+ EXPECT_TRUE(typenames_.ResolveTypename("p.Outer.Inner").is_resolved);
// C++ uses "::" instead of "." to refer to a inner class.
AidlTypeSpecifier nested_type(AIDL_LOCATION_HERE, "p.Outer.Inner", false, nullptr, "");
EXPECT_EQ("::p::Outer::Inner", cpp::CppNameOf(nested_type, typenames_));
@@ -777,8 +795,7 @@
const string input = "package p; import p.Bar; interface IFoo { }";
auto parse_result = Parse(input_path, input, typenames_, GetLanguage());
EXPECT_NE(nullptr, parse_result);
- auto pair = typenames_.ResolveTypename("p.Bar");
- EXPECT_TRUE(pair.second);
+ EXPECT_TRUE(typenames_.ResolveTypename("p.Bar").is_resolved);
AidlTypeSpecifier native_type(AIDL_LOCATION_HERE, "p.Bar", false, nullptr, "");
native_type.Resolve(typenames_);
@@ -911,6 +928,37 @@
EXPECT_EQ(expected_stderr, GetCapturedStderr());
}
+TEST_P(AidlTest, RejectsPrimitiveListInStableAidl) {
+ AidlError error;
+ string expected_stderr =
+ "ERROR: a/IFoo.aidl:2.7-11: "
+ "Encountered an untyped List or Map. The use of untyped List/Map is "
+ "prohibited because it is not guaranteed that the objects in the list are recognizable in "
+ "the receiving side. Consider switching to an array or a generic List/Map.\n";
+ if (GetLanguage() != Options::Language::JAVA) {
+ expected_stderr =
+ "ERROR: a/IFoo.aidl:2.1-7: "
+ "Currently, only the Java backend supports non-generic List.\n";
+ }
+
+ const string primitive_interface =
+ "package a; interface IFoo {\n"
+ " List foo(); }";
+ CaptureStderr();
+ EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", primitive_interface, typenames_, GetLanguage(), &error,
+ {"--structured"}));
+ EXPECT_EQ(expected_stderr, GetCapturedStderr());
+ typenames_.Reset();
+
+ string primitive_parcelable =
+ "package a; parcelable IFoo {\n"
+ " List foo;}";
+ CaptureStderr();
+ EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", primitive_parcelable, typenames_, GetLanguage(), &error,
+ {"--structured"}));
+ EXPECT_EQ(expected_stderr, GetCapturedStderr());
+}
+
TEST_F(AidlTest, ApiDump) {
io_delegate_.SetFileContents(
"foo/bar/IFoo.aidl",
@@ -1323,6 +1371,7 @@
"interface IFoo {"
" void foo(int a);"
" void bar();"
+ " void baz(in List<IFoo> arg);"
"}");
EXPECT_TRUE(::android::aidl::check_api(options_, io_delegate_));
}
@@ -1337,7 +1386,8 @@
"package p;"
"parcelable Data {"
" int foo;"
- " int bar;"
+ " int bar = 0;"
+ " @nullable List<Data> list;"
"}");
EXPECT_TRUE(::android::aidl::check_api(options_, io_delegate_));
}
@@ -1478,6 +1528,52 @@
EXPECT_EQ(expected_stderr, GetCapturedStderr());
}
+TEST_F(AidlTestIncompatibleChanges, UntypedListInInterface) {
+ const string expected_stderr =
+ "ERROR: new/p/IFoo.aidl:1.61-65: "
+ "Encountered an untyped List or Map. The use of untyped List/Map is "
+ "prohibited because it is not guaranteed that the objects in the list are recognizable in "
+ "the receiving side. Consider switching to an array or a generic List/Map.\n"
+ "ERROR: new/p/IFoo.aidl: Failed to read.\n";
+ io_delegate_.SetFileContents("old/p/IFoo.aidl",
+ "package p;"
+ "interface IFoo {"
+ " void foo(in String[] str);"
+ "}");
+ io_delegate_.SetFileContents("new/p/IFoo.aidl",
+ "package p;"
+ "interface IFoo {"
+ " void foo(in String[] str);"
+ " void bar(in List arg);"
+ "}");
+ CaptureStderr();
+ EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
+ EXPECT_EQ(expected_stderr, GetCapturedStderr());
+}
+
+TEST_F(AidlTestCompatibleChanges, UntypedListInParcelable) {
+ const string expected_stderr =
+ "ERROR: new/p/Data.aidl:1.54-59: "
+ "Encountered an untyped List or Map. The use of untyped List/Map is "
+ "prohibited because it is not guaranteed that the objects in the list are recognizable in "
+ "the receiving side. Consider switching to an array or a generic List/Map.\n"
+ "ERROR: new/p/Data.aidl: Failed to read.\n";
+ io_delegate_.SetFileContents("old/p/Data.aidl",
+ "package p;"
+ "parcelable Data {"
+ " int foo;"
+ "}");
+ io_delegate_.SetFileContents("new/p/Data.aidl",
+ "package p;"
+ "parcelable Data {"
+ " int foo;"
+ " @nullable List list;"
+ "}");
+ CaptureStderr();
+ EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
+ EXPECT_EQ(expected_stderr, GetCapturedStderr());
+}
+
TEST_F(AidlTestIncompatibleChanges, RemovedField) {
const string expected_stderr =
"ERROR: new/p/Data.aidl:1.21-26: Number of fields in p.Data is reduced from 2 to 1.\n";
@@ -1536,25 +1632,6 @@
EXPECT_EQ(expected_stderr, GetCapturedStderr());
}
-TEST_F(AidlTestIncompatibleChanges, RenamedField) {
- const string expected_stderr = "ERROR: new/p/Data.aidl:1.21-26: Renamed field: bar to bar2.\n";
- io_delegate_.SetFileContents("old/p/Data.aidl",
- "package p;"
- "parcelable Data {"
- " int foo;"
- " int bar;"
- "}");
- io_delegate_.SetFileContents("new/p/Data.aidl",
- "package p;"
- "parcelable Data {"
- " int foo;"
- " int bar2;"
- "}");
- CaptureStderr();
- EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
- EXPECT_EQ(expected_stderr, GetCapturedStderr());
-}
-
TEST_F(AidlTestIncompatibleChanges, RenamedType) {
const string expected_stderr = "ERROR: old/p/IFoo.aidl:1.11-20: Removed type: p.IFoo\n";
io_delegate_.SetFileContents("old/p/IFoo.aidl",
@@ -1619,8 +1696,8 @@
TEST_F(AidlTestIncompatibleChanges, ReorderedField) {
const string expected_stderr =
- "ERROR: new/p/Data.aidl:1.21-26: Renamed field: foo to bar.\n"
- "ERROR: new/p/Data.aidl:1.21-26: Renamed field: bar to foo.\n";
+ "ERROR: new/p/Data.aidl:1.33-37: Reordered bar from 1 to 0.\n"
+ "ERROR: new/p/Data.aidl:1.43-47: Reordered foo from 0 to 1.\n";
io_delegate_.SetFileContents("old/p/Data.aidl",
"package p;"
"parcelable Data {"
@@ -1708,7 +1785,7 @@
}
TEST_F(AidlTestIncompatibleChanges, ChangedDefaultValue) {
- const string expected_stderr = "ERROR: new/p/D.aidl:1.22-24: Changed default value: 1 to 2.\n";
+ const string expected_stderr = "ERROR: new/p/D.aidl:1.30-32: Changed default value: 1 to 2.\n";
io_delegate_.SetFileContents("old/p/D.aidl", "package p; parcelable D { int a = 1; }");
io_delegate_.SetFileContents("new/p/D.aidl", "package p; parcelable D { int a = 2; }");
CaptureStderr();
@@ -1885,6 +1962,26 @@
EXPECT_EQ(expected_stderr, GetCapturedStderr());
}
+TEST_F(AidlTest, UnusedImportDoesNotContributeInclude) {
+ io_delegate_.SetFileContents("a/b/IFoo.aidl",
+ "package a.b;\n"
+ "import a.b.IBar;\n"
+ "import a.b.IQux;\n"
+ "interface IFoo { IQux foo(); }\n");
+ io_delegate_.SetFileContents("a/b/IBar.aidl", "package a.b; interface IBar { void foo(); }");
+ io_delegate_.SetFileContents("a/b/IQux.aidl", "package a.b; interface IQux { void foo(); }");
+
+ Options options = Options::From("aidl --lang=ndk a/b/IFoo.aidl -I . -o out -h out/include");
+ EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+
+ string output;
+ EXPECT_TRUE(io_delegate_.GetWrittenContents("out/include/aidl/a/b/IFoo.h", &output));
+ // IBar was imported but wasn't used. include is not expected.
+ EXPECT_THAT(output, Not(testing::HasSubstr("#include <aidl/a/b/IBar.h>")));
+ // IBar was imported and used. include is expected.
+ EXPECT_THAT(output, (testing::HasSubstr("#include <aidl/a/b/IQux.h>")));
+}
+
class AidlOutputPathTest : public AidlTest {
protected:
void SetUp() override {
@@ -2003,5 +2100,26 @@
EXPECT_EQ(AidlError::BAD_TYPE, error);
}
+TEST_P(AidlTest, UnsupportedBackingAnnotationParam) {
+ AidlError error;
+ const string expected_stderr =
+ "ERROR: p/TestEnum.aidl:2.1-51: Parameter foo not supported for annotation Backing. It must "
+ "be one of: type\n"
+ "ERROR: p/TestEnum.aidl:2.1-51: Parameter foo not supported for annotation Backing. It must "
+ "be one of: type\n";
+ CaptureStderr();
+ EXPECT_EQ(nullptr, Parse("p/TestEnum.aidl",
+ R"(package p;
+ @Backing(foo="byte")
+ enum TestEnum {
+ FOO = 1,
+ BAR,
+ }
+ )",
+ typenames_, GetLanguage(), &error));
+ EXPECT_EQ(expected_stderr, GetCapturedStderr());
+ EXPECT_EQ(AidlError::BAD_TYPE, error);
+}
+
} // namespace aidl
} // namespace android
diff --git a/build/Android.bp b/build/Android.bp
index d537196..57eccc7 100644
--- a/build/Android.bp
+++ b/build/Android.bp
@@ -105,6 +105,12 @@
imports: [
"test-piece-1",
],
+ backend: {
+ java: {
+ platform_apis: true,
+ },
+ },
+ gen_trace: true,
versions: ["1"],
}
@@ -117,6 +123,12 @@
imports: [
"test-piece-2",
],
+ backend: {
+ java: {
+ platform_apis: true,
+ },
+ },
+ gen_trace: true,
versions: ["1"],
}
@@ -129,6 +141,12 @@
imports: [
"test-piece-1",
],
+ backend: {
+ java: {
+ platform_apis: true,
+ },
+ },
+ gen_trace: true,
versions: ["1"],
}
@@ -140,6 +158,12 @@
imports: [
"test-piece-2",
],
+ backend: {
+ java: {
+ platform_apis: true,
+ },
+ },
+ gen_trace: true,
versions: [
"1",
"2",
diff --git a/build/aidl_interface.go b/build/aidl_interface.go
index 2f49307..4fb9285 100644
--- a/build/aidl_interface.go
+++ b/build/aidl_interface.go
@@ -480,8 +480,7 @@
i, err := strconv.Atoi(latestVersion)
if err != nil {
- ctx.PropertyErrorf("versions", "%q is not an integer", latestVersion)
- return ""
+ panic(err)
}
return strconv.Itoa(i + 1)
@@ -920,22 +919,38 @@
}
}
+func (i *aidlInterface) checkGenTrace(mctx android.LoadHookContext) {
+ if !proptools.Bool(i.properties.Gen_trace) {
+ return
+ }
+ if i.shouldGenerateJavaBackend() && !proptools.Bool(i.properties.Backend.Java.Platform_apis) {
+ mctx.PropertyErrorf("gen_trace", "must be false when Java backend is enabled and platform_apis is false")
+ }
+}
+
func (i *aidlInterface) checkStability(mctx android.LoadHookContext) {
if i.properties.Stability == nil {
return
}
+ if proptools.Bool(i.properties.Unstable) {
+ mctx.PropertyErrorf("stability", "must be empty when \"unstable\" is true")
+ }
+
// TODO(b/136027762): should we allow more types of stability (e.g. for APEX) or
// should we switch this flag to be something like "vintf { enabled: true }"
isVintf := "vintf" == proptools.String(i.properties.Stability)
if !isVintf {
mctx.PropertyErrorf("stability", "must be empty or \"vintf\"")
}
-
- // TODO(b/152655544): might need to change the condition
- sdkIsFinal := mctx.Config().DefaultAppTargetSdkInt() != android.FutureApiLevel
- if sdkIsFinal && !i.hasVersion() && isVintf && i.Owner() == "" {
- mctx.PropertyErrorf("versions", "must be set(need to be frozen) when stability is \"vintf\" and PLATFORM_VERSION_CODENAME is REL.")
+}
+func (i *aidlInterface) checkVersions(mctx android.LoadHookContext) {
+ for _, ver := range i.properties.Versions {
+ _, err := strconv.Atoi(ver)
+ if err != nil {
+ mctx.PropertyErrorf("versions", "%q is not an integer", ver)
+ continue
+ }
}
}
@@ -946,8 +961,7 @@
ver := i.latestVersion()
i, err := strconv.Atoi(ver)
if err != nil {
- ctx.PropertyErrorf("versions", "%q is not an integer", ver)
- return ""
+ panic(err)
}
return strconv.Itoa(i + 1)
@@ -1040,6 +1054,8 @@
i.gatherInterface(mctx)
i.checkStability(mctx)
+ i.checkVersions(mctx)
+ i.checkGenTrace(mctx)
if mctx.Failed() {
return
@@ -1121,6 +1137,10 @@
mctx.ModuleErrorf("unstable:true and stability:%q cannot happen at the same time", i.properties.Stability)
}
} else {
+ sdkIsFinal := mctx.Config().DefaultAppTargetSdkInt() != android.FutureApiLevel
+ if sdkIsFinal && !i.hasVersion() && i.Owner() == "" {
+ mctx.PropertyErrorf("versions", "must be set (need to be frozen) when \"unstable\" is false and PLATFORM_VERSION_CODENAME is REL.")
+ }
addApiModule(mctx, i)
}
@@ -1188,8 +1208,10 @@
})
importExportDependencies := wrap("", i.properties.Imports, "-"+lang)
+ var sharedLibDependency []string
var libJSONCppDependency []string
var staticLibDependency []string
+ var headerLibs []string
var sdkVersion *string
var minSdkVersion *string
var stl *string
@@ -1203,7 +1225,7 @@
libJSONCppDependency = []string{"libjsoncpp"}
}
if genTrace {
- importExportDependencies = append(importExportDependencies, "libcutils")
+ sharedLibDependency = append(sharedLibDependency, "libcutils")
}
hostSupported = i.properties.Host_supported
minSdkVersion = i.properties.Backend.Cpp.Min_sdk_version
@@ -1212,6 +1234,9 @@
if genLog {
staticLibDependency = []string{"libjsoncpp_ndk"}
}
+ if genTrace {
+ sharedLibDependency = append(sharedLibDependency, "libandroid")
+ }
sdkVersion = proptools.StringPtr("current")
stl = proptools.StringPtr("c++_shared")
minSdkVersion = i.properties.Backend.Ndk.Min_sdk_version
@@ -1220,6 +1245,10 @@
if genLog {
libJSONCppDependency = []string{"libjsoncpp"}
}
+ if genTrace {
+ headerLibs = append(headerLibs, "libandroid_aidltrace")
+ sharedLibDependency = append(sharedLibDependency, "libcutils")
+ }
hostSupported = i.properties.Host_supported
addCflags = append(addCflags, "-DBINDER_STABILITY_SUPPORT")
minSdkVersion = i.properties.Backend.Ndk.Min_sdk_version
@@ -1250,7 +1279,8 @@
Static: staticLib{Whole_static_libs: libJSONCppDependency},
Shared: sharedLib{Shared_libs: libJSONCppDependency, Export_shared_lib_headers: libJSONCppDependency},
Static_libs: staticLibDependency,
- Shared_libs: importExportDependencies,
+ Shared_libs: append(importExportDependencies, sharedLibDependency...),
+ Header_libs: headerLibs,
Export_shared_lib_headers: importExportDependencies,
Sdk_version: sdkVersion,
Stl: stl,
@@ -1294,6 +1324,7 @@
Lang: langJava,
BaseName: i.ModuleBase.Name(),
Version: version,
+ GenTrace: proptools.Bool(i.properties.Gen_trace),
Unstable: i.properties.Unstable,
})
diff --git a/build/aidl_test.go b/build/aidl_test.go
index 9732675..8d40040 100644
--- a/build/aidl_test.go
+++ b/build/aidl_test.go
@@ -22,6 +22,7 @@
"testing"
"github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
"android/soong/android"
"android/soong/cc"
@@ -63,6 +64,13 @@
}
}
+func setReleaseEnv() testCustomizer {
+ return func(_ map[string][]byte, config android.Config) {
+ config.TestProductVariables.Platform_sdk_codename = proptools.StringPtr("REL")
+ config.TestProductVariables.Platform_sdk_final = proptools.BoolPtr(true)
+ }
+}
+
func _testAidl(t *testing.T, bp string, customizers ...testCustomizer) (*android.TestContext, android.Config) {
t.Helper()
@@ -120,6 +128,11 @@
config := android.TestArchConfig(buildDir, nil, bp, fs)
+ // To keep tests stable, fix Platform_sdk_codename and Platform_sdk_final
+ // Use setReleaseEnv() to test release version
+ config.TestProductVariables.Platform_sdk_codename = proptools.StringPtr("Q")
+ config.TestProductVariables.Platform_sdk_final = proptools.BoolPtr(false)
+
for _, c := range customizers {
// The fs now needs to be populated before creating the config, call customizers twice
// for now, earlier to get any fs changes, and now after the config was created to
@@ -143,7 +156,9 @@
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
ctx.PostDepsMutators(android.RegisterOverridePostDepsMutators)
-
+ ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.BottomUp("checkUnstableModule", checkUnstableModuleMutator).Parallel()
+ })
ctx.Register(config)
return ctx, config
@@ -194,6 +209,153 @@
}
}
+// Vintf module must have versions in release version
+func TestVintfWithoutVersionInRelease(t *testing.T) {
+ vintfWithoutVersionBp := `
+ aidl_interface {
+ name: "foo",
+ stability: "vintf",
+ srcs: [
+ "IFoo.aidl",
+ ],
+ }`
+ expectedError := `module "foo_interface": versions: must be set \(need to be frozen\) when "unstable" is false and PLATFORM_VERSION_CODENAME is REL`
+ testAidlError(t, expectedError, vintfWithoutVersionBp, setReleaseEnv())
+
+ ctx, _ := testAidl(t, vintfWithoutVersionBp)
+ assertModulesExists(t, ctx, "foo-java", "foo-cpp", "foo-ndk", "foo-ndk_platform")
+}
+
+// Check if using unstable version in release cause an error.
+func TestUnstableVersionUsageInRelease(t *testing.T) {
+ unstableVersionUsageInJavaBp := `
+ aidl_interface {
+ name: "foo",
+ versions: [
+ "1",
+ ],
+ srcs: [
+ "IFoo.aidl",
+ ],
+ }
+ java_library {
+ name: "bar",
+ libs: ["foo-unstable-java"],
+ }`
+
+ expectedError := `unstable-java is disallowed in release version because it is unstable.`
+ testAidlError(t, expectedError, unstableVersionUsageInJavaBp, setReleaseEnv(), withFiles(map[string][]byte{
+ "aidl_api/foo/1/foo.1.aidl": nil,
+ "aidl_api/foo/1/.hash": nil,
+ }))
+
+ testAidl(t, unstableVersionUsageInJavaBp, withFiles(map[string][]byte{
+ "aidl_api/foo/1/foo.1.aidl": nil,
+ "aidl_api/foo/1/.hash": nil,
+ }))
+
+ // A stable version can be used in release version
+ stableVersionUsageInJavaBp := `
+ aidl_interface {
+ name: "foo",
+ versions: [
+ "1",
+ ],
+ srcs: [
+ "IFoo.aidl",
+ ],
+ }
+ java_library {
+ name: "bar",
+ libs: ["foo-java"],
+ }`
+
+ testAidl(t, stableVersionUsageInJavaBp, setReleaseEnv(), withFiles(map[string][]byte{
+ "aidl_api/foo/1/foo.1.aidl": nil,
+ "aidl_api/foo/1/.hash": nil,
+ }))
+
+ testAidl(t, stableVersionUsageInJavaBp, withFiles(map[string][]byte{
+ "aidl_api/foo/1/foo.1.aidl": nil,
+ "aidl_api/foo/1/.hash": nil,
+ }))
+}
+
+// The module which has never been frozen and is not "unstable" is not allowed in release version.
+func TestNonVersionedModuleUsageInRelease(t *testing.T) {
+ nonVersionedModuleUsageInJavaBp := `
+ aidl_interface {
+ name: "foo",
+ srcs: [
+ "IFoo.aidl",
+ ],
+ }
+
+ java_library {
+ name: "bar",
+ libs: ["foo-java"],
+ }`
+
+ expectedError := `"foo_interface": versions: must be set \(need to be frozen\) when "unstable" is false and PLATFORM_VERSION_CODENAME is REL.`
+ testAidlError(t, expectedError, nonVersionedModuleUsageInJavaBp, setReleaseEnv())
+ testAidl(t, nonVersionedModuleUsageInJavaBp)
+
+ nonVersionedUnstableModuleUsageInJavaBp := `
+ aidl_interface {
+ name: "foo",
+ srcs: [
+ "IFoo.aidl",
+ ],
+ unstable: true,
+ }
+
+ java_library {
+ name: "bar",
+ libs: ["foo-java"],
+ }`
+
+ testAidl(t, nonVersionedUnstableModuleUsageInJavaBp, setReleaseEnv())
+ testAidl(t, nonVersionedUnstableModuleUsageInJavaBp)
+}
+
+func TestUnstableModules(t *testing.T) {
+ testAidlError(t, `module "foo_interface": stability: must be empty when "unstable" is true`, `
+ aidl_interface {
+ name: "foo",
+ stability: "vintf",
+ unstable: true,
+ srcs: [
+ "IFoo.aidl",
+ ],
+ }
+ `)
+
+ testAidlError(t, `module "foo_interface": versions: cannot have versions for an unstable interface`, `
+ aidl_interface {
+ name: "foo",
+ versions: [
+ "1",
+ ],
+ unstable: true,
+ srcs: [
+ "IFoo.aidl",
+ ],
+ }
+ `)
+
+ ctx, _ := testAidl(t, `
+ aidl_interface {
+ name: "foo",
+ unstable: true,
+ srcs: [
+ "IFoo.aidl",
+ ],
+ }
+ `)
+
+ assertModulesExists(t, ctx, "foo-java", "foo-cpp", "foo-ndk", "foo-ndk_platform")
+}
+
func TestCreatesModulesWithNoVersions(t *testing.T) {
ctx, _ := testAidl(t, `
aidl_interface {
diff --git a/build/properties.go b/build/properties.go
index 60d6a3f..eb52a52 100644
--- a/build/properties.go
+++ b/build/properties.go
@@ -39,6 +39,7 @@
Shared_libs []string
Export_shared_lib_headers []string
Export_generated_headers []string
+ Header_libs []string
Sdk_version *string
Stl *string
Cpp_std *string
diff --git a/docs/aidl-cpp.md b/docs/aidl-cpp.md
deleted file mode 100644
index aa97aa9..0000000
--- a/docs/aidl-cpp.md
+++ /dev/null
@@ -1,270 +0,0 @@
-# Generating C++ Binder Interfaces with `aidl-cpp`
-
-## Background
-
-“aidl” refers to several related but distinct concepts:
-
- - the AIDL interface [definition language](http://developer.android.com/guide/components/aidl.html)
- - .aidl files (which contain AIDL)
- - the aidl generator which transforms AIDL into client/server IPC interfaces
-
-The _aidl generator_ is a command line tool that generates client and server
-stubs for Binder interfaces from a specification in a file with the .aidl
-extension. For Java interfaces, the executable is called `aidl` while for C++
-the binary is called `aidl-cpp`. In this document, we’ll use AIDL to describe
-the language of .aidl files and _aidl generator_ to refer to the code generation
-tool that takes an .aidl file, parses the AIDL, and outputs code.
-
-Previously, the _aidl generator_ only generated Java interface/stub/proxy
-objects. C++ Binder interfaces were handcrafted with various degrees of
-compatibility with the Java equivalents. The Brillo project added support for
-generating C++ with the _aidl generator_. This generated C++ is cross-language
-compatible (e.g. Java clients are tested to interoperate with native services).
-
-## Overview
-
-This document describes how C++ generation works with attention to:
-
- - build interface
- - cross-language type mapping
- - implementing a generated interface
- - C++ parcelables
- - cross-language error reporting
- - cross-language null reference handling
-
-## Detailed Design
-
-### Build Interface
-
-Write AIDL in .aidl files and add them to `LOCAL_SRC_FILES` in your Android.mk.
-If your build target is a binary (e.g. you include `$(BUILD_SHARED_LIBRARY)`),
-then the generated code will be C++, not Java.
-
-AIDL definitions should be hosted from the same repository as the
-implementation. Any system that needs the definition will also need the
-implementation (for both parcelables and interface). If there are multiple
-implementations (i.e. one in Java and one in C++), keep the definition with the
-native implementation. Android
-[now has systems](https://developers.google.com/brillo/?hl=en) that run the
-native components of the system without the Java.
-
-If you use an import statement in your AIDL, even from the same package, you
-need to add a path to `LOCAL_AIDL_INCLUDES`. This path should be relative to
-the root of the Android tree. For instance, a file IFoo.aidl defining
-com.example.IFoo might sit in a folder hierarchy
-something/something-else/com/example/IFoo.aidl. Then we would write:
-
-```
-LOCAL_AIDL_INCLUDES := something/something-else
-```
-
-Generated C++ ends up in nested namespaces corresponding to the interface’s
-package. The generated header also corresponds to the interface package. So
-com.example.IFoo becomes ::com::example::IFoo in header “com/example/IFoo.h”.
-
-Similar to how Java works, the suffix of the path to a .aidl file must match
-the package. So if IFoo.aidl declares itself to be in package com.example, the
-folder structure (as given to `LOCAL_SRC_FILES`) must look like:
-`some/prefix/com/example/IFoo.aidl`.
-
-To generate code from .aidl files from another build target (e.g. another
-binary or java), just add a relative path to the .aidl files to
-`LOCAL_SRC_FILES`. Remember that importing AIDL works the same, even for code
-in other directory hierarchies: add the include root path relative to the
-checkout root to `LOCAL_AIDL_INCLUDES`.
-
-### Type Mapping
-
-The following table summarizes the equivalent C++ types for common Java types
-and whether those types may be used as in/out/inout parameters in AIDL
-interfaces.
-
-| Java Type | C++ Type | inout | Notes |
-|-----------------------|---------------------|-------|-------------------------------------------------------|
-| boolean | bool | in | "These 8 types are all considered primitives. |
-| byte | int8\_t | in | |
-| char | char16\_t | in | |
-| int | int32\_t | in | |
-| long | int64\_t | in | |
-| float | float | in | |
-| double | double | in | |
-| String | String16 | in | Supports null references. |
-| @utf8InCpp String | std::string | in | @utf8InCpp causes UTF16 to UTF8 conversion in C++. |
-| android.os.Parcelable | android::Parcelable | inout | |
-| T extends IBinder | sp<T> | in | |
-| Arrays (T[]) | vector<T> | inout | May contain only primitives, Strings and parcelables. |
-| List<String> | vector<String16> | inout | |
-| PersistableBundle | PersistableBundle | inout | binder/PersistableBundle.h |
-| List<IBinder> | vector<sp<IBinder>> | inout | |
-| FileDescriptor | unique_fd | inout | android-base/unique_fd.h from libbase |
-
-Note that annotations may be placed at the interface level, as well as on a
-type by type basis. Interface level annotations will be applied
-opportunistically and be overridden by per type annotations. For instance, an
-interface marked @nullable will still not allow null int parameters.
-
-### Implementing a generated interface
-
-Given an interface declaration like:
-
-```
-package foo;
-
-import bar.IAnotherInterface;
-
-interface IFoo {
- IAnotherInterface DoSomething(int count, out List<String> output);
-}
-```
-
-`aidl-cpp` will generate a C++ interface:
-
-```
-namespace foo {
-
-// Some headers have been omitted for clarity.
-#include <android/String16.h>
-#include <cstdint>
-#include <vector>
-#include <bar/IAnotherInterface.h>
-
-// Some class members have been omitted for clarity.
-class IFoo : public android::IInterface {
- public:
- virtual android::binder::Status DoSomething(
- int32_t count,
- std::vector<android::String16>* output,
- android::sp<bar::IAnotherInterface>* returned_value) = 0;
-};
-```
-
-Note that `aidl-cpp` will import headers for types used in the interface. For
-imported types (e.g. parcelables and interfaces), it will import a header
-corresponding to the package/class name of the import. For instance,
-`import bar.IAnotherInterface` causes aidl-cpp to generate
-`#include <bar/IAnotherInterface.h>`.
-
-When writing a service that implements this interface, write:
-
-```
-#include "foo/BnFoo.h"
-
-namespace unrelated_namespace {
-
-class MyFoo : public foo::BnFoo {
- public:
- android::binder::Status DoSomething(
- int32_t count,
- std::vector<android::String16>* output,
- android::sp<bar::IAnotherInterface>* returned_value) override {
- for (int32_t i = 0; i < count; ++i) {
- output->push_back(String16("..."));
- }
- *returned_value = new InstanceOfAnotherInterface;
- return Status::ok();
- }
-}; // class MyFoo
-
-} // namespace unrelated_namespace
-```
-
-Note that the output values, `output` and `returned_value` are passed by
-pointer, and that this pointer is always valid.
-
-#### Dependencies
-
-The generated C++ code will use symbols from libbinder as well as libutils.
-AIDL files using the FileDescriptor type will also explicitly require
-libnativehelper, although this is likely a transitive dependency of the other
-two, and should be included automatically within the Android build tree
-regardless.
-
-### C++ Parcelables
-
-In Java, a parcelable should extend android.os.Parcelable and provide a static
-final CREATOR field that acts as a factory for new instances/arrays of
-instances of the parcelable. In addition, in order to be used as an out
-parameter, a parcelable class must define a readFromParcel method.
-
-In C++, parcelables must implement android::Parcelable from binder/Parcelable.h
-in libbinder. Parcelables must define a constructor that takes no arguments.
-In order to be used in arrays, a parcelable must implement a copy or move
-constructor (called implicitly in vector).
-
-The C++ generator needs to know what header defines the C++ parcelable. It
-learns this from the `cpp_header` directive shown below. The generator takes
-this string and uses it as the literal include statement in generated code.
-The idea here is that you generate your code once, link it into a library along
-with parcelable implementations, and export appropriate header paths. This
-header include must make sense in the context of the Android.mk that compiles
-this generated code.
-
-```
-// ExampleParcelable.aidl
-package com.example.android;
-
-// Native types must be aliased at their declaration in the appropriate .aidl
-// file. This allows multiple interfaces to use a parcelable and its C++
-// equivalent without duplicating the mapping between the C++ and Java types.
-// Generator will assume bar/foo.h declares class
-// com::example::android::ExampleParcelable
-parcelable ExampleParcelable cpp_header "bar/foo.h";
-```
-
-### Null Reference Handling
-
-The aidl generator for both C++ and Java languages has been expanded to
-understand nullable annotations.
-
-Given an interface definition like:
-
-```
-interface IExample {
- void ReadStrings(String neverNull, in @nullable String maybeNull);
-};
-```
-
-the generated C++ header code looks like:
-
-```
-class IExample {
- android::binder::Status ReadStrings(
- const android::String16& in_neverNull,
- const std::unique_ptr<android::String16>& in_maybeNull);
-};
-```
-
-Note that by default, the generated C++ passes a const reference to the value
-of a parameter and rejects null references with a NullPointerException sent
-back the caller. Parameters marked with @nullable are passed by pointer,
-allowing native services to explicitly control whether they allow method
-overloading via null parameters. Java stubs and proxies currently do nothing
-with the @nullable annotation.
-
-Consider an AIDL type `in @nullable List<String> bar`. This type
-indicates that the remote caller may pass in a list of strings, and that both
-the list and any string in the list may be null. This type will map to a C++
-type `unique_ptr<vector<unique_ptr<String16>>>* bar`. In this case:
-
- - `bar` is never null
- - `*bar` might be null
- - `(*bar)->empty()` could be true
- - `(**bar)[0]` could be null (and so on)
-
-### Exception Reporting
-
-C++ methods generated by the aidl generator return `android::binder::Status`
-objects, rather than `android::status_t`. This Status object allows generated
-C++ code to send and receive exceptions (an exception type and a String16 error
-message) since we do not use real exceptions in C++. More background on Status
-objects can be found here.
-
-For legacy support and migration ease, the Status object includes a mechanism
-to report a `android::status_t`. However, that return code is interpreted by a
-different code path and does not include a helpful String message.
-
-For situations where your native service needs to throw an error code specific
-to the service, use `Status::fromServiceSpecificError()`. This kind of
-exception comes with a helpful message and an integer error code. Make your
-error codes consistent across services by using interface constants (see
-below).
diff --git a/generate_cpp.cpp b/generate_cpp.cpp
index cc25657..da1e40e 100644
--- a/generate_cpp.cpp
+++ b/generate_cpp.cpp
@@ -271,9 +271,9 @@
b->AddLiteral(StringPrintf("%s %s", kBinderStatusLiteral, kStatusVarName));
if (options.GenTraces()) {
- b->AddLiteral(StringPrintf("::android::ScopedTrace %s(ATRACE_TAG_AIDL, \"%s::%s::cppClient\")",
- kTraceVarName, interface.GetName().c_str(),
- method.GetName().c_str()));
+ b->AddLiteral(
+ StringPrintf("::android::ScopedTrace %s(ATRACE_TAG_AIDL, \"AIDL::cpp::%s::%s::cppClient\")",
+ kTraceVarName, interface.GetName().c_str(), method.GetName().c_str()));
}
if (options.GenLog()) {
@@ -552,6 +552,12 @@
new Assignment(kAndroidStatusVarName, "::android::BAD_TYPE"));
interface_check->OnTrue()->AddLiteral("break");
+ if (options.GenTraces()) {
+ b->AddLiteral(
+ StringPrintf("::android::ScopedTrace %s(ATRACE_TAG_AIDL, \"AIDL::cpp::%s::%s::cppServer\")",
+ kTraceVarName, interface.GetName().c_str(), method.GetName().c_str()));
+ }
+
// Deserialize each "in" parameter to the transaction.
for (const auto& a: method.GetArguments()) {
// Deserialization looks roughly like:
@@ -576,13 +582,6 @@
}
}
- if (options.GenTraces()) {
- b->AddStatement(new Statement(new MethodCall("atrace_begin",
- ArgList{{"ATRACE_TAG_AIDL",
- StringPrintf("\"%s::%s::cppServer\"",
- interface.GetName().c_str(),
- method.GetName().c_str())}})));
- }
const string bn_name = ClassName(interface, ClassNames::SERVER);
if (options.GenLog()) {
b->AddLiteral(GenLogBeforeExecute(bn_name, method, true /* isServer */, false /* isNdk */),
@@ -596,11 +595,6 @@
StringPrintf("%s %s", kBinderStatusLiteral, kStatusVarName),
ArgList(std::move(status_args)))));
- if (options.GenTraces()) {
- b->AddStatement(new Statement(new MethodCall("atrace_end",
- "ATRACE_TAG_AIDL")));
- }
-
if (options.GenLog()) {
b->AddLiteral(GenLogAfterExecute(bn_name, interface, method, kStatusVarName, kReturnVarName,
true /* isServer */, false /* isNdk */),
@@ -1117,6 +1111,11 @@
parcel_class->AddPublic(std::unique_ptr<LiteralDecl>(new LiteralDecl(out.str())));
}
+ if (parcel.IsVintfStability()) {
+ parcel_class->AddPublic(std::unique_ptr<LiteralDecl>(
+ new LiteralDecl("bool isStable() const override { return true; }\n")));
+ }
+
unique_ptr<MethodDecl> read(new MethodDecl(kAndroidStatusLiteral, "readFromParcel",
ArgList("const ::android::Parcel* _aidl_parcel"),
MethodDecl::IS_OVERRIDE | MethodDecl::IS_FINAL));
diff --git a/generate_cpp_unittest.cpp b/generate_cpp_unittest.cpp
index f4f2650..b7df190 100644
--- a/generate_cpp_unittest.cpp
+++ b/generate_cpp_unittest.cpp
@@ -421,7 +421,7 @@
::android::Parcel _aidl_reply;
::android::status_t _aidl_ret_status = ::android::OK;
::android::binder::Status _aidl_status;
- ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "IComplexTypeInterface::Send::cppClient");
+ ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::IComplexTypeInterface::Send::cppClient");
_aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
@@ -474,7 +474,7 @@
::android::Parcel _aidl_reply;
::android::status_t _aidl_ret_status = ::android::OK;
::android::binder::Status _aidl_status;
- ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "IComplexTypeInterface::Piff::cppClient");
+ ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::IComplexTypeInterface::Piff::cppClient");
_aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
@@ -500,7 +500,7 @@
::android::Parcel _aidl_reply;
::android::status_t _aidl_ret_status = ::android::OK;
::android::binder::Status _aidl_status;
- ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "IComplexTypeInterface::TakesABinder::cppClient");
+ ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::IComplexTypeInterface::TakesABinder::cppClient");
_aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
@@ -537,7 +537,7 @@
::android::Parcel _aidl_reply;
::android::status_t _aidl_ret_status = ::android::OK;
::android::binder::Status _aidl_status;
- ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "IComplexTypeInterface::NullableBinder::cppClient");
+ ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::IComplexTypeInterface::NullableBinder::cppClient");
_aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
@@ -570,7 +570,7 @@
::android::Parcel _aidl_reply;
::android::status_t _aidl_ret_status = ::android::OK;
::android::binder::Status _aidl_status;
- ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "IComplexTypeInterface::StringListMethod::cppClient");
+ ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::IComplexTypeInterface::StringListMethod::cppClient");
_aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
@@ -611,7 +611,7 @@
::android::Parcel _aidl_reply;
::android::status_t _aidl_ret_status = ::android::OK;
::android::binder::Status _aidl_status;
- ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "IComplexTypeInterface::BinderListMethod::cppClient");
+ ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::IComplexTypeInterface::BinderListMethod::cppClient");
_aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
@@ -652,7 +652,7 @@
::android::Parcel _aidl_reply;
::android::status_t _aidl_ret_status = ::android::OK;
::android::binder::Status _aidl_status;
- ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "IComplexTypeInterface::TakesAFileDescriptor::cppClient");
+ ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::IComplexTypeInterface::TakesAFileDescriptor::cppClient");
_aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
@@ -689,7 +689,7 @@
::android::Parcel _aidl_reply;
::android::status_t _aidl_ret_status = ::android::OK;
::android::binder::Status _aidl_status;
- ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "IComplexTypeInterface::TakesAFileDescriptorArray::cppClient");
+ ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::IComplexTypeInterface::TakesAFileDescriptorArray::cppClient");
_aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
@@ -1030,6 +1030,7 @@
_aidl_ret_status = ::android::BAD_TYPE;
break;
}
+ ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::IComplexTypeInterface::Send::cppServer");
_aidl_ret_status = _aidl_data.readInt32Vector(&in_goes_in);
if (((_aidl_ret_status) != (::android::OK))) {
break;
@@ -1042,9 +1043,7 @@
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
- atrace_begin(ATRACE_TAG_AIDL, "IComplexTypeInterface::Send::cppServer");
::android::binder::Status _aidl_status(Send(in_goes_in, &in_goes_in_and_out, &out_goes_out, &_aidl_return));
- atrace_end(ATRACE_TAG_AIDL);
_aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
if (((_aidl_ret_status) != (::android::OK))) {
break;
@@ -1073,13 +1072,12 @@
_aidl_ret_status = ::android::BAD_TYPE;
break;
}
+ ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::IComplexTypeInterface::Piff::cppServer");
_aidl_ret_status = _aidl_data.readInt32(&in_times);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
- atrace_begin(ATRACE_TAG_AIDL, "IComplexTypeInterface::Piff::cppServer");
::android::binder::Status _aidl_status(Piff(in_times));
- atrace_end(ATRACE_TAG_AIDL);
}
break;
case ::android::IBinder::FIRST_CALL_TRANSACTION + 2 /* TakesABinder */:
@@ -1090,13 +1088,12 @@
_aidl_ret_status = ::android::BAD_TYPE;
break;
}
+ ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::IComplexTypeInterface::TakesABinder::cppServer");
_aidl_ret_status = _aidl_data.readStrongBinder(&in_f);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
- atrace_begin(ATRACE_TAG_AIDL, "IComplexTypeInterface::TakesABinder::cppServer");
::android::binder::Status _aidl_status(TakesABinder(in_f, &_aidl_return));
- atrace_end(ATRACE_TAG_AIDL);
_aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
if (((_aidl_ret_status) != (::android::OK))) {
break;
@@ -1117,9 +1114,8 @@
_aidl_ret_status = ::android::BAD_TYPE;
break;
}
- atrace_begin(ATRACE_TAG_AIDL, "IComplexTypeInterface::NullableBinder::cppServer");
+ ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::IComplexTypeInterface::NullableBinder::cppServer");
::android::binder::Status _aidl_status(NullableBinder(&_aidl_return));
- atrace_end(ATRACE_TAG_AIDL);
_aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
if (((_aidl_ret_status) != (::android::OK))) {
break;
@@ -1142,13 +1138,12 @@
_aidl_ret_status = ::android::BAD_TYPE;
break;
}
+ ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::IComplexTypeInterface::StringListMethod::cppServer");
_aidl_ret_status = _aidl_data.readString16Vector(&in_input);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
- atrace_begin(ATRACE_TAG_AIDL, "IComplexTypeInterface::StringListMethod::cppServer");
::android::binder::Status _aidl_status(StringListMethod(in_input, &out_output, &_aidl_return));
- atrace_end(ATRACE_TAG_AIDL);
_aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
if (((_aidl_ret_status) != (::android::OK))) {
break;
@@ -1175,13 +1170,12 @@
_aidl_ret_status = ::android::BAD_TYPE;
break;
}
+ ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::IComplexTypeInterface::BinderListMethod::cppServer");
_aidl_ret_status = _aidl_data.readStrongBinderVector(&in_input);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
- atrace_begin(ATRACE_TAG_AIDL, "IComplexTypeInterface::BinderListMethod::cppServer");
::android::binder::Status _aidl_status(BinderListMethod(in_input, &out_output, &_aidl_return));
- atrace_end(ATRACE_TAG_AIDL);
_aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
if (((_aidl_ret_status) != (::android::OK))) {
break;
@@ -1207,13 +1201,12 @@
_aidl_ret_status = ::android::BAD_TYPE;
break;
}
+ ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::IComplexTypeInterface::TakesAFileDescriptor::cppServer");
_aidl_ret_status = _aidl_data.readUniqueFileDescriptor(&in_f);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
- atrace_begin(ATRACE_TAG_AIDL, "IComplexTypeInterface::TakesAFileDescriptor::cppServer");
::android::binder::Status _aidl_status(TakesAFileDescriptor(std::move(in_f), &_aidl_return));
- atrace_end(ATRACE_TAG_AIDL);
_aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
if (((_aidl_ret_status) != (::android::OK))) {
break;
@@ -1235,13 +1228,12 @@
_aidl_ret_status = ::android::BAD_TYPE;
break;
}
+ ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::IComplexTypeInterface::TakesAFileDescriptorArray::cppServer");
_aidl_ret_status = _aidl_data.readUniqueFileDescriptorVector(&in_f);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
- atrace_begin(ATRACE_TAG_AIDL, "IComplexTypeInterface::TakesAFileDescriptorArray::cppServer");
::android::binder::Status _aidl_status(TakesAFileDescriptorArray(in_f, &_aidl_return));
- atrace_end(ATRACE_TAG_AIDL);
_aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
if (((_aidl_ret_status) != (::android::OK))) {
break;
diff --git a/generate_java.cpp b/generate_java.cpp
index 5d572a4..df98e26 100644
--- a/generate_java.cpp
+++ b/generate_java.cpp
@@ -119,6 +119,13 @@
}
std::ostringstream out;
+
+ if (parcel->IsVintfStability()) {
+ out << "public final boolean isStable() { return true; }\n";
+ parcel_class->elements.push_back(std::make_shared<LiteralClassElement>(out.str()));
+ }
+
+ out.str("");
out << "public static final android.os.Parcelable.Creator<" << parcel->GetName() << "> CREATOR = "
<< "new android.os.Parcelable.Creator<" << parcel->GetName() << ">() {\n";
out << " @Override\n";
diff --git a/generate_java_binder.cpp b/generate_java_binder.cpp
index aaa0471..dd629b2 100644
--- a/generate_java_binder.cpp
+++ b/generate_java_binder.cpp
@@ -419,10 +419,29 @@
std::shared_ptr<Variable> transact_data,
std::shared_ptr<Variable> transact_reply,
const AidlTypenames& typenames,
- std::shared_ptr<StatementBlock> statements,
+ std::shared_ptr<StatementBlock> statement_block,
std::shared_ptr<StubClass> stubClass, const Options& options) {
- std::shared_ptr<TryStatement> tryStatement;
- std::shared_ptr<FinallyStatement> finallyStatement;
+ // try and finally
+ auto tryStatement = std::make_shared<TryStatement>();
+ auto finallyStatement = std::make_shared<FinallyStatement>();
+ auto& statements = statement_block;
+
+ if (options.GenTraces()) {
+ statements->Add(tryStatement);
+ statements->Add(finallyStatement);
+ statements = tryStatement->statements;
+ tryStatement->statements->Add(std::make_shared<MethodCall>(
+ std::make_shared<LiteralExpression>("android.os.Trace"), "traceBegin",
+ std::vector<std::shared_ptr<Expression>>{
+ std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL"),
+ std::make_shared<StringLiteralExpression>("AIDL::java::" + iface.GetName() +
+ "::" + method.GetName() + "::server")}));
+ finallyStatement->statements->Add(std::make_shared<MethodCall>(
+ std::make_shared<LiteralExpression>("android.os.Trace"), "traceEnd",
+ std::vector<std::shared_ptr<Expression>>{
+ std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL")}));
+ }
+
auto realCall = std::make_shared<MethodCall>(THIS_VALUE, method.GetName());
// interface token validation is the very first thing we do
@@ -467,33 +486,9 @@
}
}
- if (options.GenTraces()) {
- // try and finally, but only when generating trace code
- tryStatement = std::make_shared<TryStatement>();
- finallyStatement = std::make_shared<FinallyStatement>();
-
- tryStatement->statements->Add(std::make_shared<MethodCall>(
- std::make_shared<LiteralExpression>("android.os.Trace"), "traceBegin",
- std::vector<std::shared_ptr<Expression>>{
- std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL"),
- std::make_shared<StringLiteralExpression>(iface.GetName() + "::" + method.GetName() +
- "::server")}));
-
- finallyStatement->statements->Add(std::make_shared<MethodCall>(
- std::make_shared<LiteralExpression>("android.os.Trace"), "traceEnd",
- std::vector<std::shared_ptr<Expression>>{
- std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL")}));
- }
-
// the real call
if (method.GetType().GetName() == "void") {
- if (options.GenTraces()) {
- statements->Add(tryStatement);
- tryStatement->statements->Add(realCall);
- statements->Add(finallyStatement);
- } else {
- statements->Add(realCall);
- }
+ statements->Add(realCall);
if (!oneway) {
// report that there were no exceptions
@@ -503,14 +498,7 @@
} else {
auto _result =
std::make_shared<Variable>(JavaSignatureOf(method.GetType(), typenames), "_result");
- if (options.GenTraces()) {
- statements->Add(std::make_shared<VariableDeclaration>(_result));
- statements->Add(tryStatement);
- tryStatement->statements->Add(std::make_shared<Assignment>(_result, realCall));
- statements->Add(finallyStatement);
- } else {
statements->Add(std::make_shared<VariableDeclaration>(_result, realCall));
- }
if (!oneway) {
// report that there were no exceptions
@@ -631,8 +619,8 @@
std::make_shared<LiteralExpression>("android.os.Trace"), "traceBegin",
std::vector<std::shared_ptr<Expression>>{
std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL"),
- std::make_shared<StringLiteralExpression>(iface.GetName() + "::" + method.GetName() +
- "::client")}));
+ std::make_shared<StringLiteralExpression>("AIDL::java::" + iface.GetName() +
+ "::" + method.GetName() + "::client")}));
}
// the interface identifier token: the DESCRIPTOR constant, marshalled as a
@@ -868,7 +856,7 @@
<< "public synchronized String " << kGetInterfaceHash << "()"
<< " throws "
<< "android.os.RemoteException {\n"
- << " if (mCachedHash == \"-1\") {\n"
+ << " if (\"-1\".equals(mCachedHash)) {\n"
<< " android.os.Parcel data = android.os.Parcel.obtain();\n"
<< " android.os.Parcel reply = android.os.Parcel.obtain();\n"
<< " try {\n"
@@ -1141,7 +1129,13 @@
const string i_name = iface->GetCanonicalName();
stub->elements.emplace_back(std::make_shared<LiteralClassElement>(
StringPrintf("public static boolean setDefaultImpl(%s impl) {\n"
- " if (Stub.Proxy.sDefaultImpl == null && impl != null) {\n"
+ " // Only one user of this interface can use this function\n"
+ " // at a time. This is a heuristic to detect if two different\n"
+ " // users in the same process use this function.\n"
+ " if (Stub.Proxy.sDefaultImpl != null) {\n"
+ " throw new IllegalStateException(\"setDefaultImpl() called twice\");\n"
+ " }\n"
+ " if (impl != null) {\n"
" Stub.Proxy.sDefaultImpl = impl;\n"
" return true;\n"
" }\n"
diff --git a/generate_ndk.cpp b/generate_ndk.cpp
index d08ac1b..0037b8a 100644
--- a/generate_ndk.cpp
+++ b/generate_ndk.cpp
@@ -182,25 +182,59 @@
out << "#include <android/binder_stability.h>\n";
out << "#endif // BINDER_STABILITY_SUPPORT\n";
- types.IterateTypes([&](const AidlDefinedType& other_defined_type) {
- if (&other_defined_type == &defined_type) return;
-
- if (other_defined_type.AsInterface() != nullptr) {
- out << "#include <"
- << NdkHeaderFile(other_defined_type, ClassNames::RAW, false /*use_os_sep*/) << ">\n";
- } else if (other_defined_type.AsStructuredParcelable() != nullptr) {
- out << "#include <"
- << NdkHeaderFile(other_defined_type, ClassNames::RAW, false /*use_os_sep*/) << ">\n";
- } else if (other_defined_type.AsParcelable() != nullptr) {
- out << "#include \"" << other_defined_type.AsParcelable()->GetCppHeader() << "\"\n";
- } else if (other_defined_type.AsEnumDeclaration() != nullptr) {
- out << "#include <"
- << NdkHeaderFile(other_defined_type, ClassNames::RAW, false /*use_os_sep*/) << ">\n";
- } else {
- AIDL_FATAL(defined_type) << "Unrecognized type.";
+ auto headerFilePath = [&types](const AidlTypeSpecifier& typespec) -> std::string {
+ const AidlDefinedType* type = types.TryGetDefinedType(typespec.GetName());
+ if (type == nullptr) {
+ // could be a primitive type.
+ return "";
}
- });
+
+ if (type->AsInterface() != nullptr) {
+ return NdkHeaderFile(*type, ClassNames::RAW, false /*use_os_sep*/);
+ } else if (type->AsStructuredParcelable() != nullptr) {
+ return NdkHeaderFile(*type, ClassNames::RAW, false /*use_os_sep*/);
+ } else if (type->AsParcelable() != nullptr) {
+ return type->AsParcelable()->GetCppHeader();
+ } else if (type->AsEnumDeclaration() != nullptr) {
+ return NdkHeaderFile(*type, ClassNames::RAW, false /*use_os_sep*/);
+ } else {
+ AIDL_FATAL(*type) << "Unrecognized type.";
+ return "";
+ }
+ };
+
+ std::set<std::string> includes;
+
+ const AidlInterface* interface = defined_type.AsInterface();
+ if (interface != nullptr) {
+ for (const auto& method : interface->GetMethods()) {
+ includes.insert(headerFilePath(method->GetType()));
+ for (const auto& argument : method->GetArguments()) {
+ includes.insert(headerFilePath(argument->GetType()));
+ }
+ }
+ }
+
+ const AidlStructuredParcelable* parcelable = defined_type.AsStructuredParcelable();
+ if (parcelable != nullptr) {
+ for (const auto& field : parcelable->GetFields()) {
+ includes.insert(headerFilePath(field->GetType()));
+ }
+ }
+
+ const AidlEnumDeclaration* enum_decl = defined_type.AsEnumDeclaration();
+ if (enum_decl != nullptr) {
+ includes.insert(headerFilePath(enum_decl->GetBackingType()));
+ }
+
+ for (const auto& path : includes) {
+ if (path == "") {
+ continue;
+ }
+ out << "#include <" << path << ">\n";
+ }
}
+
static void GenerateSourceIncludes(CodeWriter& out, const AidlTypenames& types,
const AidlDefinedType& /*defined_type*/) {
out << "#include <android/binder_parcel_utils.h>\n";
@@ -325,6 +359,11 @@
out << cpp::GenLogBeforeExecute(ClassName(defined_type, ClassNames::CLIENT), method,
false /* isServer */, true /* isNdk */);
}
+ if (options.GenTraces()) {
+ out << "ScopedTrace _aidl_trace(\"AIDL::" << Options::LanguageToString(options.TargetLanguage())
+ << "::" << ClassName(defined_type, ClassNames::INTERFACE) << "::" << method.GetName()
+ << "::client\");\n";
+ }
out << "_aidl_ret_status = AIBinder_prepareTransaction(asBinder().get(), _aidl_in.getR());\n";
StatusCheckGoto(out);
@@ -362,8 +401,9 @@
out << "if (_aidl_ret_status == STATUS_UNKNOWN_TRANSACTION && ";
out << iface << "::getDefaultImpl()) {\n";
out.Indent();
- out << "return " << iface << "::getDefaultImpl()->" << method.GetName() << "(";
+ out << "_aidl_status = " << iface << "::getDefaultImpl()->" << method.GetName() << "(";
out << NdkArgList(types, method, FormatArgNameOnly) << ");\n";
+ out << "goto _aidl_status_return;\n";
out.Dedent();
out << "}\n";
@@ -373,7 +413,7 @@
out << "_aidl_ret_status = AParcel_readStatusHeader(_aidl_out.get(), _aidl_status.getR());\n";
StatusCheckGoto(out);
- out << "if (!AStatus_isOk(_aidl_status.get())) return _aidl_status;\n\n";
+ out << "if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;\n";
}
if (method.GetType().GetName() != "void") {
@@ -396,11 +436,13 @@
out << "_aidl_error:\n";
out << "_aidl_status.set(AStatus_fromStatus(_aidl_ret_status));\n";
+ out << "_aidl_status_return:\n";
if (options.GenLog()) {
out << cpp::GenLogAfterExecute(ClassName(defined_type, ClassNames::CLIENT), defined_type,
method, "_aidl_status", "_aidl_return", false /* isServer */,
true /* isNdk */);
}
+
out << "return _aidl_status;\n";
out.Dedent();
out << "}\n";
@@ -419,6 +461,11 @@
out << NdkNameOf(types, method.GetType(), StorageMode::STACK) << " _aidl_return;\n";
}
out << "\n";
+ if (options.GenTraces()) {
+ out << "ScopedTrace _aidl_trace(\"AIDL::" << Options::LanguageToString(options.TargetLanguage())
+ << "::" << ClassName(defined_type, ClassNames::INTERFACE) << "::" << method.GetName()
+ << "::server\");\n";
+ }
for (const auto& arg : method.GetArguments()) {
const std::string var_name = cpp::BuildVarName(*arg);
@@ -476,7 +523,19 @@
const AidlInterface& defined_type, const Options& options) {
const std::string clazz = ClassName(defined_type, ClassNames::INTERFACE);
const std::string bn_clazz = ClassName(defined_type, ClassNames::SERVER);
-
+ if (options.GenTraces()) {
+ out << "class ScopedTrace {\n";
+ out.Indent();
+ out << "public:\n"
+ << "inline ScopedTrace(const char* name) {\n"
+ << "ATrace_beginSection(name);\n"
+ << "}\n"
+ << "inline ~ScopedTrace() {\n"
+ << "ATrace_endSection();\n"
+ << "}\n";
+ out.Dedent();
+ out << "};\n";
+ }
out << "static binder_status_t "
<< "_aidl_onTransact"
<< "(AIBinder* _aidl_binder, transaction_code_t _aidl_code, const AParcel* _aidl_in, "
@@ -623,7 +682,11 @@
// defintion for static member setDefaultImpl
out << "bool " << clazz << "::setDefaultImpl(std::shared_ptr<" << clazz << "> impl) {\n";
out.Indent();
- out << "if (!" << clazz << "::default_impl && impl) {\n";
+ out << "// Only one user of this interface can use this function\n";
+ out << "// at a time. This is a heuristic to detect if two different\n";
+ out << "// users in the same process use this function.\n";
+ out << "assert(!" << clazz << "::default_impl);\n";
+ out << "if (impl) {\n";
out.Indent();
out << clazz << "::default_impl = impl;\n";
out << "return true;\n";
@@ -705,6 +768,9 @@
out << "#include <chrono>\n";
out << "#include <sstream>\n";
}
+ if (options.GenTraces()) {
+ out << "#include <android/trace.h>\n";
+ }
out << "\n";
EnterNdkNamespace(out, defined_type);
out << "class " << clazz << " : public ::ndk::BpCInterface<"
@@ -881,6 +947,9 @@
out << "\n";
out << "binder_status_t readFromParcel(const AParcel* parcel);\n";
out << "binder_status_t writeToParcel(AParcel* parcel) const;\n";
+
+ out << "static const bool _aidl_is_stable = "
+ << (defined_type.IsVintfStability() ? "true" : "false") << ";\n";
out.Dedent();
out << "};\n";
LeaveNdkNamespace(out, defined_type);
diff --git a/run_integration_tests.sh b/run_integration_tests.sh
new file mode 100755
index 0000000..066faad
--- /dev/null
+++ b/run_integration_tests.sh
@@ -0,0 +1,32 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 2020 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.
+
+set -ex
+
+# TODO(b/156942077): when this test was converted to atest, we lost the ability
+# to see test results on stdout, and we can't print out the gtest results on
+# stderr because it breaks python test parsing. So, this file is added to help
+# run integration tests.
+
+$ANDROID_BUILD_TOP/build/soong/soong_ui.bash --make-mode \
+ MODULES-IN-system-tools-aidl
+
+adb root
+adb sync data
+adb install -r \
+ ${ANDROID_PRODUCT_OUT}/testcases/aidl_test_services/x86/aidl_test_services.apk
+
+${ANDROID_BUILD_TOP}/system/tools/aidl/tests/aidl_integration_test.py
diff --git a/tests/aidl_integration_test.py b/tests/aidl_integration_test.py
index ffd26a5..fe67ae4 100755
--- a/tests/aidl_integration_test.py
+++ b/tests/aidl_integration_test.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
import pipes
import subprocess
@@ -114,8 +114,8 @@
self.host.run('killall %s' % self.binary, ignore_status=True)
def run(self):
result = self.host.run(self.binary, ignore_status=True)
+ print(result.printable_string())
if result.exit_status:
- print(result.printable_string())
raise TestFail('%s returned status code %d' %
(self.binary, result.exit_status))
@@ -141,16 +141,16 @@
JAVA_LOG_FILE, JAVA_SUCCESS_SENTINEL,
JAVA_FAILURE_SENTINEL),
ignore_status=True)
+ print(result.printable_string())
if result.exit_status:
- print(result.printable_string())
raise TestFail('Java client did not complete successfully.')
def supported_bitnesses(host):
bitnesses = []
- if host.run('ls /data/nativetest/', ignore_status=True).exit_status == 0:
- bitnesses = [BITNESS_32]
- if host.run('ls /data/nativetest64/', ignore_status=True).exit_status == 0:
- bitnesses += [BITNESS_64]
+ for bitness in [BITNESS_32, BITNESS_64]:
+ native_client = NATIVE_TEST_CLIENT_FOR_BITNESS % bitness
+ if host.run('ls %s' % native_client, ignore_status=True).exit_status == 0:
+ bitnesses += [bitness]
return bitnesses
# tests added dynamically below
diff --git a/tests/aidl_test_client.cpp b/tests/aidl_test_client.cpp
index 678edc5..c95bc90 100644
--- a/tests/aidl_test_client.cpp
+++ b/tests/aidl_test_client.cpp
@@ -14,107 +14,42 @@
* limitations under the License.
*/
-#include <iostream>
-
-#include <android-base/logging.h>
-#include <binder/IServiceManager.h>
-#include <utils/String16.h>
-#include <utils/StrongPointer.h>
-
-#include "android/aidl/tests/ITestService.h"
+#include "aidl_test_client.h"
#include "aidl_test_client_defaultimpl.h"
#include "aidl_test_client_file_descriptors.h"
#include "aidl_test_client_nullables.h"
-#include "aidl_test_client_parcelables.h"
#include "aidl_test_client_primitives.h"
#include "aidl_test_client_service_exceptions.h"
#include "aidl_test_client_utf8_strings.h"
-// libutils:
-using android::OK;
-using android::sp;
-using android::status_t;
-using android::String16;
+#include <android-base/logging.h>
-// libbinder:
-using android::getService;
-
-// generated
-using android::aidl::tests::ITestService;
-
-using std::cerr;
-using std::cout;
-using std::endl;
-
-namespace android {
-namespace aidl {
-namespace tests {
-namespace client {
-
-const char kServiceName[] = "android.aidl.tests.ITestService";
-
-bool GetService(sp<ITestService>* service) {
- cout << "Retrieving test service binder" << endl;
- status_t status = getService(String16(kServiceName), service);
- if (status != OK) {
- cerr << "Failed to get service binder: '" << kServiceName
- << "' status=" << status << endl;
- return false;
- }
- return true;
-}
-
-} // namespace client
-} // namespace tests
-} // namespace aidl
-} // namespace android
-
-/* Runs all the test cases in aidl_test_client_*.cpp files. */
-int main(int /* argc */, char * argv []) {
- android::base::InitLogging(argv, android::base::StderrLogger);
- sp<ITestService> service;
+// These tests were written without gtest, and not all have been converted to
+// gtest. Places which haven't been converted are still included as part of this
+// test here.
+TEST_F(AidlTest, UnconvertedTests) {
namespace client_tests = android::aidl::tests::client;
- if (!client_tests::GetService(&service)) return 1;
+ EXPECT_TRUE(client_tests::ConfirmPrimitiveRepeat(service));
+ EXPECT_TRUE(client_tests::ConfirmReverseArrays(service));
+ EXPECT_TRUE(client_tests::ConfirmReverseLists(service));
+ EXPECT_TRUE(client_tests::ConfirmReverseBinderLists(service));
+ EXPECT_TRUE(client_tests::ConfirmIntfConstantExpressions(service));
+ EXPECT_TRUE(client_tests::ConfirmFileDescriptors(service));
+ EXPECT_TRUE(client_tests::ConfirmFileDescriptorArrays(service));
+ EXPECT_TRUE(client_tests::ConfirmParcelFileDescriptors(service));
+ EXPECT_TRUE(client_tests::ConfirmParcelFileDescriptorArrays(service));
+ EXPECT_TRUE(client_tests::ConfirmServiceSpecificExceptions(service));
+ EXPECT_TRUE(client_tests::ConfirmNullables(service));
+ EXPECT_TRUE(client_tests::ConfirmUtf8InCppStringRepeat(service));
+ EXPECT_TRUE(client_tests::ConfirmUtf8InCppStringArrayReverse(service));
+ EXPECT_TRUE(client_tests::ConfirmUtf8InCppStringListReverse(service));
+ EXPECT_TRUE(client_tests::ConfirmDefaultImpl(service));
+}
- if (!client_tests::ConfirmPrimitiveRepeat(service)) return 1;
-
- if (!client_tests::ConfirmReverseArrays(service)) return 1;
-
- if (!client_tests::ConfirmReverseLists(service)) return 1;
-
- if (!client_tests::ConfirmReverseBinderLists(service)) return 1;
-
- if (!client_tests::ConfirmSimpleParcelables(service)) return 1;
-
- if (!client_tests::ConfirmPersistableBundles(service)) return 1;
-
- if (!client_tests::ConfirmIntfConstantExpressions(service)) return 1;
-
- if (!client_tests::ConfirmStructuredParcelables(service)) return 1;
-
- if (!client_tests::ConfirmStructuredParcelablesEquality(service)) return 1;
-
- if (!client_tests::ConfirmFileDescriptors(service)) return 1;
-
- if (!client_tests::ConfirmFileDescriptorArrays(service)) return 1;
-
- if (!client_tests::ConfirmParcelFileDescriptors(service)) return 1;
-
- if (!client_tests::ConfirmParcelFileDescriptorArrays(service)) return 1;
-
- if (!client_tests::ConfirmServiceSpecificExceptions(service)) return 1;
-
- if (!client_tests::ConfirmNullables(service)) return 1;
-
- if (!client_tests::ConfirmUtf8InCppStringRepeat(service)) return 1;
-
- if (!client_tests::ConfirmUtf8InCppStringArrayReverse(service)) return 1;
-
- if (!client_tests::ConfirmUtf8InCppStringListReverse(service)) return 1;
-
- if (!client_tests::ConfirmDefaultImpl(service)) return 1;
-
- return 0;
+int main(int argc, char* argv[]) {
+ android::base::InitLogging(argv, android::base::StderrLogger);
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
}
diff --git a/tests/aidl_test_client.h b/tests/aidl_test_client.h
new file mode 100644
index 0000000..bdd0b7c
--- /dev/null
+++ b/tests/aidl_test_client.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#pragma once
+
+#include <android/aidl/tests/ITestService.h>
+#include <binder/IServiceManager.h>
+#include <gtest/gtest.h>
+#include <utils/String16.h>
+
+using android::sp;
+using android::aidl::tests::ITestService;
+
+class AidlTest : public testing::Test {
+ public:
+ void SetUp() override {
+ using android::getService;
+ using android::OK;
+ using android::String16;
+
+ static const char kServiceName[] = "android.aidl.tests.ITestService";
+ ASSERT_EQ(OK, getService(String16(kServiceName), &service));
+ ASSERT_NE(nullptr, service);
+ }
+
+ sp<ITestService> service;
+};
diff --git a/tests/aidl_test_client_parcelables.cpp b/tests/aidl_test_client_parcelables.cpp
index cc89270..7152acc 100644
--- a/tests/aidl_test_client_parcelables.cpp
+++ b/tests/aidl_test_client_parcelables.cpp
@@ -14,84 +14,55 @@
* limitations under the License.
*/
-#include "aidl_test_client_parcelables.h"
+#include "aidl_test_client.h"
-#include <iostream>
#include <vector>
-// libutils:
+using android::IInterface;
using android::sp;
-
-// libbinder:
-using android::binder::Status;
-
-// generated
+using android::String16;
using android::aidl::tests::ConstantExpressionEnum;
+using android::aidl::tests::INamedCallback;
+using android::aidl::tests::IntEnum;
using android::aidl::tests::ITestService;
using android::aidl::tests::SimpleParcelable;
+using android::aidl::tests::StructuredParcelable;
+using android::binder::Status;
using android::os::PersistableBundle;
-
-using std::cout;
-using std::endl;
using std::vector;
-namespace android {
-namespace aidl {
-namespace tests {
-namespace client {
-
-bool ConfirmSimpleParcelables(const sp<ITestService>& s) {
- cout << "Confirming passing and returning SimpleParcelable objects works."
- << endl;
-
+TEST_F(AidlTest, RepeatSimpleParcelable) {
SimpleParcelable input("Booya", 42);
SimpleParcelable out_param, returned;
- Status status = s->RepeatSimpleParcelable(input, &out_param, &returned);
- if (!status.isOk()) {
- cout << "Binder call failed." << endl;
- return false;
- }
- if (input != out_param || input != returned) {
- cout << "Failed to repeat SimpleParcelable objects." << endl;
- return false;
- }
+ Status status = service->RepeatSimpleParcelable(input, &out_param, &returned);
+ ASSERT_TRUE(status.isOk()) << status.toString8();
+ EXPECT_EQ(input, out_param);
+ EXPECT_EQ(input, returned);
+}
- cout << "Attempting to reverse an array of SimpleParcelable objects." << endl;
+TEST_F(AidlTest, ReverseSimpleParcelable) {
const vector<SimpleParcelable> original{SimpleParcelable("first", 0),
SimpleParcelable("second", 1),
SimpleParcelable("third", 2)};
vector<SimpleParcelable> repeated;
vector<SimpleParcelable> reversed;
- status = s->ReverseSimpleParcelables(original, &repeated, &reversed);
- if (!status.isOk()) {
- cout << "Binder call failed." << endl;
- return false;
- }
- std::reverse(reversed.begin(), reversed.end());
- if (repeated != original || reversed != original) {
- cout << "Failed to reverse an array of SimpleParcelable objects." << endl;
- return false;
- }
+ Status status = service->ReverseSimpleParcelables(original, &repeated, &reversed);
+ ASSERT_TRUE(status.isOk()) << status.toString8();
- return true;
+ EXPECT_EQ(repeated, original);
+
+ std::reverse(reversed.begin(), reversed.end());
}
-bool ConfirmPersistableBundles(const sp<ITestService>& s) {
- cout << "Confirming passing and returning PersistableBundle objects works."
- << endl;
-
+TEST_F(AidlTest, ConfirmPersistableBundles) {
PersistableBundle empty_bundle, returned;
- Status status = s->RepeatPersistableBundle(empty_bundle, &returned);
- if (!status.isOk()) {
- cout << "Binder call failed for empty PersistableBundle." << endl;
- return false;
- }
- if (empty_bundle != returned) {
- cout << "Failed to repeat empty PersistableBundle." << endl;
- return false;
- }
+ Status status = service->RepeatPersistableBundle(empty_bundle, &returned);
+ ASSERT_TRUE(status.isOk()) << status.toString8();
+ EXPECT_EQ(empty_bundle, returned);
+}
- PersistableBundle non_empty_bundle;
+TEST_F(AidlTest, ConfirmPersistableBundlesNonEmpty) {
+ PersistableBundle non_empty_bundle, returned;
non_empty_bundle.putBoolean(String16("test_bool"), false);
non_empty_bundle.putInt(String16("test_int"), 33);
non_empty_bundle.putLong(String16("test_long"), 34359738368L);
@@ -110,18 +81,12 @@
non_empty_bundle.putPersistableBundle(String16("test_persistable_bundle"),
nested_bundle);
- status = s->RepeatPersistableBundle(non_empty_bundle, &returned);
- if (!status.isOk()) {
- cout << "Binder call failed. " << endl;
- return false;
- }
- if (non_empty_bundle != returned) {
- cout << "Failed to repeat PersistableBundle object." << endl;
- return false;
- }
+ Status status = service->RepeatPersistableBundle(non_empty_bundle, &returned);
+ ASSERT_TRUE(status.isOk()) << status.toString8();
+ EXPECT_EQ(non_empty_bundle, returned);
+}
- cout << "Attempting to reverse an array of PersistableBundle objects."
- << endl;
+TEST_F(AidlTest, ReversePersistableBundles) {
PersistableBundle first;
PersistableBundle second;
PersistableBundle third;
@@ -132,275 +97,113 @@
vector<PersistableBundle> repeated;
vector<PersistableBundle> reversed;
- status = s->ReversePersistableBundles(original, &repeated, &reversed);
- if (!status.isOk()) {
- cout << "Binder call failed." << endl;
- return false;
- }
- std::reverse(reversed.begin(), reversed.end());
- if (repeated != original || reversed != original) {
- cout << "Failed to reverse an array of PersistableBundle objects." << endl;
- return false;
- }
+ Status status = service->ReversePersistableBundles(original, &repeated, &reversed);
+ ASSERT_TRUE(status.isOk()) << status.toString8();
- return true;
+ EXPECT_EQ(repeated, original);
+
+ std::reverse(reversed.begin(), reversed.end());
+ EXPECT_EQ(reversed, original);
}
-bool ConfirmStructuredParcelablesEquality(const sp<ITestService>& s) {
+TEST_F(AidlTest, StructuredParcelableEquality) {
+ // TODO: break up equality tests, these are hard to read, because you need to
+ // keep the state of the parcelables in mind
StructuredParcelable parcelable1;
StructuredParcelable parcelable2;
parcelable1.f = 11;
parcelable2.f = 11;
- s->FillOutStructuredParcelable(&parcelable1);
- s->FillOutStructuredParcelable(&parcelable2);
+ service->FillOutStructuredParcelable(&parcelable1);
+ service->FillOutStructuredParcelable(&parcelable2);
sp<INamedCallback> callback1;
sp<INamedCallback> callback2;
- s->GetOtherTestService(String16("callback1"), &callback1);
- s->GetOtherTestService(String16("callback2"), &callback2);
+ service->GetOtherTestService(String16("callback1"), &callback1);
+ service->GetOtherTestService(String16("callback2"), &callback2);
parcelable1.ibinder = IInterface::asBinder(callback1);
parcelable2.ibinder = IInterface::asBinder(callback1);
- if (parcelable1 != parcelable2) {
- cout << "parcelable1 and parcelable2 should be same." << endl;
- return false;
- }
+ EXPECT_EQ(parcelable1, parcelable2);
+
parcelable1.f = 0;
- if (parcelable1 >= parcelable2) {
- cout << "parcelable1 and parcelable2 should be different because of shouldContainThreeFs"
- << endl;
- return false;
- }
+ EXPECT_LT(parcelable1, parcelable2);
parcelable1.f = 11;
parcelable1.shouldBeJerry = "Jarry";
- if (!(parcelable1 < parcelable2)) {
- cout << "parcelable1 and parcelable2 should be different because of shouldContainThreeFs"
- << endl;
- return false;
- }
+ EXPECT_LT(parcelable1, parcelable2);
parcelable1.shouldBeJerry = "Jerry";
parcelable2.shouldContainThreeFs = {};
- if (parcelable1 <= parcelable2) {
- cout << "parcelable1 and parcelable2 should be different because of shouldContainThreeFs"
- << endl;
- return false;
- }
+ EXPECT_GT(parcelable1, parcelable2);
parcelable2.shouldContainThreeFs = {parcelable2.f, parcelable2.f, parcelable2.f};
parcelable2.shouldBeIntBar = IntEnum::FOO;
- if (!(parcelable1 > parcelable2)) {
- cout << "parcelable1 and parcelable2 should be different because of shouldBeIntBar" << endl;
- return false;
- }
+ EXPECT_GT(parcelable1, parcelable2);
parcelable2.shouldBeIntBar = IntEnum::BAR;
parcelable2.ibinder = IInterface::asBinder(callback2);
- if (parcelable1 == parcelable2) {
- cout << "parcelable1 and parcelable2 should be different because of ibinder" << endl;
- return false;
- }
- return true;
+ EXPECT_NE(parcelable1, parcelable2);
}
-bool ConfirmStructuredParcelables(const sp<ITestService>& s) {
- bool success = true;
+TEST_F(AidlTest, ConfirmStructuredParcelables) {
constexpr int kDesiredValue = 23;
StructuredParcelable parcelable;
parcelable.f = kDesiredValue;
- if (parcelable.stringDefaultsToFoo != String16("foo")) {
- cout << "stringDefaultsToFoo should be 'foo' but is " << parcelable.stringDefaultsToFoo << endl;
- return false;
- }
- if (parcelable.byteDefaultsToFour != 4) {
- cout << "byteDefaultsToFour should be 4 but is " << parcelable.byteDefaultsToFour << endl;
- return false;
- }
- if (parcelable.intDefaultsToFive != 5) {
- cout << "intDefaultsToFive should be 5 but is " << parcelable.intDefaultsToFive << endl;
- return false;
- }
- if (parcelable.longDefaultsToNegativeSeven != -7) {
- cout << "longDefaultsToNegativeSeven should be -7 but is "
- << parcelable.longDefaultsToNegativeSeven << endl;
- return false;
- }
- if (!parcelable.booleanDefaultsToTrue) {
- cout << "booleanDefaultsToTrue isn't true" << endl;
- return false;
- }
- if (parcelable.charDefaultsToC != 'C') {
- cout << "charDefaultsToC is " << parcelable.charDefaultsToC << endl;
- return false;
- }
- if (parcelable.floatDefaultsToPi != 3.14f) {
- cout << "floatDefaultsToPi is " << parcelable.floatDefaultsToPi << endl;
- return false;
- }
- if (parcelable.doubleWithDefault != -3.14e17) {
- cout << "doubleWithDefault is " << parcelable.doubleWithDefault << " but should be -3.14e17"
- << endl;
- return false;
- }
- if (parcelable.arrayDefaultsTo123.size() != 3) {
- cout << "arrayDefaultsTo123 is of length " << parcelable.arrayDefaultsTo123.size() << endl;
- return false;
- }
- for (int i = 0; i < 3; i++) {
- if (parcelable.arrayDefaultsTo123[i] != i + 1) {
- cout << "arrayDefaultsTo123[" << i << "] is " << parcelable.arrayDefaultsTo123[i]
- << " but should be " << i + 1 << endl;
- return false;
- }
- }
- if (!parcelable.arrayDefaultsToEmpty.empty()) {
- cout << "arrayDefaultsToEmpty is not empty " << parcelable.arrayDefaultsToEmpty.size() << endl;
- return false;
- }
+ EXPECT_EQ(parcelable.stringDefaultsToFoo, String16("foo"));
+ EXPECT_EQ(parcelable.byteDefaultsToFour, 4);
+ EXPECT_EQ(parcelable.intDefaultsToFive, 5);
+ EXPECT_EQ(parcelable.longDefaultsToNegativeSeven, -7);
+ EXPECT_EQ(parcelable.booleanDefaultsToTrue, true);
+ EXPECT_EQ(parcelable.charDefaultsToC, 'C');
+ EXPECT_TRUE(parcelable.floatDefaultsToPi == 3.14f) << parcelable.floatDefaultsToPi;
+ EXPECT_TRUE(parcelable.doubleWithDefault == -3.14e17) << parcelable.doubleWithDefault;
- s->FillOutStructuredParcelable(&parcelable);
+ ASSERT_EQ(parcelable.arrayDefaultsTo123.size(), 3u);
+ EXPECT_EQ(parcelable.arrayDefaultsTo123[0], 1);
+ EXPECT_EQ(parcelable.arrayDefaultsTo123[1], 2);
+ EXPECT_EQ(parcelable.arrayDefaultsTo123[2], 3);
+ EXPECT_TRUE(parcelable.arrayDefaultsToEmpty.empty());
- if (parcelable.shouldContainThreeFs.size() != 3) {
- cout << "shouldContainThreeFs is of length " << parcelable.shouldContainThreeFs.size() << endl;
- return false;
- }
+ service->FillOutStructuredParcelable(&parcelable);
- for (int i = 0; i < 3; i++) {
- if (parcelable.shouldContainThreeFs[i] != kDesiredValue) {
- cout << "shouldContainThreeFs[" << i << "] is " << parcelable.shouldContainThreeFs[i]
- << " but should be " << kDesiredValue << endl;
- return false;
- }
- }
+ ASSERT_EQ(parcelable.shouldContainThreeFs.size(), 3u);
+ EXPECT_EQ(parcelable.shouldContainThreeFs[0], kDesiredValue);
+ EXPECT_EQ(parcelable.shouldContainThreeFs[1], kDesiredValue);
+ EXPECT_EQ(parcelable.shouldContainThreeFs[2], kDesiredValue);
- if (parcelable.shouldBeJerry != "Jerry") {
- cout << "shouldBeJerry should be 'Jerry' but is " << parcelable.shouldBeJerry << endl;
- return false;
- }
-
- if (parcelable.int32_min != INT32_MIN) {
- cout << "int32_min should be " << INT32_MIN << "but is " << parcelable.int32_min << endl;
- return false;
- }
-
- if (parcelable.int32_max != INT32_MAX) {
- cout << "int32_max should be " << INT32_MAX << "but is " << parcelable.int32_max << endl;
- return false;
- }
-
- if (parcelable.int64_max != INT64_MAX) {
- cout << "int64_max should be " << INT64_MAX << "but is " << parcelable.int64_max << endl;
- return false;
- }
-
- if (parcelable.hexInt32_neg_1 != -1) {
- cout << "hexInt32_neg_1 should be -1 but is " << parcelable.hexInt32_neg_1 << endl;
- return false;
- }
+ EXPECT_EQ(parcelable.shouldBeJerry, "Jerry");
+ EXPECT_EQ(parcelable.int32_min, INT32_MIN);
+ EXPECT_EQ(parcelable.int32_max, INT32_MAX);
+ EXPECT_EQ(parcelable.int64_max, INT64_MAX);
+ EXPECT_EQ(parcelable.hexInt32_neg_1, -1);
for (size_t ndx = 0; ndx < parcelable.int32_1.size(); ndx++) {
- if (parcelable.int32_1[ndx] != 1) {
- cout << "int32_1[" << ndx << "] should be 1 but is " << parcelable.int32_1[ndx] << endl;
- success = false;
- }
- }
- if (!success) {
- return false;
+ EXPECT_EQ(parcelable.int32_1[ndx], 1) << ndx;
}
for (size_t ndx = 0; ndx < parcelable.int64_1.size(); ndx++) {
- if (parcelable.int64_1[ndx] != 1) {
- cout << "int64_1[" << ndx << "] should be 1 but is " << parcelable.int64_1[ndx] << endl;
- success = false;
- }
- }
- if (!success) {
- return false;
+ EXPECT_EQ(parcelable.int64_1[ndx], 1) << ndx;
}
- if (static_cast<int>(parcelable.hexInt32_pos_1) != 1) {
- cout << "hexInt32_pos_1 should be 1 but is " << parcelable.hexInt32_pos_1 << endl;
- return false;
- }
+ EXPECT_EQ(parcelable.hexInt32_pos_1, 1);
+ EXPECT_EQ(parcelable.hexInt64_pos_1, 1);
- if (parcelable.hexInt64_pos_1 != 1) {
- cout << "hexInt64_pos_1 should be 1 but is " << parcelable.hexInt64_pos_1 << endl;
- return false;
- }
+ EXPECT_EQ(static_cast<int>(parcelable.const_exprs_1), 1);
+ EXPECT_EQ(static_cast<int>(parcelable.const_exprs_2), 1);
+ EXPECT_EQ(static_cast<int>(parcelable.const_exprs_3), 1);
+ EXPECT_EQ(static_cast<int>(parcelable.const_exprs_4), 1);
+ EXPECT_EQ(static_cast<int>(parcelable.const_exprs_5), 1);
+ EXPECT_EQ(static_cast<int>(parcelable.const_exprs_6), 1);
+ EXPECT_EQ(static_cast<int>(parcelable.const_exprs_7), 1);
+ EXPECT_EQ(static_cast<int>(parcelable.const_exprs_8), 1);
+ EXPECT_EQ(static_cast<int>(parcelable.const_exprs_9), 1);
+ EXPECT_EQ(static_cast<int>(parcelable.const_exprs_10), 1);
- if (static_cast<int>(parcelable.const_exprs_1) != 1) {
- cout << "parcelable.const_exprs_1 should be 1 but is "
- << static_cast<int>(parcelable.const_exprs_1) << endl;
- return false;
- }
- if (static_cast<int>(parcelable.const_exprs_2) != 1) {
- cout << "parcelable.const_exprs_2 should be 1 but is "
- << static_cast<int>(parcelable.const_exprs_2) << endl;
- return false;
- }
- if (static_cast<int>(parcelable.const_exprs_3) != 1) {
- cout << "parcelable.const_exprs_3 should be 1 but is "
- << static_cast<int>(parcelable.const_exprs_3) << endl;
- return false;
- }
- if (static_cast<int>(parcelable.const_exprs_4) != 1) {
- cout << "parcelable.const_exprs_4 should be 1 but is "
- << static_cast<int>(parcelable.const_exprs_4) << endl;
- return false;
- }
- if (static_cast<int>(parcelable.const_exprs_5) != 1) {
- cout << "parcelable.const_exprs_5 should be 1 but is "
- << static_cast<int>(parcelable.const_exprs_5) << endl;
- return false;
- }
- if (static_cast<int>(parcelable.const_exprs_6) != 1) {
- cout << "parcelable.const_exprs_6 should be 1 but is "
- << static_cast<int>(parcelable.const_exprs_6) << endl;
- return false;
- }
- if (static_cast<int>(parcelable.const_exprs_7) != 1) {
- cout << "parcelable.const_exprs_7 should be 1 but is "
- << static_cast<int>(parcelable.const_exprs_7) << endl;
- return false;
- }
- if (static_cast<int>(parcelable.const_exprs_8) != 1) {
- cout << "parcelable.const_exprs_8 should be 1 but is "
- << static_cast<int>(parcelable.const_exprs_8) << endl;
- return false;
- }
- if (static_cast<int>(parcelable.const_exprs_9) != 1) {
- cout << "parcelable.const_exprs_9 should be 1 but is "
- << static_cast<int>(parcelable.const_exprs_9) << endl;
- return false;
- }
- if (static_cast<int>(parcelable.const_exprs_10) != 1) {
- cout << "parcelable.const_exprs_10 should be 1 but is "
- << static_cast<int>(parcelable.const_exprs_10) << endl;
- return false;
- }
-
- if (parcelable.addString1 != "hello world!") {
- cout << "parcelable.addString1 should be \"hello world!\" but is \"" << parcelable.addString1
- << "\"" << endl;
- return false;
- }
- if (parcelable.addString2 != "The quick brown fox jumps over the lazy dog.") {
- cout << "parcelable.addString2 should be \"The quick brown fox jumps over the lazy dog.\""
- " but is \""
- << parcelable.addString2 << "\"" << endl;
- return false;
- }
-
- return true;
+ EXPECT_EQ(parcelable.addString1, "hello world!");
+ EXPECT_EQ(parcelable.addString2, "The quick brown fox jumps over the lazy dog.");
}
-
-} // namespace client
-} // namespace tests
-} // namespace aidl
-} // namespace android
diff --git a/tests/aidl_test_client_parcelables.h b/tests/aidl_test_client_parcelables.h
deleted file mode 100644
index 3031ad4..0000000
--- a/tests/aidl_test_client_parcelables.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#ifndef ANDROID_AIDL_TESTS_CLIENT_PARCELABLES_H
-#define ANDROID_AIDL_TESTS_CLIENT_PARCELABLES_H
-
-#include <utils/StrongPointer.h>
-
-#include "android/aidl/tests/ITestService.h"
-
-// Tests for passing and returning parcelable types.
-namespace android {
-namespace aidl {
-namespace tests {
-namespace client {
-
-bool ConfirmSimpleParcelables(const sp<ITestService>& s);
-bool ConfirmPersistableBundles(const sp<ITestService>& s);
-bool ConfirmStructuredParcelables(const sp<ITestService>& s);
-bool ConfirmStructuredParcelablesEquality(const sp<ITestService>& s);
-
-} // namespace client
-} // namespace tests
-} // namespace aidl
-} // namespace android
-
-#endif // ANDROID_AIDL_TESTS_CLIENT_PARCELABLES_H
diff --git a/tests/corpus/enum_named_byte b/tests/corpus/enum_named_byte
new file mode 100644
index 0000000..3cf3ad6
--- /dev/null
+++ b/tests/corpus/enum_named_byte
@@ -0,0 +1 @@
+= import s;enum byte{p}enum s{p} enum oz{p2}parcelable e{e oy;oz y;}
\ No newline at end of file
diff --git a/tests/corpus/ibinder_array b/tests/corpus/ibinder_array
new file mode 100644
index 0000000..853e41a
--- /dev/null
+++ b/tests/corpus/ibinder_array
@@ -0,0 +1 @@
+ enum F{p}parcelable e{IBinder[]y;}
diff --git a/tests/corpus/nullable_parcelable_array b/tests/corpus/nullable_parcelable_array
new file mode 100644
index 0000000..65cb0af
--- /dev/null
+++ b/tests/corpus/nullable_parcelable_array
@@ -0,0 +1 @@
+)enum r{r}parcelable e{@nullable e[]e;}
\ No newline at end of file
diff --git a/tests/corpus/nullable_pfd_array b/tests/corpus/nullable_pfd_array
new file mode 100644
index 0000000..a18ddd1
--- /dev/null
+++ b/tests/corpus/nullable_pfd_array
@@ -0,0 +1 @@
+ enum F{p}parcelable e{@nullable ParcelFileDescriptor[]y;}
\ No newline at end of file
diff --git a/tests/test_data_example_interface.cpp b/tests/test_data_example_interface.cpp
index c6e0f73..7e23120 100644
--- a/tests/test_data_example_interface.cpp
+++ b/tests/test_data_example_interface.cpp
@@ -548,7 +548,13 @@
static final int TRANSACTION_takesAnInterface = (android.os.IBinder.FIRST_CALL_TRANSACTION + 7);
static final int TRANSACTION_takesAParcelable = (android.os.IBinder.FIRST_CALL_TRANSACTION + 8);
public static boolean setDefaultImpl(android.test.IExampleInterface impl) {
- if (Stub.Proxy.sDefaultImpl == null && impl != null) {
+ // Only one user of this interface can use this function
+ // at a time. This is a heuristic to detect if two different
+ // users in the same process use this function.
+ if (Stub.Proxy.sDefaultImpl != null) {
+ throw new IllegalStateException("setDefaultImpl() called twice");
+ }
+ if (impl != null) {
Stub.Proxy.sDefaultImpl = impl;
return true;
}
@@ -1062,7 +1068,13 @@
static final int TRANSACTION_takesAnInterface = (android.os.IBinder.FIRST_CALL_TRANSACTION + 7);
static final int TRANSACTION_takesAParcelable = (android.os.IBinder.FIRST_CALL_TRANSACTION + 8);
public static boolean setDefaultImpl(android.test.IExampleInterface impl) {
- if (Stub.Proxy.sDefaultImpl == null && impl != null) {
+ // Only one user of this interface can use this function
+ // at a time. This is a heuristic to detect if two different
+ // users in the same process use this function.
+ if (Stub.Proxy.sDefaultImpl != null) {
+ throw new IllegalStateException("setDefaultImpl() called twice");
+ }
+ if (impl != null) {
Stub.Proxy.sDefaultImpl = impl;
return true;
}
@@ -1189,165 +1201,157 @@
}
case TRANSACTION_isEnabled:
{
- data.enforceInterface(descriptor);
- boolean _result;
try {
- android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::isEnabled::server");
- _result = this.isEnabled();
+ android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::isEnabled::server");
+ data.enforceInterface(descriptor);
+ boolean _result = this.isEnabled();
+ reply.writeNoException();
+ reply.writeInt(((_result)?(1):(0)));
+ return true;
}
finally {
android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
}
- reply.writeNoException();
- reply.writeInt(((_result)?(1):(0)));
- return true;
}
case TRANSACTION_getState:
{
- data.enforceInterface(descriptor);
- int _result;
try {
- android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::getState::server");
- _result = this.getState();
+ android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::getState::server");
+ data.enforceInterface(descriptor);
+ int _result = this.getState();
+ reply.writeNoException();
+ reply.writeInt(_result);
+ return true;
}
finally {
android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
}
- reply.writeNoException();
- reply.writeInt(_result);
- return true;
}
case TRANSACTION_getAddress:
{
- data.enforceInterface(descriptor);
- java.lang.String _result;
try {
- android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::getAddress::server");
- _result = this.getAddress();
+ android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::getAddress::server");
+ data.enforceInterface(descriptor);
+ java.lang.String _result = this.getAddress();
+ reply.writeNoException();
+ reply.writeString(_result);
+ return true;
}
finally {
android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
}
- reply.writeNoException();
- reply.writeString(_result);
- return true;
}
case TRANSACTION_getParcelables:
{
- data.enforceInterface(descriptor);
- android.foo.ExampleParcelable[] _result;
try {
- android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::getParcelables::server");
- _result = this.getParcelables();
+ android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::getParcelables::server");
+ data.enforceInterface(descriptor);
+ android.foo.ExampleParcelable[] _result = this.getParcelables();
+ reply.writeNoException();
+ reply.writeTypedArray(_result, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+ return true;
}
finally {
android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
}
- reply.writeNoException();
- reply.writeTypedArray(_result, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
- return true;
}
case TRANSACTION_setScanMode:
{
- data.enforceInterface(descriptor);
- int _arg0;
- _arg0 = data.readInt();
- int _arg1;
- _arg1 = data.readInt();
- boolean _result;
try {
- android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::setScanMode::server");
- _result = this.setScanMode(_arg0, _arg1);
+ android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::setScanMode::server");
+ data.enforceInterface(descriptor);
+ int _arg0;
+ _arg0 = data.readInt();
+ int _arg1;
+ _arg1 = data.readInt();
+ boolean _result = this.setScanMode(_arg0, _arg1);
+ reply.writeNoException();
+ reply.writeInt(((_result)?(1):(0)));
+ return true;
}
finally {
android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
}
- reply.writeNoException();
- reply.writeInt(((_result)?(1):(0)));
- return true;
}
case TRANSACTION_registerBinder:
{
- data.enforceInterface(descriptor);
- android.bar.IAuxInterface _arg0;
- _arg0 = android.bar.IAuxInterface.Stub.asInterface(data.readStrongBinder());
try {
- android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::registerBinder::server");
+ android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::registerBinder::server");
+ data.enforceInterface(descriptor);
+ android.bar.IAuxInterface _arg0;
+ _arg0 = android.bar.IAuxInterface.Stub.asInterface(data.readStrongBinder());
this.registerBinder(_arg0);
+ reply.writeNoException();
+ return true;
}
finally {
android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
}
- reply.writeNoException();
- return true;
}
case TRANSACTION_getRecursiveBinder:
{
- data.enforceInterface(descriptor);
- android.test.IExampleInterface _result;
try {
- android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::getRecursiveBinder::server");
- _result = this.getRecursiveBinder();
+ android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::getRecursiveBinder::server");
+ data.enforceInterface(descriptor);
+ android.test.IExampleInterface _result = this.getRecursiveBinder();
+ reply.writeNoException();
+ reply.writeStrongBinder((((_result!=null))?(_result.asBinder()):(null)));
+ return true;
}
finally {
android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
}
- reply.writeNoException();
- reply.writeStrongBinder((((_result!=null))?(_result.asBinder()):(null)));
- return true;
}
case TRANSACTION_takesAnInterface:
{
- data.enforceInterface(descriptor);
- android.test.IAuxInterface2 _arg0;
- _arg0 = android.test.IAuxInterface2.Stub.asInterface(data.readStrongBinder());
- int _result;
try {
- android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::takesAnInterface::server");
- _result = this.takesAnInterface(_arg0);
+ android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::takesAnInterface::server");
+ data.enforceInterface(descriptor);
+ android.test.IAuxInterface2 _arg0;
+ _arg0 = android.test.IAuxInterface2.Stub.asInterface(data.readStrongBinder());
+ int _result = this.takesAnInterface(_arg0);
+ reply.writeNoException();
+ reply.writeInt(_result);
+ return true;
}
finally {
android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
}
- reply.writeNoException();
- reply.writeInt(_result);
- return true;
}
case TRANSACTION_takesAParcelable:
{
- data.enforceInterface(descriptor);
- android.test.CompoundParcelable.Subclass1 _arg0;
- if ((0!=data.readInt())) {
- _arg0 = android.test.CompoundParcelable.Subclass1.CREATOR.createFromParcel(data);
- }
- else {
- _arg0 = null;
- }
- android.test.CompoundParcelable.Subclass2 _arg1;
- if ((0!=data.readInt())) {
- _arg1 = android.test.CompoundParcelable.Subclass2.CREATOR.createFromParcel(data);
- }
- else {
- _arg1 = null;
- }
- int _result;
try {
- android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::takesAParcelable::server");
- _result = this.takesAParcelable(_arg0, _arg1);
+ android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::takesAParcelable::server");
+ data.enforceInterface(descriptor);
+ android.test.CompoundParcelable.Subclass1 _arg0;
+ if ((0!=data.readInt())) {
+ _arg0 = android.test.CompoundParcelable.Subclass1.CREATOR.createFromParcel(data);
+ }
+ else {
+ _arg0 = null;
+ }
+ android.test.CompoundParcelable.Subclass2 _arg1;
+ if ((0!=data.readInt())) {
+ _arg1 = android.test.CompoundParcelable.Subclass2.CREATOR.createFromParcel(data);
+ }
+ else {
+ _arg1 = null;
+ }
+ int _result = this.takesAParcelable(_arg0, _arg1);
+ reply.writeNoException();
+ reply.writeInt(_result);
+ if ((_arg1!=null)) {
+ reply.writeInt(1);
+ _arg1.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+ }
+ else {
+ reply.writeInt(0);
+ }
+ return true;
}
finally {
android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
}
- reply.writeNoException();
- reply.writeInt(_result);
- if ((_arg1!=null)) {
- reply.writeInt(1);
- _arg1.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
- }
- else {
- reply.writeInt(0);
- }
- return true;
}
default:
{
@@ -1376,7 +1380,7 @@
android.os.Parcel _reply = android.os.Parcel.obtain();
boolean _result;
try {
- android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::isEnabled::client");
+ android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::isEnabled::client");
_data.writeInterfaceToken(DESCRIPTOR);
boolean _status = mRemote.transact(Stub.TRANSACTION_isEnabled, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
@@ -1398,7 +1402,7 @@
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
- android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::getState::client");
+ android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::getState::client");
_data.writeInterfaceToken(DESCRIPTOR);
boolean _status = mRemote.transact(Stub.TRANSACTION_getState, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
@@ -1420,7 +1424,7 @@
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.String _result;
try {
- android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::getAddress::client");
+ android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::getAddress::client");
_data.writeInterfaceToken(DESCRIPTOR);
boolean _status = mRemote.transact(Stub.TRANSACTION_getAddress, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
@@ -1443,7 +1447,7 @@
android.os.Parcel _reply = android.os.Parcel.obtain();
android.foo.ExampleParcelable[] _result;
try {
- android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::getParcelables::client");
+ android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::getParcelables::client");
_data.writeInterfaceToken(DESCRIPTOR);
boolean _status = mRemote.transact(Stub.TRANSACTION_getParcelables, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
@@ -1467,7 +1471,7 @@
android.os.Parcel _reply = android.os.Parcel.obtain();
boolean _result;
try {
- android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::setScanMode::client");
+ android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::setScanMode::client");
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(mode);
_data.writeInt(duration);
@@ -1492,7 +1496,7 @@
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
- android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::registerBinder::client");
+ android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::registerBinder::client");
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeStrongBinder((((foo!=null))?(foo.asBinder()):(null)));
boolean _status = mRemote.transact(Stub.TRANSACTION_registerBinder, _data, _reply, 0);
@@ -1514,7 +1518,7 @@
android.os.Parcel _reply = android.os.Parcel.obtain();
android.test.IExampleInterface _result;
try {
- android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::getRecursiveBinder::client");
+ android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::getRecursiveBinder::client");
_data.writeInterfaceToken(DESCRIPTOR);
boolean _status = mRemote.transact(Stub.TRANSACTION_getRecursiveBinder, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
@@ -1536,7 +1540,7 @@
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
- android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::takesAnInterface::client");
+ android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::takesAnInterface::client");
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeStrongBinder((((arg!=null))?(arg.asBinder()):(null)));
boolean _status = mRemote.transact(Stub.TRANSACTION_takesAnInterface, _data, _reply, 0);
@@ -1559,7 +1563,7 @@
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
- android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "IExampleInterface::takesAParcelable::client");
+ android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::IExampleInterface::takesAParcelable::client");
_data.writeInterfaceToken(DESCRIPTOR);
if ((arg!=null)) {
_data.writeInt(1);
@@ -1604,7 +1608,13 @@
static final int TRANSACTION_takesAnInterface = (android.os.IBinder.FIRST_CALL_TRANSACTION + 7);
static final int TRANSACTION_takesAParcelable = (android.os.IBinder.FIRST_CALL_TRANSACTION + 8);
public static boolean setDefaultImpl(android.test.IExampleInterface impl) {
- if (Stub.Proxy.sDefaultImpl == null && impl != null) {
+ // Only one user of this interface can use this function
+ // at a time. This is a heuristic to detect if two different
+ // users in the same process use this function.
+ if (Stub.Proxy.sDefaultImpl != null) {
+ throw new IllegalStateException("setDefaultImpl() called twice");
+ }
+ if (impl != null) {
Stub.Proxy.sDefaultImpl = impl;
return true;
}
@@ -2094,7 +2104,13 @@
return true;
}
public static boolean setDefaultImpl(android.test.IExampleInterface impl) {
- if (Stub.Proxy.sDefaultImpl == null && impl != null) {
+ // Only one user of this interface can use this function
+ // at a time. This is a heuristic to detect if two different
+ // users in the same process use this function.
+ if (Stub.Proxy.sDefaultImpl != null) {
+ throw new IllegalStateException("setDefaultImpl() called twice");
+ }
+ if (impl != null) {
Stub.Proxy.sDefaultImpl = impl;
return true;
}
@@ -2546,7 +2562,7 @@
}
@Override
public synchronized String getInterfaceHash() throws android.os.RemoteException {
- if (mCachedHash == "-1") {
+ if ("-1".equals(mCachedHash)) {
android.os.Parcel data = android.os.Parcel.obtain();
android.os.Parcel reply = android.os.Parcel.obtain();
try {
@@ -2660,7 +2676,13 @@
static final int TRANSACTION_getInterfaceVersion = (android.os.IBinder.FIRST_CALL_TRANSACTION + 16777214);
static final int TRANSACTION_getInterfaceHash = (android.os.IBinder.FIRST_CALL_TRANSACTION + 16777213);
public static boolean setDefaultImpl(android.test.IExampleInterface impl) {
- if (Stub.Proxy.sDefaultImpl == null && impl != null) {
+ // Only one user of this interface can use this function
+ // at a time. This is a heuristic to detect if two different
+ // users in the same process use this function.
+ if (Stub.Proxy.sDefaultImpl != null) {
+ throw new IllegalStateException("setDefaultImpl() called twice");
+ }
+ if (impl != null) {
Stub.Proxy.sDefaultImpl = impl;
return true;
}
diff --git a/tests/test_data_string_constants.cpp b/tests/test_data_string_constants.cpp
index 8b1b479..2bbd8fd 100644
--- a/tests/test_data_string_constants.cpp
+++ b/tests/test_data_string_constants.cpp
@@ -107,7 +107,13 @@
public static android.os.IStringConstants sDefaultImpl;
}
public static boolean setDefaultImpl(android.os.IStringConstants impl) {
- if (Stub.Proxy.sDefaultImpl == null && impl != null) {
+ // Only one user of this interface can use this function
+ // at a time. This is a heuristic to detect if two different
+ // users in the same process use this function.
+ if (Stub.Proxy.sDefaultImpl != null) {
+ throw new IllegalStateException("setDefaultImpl() called twice");
+ }
+ if (impl != null) {
Stub.Proxy.sDefaultImpl = impl;
return true;
}
@@ -354,7 +360,7 @@
}
@Override
public synchronized String getInterfaceHash() throws android.os.RemoteException {
- if (mCachedHash == "-1") {
+ if ("-1".equals(mCachedHash)) {
android.os.Parcel data = android.os.Parcel.obtain();
android.os.Parcel reply = android.os.Parcel.obtain();
try {
@@ -379,7 +385,13 @@
static final int TRANSACTION_getInterfaceVersion = (android.os.IBinder.FIRST_CALL_TRANSACTION + 16777214);
static final int TRANSACTION_getInterfaceHash = (android.os.IBinder.FIRST_CALL_TRANSACTION + 16777213);
public static boolean setDefaultImpl(android.os.IStringConstants impl) {
- if (Stub.Proxy.sDefaultImpl == null && impl != null) {
+ // Only one user of this interface can use this function
+ // at a time. This is a heuristic to detect if two different
+ // users in the same process use this function.
+ if (Stub.Proxy.sDefaultImpl != null) {
+ throw new IllegalStateException("setDefaultImpl() called twice");
+ }
+ if (impl != null) {
Stub.Proxy.sDefaultImpl = impl;
return true;
}
diff --git a/trace/android/trace.h b/trace/android/trace.h
new file mode 100644
index 0000000..cd6294c
--- /dev/null
+++ b/trace/android/trace.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+#pragma once
+
+#include <cutils/trace.h>
+
+inline void ATrace_beginSection(const char* sectionName) {
+ atrace_begin(ATRACE_TAG_AIDL, sectionName);
+}
+
+inline void ATrace_endSection() {
+ atrace_end(ATRACE_TAG_AIDL);
+}