summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristopher Wiley <wiley@google.com>2016-08-19 11:06:32 -0700
committerChristopher Wiley <wiley@google.com>2016-08-19 11:21:22 -0700
commit74b7bf1043d1905e6f999f7c47920319029453c0 (patch)
treefab6cde4ce761084b1bc39cf46e7c29b0cb39138
parent041c8d7ad2f9660a44e6ebc4f173b125b35f63f0 (diff)
downloadandroid_system_tools_aidl-74b7bf1043d1905e6f999f7c47920319029453c0.tar.gz
android_system_tools_aidl-74b7bf1043d1905e6f999f7c47920319029453c0.tar.bz2
android_system_tools_aidl-74b7bf1043d1905e6f999f7c47920319029453c0.zip
Write expected length of out arrays to parcel
This makes generated C++ consistent with the Java. Unfortunately, C++ server authors still need to understand that if they resize inout/out arrays, this will cause runtime exceptions for Java clients, which cannot resize their array types. Addressing this is a much more invasive patch. Bug: 30836680 Change-Id: I996bfea8383d6207377e7bc545d3d39c21bbe033 Test: integration and unit tests continue to pass
-rw-r--r--generate_cpp.cpp56
-rw-r--r--generate_cpp_unittest.cpp8
2 files changed, 47 insertions, 17 deletions
diff --git a/generate_cpp.cpp b/generate_cpp.cpp
index a8b2157..41e9fb4 100644
--- a/generate_cpp.cpp
+++ b/generate_cpp.cpp
@@ -279,20 +279,31 @@ unique_ptr<Declaration> DefineClientTransaction(const TypeNamespace& types,
"getInterfaceDescriptor()")));
b->AddStatement(GotoErrorOnBadStatus());
- // Serialization looks roughly like:
- // _aidl_ret_status = _aidl_data.WriteInt32(in_param_name);
- // if (_aidl_ret_status != ::android::OK) { goto error; }
- for (const AidlArgument* a : method.GetInArguments()) {
+ for (const auto& a: method.GetArguments()) {
const Type* type = a->GetType().GetLanguageType<Type>();
- const string& method = type->WriteToParcelMethod();
-
string var_name = ((a->IsOut()) ? "*" : "") + a->GetName();
var_name = type->WriteCast(var_name);
- b->AddStatement(new Assignment(
- kAndroidStatusVarName,
- new MethodCall(StringPrintf("%s.%s", kDataVarName, method.c_str()),
- ArgList(var_name))));
- b->AddStatement(GotoErrorOnBadStatus());
+
+ if (a->IsIn()) {
+ // Serialization looks roughly like:
+ // _aidl_ret_status = _aidl_data.WriteInt32(in_param_name);
+ // if (_aidl_ret_status != ::android::OK) { goto error; }
+ const string& method = type->WriteToParcelMethod();
+ b->AddStatement(new Assignment(
+ kAndroidStatusVarName,
+ new MethodCall(StringPrintf("%s.%s", kDataVarName, method.c_str()),
+ ArgList(var_name))));
+ b->AddStatement(GotoErrorOnBadStatus());
+ } else if (a->IsOut() && a->GetType().IsArray()) {
+ // Special case, the length of the out array is written into the parcel.
+ // _aidl_ret_status = _aidl_data.writeVectorSize(&out_param_name);
+ // if (_aidl_ret_status != ::android::OK) { goto error; }
+ b->AddStatement(new Assignment(
+ kAndroidStatusVarName,
+ new MethodCall(StringPrintf("%s.writeVectorSize", kDataVarName),
+ ArgList(var_name))));
+ b->AddStatement(GotoErrorOnBadStatus());
+ }
}
// Invoke the transaction on the remote binder and confirm status.
@@ -433,18 +444,29 @@ bool HandleServerTransaction(const TypeNamespace& types,
interface_check->OnTrue()->AddLiteral("break");
// Deserialize each "in" parameter to the transaction.
- for (const AidlArgument* a : method.GetInArguments()) {
+ for (const auto& a: method.GetArguments()) {
// Deserialization looks roughly like:
// _aidl_ret_status = _aidl_data.ReadInt32(&in_param_name);
// if (_aidl_ret_status != ::android::OK) { break; }
const Type* type = a->GetType().GetLanguageType<Type>();
const string& readMethod = type->ReadFromParcelMethod();
- b->AddStatement(new Assignment{
- kAndroidStatusVarName,
- new MethodCall{string(kDataVarName) + "." + readMethod,
- "&" + BuildVarName(*a)}});
- b->AddStatement(BreakOnStatusNotOk());
+ if (a->IsIn()) {
+ b->AddStatement(new Assignment{
+ kAndroidStatusVarName,
+ new MethodCall{string(kDataVarName) + "." + readMethod,
+ "&" + BuildVarName(*a)}});
+ b->AddStatement(BreakOnStatusNotOk());
+ } else if (a->IsOut() && a->GetType().IsArray()) {
+ // Special case, the length of the out array is written into the parcel.
+ // _aidl_ret_status = _aidl_data.resizeOutVector(&out_param_name);
+ // if (_aidl_ret_status != ::android::OK) { break; }
+ b->AddStatement(new Assignment{
+ kAndroidStatusVarName,
+ new MethodCall{string(kDataVarName) + ".resizeOutVector",
+ "&" + BuildVarName(*a)}});
+ b->AddStatement(BreakOnStatusNotOk());
+ }
}
// Call the actual method. This is implemented by the subclass.
diff --git a/generate_cpp_unittest.cpp b/generate_cpp_unittest.cpp
index 6cdf835..50bfd9c 100644
--- a/generate_cpp_unittest.cpp
+++ b/generate_cpp_unittest.cpp
@@ -117,6 +117,10 @@ _aidl_ret_status = _aidl_data.writeDoubleVector(*goes_in_and_out);
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
+_aidl_ret_status = _aidl_data.writeVectorSize(*goes_out);
+if (((_aidl_ret_status) != (::android::OK))) {
+goto _aidl_error;
+}
_aidl_ret_status = remote()->transact(IComplexTypeInterface::SEND, _aidl_data, &_aidl_reply);
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
@@ -426,6 +430,10 @@ _aidl_ret_status = _aidl_data.readDoubleVector(&in_goes_in_and_out);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
+_aidl_ret_status = _aidl_data.resizeOutVector(&out_goes_out);
+if (((_aidl_ret_status) != (::android::OK))) {
+break;
+}
::android::binder::Status _aidl_status(Send(in_goes_in, &in_goes_in_and_out, &out_goes_out, &_aidl_return));
_aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
if (((_aidl_ret_status) != (::android::OK))) {