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