1 /*
2  * Copyright (c) 2021 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 "communication_adapter/include/sa_client.h"
17 
18 #include "ipc_skeleton.h"
19 
20 #include "communication_adapter/include/sa_client_proxy.h"
21 #include "platform/os_wrapper/ipc/include/aie_ipc.h"
22 #include "protocol/ipc_interface/ai_service.h"
23 #include "protocol/retcode_inner/aie_retcode_inner.h"
24 #include "utils/aie_macros.h"
25 #include "utils/constants/constants.h"
26 #include "utils/log/aie_log.h"
27 
28 namespace OHOS {
29 namespace AI {
30 namespace {
AsyncCallback(uint32_t code,IpcIo * data,IpcIo * reply,MessageOption option)31 int32_t AsyncCallback(uint32_t code, IpcIo *data, IpcIo *reply, MessageOption option)
32 {
33     int asyncCallbackRet;
34     ReadInt32(data, &asyncCallbackRet);
35     int requestId;
36     ReadInt32(data, &requestId);
37     int sessionId;
38     ReadInt32(data, &sessionId);
39     DataInfo outputInfo = {
40         .data = nullptr,
41         .length = 0,
42     };
43     int ipcUnParcelRet = UnParcelDataInfo(data, &outputInfo);
44     SaClient *client = SaClient::GetInstance();
45     if (client == nullptr) {
46         HILOGE("[SaClient]The client is nullptr, maybe out of memory.");
47         FreeDataInfo(&outputInfo);
48         return RETCODE_FAILURE;
49     }
50     CallbackHandle callback = client->GetSaClientResultCb();
51     if (callback == nullptr) {
52         HILOGE("[SaClient]SA client callback is nullptr, maybe Release interface is called or the callback is deleted");
53         FreeDataInfo(&outputInfo);
54         return RETCODE_FAILURE;
55     }
56     // The asynchronous callback retCode is used only when the IPC is normal.
57     int retCode = asyncCallbackRet;
58     if (ipcUnParcelRet != RETCODE_SUCCESS) {
59         HILOGE("[SaClient]AsyncCallback failed, UnParcelDataInfo retCode[%d].", ipcUnParcelRet);
60         // The IPC is abnormal.
61         retCode = RETCODE_FAILURE;
62     }
63     callback(sessionId, outputInfo, retCode, requestId);
64     FreeDataInfo(&outputInfo);
65     return retCode;
66 }
67 
OnAiDead(void * arg)68 void OnAiDead(void *arg)
69 {
70     SaClient *client = SaClient::GetInstance();
71     if (client == nullptr) {
72         HILOGE("[SaClient]callback is null.");
73         return;
74     }
75     DeathCallbackHandle onDead = client->GetSaDeathResultCb();
76     if (onDead == nullptr) {
77         HILOGE("[SaClient]Dead callback is null.");
78         return;
79     }
80     int clientId = *(reinterpret_cast<int *>(arg));
81     HILOGW("[SaClient]OnAiDead for [clientId:%d].", clientId);
82     onDead();
83 }
84 } // anonymous namespaces
85 
86 std::mutex SaClient::instance_mutex_;
87 SaClient *SaClient::instance_ = nullptr;
88 
89 SaClient::SaClient() = default;
90 
91 SaClient::~SaClient() = default;
92 
GetInstance()93 SaClient *SaClient::GetInstance()
94 {
95     CHK_RET(instance_ != nullptr, instance_);
96 
97     std::lock_guard<std::mutex> lock(instance_mutex_);
98     CHK_RET(instance_ != nullptr, instance_);
99 
100     SaClient *tempInstance = nullptr;
101     AIE_NEW(tempInstance, SaClient);
102     CHK_RET(tempInstance == nullptr, nullptr);
103 
104     instance_ = tempInstance;
105     return instance_;
106 }
107 
ReleaseInstance()108 void SaClient::ReleaseInstance()
109 {
110     std::lock_guard<std::mutex> lock(instance_mutex_);
111     AIE_DELETE(instance_);
112 }
113 
Init(const ConfigInfo & configInfo,ClientInfo & clientInfo)114 int SaClient::Init(const ConfigInfo &configInfo, ClientInfo &clientInfo)
115 {
116     HosInit();
117     proxy_ = GetRemoteIUnknown();
118     if (proxy_ == nullptr) {
119         HILOGE("[SaClient]Fail to get server proxy, server exception.");
120         return RETCODE_SA_SERVICE_EXCEPTION;
121     }
122 
123     int retCode = InitSaEngine(*proxy_, configInfo, clientInfo);
124     if (retCode != RETCODE_SUCCESS || clientInfo.clientId == INVALID_CLIENT_ID) {
125         HILOGE("[SaClient]InitServer result failed, clientId: %d, errorCode: [%d]", clientInfo.clientId, retCode);
126         ReleaseIUnknown(*((IUnknown *)proxy_));
127         proxy_ = nullptr;
128         return RETCODE_FAILURE;
129     }
130 
131     // Register SA Death Callback
132     svc_ = SAMGR_GetRemoteIdentity(AI_SERVICE, nullptr);
133     int32_t resultCode = AddDeathRecipient(svc_, OnAiDead, &clientInfo.clientId, &deadId_);
134     if (resultCode != 0) {
135         HILOGE("[SaClient]Register SA Death Callback failed, errorCode[%d]", resultCode);
136         return RETCODE_FAILURE;
137     }
138     return RETCODE_SUCCESS;
139 }
140 
LoadAlgorithm(const ClientInfo & clientInfo,const AlgorithmInfo & algorithmInfo,const DataInfo & inputInfo,DataInfo & outputInfo)141 int SaClient::LoadAlgorithm(const ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo,
142     const DataInfo &inputInfo, DataInfo &outputInfo)
143 {
144     if (proxy_ == nullptr) {
145         HILOGE("[SaClient]Service is nullptr, need reconnect server");
146         return RETCODE_SA_SERVICE_EXCEPTION;
147     }
148     return LoadAlgorithmProxy(*proxy_, clientInfo, algorithmInfo, inputInfo, outputInfo);
149 }
150 
SyncExecuteAlgorithm(const ClientInfo & clientInfo,const AlgorithmInfo & algorithmInfo,const DataInfo & inputInfo,DataInfo & outputInfo)151 int SaClient::SyncExecuteAlgorithm(const ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo,
152     const DataInfo &inputInfo, DataInfo &outputInfo)
153 {
154     if (proxy_ == nullptr) {
155         HILOGE("[SaClient]Service is nullptr, need reconnect server.");
156         return RETCODE_SA_SERVICE_EXCEPTION;
157     }
158     return SyncExecAlgorithmProxy(*proxy_, clientInfo, algorithmInfo, inputInfo, outputInfo);
159 }
160 
AsyncExecuteAlgorithm(const ClientInfo & clientInfo,const AlgorithmInfo & algorithmInfo,const DataInfo & inputInfo)161 int SaClient::AsyncExecuteAlgorithm(const ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo,
162     const DataInfo &inputInfo)
163 {
164     if (proxy_ == nullptr) {
165         HILOGE("[SaClient]Fail to get server proxy, retry to prepare.");
166         return RETCODE_SA_SERVICE_EXCEPTION;
167     }
168 
169     return AsyncExecuteAlgorithmProxy(*proxy_, clientInfo, algorithmInfo, inputInfo);
170 }
171 
UnloadAlgorithm(const ClientInfo & clientInfo,const AlgorithmInfo & algorithmInfo,const DataInfo & inputInfo)172 int SaClient::UnloadAlgorithm(const ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo,
173     const DataInfo &inputInfo)
174 {
175     if (proxy_ == nullptr) {
176         HILOGE("[SaClient]Service is nullptr, need reconnect server.");
177         return RETCODE_SA_SERVICE_EXCEPTION;
178     }
179 
180     return UnloadAlgorithmProxy(*proxy_, clientInfo, algorithmInfo, inputInfo);
181 }
182 
Destroy(const ClientInfo & clientInfo)183 int SaClient::Destroy(const ClientInfo &clientInfo)
184 {
185     if (proxy_ == nullptr) {
186         HILOGE("[SaClient]The proxy_ is nullptr. No need to destroy.");
187         return RETCODE_SA_SERVICE_EXCEPTION;
188     }
189 
190     int retCode = DestroyEngineProxy(*proxy_, clientInfo);
191     (void)RemoveDeathRecipient(svc_, deadId_);
192     ReleaseIUnknown(*((IUnknown *)proxy_));
193     proxy_ = nullptr;
194     return retCode;
195 }
196 
SetOption(const ClientInfo & clientInfo,int optionType,const DataInfo & inputInfo)197 int SaClient::SetOption(const ClientInfo &clientInfo, int optionType, const DataInfo &inputInfo)
198 {
199     if (proxy_ == nullptr) {
200         HILOGE("[SaClient]Service is nullptr. need reconnect server.");
201         return RETCODE_SA_SERVICE_EXCEPTION;
202     }
203     return SetOptionProxy(*proxy_, clientInfo, optionType, inputInfo);
204 }
205 
GetOption(const ClientInfo & clientInfo,int optionType,const DataInfo & inputInfo,DataInfo & outputInfo)206 int SaClient::GetOption(const ClientInfo &clientInfo, int optionType, const DataInfo &inputInfo,
207     DataInfo &outputInfo)
208 {
209     if (proxy_ == nullptr) {
210         HILOGE("[SaClient]Service is nullptr. need reconnect server.");
211         return RETCODE_SA_SERVICE_EXCEPTION;
212     }
213     return GetOptionProxy(*proxy_, clientInfo, optionType, inputInfo, outputInfo);
214 }
215 
RegisterCallback(const ClientInfo & clientInfo)216 int SaClient::RegisterCallback(const ClientInfo &clientInfo)
217 {
218     if (proxy_ == nullptr) {
219         HILOGE("[SaClient]The proxy_ is nullptr.");
220         return RETCODE_SA_SERVICE_EXCEPTION;
221     }
222 
223     return RegisterCallbackProxy(*proxy_, clientInfo, AsyncCallback);
224 }
225 
UnregisterCallback(const ClientInfo & clientInfo)226 int SaClient::UnregisterCallback(const ClientInfo &clientInfo)
227 {
228     if (proxy_ == nullptr) {
229         HILOGE("[SaClient]Service is nullptr, need reconnect server.");
230         return RETCODE_SA_SERVICE_EXCEPTION;
231     }
232 
233     return UnregisterCallbackProxy(*proxy_, clientInfo);
234 }
235 
RegisterSaClientCb(CallbackHandle resultCb)236 void SaClient::RegisterSaClientCb(CallbackHandle resultCb)
237 {
238     ResultCb_ = resultCb;
239 }
240 
UnRegisterSaClientCb()241 void SaClient::UnRegisterSaClientCb()
242 {
243     ResultCb_ = nullptr;
244 }
245 
GetSaClientResultCb()246 CallbackHandle SaClient::GetSaClientResultCb()
247 {
248     return ResultCb_;
249 }
250 
RegisterSaDeathCb(DeathCallbackHandle deathCb)251 void SaClient::RegisterSaDeathCb(DeathCallbackHandle deathCb)
252 {
253     deathCb_ = deathCb;
254 }
255 
UnRegisterSaDeathCb()256 void SaClient::UnRegisterSaDeathCb()
257 {
258     deathCb_ = nullptr;
259 }
260 
GetSaDeathResultCb()261 DeathCallbackHandle SaClient::GetSaDeathResultCb()
262 {
263     return deathCb_;
264 }
265 } // namespace AI
266 } // namespace OHOS
267