From 649c02942b2bcff14bb765b5c5b468968adb6cfc Mon Sep 17 00:00:00 2001 From: dengliang <15934868816@139.com> Date: Fri, 29 Aug 2025 18:23:51 +0800 Subject: [PATCH 1/4] freeze process Signed-off-by: dengliang <15934868816@139.com> --- .../innerkits/ipc_core/include/ipc_skeleton.h | 4 + .../ipc_core/include/message_option.h | 1 + .../include/dbinder_base_invoker_interface.h | 12 ++ .../src/core/framework/include/sys_binder.h | 17 ++- .../core/framework/source/ipc_skeleton.cpp | 18 +++ .../src/core/invoker/include/binder_invoker.h | 4 + .../core/invoker/include/iremote_invoker.h | 4 + .../core/invoker/source/binder_invoker.cpp | 38 +++++ .../common/binder_invoker_unittest.cpp | 36 +++++ .../unittest/common/ipc_skeleton_unittest.cpp | 55 ++++++++ .../unittest/common/mock_iremote_invoker.h | 2 + .../auxiliary/native/include/test_service.h | 2 + .../native/include/test_service_base.h | 4 + .../native/include/test_service_stub.h | 2 + ipc/test/auxiliary/native/src/main_client.cpp | 21 +++ .../auxiliary/native/src/test_service.cpp | 10 ++ .../native/src/test_service_client.cpp | 30 ++++ .../native/src/test_service_proxy.cpp | 130 ++++++++++++++++++ .../native/src/test_service_stub.cpp | 16 +++ test/unittest/mock/mock_iremote_invoker.h | 2 + 20 files changed, 407 insertions(+), 1 deletion(-) diff --git a/interfaces/innerkits/ipc_core/include/ipc_skeleton.h b/interfaces/innerkits/ipc_core/include/ipc_skeleton.h index a19a0e79..b2a8e66c 100644 --- a/interfaces/innerkits/ipc_core/include/ipc_skeleton.h +++ b/interfaces/innerkits/ipc_core/include/ipc_skeleton.h @@ -207,6 +207,10 @@ public: * @since 20 */ static uint32_t GetDCallingTokenID(); + + static int32_t FreezeProcess(uint32_t pid, bool freeze, uint32_t timeout); + + static int32_t CheckFreeze(uint32_t pid, bool &isFreeze); }; class IPCDfx { diff --git a/interfaces/innerkits/ipc_core/include/message_option.h b/interfaces/innerkits/ipc_core/include/message_option.h index bd9f222f..0fe51ff6 100644 --- a/interfaces/innerkits/ipc_core/include/message_option.h +++ b/interfaces/innerkits/ipc_core/include/message_option.h @@ -26,6 +26,7 @@ public: TF_STATUS_CODE = 0x08, TF_ACCEPT_FDS = 0x10, TF_WAIT_TIME = 0x8, + TF_UPDATE_TXN = 0x40, TF_ASYNC_WAKEUP_LATER = 0x100000, }; MessageOption(int flags = TF_SYNC, int waitTime = TF_WAIT_TIME); diff --git a/ipc/native/src/core/dbinder/include/dbinder_base_invoker_interface.h b/ipc/native/src/core/dbinder/include/dbinder_base_invoker_interface.h index 7561c06a..937e96e6 100644 --- a/ipc/native/src/core/dbinder/include/dbinder_base_invoker_interface.h +++ b/ipc/native/src/core/dbinder/include/dbinder_base_invoker_interface.h @@ -120,6 +120,18 @@ int DBinderBaseInvoker::SendRequest(int32_t handle, uint32_t code, MessagePar return ret; } +template +int32_t DBinderBaseInvoker::FreezeProcess(uint32_t pid, bool freeze, uint32_t timeout) +{ + return ERR_NONE; +} + +template +int32_t DBinderBaseInvoker::CheckFreeze(uint32_t pid, bool &isFreeze) +{ + return ERR_NONE; +} + template bool DBinderBaseInvoker::SetMaxWorkThread(int maxThreadNum) { return true; diff --git a/ipc/native/src/core/framework/include/sys_binder.h b/ipc/native/src/core/framework/include/sys_binder.h index 206e09e6..54dd232d 100644 --- a/ipc/native/src/core/framework/include/sys_binder.h +++ b/ipc/native/src/core/framework/include/sys_binder.h @@ -62,6 +62,18 @@ struct flat_binder_object { }; binder_uintptr_t cookie; }; + +struct binder_freeze_info { + __u32 pid; + __u32 enable; + __u32 timeout_ms; +}; + +struct binder_frozen_state_info { + __u32 pid; + bool has_unfrozen; +}; + #ifndef __linux__ #define HMB_ERROR_INFO_LEN 64 struct hmb_detailed_err { @@ -160,6 +172,8 @@ struct binder_sender_info { #define BINDER_GET_NODE_DEBUG_INFO _IOWR('b', 11, struct binder_node_debug_info) #define BINDER_GET_NODE_INFO_FOR_REF _IOWR('b', 12, struct binder_node_info_for_ref) #define BINDER_SET_CONTEXT_MGR_EXT _IOW('b', 13, struct flat_binder_object) +#define BINDER_FREEZE _IOW('b', 14, struct binder_freeze_info) +#define BINDER_GET_FROZEN_STATE _IOW('b', 15, struct binder_frozen_state_info) #define BINDER_FEATURE_SET _IOWR('b', 30, struct binder_feature_set) #define BINDER_GET_ACCESS_TOKEN _IOWR('b', 31, struct access_token) #define BINDER_GET_SENDER_INFO _IOWR('b', 32, struct binder_sender_info) @@ -241,7 +255,8 @@ enum binder_driver_return_protocol { BR_DEAD_BINDER = _IOR('r', 15, binder_uintptr_t), BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, binder_uintptr_t), BR_FAILED_REPLY = _IO('r', 17), - BR_RELEASE_NODE = _IO('r', 18), + BR_FROZEN_REPLY = _IO('r', 18), + BR_TRANSACTION_PENDING_FROZEN = _IO('r', 20), }; enum binder_driver_command_protocol { BC_TRANSACTION = _IOW('c', 0, struct binder_transaction_data), diff --git a/ipc/native/src/core/framework/source/ipc_skeleton.cpp b/ipc/native/src/core/framework/source/ipc_skeleton.cpp index 7948b69c..a0ecd644 100644 --- a/ipc/native/src/core/framework/source/ipc_skeleton.cpp +++ b/ipc/native/src/core/framework/source/ipc_skeleton.cpp @@ -330,6 +330,24 @@ uint32_t IPCSkeleton::GetDCallingTokenID() return static_cast(GetSelfTokenID()); } +int32_t IPCSkeleton::FreezeProcess(uint32_t pid, bool freeze, uint32_t timeout) +{ + IRemoteInvoker *invoker = IPCThreadSkeleton::GetDefaultInvoker(); + if (invoker == nullptr) { + return IPC_SKELETON_NULL_OBJECT_ERR; + } + return invoker->FreezeProcess(pid, freeze, timeout); +} + +int32_t IPCSkeleton::CheckFreeze(uint32_t pid, bool &isFreeze) +{ + IRemoteInvoker *invoker = IPCThreadSkeleton::GetDefaultInvoker(); + if (invoker == nullptr) { + return IPC_SKELETON_NULL_OBJECT_ERR; + } + return invoker->CheckFreeze(pid, isFreeze); +} + void IPCDfx::BlockUntilThreadAvailable() { IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent(); diff --git a/ipc/native/src/core/invoker/include/binder_invoker.h b/ipc/native/src/core/invoker/include/binder_invoker.h index d8743e2b..58221dc8 100644 --- a/ipc/native/src/core/invoker/include/binder_invoker.h +++ b/ipc/native/src/core/invoker/include/binder_invoker.h @@ -90,6 +90,10 @@ public: int SendRequest(int handle, uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; + int32_t FreezeProcess(uint32_t pid, bool freeze, uint32_t timeout) override; + + int32_t CheckFreeze(uint32_t pid, bool &isFreeze) override; + int SendReply(MessageParcel &reply, uint32_t flags, int32_t result) override; bool FlattenObject(Parcel &parcel, const IRemoteObject *object) const override; diff --git a/ipc/native/src/core/invoker/include/iremote_invoker.h b/ipc/native/src/core/invoker/include/iremote_invoker.h index 9feb8517..2dff97b7 100644 --- a/ipc/native/src/core/invoker/include/iremote_invoker.h +++ b/ipc/native/src/core/invoker/include/iremote_invoker.h @@ -51,6 +51,10 @@ public: virtual int SendRequest(int handle, uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) = 0; + virtual int32_t FreezeProcess(uint32_t pid, bool freeze, uint32_t timeout) = 0; + + virtual int32_t CheckFreeze(uint32_t pid, bool &isFreeze) = 0; + virtual bool AddDeathRecipient(int32_t handle, void *cookie) = 0; virtual bool RemoveDeathRecipient(int32_t handle, void *cookie) = 0; diff --git a/ipc/native/src/core/invoker/source/binder_invoker.cpp b/ipc/native/src/core/invoker/source/binder_invoker.cpp index df701131..ceda2dc6 100644 --- a/ipc/native/src/core/invoker/source/binder_invoker.cpp +++ b/ipc/native/src/core/invoker/source/binder_invoker.cpp @@ -737,6 +737,40 @@ int32_t BinderInvoker::SamgrServiceSendRequest( return error; } +int32_t BinderInvoker::FreezeProcess(uint32_t pid, bool freeze, uint32_t timeout) +{ + if ((binderConnector_ == nullptr) || (!binderConnector_->IsDriverAlive())) { + return IPC_INVOKER_CONNECT_ERR; + } + binder_freeze_info info{}; + info.enable = pid; + info.enable = freeze; + info.timeout_ms = timeout; + int error = binderConnector_->WriteBinder(BINDER_FREEZE, &info); + if (error != ERR_NONE) { + ZLOGE(LABEL, "Freeze process failed, error:%{public}d", error); + return error; + } + return ERR_NONE; +} + +int32_t BinderInvoker::CheckFreeze(uint32_t pid, bool &isFreeze) +{ + if ((binderConnector_ == nullptr) || (!binderConnector_->IsDriverAlive())) { + return IPC_INVOKER_CONNECT_ERR; + } + binder_frozen_state_info info{}; + info.pid = pid; + info.has_unfrozen = false; + int error = binderConnector_->WriteBinder(BINDER_GET_FROZEN_STATE, &info); + if (error != ERR_NONE) { + ZLOGE(LABEL, "Get freeze state failed, error:%{public}d", error); + return error; + } + isFreeze = !info.has_unfrozen; + return ERR_NONE; +} + int32_t BinderInvoker::GeneralServiceSendRequest( const binder_transaction_data &tr, MessageParcel &data, MessageParcel &reply, MessageOption &option) { @@ -1232,7 +1266,11 @@ void BinderInvoker::DealWithCmd(MessageParcel *reply, bool &continueLoop, int32_ case BR_FAILED_REPLY: OnDeadOrFailedReply(reply, continueLoop, error, cmd); break; + case BR_FROZEN_REPLY: + OnDeadOrFailedReply(reply, continueLoop, error, cmd); + break; case BR_REPLY: + case BR_TRANSACTION_PENDING_FROZEN: OnReply(reply, continueLoop, error, cmd); break; default: diff --git a/ipc/native/test/unittest/common/binder_invoker_unittest.cpp b/ipc/native/test/unittest/common/binder_invoker_unittest.cpp index f24bce52..62abcbbd 100644 --- a/ipc/native/test/unittest/common/binder_invoker_unittest.cpp +++ b/ipc/native/test/unittest/common/binder_invoker_unittest.cpp @@ -25,6 +25,7 @@ #include "ipc_process_skeleton.h" #include "sys_binder.h" +using namespace testing; using namespace testing::ext; using namespace OHOS; @@ -830,4 +831,39 @@ HWTEST_F(BinderInvokerUnitTest, GetInvocationStateTest001, TestSize.Level1) binderInvoker.isFirstInvoke_ = STATUS_FIRST_INVOKE; EXPECT_EQ(binderInvoker.GetInvocationState(), STATUS_FIRST_INVOKE); } + +/** + * @tc.name: FreezeProcessTest001 + * @tc.desc: cover FreezeProcess branch + * @tc.type: FUNC + */ +HWTEST_F(BinderInvokerUnitTest, FreezeProcessTest, TestSize.Level1) +{ + BinderInvoker binderInvoker; + binderInvoker.binderConnector_ = nullptr; + EXPECT_EQ(binderInvoker.FreezeProcess(1, true, 1), IPC_INVOKER_CONNECT_ERR); + + BinderConnector *binderConnector = BinderConnector::GetInstance(); + binderConnector->driverFD_ = -1; + binderInvoker.binderConnector_ = binderConnector; + EXPECT_EQ(binderInvoker.FreezeProcess(1, true, 1), IPC_INVOKER_CONNECT_ERR); +} + +/** + * @tc.name: CheckFreezeTest + * @tc.desc: cover CheckFreeze branch + * @tc.type: FUNC + */ + HWTEST_F(BinderInvokerUnitTest, CheckFreezeTest, TestSize.Level1) + { + bool isFreeze = false; + BinderInvoker binderInvoker; + binderInvoker.binderConnector_ = nullptr; + EXPECT_EQ(binderInvoker.CheckFreeze(1, isFreeze), IPC_INVOKER_CONNECT_ERR); + + BinderConnector *binderConnector = BinderConnector::GetInstance(); + binderConnector->driverFD_ = -1; + binderInvoker.binderConnector_ = binderConnector; + EXPECT_EQ(binderInvoker.CheckFreeze(1, isFreeze), IPC_INVOKER_CONNECT_ERR); + } } // namespace OHOS \ No newline at end of file diff --git a/ipc/native/test/unittest/common/ipc_skeleton_unittest.cpp b/ipc/native/test/unittest/common/ipc_skeleton_unittest.cpp index 71223a8f..572be748 100644 --- a/ipc/native/test/unittest/common/ipc_skeleton_unittest.cpp +++ b/ipc/native/test/unittest/common/ipc_skeleton_unittest.cpp @@ -35,6 +35,7 @@ #undef protected #undef private +using namespace testing; using namespace testing::ext; using namespace OHOS; @@ -906,4 +907,58 @@ HWTEST_F(IPCSkeletonTest, GetDCallingTokenIDInRPC, TestSize.Level1) ASSERT_EQ(tokenId, 0); } + +/** + * @tc.name: FreezeProcessTest + * @tc.desc: Verify the FreezeProcess function. + * @tc.type: FUNC + */ +HWTEST_F(IPCSkeletonTest, FreezeProcessTest, TestSize.Level1) +{ + IPCThreadSkeleton *current = IPCThreadSkeleton::GetCurrent(); + ASSERT_NE(current, nullptr); + MockIRemoteInvoker *binderInvoker = new (std::nothrow) MockIRemoteInvoker(); + ASSERT_NE(binderInvoker, nullptr); + MockIRemoteInvoker *dbinderInvoker = new (std::nothrow) MockIRemoteInvoker(); + ASSERT_NE(dbinderInvoker, nullptr); + + current->invokers_[IRemoteObject::IF_PROT_DEFAULT] = binderInvoker; + current->invokers_[IRemoteObject::IF_PROT_DATABUS] = dbinderInvoker; + + EXPECT_CALL(*binderInvoker, FreezeProcess(testing::_, testing::_, testing::_)()) + .WillRepeatedly(testing::Return(ERR_NONE)); + + ASSERT_EQ(IPCSkeleton::FreezeProcess(0, true, 0), ERR_NONE); + std::fill(current->invokers_, current->invokers_ + IPCThreadSkeleton::INVOKER_MAX_COUNT, nullptr); + delete binderInvoker; + delete dbinderInvoker; +} + +/** + * @tc.name: CheckFreezeTest + * @tc.desc: Verify the CheckFreeze function. + * @tc.type: FUNC + */ +HWTEST_F(IPCSkeletonTest, CheckFreezeTest, TestSize.Level1) +{ + IPCThreadSkeleton *current = IPCThreadSkeleton::GetCurrent(); + ASSERT_NE(current, nullptr); + MockIRemoteInvoker *binderInvoker = new (std::nothrow) MockIRemoteInvoker(); + ASSERT_NE(binderInvoker, nullptr); + MockIRemoteInvoker *dbinderInvoker = new (std::nothrow) MockIRemoteInvoker(); + ASSERT_NE(dbinderInvoker, nullptr); + + current->invokers_[IRemoteObject::IF_PROT_DEFAULT] = binderInvoker; + current->invokers_[IRemoteObject::IF_PROT_DATABUS] = dbinderInvoker; + + EXPECT_CALL(*binderInvoker, CheckFreeze(testing::_, testing::_)()) + .WillRepeatedly(testing::Return(ERR_NONE)); + + bool isFreeze = false; + ASSERT_EQ(IPCSkeleton::CheckFreeze(0, isFreeze), ERR_NONE); + std::fill(current->invokers_, current->invokers_ + IPCThreadSkeleton::INVOKER_MAX_COUNT, nullptr); + delete binderInvoker; + delete dbinderInvoker; +} + } // namespace OHOS \ No newline at end of file diff --git a/ipc/native/test/unittest/common/mock_iremote_invoker.h b/ipc/native/test/unittest/common/mock_iremote_invoker.h index b53f3bb8..d4c9004a 100644 --- a/ipc/native/test/unittest/common/mock_iremote_invoker.h +++ b/ipc/native/test/unittest/common/mock_iremote_invoker.h @@ -41,6 +41,8 @@ public: MOCK_METHOD3(SendReply, int(MessageParcel &reply, uint32_t flags, int32_t result)); MOCK_METHOD5(SendRequest, int(int handle, uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)); + MOCK_METHOD3(FreezeProcess, int32_t(uint32_t pid, bool freeze, uint32_t timeout)); + MOCK_METHOD2(CheckFreeze, int32_t(uint32_t pid, bool &isFreeze)); MOCK_METHOD2(AddDeathRecipient, bool(int32_t handle, void *cookie)); MOCK_METHOD2(RemoveDeathRecipient, bool(int32_t handle, void *cookie)); MOCK_METHOD1(SetMaxWorkThread, bool(int maxThreadNum)); diff --git a/ipc/test/auxiliary/native/include/test_service.h b/ipc/test/auxiliary/native/include/test_service.h index c7ece976..aa770f9b 100644 --- a/ipc/test/auxiliary/native/include/test_service.h +++ b/ipc/test/auxiliary/native/include/test_service.h @@ -56,6 +56,8 @@ public: int TestSendTooManyRequest(int data, int &reply) override; int TestMultiThreadSendRequest(int data, int &reply) override; int TestQueryThreadInvocationState() override; + int TestFreezeProcess() override; + int TestFreezeProcessAsyncReq() override; private: int testFd_; std::mutex remoteObjectsMutex_; diff --git a/ipc/test/auxiliary/native/include/test_service_base.h b/ipc/test/auxiliary/native/include/test_service_base.h index fd969b7c..8b7e8bcd 100644 --- a/ipc/test/auxiliary/native/include/test_service_base.h +++ b/ipc/test/auxiliary/native/include/test_service_base.h @@ -56,6 +56,8 @@ public: TRANS_ID_UNREGISTER_REMOTE_STUB_OBJECT = 24, TRANS_ID_QUERY_REMOTE_PROXY_OBJECT = 25, TRANS_ID_QUERY_THREAD_INVOCATION_STATE = 26, + TRANS_ID_TEST_FREEZE_PROCESS = 27, + TRANS_ID_TEST_TXN_ASYNC_TRANS = 28, }; public: virtual int TestSyncTransaction(int value, int &reply, int delayTime = 0) = 0; @@ -87,6 +89,8 @@ public: virtual int TestSendTooManyRequest(int data, int &reply) = 0; virtual int TestMultiThreadSendRequest(int data, int &reply) = 0; virtual int TestQueryThreadInvocationState() = 0; + virtual int TestFreezeProcess() = 0; + virtual int TestFreezeProcessAsyncReq() = 0; public: DECLARE_INTERFACE_DESCRIPTOR(u"test.ipc.ITestService"); diff --git a/ipc/test/auxiliary/native/include/test_service_stub.h b/ipc/test/auxiliary/native/include/test_service_stub.h index b5190036..c7bda112 100644 --- a/ipc/test/auxiliary/native/include/test_service_stub.h +++ b/ipc/test/auxiliary/native/include/test_service_stub.h @@ -50,6 +50,8 @@ private: int32_t QueryRemoteProxy(MessageParcel &data, MessageParcel &reply); int32_t ServerFlushAsyncCalls(MessageParcel &data, MessageParcel &reply); int32_t ServerThreadInvocationState(MessageParcel &data, MessageParcel &reply); + int32_t ServerTestFreezeProcess(MessageParcel &data, MessageParcel &reply); + int32_t ServerTxnAsyncTransaction(MessageParcel &data, MessageParcel &reply); void InitMessageProcessMap(); using TestServiceStubFunc = int32_t(TestServiceStub::*)(MessageParcel &data, MessageParcel &reply); diff --git a/ipc/test/auxiliary/native/src/main_client.cpp b/ipc/test/auxiliary/native/src/main_client.cpp index 6a486a57..45e15289 100644 --- a/ipc/test/auxiliary/native/src/main_client.cpp +++ b/ipc/test/auxiliary/native/src/main_client.cpp @@ -82,6 +82,25 @@ void TestCaseSyncTrans(std::shared_ptr &testClient) } } +void TestCaseFreezeProcess(std::shared_ptr &testClient) +{ + bool ret = testClient->TestFreezeProcess(); + if (!ret) { + std::cout << "[FAILED] Execution of TestFreezeProcess case failed" < &testClient) +{ + bool ret = testClient->TestFreezeProcessAsyncReq(); + if (!ret) { + std::cout << "[FAILED] Execution of TestCaseFreezeProcessAsyncReq case failed" < &testClient) { bool ret = testClient->StartPingService(); @@ -229,6 +248,8 @@ void ExecuteAllTestCase() TestCaseRegisterRemoteStub(testClient); TestCaseTooManyRequests(testClient); TestCaseMultiThreadSendRequest(testClient); + TestCaseFreezeProcess(testClient); + TestCaseFreezeProcessAsyncReq(testClient); ZLOGI(LABEL, "All test cases have been executed"); } diff --git a/ipc/test/auxiliary/native/src/test_service.cpp b/ipc/test/auxiliary/native/src/test_service.cpp index c8b6b110..7bffefc3 100644 --- a/ipc/test/auxiliary/native/src/test_service.cpp +++ b/ipc/test/auxiliary/native/src/test_service.cpp @@ -345,4 +345,14 @@ int TestService::TestQueryThreadInvocationState() return state; } + +int TestService::TestFreezeProcess() +{ + return 0; +} + +int TestService::TestFreezeprocessAsyncReq() +{ + return 0; +} } // namespace OHOS diff --git a/ipc/test/auxiliary/native/src/test_service_client.cpp b/ipc/test/auxiliary/native/src/test_service_client.cpp index 154a7b0e..030a29d3 100644 --- a/ipc/test/auxiliary/native/src/test_service_client.cpp +++ b/ipc/test/auxiliary/native/src/test_service_client.cpp @@ -74,6 +74,36 @@ bool TestServiceClient::StartSyncTransaction() return true; } +bool TestServiceClient::TestFreezeProcess() +{ + if (testService_ == nullptr) { + ZLOGE(LABEL, "The testService_ object is an empty object"); + return false; + } + + int ret = testService_->TestFreezeProcess(); + if (ret != 0) { + ZLOGE(LABEL, "TestFreezeProcess function call failed"); + return false; + } + return true; +} + +bool TestServiceClient::TestFreezeprocessAsyncReq() +{ + if (testService_ == nullptr) { + ZLOGE(LABEL, "The testService_ object is an empty object"); + return false; + } + + int ret = testService_->TestFreezeProcessAsyncReq(); + if (ret != 0) { + ZLOGE(LABEL, "TestFreezeProcessAsyncReq function call failed"); + return false; + } + return true; +} + bool TestServiceClient::StartPingService() { if (testService_ == nullptr) { diff --git a/ipc/test/auxiliary/native/src/test_service_proxy.cpp b/ipc/test/auxiliary/native/src/test_service_proxy.cpp index 7a043511..a0c68464 100644 --- a/ipc/test/auxiliary/native/src/test_service_proxy.cpp +++ b/ipc/test/auxiliary/native/src/test_service_proxy.cpp @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include #include @@ -95,6 +97,134 @@ int TestServiceProxy::TestSyncTransaction(int value, int &reply, int delayTime) return ret; } +int TestServiceProxy::TestFreezeProcess() +{ + ZLOGI(LABEL, "TestFreezeProcess"); + + auto remote = Remote(); + if (remote == nullptr) { + ZLOGI(LABEL, "The obtained proxy is a null pointer"); + return -1; + } + + MessageOption option; + MessageParcel dataParcel; + MessageParcel replyParcel; + int ret = remote->SendRequest(TRANS_ID_TEST_FREEZE_PROCESS, dataParcel, replyParcel, option); + if (ret != ERR_NONE) { + return ret; + } + int pid = replyParcel.ReadInt32(); + ZLOGI(LABEL, "Get pid from server, server pid = %{public}d", pid); + + int timeout = 1000; + auto res = IPCSkeleton::FreezeProcess(pid, true, timeout); + if (res != ERR_NONE) { + ZLOGI(LABEL, "FreezeProcess failed, error code = %{public}d", res); + return res; + } + + bool isFreeze = false; + res = IPCSkeleton::CheckFreeze(pid, isFreeze); + if (res != ERR_NONE || !isFreeze) { + ZLOGI(LABEL, "CheckFreeze failed, error code = %{public}d isFreeze = %{public}d ",res, isFreeze); + return -1; + } + + ret = remote->SendRequest(TRANS_ID_TEST_FREEZE_PROCESS, dataParcel, replyParcel, option); + if (ret != ERR_NONE) { + ZLOGI(LABEL, "SendRequest failed, error code = %{public}d", ret); + return -1; + } + + ZLOGI(LABEL, "TestFreezeProcess success"); + return 0; +} + +int TestServiceProxy::TestFreezeProcessAcyncReq() +{ + ZLOGI(LABEL, "TestFreezeProcessAcyncReq"); + + auto remote = Remote(); + if (remote == nullptr) { + ZLOGI(LABEL, "The obtained proxy is a null pointer"); + return -1; + } + + MessageOption option; + MessageParcel dataParcel; + MessageParcel replyParcel; + int timeout = 1000; + + int ret = remote->SendRequest(TRANS_ID_TEST_FREEZE_PROCESS, dataParcel, replyParcel, option); + if (ret != ERR_NONE) { + ZLOGI(LABEL, "SendRequest failed, error code = %{public}d", ret); + return -1; + } + int pid = replyParcel.ReadInt32(); + ZLOGI(LABEL, "Get pid from server, server pid = %{public}d", pid); + + ret = IPCSkeleton::FreezeProcess(pid, true, timeout); + if (ret != ERR_NONE) { + ZLOGI(LABEL, "FreezeProcess failed, error code = %{public}d", ret); + return ret; + } + + enum ReplyStatus { + NO_REPLY = 0, + DATA_NOT_UPDATAED = 1, + DATA_UPDATAED = 2, + }; + + // TF_ASYNC 1 + MessageOption option1 = { MessageOption::TF_ASYNC }; + MessageParcel dataParcel1; + MessageParcel replyParcel1; + dataParcel1.WriteInt32(static_cast(ReplyStatus::DATA_NOT_UPDATAED)); + sptr fooCallback1 = new FooStub(); + dataParcel1.WriteRemoteObject(fooCallback1); + ret = remote->SendRequest(TRANS_ID_TEST_TXN_ASYNC_TRANS, dataParcel1, replyParcel1, option1); + if (ret != ERR_NONE) { + ZLOGI(LABEL, "SendRequest failed, error code = %{public}d", ret); + return -1; + } + std::future fut1 = std::async(std::launch::async, WaitForReply, std::ref(fooCallback1), timeout); + + + // TF_ASYNC 2 + MessageOption option2 = { MessageOption::TF_UPDATE_TXN }; + MessageParcel dataParcel2; + MessageParcel replyParcel2; + dataParcel2.WriteInt32(static_cast(ReplyStatus::DATA_UPDATAED)); + sptr fooCallback2 = new FooStub(); + dataParcel2.WriteRemoteObject(fooCallback2); + ret = remote->SendRequest(TRANS_ID_TEST_TXN_ASYNC_TRANS, dataParcel2, replyParcel2, option2); + if (ret != ERR_NONE) { + ZLOGI(LABEL, "SendRequest failed, error code = %{public}d", ret); + return -1; + } + std::future fut2 = std::async(std::launch::async, WaitForReply, std::ref(fooCallback2), timeout); + + // unfreeze + IPCSkeleton::FreezeProcess(pid, false, 0); + + // wait for reply + int32_t reply1 = fut1.get(); + int32_t reply2 = fut2.get(); + if (reply1 != ReplyStatus::NO_REPLY || reply2 != DATA_UPDATAED) { + ZLOGI(LABEL, "TestFreezeProcessAcyncReq failed"); + return -1; + } + + return 0; +} +static int WaitForReply(sptr &fooCallback, int timeout) +{ + return fooCallback->WaitForAsyncReply(timeout); +} + + + int TestServiceProxy::TestSendTooManyRequest(int data, int &reply) { int ret = 0; diff --git a/ipc/test/auxiliary/native/src/test_service_stub.cpp b/ipc/test/auxiliary/native/src/test_service_stub.cpp index d9a082d6..93d32728 100644 --- a/ipc/test/auxiliary/native/src/test_service_stub.cpp +++ b/ipc/test/auxiliary/native/src/test_service_stub.cpp @@ -483,4 +483,20 @@ int32_t TestServiceStub::ServerThreadInvocationState(MessageParcel &data, Messag reply.WriteInt32(ret); return ret; } + +int32_t TestServiceStub::ServerTestFreezeProcess(MessageParcel &data, MessageParcel &reply) +{ + reply.WriteInt32(getpid()); + return 0; +} + +int32_t TestServiceStub::ServerTxnAsyncTransaction(MessageParcel &data, MessageParcel &reply) +{ + int32_t retData = data.ReadInt32(); + sptr fooProxy = iface_cast(data.ReadRemoteObject()); + if (fooProxy != nullptr) { + fooProxy->SendAsyncReply(retData); + } + return 0; +} } // namespace OHOS diff --git a/test/unittest/mock/mock_iremote_invoker.h b/test/unittest/mock/mock_iremote_invoker.h index b524b532..6c048baf 100644 --- a/test/unittest/mock/mock_iremote_invoker.h +++ b/test/unittest/mock/mock_iremote_invoker.h @@ -41,6 +41,8 @@ public: MOCK_METHOD3(SendReply, int(MessageParcel &reply, uint32_t flags, int32_t result)); MOCK_METHOD5(SendRequest, int(int handle, uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)); + MOCK_METHOD3(FreezeProcess, int32_t(uint32_t pid, bool freeze, uint32_t timeout)); + MOCK_METHOD2(CheckFreeze, int32_t(uint32_t pid, bool &isFreeze)); MOCK_METHOD2(AddDeathRecipient, bool(int32_t handle, void *cookie)); MOCK_METHOD2(RemoveDeathRecipient, bool(int32_t handle, void *cookie)); MOCK_METHOD1(SetMaxWorkThread, bool(int maxThreadNum)); -- Gitee From 0d0a456cf573943b0a8c2a60ee9c29e8d1d4de97 Mon Sep 17 00:00:00 2001 From: dengliang <15934868816@139.com> Date: Wed, 3 Sep 2025 15:05:32 +0800 Subject: [PATCH 2/4] freeze process Signed-off-by: dengliang <15934868816@139.com> --- config.gni | 6 ++ .../innerkits/ipc_core/include/ipc_skeleton.h | 22 +++++ interfaces/innerkits/ipc_single/BUILD.gn | 6 ++ .../include/dbinder_base_invoker_define.h | 5 +- .../include/dbinder_base_invoker_interface.h | 14 +++ .../core/framework/source/ipc_skeleton.cpp | 2 + .../core/invoker/include/iremote_invoker.h | 2 + .../core/invoker/source/binder_invoker.cpp | 12 ++- ipc/native/test/unittest/common/BUILD.gn | 4 + .../common/binder_invoker_unittest.cpp | 24 +++--- .../unittest/common/ipc_skeleton_unittest.cpp | 3 +- .../unittest/common/mock_iremote_invoker.h | 2 + ipc/test/auxiliary/native/BUILD.gn | 13 +++ .../auxiliary/native/include/test_service.h | 3 +- .../native/include/test_service_base.h | 3 +- .../native/include/test_service_client.h | 3 + .../native/include/test_service_proxy.h | 3 + .../native/include/test_service_stub.h | 3 +- ipc/test/auxiliary/native/src/main_client.cpp | 14 +-- .../auxiliary/native/src/test_service.cpp | 7 +- .../native/src/test_service_client.cpp | 17 +--- .../native/src/test_service_proxy.cpp | 86 +------------------ .../native/src/test_service_stub.cpp | 15 ++-- .../ipc/native/src/core/source/BUILD.gn | 4 + test/unittest/mock/mock_iremote_invoker.h | 2 + 25 files changed, 133 insertions(+), 142 deletions(-) diff --git a/config.gni b/config.gni index bf6ea89d..5d3c8bbd 100644 --- a/config.gni +++ b/config.gni @@ -23,6 +23,7 @@ declare_args() { hiviewdfx_backtrace_support = false hiviewdfx_hisysevent_support = false ipc_proxy_dfx_backtrace_enabled = false + ipc_freeze_process_support = false } if (defined(global_parts_info) && @@ -44,3 +45,8 @@ if (defined(global_parts_info) && defined(global_parts_info.hiviewdfx_hisysevent)) { hiviewdfx_hisysevent_support = true } + +if (defined(global_parts_info) && + defined(global_parts_info.officeservice_space_mgr_service)) { + ipc_freeze_process_support = true +} \ No newline at end of file diff --git a/interfaces/innerkits/ipc_core/include/ipc_skeleton.h b/interfaces/innerkits/ipc_core/include/ipc_skeleton.h index b2a8e66c..3cf4e1e7 100644 --- a/interfaces/innerkits/ipc_core/include/ipc_skeleton.h +++ b/interfaces/innerkits/ipc_core/include/ipc_skeleton.h @@ -208,9 +208,31 @@ public: */ static uint32_t GetDCallingTokenID(); +#ifdef FREEZE_PROCESS_SUPPORT + /** + * @brief Freeze or unfreeze a process. + * @param pid Process ID to freeze or unfreeze. + * @param freeze True to freeze the process, false to unfreeze it. + * @param timeout Timeout value in milliseconds to wait for the stub to finish processing requests + * before freezing. If the timeout is reached and processing is not completed, the freeze operation + * will be abandoned. + * @return Returns {@link ERR_NONE} if the operation is successful; returns an error code + * defined in {@link ipc_types.h} otherwise. + * @since 20 + */ static int32_t FreezeProcess(uint32_t pid, bool freeze, uint32_t timeout); + /** + * @brief Check if a process is frozen. + * @param pid Process ID to check. + * @param isFreeze Reference to a boolean variable that will store the freeze status of the process. + * True if the process is frozen, false otherwise. + * @return Returns {@link ERR_NONE} if the operation is successful; returns an error code + * defined in {@link ipc_types.h} otherwise. + * @since 20 + */ static int32_t CheckFreeze(uint32_t pid, bool &isFreeze); +#endif // FREEZE_PROCESS_SUPPORT }; class IPCDfx { diff --git a/interfaces/innerkits/ipc_single/BUILD.gn b/interfaces/innerkits/ipc_single/BUILD.gn index 497d8b40..23d8913c 100644 --- a/interfaces/innerkits/ipc_single/BUILD.gn +++ b/interfaces/innerkits/ipc_single/BUILD.gn @@ -122,6 +122,9 @@ ohos_shared_library("ipc_single") { if (hiviewdfx_hisysevent_support) { defines += [ "HIVIEWDFX_HISYSEVENT_SUPPORT" ] } + if (ipc_freeze_process_support) { + defines += [ "FREEZE_PROCESS_SUPPORT" ] + } innerapi_tags = [ "chipsetsdk", "platformsdk", @@ -164,6 +167,9 @@ ohos_shared_library("ipc_single_test") { if (hiviewdfx_hisysevent_support) { defines += [ "HIVIEWDFX_HISYSEVENT_SUPPORT" ] } + if (ipc_freeze_process_support) { + defines += [ "FREEZE_PROCESS_SUPPORT" ] + } innerapi_tags = [ "chipsetsdk_sp", "platformsdk", diff --git a/ipc/native/src/core/dbinder/include/dbinder_base_invoker_define.h b/ipc/native/src/core/dbinder/include/dbinder_base_invoker_define.h index 157db0e7..2b6d05ed 100644 --- a/ipc/native/src/core/dbinder/include/dbinder_base_invoker_define.h +++ b/ipc/native/src/core/dbinder/include/dbinder_base_invoker_define.h @@ -77,6 +77,10 @@ public: virtual sptr GetSAMgrObject() override; virtual bool SetRegistryObject(sptr &object) override; virtual void FreeBuffer(void *data) override; +#ifdef FREEZE_PROCESS_SUPPORT + virtual int32_t FreezeProcess(uint32_t pid, bool freeze, uint32_t timeout) override; + virtual int32_t CheckFreeze(uint32_t pid, bool &isFreeze) override; +#endif // FREEZE_PROCESS_SUPPORT virtual std::shared_ptr WriteTransaction(int cmd, uint32_t flags, int32_t handle, int32_t socketId, uint32_t code, MessageParcel &data, uint64_t &seqNumber, int status); virtual int SendOrWaitForCompletion(int userWaitTime, uint64_t seqNumber, std::shared_ptr sessionOfPeer, @@ -111,7 +115,6 @@ public: void PrintDBinderTransaction(const char *funcName, const char *titleName, const dbinder_transaction_data *tr); void PrintBuffer(const char *funcName, const char *titleName, const uint8_t *data, size_t length); void PrintDBinderTransData(const dbinder_transaction_data *transData, uint32_t dataLen); - private: uint32_t TranslateBinderType(flat_binder_object *binderObject, unsigned char *sessionOffset, std::shared_ptr session); diff --git a/ipc/native/src/core/dbinder/include/dbinder_base_invoker_interface.h b/ipc/native/src/core/dbinder/include/dbinder_base_invoker_interface.h index 937e96e6..1adc766c 100644 --- a/ipc/native/src/core/dbinder/include/dbinder_base_invoker_interface.h +++ b/ipc/native/src/core/dbinder/include/dbinder_base_invoker_interface.h @@ -200,6 +200,20 @@ template void DBinderBaseInvoker::FreeBuffer(void *data) return; } +#ifdef FREEZE_PROCESS_SUPPORT +template +int32_t bool DBinderBaseInvoker::FreezeProcess(uint32_t pid, bool freeze, uint32_t timeout) +{ + return ERR_NONE; +} + +template +int32_t bool DBinderBaseInvoker::CheckFreeze(uint32_t pid, bool &isFreeze) +{ + return ERR_NONE; +} +#endif // FREEZE_PROCESS_SUPPORT + template bool DBinderBaseInvoker::CheckTransactionData(const dbinder_transaction_data *tr) const { if (tr->sizeOfSelf == 0 || tr->sizeOfSelf > SOCKET_MAX_BUFF_SIZE || tr->buffer_size > SOCKET_MAX_BUFF_SIZE || diff --git a/ipc/native/src/core/framework/source/ipc_skeleton.cpp b/ipc/native/src/core/framework/source/ipc_skeleton.cpp index a0ecd644..94c93f85 100644 --- a/ipc/native/src/core/framework/source/ipc_skeleton.cpp +++ b/ipc/native/src/core/framework/source/ipc_skeleton.cpp @@ -330,6 +330,7 @@ uint32_t IPCSkeleton::GetDCallingTokenID() return static_cast(GetSelfTokenID()); } +#ifdef FREEZE_PROCESS_SUPPORT int32_t IPCSkeleton::FreezeProcess(uint32_t pid, bool freeze, uint32_t timeout) { IRemoteInvoker *invoker = IPCThreadSkeleton::GetDefaultInvoker(); @@ -347,6 +348,7 @@ int32_t IPCSkeleton::CheckFreeze(uint32_t pid, bool &isFreeze) } return invoker->CheckFreeze(pid, isFreeze); } +#endif // FREEZE_PROCESS_SUPPORT void IPCDfx::BlockUntilThreadAvailable() { diff --git a/ipc/native/src/core/invoker/include/iremote_invoker.h b/ipc/native/src/core/invoker/include/iremote_invoker.h index 2dff97b7..3d5753f9 100644 --- a/ipc/native/src/core/invoker/include/iremote_invoker.h +++ b/ipc/native/src/core/invoker/include/iremote_invoker.h @@ -51,9 +51,11 @@ public: virtual int SendRequest(int handle, uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) = 0; +#ifdef FREEZE_PROCESS_SUPPORT virtual int32_t FreezeProcess(uint32_t pid, bool freeze, uint32_t timeout) = 0; virtual int32_t CheckFreeze(uint32_t pid, bool &isFreeze) = 0; +#endif // FREEZE_PROCESS_SUPPORT virtual bool AddDeathRecipient(int32_t handle, void *cookie) = 0; diff --git a/ipc/native/src/core/invoker/source/binder_invoker.cpp b/ipc/native/src/core/invoker/source/binder_invoker.cpp index ceda2dc6..f96a87ae 100644 --- a/ipc/native/src/core/invoker/source/binder_invoker.cpp +++ b/ipc/native/src/core/invoker/source/binder_invoker.cpp @@ -737,12 +737,13 @@ int32_t BinderInvoker::SamgrServiceSendRequest( return error; } +#ifdef FREEZE_PROCESS_SUPPORT int32_t BinderInvoker::FreezeProcess(uint32_t pid, bool freeze, uint32_t timeout) { if ((binderConnector_ == nullptr) || (!binderConnector_->IsDriverAlive())) { return IPC_INVOKER_CONNECT_ERR; } - binder_freeze_info info{}; + binder_freeze_info info; info.enable = pid; info.enable = freeze; info.timeout_ms = timeout; @@ -759,7 +760,7 @@ int32_t BinderInvoker::CheckFreeze(uint32_t pid, bool &isFreeze) if ((binderConnector_ == nullptr) || (!binderConnector_->IsDriverAlive())) { return IPC_INVOKER_CONNECT_ERR; } - binder_frozen_state_info info{}; + binder_frozen_state_info info; info.pid = pid; info.has_unfrozen = false; int error = binderConnector_->WriteBinder(BINDER_GET_FROZEN_STATE, &info); @@ -770,6 +771,7 @@ int32_t BinderInvoker::CheckFreeze(uint32_t pid, bool &isFreeze) isFreeze = !info.has_unfrozen; return ERR_NONE; } +#endif // FREEZE_PROCESS_SUPPORT int32_t BinderInvoker::GeneralServiceSendRequest( const binder_transaction_data &tr, MessageParcel &data, MessageParcel &reply, MessageOption &option) @@ -1260,10 +1262,16 @@ void BinderInvoker::DealWithCmd(MessageParcel *reply, bool &continueLoop, int32_ { switch (cmd) { case BR_TRANSACTION_COMPLETE: +#ifdef FREEZE_PROCESS_SUPPORT + case BR_TRANSACTION_PENDING_FROZEN: +#endif // FREEZE_PROCESS_SUPPORT OnTransactionComplete(reply, continueLoop, error, cmd); break; case BR_DEAD_REPLY: case BR_FAILED_REPLY: +#ifdef FREEZE_PROCESS_SUPPORT + case BR_FROZEN_REPLY: +#endif // FREEZE_PROCESS_SUPPORT OnDeadOrFailedReply(reply, continueLoop, error, cmd); break; case BR_FROZEN_REPLY: diff --git a/ipc/native/test/unittest/common/BUILD.gn b/ipc/native/test/unittest/common/BUILD.gn index f894a221..699de142 100644 --- a/ipc/native/test/unittest/common/BUILD.gn +++ b/ipc/native/test/unittest/common/BUILD.gn @@ -62,6 +62,10 @@ template("ipc_unittest") { "samgr:samgr_proxy", ] + if (ipc_freeze_process_support) { + defines = ["FREEZE_PROCESS_SUPPORT"] + } + if (hiviewdfx_hisysevent_support) { external_deps += [ "hisysevent:libhisysevent" ] } diff --git a/ipc/native/test/unittest/common/binder_invoker_unittest.cpp b/ipc/native/test/unittest/common/binder_invoker_unittest.cpp index 62abcbbd..48113a26 100644 --- a/ipc/native/test/unittest/common/binder_invoker_unittest.cpp +++ b/ipc/native/test/unittest/common/binder_invoker_unittest.cpp @@ -832,11 +832,12 @@ HWTEST_F(BinderInvokerUnitTest, GetInvocationStateTest001, TestSize.Level1) EXPECT_EQ(binderInvoker.GetInvocationState(), STATUS_FIRST_INVOKE); } +#ifdef FREEZE_PROCESS_SUPPORT /** - * @tc.name: FreezeProcessTest001 - * @tc.desc: cover FreezeProcess branch - * @tc.type: FUNC - */ +* @tc.name: FreezeProcessTest001 +* @tc.desc: cover FreezeProcess branch +* @tc.type: FUNC +*/ HWTEST_F(BinderInvokerUnitTest, FreezeProcessTest, TestSize.Level1) { BinderInvoker binderInvoker; @@ -850,12 +851,12 @@ HWTEST_F(BinderInvokerUnitTest, FreezeProcessTest, TestSize.Level1) } /** - * @tc.name: CheckFreezeTest - * @tc.desc: cover CheckFreeze branch - * @tc.type: FUNC - */ - HWTEST_F(BinderInvokerUnitTest, CheckFreezeTest, TestSize.Level1) - { +* @tc.name: CheckFreezeTest +* @tc.desc: cover CheckFreeze branch +* @tc.type: FUNC +*/ +HWTEST_F(BinderInvokerUnitTest, CheckFreezeTest, TestSize.Level1) +{ bool isFreeze = false; BinderInvoker binderInvoker; binderInvoker.binderConnector_ = nullptr; @@ -865,5 +866,6 @@ HWTEST_F(BinderInvokerUnitTest, FreezeProcessTest, TestSize.Level1) binderConnector->driverFD_ = -1; binderInvoker.binderConnector_ = binderConnector; EXPECT_EQ(binderInvoker.CheckFreeze(1, isFreeze), IPC_INVOKER_CONNECT_ERR); - } +} +#endif // FREEZE_PROCESS_SUPPORT } // namespace OHOS \ No newline at end of file diff --git a/ipc/native/test/unittest/common/ipc_skeleton_unittest.cpp b/ipc/native/test/unittest/common/ipc_skeleton_unittest.cpp index 572be748..8e35ca66 100644 --- a/ipc/native/test/unittest/common/ipc_skeleton_unittest.cpp +++ b/ipc/native/test/unittest/common/ipc_skeleton_unittest.cpp @@ -908,6 +908,7 @@ HWTEST_F(IPCSkeletonTest, GetDCallingTokenIDInRPC, TestSize.Level1) ASSERT_EQ(tokenId, 0); } +#ifdef FREEZE_PROCESS_SUPPORT /** * @tc.name: FreezeProcessTest * @tc.desc: Verify the FreezeProcess function. @@ -960,5 +961,5 @@ HWTEST_F(IPCSkeletonTest, CheckFreezeTest, TestSize.Level1) delete binderInvoker; delete dbinderInvoker; } - +#endif // FREEZE_PROCESS_SUPPORT } // namespace OHOS \ No newline at end of file diff --git a/ipc/native/test/unittest/common/mock_iremote_invoker.h b/ipc/native/test/unittest/common/mock_iremote_invoker.h index d4c9004a..e0402d68 100644 --- a/ipc/native/test/unittest/common/mock_iremote_invoker.h +++ b/ipc/native/test/unittest/common/mock_iremote_invoker.h @@ -41,8 +41,10 @@ public: MOCK_METHOD3(SendReply, int(MessageParcel &reply, uint32_t flags, int32_t result)); MOCK_METHOD5(SendRequest, int(int handle, uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)); +#ifdef FREEZE_PROCESS_SUPPORT MOCK_METHOD3(FreezeProcess, int32_t(uint32_t pid, bool freeze, uint32_t timeout)); MOCK_METHOD2(CheckFreeze, int32_t(uint32_t pid, bool &isFreeze)); +#endif // FREEZE_PROCESS_SUPPORT MOCK_METHOD2(AddDeathRecipient, bool(int32_t handle, void *cookie)); MOCK_METHOD2(RemoveDeathRecipient, bool(int32_t handle, void *cookie)); MOCK_METHOD1(SetMaxWorkThread, bool(int maxThreadNum)); diff --git a/ipc/test/auxiliary/native/BUILD.gn b/ipc/test/auxiliary/native/BUILD.gn index 8832a75c..e5d4b12a 100644 --- a/ipc/test/auxiliary/native/BUILD.gn +++ b/ipc/test/auxiliary/native/BUILD.gn @@ -11,6 +11,7 @@ # See the License for the specific language governing permissions and # limitations under the License. import("//build/ohos.gni") +import("//foundation/communication/ipc/config.gni") SUBSYSTEM_DIR = "//foundation/communication/ipc" IPC_CORE_ROOT = "$SUBSYSTEM_DIR/ipc/native" @@ -31,6 +32,10 @@ ohos_shared_library("ipc_test_helper") { "./src/test_service_stub.cpp", ] + if (ipc_freeze_process_support) { + defines = [ "FREEZE_PROCESS_SUPPORT" ] + } + configs = [ "$IPC_TEST_ROOT:ipc_test_config", "$SUBSYSTEM_DIR/config:ipc_util_config", @@ -90,6 +95,10 @@ ohos_executable("ipc_client_test") { "$SUBSYSTEM_DIR/interfaces/innerkits/c_api:ipc_capi", ] + if (ipc_freeze_process_support) { + defines = [ "FREEZE_PROCESS_SUPPORT" ] + } + external_deps = [ "access_token:libnativetoken_shared", "access_token:libtokensetproc_shared", @@ -125,6 +134,10 @@ ohos_shared_library("ipc_test_helper_extra") { "$SUBSYSTEM_DIR/config:ipc_util_config", ] + if (ipc_freeze_process_support) { + defines = [ "FREEZE_PROCESS_SUPPORT" ] + } + deps = [ "$SUBSYSTEM_DIR/interfaces/innerkits/c_api:ipc_capi", "$SUBSYSTEM_DIR/interfaces/innerkits/ipc_single:ipc_single_test", diff --git a/ipc/test/auxiliary/native/include/test_service.h b/ipc/test/auxiliary/native/include/test_service.h index aa770f9b..a522e2af 100644 --- a/ipc/test/auxiliary/native/include/test_service.h +++ b/ipc/test/auxiliary/native/include/test_service.h @@ -56,8 +56,9 @@ public: int TestSendTooManyRequest(int data, int &reply) override; int TestMultiThreadSendRequest(int data, int &reply) override; int TestQueryThreadInvocationState() override; +#ifdef FREEZE_PROCESS_SUPPORT int TestFreezeProcess() override; - int TestFreezeProcessAsyncReq() override; +#endif // FREEZE_PROCESS_SUPPORT private: int testFd_; std::mutex remoteObjectsMutex_; diff --git a/ipc/test/auxiliary/native/include/test_service_base.h b/ipc/test/auxiliary/native/include/test_service_base.h index 8b7e8bcd..e0670ca3 100644 --- a/ipc/test/auxiliary/native/include/test_service_base.h +++ b/ipc/test/auxiliary/native/include/test_service_base.h @@ -89,8 +89,9 @@ public: virtual int TestSendTooManyRequest(int data, int &reply) = 0; virtual int TestMultiThreadSendRequest(int data, int &reply) = 0; virtual int TestQueryThreadInvocationState() = 0; +#ifdef FREEZE_PROCESS_SUPPORT virtual int TestFreezeProcess() = 0; - virtual int TestFreezeProcessAsyncReq() = 0; +#endif // FREEZE_PROCESS_SUPPORT public: DECLARE_INTERFACE_DESCRIPTOR(u"test.ipc.ITestService"); diff --git a/ipc/test/auxiliary/native/include/test_service_client.h b/ipc/test/auxiliary/native/include/test_service_client.h index 605e805d..bc22e773 100644 --- a/ipc/test/auxiliary/native/include/test_service_client.h +++ b/ipc/test/auxiliary/native/include/test_service_client.h @@ -45,6 +45,9 @@ public: bool TestUnRegisterRemoteStub(); bool TestSendTooManyRequest(); bool TestMultiThreadSendRequest(); +#ifdef FREEZE_PROCESS_SUPPORT + int TestFreezeProcess(); +#endif // FREEZE_PROCESS_SUPPORT bool TestQueryThreadInvocationState(); private: diff --git a/ipc/test/auxiliary/native/include/test_service_proxy.h b/ipc/test/auxiliary/native/include/test_service_proxy.h index c6334114..15d0cd67 100644 --- a/ipc/test/auxiliary/native/include/test_service_proxy.h +++ b/ipc/test/auxiliary/native/include/test_service_proxy.h @@ -51,6 +51,9 @@ public: sptr TestQueryRemoteProxy(const char *descriptor) override; int TestSendTooManyRequest(int data, int &reply) override; int TestMultiThreadSendRequest(int data, int &reply) override; +#ifdef FREEZE_PROCESS_SUPPORT + int TestFreezeProcess() override; +#endif // FREEZE_PROCESS_SUPPORT int TestQueryThreadInvocationState() override; private: diff --git a/ipc/test/auxiliary/native/include/test_service_stub.h b/ipc/test/auxiliary/native/include/test_service_stub.h index c7bda112..32bdfaa8 100644 --- a/ipc/test/auxiliary/native/include/test_service_stub.h +++ b/ipc/test/auxiliary/native/include/test_service_stub.h @@ -50,8 +50,9 @@ private: int32_t QueryRemoteProxy(MessageParcel &data, MessageParcel &reply); int32_t ServerFlushAsyncCalls(MessageParcel &data, MessageParcel &reply); int32_t ServerThreadInvocationState(MessageParcel &data, MessageParcel &reply); +#ifdef FREEZE_PROCESS_SUPPORT int32_t ServerTestFreezeProcess(MessageParcel &data, MessageParcel &reply); - int32_t ServerTxnAsyncTransaction(MessageParcel &data, MessageParcel &reply); +#endif // FREEZE_PROCESS_SUPPORT void InitMessageProcessMap(); using TestServiceStubFunc = int32_t(TestServiceStub::*)(MessageParcel &data, MessageParcel &reply); diff --git a/ipc/test/auxiliary/native/src/main_client.cpp b/ipc/test/auxiliary/native/src/main_client.cpp index 45e15289..e5d66bc5 100644 --- a/ipc/test/auxiliary/native/src/main_client.cpp +++ b/ipc/test/auxiliary/native/src/main_client.cpp @@ -82,6 +82,7 @@ void TestCaseSyncTrans(std::shared_ptr &testClient) } } +#ifdef FREEZE_PROCESS_SUPPORT void TestCaseFreezeProcess(std::shared_ptr &testClient) { bool ret = testClient->TestFreezeProcess(); @@ -91,16 +92,8 @@ void TestCaseFreezeProcess(std::shared_ptr &testClient) std::cout << "[PASS] Execution of TestFreezeProcess case Successful" < &testClient) -{ - bool ret = testClient->TestFreezeProcessAsyncReq(); - if (!ret) { - std::cout << "[FAILED] Execution of TestCaseFreezeProcessAsyncReq case failed" < &testClient) { bool ret = testClient->StartPingService(); @@ -248,8 +241,9 @@ void ExecuteAllTestCase() TestCaseRegisterRemoteStub(testClient); TestCaseTooManyRequests(testClient); TestCaseMultiThreadSendRequest(testClient); +#ifdef FREEZE_PROCESS_SUPPORT TestCaseFreezeProcess(testClient); - TestCaseFreezeProcessAsyncReq(testClient); +#endif // FREEZE_PROCESS_SUPPORT ZLOGI(LABEL, "All test cases have been executed"); } diff --git a/ipc/test/auxiliary/native/src/test_service.cpp b/ipc/test/auxiliary/native/src/test_service.cpp index 7bffefc3..379b2695 100644 --- a/ipc/test/auxiliary/native/src/test_service.cpp +++ b/ipc/test/auxiliary/native/src/test_service.cpp @@ -346,13 +346,10 @@ int TestService::TestQueryThreadInvocationState() return state; } +#ifdef FREEZE_PROCESS_SUPPORT int TestService::TestFreezeProcess() { return 0; } - -int TestService::TestFreezeprocessAsyncReq() -{ - return 0; -} +#endif // FREEZE_PROCESS_SUPPORT } // namespace OHOS diff --git a/ipc/test/auxiliary/native/src/test_service_client.cpp b/ipc/test/auxiliary/native/src/test_service_client.cpp index 030a29d3..479c965f 100644 --- a/ipc/test/auxiliary/native/src/test_service_client.cpp +++ b/ipc/test/auxiliary/native/src/test_service_client.cpp @@ -74,6 +74,7 @@ bool TestServiceClient::StartSyncTransaction() return true; } +#ifdef FREEZE_PROCESS_SUPPORT bool TestServiceClient::TestFreezeProcess() { if (testService_ == nullptr) { @@ -88,21 +89,7 @@ bool TestServiceClient::TestFreezeProcess() } return true; } - -bool TestServiceClient::TestFreezeprocessAsyncReq() -{ - if (testService_ == nullptr) { - ZLOGE(LABEL, "The testService_ object is an empty object"); - return false; - } - - int ret = testService_->TestFreezeProcessAsyncReq(); - if (ret != 0) { - ZLOGE(LABEL, "TestFreezeProcessAsyncReq function call failed"); - return false; - } - return true; -} +#endif // FREEZE_PROCESS_SUPPORT bool TestServiceClient::StartPingService() { diff --git a/ipc/test/auxiliary/native/src/test_service_proxy.cpp b/ipc/test/auxiliary/native/src/test_service_proxy.cpp index a0c68464..10ed413a 100644 --- a/ipc/test/auxiliary/native/src/test_service_proxy.cpp +++ b/ipc/test/auxiliary/native/src/test_service_proxy.cpp @@ -97,6 +97,7 @@ int TestServiceProxy::TestSyncTransaction(int value, int &reply, int delayTime) return ret; } +#ifdef FREEZE_PROCESS_SUPPORT int TestServiceProxy::TestFreezeProcess() { ZLOGI(LABEL, "TestFreezeProcess"); @@ -140,90 +141,7 @@ int TestServiceProxy::TestFreezeProcess() ZLOGI(LABEL, "TestFreezeProcess success"); return 0; } - -int TestServiceProxy::TestFreezeProcessAcyncReq() -{ - ZLOGI(LABEL, "TestFreezeProcessAcyncReq"); - - auto remote = Remote(); - if (remote == nullptr) { - ZLOGI(LABEL, "The obtained proxy is a null pointer"); - return -1; - } - - MessageOption option; - MessageParcel dataParcel; - MessageParcel replyParcel; - int timeout = 1000; - - int ret = remote->SendRequest(TRANS_ID_TEST_FREEZE_PROCESS, dataParcel, replyParcel, option); - if (ret != ERR_NONE) { - ZLOGI(LABEL, "SendRequest failed, error code = %{public}d", ret); - return -1; - } - int pid = replyParcel.ReadInt32(); - ZLOGI(LABEL, "Get pid from server, server pid = %{public}d", pid); - - ret = IPCSkeleton::FreezeProcess(pid, true, timeout); - if (ret != ERR_NONE) { - ZLOGI(LABEL, "FreezeProcess failed, error code = %{public}d", ret); - return ret; - } - - enum ReplyStatus { - NO_REPLY = 0, - DATA_NOT_UPDATAED = 1, - DATA_UPDATAED = 2, - }; - - // TF_ASYNC 1 - MessageOption option1 = { MessageOption::TF_ASYNC }; - MessageParcel dataParcel1; - MessageParcel replyParcel1; - dataParcel1.WriteInt32(static_cast(ReplyStatus::DATA_NOT_UPDATAED)); - sptr fooCallback1 = new FooStub(); - dataParcel1.WriteRemoteObject(fooCallback1); - ret = remote->SendRequest(TRANS_ID_TEST_TXN_ASYNC_TRANS, dataParcel1, replyParcel1, option1); - if (ret != ERR_NONE) { - ZLOGI(LABEL, "SendRequest failed, error code = %{public}d", ret); - return -1; - } - std::future fut1 = std::async(std::launch::async, WaitForReply, std::ref(fooCallback1), timeout); - - - // TF_ASYNC 2 - MessageOption option2 = { MessageOption::TF_UPDATE_TXN }; - MessageParcel dataParcel2; - MessageParcel replyParcel2; - dataParcel2.WriteInt32(static_cast(ReplyStatus::DATA_UPDATAED)); - sptr fooCallback2 = new FooStub(); - dataParcel2.WriteRemoteObject(fooCallback2); - ret = remote->SendRequest(TRANS_ID_TEST_TXN_ASYNC_TRANS, dataParcel2, replyParcel2, option2); - if (ret != ERR_NONE) { - ZLOGI(LABEL, "SendRequest failed, error code = %{public}d", ret); - return -1; - } - std::future fut2 = std::async(std::launch::async, WaitForReply, std::ref(fooCallback2), timeout); - - // unfreeze - IPCSkeleton::FreezeProcess(pid, false, 0); - - // wait for reply - int32_t reply1 = fut1.get(); - int32_t reply2 = fut2.get(); - if (reply1 != ReplyStatus::NO_REPLY || reply2 != DATA_UPDATAED) { - ZLOGI(LABEL, "TestFreezeProcessAcyncReq failed"); - return -1; - } - - return 0; -} -static int WaitForReply(sptr &fooCallback, int timeout) -{ - return fooCallback->WaitForAsyncReply(timeout); -} - - +#endif // FREEZE_PROCESS_SUPPORT int TestServiceProxy::TestSendTooManyRequest(int data, int &reply) { diff --git a/ipc/test/auxiliary/native/src/test_service_stub.cpp b/ipc/test/auxiliary/native/src/test_service_stub.cpp index 93d32728..549216b6 100644 --- a/ipc/test/auxiliary/native/src/test_service_stub.cpp +++ b/ipc/test/auxiliary/native/src/test_service_stub.cpp @@ -72,6 +72,9 @@ void TestServiceStub::InitMessageProcessMap() funcMap_[static_cast(TRANS_ID_UNREGISTER_REMOTE_STUB_OBJECT)] = &TestServiceStub::UnRegisterRemoteStub; funcMap_[static_cast(TRANS_ID_QUERY_REMOTE_PROXY_OBJECT)] = &TestServiceStub::QueryRemoteProxy; funcMap_[static_cast(TRANS_ID_QUERY_THREAD_INVOCATION_STATE)] = &TestServiceStub::ServerThreadInvocationState; +#ifdef FREEZE_PROCESS_SUPPORT + funcMap_[static_cast(TRANS_ID_TEST_FREEZE_PROCESS)] = &TestServiceStub::ServerTestFreezeProcess; +#endif // FREEZE_PROCESS_SUPPORT } int32_t TestServiceStub::ServerSyncTransaction(MessageParcel &data, MessageParcel &reply) @@ -484,19 +487,11 @@ int32_t TestServiceStub::ServerThreadInvocationState(MessageParcel &data, Messag return ret; } +#ifdef FREEZE_PROCESS_SUPPORT int32_t TestServiceStub::ServerTestFreezeProcess(MessageParcel &data, MessageParcel &reply) { reply.WriteInt32(getpid()); return 0; } - -int32_t TestServiceStub::ServerTxnAsyncTransaction(MessageParcel &data, MessageParcel &reply) -{ - int32_t retData = data.ReadInt32(); - sptr fooProxy = iface_cast(data.ReadRemoteObject()); - if (fooProxy != nullptr) { - fooProxy->SendAsyncReply(retData); - } - return 0; -} +#endif // FREEZE_PROCESS_SUPPORT } // namespace OHOS diff --git a/test/unittest/ipc/native/src/core/source/BUILD.gn b/test/unittest/ipc/native/src/core/source/BUILD.gn index 8236f82c..c843dc2d 100644 --- a/test/unittest/ipc/native/src/core/source/BUILD.gn +++ b/test/unittest/ipc/native/src/core/source/BUILD.gn @@ -64,6 +64,10 @@ template("ipc_unittest") { "samgr:samgr_proxy", ] + if (ipc_freeze_process_support) { + defines += [ "FREEZE_PROCESS_SUPPORT" ] + } + if (hiviewdfx_hisysevent_support) { external_deps += [ "hisysevent:libhisysevent" ] } diff --git a/test/unittest/mock/mock_iremote_invoker.h b/test/unittest/mock/mock_iremote_invoker.h index 6c048baf..bb2d41a6 100644 --- a/test/unittest/mock/mock_iremote_invoker.h +++ b/test/unittest/mock/mock_iremote_invoker.h @@ -41,8 +41,10 @@ public: MOCK_METHOD3(SendReply, int(MessageParcel &reply, uint32_t flags, int32_t result)); MOCK_METHOD5(SendRequest, int(int handle, uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)); +#ifdef FREEZE_PROCESS_SUPPORT MOCK_METHOD3(FreezeProcess, int32_t(uint32_t pid, bool freeze, uint32_t timeout)); MOCK_METHOD2(CheckFreeze, int32_t(uint32_t pid, bool &isFreeze)); +#endif // FREEZE_PROCESS_SUPPORT MOCK_METHOD2(AddDeathRecipient, bool(int32_t handle, void *cookie)); MOCK_METHOD2(RemoveDeathRecipient, bool(int32_t handle, void *cookie)); MOCK_METHOD1(SetMaxWorkThread, bool(int maxThreadNum)); -- Gitee From ff6e7ef7002bb817d2549c3b0155d51dd09b09d1 Mon Sep 17 00:00:00 2001 From: dengliang <15934868816@139.com> Date: Wed, 3 Sep 2025 15:09:27 +0800 Subject: [PATCH 3/4] freeze process Signed-off-by: dengliang <15934868816@139.com> --- .../dbinder/include/dbinder_base_invoker_define.h | 1 + .../dbinder/include/dbinder_base_invoker_interface.h | 12 ------------ ipc/native/src/core/invoker/include/binder_invoker.h | 2 ++ 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/ipc/native/src/core/dbinder/include/dbinder_base_invoker_define.h b/ipc/native/src/core/dbinder/include/dbinder_base_invoker_define.h index 2b6d05ed..fe6add34 100644 --- a/ipc/native/src/core/dbinder/include/dbinder_base_invoker_define.h +++ b/ipc/native/src/core/dbinder/include/dbinder_base_invoker_define.h @@ -115,6 +115,7 @@ public: void PrintDBinderTransaction(const char *funcName, const char *titleName, const dbinder_transaction_data *tr); void PrintBuffer(const char *funcName, const char *titleName, const uint8_t *data, size_t length); void PrintDBinderTransData(const dbinder_transaction_data *transData, uint32_t dataLen); + private: uint32_t TranslateBinderType(flat_binder_object *binderObject, unsigned char *sessionOffset, std::shared_ptr session); diff --git a/ipc/native/src/core/dbinder/include/dbinder_base_invoker_interface.h b/ipc/native/src/core/dbinder/include/dbinder_base_invoker_interface.h index 1adc766c..e179c402 100644 --- a/ipc/native/src/core/dbinder/include/dbinder_base_invoker_interface.h +++ b/ipc/native/src/core/dbinder/include/dbinder_base_invoker_interface.h @@ -120,18 +120,6 @@ int DBinderBaseInvoker::SendRequest(int32_t handle, uint32_t code, MessagePar return ret; } -template -int32_t DBinderBaseInvoker::FreezeProcess(uint32_t pid, bool freeze, uint32_t timeout) -{ - return ERR_NONE; -} - -template -int32_t DBinderBaseInvoker::CheckFreeze(uint32_t pid, bool &isFreeze) -{ - return ERR_NONE; -} - template bool DBinderBaseInvoker::SetMaxWorkThread(int maxThreadNum) { return true; diff --git a/ipc/native/src/core/invoker/include/binder_invoker.h b/ipc/native/src/core/invoker/include/binder_invoker.h index 58221dc8..d2362351 100644 --- a/ipc/native/src/core/invoker/include/binder_invoker.h +++ b/ipc/native/src/core/invoker/include/binder_invoker.h @@ -90,9 +90,11 @@ public: int SendRequest(int handle, uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; +#ifdef FREEZE_PROCESS_SUPPORT int32_t FreezeProcess(uint32_t pid, bool freeze, uint32_t timeout) override; int32_t CheckFreeze(uint32_t pid, bool &isFreeze) override; +#endif // FREEZE_PROCESS_SUPPORT int SendReply(MessageParcel &reply, uint32_t flags, int32_t result) override; -- Gitee From 2b4dc9ddad50931fb9ab91860b3beadd28714739 Mon Sep 17 00:00:00 2001 From: dengliang <15934868816@139.com> Date: Wed, 3 Sep 2025 15:56:21 +0800 Subject: [PATCH 4/4] freeze process Signed-off-by: dengliang <15934868816@139.com> --- ipc/native/src/core/invoker/source/binder_invoker.cpp | 4 ---- .../core/binderinvokernew_fuzzer/binderinvokernew_fuzzer.cpp | 1 - 2 files changed, 5 deletions(-) diff --git a/ipc/native/src/core/invoker/source/binder_invoker.cpp b/ipc/native/src/core/invoker/source/binder_invoker.cpp index f96a87ae..94ab240c 100644 --- a/ipc/native/src/core/invoker/source/binder_invoker.cpp +++ b/ipc/native/src/core/invoker/source/binder_invoker.cpp @@ -1274,11 +1274,7 @@ void BinderInvoker::DealWithCmd(MessageParcel *reply, bool &continueLoop, int32_ #endif // FREEZE_PROCESS_SUPPORT OnDeadOrFailedReply(reply, continueLoop, error, cmd); break; - case BR_FROZEN_REPLY: - OnDeadOrFailedReply(reply, continueLoop, error, cmd); - break; case BR_REPLY: - case BR_TRANSACTION_PENDING_FROZEN: OnReply(reply, continueLoop, error, cmd); break; default: diff --git a/test/fuzztest/ipc/native/src/core/binderinvokernew_fuzzer/binderinvokernew_fuzzer.cpp b/test/fuzztest/ipc/native/src/core/binderinvokernew_fuzzer/binderinvokernew_fuzzer.cpp index 89196cb9..57467c55 100644 --- a/test/fuzztest/ipc/native/src/core/binderinvokernew_fuzzer/binderinvokernew_fuzzer.cpp +++ b/test/fuzztest/ipc/native/src/core/binderinvokernew_fuzzer/binderinvokernew_fuzzer.cpp @@ -44,7 +44,6 @@ static const std::vector cmdList = { binder_driver_return_protocol::BR_DEAD_BINDER, binder_driver_return_protocol::BR_CLEAR_DEATH_NOTIFICATION_DONE, binder_driver_return_protocol::BR_FAILED_REPLY, - binder_driver_return_protocol::BR_RELEASE_NODE, }; static const std::vector binderTypeList = { BINDER_TYPE_BINDER, -- Gitee