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