• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "sa_cpp_client_code_emitter.h"
17 #include "util/file.h"
18 
19 namespace OHOS {
20 namespace Idl {
21 
EmitCode()22 void SaCppClientCodeEmitter::EmitCode()
23 {
24     SaTypeEmitter::circleCount_ = 0;
25     EmitClientHeaderFile();
26     EmitClientSourceFile();
27 }
28 
EmitClientHeaderFile()29 void SaCppClientCodeEmitter::EmitClientHeaderFile()
30 {
31     std::string filePath =
32         File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(clientName_).c_str()));
33     File file(filePath, File::WRITE);
34     StringBuilder sb;
35 
36     EmitLicense(sb);
37     EmitHeadMacro(sb, clientFullName_);
38     sb.Append('\n');
39 
40     sb.Append("#include <shared_mutex>\n");
41     sb.Append("#include <utility>\n");
42     sb.Append("#include <iremote_proxy.h>\n");
43     sb.Append("#include <if_system_ability_manager.h>\n");
44     sb.Append("#include <iservice_registry.h>\n");
45     sb.Append("#include <system_ability_load_callback_stub.h>\n");
46 
47     EmitSecurecInclusion(sb);
48     sb.AppendFormat("#include \"%s.h\"\n", FileName(interfaceName_).c_str());
49     sb.Append('\n');
50     EmitInterfaceClientInHeaderFile(sb);
51     EmitTailMacro(sb, clientFullName_);
52 
53     std::string data = sb.ToString();
54     file.WriteData(data.c_str(), data.size());
55     file.Flush();
56     file.Close();
57 }
58 
EmitInterfaceClientInHeaderFile(StringBuilder & sb) const59 void SaCppClientCodeEmitter::EmitInterfaceClientInHeaderFile(StringBuilder &sb) const
60 {
61     EmitBeginNamespace(sb);
62     EmitImportUsingNamespace(sb);
63     sb.AppendFormat("using %sOnRemoteDiedCallback = std::function<void()>;\n", baseName_.c_str());
64     sb.AppendFormat("using %sOnLocalCallback = std::function<void(bool status)>;\n\n", baseName_.c_str());
65     sb.AppendFormat("class %s {\n", clientName_.c_str());
66     sb.Append("public:\n");
67     EmitInterfaceClientConstructor(sb, TAB);
68     sb.Append('\n');
69     EmitLoadCallback(sb, TAB);
70     sb.Append('\n');
71     EmitInterfaceClientMethodDecls(sb, TAB);
72     sb.Append('\n');
73     sb.Append("private:\n");
74     EmitInterfaceClientDeathRecipient(sb, TAB);
75     sb.Append("\n");
76     EmitInterfaceClientSetParam(sb, TAB);
77     sb.Append("};\n");
78     EmitEndNamespace(sb);
79 }
80 
EmitInterfaceClientConstructor(StringBuilder & sb,const std::string & prefix) const81 void SaCppClientCodeEmitter::EmitInterfaceClientConstructor(StringBuilder &sb, const std::string &prefix) const
82 {
83     sb.Append(prefix).AppendFormat("explicit %s(int32_t systemAbilityId, const std::string &deviceId = \"\");\n",
84         clientName_.c_str());
85     sb.Append('\n');
86     sb.Append(prefix).AppendFormat("~%s();\n", clientName_.c_str());
87 }
88 
EmitLoadCallback(StringBuilder & sb,const std::string & prefix) const89 void SaCppClientCodeEmitter::EmitLoadCallback(StringBuilder &sb, const std::string &prefix) const
90 {
91     sb.Append(prefix).Append("/**\n");
92     sb.Append(prefix).Append(" * Sync load sa with timeout\n");
93     sb.Append(prefix).Append(" * @param timeout timeout seconds\n");
94     sb.Append(prefix).Append(" * @return error code\n");
95     sb.Append(prefix).Append(" */\n");
96     sb.Append(prefix).Append("ErrCode LoadSystemAbility(int32_t timeout);\n\n");
97 
98     sb.Append(prefix).Append("/**\n");
99     sb.Append(prefix).Append(" * Async load sa with a callback\n");
100     sb.Append(prefix).Append(" * @param cb callback function\n");
101     sb.Append(prefix).Append(" * @return error code\n");
102     sb.Append(prefix).Append(" */\n");
103     sb.Append(prefix).AppendFormat("ErrCode LoadSystemAbility(const %sOnLocalCallback &cb);\n\n", baseName_.c_str());
104 
105     sb.Append(prefix).Append("/**\n");
106     sb.Append(prefix).Append(" * Check sa\n");
107     sb.Append(prefix).Append(" * @return error code\n");
108     sb.Append(prefix).Append(" */\n");
109     sb.Append(prefix).Append("ErrCode CheckSystemAbility();\n\n");
110 
111     sb.Append(prefix).Append("/**\n");
112     sb.Append(prefix).Append(" * Get proxy status\n");
113     sb.Append(prefix).Append(" * @return status\n");
114     sb.Append(prefix).Append(" */\n");
115     sb.Append(prefix).AppendFormat("bool Get%sStatus();\n\n", proxyName_.c_str());
116 
117     sb.Append(prefix).Append("/**\n");
118     sb.Append(prefix).Append(" * Register remote death callback function\n");
119     sb.Append(prefix).Append(" * @param cb callback function\n");
120     sb.Append(prefix).Append(" */\n");
121     sb.Append(prefix).AppendFormat("void RegisterOnRemoteDiedCallback(const %sOnRemoteDiedCallback &cb);\n",
122         baseName_.c_str());
123 }
124 
EmitInterfaceClientMethodDecls(StringBuilder & sb,const std::string & prefix) const125 void SaCppClientCodeEmitter::EmitInterfaceClientMethodDecls(StringBuilder &sb, const std::string &prefix) const
126 {
127     if (interface_ == nullptr) {
128         return;
129     }
130     size_t methodNumber = interface_->GetMethodNumber();
131     for (size_t i = 0; i < methodNumber; i++) {
132         AutoPtr<ASTMethod> method = interface_->GetMethod(i);
133         if (method == nullptr) {
134             return;
135         }
136         EmitInterfaceClientMethodDecl(method, sb, prefix);
137         if (i != methodNumber - 1) {
138             sb.Append('\n');
139         }
140     }
141 }
142 
EmitInterfaceClientMethodDecl(AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const143 void SaCppClientCodeEmitter::EmitInterfaceClientMethodDecl(AutoPtr<ASTMethod> &method, StringBuilder &sb,
144     const std::string &prefix) const
145 {
146     if (method->IsMacro()) {
147         sb.AppendFormat("#%s %s\n", method->GetMacroType().c_str(), method->GetMacroVal().c_str());
148     }
149     sb.Append(prefix).AppendFormat("ErrCode %s(", method->GetName().c_str());
150     EmitInterfaceClientMethodParams(method, sb, prefix + TAB, true);
151     sb.Append(");\n");
152     if (method->IsMacro()) {
153         sb.Append("#endif\n");
154     }
155 }
156 
EmitInterfaceClientDeathRecipient(StringBuilder & sb,const std::string & prefix) const157 void SaCppClientCodeEmitter::EmitInterfaceClientDeathRecipient(StringBuilder &sb, const std::string &prefix) const
158 {
159     sb.Append(prefix).Append("// death callback class\n");
160     sb.Append(prefix).AppendFormat("class %sRecipient : public IRemoteObject::DeathRecipient {\n", baseName_.c_str());
161     sb.Append(prefix).Append("public:\n");
162     sb.Append(prefix + TAB).AppendFormat("explicit %sRecipient(%s &client) : client_(client) {}\n", baseName_.c_str(),
163         clientName_.c_str());
164     sb.Append(prefix + TAB).Append("void OnRemoteDied(const wptr<IRemoteObject> &remote) override\n");
165     sb.Append(prefix + TAB).Append("{\n");
166     sb.Append(prefix + TAB + TAB).Append("client_.OnRemoteDied(remote);\n");
167     sb.Append(prefix + TAB).Append("}\n");
168     sb.Append(prefix).Append("private:\n");
169     sb.Append(prefix + TAB).AppendFormat("%s &client_;\n", clientName_.c_str());
170     sb.Append(prefix).Append("};\n");
171     sb.Append(prefix).Append("void RemoveDeathRecipient();\n");
172     sb.Append(prefix).Append("void OnRemoteDied(const wptr<IRemoteObject> &remote);\n\n");
173 
174     sb.Append(prefix).Append("// load callback class\n");
175     sb.Append(prefix).Append("class LoadCallback : public SystemAbilityLoadCallbackStub {\n");
176     sb.Append(prefix).Append("public:\n");
177     sb.Append(prefix + TAB).AppendFormat(
178         "LoadCallback(%sOnLocalCallback cb, %s &client): localCallback_(std::move(cb)), client_(client) {}\n",
179         baseName_.c_str(), clientName_.c_str());
180     sb.Append(prefix + TAB).Append(
181         "void OnLoadSystemAbilitySuccess(int32_t systemAbilityId, const sptr<IRemoteObject> &remote) override;\n");
182     sb.Append(prefix + TAB).Append("void OnLoadSystemAbilityFail(int32_t systemAbilityId) override;\n");
183     sb.Append(prefix).Append("private:\n");
184     sb.Append(prefix + TAB).AppendFormat("%sOnLocalCallback localCallback_;\n", baseName_.c_str());
185     sb.Append(prefix + TAB).AppendFormat("%s &client_;\n", clientName_.c_str());
186     sb.Append(prefix).Append("};\n\n");
187 
188     sb.Append(prefix).Append("// local load callback class\n");
189     sb.Append(prefix).Append("class LocalLoadCallback : public SystemAbilityLoadCallbackStub {\n");
190     sb.Append(prefix).Append("public:\n");
191     sb.Append(prefix + TAB).AppendFormat("explicit LocalLoadCallback(%s &client) : client_(client) {}\n",
192         clientName_.c_str());
193     sb.Append(prefix + TAB).Append(
194         "void OnLoadSystemAbilitySuccess(int32_t systemAbilityId, const sptr<IRemoteObject> &remote) override;\n");
195     sb.Append(prefix + TAB).Append("void OnLoadSystemAbilityFail(int32_t systemAbilityId) override;\n");
196     sb.Append(prefix).Append("private:\n");
197     sb.Append(prefix + TAB).AppendFormat("%s &client_;\n", clientName_.c_str());
198     sb.Append(prefix).Append("};\n");
199 }
200 
EmitInterfaceClientSetParam(StringBuilder & sb,const std::string & prefix) const201 void SaCppClientCodeEmitter::EmitInterfaceClientSetParam(StringBuilder &sb, const std::string &prefix) const
202 {
203     sb.Append(prefix).AppendFormat("void Set%sStatus();\n", baseName_.c_str());
204     sb.Append(prefix).AppendFormat("ErrCode Set%s(const sptr<IRemoteObject> &remote);\n", proxyName_.c_str());
205     sb.Append(prefix).Append("ErrCode PreventJitter(bool isSync, int32_t timeout = 0);\n");
206     sb.Append(prefix).Append("ErrCode LoadSystemAbility() const;\n\n");
207 
208     sb.Append(prefix).Append("sptr<IRemoteObject::DeathRecipient> deathRecipient_;\n");
209     sb.Append(prefix).AppendFormat("sptr<%s> proxy_;\n", interfaceName_.c_str());
210     sb.Append(prefix).Append("sptr<IRemoteObject> remote_;\n\n");
211 
212     sb.Append(prefix).AppendFormat("%sOnRemoteDiedCallback remoteDiedCallback_;\n", baseName_.c_str());
213     sb.Append(prefix).Append("sptr<LoadCallback> loadCallback_;\n");
214     sb.Append(prefix).Append("sptr<LocalLoadCallback> localLoadCallback_;\n\n");
215 
216     sb.Append(prefix).Append("std::shared_mutex mutexRemote_;\n");
217     sb.Append(prefix).Append("std::shared_mutex mutexLoadSA_;\n");
218     sb.Append(prefix).Append("std::shared_mutex mutexRemoteDied_;\n\n");
219 
220     sb.Append(prefix).Append("int32_t systemAbilityId_;\n");
221     sb.Append(prefix).Append("std::string deviceId_;\n");
222     sb.Append(prefix).Append("std::atomic_bool saLoading_ = false;\n");
223     sb.Append(prefix).Append("std::atomic_llong loadStart_ = 0; // microsecond timestamp\n\n");
224 
225     sb.Append(prefix).
226         Append("static constexpr int32_t LOAD_SA_TIMEOUT = 4;    // default load sa timeout is 4 seconds\n");
227     sb.Append(prefix).
228         Append("static constexpr double MICROSECOND_TO_SECOND = 1000000.0;    // microseconds to seconds\n");
229     if (logOn_) {
230         sb.Append(prefix).AppendFormat(
231             "static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, %s, \"%s\"};\n",
232             domainId_.c_str(), logTag_.c_str());
233     }
234 }
235 
EmitClientSourceFile()236 void SaCppClientCodeEmitter::EmitClientSourceFile()
237 {
238     std::string filePath =
239         File::AdapterPath(StringHelper::Format("%s/%s.cpp", directory_.c_str(), FileName(clientName_).c_str()));
240     File file(filePath, File::WRITE);
241     StringBuilder sb;
242 
243     EmitLicense(sb);
244     sb.Append('\n');
245     sb.Append("#include <chrono>\n");
246     sb.AppendFormat("#include \"%s.h\"\n", FileName(clientName_).c_str());
247     if (logOn_) {
248         sb.Append("#include \"hilog/log.h\"\n");
249     }
250     if (hitraceOn_) {
251         sb.Append("#include \"hitrace_meter.h\"\n");
252     }
253     sb.Append('\n');
254     if (logOn_) {
255         sb.Append("using OHOS::HiviewDFX::HiLog;\n\n");
256     }
257     EmitBeginNamespace(sb);
258     EmitImportUsingNamespace(sb);
259     EmitInterfaceClientMethodConstructor(sb, "");
260     EmitInterfaceClientMethodAbility(sb);
261     EmitInterfaceClientMethodDeathCallback(sb, "");
262     EmitInterfaceClientMethodImpls(sb, "");
263     sb.Append('\n');
264     EmitInterfaceClientMethodDeathRecipient(sb, "");
265     EmitInterfaceClientMethodAbilitySF(sb, "");
266     EmitInterfaceClientMethodStatusProxy(sb, "");
267     EmitInterfaceClientMethodPrevent(sb, "");
268     EmitInterfaceClientMethodAbilityLoad(sb, "");
269     EmitEndNamespace(sb);
270 
271     std::string data = sb.ToString();
272     file.WriteData(data.c_str(), data.size());
273     file.Flush();
274     file.Close();
275 }
276 
EmitInterfaceClientMethodConstructor(StringBuilder & sb,const std::string & prefix) const277 void SaCppClientCodeEmitter::EmitInterfaceClientMethodConstructor(StringBuilder &sb, const std::string &prefix) const
278 {
279     sb.Append(prefix).AppendFormat("%s::%s(int32_t systemAbilityId, const std::string &deviceId) :\n",
280         clientName_.c_str(), clientName_.c_str());
281     sb.Append(prefix + TAB).Append("systemAbilityId_(systemAbilityId), deviceId_(deviceId)\n");
282     sb.Append(prefix).Append("{\n");
283     sb.Append(prefix + TAB).AppendFormat("deathRecipient_ = new (std::nothrow) %sRecipient(*this);\n",
284         baseName_.c_str());
285     if (logOn_) {
286         sb.Append(prefix + TAB).Append("if (!deathRecipient_) {\n");
287         sb.Append(prefix + TAB + TAB).Append("HiLog::Error(LABEL, \"idl init deathRecipient_ failed\");\n");
288         sb.Append(prefix + TAB).Append("}\n");
289     }
290     sb.Append("\n");
291     sb.Append(prefix + TAB).Append("localLoadCallback_ = new (std::nothrow) LocalLoadCallback(*this);\n");
292     if (logOn_) {
293         sb.Append(prefix + TAB).Append("if (!localLoadCallback_) {\n");
294         sb.Append(prefix + TAB + TAB).Append("HiLog::Error(LABEL, \"idl init localLoadCallback_ failed\");\n");
295         sb.Append(prefix + TAB).Append("}\n");
296     }
297     sb.Append(prefix).Append("}\n\n");
298 
299     sb.Append(prefix).AppendFormat("%s::~%s()\n", clientName_.c_str(), clientName_.c_str());
300     sb.Append(prefix).Append("{\n");
301     sb.Append(prefix + TAB).Append("RemoveDeathRecipient();\n");
302     sb.Append(prefix + TAB).Append("remoteDiedCallback_ = nullptr;\n");
303     sb.Append(prefix + TAB).Append("loadCallback_ = nullptr;\n");
304     sb.Append(prefix + TAB).Append("localLoadCallback_ = nullptr;\n");
305     sb.Append(prefix + TAB).Append("deathRecipient_ = nullptr;\n");
306     sb.Append(prefix).Append("}\n\n");
307 }
308 
EmitInterfaceClientMethodAbility(StringBuilder & sb) const309 void SaCppClientCodeEmitter::EmitInterfaceClientMethodAbility(StringBuilder &sb) const
310 {
311     EmitInterfaceClientMethodAbilitySync(sb, "");
312     EmitInterfaceClientMethodAbilityAsync(sb, "");
313     EmitInterfaceClientMethodAbilityCheck(sb, "");
314 }
315 
EmitInterfaceClientMethodAbilitySync(StringBuilder & sb,const std::string & prefix) const316 void SaCppClientCodeEmitter::EmitInterfaceClientMethodAbilitySync(StringBuilder &sb, const std::string &prefix) const
317 {
318     sb.Append(prefix).Append("// Sync load sa with timeout\n");
319     sb.Append(prefix).AppendFormat("ErrCode %s::LoadSystemAbility(int32_t timeout)\n", clientName_.c_str());
320     sb.Append(prefix).Append("{\n");
321     EmitInterfaceClientSamgr(sb, prefix);
322     sb.Append(prefix + TAB).
323         Append("sptr<IRemoteObject> remote = samgr->LoadSystemAbility(systemAbilityId_, timeout);\n");
324     sb.Append(prefix + TAB).AppendFormat("ErrCode ret = Set%s(remote);\n", proxyName_.c_str());
325     sb.Append(prefix + TAB).AppendFormat("Set%sStatus();\n", baseName_.c_str());
326     sb.Append(prefix + TAB).Append("return ret;\n");
327     sb.Append(prefix).Append("}\n\n");
328 }
329 
EmitInterfaceClientMethodAbilityAsync(StringBuilder & sb,const std::string & prefix) const330 void SaCppClientCodeEmitter::EmitInterfaceClientMethodAbilityAsync(StringBuilder &sb, const std::string &prefix) const
331 {
332     sb.Append(prefix).Append("// Async load sa with a callback\n");
333     sb.Append(prefix).AppendFormat("ErrCode %s::LoadSystemAbility(const %sOnLocalCallback &cb)\n",
334         clientName_.c_str(), baseName_.c_str());
335     sb.Append(prefix).Append("{\n");
336     sb.Append(prefix + TAB).Append("{\n");
337     sb.Append(prefix + TAB + TAB).Append("std::shared_lock<std::shared_mutex> lock(mutexLoadSA_);\n");
338     sb.Append(prefix + TAB + TAB).Append("if (!loadCallback_) {\n");
339     sb.Append(prefix + TAB + TAB + TAB).Append("loadCallback_ = new LoadCallback(cb, *this);\n");
340     sb.Append(prefix + TAB + TAB).Append("}");
341     if (logOn_) {
342         sb.Append(" else {\n");
343         sb.Append(prefix + TAB + TAB + TAB).Append("HiLog::Warn(LABEL, \"idl load callback is already exist\");\n");
344         sb.Append(prefix + TAB + TAB).Append("}");
345     }
346     sb.Append("\n");
347     sb.Append(prefix + TAB).Append("}\n\n");
348     EmitInterfaceClientSamgr(sb, prefix);
349     sb.Append(prefix + TAB).Append("if (deviceId_.empty()) {\n");
350     sb.Append(prefix + TAB + TAB).Append("return samgr->LoadSystemAbility(systemAbilityId_, loadCallback_);\n");
351     sb.Append(prefix + TAB).Append("} else {\n");
352     sb.Append(prefix + TAB + TAB).
353         Append("return samgr->LoadSystemAbility(systemAbilityId_, deviceId_, loadCallback_);\n");
354     sb.Append(prefix + TAB).Append("}\n");
355     sb.Append(prefix).Append("}\n\n");
356 }
357 
EmitInterfaceClientMethodAbilityCheck(StringBuilder & sb,const std::string & prefix) const358 void SaCppClientCodeEmitter::EmitInterfaceClientMethodAbilityCheck(StringBuilder &sb, const std::string &prefix) const
359 {
360     sb.Append(prefix).Append("// Check sa\n");
361     sb.Append(prefix).AppendFormat("ErrCode %s::CheckSystemAbility()\n", clientName_.c_str());
362     sb.Append(prefix).Append("{\n");
363     EmitInterfaceClientSamgr(sb, prefix);
364     sb.Append(prefix + TAB).
365         Append("sptr<IRemoteObject> remote = samgr->CheckSystemAbility(systemAbilityId_, deviceId_);\n");
366     sb.Append(prefix + TAB).AppendFormat("ErrCode ret = Set%s(remote);\n", proxyName_.c_str());
367     sb.Append(prefix + TAB).AppendFormat("Set%sStatus();\n", baseName_.c_str());
368     sb.Append(prefix + TAB).Append("return ret;\n");
369     sb.Append(prefix).Append("}\n\n");
370 }
371 
EmitInterfaceClientMethodDeathCallback(StringBuilder & sb,const std::string & prefix) const372 void SaCppClientCodeEmitter::EmitInterfaceClientMethodDeathCallback(StringBuilder &sb, const std::string &prefix) const
373 {
374     sb.Append(prefix).Append("// Get proxy status\n");
375     sb.Append(prefix).AppendFormat("bool %s::Get%sStatus()\n", clientName_.c_str(), proxyName_.c_str());
376     sb.Append(prefix).Append("{\n");
377     sb.Append(prefix + TAB).Append("std::shared_lock<std::shared_mutex> readLock(mutexRemote_);\n");
378     sb.Append(prefix + TAB).Append("return proxy_ != nullptr;\n");
379     sb.Append(prefix).Append("}\n\n");
380 
381     sb.Append(prefix).Append("// Register remote death callback function\n");
382     sb.Append(prefix).AppendFormat("void %s::RegisterOnRemoteDiedCallback(const %sOnRemoteDiedCallback &cb)\n",
383         clientName_.c_str(), baseName_.c_str());
384     sb.Append(prefix).Append("{\n");
385     sb.Append(prefix + TAB).Append("std::unique_lock<std::shared_mutex> lock(mutexRemoteDied_);\n");
386     sb.Append(prefix + TAB).Append("remoteDiedCallback_ = cb;\n");
387     sb.Append(prefix).Append("}\n\n");
388 }
389 
EmitInterfaceClientMethodImpls(StringBuilder & sb,const std::string & prefix) const390 void SaCppClientCodeEmitter::EmitInterfaceClientMethodImpls(StringBuilder &sb, const std::string &prefix) const
391 {
392     if (interface_ == nullptr) {
393         return;
394     }
395     size_t methodNumber = interface_->GetMethodNumber();
396     for (size_t i = 0; i < methodNumber; i++) {
397         AutoPtr<ASTMethod> method = interface_->GetMethod(i);
398         if (method == nullptr) {
399             return;
400         }
401         EmitInterfaceClientMethodImpl(method, sb, prefix);
402         if (i != methodNumber - 1) {
403             sb.Append('\n');
404         }
405     }
406 }
407 
EmitInterfaceClientMethodImpl(AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const408 void SaCppClientCodeEmitter::EmitInterfaceClientMethodImpl(AutoPtr<ASTMethod> &method, StringBuilder &sb,
409     const std::string &prefix) const
410 {
411     if (method->IsMacro()) {
412         sb.AppendFormat("#%s %s\n", method->GetMacroType().c_str(), method->GetMacroVal().c_str());
413     }
414     sb.Append(prefix).AppendFormat("ErrCode %s::%s(", clientName_.c_str(), method->GetName().c_str());
415     EmitInterfaceClientMethodParams(method, sb, prefix + TAB, false);
416     sb.Append(")\n");
417     EmitInterfaceClientMethodBody(method, sb, prefix);
418     if (method->IsMacro()) {
419         sb.Append("#endif\n");
420     }
421 }
422 
EmitInterfaceClientMethodBody(AutoPtr<ASTMethod> & method,StringBuilder & sb,const std::string & prefix) const423 void SaCppClientCodeEmitter::EmitInterfaceClientMethodBody(AutoPtr<ASTMethod> &method, StringBuilder &sb,
424     const std::string &prefix) const
425 {
426     sb.Append(prefix).Append("{\n");
427     sb.Append(prefix + TAB).Append("{\n");
428     sb.Append(prefix + TAB + TAB).Append("std::shared_lock<std::shared_mutex> readLock(mutexRemote_);\n");
429     sb.Append(prefix + TAB + TAB).Append("if (proxy_) {\n");
430     sb.Append(prefix + TAB + TAB + TAB).AppendFormat("return proxy_->%s(", method->GetName().c_str());
431     EmitInterfaceClientMethodParamsWithoutType(method, sb, prefix + TAB + TAB + TAB + TAB);
432     sb.Append(");\n");
433     sb.Append(prefix + TAB + TAB).Append("}\n");
434     sb.Append(prefix + TAB).Append("}\n");
435 
436     if (method->IsOneWay()) {
437         sb.Append(prefix + TAB).Append("ErrCode ret = PreventJitter(false, LOAD_SA_TIMEOUT);\n");
438         sb.Append(prefix + TAB).Append("if (ret != ERR_OK) {\n");
439         sb.Append(prefix + TAB + TAB).Append("return ret;\n");
440         sb.Append(prefix + TAB).Append("}\n");
441         sb.Append(prefix + TAB).Append("return ERR_INVALID_VALUE;\n");
442     } else {
443         sb.Append(prefix + TAB).Append("ErrCode ret = PreventJitter(true, timeout);\n");
444         sb.Append(prefix + TAB).Append("if (ret == ERR_OK) {\n");
445         sb.Append(prefix + TAB + TAB).Append("std::shared_lock<std::shared_mutex> readLock(mutexRemote_);\n");
446         sb.Append(prefix + TAB + TAB).Append("if (proxy_) {\n");
447         sb.Append(prefix + TAB + TAB + TAB).AppendFormat("return proxy_->%s(", method->GetName().c_str());
448         EmitInterfaceClientMethodParamsWithoutType(method, sb, prefix + TAB + TAB + TAB + TAB);
449         sb.Append(");\n");
450         sb.Append(prefix + TAB + TAB).Append("}\n");
451         sb.Append(prefix + TAB).Append("}\n");
452         sb.Append(prefix + TAB).Append("return ret;\n");
453     }
454     sb.Append(prefix).AppendFormat("}\n");
455 }
456 
EmitInterfaceClientMethodDeathRecipient(StringBuilder & sb,const std::string & prefix) const457 void SaCppClientCodeEmitter::EmitInterfaceClientMethodDeathRecipient(StringBuilder &sb, const std::string &prefix) const
458 {
459     sb.Append(prefix).AppendFormat("void %s::RemoveDeathRecipient()\n", clientName_.c_str());
460     sb.Append(prefix).Append("{\n");
461     sb.Append(prefix + TAB).Append("std::unique_lock<std::shared_mutex> writeLock(mutexRemote_);\n");
462     sb.Append(prefix + TAB).Append("proxy_ = nullptr;\n");
463     sb.Append(prefix + TAB).Append("if (remote_ && deathRecipient_) {\n");
464     sb.Append(prefix + TAB + TAB).Append("remote_->RemoveDeathRecipient(deathRecipient_);\n");
465     sb.Append(prefix + TAB).Append("}\n");
466     sb.Append(prefix + TAB).Append("remote_ = nullptr;\n");
467     sb.Append(prefix).Append("}\n\n");
468 
469     sb.Append(prefix).AppendFormat("void %s::OnRemoteDied(const wptr<IRemoteObject> &remote)\n", clientName_.c_str());
470     sb.Append(prefix).Append("{\n");
471     sb.Append(prefix + TAB).Append("{\n");
472     sb.Append(prefix + TAB + TAB).Append("std::shared_lock<std::shared_mutex> readLock(mutexRemote_);\n");
473     sb.Append(prefix + TAB + TAB).Append("if (remote != remote_) {\n");
474     sb.Append(prefix + TAB + TAB + TAB).Append("return;\n");
475     sb.Append(prefix + TAB + TAB).Append("}\n");
476     sb.Append(prefix + TAB).Append("}\n");
477     sb.Append(prefix + TAB).Append("{\n");
478     sb.Append(prefix + TAB + TAB).Append("std::unique_lock<std::shared_mutex> lock(mutexRemoteDied_);\n");
479     sb.Append(prefix + TAB + TAB).Append("if (remoteDiedCallback_) {\n");
480     sb.Append(prefix + TAB + TAB + TAB).Append("remoteDiedCallback_();\n");
481     sb.Append(prefix + TAB + TAB).Append("}\n");
482     sb.Append(prefix + TAB).Append("}\n");
483     sb.Append(prefix + TAB).Append("RemoveDeathRecipient();\n");
484     sb.Append(prefix).Append("}\n\n");
485 }
486 
EmitInterfaceClientMethodAbilitySF(StringBuilder & sb,const std::string & prefix) const487 void SaCppClientCodeEmitter::EmitInterfaceClientMethodAbilitySF(StringBuilder &sb, const std::string &prefix) const
488 {
489     sb.Append(prefix).AppendFormat("void %s::LoadCallback::OnLoadSystemAbilitySuccess("
490         "int32_t systemAbilityId, const sptr<IRemoteObject> &remote)\n", clientName_.c_str());
491     sb.Append(prefix).Append("{\n");
492     sb.Append(prefix + TAB).AppendFormat("client_.Set%s(remote);\n", proxyName_.c_str());
493     sb.Append(prefix + TAB).AppendFormat("client_.Set%sStatus();\n", baseName_.c_str());
494     sb.Append(prefix + TAB).Append("if (localCallback_) {\n");
495     sb.Append(prefix + TAB + TAB).Append("localCallback_(remote != nullptr);\n");
496     sb.Append(prefix + TAB).Append("}\n");
497     sb.Append(prefix).Append("}\n\n");
498 
499     sb.Append(prefix).AppendFormat("void %s::LoadCallback::OnLoadSystemAbilityFail(int32_t systemAbilityId)\n",
500         clientName_.c_str());
501     sb.Append(prefix).Append("{\n");
502     if (logOn_) {
503         sb.Append(prefix + TAB).
504             Append("HiLog::Error(LABEL, \"idl LoadSystemAbility failed, %{public}d\", systemAbilityId);\n");
505     }
506     sb.Append(prefix + TAB).AppendFormat("client_.Set%sStatus();\n", baseName_.c_str());
507     sb.Append(prefix + TAB).Append("if (localCallback_) {\n");
508     sb.Append(prefix + TAB + TAB).Append("localCallback_(false);\n");
509     sb.Append(prefix + TAB).Append("}\n");
510     sb.Append(prefix).Append("}\n\n");
511 
512     sb.Append(prefix).AppendFormat("void %s::LocalLoadCallback::OnLoadSystemAbilitySuccess(int32_t systemAbilityId,\n",
513         clientName_.c_str());
514     sb.Append(prefix + TAB).Append("const sptr<IRemoteObject> &remote)\n");
515     sb.Append(prefix).Append("{\n");
516     sb.Append(prefix + TAB).AppendFormat("client_.Set%s(remote);\n", proxyName_.c_str());
517     sb.Append(prefix + TAB).AppendFormat("client_.Set%sStatus();\n", baseName_.c_str());
518     sb.Append(prefix).Append("}\n\n");
519 
520     sb.Append(prefix).AppendFormat("void %s::LocalLoadCallback::OnLoadSystemAbilityFail(int32_t systemAbilityId)\n",
521         clientName_.c_str());
522     sb.Append(prefix).Append("{\n");
523     if (logOn_) {
524         sb.Append(prefix + TAB).
525             Append("HiLog::Error(LABEL, \"idl local LoadSystemAbility failed, %{public}d\", systemAbilityId);\n");
526     }
527     sb.Append(prefix + TAB).AppendFormat("client_.Set%sStatus();\n", baseName_.c_str());
528     sb.Append(prefix).Append("}\n\n");
529 }
530 
EmitInterfaceClientMethodStatusProxy(StringBuilder & sb,const std::string & prefix) const531 void SaCppClientCodeEmitter::EmitInterfaceClientMethodStatusProxy(StringBuilder &sb, const std::string &prefix) const
532 {
533     sb.Append(prefix).AppendFormat("void %s::Set%sStatus()\n", clientName_.c_str(), baseName_.c_str());
534     sb.Append(prefix).Append("{\n");
535     sb.Append(prefix + TAB).Append("saLoading_ = false;\n");
536     sb.Append(prefix + TAB).Append("loadStart_ = std::chrono::duration_cast<std::chrono::microseconds>(\n");
537     sb.Append(prefix + TAB + TAB).Append("std::chrono::system_clock::now().time_since_epoch()).count();\n");
538     sb.Append(prefix).Append("}\n\n");
539 
540     sb.Append(prefix).AppendFormat("ErrCode %s::Set%s(const sptr<IRemoteObject> &remote)\n",
541         clientName_.c_str(), proxyName_.c_str());
542     sb.Append(prefix).Append("{\n");
543     sb.Append(prefix + TAB).Append("std::unique_lock<std::shared_mutex> writeLock(mutexRemote_);\n\n");
544     sb.Append(prefix + TAB).Append("// prevent re-entry\n");
545     sb.Append(prefix + TAB).Append("if (!remote) {\n");
546     if (logOn_) {
547         sb.Append(prefix + TAB + TAB)
548             .Append("HiLog::Error(LABEL, \"idl remote is nullptr, said:%{public}d\", systemAbilityId_);\n");
549     }
550     sb.Append(prefix + TAB + TAB).Append("return ERR_NULL_OBJECT;\n");
551     sb.Append(prefix + TAB).Append("}\n");
552     sb.Append(prefix + TAB).Append("if (remote_ && remote == remote_) {\n");
553     sb.Append(prefix + TAB + TAB).Append("return ERR_OK;\n");
554     sb.Append(prefix + TAB).Append("}\n");
555     sb.Append(prefix + TAB).Append("remote_ = remote;\n\n");
556     if (logOn_) {
557         sb.Append(prefix + TAB).Append("if (deathRecipient_ && !remote_->AddDeathRecipient(deathRecipient_)) {\n");
558         sb.Append(prefix + TAB + TAB).Append("HiLog::Error(LABEL, \"idl AddDeathRecipient failed\");\n");
559         sb.Append(prefix + TAB).Append("}\n\n");
560     }
561     sb.Append(prefix + TAB).AppendFormat("proxy_ = iface_cast<%s>(remote_);\n", interfaceName_.c_str());
562     sb.Append(prefix + TAB).Append("if (!proxy_) {\n");
563     if (logOn_) {
564         sb.Append(prefix + TAB + TAB).Append("HiLog::Error(LABEL, \"idl init proxy failed\");\n");
565     }
566     sb.Append(prefix + TAB + TAB).Append("return ERR_NULL_OBJECT;\n");
567     sb.Append(prefix + TAB).Append("}\n\n");
568     sb.Append(prefix + TAB).Append("return ERR_OK;\n");
569     sb.Append(prefix).Append("}\n\n");
570 }
571 
EmitInterfaceClientMethodPrevent(StringBuilder & sb,const std::string & prefix) const572 void SaCppClientCodeEmitter::EmitInterfaceClientMethodPrevent(StringBuilder &sb, const std::string &prefix) const
573 {
574     sb.Append(prefix).
575         Append("// Prevent jitter, avoid multiple calls at the same time. The unit of timeout is second.\n");
576     sb.Append(prefix).AppendFormat("ErrCode %s::PreventJitter(bool isSync, int32_t timeout)\n", clientName_.c_str());
577     sb.Append(prefix).Append("{\n");
578     sb.Append(prefix + TAB).Append("// Load once every TIMEOUT seconds, default is 4 seconds\n");
579     sb.Append(prefix + TAB).Append("double loadDiff = 0;\n");
580     sb.Append(prefix + TAB).Append("if (saLoading_) {\n");
581     sb.Append(prefix + TAB + TAB).Append("auto loadEnd = std::chrono::duration_cast<std::chrono::microseconds>(\n");
582     sb.Append(prefix + TAB + TAB + TAB).Append("std::chrono::system_clock::now().time_since_epoch()).count();\n");
583     sb.Append(prefix + TAB + TAB).
584         Append("loadDiff = static_cast<double>(loadEnd - loadStart_.load()) / MICROSECOND_TO_SECOND;\n");
585     sb.Append(prefix + TAB).Append("}\n\n");
586 
587     sb.Append(prefix + TAB).Append("if (!saLoading_ || loadDiff >= static_cast<double>(timeout)) {\n");
588     sb.Append(prefix + TAB + TAB).Append("saLoading_ = true;\n");\
589     sb.Append(prefix + TAB + TAB).Append("if (isSync) {\n");
590     sb.Append(prefix + TAB + TAB + TAB).Append("return LoadSystemAbility(timeout);\n");
591     sb.Append(prefix + TAB + TAB).Append("}\n");
592     sb.Append(prefix + TAB + TAB).Append("return LoadSystemAbility();\n");
593     sb.Append(prefix + TAB).Append("} else {\n");
594     if (logOn_) {
595         sb.Append(prefix + TAB + TAB).Append("HiLog::Error(LABEL, \"idl sa is loading or not timeout\");\n");
596     }
597     sb.Append(prefix + TAB + TAB).Append("return ERR_INVALID_VALUE;\n");
598     sb.Append(prefix + TAB).Append("}\n");
599     sb.Append(prefix).Append("}\n\n");
600 }
601 
EmitInterfaceClientMethodAbilityLoad(StringBuilder & sb,const std::string & prefix) const602 void SaCppClientCodeEmitter::EmitInterfaceClientMethodAbilityLoad(StringBuilder &sb, const std::string &prefix) const
603 {
604     sb.Append(prefix).Append("// Async callback function\n");
605     sb.Append(prefix).AppendFormat("ErrCode %s::LoadSystemAbility() const\n", clientName_.c_str());
606     sb.Append(prefix).Append("{\n");
607     sb.Append(prefix + TAB).Append("if (!localLoadCallback_) {\n");
608     if (logOn_) {
609         sb.Append(prefix + TAB + TAB).Append("HiLog::Error(LABEL, \"idl localLoadCallback_ is nullptr\");\n");
610     }
611     sb.Append(prefix + TAB + TAB).Append("return ERR_NULL_OBJECT;\n");
612     sb.Append(prefix + TAB).Append("}\n\n");
613 
614     EmitInterfaceClientSamgr(sb, prefix);
615 
616     sb.Append(prefix + TAB).Append("if (deviceId_.empty()) {\n");
617     sb.Append(prefix + TAB + TAB).Append("return samgr->LoadSystemAbility(systemAbilityId_, localLoadCallback_);\n");
618     sb.Append(prefix + TAB).Append("} else {\n");
619     sb.Append(prefix + TAB + TAB).
620         Append("return samgr->LoadSystemAbility(systemAbilityId_, deviceId_, localLoadCallback_);\n");
621     sb.Append(prefix + TAB).Append("}\n");
622     sb.Append(prefix).Append("}\n");
623 }
624 
EmitInterfaceClientSamgr(StringBuilder & sb,const std::string & prefix) const625 void SaCppClientCodeEmitter::EmitInterfaceClientSamgr(StringBuilder &sb, const std::string &prefix) const
626 {
627     sb.Append(prefix + TAB).
628         Append("auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();\n");
629     sb.Append(prefix + TAB).Append("if (!samgr) {\n");
630     if (logOn_) {
631         sb.Append(prefix + TAB + TAB).Append("HiLog::Error(LABEL, \"idl samgr is nullptr\");\n");
632     }
633     sb.Append(prefix + TAB + TAB).Append("return ERR_NULL_OBJECT;\n");
634     sb.Append(prefix + TAB).Append("}\n\n");
635 }
636 
637 } // namespace Idl
638 } // namespace OHOS