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 #include <cinttypes>
16 #include <thread>
17 #include <chrono>
18 #include <sstream>
19 #include <string>
20 #include <fcntl.h>
21 #include <cstdio>
22 #include <cstdlib>
23 #include <cstring>
24 #include <securec.h>
25 #include <unistd.h>
26 #include <random>
27 #include "system_ability_definition.h"
28 #include "iservice_registry.h"
29 #include "ipc_kit.h"
30 #include "test_capi_skeleton.h"
31 #include "ipc_debug.h"
32 #include "ipc_inner_object.h"
33 #include "test_service_command.h"
34 
35 namespace OHOS {
36 
37 static constexpr int MAX_MEMORY_SIZE = 204800;
38 static constexpr int8_t TEST_VAL_INT8 = 121;
39 static constexpr int16_t TEST_VAL_INT16 = 1234;
40 static constexpr int32_t TEST_VAL_INT32 = 12345678;
41 static constexpr int64_t TEST_VAL_INT64 = 1234567890123L;
42 static constexpr float TEST_VAL_FLOAT = 123.456f;
43 static constexpr double TEST_VAL_DOUBLE = 123.456789;
44 static const std::string TEST_VAL_STRING = "0123456789abcdefghijklmnopqrstuvwxyz~!@#$%^&*()_+{}?/[]<>-='|~";
45 static constexpr uint8_t TEST_VAL_BUFFER[] = { 0xA1, 0xB2, 0xC3, 0xD4, 0xE5 };
46 static const std::string TEST_VAL_INTERFACE_TOKEN = "interface_token: test capi skeleton!";
47 
LocalMemAllocator(int32_t len)48 static void* LocalMemAllocator(int32_t len)
49 {
50     if (len <= 0 || len > MAX_MEMORY_SIZE) {
51         return nullptr;
52     }
53     void *buffer = malloc(len);
54     if (buffer != nullptr) {
55         if (memset_s(buffer, len, 0, len) != EOK) {
56             ZLOGE(NativeRemoteProxyTest::LABEL, "memset_s failed!");
57         }
58     }
59 
60     return buffer;
61 }
62 
NativeRemoteBase(const sptr<ITestService> & testService)63 NativeRemoteBase::NativeRemoteBase(const sptr<ITestService> &testService)
64     : testService_(testService)
65 {
66 }
67 
NativeRemoteProxyTest(const sptr<ITestService> & testService)68 NativeRemoteProxyTest::NativeRemoteProxyTest(const sptr<ITestService> &testService)
69     : NativeRemoteBase(testService)
70 {
71     if (testService_ == nullptr) {
72         ZLOGE(LABEL, "test service is nullptr");
73         return;
74     }
75 
76     sptr<IRemoteObject> remote = testService_->TestQueryRemoteProxy(NATIVEREMOTESTUBTEST_DESCRIPTOR.c_str());
77     proxy_ = CreateIPCRemoteProxy(remote);
78     if (proxy_ == nullptr) {
79         ZLOGE(LABEL, "CreateNativeRemoteProxy failed!");
80         return;
81     }
82     stubCallBack_ = OH_IPCRemoteStub_Create(NATIVEREMOTESTUBCALLBACKTEST_DESCRIPTOR.c_str(),
83         OnRemoteRequestStubCallBack, nullptr, this);
84 }
85 
~NativeRemoteProxyTest()86 NativeRemoteProxyTest::~NativeRemoteProxyTest()
87 {
88     if (stubCallBack_ != nullptr) {
89         OH_IPCRemoteStub_Destroy(stubCallBack_);
90     }
91     if (proxy_ != nullptr) {
92         OH_IPCRemoteProxy_Destroy(proxy_);
93     }
94 }
95 
SyncAdd()96 int NativeRemoteProxyTest::SyncAdd()
97 {
98     if (proxy_ == nullptr) {
99         return -1;
100     }
101     OHIPCParcel *data = OH_IPCParcel_Create();
102     if (data == nullptr) {
103         return -1;
104     }
105     OHIPCParcel *reply = OH_IPCParcel_Create();
106     if (reply == nullptr) {
107         OH_IPCParcel_Destroy(data);
108         return -1;
109     }
110     OH_IPC_MessageOption option{ OH_IPC_REQUEST_MODE_SYNC, 0 };
111     int ret = OH_IPCParcel_WriteInterfaceToken(data, NATIVEREMOTESTUBTEST_DESCRIPTOR.c_str());
112     if (ret != OH_IPC_SUCCESS) {
113         ZLOGE(LABEL, "OH_IPCParcel_WriteInterfaceToken failed! ret:%{public}d", ret);
114         OH_IPCParcel_Destroy(data);
115         OH_IPCParcel_Destroy(reply);
116         return -1;
117     }
118     int a = randomDistribution_(randomDevice_);
119     int b = randomDistribution_(randomDevice_);
120     OH_IPCParcel_WriteInt32(data, a);
121     OH_IPCParcel_WriteInt32(data, b);
122     ret = OH_IPCRemoteProxy_SendRequest(proxy_, NATIVE_TEST_CMD_SYNC_ADD, data, reply, &option);
123     if (ret != OH_IPC_SUCCESS) {
124         ZLOGE(LABEL, "OH_IPCRemoteProxy_SendRequest failed! ret:%{public}d", ret);
125         OH_IPCParcel_Destroy(data);
126         OH_IPCParcel_Destroy(reply);
127         return -1;
128     }
129     int result = 0;
130     OH_IPCParcel_ReadInt32(reply, &result);
131     OH_IPCParcel_Destroy(data);
132     OH_IPCParcel_Destroy(reply);
133     if ((a + b) == result) {
134         ZLOGD(LABEL, "SyncAdd success! %{public}d + %{public}d = %{public}d", a, b, result);
135         return 0;
136     }
137     ZLOGE(LABEL, "SyncAdd failed! %{public}d + %{public}d = %{public}d", a, b, result);
138     return -1;
139 }
140 
ASyncAdd()141 int NativeRemoteProxyTest::ASyncAdd()
142 {
143     if (proxy_ == nullptr) {
144         return -1;
145     }
146     OHIPCParcel *data = OH_IPCParcel_Create();
147     if (data == nullptr) {
148         return -1;
149     }
150 
151     OH_IPC_MessageOption option{ OH_IPC_REQUEST_MODE_ASYNC, 0 };
152     if (OH_IPCParcel_WriteInterfaceToken(data, NATIVEREMOTESTUBTEST_DESCRIPTOR.c_str()) != OH_IPC_SUCCESS) {
153         OH_IPCParcel_Destroy(data);
154         ZLOGE(LABEL, "OH_IPCParcel_WriteInterfaceToken failed!");
155         return -1;
156     }
157     int a = randomDistribution_(randomDevice_);
158     int b = randomDistribution_(randomDevice_);
159     OH_IPCParcel_WriteInt32(data, a);
160     OH_IPCParcel_WriteInt32(data, b);
161     OH_IPCParcel_WriteRemoteStub(data, stubCallBack_);
162     int ret = OH_IPCRemoteProxy_SendRequest(proxy_, NATIVE_TEST_CMD_ASYNC_ADD, data, nullptr, &option);
163     OH_IPCParcel_Destroy(data);
164     if (ret != OH_IPC_SUCCESS) {
165         ZLOGE(LABEL, "ipc sendRequest return=%{public}d ", ret);
166         return -1;
167     }
168     static constexpr int TIMEOUT = 3;
169     WaitForAsyncReply(TIMEOUT);
170     if ((a + b) == asyncReply_) {
171         ZLOGD(LABEL, "ASyncAdd success! %{public}d + %{public}d = %{public}d", a, b, asyncReply_);
172         return 0;
173     }
174     ZLOGE(LABEL, "ASyncAdd failed! %{public}d + %{public}d = %{public}d", a, b, asyncReply_);
175     return -1;
176 }
177 
OnRemoteRequestStubCallBack(uint32_t code,const OHIPCParcel * data,OHIPCParcel * reply,void * userData)178 int NativeRemoteProxyTest::OnRemoteRequestStubCallBack(uint32_t code,
179     const OHIPCParcel *data, OHIPCParcel *reply, void *userData)
180 {
181     ZLOGD(LABEL, "start %{public}u", code);
182     auto *proxyTest = reinterpret_cast<NativeRemoteProxyTest *>(userData);
183     if (code != NATIVE_TEST_CMD_ASYNC_ADD || proxyTest == nullptr) {
184         ZLOGE(LABEL, "check params or init failed!");
185         return OH_IPC_CHECK_PARAM_ERROR;
186     }
187 
188     int32_t val = 0;
189     int ret = OH_IPCParcel_ReadInt32(data, &val);
190     if (ret != OH_IPC_SUCCESS) {
191         ZLOGE(LABEL, "OH_IPCParcel_ReadInt32 failed!");
192         return ret;
193     }
194 
195     switch (code) {
196         case NATIVE_TEST_CMD_ASYNC_ADD: {
197             proxyTest->SendAsyncReply(val);
198             return OH_IPC_SUCCESS;
199         }
200         default:
201             break;
202     }
203     return OH_IPC_SUCCESS;
204 }
205 
WaitForAsyncReply(int timeout)206 int NativeRemoteProxyTest::WaitForAsyncReply(int timeout)
207 {
208     asyncReply_ = 0;
209     std::unique_lock<std::mutex> lck(mutex_);
210     cv_.wait_for(lck, std::chrono::seconds(timeout), [&]() {
211         return asyncReply_ != 0;
212     });
213     return asyncReply_;
214 }
215 
SendAsyncReply(int & replyValue)216 void NativeRemoteProxyTest::SendAsyncReply(int &replyValue)
217 {
218     std::unique_lock<std::mutex> lck(mutex_);
219     asyncReply_ = replyValue;
220     cv_.notify_all();
221 }
222 
SendBasicDataType(OHIPCParcel * data)223 void NativeRemoteProxyTest::SendBasicDataType(OHIPCParcel *data)
224 {
225     if (data != nullptr) {
226         OH_IPCParcel_WriteInt8(data, TEST_VAL_INT8);
227         OH_IPCParcel_WriteInt16(data, TEST_VAL_INT16);
228         OH_IPCParcel_WriteInt32(data, TEST_VAL_INT32);
229         OH_IPCParcel_WriteInt64(data, TEST_VAL_INT64);
230         OH_IPCParcel_WriteFloat(data, TEST_VAL_FLOAT);
231         OH_IPCParcel_WriteDouble(data, TEST_VAL_DOUBLE);
232     }
233 }
234 
235 template <typename T>
CheckBaseDataReply(const OHIPCParcel * data,T checkValue,int (* readFunc)(const OHIPCParcel * data,T * value))236 static int CheckBaseDataReply(const OHIPCParcel *data, T checkValue,
237     int (*readFunc)(const OHIPCParcel *data, T *value))
238 {
239     int ret = OH_IPC_SUCCESS;
240     T value = 0;
241     ret = readFunc(data, &value);
242     if (value != checkValue) {
243         ZLOGE(NativeRemoteProxyTest::LABEL, "CheckBaseDataReply failed! expect value:%{public}" PRId64
244             ", real value:%{public}" PRId64, static_cast<int64_t>(checkValue), static_cast<int64_t>(value));
245         return -1;
246     }
247     return 0;
248 }
249 
TestBasicDataTypeReply(const OHIPCParcel * reply)250 int NativeRemoteProxyTest::TestBasicDataTypeReply(const OHIPCParcel *reply)
251 {
252     static const double ESP = 1e-6;
253     if (reply == nullptr) {
254         return -1;
255     }
256     if (CheckBaseDataReply<int8_t>(reply, TEST_VAL_INT8, OH_IPCParcel_ReadInt8) != 0) {
257         return -1;
258     }
259     if (CheckBaseDataReply<int16_t>(reply, TEST_VAL_INT16, OH_IPCParcel_ReadInt16) != 0) {
260         return -1;
261     }
262     if (CheckBaseDataReply<int32_t>(reply, TEST_VAL_INT32, OH_IPCParcel_ReadInt32) != 0) {
263         return -1;
264     }
265     if (CheckBaseDataReply<int64_t>(reply, TEST_VAL_INT64, OH_IPCParcel_ReadInt64) != 0) {
266         return -1;
267     }
268     float valFloat = 0.0f;
269     int ret = OH_IPCParcel_ReadFloat(reply, &valFloat);
270     if (abs(valFloat - TEST_VAL_FLOAT) > ESP) {
271         ZLOGE(LABEL, "CheckBaseDataReply failed! expect value:%{public}f, real value:%{public}f",
272             TEST_VAL_FLOAT, valFloat);
273         return -1;
274     }
275 
276     double valDouble = 0.0;
277     ret = OH_IPCParcel_ReadDouble(reply, &valDouble);
278     if (abs(valDouble - TEST_VAL_DOUBLE) > ESP) {
279         ZLOGE(LABEL, "CheckBaseDataReply failed! expect value:%{public}f, real value:%{public}f",
280             TEST_VAL_DOUBLE, valDouble);
281         return -1;
282     }
283     return 0;
284 }
285 
SendAndEchoBase()286 int NativeRemoteProxyTest::SendAndEchoBase()
287 {
288     if (proxy_ == nullptr) {
289         return -1;
290     }
291     OHIPCParcel *data = OH_IPCParcel_Create();
292     if (data == nullptr) {
293         return -1;
294     }
295     OHIPCParcel *reply = OH_IPCParcel_Create();
296     if (reply == nullptr) {
297         OH_IPCParcel_Destroy(data);
298         return -1;
299     }
300     OH_IPC_MessageOption option{ OH_IPC_REQUEST_MODE_SYNC, 0 };
301     if (OH_IPCParcel_WriteInterfaceToken(data, NATIVEREMOTESTUBTEST_DESCRIPTOR.c_str()) != OH_IPC_SUCCESS) {
302         OH_IPCParcel_Destroy(data);
303         OH_IPCParcel_Destroy(reply);
304         return -1;
305     }
306 
307     SendBasicDataType(data);
308 
309     int ret = OH_IPCRemoteProxy_SendRequest(proxy_, NATIVE_TEST_CMD_SEND_AND_ECHO_BASE, data, reply, &option);
310     if (ret != OH_IPC_SUCCESS) {
311         OH_IPCParcel_Destroy(data);
312         OH_IPCParcel_Destroy(reply);
313         ZLOGE(LABEL, "SendAndEchoBase SendRequest ret:%{public}d", ret);
314         return -1;
315     }
316     OH_IPCParcel_Destroy(data);
317     if (TestBasicDataTypeReply(reply) != 0) {
318         OH_IPCParcel_Destroy(reply);
319         return -1;
320     }
321 
322     OH_IPCParcel_Destroy(reply);
323     return 0;
324 }
325 
SendAndEchoString()326 int NativeRemoteProxyTest::SendAndEchoString()
327 {
328     if (proxy_ == nullptr) {
329         return -1;
330     }
331     OHIPCParcel *data = OH_IPCParcel_Create();
332     if (data == nullptr) {
333         return -1;
334     }
335     OHIPCParcel *reply = OH_IPCParcel_Create();
336     if (reply == nullptr) {
337         OH_IPCParcel_Destroy(data);
338         return -1;
339     }
340     OH_IPC_MessageOption option{ OH_IPC_REQUEST_MODE_SYNC, 0 };
341     if (OH_IPCParcel_WriteInterfaceToken(data, NATIVEREMOTESTUBTEST_DESCRIPTOR.c_str()) != OH_IPC_SUCCESS) {
342         OH_IPCParcel_Destroy(data);
343         OH_IPCParcel_Destroy(reply);
344         return -1;
345     }
346     if (OH_IPCParcel_WriteString(data, TEST_VAL_STRING.c_str()) != OH_IPC_SUCCESS) {
347         ZLOGE(LABEL, "OH_IPCParcel_WriteString failed!");
348         OH_IPCParcel_Destroy(data);
349         OH_IPCParcel_Destroy(reply);
350         return -1;
351     }
352     int ret = OH_IPCRemoteProxy_SendRequest(proxy_, NATIVE_TEST_CMD_SEND_AND_ECHO_SRING,
353         data, reply, &option);
354     if (ret != OH_IPC_SUCCESS) {
355         ZLOGE(LABEL, "SendAndEchoString SendRequest ret:%{public}d", ret);
356         OH_IPCParcel_Destroy(data);
357         OH_IPCParcel_Destroy(reply);
358         return -1;
359     }
360 
361     const char *readStr = OH_IPCParcel_ReadString(reply);
362     if (readStr == nullptr || TEST_VAL_STRING != readStr) {
363         ZLOGE(LABEL, "OH_IPCParcel_ReadString failed!");
364         OH_IPCParcel_Destroy(data);
365         OH_IPCParcel_Destroy(reply);
366         return -1;
367     }
368     OH_IPCParcel_Destroy(data);
369     OH_IPCParcel_Destroy(reply);
370     return 0;
371 }
372 
SendAndEchoBuffer()373 int NativeRemoteProxyTest::SendAndEchoBuffer()
374 {
375     if (proxy_ == nullptr) {
376         return -1;
377     }
378     OHIPCParcel *data = OH_IPCParcel_Create();
379     if (data == nullptr) {
380         return -1;
381     }
382     OHIPCParcel *reply = OH_IPCParcel_Create();
383     if (reply == nullptr) {
384         OH_IPCParcel_Destroy(data);
385         return -1;
386     }
387     OH_IPC_MessageOption option{ OH_IPC_REQUEST_MODE_SYNC, 0 };
388     if (OH_IPCParcel_WriteInterfaceToken(data, NATIVEREMOTESTUBTEST_DESCRIPTOR.c_str()) != OH_IPC_SUCCESS) {
389         OH_IPCParcel_Destroy(data);
390         OH_IPCParcel_Destroy(reply);
391         return -1;
392     }
393     OH_IPCParcel_WriteInt32(data, sizeof(TEST_VAL_BUFFER));
394     OH_IPCParcel_WriteBuffer(data, TEST_VAL_BUFFER, sizeof(TEST_VAL_BUFFER));
395 
396     int ret = OH_IPCRemoteProxy_SendRequest(proxy_, NATIVE_TEST_CMD_SEND_AND_ECHO_BUFFER,
397         data, reply, &option);
398     if (ret != OH_IPC_SUCCESS) {
399         ZLOGE(LABEL, "SendAndEchoBuffer SendRequest ret:%{public}d", ret);
400         OH_IPCParcel_Destroy(data);
401         OH_IPCParcel_Destroy(reply);
402         return -1;
403     }
404 
405     const uint8_t *readBuff = OH_IPCParcel_ReadBuffer(reply, sizeof(TEST_VAL_BUFFER));
406     if (readBuff == nullptr) {
407         OH_IPCParcel_Destroy(data);
408         OH_IPCParcel_Destroy(reply);
409         return -1;
410     }
411     int cmpResult = memcmp(readBuff, TEST_VAL_BUFFER, sizeof(TEST_VAL_BUFFER));
412     if (cmpResult != 0) {
413         ZLOGE(LABEL, "SendAndEchoBuffer check echo buffer faield!");
414         OH_IPCParcel_Destroy(data);
415         OH_IPCParcel_Destroy(reply);
416         return -1;
417     }
418     OH_IPCParcel_Destroy(data);
419     OH_IPCParcel_Destroy(reply);
420     return 0;
421 }
422 
SendAndEchoFileDescriptor()423 int NativeRemoteProxyTest::SendAndEchoFileDescriptor()
424 {
425     if (proxy_ == nullptr) {
426         return -1;
427     }
428     OHIPCParcel *data = OH_IPCParcel_Create();
429     if (data == nullptr) {
430         return -1;
431     }
432     OHIPCParcel *reply = OH_IPCParcel_Create();
433     if (reply == nullptr) {
434         OH_IPCParcel_Destroy(data);
435         return -1;
436     }
437     OH_IPC_MessageOption option{ OH_IPC_REQUEST_MODE_SYNC, 0 };
438     if (OH_IPCParcel_WriteInterfaceToken(data, NATIVEREMOTESTUBTEST_DESCRIPTOR.c_str()) != OH_IPC_SUCCESS) {
439         OH_IPCParcel_Destroy(data);
440         OH_IPCParcel_Destroy(reply);
441         return -1;
442     }
443     int32_t fd = open("/data/capiTest.txt", O_RDWR | O_CREAT);
444     if (fd == INVALID_FD) {
445         OH_IPCParcel_Destroy(data);
446         OH_IPCParcel_Destroy(reply);
447         ZLOGE(LABEL, "open file failed!");
448         return -1;
449     }
450     OH_IPCParcel_WriteFileDescriptor(data, fd);
451     int ret = OH_IPCRemoteProxy_SendRequest(proxy_, NATIVE_TEST_CMD_SEND_FILE_DESCRIPTOR, data, reply, &option);
452     if (ret != OH_IPC_SUCCESS) {
453         ZLOGE(LABEL, "SendAndEchoFileDescriptor SendRequest ret:%{public}d", ret);
454         OH_IPCParcel_Destroy(data);
455         OH_IPCParcel_Destroy(reply);
456         close(fd);
457         return -1;
458     }
459     close(fd);
460     OH_IPCParcel_Destroy(data);
461     OH_IPCParcel_Destroy(reply);
462     return 0;
463 }
464 
SendErrorCode()465 int NativeRemoteProxyTest::SendErrorCode()
466 {
467     static std::map<int, int> vec = {
468         { OH_IPC_USER_ERROR_CODE_MIN, OH_IPC_USER_ERROR_CODE_MIN },
469         { OH_IPC_USER_ERROR_CODE_MAX, OH_IPC_USER_ERROR_CODE_MAX },
470         { OH_IPC_USER_ERROR_CODE_MIN - 1, OH_IPC_INVALID_USER_ERROR_CODE },
471         { OH_IPC_USER_ERROR_CODE_MAX + 1, OH_IPC_INVALID_USER_ERROR_CODE }
472     };
473 
474     if (proxy_ == nullptr) {
475         return -1;
476     }
477     auto func = [&, this](int val, int expect) -> int {
478         OHIPCParcel *data = OH_IPCParcel_Create();
479         if (data == nullptr) {
480             return -1;
481         }
482         OHIPCParcel *reply = OH_IPCParcel_Create();
483         if (reply == nullptr) {
484             OH_IPCParcel_Destroy(data);
485             return -1;
486         }
487         OH_IPC_MessageOption option{ OH_IPC_REQUEST_MODE_SYNC, 0 };
488         if (OH_IPCParcel_WriteInterfaceToken(data, NATIVEREMOTESTUBTEST_DESCRIPTOR.c_str()) != OH_IPC_SUCCESS) {
489             OH_IPCParcel_Destroy(data);
490             OH_IPCParcel_Destroy(reply);
491             return -1;
492         }
493         OH_IPCParcel_WriteInt32(data, val);
494         int ret = OH_IPCRemoteProxy_SendRequest(this->proxy_, NATIVE_TEST_CMD_SEND_ERROR_CODE, data, reply, &option);
495         OH_IPCParcel_Destroy(data);
496         OH_IPCParcel_Destroy(reply);
497         return (ret == expect) ? 0 : -1;
498     };
499 
500     for (const auto &item : vec) {
501         if (func(item.first, item.second) != 0) {
502             ZLOGE(LABEL, "SendErrorCode test failed error code:%{public}d, expect error code:%{public}d",
503                 item.first, item.second);
504             return -1;
505         }
506     }
507     return 0;
508 }
509 
AddParallel(bool isSync)510 int NativeRemoteProxyTest::AddParallel(bool isSync)
511 {
512     static constexpr int PARALLEL_NUMBER = 1000;
513     static constexpr int PARALLEL_ACTION_SLEEP_CNT = 20;
514     int parallelNum = PARALLEL_NUMBER;
515     while (parallelNum-- > 0) {
516         std::this_thread::sleep_for(std::chrono::milliseconds(PARALLEL_ACTION_SLEEP_CNT));
517         int ret = isSync ? SyncAdd() : ASyncAdd();
518         if (ret != 0) {
519             ZLOGE(LABEL, "Add Parallel Test failed!");
520             return ret;
521         }
522     }
523     ZLOGD(LABEL, "Parallel test success!");
524     return 0;
525 }
526 
527 thread_local const OHIPCParcel *NativeRemoteStubTest::currentData_ = nullptr;
528 thread_local OHIPCParcel *NativeRemoteStubTest::currentReply_ = nullptr;
529 
530 std::map<int, std::function<int(NativeRemoteStubTest *stub)>> NativeRemoteStubTest::funcMap_ = {
__anon2b43c6f60302() 531     { NATIVE_TEST_CMD_SYNC_ADD, [](NativeRemoteStubTest *stub) { return stub->SyncAdd(); }},
__anon2b43c6f60402() 532     { NATIVE_TEST_CMD_ASYNC_ADD, [](NativeRemoteStubTest *stub) { return stub->ASyncAdd(); }},
__anon2b43c6f60502() 533     { NATIVE_TEST_CMD_SEND_AND_ECHO_BASE, [](NativeRemoteStubTest *stub) { return stub->SendAndEchoBase(); }},
__anon2b43c6f60602() 534     { NATIVE_TEST_CMD_SEND_AND_ECHO_SRING, [](NativeRemoteStubTest *stub) { return stub->SendAndEchoString(); }},
__anon2b43c6f60702() 535     { NATIVE_TEST_CMD_SEND_AND_ECHO_BUFFER, [](NativeRemoteStubTest *stub) { return stub->SendAndEchoBuffer(); }},
536     { NATIVE_TEST_CMD_SEND_FILE_DESCRIPTOR, [](NativeRemoteStubTest *stub)
__anon2b43c6f60802() 537         { return stub->SendAndEchoFileDescriptor(); }},
__anon2b43c6f60902() 538     { NATIVE_TEST_CMD_SEND_ERROR_CODE, [](NativeRemoteStubTest *stub) { return stub->SendErrorCode(); }},
539 };
540 
NativeRemoteStubTest(const sptr<ITestService> & testService)541 NativeRemoteStubTest::NativeRemoteStubTest(const sptr<ITestService> &testService)
542     : NativeRemoteBase(testService)
543 {
544     stub_ = OH_IPCRemoteStub_Create(NATIVEREMOTESTUBTEST_DESCRIPTOR.c_str(),
545         &NativeRemoteStubTest::OnRemoteRequest, nullptr, this);
546 }
547 
~NativeRemoteStubTest()548 NativeRemoteStubTest::~NativeRemoteStubTest()
549 {
550     if (stub_ != nullptr) {
551         OH_IPCRemoteStub_Destroy(stub_);
552     }
553 }
554 
RegisterRemoteStub()555 int NativeRemoteStubTest::RegisterRemoteStub()
556 {
557     ZLOGD(LABEL, "TestRegisterRemoteStubTest");
558     if (testService_ == nullptr) {
559         ZLOGE(LABEL, "Member variable testService_ Is a null pointer");
560         return OH_IPC_INNER_ERROR;
561     }
562     int result = testService_->TestRegisterRemoteStub(NATIVEREMOTESTUBTEST_DESCRIPTOR.c_str(), stub_->remote);
563     return result;
564 }
565 
UnRegisterRemoteStub()566 int NativeRemoteStubTest::UnRegisterRemoteStub()
567 {
568     ZLOGD(LABEL, "TestRegisterRemoteStubTest");
569     if (testService_ == nullptr) {
570         ZLOGE(LABEL, "Member variable testService_ Is a null pointer");
571         return OH_IPC_INNER_ERROR;
572     }
573     int result = testService_->TestUnRegisterRemoteStub(NATIVEREMOTESTUBTEST_DESCRIPTOR.c_str());
574     return result;
575 }
576 
OnRemoteRequest(uint32_t code,const OHIPCParcel * data,OHIPCParcel * reply,void * userData)577 int NativeRemoteStubTest::OnRemoteRequest(uint32_t code, const OHIPCParcel *data, OHIPCParcel *reply, void *userData)
578 {
579     NativeRemoteStubTest *stubTest = reinterpret_cast<NativeRemoteStubTest *>(userData);
580     if (stubTest == nullptr) {
581         ZLOGE(LABEL, "change user data failed!");
582         return OH_IPC_INNER_ERROR;
583     }
584 
585     int readLen = 0;
586     char *token = nullptr;
587     if (OH_IPCParcel_ReadInterfaceToken(data, &token, &readLen, LocalMemAllocator) != OH_IPC_SUCCESS
588         || NATIVEREMOTESTUBTEST_DESCRIPTOR != token) {
589         if (token != nullptr) {
590             ZLOGE(LABEL, "ReadInterfaceToken failed");
591             free(token);
592         }
593         return OH_IPC_INNER_ERROR;
594     }
595     free(token);
596 
597     stubTest->currentData_ = data;
598     stubTest->currentReply_ = reply;
599     auto it = funcMap_.find(static_cast<int>(code));
600     if (it != funcMap_.end()) {
601         return it->second(stubTest);
602     } else {
603         ZLOGE(LABEL, "unknown code:%{public}d", code);
604         return OH_IPC_INNER_ERROR;
605     }
606 }
607 
SyncAdd()608 int NativeRemoteStubTest::SyncAdd()
609 {
610     int32_t a = 0;
611     int32_t b = 0;
612     OH_IPCParcel_ReadInt32(this->currentData_, &a);
613     OH_IPCParcel_ReadInt32(this->currentData_, &b);
614 
615     OH_IPCParcel_WriteInt32(this->currentReply_, a + b);
616     return 0;
617 }
618 
ASyncAdd()619 int NativeRemoteStubTest::ASyncAdd()
620 {
621     int32_t a = 0;
622     int32_t b = 0;
623     OH_IPCParcel_ReadInt32(this->currentData_, &a);
624     OH_IPCParcel_ReadInt32(this->currentData_, &b);
625     auto proxyCallBack = OH_IPCParcel_ReadRemoteProxy(this->currentData_);
626     if (proxyCallBack == nullptr) {
627         return OH_IPC_PARCEL_READ_ERROR;
628     }
629     OHIPCParcel *dataParcel = OH_IPCParcel_Create();
630     if (dataParcel == nullptr) {
631         OH_IPCRemoteProxy_Destroy(proxyCallBack);
632         return OH_IPC_MEM_ALLOCATOR_ERROR;
633     }
634     OHIPCParcel *replyParcel = OH_IPCParcel_Create();
635     if (replyParcel == nullptr) {
636         OH_IPCRemoteProxy_Destroy(proxyCallBack);
637         OH_IPCParcel_Destroy(dataParcel);
638         return OH_IPC_MEM_ALLOCATOR_ERROR;
639     }
640     ZLOGD(LABEL, "start create sendCallback thread!");
641     std::thread th([proxyCallBack, dataParcel, replyParcel, a, b] {
642         std::this_thread::sleep_for(std::chrono::seconds(1));
643         OH_IPCParcel_WriteInt32(dataParcel, a + b);
644         OH_IPC_MessageOption option{ OH_IPC_REQUEST_MODE_ASYNC, 0 };
645         ZLOGD(LABEL, "thread start sendCallback!");
646         int ret = OH_IPCRemoteProxy_SendRequest(proxyCallBack, NATIVE_TEST_CMD_ASYNC_ADD,
647             dataParcel, replyParcel, &option);
648         if (ret != OH_IPC_SUCCESS) {
649             ZLOGE(LABEL, "ASyncAdd SendRequest failed! ret=%{public}d", ret);
650         }
651         OH_IPCRemoteProxy_Destroy(proxyCallBack);
652         OH_IPCParcel_Destroy(dataParcel);
653         OH_IPCParcel_Destroy(replyParcel);
654     });
655     th.detach();
656     return OH_IPC_SUCCESS;
657 }
658 
659 template <typename T>
ReadAndEchoBaseType(const OHIPCParcel * data,OHIPCParcel * reply,int (* readFunc)(const OHIPCParcel * data,T * value),int (* writeFunc)(OHIPCParcel * reply,T value))660 static int ReadAndEchoBaseType(const OHIPCParcel *data, OHIPCParcel *reply,
661     int (*readFunc)(const OHIPCParcel *data, T *value), int (*writeFunc)(OHIPCParcel *reply, T value))
662 {
663     T value = 0;
664     int ret = readFunc(data, &value);
665     if (ret != OH_IPC_SUCCESS) {
666         return OH_IPC_PARCEL_READ_ERROR;
667     }
668     return writeFunc(reply, value);
669 }
670 
SendAndEchoBase()671 int NativeRemoteStubTest::SendAndEchoBase()
672 {
673     int ret = ReadAndEchoBaseType<int8_t>(this->currentData_, this->currentReply_,
674         OH_IPCParcel_ReadInt8, OH_IPCParcel_WriteInt8);
675     if (ret != OH_IPC_SUCCESS) {
676         ZLOGE(LABEL, "Read or Write Int8 failed! ret:%{public}d", ret);
677         return ret;
678     }
679     ret = ReadAndEchoBaseType<int16_t>(this->currentData_, this->currentReply_,
680         OH_IPCParcel_ReadInt16, OH_IPCParcel_WriteInt16);
681     if (ret != OH_IPC_SUCCESS) {
682         ZLOGE(LABEL, "Read or Write Int16 failed! ret:%{public}d", ret);
683         return ret;
684     }
685     ret = ReadAndEchoBaseType<int32_t>(this->currentData_, this->currentReply_,
686         OH_IPCParcel_ReadInt32, OH_IPCParcel_WriteInt32);
687     if (ret != OH_IPC_SUCCESS) {
688         ZLOGE(LABEL, "Read or Write Int32 failed! ret:%{public}d", ret);
689         return ret;
690     }
691     ret = ReadAndEchoBaseType<int64_t>(this->currentData_, this->currentReply_,
692         OH_IPCParcel_ReadInt64, OH_IPCParcel_WriteInt64);
693     if (ret != OH_IPC_SUCCESS) {
694         ZLOGE(LABEL, "Read or Write Int64 failed! ret:%{public}d", ret);
695         return ret;
696     }
697     ret = ReadAndEchoBaseType<float>(this->currentData_, this->currentReply_,
698         OH_IPCParcel_ReadFloat, OH_IPCParcel_WriteFloat);
699     if (ret != OH_IPC_SUCCESS) {
700         ZLOGE(LABEL, "Read or Write float failed! ret:%{public}d", ret);
701         return ret;
702     }
703     ret = ReadAndEchoBaseType<double>(this->currentData_, this->currentReply_,
704         OH_IPCParcel_ReadDouble, OH_IPCParcel_WriteDouble);
705     if (ret != OH_IPC_SUCCESS) {
706         ZLOGE(LABEL, "Read or Write double failed! ret:%{public}d", ret);
707     }
708     return ret;
709 }
710 
SendAndEchoString()711 int OHOS::NativeRemoteStubTest::SendAndEchoString()
712 {
713     const char *readString = OH_IPCParcel_ReadString(this->currentData_);
714     if (readString == nullptr) {
715         ZLOGE(LABEL, "OH_IPCParcel_ReadString failed!");
716         return OH_IPC_PARCEL_READ_ERROR;
717     }
718 
719     return OH_IPCParcel_WriteString(this->currentReply_, readString);
720 }
721 
SendAndEchoBuffer()722 int OHOS::NativeRemoteStubTest::SendAndEchoBuffer()
723 {
724     int32_t buffLen = 0;
725     int ret = OH_IPCParcel_ReadInt32(this->currentData_, &buffLen);
726     if (ret != OH_IPC_SUCCESS) {
727         ZLOGE(LABEL, "SendAndEchoBuffer read buffer len failed! ret:%{public}d", ret);
728         return OH_IPC_PARCEL_READ_ERROR;
729     }
730     const uint8_t *buffer = OH_IPCParcel_ReadBuffer(this->currentData_, buffLen);
731     if (buffer == nullptr) {
732         ZLOGE(LABEL, "OH_IPCParcel_ReadBuffer failed!");
733         return OH_IPC_PARCEL_READ_ERROR;
734     }
735 
736     return OH_IPCParcel_WriteBuffer(this->currentReply_, buffer, buffLen);
737 }
738 
SendAndEchoFileDescriptor()739 int OHOS::NativeRemoteStubTest::SendAndEchoFileDescriptor()
740 {
741     int32_t fd = INVALID_FD;
742     int ret = OH_IPCParcel_ReadFileDescriptor(this->currentData_, &fd);
743     if (ret != OH_IPC_SUCCESS || fd == INVALID_FD) {
744         ZLOGE(LABEL, "OH_IPCParcel_ReadFileDescriptor failed! ret:%{public}d", ret);
745         return OH_IPC_PARCEL_READ_ERROR;
746     }
747     (void)write(fd, TEST_VAL_STRING.c_str(), TEST_VAL_STRING.length());
748     close(fd);
749     return OH_IPC_SUCCESS;
750 }
751 
SendErrorCode()752 int NativeRemoteStubTest::SendErrorCode()
753 {
754     int32_t valInt32 = 0;
755     int ret = OH_IPCParcel_ReadInt32(this->currentData_, &valInt32);
756     return ret == OH_IPC_SUCCESS ? valInt32 : OH_IPC_PARCEL_READ_ERROR;
757 }
758 }
759