diff --git a/services/distributeddataservice/app/src/feature_stub_impl.cpp b/services/distributeddataservice/app/src/feature_stub_impl.cpp index e81ed5a8991f8957d348aacda04ce76771d6bd36..1cddeacfaafd54fa741de0602ef826303520e174 100644 --- a/services/distributeddataservice/app/src/feature_stub_impl.cpp +++ b/services/distributeddataservice/app/src/feature_stub_impl.cpp @@ -53,6 +53,14 @@ int32_t FeatureStubImpl::OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId, const return featureImpl_->OnAppExit(uid, pid, tokenId, bundleName); } +int32_t FeatureStubImpl::OnFeatureExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &bundleName) +{ + if (featureImpl_ == nullptr) { + return -1; + } + return featureImpl_->OnFeatureExit(uid, pid, tokenId, bundleName); +} + int32_t FeatureStubImpl::OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index) { if (featureImpl_ == nullptr) { diff --git a/services/distributeddataservice/app/src/feature_stub_impl.h b/services/distributeddataservice/app/src/feature_stub_impl.h index 77e90d58907c36c7c1674fd6c49e8c1da4d0b31d..7c2715a61b201112fc7e00951f7c6263048c4ebf 100644 --- a/services/distributeddataservice/app/src/feature_stub_impl.h +++ b/services/distributeddataservice/app/src/feature_stub_impl.h @@ -32,6 +32,7 @@ public: MessageOption &option) override; int32_t OnInitialize(std::shared_ptr executor); int32_t OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &bundleName); + int32_t OnFeatureExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &bundleName); int32_t OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index); int32_t OnAppUpdate(const std::string &bundleName, int32_t user, int32_t index); int32_t OnAppInstall(const std::string &bundleName, int32_t user, int32_t index); diff --git a/services/distributeddataservice/app/src/kvstore_data_service.cpp b/services/distributeddataservice/app/src/kvstore_data_service.cpp index 0a3fc46a528ee656510fab1c41f09100fbdfe7f4..2a7af16e452e06c11abdff714a2232e3be48902b 100644 --- a/services/distributeddataservice/app/src/kvstore_data_service.cpp +++ b/services/distributeddataservice/app/src/kvstore_data_service.cpp @@ -162,7 +162,7 @@ sptr KvStoreDataService::GetFeatureInterface(const std::string &n { sptr feature; bool isFirstCreate = false; - features_.Compute(name, [&feature, &isFirstCreate](const auto &key, auto &value) ->bool { + features_.Compute(name, [&feature, &isFirstCreate](const auto &key, auto &value) -> bool { if (value != nullptr) { feature = value; return true; @@ -204,7 +204,8 @@ void KvStoreDataService::LoadFeatures() } /* RegisterClientDeathObserver */ -Status KvStoreDataService::RegisterClientDeathObserver(const AppId &appId, sptr observer) +Status KvStoreDataService::RegisterClientDeathObserver(const AppId &appId, sptr observer, + const std::string &featureName) { ZLOGD("begin."); KVSTORE_ACCOUNT_EVENT_PROCESSING_CHECKER(Status::SYSTEM_ACCOUNT_EVENT_PROCESSING); @@ -223,16 +224,50 @@ Status KvStoreDataService::RegisterClientDeathObserver(const AppId &appId, sptr< return Status::PERMISSION_DENIED; } auto pid = IPCSkeleton::GetCallingPid(); - clients_.Compute( - info.tokenId, [&appId, &info, pid, this, obs = std::move(observer)](const auto tokenId, auto &clients) { - auto res = clients.try_emplace(pid, appId, *this, std::move(obs)); - ZLOGI("bundleName:%{public}s, uid:%{public}d, pid:%{public}d, inserted:%{public}s.", appId.appId.c_str(), - info.uid, pid, res.second ? "success" : "failed"); + clients_.Compute(info.tokenId, + [&appId, &info, pid, this, obs = std::move(observer), featureName](const auto tokenId, auto &clients) { + auto it = clients.find(pid); + if (it == clients.end()) { + auto res = clients.try_emplace(pid, appId, *this, std::move(obs), featureName); + ZLOGI("bundle:%{public}s, feature:%{public}s, uid:%{public}d, pid:%{public}d, emplace:%{public}s.", + appId.appId.c_str(), featureName.c_str(), info.uid, pid, res.second ? "success" : "failed"); + } else { + auto res = it->second.Insert(obs, featureName); + ZLOGI("bundle:%{public}s, feature:%{public}s, uid:%{public}d, pid:%{public}d, inserted:%{public}s.", + appId.appId.c_str(), featureName.c_str(), info.uid, pid, res ? "success" : "failed"); + } return !clients.empty(); }); return Status::SUCCESS; } +int32_t KvStoreDataService::Exit(const std::string &featureName) +{ + ZLOGI("FeatureExit:%{public}s", featureName.c_str()); + auto tokenId = IPCSkeleton::GetCallingTokenID(); + auto pid = IPCSkeleton::GetCallingPid(); + std::string bundleName; + KvStoreClientDeathObserverImpl impl(*this); + bool removed = false; + clients_.ComputeIfPresent(tokenId, [pid, &featureName, &bundleName, &impl, &removed](auto &, auto &value) { + auto it = value.find(pid); + if (it == value.end()) { + return !value.empty(); + } + bundleName = it->second.GetAppId(); + removed = it->second.Delete(featureName); + if (it->second.Empty()) { + impl = std::move(it->second); + value.erase(it); + } + return !value.empty(); + }); + auto [exist, feature] = features_.Find(featureName); + if (removed && exist && feature != nullptr) { + feature->OnFeatureExit(IPCSkeleton::GetCallingUid(), pid, tokenId, bundleName); + } + return Status::SUCCESS; +} Status KvStoreDataService::AppExit(pid_t uid, pid_t pid, uint32_t token, const AppId &appId) { ZLOGI("AppExit"); @@ -733,20 +768,20 @@ void KvStoreDataService::OnStop() Memory::MemMgrClient::GetInstance().NotifyProcessStatus(getpid(), 1, 0, DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID); } -KvStoreDataService::KvStoreClientDeathObserverImpl::KvStoreClientDeathObserverImpl( - const AppId &appId, KvStoreDataService &service, sptr observer) - : appId_(appId), dataService_(service), observerProxy_(std::move(observer)), - deathRecipient_(new KvStoreDeathRecipient(*this)) +KvStoreDataService::KvStoreClientDeathObserverImpl::KvStoreClientDeathObserverImpl(const AppId &appId, + KvStoreDataService &service, sptr observer, const std::string &featureName) + : appId_(appId), dataService_(service), deathRecipient_(new KvStoreDeathRecipient(*this)) { ZLOGD("KvStoreClientDeathObserverImpl"); uid_ = IPCSkeleton::GetCallingUid(); pid_ = IPCSkeleton::GetCallingPid(); token_ = IPCSkeleton::GetCallingTokenID(); - if (observerProxy_ != nullptr) { + if (observer != nullptr) { ZLOGI("add death recipient"); - observerProxy_->AddDeathRecipient(deathRecipient_); + observer->AddDeathRecipient(deathRecipient_); + observerProxy_.insert_or_assign(featureName, std::move(observer)); } else { - ZLOGW("observerProxy_ is nullptr"); + ZLOGW("observer is nullptr"); } } KvStoreDataService::KvStoreClientDeathObserverImpl::KvStoreClientDeathObserverImpl(KvStoreDataService &service) @@ -777,9 +812,13 @@ KvStoreDataService::KvStoreClientDeathObserverImpl &KvStoreDataService::KvStoreC KvStoreDataService::KvStoreClientDeathObserverImpl::~KvStoreClientDeathObserverImpl() { ZLOGI("~KvStoreClientDeathObserverImpl"); - if (deathRecipient_ != nullptr && observerProxy_ != nullptr) { + if (deathRecipient_ != nullptr && !observerProxy_.empty()) { ZLOGI("remove death recipient"); - observerProxy_->RemoveDeathRecipient(deathRecipient_); + for (auto &[key, value] : observerProxy_) { + if (value != nullptr) { + value->RemoveDeathRecipient(deathRecipient_); + } + } } if (uid_ == INVALID_UID || pid_ == INVALID_PID || token_ == INVALID_TOKEN || !appId_.IsValid()) { return; @@ -809,6 +848,32 @@ void KvStoreDataService::KvStoreClientDeathObserverImpl::Reset() appId_.appId = ""; } +bool KvStoreDataService::KvStoreClientDeathObserverImpl::Insert(sptr observer, + const std::string &featureName) +{ + observer->AddDeathRecipient(deathRecipient_); + return observerProxy_.insert_or_assign(featureName, std::move(observer)).second; +} + +bool KvStoreDataService::KvStoreClientDeathObserverImpl::Delete(const std::string &featureName) +{ + auto it = observerProxy_.find(featureName); + if (it != observerProxy_.end() && it->second != nullptr) { + it->second->RemoveDeathRecipient(deathRecipient_); + } + return observerProxy_.erase(featureName) != 0; +} + +std::string KvStoreDataService::KvStoreClientDeathObserverImpl::GetAppId() +{ + return appId_; +} + +bool KvStoreDataService::KvStoreClientDeathObserverImpl::Empty() +{ + return observerProxy_.empty(); +} + KvStoreDataService::KvStoreClientDeathObserverImpl::KvStoreDeathRecipient::KvStoreDeathRecipient( KvStoreClientDeathObserverImpl &kvStoreClientDeathObserverImpl) : kvStoreClientDeathObserverImpl_(kvStoreClientDeathObserverImpl) @@ -826,7 +891,9 @@ void KvStoreDataService::KvStoreClientDeathObserverImpl::KvStoreDeathRecipient:: { (void) remote; ZLOGI("begin"); - kvStoreClientDeathObserverImpl_.NotifyClientDie(); + if (!clientDead_.exchange(true)) { + kvStoreClientDeathObserverImpl_.NotifyClientDie(); + } } void KvStoreDataService::AccountEventChanged(const AccountEventInfo &eventInfo) diff --git a/services/distributeddataservice/app/src/kvstore_data_service.h b/services/distributeddataservice/app/src/kvstore_data_service.h index d548368676ac09b6595ffff8b68cb4535201ad5a..f49a323c8657e517ea69796921783392e5e9a3d6 100644 --- a/services/distributeddataservice/app/src/kvstore_data_service.h +++ b/services/distributeddataservice/app/src/kvstore_data_service.h @@ -92,12 +92,15 @@ public: void PrintfInfo(int fd, const std::map &datas); void DumpBundleInfo(int fd, std::map> ¶ms); - Status RegisterClientDeathObserver(const AppId &appId, sptr observer) override; + Status RegisterClientDeathObserver(const AppId &appId, sptr observer, + const std::string &featureName) override; sptr GetFeatureInterface(const std::string &name) override; int32_t ClearAppStorage(const std::string &bundleName, int32_t userId, int32_t appIndex, int32_t tokenId) override; + int32_t Exit(const std::string &featureName) override; + void OnDump() override; int Dump(int fd, const std::vector &args) override; @@ -138,15 +141,19 @@ public: const std::vector &bundleInfos, const std::string &userId, const std::vector &iv, std::string &content); - private: +private: void NotifyAccountEvent(const AccountEventInfo &eventInfo); class KvStoreClientDeathObserverImpl { public: - KvStoreClientDeathObserverImpl(const AppId &appId, KvStoreDataService &service, sptr observer); + KvStoreClientDeathObserverImpl(const AppId &appId, KvStoreDataService &service, sptr observer, + const std::string &featureName); explicit KvStoreClientDeathObserverImpl(KvStoreDataService &service); explicit KvStoreClientDeathObserverImpl(KvStoreClientDeathObserverImpl &&impl); KvStoreClientDeathObserverImpl &operator=(KvStoreClientDeathObserverImpl &&impl); - + bool Insert(sptr observer, const std::string &featureName); + bool Delete(const std::string &featureName); + bool Empty(); + std::string GetAppId(); virtual ~KvStoreClientDeathObserverImpl(); pid_t GetPid() const; @@ -160,6 +167,7 @@ public: private: KvStoreClientDeathObserverImpl &kvStoreClientDeathObserverImpl_; + std::atomic_bool clientDead_ = false; }; void NotifyClientDie(); void Reset(); @@ -168,7 +176,7 @@ public: uint32_t token_; AppId appId_; KvStoreDataService &dataService_; - sptr observerProxy_; + std::map> observerProxy_; sptr deathRecipient_; }; diff --git a/services/distributeddataservice/app/src/kvstore_data_service_stub.cpp b/services/distributeddataservice/app/src/kvstore_data_service_stub.cpp index 4d0a55fab62ca5d40d0feffecf56d77298f17a82..3b74cbee45d238d8a0067adc34d058275c0118e2 100644 --- a/services/distributeddataservice/app/src/kvstore_data_service_stub.cpp +++ b/services/distributeddataservice/app/src/kvstore_data_service_stub.cpp @@ -37,7 +37,8 @@ int32_t KvStoreDataServiceStub::RegisterClientDeathObserverOnRemote(MessageParce if (kvStoreClientDeathObserverProxy == nullptr) { return -1; } - Status status = RegisterClientDeathObserver(appId, std::move(kvStoreClientDeathObserverProxy)); + std::string featureName = data.ReadString(); + Status status = RegisterClientDeathObserver(appId, std::move(kvStoreClientDeathObserverProxy), featureName); if (!reply.WriteInt32(static_cast(status))) { return -1; } @@ -67,8 +68,21 @@ int32_t KvStoreDataServiceStub::ClearAppStorageOnRemote(MessageParcel &data, Mes if (!ITypesUtil::Unmarshal(data, bundleName, userId, appIndex, tokenId)) { return -1; } - auto remoteObject = ClearAppStorage(bundleName, userId, appIndex, tokenId); - if (!ITypesUtil::Marshal(reply, remoteObject)) { + auto code = ClearAppStorage(bundleName, userId, appIndex, tokenId); + if (!ITypesUtil::Marshal(reply, code)) { + return -1; + } + return 0; +} + +int32_t KvStoreDataServiceStub::ExitOnRemote(MessageParcel &data, MessageParcel &reply) +{ + std::string featureName; + if (!ITypesUtil::Unmarshal(data, featureName)) { + return -1; + } + auto code = Exit(featureName); + if (!ITypesUtil::Marshal(reply, code)) { return -1; } return 0; diff --git a/services/distributeddataservice/app/src/kvstore_data_service_stub.h b/services/distributeddataservice/app/src/kvstore_data_service_stub.h index 08767f6d565dc6e45c6f8d0f74207fd4cd6c13bb..2e776bd01fd3238b1554a559c431cf935db560b0 100644 --- a/services/distributeddataservice/app/src/kvstore_data_service_stub.h +++ b/services/distributeddataservice/app/src/kvstore_data_service_stub.h @@ -26,6 +26,7 @@ private: int32_t GetFeatureInterfaceOnRemote(MessageParcel &data, MessageParcel &reply); int32_t RegisterClientDeathObserverOnRemote(MessageParcel &data, MessageParcel &reply); int32_t ClearAppStorageOnRemote(MessageParcel &data, MessageParcel &reply); + int32_t ExitOnRemote(MessageParcel &data, MessageParcel &reply); using RequestHandler = int32_t (KvStoreDataServiceStub::*)(MessageParcel &, MessageParcel &); using code = KvStoreDataServiceInterfaceCode; @@ -33,6 +34,7 @@ private: &KvStoreDataServiceStub::GetFeatureInterfaceOnRemote, &KvStoreDataServiceStub::RegisterClientDeathObserverOnRemote, &KvStoreDataServiceStub::ClearAppStorageOnRemote, + &KvStoreDataServiceStub::ExitOnRemote, }; }; } // namespace OHOS::DistributedKv diff --git a/services/distributeddataservice/app/test/unittest/kvstore_data_service_test.cpp b/services/distributeddataservice/app/test/unittest/kvstore_data_service_test.cpp index e60c4f042e94eb8c2c7a1a8347ac7af3d690ade7..8e761fdcb58b4ecc93fef43a2e10c17500fa77bd 100644 --- a/services/distributeddataservice/app/test/unittest/kvstore_data_service_test.cpp +++ b/services/distributeddataservice/app/test/unittest/kvstore_data_service_test.cpp @@ -149,10 +149,22 @@ HWTEST_F(KvStoreDataServiceTest, RegisterClientDeathObserver001, TestSize.Level1 Bootstrap::GetInstance().LoadCheckers(); KvStoreMetaManager::GetInstance().BindExecutor(std::make_shared(12, 5)); KvStoreMetaManager::GetInstance().InitMetaParameter(); - Status status = kvDataService.RegisterClientDeathObserver(appId, new KvStoreClientDeathObserver()); + Status status = kvDataService.RegisterClientDeathObserver(appId, new KvStoreClientDeathObserver(), ""); EXPECT_EQ(status, Status::SUCCESS) << "RegisterClientDeathObserver failed"; } +/** +* @tc.name: Exit001 +* @tc.desc: feature Exit +* @tc.type: FUNC +*/ +HWTEST_F(KvStoreDataServiceTest, Exit001, TestSize.Level1) +{ + KvStoreDataService kvDataService; + EXPECT_EQ(kvDataService.Exit(""), Status::SUCCESS); +} + + /** * @tc.name: GetIndentation001 * @tc.desc: diff --git a/services/distributeddataservice/framework/feature/feature_system.cpp b/services/distributeddataservice/framework/feature/feature_system.cpp index 593a7c63bc7290a49184a48cc50809ab75229553..23b77e1650b50ab55a4133d11b98d638e7a2f071 100644 --- a/services/distributeddataservice/framework/feature/feature_system.cpp +++ b/services/distributeddataservice/framework/feature/feature_system.cpp @@ -76,6 +76,10 @@ int32_t FeatureSystem::Feature::OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId return E_OK; } +int32_t FeatureSystem::Feature::OnFeatureExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &bundleName) +{ + return E_OK; +} int32_t FeatureSystem::Feature::OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index) { return E_OK; diff --git a/services/distributeddataservice/framework/include/feature/feature_system.h b/services/distributeddataservice/framework/include/feature/feature_system.h index 8f0d14241b55d5fdf58e29c7202379b86cdae65e..1fceb814515b6b6295668e911e387f7ae10bb2da 100644 --- a/services/distributeddataservice/framework/include/feature/feature_system.h +++ b/services/distributeddataservice/framework/include/feature/feature_system.h @@ -47,6 +47,7 @@ public: virtual int32_t OnInitialize(); virtual int32_t OnBind(const BindInfo &bindInfo); virtual int32_t OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &bundleName); + virtual int32_t OnFeatureExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &bundleName); virtual int32_t OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index); virtual int32_t OnAppUpdate(const std::string &bundleName, int32_t user, int32_t index); virtual int32_t OnAppInstall(const std::string &bundleName, int32_t user, int32_t index); diff --git a/services/distributeddataservice/service/rdb/rdb_service_impl.cpp b/services/distributeddataservice/service/rdb/rdb_service_impl.cpp index d93120bba52cb25fd27655f65ed65ca50f474b4c..9f988905d8f1a601476cce2d559a5743cd2a4d27 100644 --- a/services/distributeddataservice/service/rdb/rdb_service_impl.cpp +++ b/services/distributeddataservice/service/rdb/rdb_service_impl.cpp @@ -221,6 +221,35 @@ int32_t RdbServiceImpl::OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId, const return E_OK; } +int32_t RdbServiceImpl::OnFeatureExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &bundleName) +{ + ZLOGI("rdb exit, tokenId:%{public}d, pid:%{public}d, bundleName:%{public}s.", tokenId, pid, bundleName.c_str()); + bool destroyed = false; + syncAgents_.ComputeIfPresent(tokenId, [pid, &destroyed](auto &key, SyncAgents &agents) { + auto it = agents.find(pid); + if (it != agents.end()) { + it->second.SetNotifier(nullptr); + agents.erase(it); + } + if (!agents.empty()) { + return true; + } + destroyed = true; + return false; + }); + if (destroyed) { + auto stores = AutoCache::GetInstance().GetStoresIfPresent(tokenId); + for (auto store : stores) { + if (store != nullptr) { + store->UnregisterDetailProgressObserver(); + } + } + AutoCache::GetInstance().Enable(tokenId); + } + heartbeatTaskIds_.Erase(pid); + return E_OK; +} + bool RdbServiceImpl::CheckAccess(const std::string& bundleName, const std::string& storeName) { CheckerManager::StoreInfo storeInfo; diff --git a/services/distributeddataservice/service/rdb/rdb_service_impl.h b/services/distributeddataservice/service/rdb/rdb_service_impl.h index 82502ecff1923255d669c13e26d96568b050d839..18fe8217fbb28126951b6e4aa5034a366c0bafb0 100755 --- a/services/distributeddataservice/service/rdb/rdb_service_impl.h +++ b/services/distributeddataservice/service/rdb/rdb_service_impl.h @@ -84,6 +84,8 @@ public: int32_t OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &bundleName) override; + int32_t OnFeatureExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &bundleName) override; + int32_t Delete(const RdbSyncerParam ¶m) override; std::pair> QuerySharingResource(const RdbSyncerParam& param,