1 /*
2 * Copyright (C) 2022, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "generate_cpp_analyzer.h"
18
19 #include <string>
20 #include "aidl.h"
21 #include "aidl_language.h"
22 #include "aidl_to_common.h"
23 #include "aidl_to_cpp.h"
24 #include "code_writer.h"
25 #include "logging.h"
26
27 using std::string;
28 using std::unique_ptr;
29
30 namespace android {
31 namespace aidl {
32 namespace cpp {
33 namespace {
34
35 const char kAndroidStatusVarName[] = "_aidl_ret_status";
36 const char kReturnVarName[] = "_aidl_return";
37 const char kDataVarName[] = "_aidl_data";
38 const char kReplyVarName[] = "_aidl_reply";
39
GenerateAnalyzerTransaction(CodeWriter & out,const AidlInterface & interface,const AidlMethod & method,const AidlTypenames & typenames,const Options & options)40 void GenerateAnalyzerTransaction(CodeWriter& out, const AidlInterface& interface,
41 const AidlMethod& method, const AidlTypenames& typenames,
42 const Options& options) {
43 // Reading past the interface descriptor and reply binder status
44 out << "_aidl_ret_status = ::android::OK;\n";
45 out.Write("if (!(%s.enforceInterface(android::String16(\"%s\")))) {\n", kDataVarName,
46 interface.GetDescriptor().c_str());
47 out.Write(" %s = ::android::BAD_TYPE;\n", kAndroidStatusVarName);
48 out << " std::cout << \" Failure: Parcel interface does not match.\" << std::endl;\n"
49 << " break;\n"
50 << "}\n";
51
52 // Declare parameters
53 for (const unique_ptr<AidlArgument>& a : method.GetArguments()) {
54 out.Write("%s %s;\n", CppNameOf(a->GetType(), typenames).c_str(), BuildVarName(*a).c_str());
55 }
56 out << "::android::binder::Status binderStatus;\n";
57 // Declare and read the return value.
58 // Read past the binder status.
59 out.Write("binderStatus.readFromParcel(%s);\n", kReplyVarName);
60 if (method.GetType().GetName() != "void") {
61 out.Write("%s %s;\n", CppNameOf(method.GetType(), typenames).c_str(), kReturnVarName);
62 out.Write("bool returnError = false;\n");
63 }
64
65 // Read Reply
66 if (method.GetType().GetName() != "void") {
67 out.Write("%s = %s.%s(%s);\n", kAndroidStatusVarName, kReplyVarName,
68 ParcelReadMethodOf(method.GetType(), typenames).c_str(),
69 ParcelReadCastOf(method.GetType(), typenames, string("&") + kReturnVarName).c_str());
70 out.Write("if (((%s) != (android::NO_ERROR))) {\n", kAndroidStatusVarName);
71 out.Indent();
72 out.Write(
73 "std::cerr << \"Failure: error in reading return value from Parcel.\" << std::endl;\n");
74 out.Write("returnError = true;\n");
75 out.Dedent();
76 out.Write("}\n");
77 }
78
79 // Reading arguments
80 out << "do { // Single-pass loop to break if argument reading fails\n";
81 out.Indent();
82 for (const auto& a : method.GetArguments()) {
83 out.Write("%s = %s.%s(%s);\n", kAndroidStatusVarName, kDataVarName,
84 ParcelReadMethodOf(a->GetType(), typenames).c_str(),
85 ParcelReadCastOf(a->GetType(), typenames, "&" + BuildVarName(*a)).c_str());
86 out.Write("if (((%s) != (android::NO_ERROR))) {\n", kAndroidStatusVarName);
87 out.Indent();
88 out.Write("std::cerr << \"Failure: error in reading argument %s from Parcel.\" << std::endl;\n",
89 a->GetName().c_str());
90 out.Dedent();
91 out.Write(" break;\n}\n");
92 }
93 out.Dedent();
94 out << "} while(false);\n";
95
96 if (!method.GetArguments().empty() && options.GetMinSdkVersion() >= SDK_VERSION_Tiramisu) {
97 out.Write(
98 "if (!%s.enforceNoDataAvail().isOk()) {\n %s = android::BAD_VALUE;\n std::cout << \" "
99 "Failure: Parcel has too much data.\" << std::endl;\n break;\n}\n",
100 kDataVarName, kAndroidStatusVarName);
101 }
102
103 // Arguments
104 out.Write("std::cout << \" arguments: \" << std::endl;\n");
105 for (const auto& a : method.GetArguments()) {
106 out.Write(
107 "std::cout << \" %s: \" << ::android::internal::ToString(%s) "
108 "<< std::endl;\n",
109 a->GetName().c_str(), BuildVarName(*a).c_str());
110 }
111
112 // Return Value
113 if (method.GetType().GetName() != "void") {
114 out.Write("if (returnError) {\n");
115 out.Indent();
116 out.Write("std::cout << \" return: <error>\" << std::endl;\n");
117 out.Dedent();
118 out.Write("} else {");
119 out.Indent();
120 out.Write("std::cout << \" return: \" << ::android::internal::ToString(%s) << std::endl;\n",
121 kReturnVarName);
122 out.Dedent();
123 out.Write("}\n");
124 } else {
125 out.Write("std::cout << \" return: void\" << std::endl;\n");
126 }
127 }
128
GenerateAnalyzerSource(CodeWriter & out,const AidlDefinedType & defined_type,const AidlTypenames & typenames,const Options & options)129 void GenerateAnalyzerSource(CodeWriter& out, const AidlDefinedType& defined_type,
130 const AidlTypenames& typenames, const Options& options) {
131 auto interface = AidlCast<AidlInterface>(defined_type);
132 string q_name = GetQualifiedName(*interface, ClassNames::INTERFACE);
133
134 string canonicalName = defined_type.GetCanonicalName();
135 string interfaceName = defined_type.GetName();
136
137 // Includes
138 vector<string> include_list{
139 "iostream", "binder/Parcel.h", "android/binder_to_string.h",
140 HeaderFile(*interface, ClassNames::RAW, false),
141 // HeaderFile(*interface, ClassNames::INTERFACE, false),
142 };
143 for (const auto& include : include_list) {
144 out << "#include <" << include << ">\n";
145 }
146
147 out << "namespace {\n";
148 // Function Start
149 out.Write(
150 "android::status_t analyze%s(uint32_t _aidl_code, const android::Parcel& %s, const "
151 "android::Parcel& %s) {\n",
152 q_name.c_str(), kDataVarName, kReplyVarName);
153 out.Indent();
154 out.Write("android::status_t %s;\nswitch(_aidl_code) {\n", kAndroidStatusVarName);
155 out.Indent();
156
157 // Main Switch Statement
158 for (const auto& method : interface->GetMethods()) {
159 out.Write("case ::android::IBinder::FIRST_CALL_TRANSACTION + %d:\n{\n", (method->GetId()));
160 out.Indent();
161 out.Write("std::cout << \"%s.%s()\" << std::endl;\n", interfaceName.c_str(),
162 method->GetName().c_str());
163 GenerateAnalyzerTransaction(out, *interface, *method, typenames, options);
164 out.Dedent();
165 out << "}\n";
166 out << "break;\n";
167 }
168 out << "default:\n{\n std::cout << \" Transaction code \" << _aidl_code << \" not known.\" << "
169 "std::endl;\n";
170 out.Write("%s = android::UNKNOWN_TRANSACTION;\n}\n", kAndroidStatusVarName);
171 out.Dedent();
172 out.Write("}\nreturn %s;\n", kAndroidStatusVarName);
173 out << "// To prevent unused variable warnings\n";
174 out.Write("(void)%s; (void)%s; (void)%s;\n", kAndroidStatusVarName, kDataVarName, kReplyVarName);
175 out.Dedent();
176 out << "}\n\n} // namespace\n";
177
178 out << "\n#include <Analyzer.h>\nusing android::aidl::Analyzer;\n";
179 out.Write(
180 "__attribute__((constructor)) static void addAnalyzer() {\n"
181 " Analyzer::installAnalyzer(std::make_unique<Analyzer>(\"%s\", \"%s\", &analyze%s));\n}\n",
182 canonicalName.c_str(), interfaceName.c_str(), q_name.c_str());
183 }
184
GenerateAnalyzerPlaceholder(CodeWriter & out,const AidlDefinedType &,const AidlTypenames &,const Options &)185 void GenerateAnalyzerPlaceholder(CodeWriter& out, const AidlDefinedType& /*defined_type*/,
186 const AidlTypenames& /*typenames*/, const Options& /*options*/) {
187 out << "// This file is intentionally left blank as placeholder for building an analyzer.\n";
188 }
189
190 } // namespace
191
GenerateCppAnalyzer(const string & output_file,const Options & options,const AidlTypenames & typenames,const AidlDefinedType & defined_type,const IoDelegate & io_delegate)192 bool GenerateCppAnalyzer(const string& output_file, const Options& options,
193 const AidlTypenames& typenames, const AidlDefinedType& defined_type,
194 const IoDelegate& io_delegate) {
195 if (!ValidateOutputFilePath(output_file, options, defined_type)) {
196 return false;
197 }
198
199 using GenFn = void (*)(CodeWriter & out, const AidlDefinedType& defined_type,
200 const AidlTypenames& typenames, const Options& options);
201 auto gen = [&](auto file, GenFn fn) {
202 unique_ptr<CodeWriter> writer(io_delegate.GetCodeWriter(file));
203
204 GenerateAutoGenHeader(*writer, options);
205
206 fn(*writer, defined_type, typenames, options);
207 AIDL_FATAL_IF(!writer->Close(), defined_type) << "I/O Error!";
208 return true;
209 };
210
211 if (AidlCast<AidlInterface>(defined_type)) {
212 return gen(output_file, &GenerateAnalyzerSource);
213 } else {
214 return gen(output_file, &GenerateAnalyzerPlaceholder);
215 }
216 }
217
218 } // namespace cpp
219 } // namespace aidl
220 } // namespace android
221