diff --git a/services/param/watcher/agent/watcher.cpp b/services/param/watcher/agent/watcher.cpp index 4606d2a1e08a5895af60ffc8301b6f92d2658884..3e289e1c14100d3575e78b0319a34e62dd1554c4 100644 --- a/services/param/watcher/agent/watcher.cpp +++ b/services/param/watcher/agent/watcher.cpp @@ -17,7 +17,7 @@ namespace OHOS { namespace init_param { -void Watcher::OnParameterChange(const std::string &name, const std::string &value) +void Watcher::OnParameterChange(const std::string &prefix, const std::string &name, const std::string &value) { UNUSED(name); UNUSED(value); diff --git a/services/param/watcher/agent/watcher.h b/services/param/watcher/agent/watcher.h index c703ead58ad8f8e3a202e309af10495506e59ec9..cf2541864904b24a4ac5215366ea8a2aaa284f55 100644 --- a/services/param/watcher/agent/watcher.h +++ b/services/param/watcher/agent/watcher.h @@ -26,7 +26,7 @@ public: Watcher() = default; virtual ~Watcher() = default; - void OnParameterChange(const std::string &name, const std::string &value) override; + void OnParameterChange(const std::string &prefix, const std::string &name, const std::string &value) override; }; } // namespace init_param } // namespace OHOS diff --git a/services/param/watcher/agent/watcher_manager_kits.cpp b/services/param/watcher/agent/watcher_manager_kits.cpp index f9ffdac3b45629aa6cff43fdb338979630d7e0e6..634db59f8f06e8905083b86b2016a2e8baa129ea 100644 --- a/services/param/watcher/agent/watcher_manager_kits.cpp +++ b/services/param/watcher/agent/watcher_manager_kits.cpp @@ -25,36 +25,40 @@ namespace OHOS { namespace init_param { -WatcherManagerKits &WatcherManagerKits::GetInstance() +WatcherManagerKits &WatcherManagerKits::GetInstance(void) { return DelayedRefSingleton::GetInstance(); } -WatcherManagerKits::WatcherManagerKits() {} +WatcherManagerKits::WatcherManagerKits(void) {} -WatcherManagerKits::~WatcherManagerKits() {} +WatcherManagerKits::~WatcherManagerKits(void) {} void WatcherManagerKits::ResetService(const wptr &remote) { WATCHER_LOGI("Remote is dead, reset service instance"); - bool resetService = false; - { - std::lock_guard lock(lock_); - if (watcherManager_ != nullptr) { - sptr object = watcherManager_->AsObject(); - if ((object != nullptr) && (remote == object)) { - object->RemoveDeathRecipient(deathRecipient_); - watcherManager_ = nullptr; - resetService = true; + std::lock_guard lock(lock_); + if (watcherManager_ != nullptr) { + sptr object = watcherManager_->AsObject(); + if ((object != nullptr) && (remote == object)) { + object->RemoveDeathRecipient(deathRecipient_); + watcherManager_ = nullptr; + remoteWatcherId_ = 0; + remoteWatcher_ = nullptr; + if (threadForReWatch_ != nullptr) { + WATCHER_LOGI("Thead exist, delete thread"); + stop_ = true; + threadForReWatch_->join(); + delete threadForReWatch_; } + stop_ = false; + threadForReWatch_ = new (std::nothrow)std::thread(&WatcherManagerKits::ReAddWatcher, this); + WATCHER_CHECK(threadForReWatch_ != nullptr, return, "Failed to create thread"); } } - if (resetService) { - ReAddWatcher(); - } } -sptr WatcherManagerKits::GetService() +sptr WatcherManagerKits::GetService(void) { std::lock_guard lock(lock_); if (watcherManager_ != nullptr) { @@ -84,92 +88,125 @@ void WatcherManagerKits::DeathRecipient::OnRemoteDied(const wptr DelayedRefSingleton::GetInstance().ResetService(remote); } -WatcherManagerKits::ParamWatcherKitPtr WatcherManagerKits::GetParamWatcher(const std::string &keyPrefix) -{ - std::lock_guard lock(mutex_); - if (watchers_.find(keyPrefix) == watchers_.end()) { - return nullptr; - } - return watchers_[keyPrefix]; -} - -void WatcherManagerKits::ReAddWatcher() +void WatcherManagerKits::ReAddWatcher(void) { - WATCHER_LOGV("ReAddWatcher "); + WATCHER_LOGV("ReAddWatcher"); int count = 0; const int maxRetryCount = 100; const int sleepTime = 100; auto watcherManager = GetService(); while (watcherManager == nullptr && count < maxRetryCount) { + if (stop_) { + return; + } watcherManager = GetService(); usleep(sleepTime); count++; } + WATCHER_LOGV("ReAddWatcher count %d ", count); WATCHER_CHECK(watcherManager != nullptr, return, "Failed to get watcher manager"); + // add or get remote agent + uint32_t remoteWatcherId = GetRemoteWatcher(); + WATCHER_CHECK(remoteWatcherId > 0, return, "Failed to get remote agent"); std::lock_guard lock(mutex_); for (auto iter = watchers_.begin(); iter != watchers_.end(); iter++) { + if (stop_) { + return; + } if (iter->second == nullptr) { continue; } - WATCHER_LOGV("ReAddWatcher keyPrefix %s ", iter->first.c_str()); - uint32_t watcherId = watcherManager->AddWatcher(iter->first, iter->second); - WATCHER_CHECK(watcherId != 0, continue, "Failed to add watcher for %s", iter->first.c_str()); - iter->second->SetWatcherId(watcherId); + WATCHER_LOGI("Add old watcher keyPrefix %s ", iter->first.c_str()); + int ret = watcherManager->AddWatcher(iter->first, remoteWatcherId); + WATCHER_CHECK(ret == 0, continue, "Failed to add watcher for %s", iter->first.c_str()); + } +} + +WatcherManagerKits::ParamWatcher *WatcherManagerKits::GetParamWatcher(const std::string &keyPrefix) +{ + std::lock_guard lock(mutex_); + auto iter = watchers_.find(keyPrefix); + if (iter != watchers_.end()) { + return iter->second.get(); } + return nullptr; +} + +uint32_t WatcherManagerKits::GetRemoteWatcher(void) +{ + std::lock_guard lock(mutex_); + if (remoteWatcher_ != nullptr) { + return remoteWatcherId_; + } + auto watcherManager = GetService(); + WATCHER_CHECK(watcherManager != nullptr, return 0, "Failed to get watcher manager"); + remoteWatcher_ = new RemoteWatcher(this); + WATCHER_CHECK(remoteWatcher_ != nullptr, return 0, "Failed to create watcher"); + remoteWatcherId_ = watcherManager->AddRemoteWatcher(getpid(), remoteWatcher_); + WATCHER_CHECK(remoteWatcherId_ != 0, return 0, "Failed to add watcher"); + return remoteWatcherId_; } int32_t WatcherManagerKits::AddWatcher(const std::string &keyPrefix, ParameterChangePtr callback, void *context) { - WATCHER_LOGV("AddWatcher keyPrefix %s", keyPrefix.c_str()); auto watcherManager = GetService(); WATCHER_CHECK(watcherManager != nullptr, return -1, "Failed to get watcher manager"); - bool newWatcher = false; + // add or get remote agent + uint32_t remoteWatcherId = GetRemoteWatcher(); + WATCHER_CHECK(remoteWatcherId > 0, return -1, "Failed to get remote agent"); ParamWatcherKitPtr watcher = nullptr; { std::lock_guard lock(mutex_); + // must check + WATCHER_CHECK(remoteWatcherId > 0, return -1, "Failed to get remote agent"); if (watchers_.find(keyPrefix) == watchers_.end()) { - watcher = new ParamWatcher(keyPrefix); + watcher = std::make_shared(keyPrefix); WATCHER_CHECK(watcher != nullptr, return -1, "Failed to create watcher for %s", keyPrefix.c_str()); - watchers_[keyPrefix] = watcher; - newWatcher = true; int ret = watcher->AddParameterListener(callback, context); WATCHER_CHECK(ret == 0, return -1, "Failed to add callback for %s ", keyPrefix.c_str()); - uint32_t watcherId = watcherManager->AddWatcher(keyPrefix, watcher); - WATCHER_CHECK(watcherId != 0, return -1, "Failed to add watcher for %s", keyPrefix.c_str()); - watcher->SetWatcherId(watcherId); + ret = watcherManager->AddWatcher(keyPrefix, remoteWatcherId); + WATCHER_CHECK(ret == 0, return -1, "Failed to add watcher for %s", keyPrefix.c_str()); + watchers_[keyPrefix] = watcher; } else { watcher = watchers_[keyPrefix]; + int ret = watcher->AddParameterListener(callback, context); + WATCHER_CHECK(ret == 0, return -1, "Failed to add callback for %s ", keyPrefix.c_str()); + ret = watcherManager->RefreshWatcher(keyPrefix, remoteWatcherId); + WATCHER_CHECK(ret == 0, return -1, + "Failed to refresh watcher for %s %d", keyPrefix.c_str(), remoteWatcherId); } } - // save callback - if (!newWatcher) { // refresh - int ret = watcher->AddParameterListener(callback, context); - WATCHER_CHECK(ret == 0, return -1, "Failed to add callback for %s ", keyPrefix.c_str()); - ret = watcherManager->RefreshWatcher(keyPrefix, watcher->GetWatcherId()); - WATCHER_CHECK(ret == 0, return -1, "Failed to refresh watcher for %s", keyPrefix.c_str()); - } - WATCHER_LOGI("AddWatcher keyPrefix %s watcherId %u success", keyPrefix.c_str(), watcher->GetWatcherId()); + WATCHER_LOGI("Add watcher keyPrefix %s remoteWatcherId %u success", keyPrefix.c_str(), remoteWatcherId); return 0; } int32_t WatcherManagerKits::DelWatcher(const std::string &keyPrefix, ParameterChangePtr callback, void *context) { - ParamWatcherKitPtr watcher = GetParamWatcher(keyPrefix); - WATCHER_CHECK(watcher != nullptr, return 0, "Can not find watcher for keyPrefix %s", keyPrefix.c_str()); auto watcherManager = GetService(); WATCHER_CHECK(watcherManager != nullptr, return -1, "Failed to get watcher manager"); + + WatcherManagerKits::ParamWatcher *watcher = GetParamWatcher(keyPrefix); + WATCHER_CHECK(watcher != nullptr, return -1, "Failed to get watcher"); + int count = watcher->DelParameterListener(callback, context); WATCHER_LOGI("DelWatcher keyPrefix_ %s count %d", keyPrefix.c_str(), count); - if (count == 0) { - int ret = watcherManager->DelWatcher(keyPrefix, watcher->GetWatcherId()); - WATCHER_CHECK(ret == 0, return -1, "Failed to delete watcher for %s", keyPrefix.c_str()); - { - std::lock_guard lock(mutex_); - auto iter = watchers_.find(keyPrefix); - if (iter != watchers_.end()) { - watchers_.erase(iter); - } + if (count != 0) { + return 0; + } + // delete watcher + int ret = watcherManager->DelWatcher(keyPrefix, remoteWatcherId_); + WATCHER_CHECK(ret == 0, return -1, "Failed to delete watcher for %s", keyPrefix.c_str()); + { + std::lock_guard lock(mutex_); + auto it = watchers_.find(keyPrefix); // delete watcher + if (it != watchers_.end()) { + watchers_.erase(it); + } + if (watchers_.empty()) { // no watcher, so delete remote agent + watcherManager->DelRemoteWatcher(remoteWatcherId_); + remoteWatcherId_ = 0; + remoteWatcher_ = nullptr; } } return 0; @@ -179,7 +216,10 @@ WatcherManagerKits::ParameterChangeListener *WatcherManagerKits::ParamWatcher::G { std::lock_guard lock(mutex_); uint32_t index = *idx; - while (index < static_cast(parameterChangeListeners.size())) { + if (parameterChangeListeners.empty()) { + return nullptr; + } + while (index < listenerId_) { auto it = parameterChangeListeners.find(index); if (it != parameterChangeListeners.end()) { *idx = index; @@ -193,32 +233,17 @@ WatcherManagerKits::ParameterChangeListener *WatcherManagerKits::ParamWatcher::G void WatcherManagerKits::ParamWatcher::RemoveParameterListener(uint32_t idx) { std::lock_guard lock(mutex_); - if (idx >= static_cast(parameterChangeListeners.size())) { - return; - } - parameterChangeListeners.erase(idx); -} - -void WatcherManagerKits::ParamWatcher::OnParameterChange(const std::string &name, const std::string &value) -{ - Watcher::OnParameterChange(name, value); - WATCHER_LOGI("OnParameterChange name %s value %s", name.c_str(), value.c_str()); - uint32_t index = 0; - ParameterChangeListener *listener = GetParameterListener(&index); - while (listener != nullptr) { - if (!listener->CheckValueChange(value)) { - listener->OnParameterChange(name, value); - } - index++; - listener = GetParameterListener(&index); + auto it = parameterChangeListeners.find(idx); + if (it != parameterChangeListeners.end()) { + parameterChangeListeners.erase(it); } } int WatcherManagerKits::ParamWatcher::AddParameterListener(ParameterChangePtr callback, void *context) { WATCHER_CHECK(callback != nullptr, return -1, "Invalid callback "); - WATCHER_LOGV("AddParameterListener listenerId_ %d callback %p context %p", listenerId_, callback, context); - std::lock_guard lock(mutex_); + WATCHER_LOGV("AddParameterListener %s listenerId_ %d callback %p context %p", + keyPrefix_.c_str(), listenerId_, callback, context); for (auto it = parameterChangeListeners.begin(); it != parameterChangeListeners.end(); it++) { if (it->second == nullptr) { continue; @@ -237,12 +262,15 @@ int WatcherManagerKits::ParamWatcher::AddParameterListener(ParameterChangePtr ca int WatcherManagerKits::ParamWatcher::DelParameterListener(ParameterChangePtr callback, void *context) { + if (callback == nullptr) { + parameterChangeListeners.clear(); + return 0; + } uint32_t index = 0; ParameterChangeListener *listener = GetParameterListener(&index); while (listener != nullptr) { - if ((callback == nullptr && context == nullptr)) { - RemoveParameterListener(index); - } else if (listener->IsEqual(callback, context)) { + if (listener->IsEqual(callback, context)) { + WATCHER_LOGV("DelParameterListener listenerId_ %d callback %p context %p", index, callback, context); RemoveParameterListener(index); break; } @@ -252,6 +280,31 @@ int WatcherManagerKits::ParamWatcher::DelParameterListener(ParameterChangePtr ca return static_cast(parameterChangeListeners.size()); } +void WatcherManagerKits::RemoteWatcher::OnParameterChange( + const std::string &prefix, const std::string &name, const std::string &value) +{ + // get param watcher + WatcherManagerKits::ParamWatcher *watcher = watcherManager_->GetParamWatcher(prefix); + WATCHER_CHECK(watcher != nullptr, return, "Failed to get watcher '%s'", prefix.c_str()); + if (watcher != nullptr) { + watcher->OnParameterChange(name, value); + } +} + +void WatcherManagerKits::ParamWatcher::OnParameterChange(const std::string &name, const std::string &value) +{ + WATCHER_LOGI("OnParameterChange name %s value %s", name.c_str(), value.c_str()); + uint32_t index = 0; + ParameterChangeListener *listener = GetParameterListener(&index); + while (listener != nullptr) { + if (!listener->CheckValueChange(value)) { + listener->OnParameterChange(name, value); + } + index++; + listener = GetParameterListener(&index); + } +} + void WatcherManagerKits::ParameterChangeListener::OnParameterChange(const std::string &name, const std::string &value) { if (callback_ != nullptr) { @@ -261,20 +314,30 @@ void WatcherManagerKits::ParameterChangeListener::OnParameterChange(const std::s } // namespace init_param } // namespace OHOS -static int ParameterWatcherCheck(const char *keyPrefix) +static int PreHandleWatchParam(std::string &prefix) { - std::string key(keyPrefix); - if (key.rfind("*") == key.length() - 1) { - return WatchParamCheck(key.substr(0, key.length() - 1).c_str()); + // clear space in head or tail + prefix.erase(0, prefix.find_first_not_of(" ")); + prefix.erase(prefix.find_last_not_of(" ") + 1); + WATCHER_CHECK(!prefix.empty(), return PARAM_CODE_INVALID_PARAM, "Invalid prefix"); + int ret = 0; + if (prefix.rfind(".*") == prefix.length() - 2) { // 2 last index + ret = WatchParamCheck(prefix.substr(0, prefix.length() - 2).c_str()); // 2 last index + } else if (prefix.rfind("*") == prefix.length() - 1) { + ret = WatchParamCheck(prefix.substr(0, prefix.length() - 1).c_str()); + } else if (prefix.rfind(".") == prefix.length() - 1) { + ret = WatchParamCheck(prefix.substr(0, prefix.length() - 1).c_str()); } else { - return WatchParamCheck(keyPrefix); + ret = WatchParamCheck(prefix.c_str()); } + return ret; } int SystemWatchParameter(const char *keyPrefix, ParameterChangePtr callback, void *context) { WATCHER_CHECK(keyPrefix != nullptr, return PARAM_CODE_INVALID_PARAM, "Invalid prefix"); - int ret = ParameterWatcherCheck(keyPrefix); + std::string key(keyPrefix); + int ret = PreHandleWatchParam(key); if (ret != 0) { return ret; } @@ -290,7 +353,8 @@ int SystemWatchParameter(const char *keyPrefix, ParameterChangePtr callback, voi int RemoveParameterWatcher(const char *keyPrefix, ParameterChgPtr callback, void *context) { WATCHER_CHECK(keyPrefix != nullptr, return PARAM_CODE_INVALID_PARAM, "Invalid prefix"); - int ret = ParameterWatcherCheck(keyPrefix); + std::string key(keyPrefix); + int ret = PreHandleWatchParam(key); if (ret != 0) { return ret; } diff --git a/services/param/watcher/agent/watcher_manager_kits.h b/services/param/watcher/agent/watcher_manager_kits.h index 456a3bd8f052ce48814adffc67c07f9321470ba8..7930c00f8a1818a3e58c78ea15de1b9f421b3b64 100644 --- a/services/param/watcher/agent/watcher_manager_kits.h +++ b/services/param/watcher/agent/watcher_manager_kits.h @@ -18,6 +18,7 @@ #include #include #include +#include #include "iwatcher.h" #include "iwatcher_manager.h" @@ -33,10 +34,11 @@ class WatcherManagerKits final : public DelayedRefSingleton public: DISALLOW_COPY_AND_MOVE(WatcherManagerKits); - static WatcherManagerKits &GetInstance(); + static WatcherManagerKits &GetInstance(void); int32_t AddWatcher(const std::string &keyPrefix, ParameterChangePtr callback, void *context); int32_t DelWatcher(const std::string &keyPrefix, ParameterChangePtr callback, void *context); - void ReAddWatcher(); + void ReAddWatcher(void); + #ifndef STARTUP_INIT_TEST private: #endif @@ -44,7 +46,7 @@ private: public: ParameterChangeListener(ParameterChangePtr callback, void *context) : callback_(callback), context_(context) {} - ~ParameterChangeListener() = default; + ~ParameterChangeListener(void) = default; bool IsEqual(ParameterChangePtr callback, void *context) const { @@ -63,61 +65,63 @@ private: void *context_ { nullptr }; }; - class ParamWatcher final : public Watcher { + class ParamWatcher { public: explicit ParamWatcher(const std::string &key) : keyPrefix_(key) {} - ~ParamWatcher() override + ~ParamWatcher(void) { parameterChangeListeners.clear(); }; - - void OnParameterChange(const std::string &name, const std::string &value) override; - - void SetWatcherId(uint32_t watcherId) - { - watcherId_ = watcherId; - } - uint32_t GetWatcherId() - { - return watcherId_; - } + void OnParameterChange(const std::string &name, const std::string &value); int AddParameterListener(ParameterChangePtr callback, void *context); int DelParameterListener(ParameterChangePtr callback, void *context); private: ParameterChangeListener *GetParameterListener(uint32_t *idx); void RemoveParameterListener(uint32_t idx); - uint32_t watcherId_ { 0 }; std::string keyPrefix_ {}; - std::mutex mutex_; uint32_t listenerId_ { 0 }; std::map> parameterChangeListeners; }; - using ParamWatcherKitPtr = sptr; - ParamWatcherKitPtr GetParamWatcher(const std::string &keyPrefix); + class RemoteWatcher final : public Watcher { + public: + RemoteWatcher(WatcherManagerKits *watcherManager) : watcherManager_(watcherManager) {} + ~RemoteWatcher(void) override {} + + void OnParameterChange(const std::string &prefix, const std::string &name, const std::string &value) final; + private: + WatcherManagerKits *watcherManager_ = { nullptr }; + }; + + using ParamWatcherKitPtr = std::shared_ptr; // For death event procession class DeathRecipient final : public IRemoteObject::DeathRecipient { public: - DeathRecipient() = default; - ~DeathRecipient() final = default; + DeathRecipient(void) = default; + ~DeathRecipient(void) final = default; DISALLOW_COPY_AND_MOVE(DeathRecipient); void OnRemoteDied(const wptr &remote) final; }; - sptr GetDeathRecipient() + sptr GetDeathRecipient(void) { return deathRecipient_; } -private: + uint32_t GetRemoteWatcher(void); + ParamWatcher *GetParamWatcher(const std::string &keyPrefix); void ResetService(const wptr &remote); - sptr GetService(); + sptr GetService(void); std::mutex lock_; sptr watcherManager_ {}; sptr deathRecipient_ {}; std::mutex mutex_; + uint32_t remoteWatcherId_ = { 0 }; + sptr remoteWatcher_ = { nullptr }; std::map watchers_; + std::atomic stop_ { false }; + std::thread *threadForReWatch_ { nullptr }; }; } // namespace init_param } // namespace OHOS diff --git a/services/param/watcher/agent/watcher_manager_proxy.cpp b/services/param/watcher/agent/watcher_manager_proxy.cpp index dbd73052c061f46d79c9caa1378dce86465b355a..80f86e4165667ee95f7d372bbc89ae0a569d5e7a 100644 --- a/services/param/watcher/agent/watcher_manager_proxy.cpp +++ b/services/param/watcher/agent/watcher_manager_proxy.cpp @@ -17,55 +17,69 @@ namespace OHOS { namespace init_param { -uint32_t WatcherManagerProxy::AddWatcher(const std::string &keyPrefix, const sptr &watcher) +uint32_t WatcherManagerProxy::AddRemoteWatcher(uint32_t id, const sptr &watcher) { WATCHER_CHECK(watcher != nullptr, return ERR_INVALID_VALUE, "Invalid param"); - WATCHER_LOGV("WatcherManagerProxy::AddWatcher %s", keyPrefix.c_str()); auto remote = Remote(); WATCHER_CHECK(remote != nullptr, return 0, "Can not get remote"); MessageParcel data; data.WriteInterfaceToken(WatcherManagerProxy::GetDescriptor()); - data.WriteString(keyPrefix); bool ret = data.WriteRemoteObject(watcher->AsObject()); WATCHER_CHECK(ret, return 0, "Can not get remote"); + data.WriteUint32(id); MessageParcel reply; MessageOption option { MessageOption::TF_SYNC }; - int32_t res = remote->SendRequest(ADD_WATCHER, data, reply, option); - WATCHER_CHECK(res == ERR_OK, return 0, "Transact error"); + int32_t res = remote->SendRequest(ADD_REMOTE_AGENT, data, reply, option); + WATCHER_CHECK(res == ERR_OK, return 0, "Transact error %d", res); return reply.ReadUint32(); } -int32_t WatcherManagerProxy::DelWatcher(const std::string &keyPrefix, uint32_t watcherId) + +int32_t WatcherManagerProxy::DelRemoteWatcher(uint32_t remoteWatcherId) { - WATCHER_LOGV("WatcherManagerProxy::DelWatcher %s", keyPrefix.c_str()); auto remote = Remote(); WATCHER_CHECK(remote != nullptr, return ERR_FLATTEN_OBJECT, "Can not get remote"); MessageParcel data; data.WriteInterfaceToken(WatcherManagerProxy::GetDescriptor()); - data.WriteString(keyPrefix); - data.WriteUint32(watcherId); + data.WriteUint32(remoteWatcherId); MessageParcel reply; MessageOption option { MessageOption::TF_SYNC }; - int32_t res = remote->SendRequest(DEL_WATCHER, data, reply, option); + int32_t res = remote->SendRequest(DEL_REMOTE_AGENT, data, reply, option); WATCHER_CHECK(res == ERR_OK, return ERR_FLATTEN_OBJECT, "Transact error"); return reply.ReadInt32(); } -int32_t WatcherManagerProxy::RefreshWatcher(const std::string &keyPrefix, uint32_t watcherId) + +int32_t WatcherManagerProxy::SendMsg(int op, const std::string &keyPrefix, uint32_t remoteWatcherId) { auto remote = Remote(); - WATCHER_CHECK(remote != nullptr, return ERR_FLATTEN_OBJECT, "Can not get remote"); + WATCHER_CHECK(remote != nullptr, return 0, "Can not get remote"); MessageParcel data; data.WriteInterfaceToken(WatcherManagerProxy::GetDescriptor()); data.WriteString(keyPrefix); - data.WriteUint32(watcherId); + data.WriteUint32(remoteWatcherId); MessageParcel reply; MessageOption option { MessageOption::TF_SYNC }; - int32_t res = remote->SendRequest(REFRESH_WATCHER, data, reply, option); - WATCHER_CHECK(res == ERR_OK, return ERR_FLATTEN_OBJECT, "Transact error"); - return 0; + int32_t res = remote->SendRequest(op, data, reply, option); + WATCHER_CHECK(res == ERR_OK, return 0, "Transact error"); + return reply.ReadInt32(); +} + +int32_t WatcherManagerProxy::AddWatcher(const std::string &keyPrefix, uint32_t remoteWatcherId) +{ + return SendMsg(ADD_WATCHER, keyPrefix, remoteWatcherId); +} + +int32_t WatcherManagerProxy::DelWatcher(const std::string &keyPrefix, uint32_t remoteWatcherId) +{ + return SendMsg(DEL_WATCHER, keyPrefix, remoteWatcherId); +} + +int32_t WatcherManagerProxy::RefreshWatcher(const std::string &keyPrefix, uint32_t remoteWatcherId) +{ + return SendMsg(REFRESH_WATCHER, keyPrefix, remoteWatcherId); } } } // namespace OHOS diff --git a/services/param/watcher/agent/watcher_manager_proxy.h b/services/param/watcher/agent/watcher_manager_proxy.h index 590d6a117ad518dfc2cf5471f9aba88db88bca23..2a655ef6fbf5f1f81b05d7943de3501fb934fe45 100644 --- a/services/param/watcher/agent/watcher_manager_proxy.h +++ b/services/param/watcher/agent/watcher_manager_proxy.h @@ -25,10 +25,13 @@ class WatcherManagerProxy : public IRemoteProxy { public: explicit WatcherManagerProxy(const sptr &impl) : IRemoteProxy(impl) {} - uint32_t AddWatcher(const std::string &keyPrefix, const sptr &watcher) override; - int32_t DelWatcher(const std::string &keyPrefix, uint32_t watcherId) override; - int32_t RefreshWatcher(const std::string &keyPrefix, uint32_t watcherId) override; + uint32_t AddRemoteWatcher(uint32_t id, const sptr &watcher) override; + int32_t DelRemoteWatcher(uint32_t remoteWatcherId) override; + int32_t AddWatcher(const std::string &keyPrefix, uint32_t remoteWatcherId) override; + int32_t DelWatcher(const std::string &keyPrefix, uint32_t remoteWatcherId) override; + int32_t RefreshWatcher(const std::string &keyPrefix, uint32_t remoteWatcherId) override; private: + int32_t SendMsg(int op, const std::string &keyPrefix, uint32_t remoteWatcherId); static inline BrokerDelegator delegator_; }; } // namespace init_param diff --git a/services/param/watcher/agent/watcher_stub.cpp b/services/param/watcher/agent/watcher_stub.cpp index eef8071184e18624bf99b18c70975344844ab745..28f727b8543e8b504aaa858303fc664fd0b50a72 100644 --- a/services/param/watcher/agent/watcher_stub.cpp +++ b/services/param/watcher/agent/watcher_stub.cpp @@ -22,15 +22,16 @@ namespace OHOS { namespace init_param { int32_t WatcherStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) { - std::u16string myDescripter = IWatcher::GetDescriptor(); - std::u16string remoteDescripter = data.ReadInterfaceToken(); - WATCHER_CHECK(myDescripter == remoteDescripter, return -1, "Invalid remoteDescripter"); + std::u16string myDescriptor = IWatcher::GetDescriptor(); + std::u16string remoteDescriptor = data.ReadInterfaceToken(); + WATCHER_CHECK(myDescriptor == remoteDescriptor, return -1, "Invalid remoteDescriptor"); switch (code) { case PARAM_CHANGE: { + std::string key = data.ReadString(); std::string name = data.ReadString(); std::string value = data.ReadString(); - OnParameterChange(name, value); + OnParameterChange(key, name, value); break; } default: { diff --git a/services/param/watcher/include/iwatcher.h b/services/param/watcher/include/iwatcher.h index 4e3a0f78f347537940bd4554f4b786b507c58668..9c3226003b533fdf2a9cae64e9a07b3d3fa653da 100644 --- a/services/param/watcher/include/iwatcher.h +++ b/services/param/watcher/include/iwatcher.h @@ -31,7 +31,7 @@ public: DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.Startup.IWatcher"); public: - virtual void OnParameterChange(const std::string &name, const std::string &value) = 0; + virtual void OnParameterChange(const std::string &prefix, const std::string &name, const std::string &value) = 0; }; } // namespace init_param } // namespace OHOS diff --git a/services/param/watcher/include/iwatcher_manager.h b/services/param/watcher/include/iwatcher_manager.h index cc9eeddf330288122898b8de04e4272d60203d1f..c1e1043d8f589fac6a020597a57c196d166d0120 100644 --- a/services/param/watcher/include/iwatcher_manager.h +++ b/services/param/watcher/include/iwatcher_manager.h @@ -28,14 +28,18 @@ public: enum { ADD_WATCHER, DEL_WATCHER, + ADD_REMOTE_AGENT, + DEL_REMOTE_AGENT, REFRESH_WATCHER }; DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.Startup.IWatcherManager"); public: - virtual uint32_t AddWatcher(const std::string &keyPrefix, const sptr &watcher) = 0; - virtual int32_t DelWatcher(const std::string &keyPrefix, uint32_t watcherId) = 0; - virtual int32_t RefreshWatcher(const std::string &keyPrefix, uint32_t watcherId) = 0; + virtual uint32_t AddRemoteWatcher(uint32_t id, const sptr &watcher) = 0; + virtual int32_t DelRemoteWatcher(uint32_t remoteWatcherId) = 0; + virtual int32_t AddWatcher(const std::string &keyPrefix, uint32_t remoteWatcherId) = 0; + virtual int32_t DelWatcher(const std::string &keyPrefix, uint32_t remoteWatcherId) = 0; + virtual int32_t RefreshWatcher(const std::string &keyPrefix, uint32_t remoteWatcherId) = 0; }; } // namespace update_engine } // namespace OHOS diff --git a/services/param/watcher/proxy/watcher_manager.cpp b/services/param/watcher/proxy/watcher_manager.cpp index 57df856616a8e0a4066a3bbd023bed363dcb324b..1cebf09df24ce86bf18900d33cf9ea536dfdc1a3 100644 --- a/services/param/watcher/proxy/watcher_manager.cpp +++ b/services/param/watcher/proxy/watcher_manager.cpp @@ -20,7 +20,6 @@ #include #include -#include "param_message.h" #include "init_param.h" #include "system_ability_definition.h" #include "string_ex.h" @@ -33,86 +32,114 @@ REGISTER_SYSTEM_ABILITY_BY_ID(WatcherManager, PARAM_WATCHER_DISTRIBUTED_SERVICE_ const static int32_t INVALID_SOCKET = -1; WatcherManager::~WatcherManager() { - watchers_.clear(); - watcherGroups_.clear(); - groupMap_.clear(); + Clear(); } -uint32_t WatcherManager::AddWatcher(const std::string &keyPrefix, const sptr &watcher) +uint32_t WatcherManager::AddRemoteWatcher(uint32_t id, const sptr &watcher) { - WATCHER_CHECK(watcher != nullptr && deathRecipient_ != nullptr, - return 0, "Invalid remove watcher for %s", keyPrefix.c_str()); + WATCHER_CHECK(watcher != nullptr && deathRecipient_ != nullptr, return 0, "Invalid remove watcher"); sptr object = watcher->AsObject(); if ((object != nullptr) && (object->IsProxyObject())) { - WATCHER_CHECK(object->AddDeathRecipient(deathRecipient_), - return 0, "Failed to add death recipient %s", keyPrefix.c_str()); - } - - // check watcher id - uint32_t watcherId = 0; - int ret = GetWatcherId(watcherId); - WATCHER_CHECK(ret == 0, return 0, "Failed to get watcher id for %s", keyPrefix.c_str()); - - WATCHER_LOGV("AddWatcher prefix %s watcherId %u", keyPrefix.c_str(), watcherId); - bool newGroup = false; - WatcherGroupPtr group = GetWatcherGroup(keyPrefix); - if (group == nullptr) { - newGroup = true; - uint32_t groupId = 0; - ret = GetGroupId(groupId); - WATCHER_CHECK(ret == 0, return 0, "Failed to get group id for %s", keyPrefix.c_str()); - group = std::make_shared(groupId, keyPrefix); - WATCHER_CHECK(group != nullptr, return 0, "Failed to create group for %s", keyPrefix.c_str()); - } else { - newGroup = group->Empty(); - } - ParamWatcherPtr paramWatcher = std::make_shared(watcherId, watcher, group); - WATCHER_CHECK(paramWatcher != nullptr, return 0, "Failed to create watcher for %s", keyPrefix.c_str()); - AddParamWatcher(keyPrefix, group, paramWatcher); - if (newGroup) { - StartLoop(); - SendMessage(group, MSG_ADD_WATCHER); - } - SendLocalChange(keyPrefix, paramWatcher); - WATCHER_LOGI("AddWatcher %s watcherId: %u groupId %u success", keyPrefix.c_str(), watcherId, group->GetGroupId()); - return watcherId; -} - -int32_t WatcherManager::DelWatcher(const std::string &keyPrefix, uint32_t watcherId) -{ - auto group = GetWatcherGroup(keyPrefix); - WATCHER_CHECK(group != nullptr, return 0, "Can not find group %s", keyPrefix.c_str()); - auto paramWatcher = GetWatcher(watcherId); - WATCHER_CHECK(paramWatcher != nullptr, return 0, "Can not find watcher %s %d", keyPrefix.c_str(), watcherId); - WATCHER_LOGV("DelWatcher prefix %s watcherId %u", keyPrefix.c_str(), watcherId); - return DelWatcher(group, paramWatcher); + WATCHER_CHECK(object->AddDeathRecipient(deathRecipient_), return 0, "Failed to add death recipient %u", id); + } + uint32_t remoteWatcherId = 0; + { + std::lock_guard lock(watcherMutex_); + // check watcher id + int ret = GetRemoteWatcherId(remoteWatcherId); + WATCHER_CHECK(ret == 0, return 0, "Failed to get watcher id for %u", id); + // create remote watcher + RemoteWatcher *remoteWatcher = new RemoteWatcher(remoteWatcherId, watcher); + WATCHER_CHECK(remoteWatcher != nullptr, return 0, "Failed to create watcher for %u", id); + remoteWatcher->SetAgentId(id); + AddRemoteWatcher(remoteWatcher); + } + WATCHER_LOGI("Add remote watcher remoteWatcherId %u %u success", remoteWatcherId, id); + return remoteWatcherId; } -int32_t WatcherManager::DelWatcher(WatcherGroupPtr group, ParamWatcherPtr watcher) +int32_t WatcherManager::DelRemoteWatcher(uint32_t remoteWatcherId) { - WATCHER_CHECK(watcher != nullptr && group != nullptr, return 0, "Invalid watcher"); - sptr object = watcher->GetRemoteWatcher()->AsObject(); + sptr watcher = {0}; + { + std::lock_guard lock(watcherMutex_); + RemoteWatcher *remoteWatcher = GetRemoteWatcher(remoteWatcherId); + WATCHER_CHECK(remoteWatcher != nullptr, return 0, "Can not find watcher %u", remoteWatcherId); + WATCHER_LOGI("Del remote watcher remoteWatcherId %u", remoteWatcherId); + watcher = remoteWatcher->GetWatcher(); + DelRemoteWatcher(remoteWatcher); + } + sptr object = watcher->AsObject(); if (object != nullptr) { object->RemoveDeathRecipient(deathRecipient_); } - WATCHER_LOGI("DelWatcher watcherId %u prefix %s", watcher->GetWatcherId(), group->GetKeyPrefix().c_str()); - DelParamWatcher(watcher); - if (group->Empty()) { - SendMessage(group, MSG_DEL_WATCHER); - DelWatcherGroup(group); + return 0; +} + +int32_t WatcherManager::AddWatcher(const std::string &keyPrefix, uint32_t remoteWatcherId) +{ + // get remote watcher and group + auto remoteWatcher = GetRemoteWatcher(remoteWatcherId); + WATCHER_CHECK(remoteWatcher != nullptr, return -1, "Can not find remote watcher %d", remoteWatcherId); + auto group = AddWatcherGroup(keyPrefix); + WATCHER_CHECK(group != nullptr, return -1, "Failed to create group for %s", keyPrefix.c_str()); + { + // add watcher to agent and group + std::lock_guard lock(watcherMutex_); + bool newGroup = group->Empty(); + AddParamWatcher(group, remoteWatcher); + if (newGroup) { + StartLoop(); + SendMessage(group, MSG_ADD_WATCHER); + } + } + SendLocalChange(keyPrefix, remoteWatcher); + WATCHER_LOGI("Add watcher %s remoteWatcherId: %u groupId %u success", + keyPrefix.c_str(), remoteWatcherId, group->GetGroupId()); + return 0; +} + +int32_t WatcherManager::DelWatcher(const std::string &keyPrefix, uint32_t remoteWatcherId) +{ + auto group = GetWatcherGroup(keyPrefix); + WATCHER_CHECK(group != nullptr, return 0, "Can not find group %s", keyPrefix.c_str()); + auto remoteWatcher = GetRemoteWatcher(remoteWatcherId); + WATCHER_CHECK(remoteWatcher != nullptr, return 0, "Can not find watcher %s %d", keyPrefix.c_str(), remoteWatcherId); + WATCHER_LOGI("Delete watcher prefix %s remoteWatcherId %u", keyPrefix.c_str(), remoteWatcherId); + { + // remove watcher from agent and group + std::lock_guard lock(watcherMutex_); + DelParamWatcher(group, remoteWatcher); + if (group->Empty()) { // no watcher, so delete it + SendMessage(group, MSG_DEL_WATCHER); + DelWatcherGroup(group); + } } return 0; } +int32_t WatcherManager::RefreshWatcher(const std::string &keyPrefix, uint32_t remoteWatcherId) +{ + WATCHER_LOGV("Refresh watcher %s remoteWatcherId: %u", keyPrefix.c_str(), remoteWatcherId); + auto group = GetWatcherGroup(keyPrefix); + WATCHER_CHECK(group != nullptr, return 0, "Can not find group %s", keyPrefix.c_str()); + auto remoteWatcher = GetRemoteWatcher(remoteWatcherId); + WATCHER_CHECK(remoteWatcher != nullptr, return 0, "Can not find watcher %s %d", keyPrefix.c_str(), remoteWatcherId); + SendLocalChange(keyPrefix, remoteWatcher); + return 0; +} + int WatcherManager::SendMessage(WatcherGroupPtr group, int type) { ParamMessage *request = nullptr; - request = (ParamMessage *)CreateParamMessage(type, group->GetKeyPrefix().c_str(), sizeof(ParamMessage)); + std::string key(group->GetKeyPrefix()); + if (key.rfind("*") == key.length() - 1) { + key = key.substr(0, key.length() - 1); + } + request = (ParamMessage *)CreateParamMessage(type, key.c_str(), sizeof(ParamMessage)); WATCHER_CHECK(request != NULL, return PARAM_CODE_ERROR, "Failed to malloc for watch"); request->id.watcherId = group->GetGroupId(); request->msgSize = sizeof(ParamMessage); - - WATCHER_LOGV("SendMessage %s groupId %d type %d", group->GetKeyPrefix().c_str(), group->GetGroupId(), type); int ret = PARAM_CODE_ERROR; int fd = GetServerFd(false); if (fd != INVALID_SOCKET) { @@ -124,109 +151,61 @@ int WatcherManager::SendMessage(WatcherGroupPtr group, int type) return 0; } -void WatcherManager::ProcessWatcherMessage(const std::vector &buffer, uint32_t dataSize) -{ - ParamMessage *msg = (ParamMessage *)buffer.data(); - WATCHER_CHECK(msg != NULL, return, "Invalid msg"); - WATCHER_LOGV("ProcessWatcherMessage %d", msg->type); - uint32_t offset = 0; - if (msg->type != MSG_NOTIFY_PARAM) { - return; - } - WATCHER_CHECK(msg->msgSize <= dataSize, return, "Invalid msg size %d", msg->msgSize); - ParamMsgContent *valueContent = GetNextContent((const ParamMessage *)msg, &offset); - WATCHER_CHECK(valueContent != NULL, return, "Invalid msg "); - WATCHER_LOGV("ProcessWatcherMessage name %s watcherId %u ", msg->key, msg->id.watcherId); - WatcherGroupPtr group = GetWatcherGroup(msg->id.watcherId); - if (group != nullptr) { - std::lock_guard lock(watcherMutex_); - group->ProcessParameterChange(msg->key, valueContent->content); - } -} - -WatcherManager::WatcherGroupPtr WatcherManager::GetWatcherGroup(uint32_t groupId) +void WatcherGroup::ProcessParameterChange( + WatcherManager *mananger, const std::string &name, const std::string &value) { - std::lock_guard lock(watcherMutex_); - if (watcherGroups_.find(groupId) != watcherGroups_.end()) { - return watcherGroups_[groupId]; - } - return nullptr; + WATCHER_LOGV("ProcessParameterChange key '%s' '%s'", GetKeyPrefix().c_str(), name.c_str()); + // walk watcher + TraversalNode([this, mananger, name, value](ParamWatcherListPtr list, WatcherNodePtr node, uint32_t index) { + auto remoteWatcher = mananger->GetRemoteWatcher(node->GetNodeId()); + if (remoteWatcher == nullptr) { + return; + } + remoteWatcher->ProcessParameterChange(GetKeyPrefix(), name, value); + }); } -WatcherManager::WatcherGroupPtr WatcherManager::GetWatcherGroup(const std::string &keyPrefix) +static int FilterParam(const char *name, const std::string &keyPrefix) { - std::lock_guard lock(watcherMutex_); - if (groupMap_.find(keyPrefix) == groupMap_.end()) { - return nullptr; + if (keyPrefix.rfind("*") == keyPrefix.length() - 1) { + return strncmp(name, keyPrefix.c_str(), keyPrefix.length() - 1) == 0; } - uint32_t groupId = groupMap_[keyPrefix]; - if (watcherGroups_.find(groupId) != watcherGroups_.end()) { - return watcherGroups_[groupId]; + if (keyPrefix.rfind(".") == keyPrefix.length() - 1) { + return strncmp(name, keyPrefix.c_str(), keyPrefix.length() - 1) == 0; } - return nullptr; + return strcmp(name, keyPrefix.c_str()) == 0; } -void WatcherManager::AddParamWatcher(const std::string &keyPrefix, WatcherGroupPtr group, ParamWatcherPtr watcher) +void WatcherManager::ProcessWatcherMessage(const ParamMessage *msg) { - WATCHER_LOGV("AddParamWatcher prefix %s watcherId %u", keyPrefix.c_str(), watcher->GetWatcherId()); - uint32_t groupId = group->GetGroupId(); - std::lock_guard lock(watcherMutex_); - groupMap_[keyPrefix] = groupId; - watchers_[watcher->GetWatcherId()] = watcher; - OH_ListAddTail(group->GetWatchers(), watcher->GetGroupNode()); - - if (watcherGroups_.find(groupId) != watcherGroups_.end()) { + uint32_t offset = 0; + if (msg->type != MSG_NOTIFY_PARAM) { return; } - watcherGroups_[groupId] = group; -} - -void WatcherManager::DelParamWatcher(ParamWatcherPtr watcher) -{ - std::lock_guard lock(watcherMutex_); - OH_ListRemove(watcher->GetGroupNode()); - OH_ListInit(watcher->GetGroupNode()); - watchers_.erase(watcher->GetWatcherId()); - WATCHER_LOGV("DelParamWatcher watcherId %u", watcher->GetWatcherId()); -} - -void WatcherManager::DelWatcherGroup(WatcherGroupPtr group) -{ - std::lock_guard lock(watcherMutex_); - groupMap_.erase(group->GetKeyPrefix()); - watcherGroups_.erase(group->GetGroupId()); -} - -void WatcherManager::WatcherGroup::ProcessParameterChange(const std::string &name, const std::string &value) -{ - // walk watcher - ListNode *node = nullptr; - ForEachListEntry(&watchers_, node) { - if (node != nullptr) { - ParamWatcher *watcher = (ParamWatcher *)node; - watcher->ProcessParameterChange(name, value); + ParamMsgContent *valueContent = GetNextContent(msg, &offset); + WATCHER_CHECK(valueContent != NULL, return, "Invalid msg "); + WATCHER_LOGV("Process watcher message name '%s' group id %u ", msg->key, msg->id.watcherId); + { + std::lock_guard lock(watcherMutex_); + WatcherGroupPtr group = GetWatcherGroup(msg->id.watcherId); + WATCHER_CHECK(group != NULL, return, "Can not find group for %u %s", msg->id.watcherId, msg->key); + if (!FilterParam(msg->key, group->GetKeyPrefix())) { + WATCHER_LOGV("Invalid message name '%s' group '%s' ", msg->key, group->GetKeyPrefix().c_str()); + return; } + group->ProcessParameterChange(this, msg->key, valueContent->content); } } -static int FilterParam(const char *name, const std::string &keyPrefix) -{ - if (keyPrefix.rfind("*") == keyPrefix.length() - 1) { - return strncmp(name, keyPrefix.c_str(), keyPrefix.length() - 1) == 0; - } - return strcmp(name, keyPrefix.c_str()) == 0; -} - -void WatcherManager::SendLocalChange(const std::string &keyPrefix, ParamWatcherPtr watcher) +void WatcherManager::SendLocalChange(const std::string &keyPrefix, RemoteWatcherPtr &remoteWatcher) { struct Context { char *buffer; - ParamWatcherPtr watcher; + RemoteWatcherPtr remoteWatcher; std::string keyPrefix; }; - WATCHER_LOGV("SendLocalChange key %s ", keyPrefix.c_str()); std::vector buffer(PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX); - struct Context context = {buffer.data(), watcher, keyPrefix}; + struct Context context = {buffer.data(), remoteWatcher, keyPrefix}; // walk watcher SystemTraversalParameter("", [](ParamHandle handle, void *cookie) { struct Context *context = (struct Context *)(cookie); @@ -236,8 +215,8 @@ void WatcherManager::SendLocalChange(const std::string &keyPrefix, ParamWatcherP } uint32_t size = PARAM_CONST_VALUE_LEN_MAX; SystemGetParameterValue(handle, context->buffer + PARAM_NAME_LEN_MAX, &size); - WATCHER_LOGV("SendLocalChange key %s value: %s ", context->buffer, context->buffer + PARAM_NAME_LEN_MAX); - context->watcher->ProcessParameterChange(context->buffer, context->buffer + PARAM_NAME_LEN_MAX); + context->remoteWatcher->ProcessParameterChange( + context->keyPrefix, context->buffer, context->buffer + PARAM_NAME_LEN_MAX); }, reinterpret_cast(&context)); } @@ -261,8 +240,20 @@ void WatcherManager::RunLoop() } PARAM_LOGE("Failed to recv msg from server errno %d", errno); retry = true; // re connect - } else if (recvLen >= (ssize_t)sizeof(ParamMessage)) { - ProcessWatcherMessage(buffer, recvLen); + continue; + } + uint32_t curr = 0; + uint32_t dataLen = static_cast(recvLen); + while (curr < dataLen) { + if ((curr + sizeof(ParamMessage)) >= dataLen) { + break; + } + ParamMessage *msg = (ParamMessage *)(buffer.data() + curr); + if ((msg->msgSize > dataLen) || ((curr + msg->msgSize) > dataLen)) { + break; + } + ProcessWatcherMessage(msg); + curr += msg->msgSize; } } if (serverFd_ > 0) { @@ -297,7 +288,8 @@ int WatcherManager::GetServerFd(bool retry) serverFd_ = socket(PF_UNIX, SOCK_STREAM, 0); int flags = fcntl(serverFd_, F_GETFL, 0); (void)fcntl(serverFd_, F_SETFL, flags & ~O_NONBLOCK); - if (ConnectServer(serverFd_, CLIENT_PIPE_NAME) == 0) { + int ret = ConnectServer(serverFd_, CLIENT_PIPE_NAME); + if (ret == 0) { break; } close(serverFd_); @@ -311,7 +303,7 @@ int WatcherManager::GetServerFd(bool retry) void WatcherManager::OnStart() { - WATCHER_LOGI("WatcherManager OnStart"); + WATCHER_LOGI("Watcher manager OnStart"); bool res = Publish(this); if (!res) { WATCHER_LOGE("WatcherManager Publish failed"); @@ -325,7 +317,7 @@ void WatcherManager::OnStart() void WatcherManager::StopLoop() { - WATCHER_LOGV("WatcherManager StopLoop serverFd_ %d", serverFd_); + WATCHER_LOGI("Watcher manager StopLoop serverFd_ %d", serverFd_); stop_ = true; if (serverFd_ > 0) { shutdown(serverFd_, SHUT_RDWR); @@ -341,82 +333,81 @@ void WatcherManager::StopLoop() void WatcherManager::OnStop() { - { + if (remoteWatchers_ != nullptr) { std::lock_guard lock(watcherMutex_); - for (auto iter = watchers_.begin(); iter != watchers_.end(); ++iter) { - if (iter->second == nullptr) { - continue; - } - sptr object = iter->second->GetRemoteWatcher()->AsObject(); - if (object != nullptr) { - object->RemoveDeathRecipient(deathRecipient_); - } - } + remoteWatchers_->TraversalNodeSafe([this](ParamWatcherListPtr list, WatcherNodePtr node, uint32_t index) { + RemoteWatcherPtr remoteWatcher = ConvertTo(node); + OnRemoteDied(remoteWatcher); + }); } - watchers_.clear(); - watcherGroups_.clear(); - groupMap_.clear(); + Clear(); StopLoop(); } -void WatcherManager::DeathRecipient::OnRemoteDied(const wptr &remote) +void WatcherManager::OnRemoteDied(const wptr &remote) { WATCHER_CHECK(remote != nullptr, return, "Invalid remote obj"); - auto paramWatcher = manager_->GetWatcher(remote); - WATCHER_CHECK(paramWatcher != nullptr, return, "Failed to get remote watcher info "); - WATCHER_LOGV("OnRemoteDied watcherId %u", paramWatcher->GetWatcherId()); - manager_->DelWatcher(paramWatcher->GetWatcherGroup(), paramWatcher); + auto remoteWatcher = GetRemoteWatcher(remote); + WATCHER_CHECK(remoteWatcher != nullptr, return, "Failed to get remote watcher info "); + { + std::lock_guard lock(watcherMutex_); + OnRemoteDied(remoteWatcher); + } } -WatcherManager::ParamWatcherPtr WatcherManager::GetWatcher(uint32_t watcherId) +void WatcherManager::OnRemoteDied(RemoteWatcherPtr remoteWatcher) { - std::lock_guard lock(watcherMutex_); - auto iter = watchers_.find(watcherId); - if (iter != watchers_.end()) { - return iter->second; - } - return nullptr; + WATCHER_CHECK(remoteWatcher != nullptr, return, "Invalid remote obj"); + WATCHER_LOGI("Agent died %u %u", remoteWatcher->GetRemoteWatcherId(), remoteWatcher->GetAgentId()); + remoteWatcher->TraversalNodeSafe( + [this, remoteWatcher](ParamWatcherListPtr list, WatcherNodePtr node, uint32_t index) { + auto group = GetWatcherGroup(node->GetNodeId()); + if (group == nullptr) { + return; + } + // delete node from group and remote + DelParamWatcher(group, remoteWatcher); + if (group->Empty()) { // no watcher, so delete it + SendMessage(group, MSG_DEL_WATCHER); + DelWatcherGroup(group); + } + }); + DelRemoteWatcher(remoteWatcher); } -WatcherManager::ParamWatcherPtr WatcherManager::GetWatcher(const wptr &remote) +RemoteWatcherPtr WatcherManager::GetRemoteWatcher(const wptr &remote) { std::lock_guard lock(watcherMutex_); - for (auto iter = watchers_.begin(); iter != watchers_.end(); ++iter) { - if (iter->second == nullptr) { + WatcherNodePtr node = remoteWatchers_->GetNextNode(nullptr); + while (node != nullptr) { + RemoteWatcherPtr remoteWatcher = ConvertTo(node); + if (remoteWatcher == nullptr) { continue; } - if (remote == iter->second->GetRemoteWatcher()->AsObject()) { - return iter->second; + if (remote == remoteWatcher->GetWatcher()->AsObject()) { + return remoteWatcher; } + node = remoteWatchers_->GetNextNode(node); } return nullptr; } -int WatcherManager::GetWatcherId(uint32_t &watcherId) +int WatcherManager::GetRemoteWatcherId(uint32_t &remoteWatcherId) { - std::lock_guard lock(watcherMutex_); - watcherId = watcherId_; - do { - watcherId_++; - if (watcherId_ == 0) { - watcherId_++; - } - if (watchers_.find(watcherId_) == watchers_.end()) { - break; - } - WATCHER_CHECK(watcherId_ != watcherId, return -1, "No enough watcherId %u", watcherId); - } while (1); - watcherId = watcherId_; + remoteWatcherId_++; + if (remoteWatcherId_ == 0) { + remoteWatcherId_++; + } + remoteWatcherId = remoteWatcherId_; return 0; } int WatcherManager::GetGroupId(uint32_t &groupId) { - std::lock_guard lock(watcherMutex_); groupId = groupId_; do { groupId_++; - if (watcherGroups_.find(groupId_) == watcherGroups_.end()) { + if (watcherGroups_->GetNode(groupId_) == nullptr) { break; } WATCHER_CHECK(groupId_ == groupId, return -1, "No enough groupId %u", groupId); @@ -425,57 +416,35 @@ int WatcherManager::GetGroupId(uint32_t &groupId) return 0; } -int32_t WatcherManager::RefreshWatcher(const std::string &keyPrefix, uint32_t watcherId) +void WatcherManager::DumpAllGroup(int fd, ParamWatcherProcessor dumpHandle) { - WATCHER_LOGV("RefreshWatcher %s watcherId: %u", keyPrefix.c_str(), watcherId); - auto group = GetWatcherGroup(keyPrefix); - WATCHER_CHECK(group != nullptr, return 0, "Can not find group %s", keyPrefix.c_str()); - auto paramWatcher = GetWatcher(watcherId); - WATCHER_CHECK(paramWatcher != nullptr, return 0, "Can not find watcher %s %d", keyPrefix.c_str(), watcherId); - SendLocalChange(keyPrefix, paramWatcher); - return 0; -} - -WatcherManager::ParamWatcher *WatcherManager::WatcherGroup::GetNextWatcher(WatcherManager::ParamWatcher *watcher) -{ - if (watcher == nullptr) { - if (ListEmpty(watchers_)) { - return nullptr; + // all output + uint32_t count = 0; + std::lock_guard lock(watcherMutex_); + for (auto it = groupMap_.begin(); it != groupMap_.end(); ++it) { + auto group = it->second; + if (group == nullptr) { + continue; } - return reinterpret_cast(GetWatchers()->next); - } - if (watcher->GetGroupNode() == nullptr) { - return nullptr; - } - if (watcher->GetGroupNode()->next != GetWatchers()) { - return reinterpret_cast(watcher->GetGroupNode()->next); - } - return nullptr; -} - -void WatcherManager::DumpWatcherGroup(int fd, const WatcherManager::WatcherGroupPtr &watchGroup) -{ - dprintf(fd, "Watch prefix : %s \n", watchGroup->GetKeyPrefix().c_str()); - dprintf(fd, "Watch group id : %d \n", watchGroup->GetGroupId()); - - // watcher id - WatcherManager::ParamWatcher *watcher = watchGroup->GetNextWatcher(nullptr); - if (watcher != nullptr) { - dprintf(fd, "Watch id list : %d", watcher->GetWatcherId()); - } else { - return; - } - watcher = watchGroup->GetNextWatcher(watcher); - while (watcher != nullptr) { - dprintf(fd, ", %d", watcher->GetWatcherId()); - watcher = watchGroup->GetNextWatcher(watcher); - } - dprintf(fd, "\n"); + dprintf(fd, "Watch prefix : %s \n", group->GetKeyPrefix().c_str()); + dprintf(fd, "Watch group id : %u \n", group->GetGroupId()); + dprintf(fd, "Watch count : %zu \n", group->GetNodeCount()); + group->TraversalNode(dumpHandle); + count += group->GetNodeCount(); + dprintf(fd, "\n"); + } + + dprintf(fd, "Watch prefix count : %zu [%zu %zu %zu]\n", watcherGroups_->GetNodeCount(), + sizeof(RemoteWatcher), sizeof(WatcherGroup), sizeof(WatcherNode)); + dprintf(fd, "Watch agent count : %zu \n", remoteWatchers_->GetNodeCount()); + dprintf(fd, "Watch count : %zu \n", count); } int WatcherManager::Dump(int fd, const std::vector& args) { WATCHER_CHECK(fd >= 0, return -1, "Invalid fd for dump %d", fd); + WATCHER_CHECK(remoteWatchers_ != 0, return -1, "Invalid remote watcher"); + WATCHER_CHECK(watcherGroups_ != 0, return -1, "Invalid watcher group"); std::vector params; for (auto& arg : args) { params.emplace_back(Str16ToStr8(arg)); @@ -490,24 +459,281 @@ int WatcherManager::Dump(int fd, const std::vector& args) dprintf(fd, "%s\n", dumpInfo.c_str()); return 0; } + auto DumpParamWatcher = [this, fd](ParamWatcherListPtr list, WatcherNodePtr node, uint32_t index) { + auto remoteWatcher = GetRemoteWatcher(node->GetNodeId()); + if (remoteWatcher != nullptr) { + dprintf(fd, "%s%u(%u)", (index == 0) ? "Watch id list : " : ", ", + node->GetNodeId(), remoteWatcher->GetAgentId()); + } else { + dprintf(fd, "%s%u", (index == 0) ? "Watch id list : " : ", ", node->GetNodeId()); + } + }; + if (params.size() > 1 && params[0] == "-k") { auto group = GetWatcherGroup(params[1]); if (group == NULL) { dprintf(fd, "Prefix %s not found in watcher list\n", params[1].c_str()); return 0; } - DumpWatcherGroup(fd, group); + { + std::lock_guard lock(watcherMutex_); + group->TraversalNode(DumpParamWatcher); + } return 0; } - // all output + DumpAllGroup(fd, DumpParamWatcher); + return 0; +} + +void WatcherManager::Clear(void) +{ std::lock_guard lock(watcherMutex_); - // dump all watcher - for (auto it = groupMap_.begin(); it != groupMap_.end(); it++) { - if (watcherGroups_.find(it->second) != watcherGroups_.end()) { - DumpWatcherGroup(fd, watcherGroups_[it->second]); - } + remoteWatchers_->TraversalNodeSafe([](ParamWatcherListPtr list, WatcherNodePtr node, uint32_t index) { + list->RemoveNode(node); + auto group = ConvertTo(node); + delete group; + }); + watcherGroups_->TraversalNodeSafe([](ParamWatcherListPtr list, WatcherNodePtr node, uint32_t index) { + list->RemoveNode(node); + auto remoteWatcher = ConvertTo(node); + delete remoteWatcher; + }); + delete remoteWatchers_; + remoteWatchers_ = nullptr; + delete watcherGroups_; + watcherGroups_ = nullptr; +} + +int WatcherManager::AddRemoteWatcher(RemoteWatcherPtr remoteWatcher) +{ + if (remoteWatchers_ == nullptr) { + remoteWatchers_ = new ParamWatcherList(); + WATCHER_CHECK(remoteWatchers_ != nullptr, return -1, "Failed to create watcher"); + } + return remoteWatchers_->AddNode(ConvertTo(remoteWatcher)); +} + +RemoteWatcherPtr WatcherManager::GetRemoteWatcher(uint32_t remoteWatcherId) +{ + WATCHER_CHECK(remoteWatchers_ != nullptr, return nullptr, "Invalid remote watcher"); + WatcherNodePtr node = remoteWatchers_->GetNode(remoteWatcherId); + if (node == nullptr) { + return nullptr; } + return ConvertTo(node); +} + +void WatcherManager::DelRemoteWatcher(RemoteWatcherPtr remoteWatcher) +{ + WATCHER_CHECK(remoteWatchers_ != nullptr, return, "Invalid remote watcher"); + remoteWatchers_->RemoveNode(ConvertTo(remoteWatcher)); + delete remoteWatcher; +} + +int WatcherManager::AddParamWatcher(WatcherGroupPtr group, RemoteWatcherPtr remoteWatcher) +{ + WatcherNodePtr nodeGroup = new ParamWatcher(group->GetGroupId()); + WATCHER_CHECK(nodeGroup != nullptr, return -1, "Failed to create watcher node for group"); + WatcherNodePtr nodeRemote = new ParamWatcher(remoteWatcher->GetRemoteWatcherId()); + WATCHER_CHECK(nodeRemote != nullptr, delete nodeGroup; + return -1, "Failed to create watcher node for remote watcher"); + group->AddNode(nodeRemote); + remoteWatcher->AddNode(nodeGroup); return 0; } + +int WatcherManager::DelParamWatcher(WatcherGroupPtr group, RemoteWatcherPtr remoteWatcher) +{ + WATCHER_LOGI("Delete param watcher remoteWatcherId %u group %u", + remoteWatcher->GetRemoteWatcherId(), group->GetGroupId()); + WatcherNodePtr node = group->GetNode(remoteWatcher->GetRemoteWatcherId()); + if (node != nullptr) { + group->RemoveNode(node); + delete node; + } + node = remoteWatcher->GetNode(group->GetGroupId()); + if (node != nullptr) { + remoteWatcher->RemoveNode(node); + delete node; + } + return 0; +} + +WatcherGroupPtr WatcherManager::AddWatcherGroup(const std::string &keyPrefix) +{ + std::lock_guard lock(watcherMutex_); + if (watcherGroups_ == nullptr) { + watcherGroups_ = new ParamWatcherList(); + WATCHER_CHECK(watcherGroups_ != nullptr, return nullptr, "Failed to create watcher"); + } + // get group + auto it = groupMap_.find(keyPrefix); + if (it != groupMap_.end()) { + return it->second; + } + // create group + uint32_t groupId = 0; + int ret = GetGroupId(groupId); + WATCHER_CHECK(ret == 0, return nullptr, "Failed to get group id for %s", keyPrefix.c_str()); + WatcherGroupPtr group = new WatcherGroup(groupId, keyPrefix); + WATCHER_CHECK(group != nullptr, return nullptr, "Failed to create group for %s", keyPrefix.c_str()); + watcherGroups_->AddNode(ConvertTo(group)); + groupMap_[keyPrefix] = group; + return group; +} + +WatcherGroupPtr WatcherManager::GetWatcherGroup(uint32_t groupId) +{ + WATCHER_CHECK(watcherGroups_ != nullptr, return nullptr, "Invalid watcher groups"); + WatcherNodePtr node = watcherGroups_->GetNode(groupId); + if (node == nullptr) { + return nullptr; + } + return ConvertTo(node); +} + +WatcherGroupPtr WatcherManager::GetWatcherGroup(const std::string &keyPrefix) +{ + std::lock_guard lock(watcherMutex_); + // get group + auto it = groupMap_.find(keyPrefix); + if (it != groupMap_.end()) { + return it->second; + } + return nullptr; +} + +void WatcherManager::DelWatcherGroup(WatcherGroupPtr group) +{ + WATCHER_CHECK(watcherGroups_ != nullptr, return, "Invalid watcher groups"); + WATCHER_LOGI("Delete watcher group %s %u", group->GetKeyPrefix().c_str(), group->GetGroupId()); + watcherGroups_->RemoveNode(ConvertTo(group)); + auto it = groupMap_.find(group->GetKeyPrefix()); + if (it != groupMap_.end()) { + groupMap_.erase(it); + } + delete group; +} + +int ParamWatcherList::AddNode(WatcherNodePtr node) +{ + WATCHER_CHECK(node, return -1, "Invalid input node"); + node->AddToList(&nodeList_); + nodeCount_++; + return 0; +} + +int ParamWatcherList::RemoveNode(WatcherNodePtr node) +{ + WATCHER_CHECK(node, return -1, "Invalid input node"); + node->RemoveFromList(&nodeList_); + nodeCount_--; + return 0; +} + +WatcherNodePtr ParamWatcherList::GetNode(uint32_t nodeId) +{ + return WatcherNode::GetFromList(&nodeList_, nodeId); +} + +WatcherNodePtr ParamWatcherList::GetNextNodeSafe(WatcherNodePtr node) +{ + if (node == nullptr) { // get first + return WatcherNode::GetNextFromList(&nodeList_, 0); + } + return WatcherNode::GetNextFromList(&nodeList_, node->GetNodeId()); +} + +WatcherNodePtr ParamWatcherList::GetNextNode(WatcherNodePtr node) +{ + if (node == nullptr) { // get first + return WatcherNode::GetNextFromList(&nodeList_, 0); + } + return node->GetNext(&nodeList_); +} + +void ParamWatcherList::TraversalNode(ParamWatcherProcessor handle) +{ + uint32_t index = 0; + // get first + WatcherNodePtr node = WatcherNode::GetNextFromList(&nodeList_, 0); + while (node != NULL) { + WatcherNodePtr next = node->GetNext(&nodeList_); + handle(this, node, index); + node = next; + index++; + } +} + +void ParamWatcherList::TraversalNodeSafe(ParamWatcherProcessor processor) +{ + uint32_t index = 0; + // get first + WatcherNodePtr node = WatcherNode::GetNextFromList(&nodeList_, 0); + while (node != NULL) { + uint32_t nodeId = node->GetNodeId(); + // notify free, must be free + processor(this, node, index); + node = WatcherNode::GetNextFromList(&nodeList_, nodeId); + index++; + } +} + +void WatcherNode::AddToList(ListHead *list) +{ + OH_ListAddWithOrder(list, &node_, CompareNode); +} + +void WatcherNode::RemoveFromList(ListHead *list) +{ + OH_ListRemove(&node_); +} + +WatcherNodePtr WatcherNode::GetFromList(ListHead *list, uint32_t nodeId) +{ + ListNodePtr node = OH_ListFind(list, &nodeId, CompareData); + if (node == nullptr) { + return nullptr; + } + return WatcherNode::ConvertNodeToBase(node); +} + +WatcherNodePtr WatcherNode::GetNextFromList(ListHead *list, uint32_t nodeId) +{ + ListNodePtr node = OH_ListFind(list, &nodeId, Greater); + if (node == nullptr) { + return nullptr; + } + return WatcherNode::ConvertNodeToBase(node); +} + +WatcherNodePtr WatcherNode::GetNext(ListHead *list) +{ + if (node_.next == list) { + return nullptr; + } + return WatcherNode::ConvertNodeToBase(node_.next); +} + +int WatcherNode::CompareNode(ListNodePtr node, ListNodePtr newNode) +{ + WatcherNodePtr watcher = WatcherNode::ConvertNodeToBase(node); + WatcherNodePtr newWatcher = WatcherNode::ConvertNodeToBase(node); + return watcher->nodeId_ - newWatcher->nodeId_; +} + +int WatcherNode::CompareData(ListNodePtr node, void *data) +{ + WatcherNodePtr watcher = WatcherNode::ConvertNodeToBase(node); + uint32_t id = *(uint32_t *)data; + return watcher->nodeId_ - id; +} + +int WatcherNode::Greater(ListNodePtr node, void *data) +{ + WatcherNodePtr watcher = WatcherNode::ConvertNodeToBase(node); + uint32_t id = *(uint32_t *)data; + return (watcher->nodeId_ > id) ? 0 : 1; +} } // namespace init_param } // namespace OHOS diff --git a/services/param/watcher/proxy/watcher_manager.h b/services/param/watcher/proxy/watcher_manager.h index 0d0db3f8aa1f656fa548f2b526da7cc759f8e82a..cc5956a0388ee487536728edc803c6be4313367a 100644 --- a/services/param/watcher/proxy/watcher_manager.h +++ b/services/param/watcher/proxy/watcher_manager.h @@ -27,13 +27,27 @@ #include "message_parcel.h" #include "param_utils.h" #include "parcel.h" +#include "param_message.h" #include "system_ability.h" #include "watcher_manager_stub.h" namespace OHOS { namespace init_param { +class WatcherNode; +class ParamWatcherList; +class WatcherGroup; +class RemoteWatcher; +using WatcherGroupPtr = WatcherGroup *; +using RemoteWatcherPtr = RemoteWatcher *; +using WatcherNodePtr = WatcherNode *; +using ListNodePtr = ListNode *; +using ListHeadPtr = ListHead *; +using ParamWatcherListPtr = ParamWatcherList *; +using ParamWatcherProcessor = std::function; + class WatcherManager : public SystemAbility, public WatcherManagerStub { public: + friend class WatcherGroup; DECLARE_SYSTEM_ABILITY(WatcherManager); DISALLOW_COPY_AND_MOVE(WatcherManager); explicit WatcherManager(int32_t systemAbilityId, bool runOnCreate = true) @@ -42,104 +56,28 @@ public: } ~WatcherManager() override; - class ParamWatcher; - class WatcherGroup; - using ParamWatcherPtr = std::shared_ptr; - using WatcherGroupPtr = std::shared_ptr; - // For death event procession class DeathRecipient final : public IRemoteObject::DeathRecipient { public: explicit DeathRecipient(WatcherManager *manager) : manager_(manager) {} ~DeathRecipient() final = default; DISALLOW_COPY_AND_MOVE(DeathRecipient); - void OnRemoteDied(const wptr &remote) final; + void OnRemoteDied(const wptr &remote) final + { + manager_->OnRemoteDied(remote); + } private: WatcherManager *manager_; }; - sptr GetDeathRecipient() + sptr GetDeathRecipient(void) { return deathRecipient_; } - - class ParamWatcher { - public: - ParamWatcher(uint32_t watcherId, const sptr &watcher, const WatcherGroupPtr &group) - : watcherId_(watcherId), watcher_(watcher), group_(group) - { - OH_ListInit(&groupNode_); - } - ~ParamWatcher() = default; - - uint32_t GetWatcherId() const - { - return watcherId_; - } - WatcherGroupPtr GetWatcherGroup() - { - return group_; - } - ListNode *GetGroupNode() - { - return &groupNode_; - } - sptr GetRemoteWatcher() const - { - return watcher_; - } - void ProcessParameterChange(const std::string &name, const std::string &value) - { -#ifndef STARTUP_INIT_TEST - watcher_->OnParameterChange(name, value); -#endif - } - private: - ListNode groupNode_; - uint32_t watcherId_ = { 0 }; - sptr watcher_; - WatcherGroupPtr group_ { nullptr }; - }; - - class WatcherGroup { - public: - WatcherGroup(uint32_t groupId, const std::string &key) : groupId_(groupId), keyPrefix_(key) - { - OH_ListInit(&watchers_); - } - ~WatcherGroup() = default; - void AddWatcher(const ParamWatcherPtr &watcher); - void ProcessParameterChange(const std::string &name, const std::string &value); - - const std::string GetKeyPrefix() const - { - return keyPrefix_; - } - bool Empty() const - { - return ListEmpty(watchers_); - } - uint32_t GetGroupId() const - { - return groupId_; - } - ListNode *GetWatchers() - { - return &watchers_; - } - ParamWatcher *GetNextWatcher(ParamWatcher *watcher); - private: - uint32_t groupId_; - std::string keyPrefix_ { }; - ListNode watchers_; - }; - - uint32_t AddWatcher(const std::string &keyPrefix, const sptr &watcher) override; - int32_t DelWatcher(const std::string &keyPrefix, uint32_t watcherId) override; - int32_t RefreshWatcher(const std::string &keyPrefix, uint32_t watcherId) override; - int32_t DelWatcher(WatcherGroupPtr group, ParamWatcherPtr watcher); - ParamWatcherPtr GetWatcher(uint32_t watcherId); - ParamWatcherPtr GetWatcher(const wptr &remote); - + uint32_t AddRemoteWatcher(uint32_t id, const sptr &watcher) override; + int32_t DelRemoteWatcher(uint32_t remoteWatcherId) override; + int32_t AddWatcher(const std::string &keyPrefix, uint32_t remoteWatcherId) override; + int32_t DelWatcher(const std::string &keyPrefix, uint32_t remoteWatcherId) override; + int32_t RefreshWatcher(const std::string &keyPrefix, uint32_t remoteWatcherId) override; #ifndef STARTUP_INIT_TEST protected: #endif @@ -149,33 +87,169 @@ protected: #ifndef STARTUP_INIT_TEST private: #endif - void ProcessWatcherMessage(const std::vector &buffer, uint32_t dataSize); - WatcherGroupPtr GetWatcherGroup(uint32_t groupId); - WatcherGroupPtr GetWatcherGroup(const std::string &keyPrefix); - void DelWatcherGroup(WatcherGroupPtr group); - void AddParamWatcher(const std::string &keyPrefix, WatcherGroupPtr group, ParamWatcherPtr watcher); - void DelParamWatcher(ParamWatcherPtr watcher); void RunLoop(); void StartLoop(); void StopLoop(); - void SendLocalChange(const std::string &keyPrefix, ParamWatcherPtr watcher); + void SendLocalChange(const std::string &keyPrefix, RemoteWatcherPtr &remoteWatcher); int SendMessage(WatcherGroupPtr group, int type); int GetServerFd(bool retry); - int GetWatcherId(uint32_t &watcherId); + int GetRemoteWatcherId(uint32_t &remoteWatcherId); int GetGroupId(uint32_t &groupId); - void DumpWatcherGroup(int fd, const WatcherGroupPtr &group); + // for remote watcher + int AddRemoteWatcher(RemoteWatcherPtr remoteWatcher); + RemoteWatcherPtr GetRemoteWatcher(uint32_t remoteWatcherId); + RemoteWatcherPtr GetRemoteWatcher(const wptr &remote); + void DelRemoteWatcher(RemoteWatcherPtr remoteWatcher); + // for group + WatcherGroupPtr AddWatcherGroup(const std::string &keyPrefix); + WatcherGroupPtr GetWatcherGroup(const std::string &keyPrefix); + WatcherGroupPtr GetWatcherGroup(uint32_t groupId); + void DelWatcherGroup(WatcherGroupPtr group); + // for param watcher + int AddParamWatcher(WatcherGroupPtr group, RemoteWatcherPtr remoteWatcher); + int DelParamWatcher(WatcherGroupPtr group, RemoteWatcherPtr remoteWatcher); + // for process message form init + void ProcessWatcherMessage(const ParamMessage *msg); + // for client died + void OnRemoteDied(const wptr &remote); + void OnRemoteDied(RemoteWatcherPtr remoteWatcher); + // clear + void Clear(void); + // dump + void DumpAllGroup(int fd, ParamWatcherProcessor dumpHandle); private: - std::atomic watcherId_ { 0 }; + std::atomic remoteWatcherId_ { 0 }; std::atomic groupId_ { 0 }; std::mutex mutex_; std::mutex watcherMutex_; int serverFd_ { -1 }; std::thread *pRecvThread_ { nullptr }; std::atomic stop_ { false }; - std::map groupMap_ {}; - std::map watcherGroups_ {}; - std::map watchers_ {}; + std::map groupMap_ {}; sptr deathRecipient_ {}; + ParamWatcherListPtr watcherGroups_ {}; + ParamWatcherListPtr remoteWatchers_ {}; +}; + +class WatcherNode { +public: + WatcherNode(uint32_t nodeId) : nodeId_(nodeId) + { + OH_ListInit(&node_); + } + virtual ~WatcherNode(void) = default; + uint32_t GetNodeId(void) const { return nodeId_; } + + void AddToList(ListHeadPtr list); + void RemoveFromList(ListHeadPtr list); + WatcherNodePtr GetNext(ListHeadPtr list); + static WatcherNodePtr GetFromList(ListHeadPtr list, uint32_t nodeId); + static WatcherNodePtr GetNextFromList(ListHeadPtr list, uint32_t nodeId); + static WatcherNodePtr ConvertNodeToBase(ListNodePtr node) { + WatcherNodePtr tmp = NULL; + return reinterpret_cast((char *)node - (char *)tmp->GetListNode()); + } + ListNodePtr GetListNode() { return &node_; } +private: + static int CompareNode(ListNodePtr node, ListNodePtr newNode); + static int CompareData(ListNodePtr node, void *data); + static int Greater(ListNodePtr node, void *data); + ListNode node_; + uint32_t nodeId_; +}; + +template +inline T *ConvertTo(WatcherNodePtr node) +{ +#ifdef PARAM_WATCHER_RTTI_ENABLE + // when -frtti is enabled, we use dynamic cast directly + // to achieve the correct base class side-to-side conversion. + T *obj = dynamic_cast(node); +#else + // adjust pointer position when multiple inheritance. + void *tmp = reinterpret_cast(node); + // when -frtti is not enable, we use static cast. + // static cast is not safe enough, but we have checked before we get here. + T *obj = static_cast(tmp); +#endif + return obj; +} + +class ParamWatcher : public WatcherNode { +public: + ParamWatcher(uint32_t watcherId) : WatcherNode(watcherId) {} + ~ParamWatcher(void) override {} +}; + +class ParamWatcherList { +public: + ParamWatcherList(void) + { + OH_ListInit(&nodeList_); + } + ~ParamWatcherList(void) = default; + + bool Empty(void) const + { + return nodeList_.next == &nodeList_; + } + uint32_t GetNodeCount(void) const { return nodeCount_; } + int AddNode(WatcherNodePtr node); + int RemoveNode(WatcherNodePtr node); + WatcherNodePtr GetNode(uint32_t nodeId); + WatcherNodePtr GetNextNodeSafe(WatcherNodePtr node); + WatcherNodePtr GetNextNode(WatcherNodePtr node); + void TraversalNode(ParamWatcherProcessor handle); + void TraversalNodeSafe(ParamWatcherProcessor processor); +public: + ListHead nodeList_ {}; + uint32_t nodeCount_ = 0; +}; + +class RemoteWatcher : public WatcherNode, public ParamWatcherList { +public: + RemoteWatcher(uint32_t watcherId, const sptr &watcher) + : WatcherNode(watcherId), ParamWatcherList(), watcher_(watcher) {} + ~RemoteWatcher(void) override + { + watcher_ = nullptr; + TraversalNodeSafe([](ParamWatcherListPtr list, WatcherNodePtr node, uint32_t index) { + list->RemoveNode(node); + ParamWatcher *watcher = ConvertTo(node); + delete watcher; + }); + } + + uint32_t GetRemoteWatcherId(void) const { return GetNodeId(); } + uint32_t GetAgentId(void) const { return id_; } + void SetAgentId(uint32_t id) { id_ = id; } + void ProcessParameterChange(const std::string &prefix, const std::string &name, const std::string &value) + { + watcher_->OnParameterChange(prefix, name, value); + } + sptr GetWatcher(void) { return watcher_; } +private: + uint32_t id_ = { 0 }; + sptr watcher_ {}; +}; + +class WatcherGroup : public WatcherNode, public ParamWatcherList { +public: + WatcherGroup(uint32_t groupId, const std::string &key) + : WatcherNode(groupId), ParamWatcherList(), keyPrefix_(key) {} + ~WatcherGroup() override + { + TraversalNodeSafe([](ParamWatcherListPtr list, WatcherNodePtr node, uint32_t index) { + list->RemoveNode(node); + ParamWatcher *watcher = ConvertTo(node); + delete watcher; + }); + } + void ProcessParameterChange(WatcherManager *mananger, const std::string &name, const std::string &value); + const std::string GetKeyPrefix() const { return keyPrefix_; } + uint32_t GetGroupId() const { return GetNodeId(); } +private: + std::string keyPrefix_ { }; }; } // namespace init_param } // namespace OHOS diff --git a/services/param/watcher/proxy/watcher_manager_stub.cpp b/services/param/watcher/proxy/watcher_manager_stub.cpp index b4d436edef9f30c7b6a0c9e067cf4c8fbf8aec39..2d6f0a06136c0694c8aa9fb7b155d8aef48f7665 100644 --- a/services/param/watcher/proxy/watcher_manager_stub.cpp +++ b/services/param/watcher/proxy/watcher_manager_stub.cpp @@ -21,32 +21,42 @@ namespace init_param { int32_t WatcherManagerStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) { - std::u16string myDescripter = IWatcherManager::GetDescriptor(); - std::u16string remoteDescripter = data.ReadInterfaceToken(); - WATCHER_CHECK(myDescripter == remoteDescripter, return -1, "Invalid remoteDescripter"); + std::u16string myDescriptor = IWatcherManager::GetDescriptor(); + std::u16string remoteDescriptor = data.ReadInterfaceToken(); + WATCHER_CHECK(myDescriptor == remoteDescriptor, return -1, "Invalid remoteDescriptor"); + WATCHER_LOGV("OnRemoteRequest code %u", code); switch (code) { case ADD_WATCHER: { std::string key = data.ReadString(); + int ret = AddWatcher(key, data.ReadUint32()); + reply.WriteInt32(ret); + break; + } + case DEL_WATCHER: { + std::string key = data.ReadString(); + int ret = DelWatcher(key, data.ReadUint32()); + reply.WriteInt32(ret); + break; + } + case ADD_REMOTE_AGENT: { auto remote = data.ReadRemoteObject(); // 0 is invalid watcherId WATCHER_CHECK(remote != nullptr, reply.WriteUint32(0); return 0, "Failed to read remote watcher"); - uint32_t watcherId = AddWatcher(key, iface_cast(remote)); - reply.WriteUint32(watcherId); + uint32_t id = data.ReadUint32(); + uint32_t remoteWatcherId = AddRemoteWatcher(id, iface_cast(remote)); + reply.WriteUint32(remoteWatcherId); break; } - case DEL_WATCHER: { - std::string key = data.ReadString(); - uint32_t watcherId = data.ReadUint32(); - int ret = DelWatcher(key, watcherId); + case DEL_REMOTE_AGENT: { + int ret = DelRemoteWatcher(data.ReadUint32()); reply.WriteInt32(ret); break; } case REFRESH_WATCHER: { std::string key = data.ReadString(); - uint32_t watcherId = data.ReadUint32(); - int ret = RefreshWatcher(key, watcherId); + int ret = RefreshWatcher(key, data.ReadUint32()); reply.WriteInt32(ret); break; } diff --git a/services/param/watcher/proxy/watcher_proxy.cpp b/services/param/watcher/proxy/watcher_proxy.cpp index 1fb5f61505b844847cd0c143410a76aa4879f4d2..09481cb70f0ed58f5c340276935886b822c3d4fa 100644 --- a/services/param/watcher/proxy/watcher_proxy.cpp +++ b/services/param/watcher/proxy/watcher_proxy.cpp @@ -23,9 +23,9 @@ namespace OHOS { namespace init_param { -void WatcherProxy::OnParameterChange(const std::string &name, const std::string &value) +void WatcherProxy::OnParameterChange(const std::string &prefix, const std::string &name, const std::string &value) { - WATCHER_LOGV("WatcherProxy::OnParameterChange %s %s", name.c_str(), value.c_str()); + WATCHER_LOGV("WatcherProxy::OnParameterChange %s %s %s", prefix.c_str(), name.c_str(), value.c_str()); MessageParcel data; MessageParcel reply; MessageOption option { MessageOption::TF_ASYNC }; @@ -33,10 +33,11 @@ void WatcherProxy::OnParameterChange(const std::string &name, const std::string WATCHER_CHECK(remote != nullptr, return, "Can not get remote"); data.WriteInterfaceToken(WatcherProxy::GetDescriptor()); + data.WriteString(prefix); data.WriteString(name); data.WriteString(value); int ret = remote->SendRequest(PARAM_CHANGE, data, reply, option); - WATCHER_CHECK(ret == ERR_OK, return, "Can not SendRequest for name %s", name.c_str()); + WATCHER_CHECK(ret == ERR_OK, return, "Can not SendRequest for name %s err:%d", name.c_str(), ret); return; } } diff --git a/services/param/watcher/proxy/watcher_proxy.h b/services/param/watcher/proxy/watcher_proxy.h index 5aa3fd2f3b63b1f5b8a58b6c2ea06d913cf7a871..6daf428ae5aa469f0acb6ae5ea09573ca1a56812 100644 --- a/services/param/watcher/proxy/watcher_proxy.h +++ b/services/param/watcher/proxy/watcher_proxy.h @@ -27,7 +27,7 @@ public: virtual ~WatcherProxy() = default; - void OnParameterChange(const std::string &name, const std::string &value) override; + void OnParameterChange(const std::string &prefix, const std::string &name, const std::string &value) override; private: static inline BrokerDelegator delegator_; diff --git a/test/moduletest/param_test_cmds.c b/test/moduletest/param_test_cmds.c index d1a1bc28cbc2f2510aa968f1c1167f98e3c8c7f8..9a73e6980f1a83772fa2a567bae12e3c8d9fcea5 100644 --- a/test/moduletest/param_test_cmds.c +++ b/test/moduletest/param_test_cmds.c @@ -19,12 +19,18 @@ #include "begetctl.h" #include "init_param.h" +#include "init_utils.h" #include "loop_event.h" #include "parameter.h" #include "plugin_test.h" #include "service_watcher.h" +#include "parameter.h" +#define MAX_THREAD_NUMBER 100 +#define MAX_NUMBER 10 #define READ_DURATION 100000 +#define CMD_INDEX 2 + static char *GetLocalBuffer(uint32_t *buffSize) { static char buffer[PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX] = {0}; @@ -77,24 +83,138 @@ static int32_t BShellParamCmdRead(BShellHandle shell, int32_t argc, char *argv[] return 0; } -static void HandleParamChange(const char *key, const char *value, void *context) +typedef struct { + char name[PARAM_NAME_LEN_MAX]; + pthread_t thread; +} TestWatchContext; + +static void HandleParamChange2(const char *key, const char *value, void *context) { PLUGIN_CHECK(key != NULL && value != NULL, return, "Invalid parameter"); long long commit = GetSystemCommitId(); - printf("Receive parameter commit %lld change %s %s \n", commit, key, value); + size_t index = (size_t)context; + printf("[%zu] Receive parameter %p commit %lld change %s %s \n", index, context, commit, key, value); + static int addWatcher = 0; + int ret = 0; + if ((index == 4) && !addWatcher) { // 4 when context == 4 add + index = 5; // 5 add context + ret = SystemWatchParameter(key, HandleParamChange2, (void *)index); + if (ret != 0) { + printf("Add watcher %s fail %d \n", key, index); + } + addWatcher = 1; + return; + } + if (index == 2) { // 2 when context == 2 delete 3 + index = 3; // 3 delete context + RemoveParameterWatcher(key, HandleParamChange2, (void *)index); + if (ret != 0) { + printf("Remove watcher fail %d \n", index); + } + return; + } + if (index == 1) { // 1 when context == 1 delete 1 + RemoveParameterWatcher(key, HandleParamChange2, (void *)index); + if (ret != 0) { + printf("Remove watcher fail %d \n", index); + } + return; + } + if ((index == 5) && (addWatcher == 1)) { // 5 when context == 5 delete 5 + RemoveParameterWatcher(key, HandleParamChange2, (void *)index); + if (ret != 0) { + printf("Remove watcher fail %d \n", index); + } + addWatcher = 0; + } +} + +static void HandleParamChange1(const char *key, const char *value, void *context) +{ + PLUGIN_CHECK(key != NULL && value != NULL, return, "Invalid parameter"); + long long commit = GetSystemCommitId(); + size_t index = (size_t)context; + printf("[%zu] Receive parameter commit %lld change %s %s \n", index, commit, key, value); +} + +static void *CmdThreadWatcher(void *args) +{ + TestWatchContext *context = (TestWatchContext *)args; + for (size_t i = 1; i <= MAX_NUMBER; i++) { + int ret = SystemWatchParameter(context->name, HandleParamChange2, (void *)i); + if (ret != 0) { + printf("Add watcher %s fail %d \n", context->name, i); + } + ret = SetParameter(context->name, context->name); + if (ret != 0) { + printf("Set parameter %s fail %d \n", context->name, i); + } + } + sleep(1); + for (size_t i = 1; i <= MAX_NUMBER; i++) { + int ret = RemoveParameterWatcher(context->name, HandleParamChange2, (void *)i); + if (ret != 0) { + printf("Remove watcher %s fail %d \n", context->name, i); + } + } + free(context); + return NULL; +} + +static void StartWatcherInThread(const char *prefix) +{ + TestWatchContext *context[MAX_THREAD_NUMBER] = { NULL }; + for (size_t i = 0; i < MAX_THREAD_NUMBER; i++) { + context[i] = calloc(1, sizeof(TestWatchContext)); + PLUGIN_CHECK(context[i] != NULL, return, "Failed to alloc context"); + int len = sprintf_s(context[i]->name, sizeof(context[i]->name), "%s.%zu", prefix, i); + if (len > 0) { + printf("Add watcher %s \n", context[i]->name); + pthread_create(&context[i]->thread, NULL, CmdThreadWatcher, context[i]); + } + } +} + +static void StartWatcher(const char *prefix) +{ + static size_t index = 0; + int ret = SystemWatchParameter(prefix, HandleParamChange1, (void *)index); + if (ret != 0) { + printf("Add watcher %s fail \n", prefix); + return; + } + index++; } static int32_t BShellParamCmdWatch(BShellHandle shell, int32_t argc, char *argv[]) { PLUGIN_CHECK(argc >= 1, return -1, "Invalid parameter"); PLUGIN_LOGV("BShellParamCmdWatch %s", argv[1]); - static size_t index = 0; - int ret = SystemWatchParameter(argv[1], HandleParamChange, (void *)index); - if (ret != 0) { - PLUGIN_LOGE("Failed to watch %s", argv[1]); + StartWatcher(argv[1]); + + if (argc <= CMD_INDEX) { return 0; } - index++; + if (strcmp(argv[CMD_INDEX], "thread") == 0) { // 2 cmd index + StartWatcherInThread(argv[1]); + return 0; + } + + int maxCount = StringToInt(argv[CMD_INDEX], -1); // 2 cmd index + if (maxCount <= 0 || maxCount > 65535) { // 65535 max count + PLUGIN_LOGE("Invalid input %s", argv[2]); + return 0; + } + uint32_t buffSize = 0; + char *buffer = GetLocalBuffer(&buffSize); + size_t count = 0; + while (count < (size_t)maxCount) { // 100 max count + int len = sprintf_s(buffer, buffSize, "%s.%d", argv[1], count); + PLUGIN_CHECK(len > 0, return -1, "Invalid buffer"); + buffer[len] = '\0'; + StartWatcher(buffer); + count++; + } return 0; } @@ -150,11 +270,71 @@ static int32_t BShellParamCmdUdidGet(BShellHandle shell, int32_t argc, char *arg return 0; } +static int CalcValue(const char *value) +{ + char *begin = (char *)value; + while (*begin != '\0') { + if (*begin == ' ') { + begin++; + } else { + break; + } + } + char *end = begin + strlen(begin); + while (end > begin) { + if (*end > '9' || *end < '0') { + *end = '\0'; + } + end--; + } + return StringToInt(begin, -1); +} + +static int32_t BShellParamCmdMemGet(BShellHandle shell, int32_t argc, char *argv[]) +{ + PLUGIN_CHECK(argc > 1, return -1, "Invalid parameter"); + uint32_t buffSize = 0; // 1024 max buffer for decode + char *buff = GetLocalBuffer(&buffSize); + int ret = sprintf_s(buff, buffSize - 1, "/proc/%s/smaps", argv[1]); + PLUGIN_CHECK(ret > 0, return -1, "Failed to format path %s", argv[1]); + buff[ret] = '\0'; + int all = 0; + if (argc > 2 && strcmp(argv[2], "all") == 0) { // 2 2 max arg + all = 1; + } + FILE *fp = fopen(buff, "r"); + int value = 0; + while (fp != NULL && buff != NULL && fgets(buff, buffSize, fp) != NULL) { + buff[buffSize - 1] = '\0'; + if (strncmp(buff, "Pss:", strlen("Pss:")) == 0) { + int v = CalcValue(buff + strlen("Pss:")); + if (all) { + printf("Pss: %d kb\n", v); + } + value += v; + } else if (strncmp(buff, "SwapPss:", strlen("SwapPss:")) == 0) { + int v = CalcValue(buff + strlen("SwapPss:")); + if (all) { + printf("SwapPss: %d kb\n", v); + } + value += v; + } + } + if (fp != NULL) { + fclose(fp); + printf("Total mem %d kb\n", value); + } else { + printf("Failed to get memory for %s %s \n", argv[1], buff); + } + return 0; +} + int32_t BShellCmdRegister(BShellHandle shell, int execMode) { if (execMode == 0) { const CmdInfo infos[] = { {"init", BShellParamCmdGroupTest, "init group test", "init group test [stage]", "init group test"}, + {"display", BShellParamCmdMemGet, "display memory pid", "display memory [pid]", "display memory"}, }; for (size_t i = 0; i < sizeof(infos) / sizeof(infos[0]); i++) { BShellEnvRegisterCmd(shell, &infos[i]); @@ -168,6 +348,7 @@ int32_t BShellCmdRegister(BShellHandle shell, int execMode) {"uninstall", BShellParamCmdInstall, "uninstall plugin", "uninstall [name]", ""}, {"group", BShellParamCmdGroupTest, "group test", "group test [stage]", "group test"}, {"display", BShellParamCmdUdidGet, "display udid", "display udid", "display udid"}, + {"display", BShellParamCmdMemGet, "display memory pid", "display memory [pid]", "display memory"}, }; for (size_t i = 0; i < sizeof(infos) / sizeof(infos[0]); i++) { BShellEnvRegisterCmd(GetShellHandle(), &infos[i]); diff --git a/test/unittest/param/watcher_agent_unittest.cpp b/test/unittest/param/watcher_agent_unittest.cpp index effd73a006bd1f65839f7a083f15584a259c2605..66a1a735ea50484859040d3859f7d71cee07eeb7 100644 --- a/test/unittest/param/watcher_agent_unittest.cpp +++ b/test/unittest/param/watcher_agent_unittest.cpp @@ -60,58 +60,71 @@ public: int TestAddWatcher() { size_t index = 1; - int ret = SystemWatchParameter("test.permission.watcher.test1", TestParameterChange, (void *)index); + int ret = SystemWatchParameter("test.permission.watcher.test1", + TestParameterChange, reinterpret_cast(index)); EXPECT_EQ(ret, 0); - ret = SystemWatchParameter("test.permission.watcher.test1*", TestParameterChange, (void *)index); + ret = SystemWatchParameter("test.permission.watcher.test1*", + TestParameterChange, reinterpret_cast(index)); EXPECT_EQ(ret, 0); // repeat add, return fail - ret = SystemWatchParameter("test.permission.watcher.test1", TestParameterChange, (void *)index); + ret = SystemWatchParameter("test.permission.watcher.test1", + TestParameterChange, reinterpret_cast(index)); EXPECT_NE(ret, 0); index++; - ret = SystemWatchParameter("test.permission.watcher.test1", TestParameterChange, (void *)index); + ret = SystemWatchParameter("test.permission.watcher.test1", + TestParameterChange, reinterpret_cast(index)); EXPECT_EQ(ret, 0); index++; - ret = SystemWatchParameter("test.permission.watcher.test1", TestParameterChange, (void *)index); + ret = SystemWatchParameter("test.permission.watcher.test1", + TestParameterChange, reinterpret_cast(index)); EXPECT_EQ(ret, 0); // delete - ret = RemoveParameterWatcher("test.permission.watcher.test1", TestParameterChange, (void *)index); + ret = RemoveParameterWatcher("test.permission.watcher.test1", + TestParameterChange, reinterpret_cast(index)); EXPECT_EQ(ret, 0); index--; - ret = RemoveParameterWatcher("test.permission.watcher.test1", TestParameterChange, (void *)index); + ret = RemoveParameterWatcher("test.permission.watcher.test1", + TestParameterChange, reinterpret_cast(index)); EXPECT_EQ(ret, 0); index--; - ret = RemoveParameterWatcher("test.permission.watcher.test1", TestParameterChange, (void *)index); - EXPECT_EQ(ret, 0); - ret = RemoveParameterWatcher("test.permission.watcher.test1", TestParameterChange, (void *)index); + ret = RemoveParameterWatcher("test.permission.watcher.test1", + TestParameterChange, reinterpret_cast(index)); EXPECT_EQ(ret, 0); + // has beed deleted + ret = RemoveParameterWatcher("test.permission.watcher.test1", + TestParameterChange, reinterpret_cast(index)); + EXPECT_NE(ret, 0); // 非法 ret = SystemWatchParameter("test.permission.watcher.tes^^^^t1*", TestParameterChange, nullptr); EXPECT_NE(ret, 0); ret = SystemWatchParameter("test.permission.read.test1*", TestParameterChange, nullptr); -#ifdef __MUSL__ EXPECT_EQ(ret, DAC_RESULT_FORBIDED); -#endif return 0; } int TestDelWatcher() { - int ret = SystemWatchParameter("test.permission.watcher.test1", nullptr, nullptr); + size_t index = 1; + int ret = SystemWatchParameter("test.permission.watcher.test3.1", TestParameterChange, (void *)index); + EXPECT_EQ(ret, 0); + ret = SystemWatchParameter("test.permission.watcher.test3.1*", TestParameterChange, (void *)index); + EXPECT_EQ(ret, 0); + ret = SystemWatchParameter("test.permission.watcher.test3.2", TestParameterChange, (void *)index); EXPECT_EQ(ret, 0); - ret = SystemWatchParameter("test.permission.watcher.test1*", nullptr, nullptr); + ret = SystemWatchParameter("test.permission.watcher.test3.1", nullptr, nullptr); EXPECT_EQ(ret, 0); - ret = SystemWatchParameter("test.permission.watcher.test2", nullptr, nullptr); + ret = SystemWatchParameter("test.permission.watcher.test3.1*", nullptr, nullptr); + EXPECT_EQ(ret, 0); + ret = SystemWatchParameter("test.permission.watcher.test3.2", nullptr, nullptr); EXPECT_EQ(ret, 0); // 非法 ret = SystemWatchParameter("test.permission.watcher.tes^^^^t1*", nullptr, nullptr); EXPECT_NE(ret, 0); ret = SystemWatchParameter("test.permission.read.test1*", nullptr, nullptr); -#ifdef __MUSL__ EXPECT_EQ(ret, DAC_RESULT_FORBIDED); -#endif return 0; } @@ -122,16 +135,15 @@ public: MessageOption option; data.WriteInterfaceToken(IWatcher::GetDescriptor()); data.WriteString(name); + data.WriteString(name); data.WriteString("watcherId"); - int ret = SystemWatchParameter(name.c_str(), TestParameterChange, nullptr); EXPECT_EQ(ret, 0); - OHOS::init_param::WatcherManagerKits &instance = OHOS::init_param::WatcherManagerKits::GetInstance(); - OHOS::init_param::WatcherManagerKits::ParamWatcherKitPtr watcher = instance.GetParamWatcher(name); - if (watcher != nullptr) { - watcher->OnRemoteRequest(IWatcher::PARAM_CHANGE, data, reply, option); - watcher->OnRemoteRequest(IWatcher::PARAM_CHANGE + 1, data, reply, option); - watcher->OnParameterChange("testname", "testvalue"); + WatcherManagerKits &instance = OHOS::init_param::WatcherManagerKits::GetInstance(); + if (instance.remoteWatcher_ != nullptr) { + instance.remoteWatcher_->OnRemoteRequest(IWatcher::PARAM_CHANGE, data, reply, option); + instance.remoteWatcher_->OnRemoteRequest(IWatcher::PARAM_CHANGE + 1, data, reply, option); + instance.remoteWatcher_->OnParameterChange(name.c_str(), "testname", "testvalue"); } return 0; } diff --git a/test/unittest/param/watcher_proxy_unittest.cpp b/test/unittest/param/watcher_proxy_unittest.cpp index 733299c7c185bbd82db204651bf01de1c41bf4cb..46caf2421ca20ff8a6074770bba227749911cdce 100644 --- a/test/unittest/param/watcher_proxy_unittest.cpp +++ b/test/unittest/param/watcher_proxy_unittest.cpp @@ -26,6 +26,7 @@ #include "parcel.h" #include "securec.h" #include "system_ability_definition.h" +#include "string_ex.h" #include "watcher.h" #include "watcher_manager.h" #include "watcher_proxy.h" @@ -41,7 +42,7 @@ public: TestWatcher() {} ~TestWatcher() = default; - void OnParameterChange(const std::string &name, const std::string &value) override + void OnParameterChange(const std::string &prefix, const std::string &name, const std::string &value) override { printf("TestWatcher::OnParameterChange name %s %s \n", name.c_str(), value.c_str()); } @@ -57,7 +58,7 @@ public: void TearDown() {} void TestBody() {} - int TestAddWatcher(const std::string &keyPrefix, uint32_t &watcherId) + int TestAddRemoteWatcher(uint32_t agentId, uint32_t &watcherId) { WatcherManagerPtr watcherManager = GetWatcherManager(); WATCHER_CHECK(watcherManager != nullptr, return -1, "Failed to create manager"); @@ -66,19 +67,58 @@ public: MessageOption option; data.WriteInterfaceToken(IWatcherManager::GetDescriptor()); - data.WriteString(keyPrefix); sptr watcher = new TestWatcher(); bool ret = data.WriteRemoteObject(watcher->AsObject()); WATCHER_CHECK(ret, return 0, "Can not get remote"); - watcherManager->OnRemoteRequest(IWatcherManager::ADD_WATCHER, data, reply, option); + data.WriteUint32(agentId); + watcherManager->OnRemoteRequest(IWatcherManager::ADD_REMOTE_AGENT, data, reply, option); watcherId = reply.ReadUint32(); EXPECT_NE(watcherId, 0); - EXPECT_EQ(watcherManager->GetWatcherGroup(1000) != NULL, 0); // 1000 test group id - EXPECT_EQ(watcherManager->GetWatcherGroup("TestAddWatcher") != NULL, 0); // test key not exist + + auto remoteWatcher = watcherManager->GetRemoteWatcher(watcherId); + if (remoteWatcher != nullptr) { + EXPECT_EQ(remoteWatcher->GetAgentId(), agentId); + } else { + EXPECT_EQ(0, agentId); + } + return 0; + } + + int TestDelRemoteWatcher(uint32_t watcherId) + { + WatcherManagerPtr watcherManager = GetWatcherManager(); + WATCHER_CHECK(watcherManager != nullptr, return -1, "Failed to create manager"); + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(IWatcherManager::GetDescriptor()); + data.WriteUint32(watcherId); + watcherManager->OnRemoteRequest(IWatcherManager::DEL_REMOTE_AGENT, data, reply, option); + EXPECT_EQ(reply.ReadInt32(), 0); + EXPECT_EQ(watcherManager->GetRemoteWatcher(watcherId) == nullptr, 1); + return 0; + } + + int TestAddWatcher(const std::string &keyPrefix, uint32_t watcherId) + { + WatcherManagerPtr watcherManager = GetWatcherManager(); + WATCHER_CHECK(watcherManager != nullptr, return -1, "Failed to create manager"); + MessageParcel data; + MessageParcel reply; + MessageOption option; + + data.WriteInterfaceToken(IWatcherManager::GetDescriptor()); + data.WriteString(keyPrefix); + data.WriteUint32(watcherId); + watcherManager->OnRemoteRequest(IWatcherManager::ADD_WATCHER, data, reply, option); + int ret = reply.ReadInt32(); + EXPECT_EQ(ret, 0); + EXPECT_EQ(watcherManager->GetWatcherGroup(keyPrefix) != nullptr, 1); return 0; } - int TestDelWatcher(const std::string &keyPrefix, uint32_t &watcherId) + int TestDelWatcher(const std::string &keyPrefix, uint32_t watcherId) { WatcherManagerPtr watcherManager = GetWatcherManager(); WATCHER_CHECK(watcherManager != nullptr, return -1, "Failed to create manager"); @@ -90,7 +130,6 @@ public: data.WriteUint32(watcherId); watcherManager->OnRemoteRequest(IWatcherManager::DEL_WATCHER, data, reply, option); EXPECT_EQ(reply.ReadInt32(), 0); - printf("TestDelWatcher %s watcherId %d %p \n", keyPrefix.c_str(), watcherId, watcherManager); return 0; } @@ -103,7 +142,7 @@ public: msgSize = PARAM_ALIGN(msgSize); // align std::vector buffer(msgSize, 0); ParamMessage *msg = (ParamMessage *)buffer.data(); - WATCHER_CHECK(msg != NULL, return -1, "Invalid msg"); + WATCHER_CHECK(msg != nullptr, return -1, "Invalid msg"); msg->type = MSG_NOTIFY_PARAM; msg->msgSize = msgSize; msg->id.watcherId = watcherId; @@ -112,7 +151,7 @@ public: uint32_t offset = 0; ret = FillParamMsgContent(msg, &offset, PARAM_VALUE, value.c_str(), value.size()); WATCHER_CHECK(ret == 0, return -1, "Failed to fill value"); - watcherManager->ProcessWatcherMessage(buffer, msgSize); + watcherManager->ProcessWatcherMessage(msg); return 0; } @@ -124,59 +163,61 @@ public: EXPECT_NE(remoteObj, nullptr); WatcherProxy *watcher = new WatcherProxy(remoteObj); if (watcher != nullptr) { - watcher->OnParameterChange(name, value); + watcher->OnParameterChange(name, name, value); delete watcher; } return 0; } - int TestWatchAgentDel(const std::string &keyPrefix) + int TestWatchAgentDump(const std::string &keyPrefix) { WatcherManagerPtr watcherManager = GetWatcherManager(); - WATCHER_CHECK(watcherManager != nullptr, return -1, "Failed to create manager"); - MessageParcel data; - MessageParcel reply; - MessageOption option; + // dump watcher + std::vector args = {}; + watcherManager->Dump(STDOUT_FILENO, args); + // dump parameter + args.push_back(Str8ToStr16("-h")); + watcherManager->Dump(STDOUT_FILENO, args); + args.clear(); + args.push_back(Str8ToStr16("-k")); + args.push_back(Str8ToStr16(keyPrefix.c_str())); + watcherManager->Dump(STDOUT_FILENO, args); + return 0; + } - data.WriteInterfaceToken(IWatcherManager::GetDescriptor()); - data.WriteString(keyPrefix); - sptr watcher = new TestWatcher(); - bool ret = data.WriteRemoteObject(watcher->AsObject()); - WATCHER_CHECK(ret, return 0, "Can not get remote"); - watcherManager->OnRemoteRequest(IWatcherManager::ADD_WATCHER, data, reply, option); - uint32_t watcherId = reply.ReadUint32(); - EXPECT_NE(watcherId, 0); + int TestWatchAgentDied(uint32_t watcherId) + { + WatcherManagerPtr watcherManager = GetWatcherManager(); + WATCHER_CHECK(watcherManager != nullptr, return -1, "Failed to get manager"); + auto remoteWatcher = watcherManager->GetRemoteWatcher(watcherId); + WATCHER_CHECK(remoteWatcher != nullptr, return -1, "Failed to get remote watcher"); if (watcherManager->GetDeathRecipient() != nullptr) { - watcherManager->GetDeathRecipient()->OnRemoteDied(watcher->AsObject()); + watcherManager->GetDeathRecipient()->OnRemoteDied(remoteWatcher->GetWatcher()->AsObject()); } - printf("TestWatchAgentDel %s success \n", keyPrefix.c_str()); - EXPECT_EQ(watcherManager->GetWatcher(watcherId) == nullptr, 1); + EXPECT_EQ(watcherManager->GetRemoteWatcher(watcherId) == nullptr, 1); return 0; } int TestInvalid(const std::string &keyPrefix) { WatcherManagerPtr watcherManager = GetWatcherManager(); - WATCHER_CHECK(watcherManager != nullptr, return -1, "Failed to create manager"); + WATCHER_CHECK(watcherManager != nullptr, return -1, "Failed to get manager"); MessageParcel data; MessageParcel reply; MessageOption option; data.WriteString(keyPrefix); - sptr watcher = new TestWatcher(); - bool ret = data.WriteRemoteObject(watcher->AsObject()); - WATCHER_CHECK(ret, return 0, "Can not get remote"); - watcherManager->OnRemoteRequest(IWatcherManager::ADD_WATCHER + 1, data, reply, option); + watcherManager->OnRemoteRequest(IWatcherManager::REFRESH_WATCHER + 1, data, reply, option); - if (watcherManager->GetDeathRecipient() != nullptr) { - watcherManager->GetDeathRecipient()->OnRemoteDied(watcher->AsObject()); - } + data.WriteInterfaceToken(IWatcherManager::GetDescriptor()); + data.WriteString(keyPrefix); + watcherManager->OnRemoteRequest(IWatcherManager::REFRESH_WATCHER + 1, data, reply, option); return 0; } int TestStop() { WatcherManagerPtr watcherManager = GetWatcherManager(); - WATCHER_CHECK(watcherManager != nullptr, return -1, "Failed to create manager"); + WATCHER_CHECK(watcherManager != nullptr, return -1, "Failed to get manager"); watcherManager->OnStop(); return 0; } @@ -199,61 +240,79 @@ HWTEST_F(WatcherProxyUnitTest, TestAddWatcher, TestSize.Level0) { WatcherProxyUnitTest test; uint32_t watcherId = 0; + test.TestAddRemoteWatcher(1000, watcherId); // 1000 test agent test.TestAddWatcher("test.permission.watcher.test1", watcherId); test.TestProcessWatcherMessage("test.permission.watcher.test1", watcherId); + test.TestWatchAgentDump("test.permission.watcher.test1"); } HWTEST_F(WatcherProxyUnitTest, TestAddWatcher2, TestSize.Level0) { WatcherProxyUnitTest test; uint32_t watcherId = 0; + test.TestAddRemoteWatcher(1001, watcherId); // 1001 test agent test.TestAddWatcher("test.permission.watcher.test2", watcherId); test.TestAddWatcher("test.permission.watcher.test2", watcherId); test.TestAddWatcher("test.permission.watcher.test2", watcherId); + test.TestWatchAgentDump("test.permission.watcher.test2"); } HWTEST_F(WatcherProxyUnitTest, TestAddWatcher3, TestSize.Level0) { WatcherProxyUnitTest test; uint32_t watcherId = 0; + test.TestAddRemoteWatcher(1003, watcherId); // 1003 test agent test.TestAddWatcher("test.permission.watcher.test3", watcherId); + test.TestWatchAgentDump("test.permission.watcher.test3"); } HWTEST_F(WatcherProxyUnitTest, TestAddWatcher4, TestSize.Level0) { WatcherProxyUnitTest test; uint32_t watcherId = 0; + test.TestAddRemoteWatcher(1004, watcherId); // 1004 test agent SystemSetParameter("test.watcher.test4", "1101"); SystemSetParameter("test.watcher.test4.test", "1102"); test.TestAddWatcher("test.watcher.test4*", watcherId); + test.TestWatchAgentDump("test.watcher.test4*"); } HWTEST_F(WatcherProxyUnitTest, TestAddWatcher5, TestSize.Level0) { WatcherProxyUnitTest test; uint32_t watcherId = 0; + test.TestAddRemoteWatcher(1005, watcherId); // 1005 test agent test.TestAddWatcher("test.permission.watcher.test5", watcherId); SystemSetParameter("test.permission.watcher.test5", "1101"); + test.TestWatchAgentDump("test.permission.watcher.test5"); } HWTEST_F(WatcherProxyUnitTest, TestDelWatcher, TestSize.Level0) { WatcherProxyUnitTest test; uint32_t watcherId = 0; + test.TestAddRemoteWatcher(1006, watcherId); // 1005 test agent test.TestAddWatcher("test.permission.watcher.testDel", watcherId); test.TestDelWatcher("test.permission.watcher.testDel", watcherId); + test.TestDelRemoteWatcher(watcherId); + test.TestWatchAgentDump("test.permission.watcher.testDel"); } -HWTEST_F(WatcherProxyUnitTest, TestWatchProxy, TestSize.Level0) +HWTEST_F(WatcherProxyUnitTest, TestDiedWatcher, TestSize.Level0) { WatcherProxyUnitTest test; - test.TestWatchProxy("test.permission.watcher.test1", "watcherId"); + uint32_t watcherId = 0; + test.TestAddRemoteWatcher(1006, watcherId); // 1005 test agent + test.TestAddWatcher("test.permission.watcher.testdied", watcherId); + test.TestDelWatcher("test.permission.watcher.testdied", watcherId); + test.TestWatchAgentDied(watcherId); + test.TestWatchAgentDump("test.permission.watcher.testdied"); } -HWTEST_F(WatcherProxyUnitTest, TestWatchAgentDel, TestSize.Level0) +HWTEST_F(WatcherProxyUnitTest, TestWatchProxy, TestSize.Level0) { WatcherProxyUnitTest test; - test.TestWatchAgentDel("test.permission.watcher.test1"); + test.TestWatchProxy("test.permission.watcher.test1", "watcherId"); } HWTEST_F(WatcherProxyUnitTest, TestInvalid, TestSize.Level0)