1 /*
2 * Copyright (C) 2024 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 "account_task_manager.h"
17
18 #include <pthread.h>
19 #include <unistd.h>
20 #include "device_auth_defines.h"
21 #include "hc_log.h"
22 #include "hc_mutex.h"
23 #include "hc_vector.h"
24 #include "plugin_adapter.h"
25 #include "account_auth_plugin_proxy.h"
26
27 #define UNLOAD_DELAY_TIME 3
28
29 typedef struct {
30 int32_t taskId;
31 } AccountTaskRecord;
32
33 DECLARE_HC_VECTOR(AccountTaskRecordList, AccountTaskRecord)
34 IMPLEMENT_HC_VECTOR(AccountTaskRecordList, AccountTaskRecord, 1)
35
36 static AccountTaskRecordList g_taskList;
37 static bool g_isPluginLoaded = false;
38 static bool g_isAsyncTaskRunning = false;
39 static bool g_hasAccountAuthPlugin = false;
40 static HcMutex g_taskMutex = { 0 };
41 static bool g_isInit = false;
42 static bool g_isUnloadState = false;
43
LoadAccountAuthPlugin(void)44 static void LoadAccountAuthPlugin(void)
45 {
46 (void)LockHcMutex(&g_taskMutex);
47 g_isUnloadState = false;
48 if (g_isPluginLoaded) {
49 UnlockHcMutex(&g_taskMutex);
50 LOGI("[ACCOUNT_TASK_MGR]: plugin is loaded.");
51 return;
52 }
53 DEV_AUTH_LOAD_PLUGIN();
54 g_isPluginLoaded = true;
55 UnlockHcMutex(&g_taskMutex);
56 LOGI("[ACCOUNT_TASK_MGR]: load plugin successfully.");
57 }
58
IsPluginUnloadNeeded(void)59 static bool IsPluginUnloadNeeded(void)
60 {
61 (void)LockHcMutex(&g_taskMutex);
62 if (!g_isPluginLoaded) {
63 UnlockHcMutex(&g_taskMutex);
64 LOGI("[ACCOUNT_TASK_MGR]: plugin is unloaded.");
65 return false;
66 }
67 if (g_isAsyncTaskRunning) {
68 UnlockHcMutex(&g_taskMutex);
69 LOGI("[ACCOUNT_TASK_MGR]: async task is running, can't unload plugin.");
70 return false;
71 }
72 if (g_taskList.size(&g_taskList) > 0) {
73 UnlockHcMutex(&g_taskMutex);
74 LOGI("[ACCOUNT_TASK_MGR]: task exist.");
75 return false;
76 }
77 UnlockHcMutex(&g_taskMutex);
78 return true;
79 }
80
ExecuteUnload(void * arg)81 void *ExecuteUnload(void *arg)
82 {
83 LOGI("[ACCOUNT_TASK_MGR]: unload task execute.");
84 sleep(UNLOAD_DELAY_TIME);
85 LockHcMutex(&g_taskMutex);
86 if (IsPluginUnloadNeeded() && g_isUnloadState) {
87 DEV_AUTH_UNLOAD_PLUGIN();
88 g_isPluginLoaded = false;
89 g_isUnloadState = false;
90 LOGI("[ACCOUNT_TASK_MGR]: unload plugin successfully.");
91 } else {
92 LOGI("[ACCOUNT_TASK_MGR]: no need to unload.");
93 }
94 UnlockHcMutex(&g_taskMutex);
95 return NULL;
96 }
97
UnloadAccountAuthPlugin(void)98 static void UnloadAccountAuthPlugin(void)
99 {
100 LockHcMutex(&g_taskMutex);
101 if (!IsPluginUnloadNeeded() || g_isUnloadState) {
102 UnlockHcMutex(&g_taskMutex);
103 return;
104 }
105 g_isUnloadState = true;
106 pthread_t tid;
107 pthread_create(&tid, NULL, ExecuteUnload, NULL);
108 pthread_detach(tid);
109 UnlockHcMutex(&g_taskMutex);
110 }
111
AddAccountTaskRecord(int32_t taskId)112 static int32_t AddAccountTaskRecord(int32_t taskId)
113 {
114 LockHcMutex(&g_taskMutex);
115 AccountTaskRecord taskRecord;
116 taskRecord.taskId = taskId;
117 if (g_taskList.pushBackT(&g_taskList, taskRecord) == NULL) {
118 UnlockHcMutex(&g_taskMutex);
119 LOGE("[ACCOUNT_TASK_MGR]: push task record failed, taskId: %" LOG_PUB "d", taskId);
120 return HC_ERR_MEMORY_COPY;
121 }
122 UnlockHcMutex(&g_taskMutex);
123 LOGI("[ACCOUNT_TASK_MGR]: add task record succeeded, taskId: %" LOG_PUB "d", taskId);
124 return HC_SUCCESS;
125 }
126
RemoveAccountTaskRecord(int32_t taskId)127 static void RemoveAccountTaskRecord(int32_t taskId)
128 {
129 LockHcMutex(&g_taskMutex);
130 uint32_t index;
131 AccountTaskRecord *ptr;
132 FOR_EACH_HC_VECTOR(g_taskList, index, ptr) {
133 if (ptr->taskId == taskId) {
134 HC_VECTOR_POPELEMENT(&g_taskList, ptr, index);
135 UnlockHcMutex(&g_taskMutex);
136 LOGI("[ACCOUNT_TASK_MGR]: remove task record succeeded, taskId: %" LOG_PUB "d", taskId);
137 return;
138 }
139 }
140 UnlockHcMutex(&g_taskMutex);
141 LOGI("[ACCOUNT_TASK_MGR]: task record not exist, taskId: %" LOG_PUB "d", taskId);
142 }
143
InitAccountTaskManager(void)144 int32_t InitAccountTaskManager(void)
145 {
146 if (g_isInit) {
147 LOGI("[ACCOUNT_TASK_MGR]: has been initialized.");
148 return HC_SUCCESS;
149 }
150 int32_t res = InitHcMutex(&g_taskMutex, true);
151 if (res != HC_SUCCESS) {
152 LOGE("[ACCOUNT_TASK_MGR]: init account task mutex failed.");
153 return res;
154 }
155 DEV_AUTH_LOAD_PLUGIN();
156 g_hasAccountAuthPlugin = HasAccountAuthPlugin();
157 DEV_AUTH_UNLOAD_PLUGIN();
158 g_taskList = CREATE_HC_VECTOR(AccountTaskRecordList);
159 g_isInit = true;
160 return HC_SUCCESS;
161 }
162
DestroyAccountTaskManager(void)163 void DestroyAccountTaskManager(void)
164 {
165 if (!g_isInit) {
166 LOGI("[ACCOUNT_TASK_MGR]: has not been initialized.");
167 return;
168 }
169 g_isInit = false;
170 (void)LockHcMutex(&g_taskMutex);
171 DESTROY_HC_VECTOR(AccountTaskRecordList, &g_taskList);
172 UnlockHcMutex(&g_taskMutex);
173 DestroyHcMutex(&g_taskMutex);
174 }
175
HasAccountPlugin(void)176 bool HasAccountPlugin(void)
177 {
178 return g_hasAccountAuthPlugin;
179 }
180
ExecuteAccountAuthCmd(int32_t osAccountId,int32_t cmdId,const CJson * in,CJson * out)181 int32_t ExecuteAccountAuthCmd(int32_t osAccountId, int32_t cmdId, const CJson *in, CJson *out)
182 {
183 if (!g_isInit) {
184 LOGE("[ACCOUNT_TASK_MGR]: has not been initialized!");
185 return HC_ERROR;
186 }
187 LoadAccountAuthPlugin();
188 int32_t res = ExcuteCredMgrCmd(osAccountId, cmdId, in, out);
189 UnloadAccountAuthPlugin();
190 return res;
191 }
192
CreateAccountAuthSession(int32_t * sessionId,const CJson * in,CJson * out)193 int32_t CreateAccountAuthSession(int32_t *sessionId, const CJson *in, CJson *out)
194 {
195 if (!g_isInit) {
196 LOGE("[ACCOUNT_TASK_MGR]: has not been initialized!");
197 return HC_ERROR;
198 }
199 LoadAccountAuthPlugin();
200 int32_t res = CreateAuthSession(sessionId, in, out);
201 if (res != HC_SUCCESS) {
202 LOGE("[ACCOUNT_TASK_MGR]: create auth session failed!");
203 UnloadAccountAuthPlugin();
204 return res;
205 }
206 res = AddAccountTaskRecord(*sessionId);
207 if (res != HC_SUCCESS) {
208 DestroyAuthSession(*sessionId);
209 UnloadAccountAuthPlugin();
210 }
211 return res;
212 }
213
ProcessAccountAuthSession(int32_t * sessionId,const CJson * in,CJson * out,int32_t * status)214 int32_t ProcessAccountAuthSession(int32_t *sessionId, const CJson *in, CJson *out, int32_t *status)
215 {
216 if (!g_isInit) {
217 LOGE("[ACCOUNT_TASK_MGR]: has not been initialized!");
218 return HC_ERROR;
219 }
220 LoadAccountAuthPlugin();
221 return ProcessAuthSession(sessionId, in, out, status);
222 }
223
DestroyAccountAuthSession(int32_t sessionId)224 int32_t DestroyAccountAuthSession(int32_t sessionId)
225 {
226 if (!g_isInit) {
227 LOGE("[ACCOUNT_TASK_MGR]: has not been initialized!");
228 return HC_ERROR;
229 }
230 LoadAccountAuthPlugin();
231 int32_t res = DestroyAuthSession(sessionId);
232 RemoveAccountTaskRecord(sessionId);
233 UnloadAccountAuthPlugin();
234 return res;
235 }
236
LoadAccountAndAddTaskRecord(int32_t taskId)237 int32_t LoadAccountAndAddTaskRecord(int32_t taskId)
238 {
239 if (!g_isInit) {
240 LOGE("[ACCOUNT_TASK_MGR]: has not been initialized!");
241 return HC_ERROR;
242 }
243 LoadAccountAuthPlugin();
244 int32_t res = AddAccountTaskRecord(taskId);
245 if (res != HC_SUCCESS) {
246 UnloadAccountAuthPlugin();
247 }
248 return res;
249 }
250
RemoveAccountTaskRecordAndUnload(int32_t taskId)251 void RemoveAccountTaskRecordAndUnload(int32_t taskId)
252 {
253 if (!g_isInit) {
254 LOGE("[ACCOUNT_TASK_MGR]: has not been initialized!");
255 return;
256 }
257 RemoveAccountTaskRecord(taskId);
258 UnloadAccountAuthPlugin();
259 }
260
NotifyAsyncTaskStart(void)261 void NotifyAsyncTaskStart(void)
262 {
263 if (!g_isInit) {
264 LOGE("[ACCOUNT_TASK_MGR]: has not been initialized!");
265 return;
266 }
267 (void)LockHcMutex(&g_taskMutex);
268 if (g_isAsyncTaskRunning) {
269 UnlockHcMutex(&g_taskMutex);
270 LOGI("[ACCOUNT_TASK_MGR]: async task is already started.");
271 return;
272 }
273 g_isAsyncTaskRunning = true;
274 UnlockHcMutex(&g_taskMutex);
275 LOGI("[ACCOUNT_TASK_MGR]: notify async task start successfully.");
276 }
277
NotifyAsyncTaskStop(void)278 void NotifyAsyncTaskStop(void)
279 {
280 if (!g_isInit) {
281 LOGE("[ACCOUNT_TASK_MGR]: has not been initialized!");
282 return;
283 }
284 (void)LockHcMutex(&g_taskMutex);
285 if (!g_isAsyncTaskRunning) {
286 UnlockHcMutex(&g_taskMutex);
287 LOGI("[ACCOUNT_TASK_MGR]: async task is already stopped.");
288 return;
289 }
290 g_isAsyncTaskRunning = false;
291 UnlockHcMutex(&g_taskMutex);
292 UnloadAccountAuthPlugin();
293 LOGI("[ACCOUNT_TASK_MGR]: notify async task stop successfully.");
294 }