diff --git a/frameworks/native/player/player_impl.cpp b/frameworks/native/player/player_impl.cpp index 5092fa4513aefedec5eceb752137dfdb9abbd220..6abbe7497a8754f45134d431a3eec1a6b4108fb3 100644 --- a/frameworks/native/player/player_impl.cpp +++ b/frameworks/native/player/player_impl.cpp @@ -490,6 +490,12 @@ int32_t PlayerImpl::SetMaxAmplitudeCbStatus(bool status) return playerService_->SetMaxAmplitudeCbStatus(status); } +void PlayerImpl::ReleaseClientListener() +{ + MEDIA_LOGD("PlayerImpl:0x%{public}06" PRIXPTR " ReleaseClientListener in", FAKE_POINTER(this)); + MediaServiceFactory::GetInstance().ReleaseClientListener(); // not related to playerService_ thus no XCollie +} + PlayerImplCallback::PlayerImplCallback(const std::shared_ptr playerCb, std::shared_ptr player) { diff --git a/frameworks/native/player/player_impl.h b/frameworks/native/player/player_impl.h index cef898510516625488516ab5a24a9124e969a109..ab7ee28d0f6b0fa02426de30329f89caf070ae7a 100644 --- a/frameworks/native/player/player_impl.h +++ b/frameworks/native/player/player_impl.h @@ -79,6 +79,7 @@ public: int32_t SetMediaMuted(OHOS::Media::MediaType mediaType, bool isMuted) override; int32_t SetMaxAmplitudeCbStatus(bool status) override; int32_t SetDeviceChangeCbStatus(bool status) override; + void ReleaseClientListener() override; private: void ResetSeekVariables(); void HandleSeekDoneInfo(PlayerOnInfoType type, int32_t extra); diff --git a/frameworks/native/player/test/unittest/include/player_mock.h b/frameworks/native/player/test/unittest/include/player_mock.h index f5f4ba695abae68464b9df75cf20438e1a5e21bd..60d835159ded93af7f9f8a856ceae2dc62b2328d 100644 --- a/frameworks/native/player/test/unittest/include/player_mock.h +++ b/frameworks/native/player/test/unittest/include/player_mock.h @@ -161,6 +161,7 @@ public: int32_t SetMediaMuted(OHOS::Media::MediaType mediaType, bool isMuted); int32_t SetDeviceChangeCbStatus(bool status); int32_t SetMaxAmplitudeCbStatus(bool status); + void ReleaseClientListener(); private: void SeekPrepare(int32_t &mseconds, PlayerSeekMode &mode); std::shared_ptr player_ = nullptr; diff --git a/frameworks/native/player/test/unittest/src/player_mock.cpp b/frameworks/native/player/test/unittest/src/player_mock.cpp index 95a11d17cd2dd2c48642f7ee197bca4d22889d8c..b0d617ae3e0add1e361e676f42087927ccc6dc5f 100644 --- a/frameworks/native/player/test/unittest/src/player_mock.cpp +++ b/frameworks/native/player/test/unittest/src/player_mock.cpp @@ -770,5 +770,11 @@ int32_t PlayerMock::SetMaxAmplitudeCbStatus(bool status) UNITTEST_CHECK_AND_RETURN_RET_LOG(player_ != nullptr, -1, "player_ == nullptr"); return player_->SetMaxAmplitudeCbStatus(status); } + +void PlayerMock::ReleaseClientListener() +{ + UNITTEST_CHECK_AND_RETURN_LOG(player_ != nullptr, "player_ == nullptr"); + player_->ReleaseClientListener(); +} } // namespace Media } // namespace OHOS diff --git a/frameworks/native/player/test/unittest/src/player_unit_test.cpp b/frameworks/native/player/test/unittest/src/player_unit_test.cpp index 9ef7845d639adf64656d2825fe4125f875398915..b0d9479246900819a8c10c9347bee357e2e70a90 100644 --- a/frameworks/native/player/test/unittest/src/player_unit_test.cpp +++ b/frameworks/native/player/test/unittest/src/player_unit_test.cpp @@ -3577,5 +3577,35 @@ HWTEST_F(PlayerUnitTest, Player_SetMaxAmplitudeCbStatus_004, TestSize.Level0) EXPECT_EQ(MSERR_OK, player_->SetMaxAmplitudeCbStatus(false)); EXPECT_EQ(MSERR_OK, player_->Play()); } + +/** + * @tc.name : Test ReleaseClientListener API + * @tc.number: Player_ReleaseClientListener_001 + * @tc.desc : Test Player ReleaseClientListener API + */ +HWTEST_F(PlayerUnitTest, Player_ReleaseClientListener_001, TestSize.Level0) +{ + ASSERT_EQ(MSERR_OK, player_->SetSource(VIDEO_FILE1)); + sptr videoSurface = player_->GetVideoSurface(); + ASSERT_NE(nullptr, videoSurface); + EXPECT_EQ(MSERR_OK, player_->SetVideoSurface(videoSurface)); + EXPECT_EQ(MSERR_OK, player_->Prepare()); + EXPECT_EQ(MSERR_OK, player_->Play()); + + player_->ReleaseClientListener(); + EXPECT_EQ(MSERR_SERVICE_DIED, player_->SetSource(VIDEO_FILE1)); + + // re-create player + player_ = std::make_shared(callback_); + ASSERT_NE(nullptr, player_); + EXPECT_TRUE(player_->CreatePlayer()); + EXPECT_EQ(MSERR_OK, player_->SetPlayerCallback(callback_)); + ASSERT_EQ(MSERR_OK, player_->SetSource(VIDEO_FILE1)); + videoSurface = player_->GetVideoSurface(); + ASSERT_NE(nullptr, videoSurface); + EXPECT_EQ(MSERR_OK, player_->SetVideoSurface(videoSurface)); + EXPECT_EQ(MSERR_OK, player_->Prepare()); + EXPECT_EQ(MSERR_OK, player_->Play()); +} } // namespace Media } // namespace OHOS diff --git a/interfaces/inner_api/native/player.h b/interfaces/inner_api/native/player.h index 25c148b595fa2624090f4331bcc9c5ecd082bed5..72066e2495bee7a2b4e06fa08f1ea899c2fbb922 100644 --- a/interfaces/inner_api/native/player.h +++ b/interfaces/inner_api/native/player.h @@ -762,6 +762,8 @@ public: return 0; } + virtual void ReleaseClientListener() = 0; + /** * @brief Enables render video first frame of the media playback. * diff --git a/services/include/i_media_service.h b/services/include/i_media_service.h index 40efcad4ba1b3cedf828d0b04836bc2f97e55339..3d18517e3b3e29ae8b14dd87db828041aad29aef 100644 --- a/services/include/i_media_service.h +++ b/services/include/i_media_service.h @@ -226,6 +226,11 @@ public: * @version 1.0 */ virtual sptr GetMonitorProxy() = 0; + + /** + * @brief Release the (service-side) proxy object monitoring client aliveness + */ + virtual void ReleaseClientListener() = 0; }; class __attribute__((visibility("default"))) MediaServiceFactory { diff --git a/services/services/sa_media/client/media_client.cpp b/services/services/sa_media/client/media_client.cpp index 7237c010ba28931076a4a9b8ae297d0cf26951df..86d3cb6f46d9acb9a0dedaf3a07e5df8a4c13a6e 100644 --- a/services/services/sa_media/client/media_client.cpp +++ b/services/services/sa_media/client/media_client.cpp @@ -71,6 +71,16 @@ bool MediaClient::IsAlived() return (mediaProxy_ != nullptr) ? true : false; } +void MediaClient::ReleaseClientListener() +{ + // there exist non-const methods of the sptr mediaProxy_, possible data-race. + if (mediaProxy_ == nullptr) { + return; + } + mediaProxy_->ReleaseClientListener(); + DoMediaServerDied(); // remove death recipient as well. Otherwise getting proxy after re-dlopen causes mem leak. +} + #ifdef SUPPORT_RECORDER std::shared_ptr MediaClient::CreateRecorderService() { diff --git a/services/services/sa_media/client/media_client.h b/services/services/sa_media/client/media_client.h index e5f5c5eed85a4ec468db37a6ddc26b4e09eac5dc..45ed16a0492161fc1c659c7ec720aa33372c3127 100644 --- a/services/services/sa_media/client/media_client.h +++ b/services/services/sa_media/client/media_client.h @@ -48,6 +48,7 @@ public: ~MediaClient(); sptr GetMonitorProxy() override; + void ReleaseClientListener() override; #ifdef SUPPORT_RECORDER std::shared_ptr CreateRecorderService() override; int32_t DestroyRecorderService(std::shared_ptr recorder) override; diff --git a/services/services/sa_media/ipc/i_standard_media_service.h b/services/services/sa_media/ipc/i_standard_media_service.h index 23b5793293c4f4334682f52c95a7c4fee4c6b55c..90982d43e0bb2e8d24c153f7c295c25664cc5b46 100644 --- a/services/services/sa_media/ipc/i_standard_media_service.h +++ b/services/services/sa_media/ipc/i_standard_media_service.h @@ -51,11 +51,16 @@ public: virtual sptr GetSubSystemAbility(IStandardMediaService::MediaSystemAbility subSystemId, const sptr &listener) = 0; + /** + * Release the proxy object monitoring client process. + */ + virtual void ReleaseClientListener() = 0; /** * IPC code ID */ enum MediaServiceMsg : int32_t { GET_SUBSYSTEM = 0, + RELEASE_CLIENT_LISTENER = 2, }; DECLARE_INTERFACE_DESCRIPTOR(u"IStandardMediaService"); diff --git a/services/services/sa_media/ipc/media_service_proxy.cpp b/services/services/sa_media/ipc/media_service_proxy.cpp index 5f1127073775027891ccb80b8f662f2f833c3a10..9ab1703b7b8f782f697acf32ae47da1e51942b65 100644 --- a/services/services/sa_media/ipc/media_service_proxy.cpp +++ b/services/services/sa_media/ipc/media_service_proxy.cpp @@ -35,6 +35,22 @@ MediaServiceProxy::~MediaServiceProxy() MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this)); } +void MediaServiceProxy::ReleaseClientListener() +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + bool token = data.WriteInterfaceToken(MediaServiceProxy::GetDescriptor()); + CHECK_AND_RETURN_LOG(token, "Failed to write descriptor!"); + + int32_t error = -1; + error = Remote()->SendRequest(MediaServiceMsg::RELEASE_CLIENT_LISTENER, data, reply, option); + if (error != MSERR_OK) { + MEDIA_LOGE("Send request failed, error: %{public}d", error); + } +} + sptr MediaServiceProxy::GetSubSystemAbility(IStandardMediaService::MediaSystemAbility subSystemId, const sptr &listener) { diff --git a/services/services/sa_media/ipc/media_service_proxy.h b/services/services/sa_media/ipc/media_service_proxy.h index 5c96f340497cd9bf61f895fef3d72bec609fca62..52aca57173f875b5e25f13920ff1f4d5a3c5c27f 100644 --- a/services/services/sa_media/ipc/media_service_proxy.h +++ b/services/services/sa_media/ipc/media_service_proxy.h @@ -28,6 +28,7 @@ public: sptr GetSubSystemAbility(IStandardMediaService::MediaSystemAbility subSystemId, const sptr &listener) override; + void ReleaseClientListener() override; private: static inline BrokerDelegator delegator_; diff --git a/services/services/sa_media/ipc/media_service_stub.cpp b/services/services/sa_media/ipc/media_service_stub.cpp index 9b9f8670626ef6440aa49fd22b84d9faa2fc6942..68403827be4599dcd9f4b578a2a2ca2223bb4ad8 100644 --- a/services/services/sa_media/ipc/media_service_stub.cpp +++ b/services/services/sa_media/ipc/media_service_stub.cpp @@ -43,6 +43,8 @@ void MediaServiceStub::Init() { mediaFuncs_[GET_SUBSYSTEM] = [this](MessageParcel &data, MessageParcel &reply) { return GetSystemAbility(data, reply); }; + mediaFuncs_[RELEASE_CLIENT_LISTENER] = + [this] (MessageParcel &data, MessageParcel &reply) { return ReleaseClientListenerStub(data, reply); }; } int32_t MediaServiceStub::DestroyStubForPid(pid_t pid) @@ -144,6 +146,20 @@ int32_t MediaServiceStub::SetDeathListener(const sptr &object) return MSERR_OK; } +int32_t MediaServiceStub::ReleaseClientListenerStub(MessageParcel &data, MessageParcel &reply) +{ + (void)data; + (void)reply; + ReleaseClientListener(); + return MSERR_OK; +} + +void MediaServiceStub::ReleaseClientListener() +{ + pid_t pid = IPCSkeleton::GetCallingPid(); + (void)DestroyStubForPid(pid); +} + int32_t MediaServiceStub::GetSystemAbility(MessageParcel &data, MessageParcel &reply) { int32_t mediaSystemAbility = data.ReadInt32(); diff --git a/services/services/sa_media/ipc/media_service_stub.h b/services/services/sa_media/ipc/media_service_stub.h index e19a54da3b78f27ab10d81fba8daeb00a6ce427b..391418b9742ca1daf21d66d3b82397eb0258a689 100644 --- a/services/services/sa_media/ipc/media_service_stub.h +++ b/services/services/sa_media/ipc/media_service_stub.h @@ -38,6 +38,8 @@ protected: private: void Init(); int32_t GetSystemAbility(MessageParcel &data, MessageParcel &reply); + int32_t ReleaseClientListenerStub(MessageParcel &data, MessageParcel &reply); + void ReleaseClientListener() override; void ClientDied(pid_t pid); int32_t DestroyStubForPid(pid_t pid); std::map mediaFuncs_; diff --git a/test/fuzztest/common/stub_common.cpp b/test/fuzztest/common/stub_common.cpp index 7d550159642596149072547a158c7b6554f73906..3ce4e30b2525576b63451bfcba13aa7af16102af 100644 --- a/test/fuzztest/common/stub_common.cpp +++ b/test/fuzztest/common/stub_common.cpp @@ -38,5 +38,13 @@ sptr MediaServiceProxyFuzzer::GetSubSystemAbility(IStandardMediaS } return reply.ReadRemoteObject(); } + +void MediaServiceProxyFuzzer::ReleaseClientListener() +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + (void)Remote()->SendRequest(MediaServiceMsg::RELEASE_CLIENT_LISTENER, data, reply, option); +} } } \ No newline at end of file diff --git a/test/fuzztest/common/stub_common.h b/test/fuzztest/common/stub_common.h index cb3bc030199ac1d14e65cbc10977a82adfb3cdc4..185b137e8d33c75f9d7013b3e99d098fbc45f450 100644 --- a/test/fuzztest/common/stub_common.h +++ b/test/fuzztest/common/stub_common.h @@ -35,6 +35,7 @@ public: virtual ~MediaServiceProxyFuzzer() {} sptr GetSubSystemAbility(IStandardMediaService::MediaSystemAbility subSystemId, const sptr &listener); + void ReleaseClientListener(); private: static inline BrokerDelegator delegator_; }; diff --git a/test/fuzztest/player_fuzztest/playerservicestub_fuzzer/playerservicestub_fuzzer.cpp b/test/fuzztest/player_fuzztest/playerservicestub_fuzzer/playerservicestub_fuzzer.cpp index de0d380885931b208c7e263b497bea1bdf722a86..b8c0df50500262a2e7ae8d056f86a9c6eb13e474 100644 --- a/test/fuzztest/player_fuzztest/playerservicestub_fuzzer/playerservicestub_fuzzer.cpp +++ b/test/fuzztest/player_fuzztest/playerservicestub_fuzzer/playerservicestub_fuzzer.cpp @@ -55,6 +55,14 @@ public: return reply.ReadRemoteObject(); } + void ReleaseClientListener() + { + MessageParcel data; + MessageParcel reply; + MessageOption option; + (void)Remote()->SendRequest(MediaServiceMsg::RELEASE_CLIENT_LISTENER, data, reply, option); + } + private: static inline BrokerDelegator delegator_; };