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