• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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