1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "codegen/c_client_proxy_code_emitter.h"
10 #include "util/file.h"
11 #include "util/logger.h"
12
13 namespace OHOS {
14 namespace HDI {
ResolveDirectory(const String & targetDirectory)15 bool CClientProxyCodeEmitter::ResolveDirectory(const String& targetDirectory)
16 {
17 if (ast_->GetASTFileType() == ASTFileType::AST_IFACE ||
18 ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) {
19 directory_ = GetFilePath(targetDirectory);
20 } else {
21 return false;
22 }
23
24 if (!File::CreateParentDir(directory_)) {
25 Logger::E("CClientProxyCodeEmitter", "Create '%s' failed!", directory_.string());
26 return false;
27 }
28
29 return true;
30 }
31
EmitCode()32 void CClientProxyCodeEmitter::EmitCode()
33 {
34 EmitProxySourceFile();
35 }
36
EmitProxySourceFile()37 void CClientProxyCodeEmitter::EmitProxySourceFile()
38 {
39 String filePath = String::Format("%s/%s.c", directory_.string(), FileName(proxyName_).string());
40 File file(filePath, File::WRITE);
41 StringBuilder sb;
42
43 EmitLicense(sb);
44 EmitProxyInclusions(sb);
45 sb.Append("\n");
46 EmitProxyDefinition(sb);
47 sb.Append("\n");
48 if (!isKernelCode_) {
49 EmitProxyCallMethodImpl(sb);
50 } else {
51 EmitProxyKernelCallMethodImpl(sb);
52 }
53
54 sb.Append("\n");
55 EmitProxyMethodImpls(sb);
56 sb.Append("\n");
57 EmitProxyConstruction(sb);
58 sb.Append("\n");
59 EmitProxyExternalMethodImpl(sb);
60
61 String data = sb.ToString();
62 file.WriteData(data.string(), data.GetLength());
63 file.Flush();
64 file.Close();
65 }
66
EmitProxyInclusions(StringBuilder & sb)67 void CClientProxyCodeEmitter::EmitProxyInclusions(StringBuilder& sb)
68 {
69 HeaderFile::HeaderFileSet headerFiles;
70
71 headerFiles.emplace(HeaderFile(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(interfaceName_)));
72 GetHeaderOtherLibInclusions(headerFiles);
73
74 for (const auto& file : headerFiles) {
75 sb.AppendFormat("%s\n", file.ToString().string());
76 }
77 }
78
GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet & headerFiles)79 void CClientProxyCodeEmitter::GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet& headerFiles)
80 {
81 headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base"));
82 headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_log"));
83 headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_sbuf"));
84 headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "osal_mem"));
85
86 if (isKernelCode_) {
87 headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_io_service_if"));
88 } else {
89 headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "servmgr_hdi"));
90 headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_dlist"));
91 }
92
93 const AST::TypeStringMap& types = ast_->GetTypes();
94 for (const auto& pair : types) {
95 AutoPtr<ASTType> type = pair.second;
96 if (type->GetTypeKind() == TypeKind::TYPE_STRING || type->GetTypeKind() == TypeKind::TYPE_UNION) {
97 headerFiles.emplace(HeaderFile(HeaderFileType::OTHER_MODULES_HEADER_FILE, "securec"));
98 break;
99 }
100 }
101 }
102
EmitProxyDefinition(StringBuilder & sb)103 void CClientProxyCodeEmitter::EmitProxyDefinition(StringBuilder& sb)
104 {
105 sb.AppendFormat("struct %sProxy {\n", baseName_.string());
106 sb.Append(g_tab).AppendFormat("struct %s impl;\n", interfaceName_.string());
107 if (isKernelCode_) {
108 sb.Append(g_tab).Append("struct HdfIoService *serv;\n");
109 } else {
110 sb.Append(g_tab).Append("struct HdfRemoteService *remote;\n");
111 }
112
113 sb.Append("};\n");
114 }
115
EmitProxyCallMethodImpl(StringBuilder & sb)116 void CClientProxyCodeEmitter::EmitProxyCallMethodImpl(StringBuilder& sb)
117 {
118 sb.AppendFormat("static int32_t %sProxyCall(struct %s *self, int32_t id, struct HdfSBuf *data,\n",
119 baseName_.string(), interfaceName_.string());
120 sb.Append(g_tab).Append("struct HdfSBuf *reply, bool isOneWay)\n");
121 sb.Append("{\n");
122
123 String remoteName = "remote";
124 sb.Append(g_tab).AppendFormat("struct HdfRemoteService *%s = self->AsObject(self);\n", remoteName.string());
125 sb.Append(g_tab).AppendFormat("if (%s == NULL\n", remoteName.string());
126 sb.Append(g_tab).Append(g_tab).AppendFormat("|| %s->dispatcher == NULL\n", remoteName.string());
127 sb.Append(g_tab).Append(g_tab).AppendFormat("|| %s->dispatcher->Dispatch == NULL\n", remoteName.string());
128 sb.Append(g_tab).Append(g_tab).AppendFormat("|| %s->dispatcher->DispatchAsync == NULL) {\n",
129 remoteName.string());
130 sb.Append(g_tab).Append(g_tab).Append("HDF_LOGE(\"%{public}s: Invalid HdfRemoteService obj\", __func__);\n");
131 sb.Append(g_tab).Append(g_tab).Append("return HDF_ERR_INVALID_OBJECT;\n");
132 sb.Append(g_tab).Append("}\n");
133
134 sb.Append(g_tab).AppendFormat("if (isOneWay) {\n");
135 sb.Append(g_tab).Append(g_tab).AppendFormat("return %s->dispatcher->DispatchAsync(%s, id, data, reply);\n",
136 remoteName.string(), remoteName.string());
137 sb.Append(g_tab).AppendFormat("} else {\n");
138 sb.Append(g_tab).Append(g_tab).AppendFormat("return %s->dispatcher->Dispatch(%s, id, data, reply);\n",
139 remoteName.string(), remoteName.string());
140 sb.Append(g_tab).AppendFormat("}\n");
141 sb.Append("}\n");
142 }
143
EmitProxyKernelCallMethodImpl(StringBuilder & sb)144 void CClientProxyCodeEmitter::EmitProxyKernelCallMethodImpl(StringBuilder& sb)
145 {
146 sb.AppendFormat("static int32_t %sProxyCall(struct %s *self, int32_t id, struct HdfSBuf *data,\n",
147 baseName_.string(), interfaceName_.string());
148 sb.Append(g_tab).Append("struct HdfSBuf *reply)\n");
149 sb.Append("{\n");
150
151 String remoteName = "serv";
152 sb.Append(g_tab).AppendFormat("struct %sProxy *proxy = CONTAINER_OF(self, struct %sProxy, impl);\n",
153 baseName_.string(), baseName_.string(), remoteName.string());
154 sb.Append(g_tab).AppendFormat("struct HdfIoService *%s = proxy->%s;\n", remoteName.string(), remoteName.string());
155
156 sb.Append(g_tab).AppendFormat("if (%s == NULL\n", remoteName.string());
157 sb.Append(g_tab).Append(g_tab).AppendFormat("|| %s->dispatcher == NULL\n", remoteName.string());
158 sb.Append(g_tab).Append(g_tab).AppendFormat("|| %s->dispatcher->Dispatch == NULL) {\n", remoteName.string());
159 sb.Append(g_tab).Append(g_tab).Append("HDF_LOGE(\"%{public}s: Invalid HdfRemoteService obj\", __func__);\n");
160 sb.Append(g_tab).Append(g_tab).Append("return HDF_ERR_INVALID_OBJECT;\n");
161 sb.Append(g_tab).Append("}\n\n");
162
163 sb.Append(g_tab).AppendFormat("return %s->dispatcher->Dispatch(", remoteName.string());
164 sb.AppendFormat("(struct HdfObject *)&(%s->object), id, data, reply);\n", remoteName.string());
165 sb.Append("}\n");
166 }
167
EmitProxyMethodImpls(StringBuilder & sb)168 void CClientProxyCodeEmitter::EmitProxyMethodImpls(StringBuilder& sb)
169 {
170 for (size_t i = 0; i < interface_->GetMethodNumber(); i++) {
171 AutoPtr<ASTMethod> method = interface_->GetMethod(i);
172 EmitProxyMethodImpl(method, sb);
173 sb.Append("\n");
174 }
175
176 EmitProxyMethodImpl(interface_->GetVersionMethod(), sb);
177
178 if (!isKernelCode_) {
179 sb.Append("\n");
180 EmitProxyAsObjectMethodImpl(sb);
181 }
182 }
183
EmitProxyMethodImpl(const AutoPtr<ASTMethod> & method,StringBuilder & sb)184 void CClientProxyCodeEmitter::EmitProxyMethodImpl(const AutoPtr<ASTMethod>& method, StringBuilder& sb)
185 {
186 if (method->GetParameterNumber() == 0) {
187 sb.AppendFormat("static int32_t %sProxy%s(struct %s *self)\n",
188 baseName_.string(), method->GetName().string(), interfaceName_.string());
189 } else {
190 StringBuilder paramStr;
191 paramStr.AppendFormat("static int32_t %sProxy%s(", baseName_.string(), method->GetName().string());
192 paramStr.AppendFormat("struct %s *self, ", interfaceName_.string());
193 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
194 AutoPtr<ASTParameter> param = method->GetParameter(i);
195 EmitInterfaceMethodParameter(param, paramStr, "");
196 if (i + 1 < method->GetParameterNumber()) {
197 paramStr.Append(", ");
198 }
199 }
200
201 paramStr.Append(")");
202 sb.Append(SpecificationParam(paramStr, g_tab));
203 sb.Append("\n");
204 }
205 EmitProxyMethodBody(method, sb, "");
206 }
207
EmitProxyMethodBody(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const String & prefix)208 void CClientProxyCodeEmitter::EmitProxyMethodBody(const AutoPtr<ASTMethod>& method, StringBuilder& sb,
209 const String& prefix)
210 {
211 sb.Append(prefix).Append("{\n");
212 sb.Append(prefix + g_tab).AppendFormat("int32_t %s = HDF_FAILURE;\n", errorCodeName_.string());
213
214 // Local variable definitions must precede all execution statements.
215 EmitInitLoopVar(method, sb, prefix + g_tab);
216
217 sb.Append("\n");
218 EmitCreateBuf(dataParcelName_, replyParcelName_, sb, prefix + g_tab);
219
220 if (!isKernelCode_) {
221 sb.Append("\n");
222 EmitWriteInterfaceToken(dataParcelName_, sb, prefix + g_tab);
223 }
224
225 sb.Append("\n");
226 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
227 AutoPtr<ASTParameter> param = method->GetParameter(i);
228 if (param->GetAttribute() == ParamAttr::PARAM_IN) {
229 param->EmitCWriteVar(dataParcelName_, errorCodeName_, finishedLabelName_, sb, prefix + g_tab);
230 sb.Append("\n");
231 } else if (param->EmitCProxyWriteOutVar(dataParcelName_, errorCodeName_, finishedLabelName_, sb,
232 prefix + g_tab)) {
233 sb.Append("\n");
234 }
235 }
236
237 EmitStubCallMethod(method, sb, prefix + g_tab);
238 sb.Append("\n");
239
240 if (!method->IsOneWay()) {
241 for (size_t i = 0; i < method->GetParameterNumber(); i++) {
242 AutoPtr<ASTParameter> param = method->GetParameter(i);
243 if (param->GetAttribute() == ParamAttr::PARAM_OUT) {
244 EmitReadProxyMethodParameter(param, replyParcelName_, finishedLabelName_, sb, prefix + g_tab);
245 sb.Append("\n");
246 }
247 }
248 }
249
250 sb.Append(prefix).AppendFormat("%s:\n", finishedLabelName_);
251 EmitReleaseBuf(dataParcelName_, replyParcelName_, sb, prefix + g_tab);
252
253 sb.Append(prefix + g_tab).AppendFormat("return %s;\n", errorCodeName_.string());
254 sb.Append("}\n");
255 }
256
EmitCreateBuf(const String & dataBufName,const String & replyBufName,StringBuilder & sb,const String & prefix)257 void CClientProxyCodeEmitter::EmitCreateBuf(const String& dataBufName, const String& replyBufName,
258 StringBuilder& sb, const String& prefix)
259 {
260 if (isKernelCode_) {
261 sb.Append(prefix).AppendFormat("struct HdfSBuf *%s = HdfSbufObtainDefaultSize();\n", dataBufName.string());
262 sb.Append(prefix).AppendFormat("struct HdfSBuf *%s = HdfSbufObtainDefaultSize();\n", replyBufName.string());
263 } else {
264 sb.Append(prefix).AppendFormat("struct HdfSBuf *%s = HdfSbufTypedObtain(SBUF_IPC);\n", dataBufName.string());
265 sb.Append(prefix).AppendFormat("struct HdfSBuf *%s = HdfSbufTypedObtain(SBUF_IPC);\n", replyBufName.string());
266 }
267
268 sb.Append("\n");
269 sb.Append(prefix).AppendFormat("if (%s == NULL || %s == NULL) {\n", dataBufName.string(), replyBufName.string());
270 sb.Append(prefix + g_tab).Append("HDF_LOGE(\"%{public}s: HdfSubf malloc failed!\", __func__);\n");
271 sb.Append(prefix + g_tab).AppendFormat("%s = HDF_ERR_MALLOC_FAIL;\n", errorCodeName_.string());
272 sb.Append(prefix + g_tab).AppendFormat("goto %s;\n", finishedLabelName_);
273 sb.Append(prefix).Append("}\n");
274 }
275
EmitWriteInterfaceToken(const String & dataBufName,StringBuilder & sb,const String & prefix)276 void CClientProxyCodeEmitter::EmitWriteInterfaceToken(const String& dataBufName, StringBuilder& sb,
277 const String& prefix)
278 {
279 sb.Append(prefix).AppendFormat("if (!HdfRemoteServiceWriteInterfaceToken(self->AsObject(self), %s)) {\n",
280 dataBufName.string());
281 sb.Append(prefix + g_tab).Append("HDF_LOGE(\"%{public}s: write interface token failed!\", __func__);\n");
282 sb.Append(prefix + g_tab).AppendFormat("%s = HDF_ERR_INVALID_PARAM;\n", errorCodeName_.string());
283 sb.Append(prefix + g_tab).AppendFormat("goto %s;\n", finishedLabelName_);
284 sb.Append(prefix).Append("}\n");
285 }
286
EmitReleaseBuf(const String & dataBufName,const String & replyBufName,StringBuilder & sb,const String & prefix)287 void CClientProxyCodeEmitter::EmitReleaseBuf(const String& dataBufName, const String& replyBufName, StringBuilder& sb,
288 const String& prefix)
289 {
290 sb.Append(prefix).AppendFormat("if (%s != NULL) {\n", dataBufName.string());
291 sb.Append(prefix + g_tab).AppendFormat("HdfSbufRecycle(%s);\n", dataBufName.string());
292 sb.Append(prefix).Append("}\n");
293 sb.Append(prefix).AppendFormat("if (%s != NULL) {\n", replyBufName.string());
294 sb.Append(prefix + g_tab).AppendFormat("HdfSbufRecycle(%s);\n", replyBufName.string());
295 sb.Append(prefix).Append("}\n");
296 }
297
EmitReadProxyMethodParameter(const AutoPtr<ASTParameter> & param,const String & parcelName,const String & gotoLabel,StringBuilder & sb,const String & prefix)298 void CClientProxyCodeEmitter::EmitReadProxyMethodParameter(const AutoPtr<ASTParameter>& param,
299 const String& parcelName, const String& gotoLabel, StringBuilder& sb, const String& prefix)
300 {
301 AutoPtr<ASTType> type = param->GetType();
302 if (type->GetTypeKind() == TypeKind::TYPE_STRING) {
303 String cloneName = String::Format("%sCopy", param->GetName().string());
304 type->EmitCProxyReadVar(parcelName, cloneName, false, errorCodeName_, gotoLabel, sb, prefix);
305 sb.Append(prefix).AppendFormat("if (strcpy_s(%s, %sLen, %s) != EOK) {\n",
306 param->GetName().string(), param->GetName().string(), cloneName.string());
307 sb.Append(prefix + g_tab).AppendFormat("HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n",
308 param->GetName().string());
309 sb.Append(prefix + g_tab).AppendFormat("%s = HDF_ERR_INVALID_PARAM;\n", errorCodeName_.string());
310 sb.Append(prefix + g_tab).AppendFormat("goto %s;\n", gotoLabel.string());
311 sb.Append(prefix).Append("}\n");
312 } else if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) {
313 type->EmitCProxyReadVar(parcelName, param->GetName().string(), false, errorCodeName_, gotoLabel, sb, prefix);
314 } else if (type->GetTypeKind() == TypeKind::TYPE_UNION) {
315 String cpName = String::Format("%sCp", param->GetName().string());
316 type->EmitCProxyReadVar(parcelName, cpName, false, errorCodeName_, gotoLabel, sb, prefix);
317 sb.Append(prefix).AppendFormat("(void)memcpy_s(%s, sizeof(%s), %s, sizeof(%s));\n",
318 param->GetName().string(), type->EmitCType().string(), cpName.string(), type->EmitCType().string());
319 } else {
320 type->EmitCProxyReadVar(parcelName, param->GetName(), false, errorCodeName_, gotoLabel, sb, prefix);
321 }
322 }
323
EmitStubCallMethod(const AutoPtr<ASTMethod> & method,StringBuilder & sb,const String & prefix)324 void CClientProxyCodeEmitter::EmitStubCallMethod(const AutoPtr<ASTMethod>& method, StringBuilder& sb,
325 const String& prefix)
326 {
327 if (!isKernelCode_) {
328 sb.Append(prefix).AppendFormat("%s = %sCall(self, %s, %s, %s, %s);\n", errorCodeName_.string(),
329 proxyName_.string(), EmitMethodCmdID(method).string(), dataParcelName_.string(),
330 replyParcelName_.string(), method->IsOneWay() ? "true" : "false");
331 } else {
332 sb.Append(prefix).AppendFormat("%s = %sCall(self, %s, %s, %s);\n", errorCodeName_.string(),
333 proxyName_.string(), EmitMethodCmdID(method).string(), dataParcelName_.string(),
334 replyParcelName_.string());
335 }
336 sb.Append(prefix).AppendFormat("if (%s != HDF_SUCCESS) {\n", errorCodeName_.string());
337 sb.Append(prefix + g_tab).AppendFormat(
338 "HDF_LOGE(\"%%{public}s: call failed! error code is %%{public}d\", __func__, %s);\n", errorCodeName_.string());
339 sb.Append(prefix + g_tab).AppendFormat("goto %s;\n", finishedLabelName_);
340 sb.Append(prefix).Append("}\n");
341 }
342
EmitProxyAsObjectMethodImpl(StringBuilder & sb)343 void CClientProxyCodeEmitter::EmitProxyAsObjectMethodImpl(StringBuilder& sb)
344 {
345 sb.AppendFormat("static struct HdfRemoteService *%sProxyAsObject(struct %s *self)\n",
346 baseName_.string(), interfaceName_.string());
347 sb.Append("{\n");
348 sb.Append(g_tab).Append("if (self == NULL) {\n");
349 sb.Append(g_tab).Append(g_tab).Append("return NULL;\n");
350 sb.Append(g_tab).Append("}\n");
351 sb.Append(g_tab).AppendFormat("struct %sProxy *proxy = CONTAINER_OF(self, struct %sProxy, impl);\n",
352 baseName_.string(), baseName_.string());
353 sb.Append(g_tab).Append("return proxy->remote;\n");
354 sb.Append("}\n");
355 }
356
EmitProxyConstruction(StringBuilder & sb)357 void CClientProxyCodeEmitter::EmitProxyConstruction(StringBuilder& sb)
358 {
359 String objName = "impl";
360 sb.AppendFormat("static void %sProxyConstruct(struct %s *%s)\n",
361 baseName_.string(), interfaceName_.string(), objName.string());
362 sb.Append("{\n");
363
364 for (size_t i = 0; i < interface_->GetMethodNumber(); i++) {
365 AutoPtr<ASTMethod> method = interface_->GetMethod(i);
366 sb.Append(g_tab).AppendFormat("%s->%s = %sProxy%s;\n",
367 objName.string(), method->GetName().string(), baseName_.string(), method->GetName().string());
368 }
369
370 AutoPtr<ASTMethod> getVerMethod = interface_->GetVersionMethod();
371 sb.Append(g_tab).AppendFormat("%s->%s = %sProxy%s;\n", objName.string(), getVerMethod->GetName().string(),
372 baseName_.string(), getVerMethod->GetName().string());
373
374 if (!isKernelCode_) {
375 sb.Append(g_tab).AppendFormat("%s->AsObject = %sProxyAsObject;\n", objName.string(), baseName_.string());
376 }
377
378 sb.Append("}\n");
379 }
380
EmitProxyExternalMethodImpl(StringBuilder & sb)381 void CClientProxyCodeEmitter::EmitProxyExternalMethodImpl(StringBuilder& sb)
382 {
383 String objName = "client";
384 String serMajorName = "serMajorVer";
385 String serMinorName = "serMinorVer";
386 String remoteName = "remote";
387 String serviceName = "serviceName";
388
389 if (isKernelCode_) {
390 remoteName = "serv";
391 EmitProxyGetMethodImpl(sb);
392 sb.Append("\n");
393 EmitKernelProxyGetInstanceMethodImpl(objName, serMajorName, serMinorName, remoteName, serviceName, sb);
394 sb.Append("\n");
395 EmitProxyReleaseMethodImpl(remoteName, "HdfIoServiceRecycle", sb);
396 } else if (interface_->IsSerializable()) {
397 EmitCbProxyGetMethodImpl(objName, serMajorName, serMinorName, remoteName, sb);
398 sb.Append("\n");
399 EmitProxyReleaseMethodImpl(remoteName, "HdfRemoteServiceRecycle", sb);
400 } else {
401 EmitProxyGetMethodImpl(sb);
402 sb.Append("\n");
403 EmitProxyGetInstanceMethodImpl(objName, serMajorName, serMinorName, remoteName, serviceName, sb);
404 sb.Append("\n");
405 EmitProxyReleaseMethodImpl(remoteName, "HdfRemoteServiceRecycle", sb);
406 }
407 }
408
EmitProxyGetMethodImpl(StringBuilder & sb)409 void CClientProxyCodeEmitter::EmitProxyGetMethodImpl(StringBuilder& sb)
410 {
411 sb.AppendFormat("struct %s *%sGet()\n", interfaceName_.string(), baseName_.string());
412 sb.Append("{\n");
413 sb.Append(g_tab).AppendFormat("return %sGetInstance(\"%s\");\n", baseName_.string(), FileName(implName_).string());
414 sb.Append("}\n");
415 }
416
EmitProxyGetInstanceMethodImpl(const String & objName,const String & serMajorName,const String & serMinorName,const String & remoteName,const String & serviceName,StringBuilder & sb)417 void CClientProxyCodeEmitter::EmitProxyGetInstanceMethodImpl(const String& objName, const String& serMajorName,
418 const String& serMinorName, const String& remoteName, const String& serviceName, StringBuilder& sb)
419 {
420 sb.AppendFormat("struct %s *%sGetInstance(const char *%s)\n", interfaceName_.string(), baseName_.string(),
421 serviceName.string());
422 sb.Append("{\n");
423 EmitProxyGetRemoteService(remoteName, serviceName, sb, g_tab);
424 sb.Append("\n");
425 EmitProxySetInterfaceDesc(remoteName, "HdfRemoteServiceRecycle", sb, g_tab);
426 sb.Append("\n");
427 EmitProxyCreateProxyObject(objName, remoteName, "HdfRemoteServiceRecycle", sb, g_tab);
428 sb.Append("\n");
429 EmitProxyCheckVersion(objName, serMajorName, serMinorName, sb, g_tab);
430 sb.Append("\n");
431 sb.Append(g_tab).AppendFormat("return %s;\n", objName.string());
432 sb.Append("}\n");
433 }
434
EmitKernelProxyGetInstanceMethodImpl(const String & objName,const String & serMajorName,const String & serMinorName,const String & remoteName,const String & serviceName,StringBuilder & sb)435 void CClientProxyCodeEmitter::EmitKernelProxyGetInstanceMethodImpl(const String& objName, const String& serMajorName,
436 const String& serMinorName, const String& remoteName, const String& serviceName, StringBuilder& sb)
437 {
438 sb.AppendFormat("struct %s *%sGetInstance(const char* %s)\n", interfaceName_.string(), baseName_.string(),
439 serviceName.string());
440 sb.Append("{\n");
441 EmitProxyGetRemoteService(remoteName, serviceName, sb, g_tab);
442 sb.Append("\n");
443 EmitProxyCreateProxyObject(objName, remoteName, "HdfIoServiceRecycle", sb, g_tab);
444 sb.Append("\n");
445 EmitProxyCheckVersion(objName, serMajorName, serMinorName, sb, g_tab);
446 sb.Append("\n");
447 sb.Append(g_tab).AppendFormat("return %s;\n", objName.string());
448 sb.Append("}\n");
449 }
450
EmitCbProxyGetMethodImpl(const String & objName,const String & serMajorName,const String & serMinorName,const String & remoteName,StringBuilder & sb)451 void CClientProxyCodeEmitter::EmitCbProxyGetMethodImpl(const String& objName, const String& serMajorName,
452 const String& serMinorName, const String& remoteName, StringBuilder& sb)
453 {
454 sb.AppendFormat("struct %s *%sGet(struct HdfRemoteService *%s)\n", interfaceName_.string(), baseName_.string(),
455 remoteName.string());
456 sb.Append("{\n");
457 sb.Append(g_tab).AppendFormat("if (%s == NULL) {\n", remoteName.string());
458 sb.Append(g_tab).Append(g_tab).AppendFormat("HDF_LOGE(\"%%{public}s: remote is null\", __func__);\n");
459 sb.Append(g_tab).Append(g_tab).Append("return NULL;\n");
460 sb.Append(g_tab).Append("}\n\n");
461 EmitProxySetInterfaceDesc(remoteName, "HdfRemoteServiceRecycle", sb, g_tab);
462 sb.Append("\n");
463 EmitProxyCreateProxyObject(objName, remoteName, "HdfRemoteServiceRecycle", sb, g_tab);
464 sb.Append("\n");
465 EmitProxyCheckVersion(objName, serMajorName, serMinorName, sb, g_tab);
466 sb.Append("\n");
467 sb.Append(g_tab).AppendFormat("return %s;\n", objName.string());
468 sb.Append("}\n");
469 }
470
EmitProxyGetRemoteService(const String & remoteName,const String & serviceName,StringBuilder & sb,const String & prefix)471 void CClientProxyCodeEmitter::EmitProxyGetRemoteService(const String& remoteName, const String& serviceName,
472 StringBuilder& sb, const String& prefix)
473 {
474 if (!isKernelCode_) {
475 sb.Append(prefix).Append("struct HDIServiceManager *serviceMgr = HDIServiceManagerGet();\n");
476 sb.Append(prefix).Append("if (serviceMgr == NULL) {\n");
477 sb.Append(prefix + g_tab).Append("HDF_LOGE(\"%{public}s: HDIServiceManager not found!\", __func__);\n");
478 sb.Append(prefix + g_tab).Append("return NULL;\n");
479 sb.Append(prefix).Append("}\n\n");
480 sb.Append(prefix).AppendFormat("struct HdfRemoteService *%s = ", remoteName.string());
481 sb.AppendFormat("serviceMgr->GetService(serviceMgr, %s);\n", serviceName.string());
482 sb.Append(prefix).Append("HDIServiceManagerRelease(serviceMgr);\n");
483 sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", remoteName.string());
484 sb.Append(prefix + g_tab).Append("HDF_LOGE(\"%{public}s: failed to get remote!\", __func__);\n");
485 sb.Append(prefix + g_tab).Append("return NULL;\n");
486 sb.Append(prefix).Append("}\n");
487 } else {
488 sb.Append(prefix).AppendFormat("struct HdfIoService *%s = ", remoteName.string());
489 sb.AppendFormat("HdfIoServiceBind(%s);\n", serviceName.string());
490 sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", remoteName.string());
491 sb.Append(prefix + g_tab).Append("HDF_LOGE(\"%{public}s: failed to get io service!\", __func__);\n");
492 sb.Append(prefix + g_tab).Append("return NULL;\n");
493 sb.Append(prefix).Append("}\n");
494 }
495 }
496
EmitProxySetInterfaceDesc(const String & remoteName,const String & recycleFuncName,StringBuilder & sb,const String & prefix)497 void CClientProxyCodeEmitter::EmitProxySetInterfaceDesc(const String& remoteName, const String& recycleFuncName,
498 StringBuilder& sb, const String& prefix)
499 {
500 sb.Append(prefix).AppendFormat("if (!HdfRemoteServiceSetInterfaceDesc(%s, %s)) {\n",
501 remoteName.string(), EmitDescMacroName().string());
502 sb.Append(prefix + g_tab).Append("HDF_LOGE(\"%{public}s: set interface token failed!\", __func__);\n");
503 sb.Append(prefix + g_tab).AppendFormat("%s(%s);\n", recycleFuncName.string(), remoteName.string());
504 sb.Append(prefix + g_tab).Append("return NULL;\n");
505 sb.Append(prefix).Append("}\n");
506 }
507
EmitProxyCreateProxyObject(const String & clientObjName,const String & remoteName,const String & recycleFuncName,StringBuilder & sb,const String & prefix)508 void CClientProxyCodeEmitter::EmitProxyCreateProxyObject(const String& clientObjName, const String& remoteName,
509 const String& recycleFuncName, StringBuilder& sb, const String& prefix)
510 {
511 sb.Append(prefix).AppendFormat("struct %sProxy *proxy = (struct %sProxy *)OsalMemCalloc(sizeof(struct %sProxy));\n",
512 baseName_.string(), baseName_.string(), baseName_.string());
513 sb.Append(prefix).Append("if (proxy == NULL) {\n");
514 sb.Append(prefix + g_tab).AppendFormat(
515 "HDF_LOGE(\"%%{public}s: malloc %s proxy failed!\", __func__);\n", interfaceName_.string());
516 if (!interface_->IsSerializable()) {
517 sb.Append(prefix + g_tab).AppendFormat("%s(%s);\n", recycleFuncName.string(), remoteName.string());
518 }
519 sb.Append(prefix + g_tab).Append("return NULL;\n");
520 sb.Append(prefix).Append("}\n");
521 sb.Append("\n");
522 sb.Append(prefix).AppendFormat("proxy->%s = %s;\n", remoteName.string(), remoteName.string());
523 sb.Append(prefix).AppendFormat("%sProxyConstruct(&proxy->impl);\n", baseName_.string());
524 sb.Append(prefix).AppendFormat("struct %s *%s = &proxy->impl;\n", interfaceName_.string(), clientObjName.string());
525 }
526
EmitProxyCheckVersion(const String & clientObjName,const String & serMajorName,const String & serMinorName,StringBuilder & sb,const String & prefix)527 void CClientProxyCodeEmitter::EmitProxyCheckVersion(const String& clientObjName, const String& serMajorName,
528 const String& serMinorName, StringBuilder& sb, const String& prefix)
529 {
530 sb.Append(prefix).AppendFormat("uint32_t %s = 0;\n", serMajorName.string());
531 sb.Append(prefix).AppendFormat("uint32_t %s = 0;\n", serMinorName.string());
532 sb.Append(prefix).AppendFormat("int32_t %s = %s->GetVersion(%s, &%s, &%s);\n", errorCodeName_.string(),
533 clientObjName.string(), clientObjName.string(), serMajorName.string(), serMinorName.string());
534 sb.Append(prefix).AppendFormat("if (%s != HDF_SUCCESS) {\n", errorCodeName_.string());
535 sb.Append(prefix + g_tab).Append("HDF_LOGE(\"%{public}s: get version failed!\", __func__);\n");
536 sb.Append(prefix + g_tab).AppendFormat("%sRelease(%s);\n", baseName_.string(), clientObjName.string());
537 sb.Append(prefix + g_tab).Append("return NULL;\n");
538 sb.Append(prefix).Append("}\n\n");
539 sb.Append(prefix).AppendFormat("if (%s != %s) {\n", serMajorName.string(), majorVerName_.string());
540 sb.Append(prefix + g_tab).Append("HDF_LOGE(\"%{public}s:check version failed! ");
541 sb.Append("version of service:%u.%u, version of client:%u.%u\", __func__,\n");
542 sb.Append(prefix + g_tab + g_tab).AppendFormat("%s, %s, %s, %s);\n", serMajorName.string(),
543 serMinorName.string(), majorVerName_.string(), minorVerName_.string());
544 sb.Append(prefix + g_tab).AppendFormat("%sRelease(%s);\n", baseName_.string(), clientObjName.string());
545 sb.Append(prefix + g_tab).Append("return NULL;\n");
546 sb.Append(prefix).Append("}\n");
547 }
548
EmitProxyReleaseMethodImpl(const String & remoteName,const String & recycleFuncName,StringBuilder & sb)549 void CClientProxyCodeEmitter::EmitProxyReleaseMethodImpl(const String& remoteName, const String& recycleFuncName,
550 StringBuilder& sb)
551 {
552 sb.AppendFormat("void %sRelease(struct %s *instance)\n", baseName_.string(), interfaceName_.string());
553 sb.Append("{\n");
554 sb.Append(g_tab).Append("if (instance == NULL) {\n");
555 sb.Append(g_tab).Append(g_tab).Append("return;\n");
556 sb.Append(g_tab).Append("}\n");
557 sb.Append(g_tab).AppendFormat("struct %sProxy *proxy = CONTAINER_OF(instance, struct %sProxy, impl);\n",
558 baseName_.string(), baseName_.string());
559 sb.Append(g_tab).AppendFormat("%s(proxy->%s);\n", recycleFuncName.string(), remoteName.string());
560 sb.Append(g_tab).Append("OsalMemFree(proxy);\n");
561 sb.Append("}\n");
562 }
563 } // namespace HDI
564 } // namespace OHOS