1/*
2 * Copyright (c) 2020-2022 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 "example.h"
17#include <stdint.h>
18#include <ohos_init.h>
19#include <securec.h>
20#include <los_base.h>
21#include <cmsis_os.h>
22#include <samgr_maintenance.h>
23#include "iunknown.h"
24#include "feature.h"
25#include "service.h"
26#include "samgr_lite.h"
27#include "time_adapter.h"
28
29#define WAIT_FEATURE_PROC 1000
30
31enum MessageId {
32    MSG_PROC,
33    MSG_TIME_PROC,
34};
35
36struct Payload {
37    int id;
38    const char *name;
39    int value;
40};
41
42typedef struct DemoApi {
43    INHERIT_IUNKNOWN;
44    BOOL (*AsyncCall)(IUnknown *iUnknown, const char *buff);
45    BOOL (*AsyncTimeCall)(IUnknown *iUnknown);
46    BOOL (*SyncCall)(IUnknown *iUnknown, struct Payload *payload);
47    BOOL (*AsyncCallBack)(IUnknown *iUnknown, const char *buff, Handler handler);
48} DemoApi;
49
50typedef struct DemoFeature {
51    INHERIT_FEATURE;
52    INHERIT_IUNKNOWNENTRY(DemoApi);
53    Identity identity;
54} DemoFeature;
55
56static BOOL AsyncCall(IUnknown *iUnknown, const char *body);
57static BOOL AsyncTimeCall(IUnknown *iUnknown);
58static BOOL SyncCall(IUnknown *iUnknown, struct Payload *payload);
59static BOOL AsyncCallBack(IUnknown *iUnknown, const char *body, Handler handler);
60static const char *FEATURE_GetName(Feature *feature);
61static void FEATURE_OnInitialize(Feature *feature, Service *parent, Identity identity);
62static void FEATURE_OnStop(Feature *feature, Identity identity);
63static BOOL FEATURE_OnMessage(Feature *feature, Request *request);
64static DemoFeature g_example = {
65    .GetName = FEATURE_GetName,
66    .OnInitialize = FEATURE_OnInitialize,
67    .OnStop = FEATURE_OnStop,
68    .OnMessage = FEATURE_OnMessage,
69    DEFAULT_IUNKNOWN_ENTRY_BEGIN,
70    .AsyncCall = AsyncCall,
71    .AsyncTimeCall = AsyncTimeCall,
72    .SyncCall = SyncCall,
73    .AsyncCallBack = AsyncCallBack,
74    DEFAULT_IUNKNOWN_ENTRY_END,
75    .identity = {-1, -1, NULL},
76};
77static uint32_t g_regStep = 0;
78
79static const char *FEATURE_GetName(Feature *feature)
80{
81    (void)feature;
82    return EXAMPLE_FEATURE;
83}
84
85static void FEATURE_OnInitialize(Feature *feature, Service *parent, Identity identity)
86{
87    DemoFeature *demoFeature = (DemoFeature *)feature;
88    demoFeature->identity = identity;
89    printf("[Register Test][TaskID:%u][Step:%u][Reg Finish S:%s, F:%s]Time: %llu!\n",
90           (int)osThreadGetId(), g_regStep++, parent->GetName(parent), feature->GetName(feature),
91           SAMGR_GetProcessTime());
92}
93
94static void FEATURE_OnStop(Feature *feature, Identity identity)
95{
96    (void)feature;
97    (void)identity;
98    g_example.identity.queueId = NULL;
99    g_example.identity.featureId = -1;
100    g_example.identity.serviceId = -1;
101}
102
103static volatile uint32 g_asyncStep = 0;
104
105static BOOL FEATURE_OnMessage(Feature *feature, Request *request)
106{
107    (void)feature;
108    if (request->msgId == MSG_PROC) {
109        printf("[LPC Test][TaskID:%u][Step:%u][OnMessage: S:%s, F:%s] msgId<MSG_PROC> %s \n",
110               (int)osThreadGetId(), g_asyncStep++, EXAMPLE_SERVICE, feature->GetName(feature),
111               (char *)request->data);
112        Response response = {.data = "Yes, you did!", .len = 0};
113        SAMGR_SendResponse(request, &response);
114        return TRUE;
115    } else {
116        if (request->msgId == MSG_TIME_PROC) {
117            LOS_Msleep(WAIT_FEATURE_PROC * 11); // sleep 11 seconds
118            printf("[LPC Test][TaskID:%u][OnMessage: S:%s, F:%s] Time Message Get Value<%s>!",
119                (int)osThreadGetId(), EXAMPLE_SERVICE, feature->GetName(feature),
120                request->msgValue ? "TRUE" : "FALSE");
121            AsyncTimeCall(GET_IUNKNOWN(g_example));
122            return FALSE;
123        }
124    }
125    printf("[LPC Test][TaskID:%u][Step:%u][OnMessage S:%s, F:%s] Inner Error! \n",
126           (int)osThreadGetId(), g_asyncStep++, EXAMPLE_SERVICE, feature->GetName(feature));
127    return FALSE;
128}
129
130static BOOL SyncCall(IUnknown *iUnknown, struct Payload *payload)
131{
132    (void)iUnknown;
133    if (payload != NULL && payload->id >= 0 && payload->name != NULL) {
134        printf("[LPC Test][TaskID:%u][Step:%u][SyncCall API] Id:%d, name:%s, value:%d \n",
135               (int)osThreadGetId(), g_asyncStep++, payload->id, payload->name, payload->value);
136        return TRUE;
137    }
138    printf("[LPC Test][TaskID:%u][Step:%u][SyncCall API] Input Error! \n", (int)osThreadGetId(), g_asyncStep++);
139    return FALSE;
140}
141
142static BOOL AsyncCall(IUnknown *iUnknown, const char *body)
143{
144    Request request = {.msgId = MSG_PROC, .msgValue = 0};
145    request.len = (uint32_t)(strlen(body) + 1);
146    request.data = malloc(request.len);
147    if (request.data == NULL) {
148        return FALSE;
149    }
150    if (strcpy_s(request.data, request.len, body) != EOK) {
151        free(request.data);
152        return FALSE;
153    }
154    DemoFeature *feature = GET_OBJECT(iUnknown, DemoFeature, iUnknown);
155    printf("[LPC Test][TaskID:%u][Step:%u][AsyncCall API] Send request! \n", (int)osThreadGetId(), g_asyncStep++);
156    return SAMGR_SendRequest(&feature->identity, &request, NULL);
157}
158
159static BOOL AsyncTimeCall(IUnknown *iUnknown)
160{
161    static int8 cnt = 0;
162    cnt = (cnt + 1) % 2; // mod 2 to get async status
163    Request request = {.msgId = MSG_TIME_PROC, .msgValue = cnt};
164    DemoFeature *feature = GET_OBJECT(iUnknown, DemoFeature, iUnknown);
165    return SAMGR_SendRequest(&feature->identity, &request, NULL);
166}
167
168static BOOL AsyncCallBack(IUnknown *iUnknown, const char *body, Handler handler)
169{
170    Request request = {.msgId = MSG_PROC, .msgValue = 0};
171    request.len = (uint32_t)(strlen(body) + 1);
172    request.data = malloc(request.len);
173    if (request.data == NULL) {
174        return FALSE;
175    }
176    if (strcpy_s(request.data, request.len, body) != EOK) {
177        free(request.data);
178        return FALSE;
179    }
180    DemoFeature *feature = GET_OBJECT(iUnknown, DemoFeature, iUnknown);
181    printf("[LPC Test][TaskID:%u][Step:%u][AsyncCallBack API] Send request! \n",
182           (int)osThreadGetId(), g_asyncStep++);
183    return SAMGR_SendRequest(&feature->identity, &request, handler);
184}
185
186static void Init(void)
187{
188    SAMGR_GetInstance()->RegisterFeature(EXAMPLE_SERVICE, (Feature *)&g_example);
189    SAMGR_GetInstance()->RegisterFeatureApi(EXAMPLE_SERVICE, EXAMPLE_FEATURE, GET_IUNKNOWN(g_example));
190    printf("[Register Test][TaskID:%u][Step:%u][Reg S:%s, F:%s]Time: %llu!\n",
191           (int)osThreadGetId(), g_regStep++, EXAMPLE_SERVICE, EXAMPLE_FEATURE, SAMGR_GetProcessTime());
192}
193
194SYSEX_FEATURE_INIT(Init);
195
196static uint32_t g_discoverStep = 0;
197
198static DemoApi *CASE_GetIUnknown(void)
199{
200    DemoApi *demoApi = NULL;
201    printf("[Discover Test][TaskID:%u][Step:%u][GetIUnknown S:%s, F:%s]: BEGIN\n",
202           (int)osThreadGetId(), g_discoverStep++, EXAMPLE_SERVICE, EXAMPLE_FEATURE);
203    IUnknown *iUnknown = SAMGR_GetInstance()->GetFeatureApi(EXAMPLE_SERVICE, EXAMPLE_FEATURE);
204    if (iUnknown == NULL) {
205        printf("[Discover Test][TaskID:%u][Step:%u][GetFeatureApi S:%s, F:%s]Error is NULL!\n",
206               (int)osThreadGetId(), g_discoverStep++, EXAMPLE_SERVICE, EXAMPLE_FEATURE);
207        goto END;
208    }
209    int result = iUnknown->QueryInterface(iUnknown, DEFAULT_VERSION, (void **)&demoApi);
210    if (result != 0 || demoApi == NULL) {
211        printf("[Discover Test][TaskID:%u][Step:%u][QueryInterface S:%s, F:%s]Error is NULL!\n",
212               (int)osThreadGetId(), g_discoverStep++, EXAMPLE_SERVICE, EXAMPLE_FEATURE);
213        goto END;
214    }
215    printf("[Discover Test][TaskID:%u][Step:%u][GetIUnknown S:%s, F:%s]Success\n",
216           (int)osThreadGetId(), g_discoverStep++, EXAMPLE_SERVICE, EXAMPLE_FEATURE);
217END:
218    printf("[Discover Test][TaskID:%u][Step:%u][GetIUnknown S:%s, F:%s]: END\n",
219           (int)osThreadGetId(), g_discoverStep++, EXAMPLE_SERVICE, EXAMPLE_FEATURE);
220    return demoApi;
221}
222
223static void CASE_SyncCall(DemoApi *demoApi)
224{
225    if (demoApi->SyncCall == NULL) {
226        return;
227    }
228    printf("[LPC Test][TaskID:%u][Step:%u][SyncCall]: BEGIN! \n", (int)osThreadGetId(), g_asyncStep++);
229    struct Payload payload = {
230        .id = 0,
231        .name = "I want to sync call good result!",
232        .value = 1
233    };
234    if (!demoApi->SyncCall((IUnknown *)demoApi, &payload)) {
235        printf("[LPC Test][TaskID:%u][Step:%u][SyncCall]Error return false! \n",
236               (int)osThreadGetId(), g_asyncStep++);
237        goto END;
238    }
239    printf("[LPC Test][TaskID:%u][Step:%u][SyncCall]Success!\n",
240           (int)osThreadGetId(), g_asyncStep++);
241END:
242    printf("[LPC Test][TaskID:%u][Step:%u][SyncCall]: END\n",
243           (int)osThreadGetId(), g_asyncStep++);
244}
245
246
247static void CASE_AsyncCall(DemoApi *demoApi)
248{
249    if (demoApi->AsyncCall == NULL) {
250        return;
251    }
252    printf("[LPC Test][TaskID:%u][Step:%u][AsyncCall]: BEGIN! \n", (int)osThreadGetId(), g_asyncStep++);
253    uint32 count = g_asyncStep;
254    demoApi->AsyncCall((IUnknown *)demoApi, "I want to async call good result!");
255    LOS_Msleep(WAIT_FEATURE_PROC);
256    if (count == g_asyncStep) {
257        printf("[LPC Test][TaskID:%u][Step:%u][AsyncCall] result is failed! \n", (int)osThreadGetId(),
258               g_asyncStep++);
259        goto END;
260    }
261    printf("[LPC Test][TaskID:%u][Step:%u][AsyncCall]Success! \n", (int)osThreadGetId(), g_asyncStep++);
262END:
263    printf("[LPC Test][TaskID:%u][Step:%u][AsyncCall]: END! \n", (int)osThreadGetId(), g_asyncStep++);
264}
265
266static void CASE_AsyncTimeCall(DemoApi *demoApi)
267{
268    if (demoApi->AsyncCall == NULL) {
269        return;
270    }
271    demoApi->AsyncTimeCall((IUnknown *)demoApi);
272}
273
274static void AsyncHandler(const Request *request, const Response *response)
275{
276    (void)request;
277    printf("[LPC Test][TaskID:%u][Step:%u][AsyncCallBack]Success! Response:%s \n",
278           (int)osThreadGetId(), g_asyncStep++, (char *)response->data);
279    printf("[LPC Test][TaskID:%u][Step:%u][AsyncCallBack]: END! \n", (int)osThreadGetId(), g_asyncStep++);
280}
281
282static void CASE_AsyncCallBack(DemoApi *demoApi)
283{
284    if (demoApi->AsyncCallBack == NULL) {
285        return;
286    }
287    printf("[LPC Test][TaskID:%u][Step:%u][AsyncCallBack]: BEGIN! \n", (int)osThreadGetId(), g_asyncStep++);
288    demoApi->AsyncCallBack((IUnknown *)demoApi, "I want to async call callback good result!", AsyncHandler);
289    printf("[LPC Test][TaskID:%u][Step:%u][AsyncCallBack]Wait for response! \n",
290           (int)osThreadGetId(), g_asyncStep++);
291}
292
293static void CASE_ReleaseIUnknown(DemoApi *demoApi)
294{
295    printf("[Discover Test][TaskID:%u][Step:%u][ReleaseIUnknown S:%s, F:%s]: BEGIN\n",
296           (int)osThreadGetId(), g_discoverStep++, EXAMPLE_SERVICE, EXAMPLE_FEATURE);
297    int32 ref = demoApi->Release((IUnknown *)demoApi);
298    if (ref <= 0) {
299        printf("[Discover Test][TaskID:%u][Step:%u][ReleaseIUnknown S:%s, F:%s]Error ref is %d!\n",
300               (int)osThreadGetId(), g_discoverStep++, EXAMPLE_SERVICE, EXAMPLE_FEATURE, ref);
301        goto END;
302    }
303    printf("[Discover Test][TaskID:%u][Step:%u][ReleaseIUnknown S:%s, F:%s]Success\n",
304           (int)osThreadGetId(), g_discoverStep++, EXAMPLE_SERVICE, EXAMPLE_FEATURE);
305END:
306    printf("[Discover Test][TaskID:%u][Step:%u][ReleaseIUnknown S:%s, F:%s]: END\n",
307           (int)osThreadGetId(), g_discoverStep++, EXAMPLE_SERVICE, EXAMPLE_FEATURE);
308}
309
310static void RunTestCase(void)
311{
312    DemoApi *demoApi = CASE_GetIUnknown();
313    CASE_SyncCall(demoApi);
314    CASE_AsyncCall(demoApi);
315    CASE_AsyncCallBack(demoApi);
316    CASE_AsyncTimeCall(demoApi);
317    CASE_ReleaseIUnknown(demoApi);
318}
319
320LAYER_INITCALL_DEF(RunTestCase, test, "test");
321