diff --git a/bundle.json b/bundle.json index 9c9b4e074c57fcc3ed05c3d3c99872989ec12529..33457e07115e3a22605d69759ae13b8913c5fed3 100644 --- a/bundle.json +++ b/bundle.json @@ -23,7 +23,8 @@ "features": [ "ipc_feature_rpc_enabled", "ipc_feature_test_enabled", - "ipc_feature_trace_enabled" + "ipc_feature_trace_enabled", + "ipc_feature_freeze_enabled" ], "syscap":[ "SystemCapability.Communication.IPC.Core" diff --git a/config.gni b/config.gni index bf6ea89d5e4db387c541611b8956b9a55862c6f6..d154289a134383f477eaa7abb14acfe9dd294681 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_feature_freeze_enabled = false } if (defined(global_parts_info) && @@ -43,4 +44,4 @@ if (defined(global_parts_info) && if (defined(global_parts_info) && defined(global_parts_info.hiviewdfx_hisysevent)) { hiviewdfx_hisysevent_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 a19a0e7996b64a0a2e0274bec0a0192064a5f1bf..010e919db95bcf83803c9f4a27add394932ab172 100644 --- a/interfaces/innerkits/ipc_core/include/ipc_skeleton.h +++ b/interfaces/innerkits/ipc_core/include/ipc_skeleton.h @@ -207,6 +207,31 @@ public: * @since 20 */ static uint32_t GetDCallingTokenID(); + +#ifdef FREEZE_PROCESS_ENABLED + /** + * @brief Freeze binder transaction of the specific 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 Freeze(uint32_t pid, bool freeze, uint32_t timeout); + + /** + * @brief Get binder transaction freeze status of the specific process. + * @param pid Process ID to check. + * @param isFrozen 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 GetProcessFreezeInfo(uint32_t pid, bool &isFrozen); +#endif // FREEZE_PROCESS_ENABLED }; class IPCDfx { diff --git a/interfaces/innerkits/ipc_core/include/message_option.h b/interfaces/innerkits/ipc_core/include/message_option.h index bd9f222fe7c2bb19d9681e26212281b8676309c4..0fe51ff64d759ced062ecc0e19da0221b8a0434e 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/interfaces/innerkits/ipc_single/BUILD.gn b/interfaces/innerkits/ipc_single/BUILD.gn index 497d8b40c6f8e9cbe452d90d0bdca6f9317fe4bd..b81c1be862d6a2a79b4714245508028e1a763b11 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_feature_freeze_enabled) { + defines += [ "FREEZE_PROCESS_ENABLED" ] + } innerapi_tags = [ "chipsetsdk", "platformsdk", @@ -164,6 +167,9 @@ ohos_shared_library("ipc_single_test") { if (hiviewdfx_hisysevent_support) { defines += [ "HIVIEWDFX_HISYSEVENT_SUPPORT" ] } + if (ipc_feature_freeze_enabled) { + defines += [ "FREEZE_PROCESS_ENABLED" ] + } 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 157db0e7728d928026372b0bfefa8af4368a7bc0..609f69cfdd05f9b1b97a4ea03b7f5dd2077103bb 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_ENABLED + virtual int32_t Freeze(uint32_t pid, bool freeze, uint32_t timeout) override; + virtual int32_t GetProcessFreezeInfo(uint32_t pid, bool &isFrozen) override; +#endif // FREEZE_PROCESS_ENABLED 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, 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 7561c06a6bfc6634e6c0ad54f704dc5290b40b59..e643cb64e8f91bbb0551e54affffa7e94ab3eafb 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 @@ -188,6 +188,20 @@ template void DBinderBaseInvoker::FreeBuffer(void *data) return; } +#ifdef FREEZE_PROCESS_ENABLED +template +int32_t DBinderBaseInvoker::Freeze(uint32_t pid, bool freeze, uint32_t timeout) +{ + return ERR_NONE; +} + +template +int32_t DBinderBaseInvoker::GetProcessFreezeInfo(uint32_t pid, bool &isFreeze) +{ + return ERR_NONE; +} +#endif // FREEZE_PROCESS_ENABLED + 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/include/sys_binder.h b/ipc/native/src/core/framework/include/sys_binder.h index 206e09e698eabe0d64d4df1f0b7e0a7113148bbc..9e9f2bb852ab053b04b809a95e626be56301e720 100644 --- a/ipc/native/src/core/framework/include/sys_binder.h +++ b/ipc/native/src/core/framework/include/sys_binder.h @@ -62,6 +62,19 @@ struct flat_binder_object { }; binder_uintptr_t cookie; }; + +struct binder_freeze_info { + __u32 pid; + __u32 enable; + __u32 timeout_ms; +}; + +struct binder_proc_frozen_state { + __u32 pid; + // false: process is fully frozen, true: process is not fully frozen + bool has_not_frozen; +}; + #ifndef __linux__ #define HMB_ERROR_INFO_LEN 64 struct hmb_detailed_err { @@ -160,6 +173,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_proc_frozen_state) #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 +256,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 7948b69c5910baa26112e0ffd1941fd3db49bb38..f2ccbed2de359627a7f51ec0c8c07064e8dd61e6 100644 --- a/ipc/native/src/core/framework/source/ipc_skeleton.cpp +++ b/ipc/native/src/core/framework/source/ipc_skeleton.cpp @@ -330,6 +330,26 @@ uint32_t IPCSkeleton::GetDCallingTokenID() return static_cast(GetSelfTokenID()); } +#ifdef FREEZE_PROCESS_ENABLED +int32_t IPCSkeleton::Freeze(uint32_t pid, bool freeze, uint32_t timeout) +{ + IRemoteInvoker *invoker = IPCThreadSkeleton::GetDefaultInvoker(); + if (invoker == nullptr) { + return IPC_SKELETON_NULL_OBJECT_ERR; + } + return invoker->Freeze(pid, freeze, timeout); +} + +int32_t IPCSkeleton::GetProcessFreezeInfo(uint32_t pid, bool &isFrozen) +{ + IRemoteInvoker *invoker = IPCThreadSkeleton::GetDefaultInvoker(); + if (invoker == nullptr) { + return IPC_SKELETON_NULL_OBJECT_ERR; + } + return invoker->GetProcessFreezeInfo(pid, isFrozen); +} +#endif // FREEZE_PROCESS_ENABLED + 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 d8743e2bb4b6c8550c036523d51b8f88cf361ebc..c4ad9cfbbf736603e6e43634311a70a5accfc49e 100644 --- a/ipc/native/src/core/invoker/include/binder_invoker.h +++ b/ipc/native/src/core/invoker/include/binder_invoker.h @@ -90,6 +90,12 @@ public: int SendRequest(int handle, uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; +#ifdef FREEZE_PROCESS_ENABLED + int32_t Freeze(uint32_t pid, bool freeze, uint32_t timeout) override; + + int32_t GetProcessFreezeInfo(uint32_t pid, bool &isFrozen) override; +#endif // FREEZE_PROCESS_ENABLED + int SendReply(MessageParcel &reply, uint32_t flags, int32_t result) override; bool FlattenObject(Parcel &parcel, const IRemoteObject *object) const override; @@ -200,6 +206,10 @@ private: void OnTransactionComplete(MessageParcel *reply, bool &continueLoop, int32_t &error, uint32_t cmd); +#ifdef FREEZE_PROCESS_ENABLED + void OnTransactionPendingFrozen(MessageParcel *reply, bool &continueLoop, int32_t &error, uint32_t cmd); +#endif // FREEZE_PROCESS_ENABLED + void OnDeadOrFailedReply(MessageParcel *reply, bool &continueLoop, int32_t &error, uint32_t cmd); void OnReply(MessageParcel *reply, bool &continueLoop, int32_t &error, uint32_t cmd); diff --git a/ipc/native/src/core/invoker/include/iremote_invoker.h b/ipc/native/src/core/invoker/include/iremote_invoker.h index 9feb8517ab665335ed2be1e252b5c9dcbe1f5c24..3ceae6a83c727cd2c2e7079df03e831691bf3f8b 100644 --- a/ipc/native/src/core/invoker/include/iremote_invoker.h +++ b/ipc/native/src/core/invoker/include/iremote_invoker.h @@ -51,6 +51,12 @@ public: virtual int SendRequest(int handle, uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) = 0; +#ifdef FREEZE_PROCESS_ENABLED + virtual int32_t Freeze(uint32_t pid, bool freeze, uint32_t timeout) = 0; + + virtual int32_t GetProcessFreezeInfo(uint32_t pid, bool &isFrozen) = 0; +#endif // FREEZE_PROCESS_ENABLED + 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 d0fded34917be62c17c0b10ad9e418eb771f3906..6f7e1cd6ccc6e87ca26c29a8052046385850e3fb 100644 --- a/ipc/native/src/core/invoker/source/binder_invoker.cpp +++ b/ipc/native/src/core/invoker/source/binder_invoker.cpp @@ -737,6 +737,42 @@ int32_t BinderInvoker::SamgrServiceSendRequest( return error; } +#ifdef FREEZE_PROCESS_ENABLED +int32_t BinderInvoker::Freeze(uint32_t pid, bool freeze, uint32_t timeout) +{ + if ((binderConnector_ == nullptr) || (!binderConnector_->IsDriverAlive())) { + return IPC_INVOKER_CONNECT_ERR; + } + binder_freeze_info info; + info.pid = pid; + info.enable = freeze; + info.timeout_ms = timeout; + int error = binderConnector_->WriteBinder(BINDER_FREEZE, &info); + if (error != ERR_NONE) { + ZLOGE(LABEL, "failed, error:%{public}d", error); + return error; + } + return ERR_NONE; +} + +int32_t BinderInvoker::GetProcessFreezeInfo(uint32_t pid, bool &isFrozen) +{ + if ((binderConnector_ == nullptr) || (!binderConnector_->IsDriverAlive())) { + return IPC_INVOKER_CONNECT_ERR; + } + binder_proc_frozen_state info; + info.pid = pid; + info.has_not_frozen = false; + int error = binderConnector_->WriteBinder(BINDER_GET_FROZEN_STATE, &info); + if (error != ERR_NONE) { + ZLOGE(LABEL, "error:%{public}d", error); + return error; + } + isFrozen = !info.has_not_frozen; + return ERR_NONE; +} +#endif // FREEZE_PROCESS_ENABLED + int32_t BinderInvoker::GeneralServiceSendRequest( const binder_transaction_data &tr, MessageParcel &data, MessageParcel &reply, MessageOption &option) { @@ -1184,6 +1220,19 @@ void BinderInvoker::OnTransactionComplete(MessageParcel *reply, bool &continueLo continueLoop = false; } } + +#ifdef FREEZE_PROCESS_ENABLED +void BinderInvoker::OnTransactionPendingFrozen(MessageParcel *reply, bool &continueLoop, int32_t &error, uint32_t cmd) +{ + (void)error; + (void)cmd; + + if (reply == nullptr) { + continueLoop = false; + } +} +#endif // FREEZE_PROCESS_ENABLED + #ifndef __linux__ bool BinderInvoker::GetDetailedErrorInfo(uint32_t &errorCode, std::string &errDesc) { @@ -1232,8 +1281,16 @@ void BinderInvoker::DealWithCmd(MessageParcel *reply, bool &continueLoop, int32_ case BR_TRANSACTION_COMPLETE: OnTransactionComplete(reply, continueLoop, error, cmd); break; +#ifdef FREEZE_PROCESS_ENABLED + case BR_TRANSACTION_PENDING_FROZEN: + OnTransactionPendingFrozen(reply, continueLoop, error, cmd); + break; +#endif // FREEZE_PROCESS_ENABLED case BR_DEAD_REPLY: case BR_FAILED_REPLY: +#ifdef FREEZE_PROCESS_ENABLED + case BR_FROZEN_REPLY: +#endif // FREEZE_PROCESS_ENABLED OnDeadOrFailedReply(reply, continueLoop, error, cmd); break; case BR_REPLY: diff --git a/ipc/native/test/unittest/common/BUILD.gn b/ipc/native/test/unittest/common/BUILD.gn index f894a22145de6361a498749cd2c4ef60d184e470..97ca7ff1f155d202ee9b427dea9a69faf4b2c17b 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_feature_freeze_enabled) { + defines = ["FREEZE_PROCESS_ENABLED"] + } + 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 f24bce52332dac687b4fbccd95b60a7d1f04ab9e..f5782f3a42d378cf331a044366a0637924bfed53 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,57 @@ HWTEST_F(BinderInvokerUnitTest, GetInvocationStateTest001, TestSize.Level1) binderInvoker.isFirstInvoke_ = STATUS_FIRST_INVOKE; EXPECT_EQ(binderInvoker.GetInvocationState(), STATUS_FIRST_INVOKE); } + +#ifdef FREEZE_PROCESS_ENABLED +/** +* @tc.name: FreezeProcessTest +* @tc.desc: cover Freeze branch +* @tc.type: FUNC +*/ +HWTEST_F(BinderInvokerUnitTest, FreezeProcessTest, TestSize.Level1) +{ + BinderInvoker binderInvoker; + BinderConnector::instance_ = nullptr; + binderInvoker.binderConnector_ = BinderConnector::GetInstance(); + EXPECT_EQ(binderInvoker.Freeze(getpid(), false, 1), ERR_NONE); + + bool isFrozen = false; + EXPECT_EQ(binderInvoker.GetProcessFreezeInfo(1, isFrozen), ERR_NONE); +} + +/** +* @tc.name: FreezeProcessTest001 +* @tc.desc: cover Freeze branch +* @tc.type: FUNC +*/ +HWTEST_F(BinderInvokerUnitTest, FreezeProcessTest001, TestSize.Level1) +{ + BinderInvoker binderInvoker; + binderInvoker.binderConnector_ = nullptr; + EXPECT_EQ(binderInvoker.Freeze(1, true, 1), IPC_INVOKER_CONNECT_ERR); + + BinderConnector *binderConnector = BinderConnector::GetInstance(); + binderConnector->driverFD_ = -1; + binderInvoker.binderConnector_ = binderConnector; + EXPECT_EQ(binderInvoker.Freeze(1, true, 1), IPC_INVOKER_CONNECT_ERR); +} + +/** +* @tc.name: GetProcessFreezeInfoTest +* @tc.desc: cover GetProcessFreezeInfo branch +* @tc.type: FUNC +*/ +HWTEST_F(BinderInvokerUnitTest, GetProcessFreezeInfoTest, TestSize.Level1) +{ + bool isFrozen = false; + BinderInvoker binderInvoker; + binderInvoker.binderConnector_ = nullptr; + EXPECT_EQ(binderInvoker.GetProcessFreezeInfo(1, isFrozen), IPC_INVOKER_CONNECT_ERR); + + BinderConnector *binderConnector = BinderConnector::GetInstance(); + binderConnector->driverFD_ = -1; + binderInvoker.binderConnector_ = binderConnector; + EXPECT_EQ(binderInvoker.GetProcessFreezeInfo(1, isFrozen), IPC_INVOKER_CONNECT_ERR); +} +#endif // FREEZE_PROCESS_ENABLED } // 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 71223a8fb0ba3f168528ce4384477b45784a6a28..d7c8a62f7dcb31efe8fa563b82ecc9aaad594064 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,51 @@ HWTEST_F(IPCSkeletonTest, GetDCallingTokenIDInRPC, TestSize.Level1) ASSERT_EQ(tokenId, 0); } + +#ifdef FREEZE_PROCESS_ENABLED +/** + * @tc.name: FreezeProcessTest + * @tc.desc: Verify the Freeze 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); + + current->invokers_[IRemoteObject::IF_PROT_DEFAULT] = binderInvoker; + + EXPECT_CALL(*binderInvoker, Freeze(_, _, _)) + .WillRepeatedly(testing::Return(ERR_NONE)); + + ASSERT_EQ(IPCSkeleton::Freeze(0, true, 0), ERR_NONE); + current->invokers_[IRemoteObject::IF_PROT_DEFAULT] = nullptr; + delete binderInvoker; +} + +/** + * @tc.name: CheckFreezeTest + * @tc.desc: Verify the GetProcessFreezeInfo 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); + + current->invokers_[IRemoteObject::IF_PROT_DEFAULT] = binderInvoker; + + EXPECT_CALL(*binderInvoker, GetProcessFreezeInfo(_, _)) + .WillRepeatedly(testing::Return(ERR_NONE)); + + bool isFrozen = false; + ASSERT_EQ(IPCSkeleton::GetProcessFreezeInfo(0, isFrozen), ERR_NONE); + current->invokers_[IRemoteObject::IF_PROT_DEFAULT] = nullptr; + delete binderInvoker; +} +#endif // FREEZE_PROCESS_ENABLED } // 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 b53f3bb8425b0ef8bb3aae5942c8e0bd8cb99b86..fd4007dfac9b2b8deeb19f9b0e30d6e4a7ee87c2 100644 --- a/ipc/native/test/unittest/common/mock_iremote_invoker.h +++ b/ipc/native/test/unittest/common/mock_iremote_invoker.h @@ -41,6 +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_ENABLED + MOCK_METHOD3(Freeze, int32_t(uint32_t pid, bool freeze, uint32_t timeout)); + MOCK_METHOD2(GetProcessFreezeInfo, int32_t(uint32_t pid, bool &isFrozen)); +#endif // FREEZE_PROCESS_ENABLED 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 8832a75c09feeb9be939a7abb491be26a66415bb..356d8f403b7e43699a6cc56fbf5865190cbc04bf 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_feature_freeze_enabled) { + defines = [ "FREEZE_PROCESS_ENABLED" ] + } + 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_feature_freeze_enabled) { + defines = [ "FREEZE_PROCESS_ENABLED" ] + } + 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_feature_freeze_enabled) { + defines = [ "FREEZE_PROCESS_ENABLED" ] + } + 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 c7ece9764da7b2efd88555dc33264539019fc89b..2bf519d64d55a30048d8f58816d86ee5a3564270 100644 --- a/ipc/test/auxiliary/native/include/test_service.h +++ b/ipc/test/auxiliary/native/include/test_service.h @@ -56,6 +56,9 @@ public: int TestSendTooManyRequest(int data, int &reply) override; int TestMultiThreadSendRequest(int data, int &reply) override; int TestQueryThreadInvocationState() override; +#ifdef FREEZE_PROCESS_ENABLED + int TestFreezeProcess() override; +#endif // FREEZE_PROCESS_ENABLED 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 fd969b7c23903d417e2ad1857176f33526ef66f4..591712f8ad7cc4aa52d11cb83274bb92ad797a34 100644 --- a/ipc/test/auxiliary/native/include/test_service_base.h +++ b/ipc/test/auxiliary/native/include/test_service_base.h @@ -56,6 +56,7 @@ 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, }; public: virtual int TestSyncTransaction(int value, int &reply, int delayTime = 0) = 0; @@ -87,6 +88,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_ENABLED + virtual int TestFreezeProcess() = 0; +#endif // FREEZE_PROCESS_ENABLED 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 605e805dd5e7a3f266bf43a4ede9c863e85c4bde..be2625d3d21139abeb08e63404f05e14eedee853 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_ENABLED + bool TestFreezeProcess(); +#endif // FREEZE_PROCESS_ENABLED 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 c633411411e7f8a7cbb781b9f59d9b550b5b407d..f39756845f82325a90b538972aa68efdefb8ab1c 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_ENABLED + int TestFreezeProcess() override; +#endif // FREEZE_PROCESS_ENABLED 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 b51900369a308a7b5b4068839295d89fdd537cf5..e926dcb5bfc6cc720b17383e61e2e0c5215ae851 100644 --- a/ipc/test/auxiliary/native/include/test_service_stub.h +++ b/ipc/test/auxiliary/native/include/test_service_stub.h @@ -50,6 +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_ENABLED + int32_t ServerTestFreezeProcess(MessageParcel &data, MessageParcel &reply); +#endif // FREEZE_PROCESS_ENABLED 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 6a486a5798d85dce2925b16f567b6282c5c63a30..17e0818fa8aec7eca00498effd0dcee6135311bf 100644 --- a/ipc/test/auxiliary/native/src/main_client.cpp +++ b/ipc/test/auxiliary/native/src/main_client.cpp @@ -82,6 +82,15 @@ void TestCaseSyncTrans(std::shared_ptr &testClient) } } +#ifdef FREEZE_PROCESS_ENABLED +void TestCaseFreezeProcess(std::shared_ptr &testClient) +{ + bool ret = testClient->TestFreezeProcess(); + std::cout << (ret ? "[PASS] Execution of TestFreezeProcess case Successful" : + "[FAILED] Execution of TestFreezeProcess case failed") << std::endl; +} +#endif // FREEZE_PROCESS_ENABLED + void TestCasePingService(std::shared_ptr &testClient) { bool ret = testClient->StartPingService(); @@ -229,6 +238,9 @@ void ExecuteAllTestCase() TestCaseRegisterRemoteStub(testClient); TestCaseTooManyRequests(testClient); TestCaseMultiThreadSendRequest(testClient); +#ifdef FREEZE_PROCESS_ENABLED + TestCaseFreezeProcess(testClient); +#endif // FREEZE_PROCESS_ENABLED 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 c8b6b1103f71c27c0ac9fc6393934c6e4a92d863..c20fef8627fe68c2be9205a3f185e50da292fea5 100644 --- a/ipc/test/auxiliary/native/src/test_service.cpp +++ b/ipc/test/auxiliary/native/src/test_service.cpp @@ -345,4 +345,11 @@ int TestService::TestQueryThreadInvocationState() return state; } + +#ifdef FREEZE_PROCESS_ENABLED +int TestService::TestFreezeProcess() +{ + return 0; +} +#endif // FREEZE_PROCESS_ENABLED } // 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 154a7b0e2a787d87d2e611cd306dec9d28f9fc9c..3b3481e6a87f11ca719622249dfd86621b901cfd 100644 --- a/ipc/test/auxiliary/native/src/test_service_client.cpp +++ b/ipc/test/auxiliary/native/src/test_service_client.cpp @@ -74,6 +74,23 @@ bool TestServiceClient::StartSyncTransaction() return true; } +#ifdef FREEZE_PROCESS_ENABLED +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; +} +#endif // FREEZE_PROCESS_ENABLED + 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 7a04351199fde2d3997853831b4a3ae3034cb81b..ce0036b35c5893271c17bf5ffcbd8c81b08f8412 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,64 @@ int TestServiceProxy::TestSyncTransaction(int value, int &reply, int delayTime) return ret; } +#ifdef FREEZE_PROCESS_ENABLED +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::Freeze(pid, true, timeout); + if (res != ERR_NONE) { + ZLOGI(LABEL, "Freeze failed, error code = %{public}d", res); + return res; + } + + bool isFrozen = false; + res = IPCSkeleton::GetProcessFreezeInfo(pid, isFrozen); + if (res != ERR_NONE || !isFrozen) { + ZLOGI(LABEL, "GetProcessFreezeInfo failed, error code = %{public}d isFrozen = %{public}d ", res, isFrozen); + return -1; + } + + ret = remote->SendRequest(TRANS_ID_TEST_FREEZE_PROCESS, dataParcel, replyParcel, option); + if (ret == ERR_NONE) { + ZLOGI(LABEL, "SendRequest success, so freeze process fail"); + return -1; + } + + res = IPCSkeleton::Freeze(pid, false, timeout); + if (res != ERR_NONE) { + ZLOGI(LABEL, "Unfreeze failed, error code = %{public}d", res); + 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; +} +#endif // FREEZE_PROCESS_ENABLED + 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 d9a082d6abb6bc7e515ad989377163a9fbf8a42f..d5575315f22ec73ca0fcbdfa58c47bf8ebf29ad9 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_ENABLED + funcMap_[static_cast(TRANS_ID_TEST_FREEZE_PROCESS)] = &TestServiceStub::ServerTestFreezeProcess; +#endif // FREEZE_PROCESS_ENABLED } int32_t TestServiceStub::ServerSyncTransaction(MessageParcel &data, MessageParcel &reply) @@ -483,4 +486,12 @@ int32_t TestServiceStub::ServerThreadInvocationState(MessageParcel &data, Messag reply.WriteInt32(ret); return ret; } + +#ifdef FREEZE_PROCESS_ENABLED +int32_t TestServiceStub::ServerTestFreezeProcess(MessageParcel &data, MessageParcel &reply) +{ + reply.WriteInt32(getpid()); + return 0; +} +#endif // FREEZE_PROCESS_ENABLED } // namespace OHOS diff --git a/test/fuzztest/ipc/native/src/core/binderinvokernew/binderinvokernew004_fuzzer/binderinvokernew004_fuzzer.cpp b/test/fuzztest/ipc/native/src/core/binderinvokernew/binderinvokernew004_fuzzer/binderinvokernew004_fuzzer.cpp index 3c886ed54e4274ad69f0cba6ffa951ea1ee6a1bb..c3b8c88f14bb4e0d968f36b5f30ab9fa719618fd 100644 --- a/test/fuzztest/ipc/native/src/core/binderinvokernew/binderinvokernew004_fuzzer/binderinvokernew004_fuzzer.cpp +++ b/test/fuzztest/ipc/native/src/core/binderinvokernew/binderinvokernew004_fuzzer/binderinvokernew004_fuzzer.cpp @@ -42,7 +42,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, }; void HandleReplyFuzzTest(FuzzedDataProvider &provider) diff --git a/test/unittest/ipc/native/src/core/source/BUILD.gn b/test/unittest/ipc/native/src/core/source/BUILD.gn index 8236f82ce7cba97d0638439c14e5226c331851a3..b0a93d82a5cdd239d048bde917d96b3e49f1b39e 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_feature_freeze_enabled) { + defines += [ "FREEZE_PROCESS_ENABLED" ] + } + 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 b524b532688a84ccdf06e26c8ce2a86296de6ffa..49ae460351753011b1bf9f1cf29492fa11faf40c 100644 --- a/test/unittest/mock/mock_iremote_invoker.h +++ b/test/unittest/mock/mock_iremote_invoker.h @@ -41,6 +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_ENABLED + MOCK_METHOD3(Freeze, int32_t(uint32_t pid, bool freeze, uint32_t timeout)); + MOCK_METHOD2(GetProcessFreezeInfo, int32_t(uint32_t pid, bool &isFrozen)); +#endif // FREEZE_PROCESS_ENABLED MOCK_METHOD2(AddDeathRecipient, bool(int32_t handle, void *cookie)); MOCK_METHOD2(RemoveDeathRecipient, bool(int32_t handle, void *cookie)); MOCK_METHOD1(SetMaxWorkThread, bool(int maxThreadNum));