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 "client_executor/include/client_factory.h"
17
18 #include <thread>
19 #include <unistd.h>
20
21 #include "client_executor/include/i_client_cb.h"
22 #include "communication_adapter/include/sa_async_handler.h"
23 #include "platform/time/include/time.h"
24 #include "protocol/retcode_inner/aie_retcode_inner.h"
25 #include "utils/constants/constants.h"
26 #include "utils/log/aie_log.h"
27
28 namespace OHOS {
29 namespace AI {
30 std::mutex ClientFactory::sessionIdMutex_;
31 namespace {
32 const int MAXIMUM_NUMBER_OF_SESSION = 100;
33 const int CHECK_CONNECTION_INTERVAL = 10;
34 const int CHECK_CONNECTION_TIMES = 100;
35 }
36
ClientFactory()37 ClientFactory::ClientFactory() : clientId_(INVALID_CLIENT_ID), sessionId_(AIE_SESSION_ID_BEGIN)
38 {
39 }
40
41 ClientFactory::~ClientFactory() = default;
42
ClientInit(const ConfigInfo & configInfo,ClientInfo & clientInfo,const AlgorithmInfo & algorithmInfo,IServiceDeadCb * cb)43 int ClientFactory::ClientInit(const ConfigInfo &configInfo, ClientInfo &clientInfo,
44 const AlgorithmInfo &algorithmInfo, IServiceDeadCb *cb)
45 {
46 HILOGI("[ClientFactory]Begin to call ClientInit.");
47 if (clientInfo.sessionId != INVALID_SESSION_ID) {
48 HILOGW("[ClientFactory]Session id is valid, does not need to do Init.");
49 // Valid sessionId tells it has been already INIT successfully before
50 return RETCODE_SUCCESS;
51 }
52
53 clientInfo.sessionId = GenerateSessionId();
54 bool isFirstSession = AddSessionInfo(clientInfo, algorithmInfo);
55 int retCode = RETCODE_SUCCESS;
56 if (isFirstSession) {
57 retCode = InitAiServer(configInfo, clientInfo, algorithmInfo);
58 if (retCode != RETCODE_SUCCESS) {
59 HILOGE("[ClientFactory][clientId:%d,sessionId:%d]Fail to connect and init server, retCode[%d].",
60 clientId_, clientInfo.sessionId, retCode);
61 return retCode;
62 }
63 }
64 retCode = WaitConnection();
65 CHK_RET(retCode != RETCODE_SUCCESS, retCode);
66 clientInfo.clientId = clientId_;
67 clientInfo.serverUid = serverUid_;
68 clientInfo.clientUid = getuid();
69
70 return RegisterDeadCb(clientInfo.sessionId, cb);
71 }
72
ClientPrepare(const ClientInfo & clientInfo,const AlgorithmInfo & algorithmInfo,const DataInfo & inputInfo,DataInfo & outputInfo,IClientCb * cb)73 int ClientFactory::ClientPrepare(const ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo,
74 const DataInfo &inputInfo, DataInfo &outputInfo, IClientCb *cb)
75 {
76 HILOGI("[ClientFactory]Begin to call ClientPrepare.");
77 if (clientInfo.sessionId == INVALID_SESSION_ID) {
78 HILOGI("[ClientFactory][clientId:%d, sessionId:%d]SessionId is invalid,"\
79 "please call aie clientInit firstly.",
80 clientId_, clientInfo.sessionId);
81 return RETCODE_SERVER_NOT_INIT;
82 }
83 int retCode = RETCODE_SUCCESS;
84 if (algorithmInfo.isAsync) {
85 if (cb == nullptr) {
86 HILOGE("[ClientFactory][clientId:%d,sessionId:%d]It is Async Algorithm, but the input callback is null.",
87 clientId_, clientInfo.sessionId);
88 return RETCODE_NULL_PARAM;
89 }
90 retCode = RegisterCb(clientInfo.sessionId, cb);
91 if (retCode != RETCODE_SUCCESS) {
92 HILOGE("[ClientFactory][clientId:%d,sessionId:%d]Failed to register callback, result code[%d].",
93 clientId_, clientInfo.sessionId, retCode);
94 return retCode;
95 }
96 }
97
98 retCode = LoadAlgorithm(clientInfo, algorithmInfo, inputInfo, outputInfo);
99 HILOGD("[ClientFactory][clientId:%d,sessionId:%d]End to call load algorithm, result code[%d]",
100 clientId_, clientInfo.sessionId, retCode);
101 if (retCode != RETCODE_SUCCESS) {
102 (void)UnRegisterCb(clientInfo.sessionId); // revert what's already inited, ignore return value.
103 }
104 return retCode;
105 }
106
ClientAsyncProcess(const ClientInfo & clientInfo,const AlgorithmInfo & algorithmInfo,const DataInfo & inputInfo)107 int ClientFactory::ClientAsyncProcess(const ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo,
108 const DataInfo &inputInfo)
109 {
110 HILOGI("[ClientFactory]Begin to call ClientAsyncProcess.");
111 if (clientInfo.sessionId == INVALID_SESSION_ID) {
112 HILOGE("[ClientFactory][clientId:%d, sessionId:%d] sessionId is invalid, please call Init firstly.",
113 clientId_, clientInfo.sessionId);
114 return RETCODE_SERVER_NOT_INIT;
115 }
116 if (!algorithmInfo.isAsync) {
117 HILOGE("[ClientFactory]algorithm is synchronous, but async process is called.");
118 return RETCODE_INVALID_PARAM;
119 }
120
121 int retCode = AsyncExecute(clientInfo, algorithmInfo, inputInfo);
122 HILOGD("[ClientFactory][clientId:%d,sessionId:%d]End to call AsyncExecute, result code[%d]",
123 clientId_, clientInfo.sessionId, retCode);
124 return retCode;
125 }
126
ClientDestroy(ClientInfo & clientInfo)127 int ClientFactory::ClientDestroy(ClientInfo &clientInfo)
128 {
129 HILOGI("[ClientFactory]Begin to call ClientDestroy.");
130 if (clientInfo.sessionId == INVALID_SESSION_ID) {
131 HILOGW("[ClientFactory][clientId:%d, sessionId:%d] sessionId is invalid value, not need destroy.",
132 clientId_, clientInfo.sessionId);
133 // invalid session id tells it has been already destroyed before, it is still successfully destroy
134 return RETCODE_FAILURE;
135 }
136 int retCode = EraseSessionInfo(clientInfo.sessionId);
137 if (retCode != RETCODE_SUCCESS) {
138 return retCode;
139 }
140 bool isLastSession = sessionInfos_.empty();
141 if (isLastSession) {
142 retCode = CloseAiServer();
143 if (retCode != RETCODE_SUCCESS) {
144 HILOGE("[ClientFactory][clientId:%d, sessionId:%d]Fail to dis-connect and unInit server, result code[%d].",
145 clientId_, clientInfo.sessionId, retCode);
146 return retCode;
147 }
148 if (clientId_ != INVALID_CLIENT_ID) {
149 HILOGE("[ClientFactory][clientId:%d, sessionId:%d]Fail to reset client id.",
150 clientId_, clientInfo.sessionId);
151 return RETCODE_FAILURE;
152 }
153 }
154 retCode = UnRegisterDeadCb(clientInfo.sessionId);
155 clientInfo.sessionId = INVALID_SESSION_ID;
156 clientInfo.clientId = INVALID_CLIENT_ID;
157 HILOGD("[ClientFactory][clientId:%d, sessionId:%d]End to call ClientDestroy, result code[%d].",
158 clientId_, clientInfo.sessionId, retCode);
159 return retCode;
160 }
161
ClientSetOption(const ClientInfo & clientInfo,int optionType,const DataInfo & inputInfo)162 int ClientFactory::ClientSetOption(const ClientInfo &clientInfo, int optionType, const DataInfo &inputInfo)
163 {
164 HILOGI("[ClientFactory]Begin to call ClientSetOption.");
165 return SetOption(clientInfo, optionType, inputInfo);
166 }
167
ClientGetOption(const ClientInfo & clientInfo,int optionType,const DataInfo & inputInfo,DataInfo & outputInfo)168 int ClientFactory::ClientGetOption(const ClientInfo &clientInfo, int optionType,
169 const DataInfo &inputInfo, DataInfo &outputInfo)
170 {
171 HILOGI("[ClientFactory]Begin to call ClientGetOption.");
172 return GetOption(clientInfo, optionType, inputInfo, outputInfo);
173 }
174
ClientSyncProcess(const ClientInfo & clientInfo,const AlgorithmInfo & algorithmInfo,const DataInfo & inputInfo,DataInfo & outputInfo)175 int ClientFactory::ClientSyncProcess(const ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo,
176 const DataInfo &inputInfo, DataInfo &outputInfo)
177 {
178 HILOGI("[ClientFactory]Begin to call ClientSyncProcess.");
179 if (clientInfo.sessionId == INVALID_SESSION_ID) {
180 HILOGE("[ClientFactory]SessionId is invalid, please call Init firstly.");
181 return RETCODE_SERVER_NOT_INIT;
182 }
183 if (algorithmInfo.isAsync) {
184 HILOGE("[ClientFactory]algorithm is asynchronous, but sync process is called.");
185 return RETCODE_INVALID_PARAM;
186 }
187 return SyncExecute(clientInfo, algorithmInfo, inputInfo, outputInfo);
188 }
189
ClientRelease(const ClientInfo & clientInfo,const AlgorithmInfo & algorithmInfo,const DataInfo & inputInfo)190 int ClientFactory::ClientRelease(const ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo,
191 const DataInfo &inputInfo)
192 {
193 HILOGI("[ClientFactory]Begin to call ClientRelease.");
194 if (clientInfo.sessionId == INVALID_SESSION_ID) {
195 HILOGI("[ClientFactory][clientId:%d, sessionId:%d] sessionId is invalid value, not need release.",
196 clientId_, clientInfo.sessionId);
197 return RETCODE_SUCCESS;
198 }
199
200 if (algorithmInfo.isAsync) {
201 int unRegisterCbRetCode = UnRegisterCb(clientInfo.sessionId);
202 if (unRegisterCbRetCode != RETCODE_SUCCESS) {
203 HILOGE("[ClientFactory][clientId:%d,sessionId:%d]Fail to unRegister callback, error code[%d]",
204 clientId_, clientInfo.sessionId, unRegisterCbRetCode);
205 return unRegisterCbRetCode;
206 }
207 }
208 int retCode = UnLoadAlgorithm(clientInfo, algorithmInfo, inputInfo);
209 HILOGD("[ClientFactory][clientId:%d,sessionId:%d]End to call unLoad algorithm, result code[%d]", clientId_,
210 clientInfo.sessionId, retCode);
211 return retCode;
212 }
213
SetClientId(int clientId)214 void ClientFactory::SetClientId(int clientId)
215 {
216 clientId_ = clientId;
217 }
218
GetClientId() const219 int ClientFactory::GetClientId() const
220 {
221 return clientId_;
222 }
223
SetServerUid(const uid_t clientId)224 void ClientFactory::SetServerUid(const uid_t clientId)
225 {
226 serverUid_ = clientId;
227 }
228
GetServerUid() const229 uid_t ClientFactory::GetServerUid() const
230 {
231 return serverUid_;
232 }
233
GenerateSessionId()234 int ClientFactory::GenerateSessionId()
235 {
236 std::lock_guard<std::mutex> lock(sessionIdMutex_);
237 if (sessionInfos_.size() > MAXIMUM_NUMBER_OF_SESSION) {
238 HILOGE("[ClientFactory]Session id exceed maximum numbers.");
239 return INVALID_SESSION_ID;
240 }
241 do {
242 ++sessionId_;
243 if (sessionId_ < AIE_SESSION_ID_BEGIN) {
244 // session id may come to the maximum value and turn to negative value
245 HILOGI("[ClientFactory]SessionId reaches max int value, now reset it to init value(%d).",
246 AIE_SESSION_ID_BEGIN);
247 sessionId_ = AIE_SESSION_ID_BEGIN;
248 }
249 } while (sessionInfos_.find(sessionId_) != sessionInfos_.end());
250 return sessionId_;
251 }
252
AddSessionInfo(const ClientInfo & clientInfo,const AlgorithmInfo & algorithmInfo)253 bool ClientFactory::AddSessionInfo(const ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo)
254 {
255 std::lock_guard<std::mutex> lock(sessionIdMutex_);
256 bool isFirstSession = sessionInfos_.empty();
257 sessionInfos_.insert(std::make_pair(clientInfo.sessionId, algorithmInfo.algorithmType));
258 return isFirstSession;
259 }
260
EraseSessionInfo(int sessionId)261 int ClientFactory::EraseSessionInfo(int sessionId)
262 {
263 std::lock_guard<std::mutex> lock(sessionIdMutex_);
264 if (!sessionInfos_.erase(sessionId)) {
265 HILOGW("[ClientFactory][sessionId:%d]session id does not exist.", sessionId);
266 return RETCODE_FAILURE;
267 }
268 return RETCODE_SUCCESS;
269 }
270
GetSessionInfo(int sessionId,int & algorithmType)271 int ClientFactory::GetSessionInfo(int sessionId, int &algorithmType)
272 {
273 std::lock_guard<std::mutex> lock(sessionIdMutex_);
274 SessionInfos::iterator iter = sessionInfos_.find(sessionId);
275 CHK_RET(iter == sessionInfos_.end(), RETCODE_EMPTY_MAP);
276 algorithmType = iter->second;
277 return RETCODE_SUCCESS;
278 }
279
RegisterCb(int sessionId,IClientCb * cb)280 int ClientFactory::RegisterCb(int sessionId, IClientCb *cb)
281 {
282 HILOGI("[ClientFactory]Begin to call RegisterCb.");
283 SaAsyncHandler *saAsyncHandler = SaAsyncHandler::GetInstance();
284 CHK_RET(saAsyncHandler == nullptr, RETCODE_NULL_PARAM);
285 int retCode = saAsyncHandler->RegisterCb(sessionId, cb);
286 CHK_RET(retCode != RETCODE_SUCCESS, retCode);
287 retCode = saAsyncHandler->RegisterAsyncClientCb();
288 if (retCode != RETCODE_SUCCESS) {
289 HILOGE("[ClientFactory]Fail to register callback, retCode[%d].", retCode);
290 (void)saAsyncHandler->UnRegisterCb(sessionId); // revert what's already inited, ignore return value.
291 return RETCODE_FAILURE;
292 }
293 return RETCODE_SUCCESS;
294 }
295
UnRegisterCb(const int sessionId)296 int ClientFactory::UnRegisterCb(const int sessionId)
297 {
298 HILOGI("[ClientFactory]Begin to call UnRegisterCb.");
299 SaAsyncHandler *saAsyncHandler = SaAsyncHandler::GetInstance();
300 CHK_RET(saAsyncHandler == nullptr, RETCODE_NULL_PARAM);
301 int serviceCallbackRetCode = saAsyncHandler->UnRegisterAsyncClientCb();
302 int sdkCallbackRetcode = saAsyncHandler->UnRegisterCb(sessionId);
303 if (serviceCallbackRetCode != RETCODE_SUCCESS || sdkCallbackRetcode != RETCODE_SUCCESS) {
304 return RETCODE_FAILURE;
305 }
306 return RETCODE_SUCCESS;
307 }
308
RegisterDeadCb(int sessionId,IServiceDeadCb * cb)309 int ClientFactory::RegisterDeadCb(int sessionId, IServiceDeadCb *cb)
310 {
311 HILOGI("[ClientFactory]Begin to call RegisterDeadCb.");
312 SaAsyncHandler *saAsyncHandler = SaAsyncHandler::GetInstance();
313 CHK_RET(saAsyncHandler == nullptr, RETCODE_NULL_PARAM);
314 int retCode = saAsyncHandler->RegisterDeadCb(sessionId, cb);
315 CHK_RET(retCode != RETCODE_SUCCESS, retCode);
316 retCode = saAsyncHandler->RegisterServiceDeathCb();
317 if (retCode != RETCODE_SUCCESS) {
318 HILOGE("[ClientFactory]Fail to register death callback, retCode[%d].", retCode);
319 (void)saAsyncHandler->UnRegisterCb(sessionId); // revert what's already inited, ignore return value.
320 return RETCODE_FAILURE;
321 }
322 return RETCODE_SUCCESS;
323 }
324
UnRegisterDeadCb(const int sessionId)325 int ClientFactory::UnRegisterDeadCb(const int sessionId)
326 {
327 HILOGI("[ClientFactory]Begin to call UnRegisterDeadCb.");
328 SaAsyncHandler *saAsyncHandler = SaAsyncHandler::GetInstance();
329 CHK_RET(saAsyncHandler == nullptr, RETCODE_NULL_PARAM);
330 int serviceCallbackRetCode = saAsyncHandler->UnRegisterServiceDeathCb();
331 int sdkCallbackRetcode = saAsyncHandler->UnRegisterDeadCb(sessionId);
332 if (serviceCallbackRetCode != RETCODE_SUCCESS || sdkCallbackRetcode != RETCODE_SUCCESS) {
333 return RETCODE_FAILURE;
334 }
335 return RETCODE_SUCCESS;
336 }
337
WaitConnection()338 int ClientFactory::WaitConnection()
339 {
340 // wait for CHECK_CONNECTION_TIMES*CHECK_CONNECTION_INTERVAL ms
341 for (int i = 0; i < CHECK_CONNECTION_TIMES; ++i) {
342 if (clientId_ != INVALID_CLIENT_ID) {
343 HILOGI("[ClientFactory][clientId:%d]status is connected.", clientId_);
344 return RETCODE_SUCCESS;
345 }
346 StepSleepMs(CHECK_CONNECTION_INTERVAL);
347 }
348
349 HILOGE("[ClientFactory][clientId:%d]The connection has not been created.", clientId_);
350 return RETCODE_SA_SERVICE_EXCEPTION;
351 }
352
ResetClient()353 void ClientFactory::ResetClient()
354 {
355 clientId_ = INVALID_CLIENT_ID;
356 sessionId_ = INVALID_SESSION_ID;
357 serverUid_ = INVALID_UID;
358 clientId_ = INVALID_UID;
359 }
360 } // namespace AI
361 } // namespace OHOS
362