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