1/*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15#include "watcher_manager_kits.h"
16
17#include "if_system_ability_manager.h"
18#include "init_param.h"
19#include "iservice_registry.h"
20#include "iwatcher.h"
21#include "iwatcher_manager.h"
22#include "system_ability_definition.h"
23#include "watcher_utils.h"
24#include "parameter.h"
25#include "init_param.h"
26
27namespace OHOS {
28namespace init_param {
29WatcherManagerKits &WatcherManagerKits::GetInstance(void)
30{
31    return DelayedRefSingleton<WatcherManagerKits>::GetInstance();
32}
33
34WatcherManagerKits::WatcherManagerKits(void) {}
35
36WatcherManagerKits::~WatcherManagerKits(void) {}
37
38void WatcherManagerKits::ResetService(const wptr<IRemoteObject> &remote)
39{
40    WATCHER_LOGI("Remote is dead, reset service instance");
41    std::lock_guard<std::mutex> lock(lock_);
42    if (watcherManager_ != nullptr) {
43        sptr<IRemoteObject> object = watcherManager_->AsObject();
44        if ((object != nullptr) && (remote == object)) {
45            object->RemoveDeathRecipient(deathRecipient_);
46            watcherManager_ = nullptr;
47            remoteWatcherId_ = 0;
48            remoteWatcher_ = nullptr;
49            if (threadForReWatch_ != nullptr) {
50                WATCHER_LOGI("Thead exist, delete thread");
51                stop_ = true;
52                threadForReWatch_->join();
53                delete threadForReWatch_;
54            }
55            stop_ = false;
56            threadForReWatch_ = new (std::nothrow)std::thread([this] {this->ReAddWatcher();});
57            WATCHER_CHECK(threadForReWatch_ != nullptr, return, "Failed to create thread");
58        }
59    }
60}
61
62sptr<IWatcherManager> WatcherManagerKits::GetService(void)
63{
64    std::lock_guard<std::mutex> lock(lock_);
65    if (watcherManager_ != nullptr) {
66        return watcherManager_;
67    }
68
69    sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
70    WATCHER_CHECK(samgr != nullptr, return nullptr, "Get samgr failed");
71    sptr<IRemoteObject> object = samgr->GetSystemAbility(PARAM_WATCHER_DISTRIBUTED_SERVICE_ID);
72    WATCHER_CHECK(object != nullptr, return nullptr, "Get watcher manager object from samgr failed");
73    if (deathRecipient_ == nullptr) {
74        deathRecipient_ = new DeathRecipient();
75    }
76
77    if ((object->IsProxyObject()) && (!object->AddDeathRecipient(deathRecipient_))) {
78        WATCHER_LOGE("Failed to add death recipient");
79    }
80    watcherManager_ = iface_cast<IWatcherManager>(object);
81    return watcherManager_;
82}
83
84void WatcherManagerKits::DeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
85{
86    DelayedRefSingleton<WatcherManagerKits>::GetInstance().ResetService(remote);
87}
88
89void WatcherManagerKits::ReAddWatcher(void)
90{
91    WATCHER_LOGV("ReAddWatcher");
92    int count = 0;
93    const int maxRetryCount = 100;
94    const int sleepTime = 100;
95    auto watcherManager = GetService();
96    while (watcherManager == nullptr && count < maxRetryCount) {
97        if (stop_) {
98            return;
99        }
100        watcherManager = GetService();
101        usleep(sleepTime);
102        count++;
103    }
104    WATCHER_LOGV("ReAddWatcher count %d ", count);
105    WATCHER_CHECK(watcherManager != nullptr, return, "Failed to get watcher manager");
106    // add or get remote agent
107    uint32_t remoteWatcherId = GetRemoteWatcher();
108    WATCHER_CHECK(remoteWatcherId > 0, return, "Failed to get remote agent");
109    std::lock_guard<std::mutex> lock(mutex_);
110    for (auto iter = watchers_.begin(); iter != watchers_.end(); iter++) {
111        WATCHER_LOGI("Add old watcher keyPrefix %s ", iter->first.c_str());
112        int ret = watcherManager->AddWatcher(iter->first, remoteWatcherId);
113        WATCHER_CHECK(ret == 0, continue, "Failed to add watcher for %s", iter->first.c_str());
114    }
115}
116
117WatcherManagerKits::ParamWatcher *WatcherManagerKits::GetParamWatcher(const std::string &keyPrefix)
118{
119    std::lock_guard<std::mutex> lock(mutex_);
120    auto iter = watchers_.find(keyPrefix);
121    if (iter != watchers_.end()) {
122        return iter->second.get();
123    }
124    return nullptr;
125}
126
127uint32_t WatcherManagerKits::GetRemoteWatcher(void)
128{
129    std::lock_guard<std::mutex> lock(mutex_);
130    if (remoteWatcher_ != nullptr) {
131        return remoteWatcherId_;
132    }
133    auto watcherManager = GetService();
134    WATCHER_CHECK(watcherManager != nullptr, return 0, "Failed to get watcher manager");
135    remoteWatcher_  = new RemoteWatcher(this);
136    WATCHER_CHECK(remoteWatcher_ != nullptr, return 0, "Failed to create watcher");
137    remoteWatcherId_ = watcherManager->AddRemoteWatcher(getpid(), remoteWatcher_);
138    WATCHER_CHECK(remoteWatcherId_ != 0, return 0, "Failed to add watcher");
139    return remoteWatcherId_;
140}
141
142int32_t WatcherManagerKits::AddWatcher(const std::string &keyPrefix, ParameterChangePtr callback, void *context)
143{
144    auto watcherManager = GetService();
145    WATCHER_CHECK(watcherManager != nullptr, return PARAM_WATCHER_GET_SERVICE_FAILED, "Failed to get watcher manager");
146
147    // add or get remote agent
148    uint32_t remoteWatcherId = GetRemoteWatcher();
149    WATCHER_CHECK(remoteWatcherId > 0, return -1, "Failed to get remote agent");
150    ParamWatcherKitPtr watcher = nullptr;
151    {
152        std::lock_guard<std::mutex> lock(mutex_);
153        // must check
154        WATCHER_CHECK(remoteWatcherId > 0, return -1, "Failed to get remote agent");
155        if (watchers_.find(keyPrefix) == watchers_.end()) {
156            watcher = std::make_shared<ParamWatcher>(keyPrefix);
157            WATCHER_CHECK(watcher != nullptr, return -1, "Failed to create watcher for %s", keyPrefix.c_str());
158            int ret = watcher->AddParameterListener(callback, context);
159            WATCHER_CHECK(ret == 0, return ret, "Failed to add callback for %s ", keyPrefix.c_str());
160            ret = watcherManager->AddWatcher(keyPrefix, remoteWatcherId);
161            WATCHER_CHECK(ret == 0, return -1, "Failed to add watcher for %s", keyPrefix.c_str());
162            watchers_[keyPrefix] = watcher;
163        } else {
164            watcher = watchers_[keyPrefix];
165            int ret = watcher->AddParameterListener(callback, context);
166            WATCHER_CHECK(ret == 0, return ret, "Failed to add callback for %s ", keyPrefix.c_str());
167            ret = watcherManager->RefreshWatcher(keyPrefix, remoteWatcherId);
168            WATCHER_CHECK(ret == 0, return -1,
169                "Failed to refresh watcher for %s %d", keyPrefix.c_str(), remoteWatcherId);
170        }
171    }
172    WATCHER_LOGI("Add watcher keyPrefix %s remoteWatcherId %u success", keyPrefix.c_str(), remoteWatcherId);
173    return 0;
174}
175
176int32_t WatcherManagerKits::DelWatcher(const std::string &keyPrefix, ParameterChangePtr callback, void *context)
177{
178    auto watcherManager = GetService();
179    WATCHER_CHECK(watcherManager != nullptr, return -1, "Failed to get watcher manager");
180
181    WatcherManagerKits::ParamWatcher *watcher = GetParamWatcher(keyPrefix);
182    WATCHER_CHECK(watcher != nullptr, return -1, "Failed to get watcher");
183
184    int count = watcher->DelParameterListener(callback, context);
185    WATCHER_LOGI("DelWatcher keyPrefix_ %s count %d", keyPrefix.c_str(), count);
186    if (count != 0) {
187        return 0;
188    }
189    // delete watcher
190    int ret = watcherManager->DelWatcher(keyPrefix, remoteWatcherId_);
191    WATCHER_CHECK(ret == 0, return -1, "Failed to delete watcher for %s", keyPrefix.c_str());
192    {
193        std::lock_guard<std::mutex> lock(mutex_);
194        auto it = watchers_.find(keyPrefix); // delete watcher
195        if (it != watchers_.end()) {
196            watchers_.erase(it);
197        }
198        if (watchers_.empty()) { // no watcher, so delete remote agent
199            watcherManager->DelRemoteWatcher(remoteWatcherId_);
200            remoteWatcherId_ = 0;
201            remoteWatcher_ = nullptr;
202        }
203    }
204    return 0;
205}
206
207WatcherManagerKits::ParameterChangeListener *WatcherManagerKits::ParamWatcher::GetParameterListener(uint32_t *idx)
208{
209    uint32_t index = *idx;
210    if (parameterChangeListeners.empty()) {
211        return nullptr;
212    }
213    while (index < listenerId_) {
214        auto it = parameterChangeListeners.find(index);
215        if (it != parameterChangeListeners.end()) {
216            *idx = index;
217            return parameterChangeListeners[index].get();
218        }
219        index++;
220    }
221    return nullptr;
222}
223
224void WatcherManagerKits::ParamWatcher::RemoveParameterListener(uint32_t idx)
225{
226    auto it = parameterChangeListeners.find(idx);
227    if (it != parameterChangeListeners.end()) {
228        parameterChangeListeners.erase(it);
229    }
230}
231
232int WatcherManagerKits::ParamWatcher::AddParameterListener(ParameterChangePtr callback, void *context)
233{
234    std::lock_guard<std::mutex> lock(mutex_);
235    WATCHER_CHECK(callback != nullptr, return -1, "Invalid callback ");
236    WATCHER_LOGV("AddParameterListener %s listenerId_ %d", keyPrefix_.c_str(), listenerId_);
237    for (auto it = parameterChangeListeners.begin(); it != parameterChangeListeners.end(); it++) {
238        if (it->second == nullptr) {
239            continue;
240        }
241        if (it->second->IsEqual(callback, context)) {
242            return PARAM_WATCHER_CALLBACK_EXIST;
243        }
244    }
245    std::shared_ptr<ParameterChangeListener> changeNode =
246        std::make_shared<ParameterChangeListener>(callback, context);
247    WATCHER_CHECK(changeNode != nullptr, return -1, "Failed to create listener");
248    parameterChangeListeners[listenerId_] = changeNode;
249    listenerId_++;
250    return 0;
251}
252
253int WatcherManagerKits::ParamWatcher::DelParameterListener(ParameterChangePtr callback, void *context)
254{
255    std::lock_guard<std::mutex> lock(mutex_);
256    if (callback == nullptr) {
257        parameterChangeListeners.clear();
258        return 0;
259    }
260    uint32_t index = 0;
261    ParameterChangeListener *listener = GetParameterListener(&index);
262    while (listener != nullptr) {
263        if (listener->IsEqual(callback, context)) {
264            WATCHER_LOGV("DelParameterListener listenerId_ %d", index);
265            RemoveParameterListener(index);
266            break;
267        }
268        index++;
269        listener = GetParameterListener(&index);
270    }
271    return static_cast<int>(parameterChangeListeners.size());
272}
273
274void WatcherManagerKits::RemoteWatcher::OnParameterChange(
275    const std::string &prefix, const std::string &name, const std::string &value)
276{
277    Watcher::OnParameterChange(prefix, name, value);
278    // get param watcher
279    WatcherManagerKits::ParamWatcher *watcher = watcherManager_->GetParamWatcher(prefix);
280    WATCHER_CHECK(watcher != nullptr, return, "Failed to get watcher '%s'", prefix.c_str());
281    if (watcher != nullptr) {
282        watcher->OnParameterChange(name, value);
283    }
284}
285
286void WatcherManagerKits::ParamWatcher::OnParameterChange(const std::string &name, const std::string &value)
287{
288    std::lock_guard<std::mutex> lock(mutex_);
289    WATCHER_LOGV("OnParameterChange name %s value %s", name.c_str(), value.c_str());
290    uint32_t index = 0;
291    ParameterChangeListener *listener = GetParameterListener(&index);
292    while (listener != nullptr) {
293        if (!listener->CheckValueChange(name, value)) {
294            listener->OnParameterChange(name, value);
295        }
296        index++;
297        listener = GetParameterListener(&index);
298    }
299}
300
301void WatcherManagerKits::ParameterChangeListener::OnParameterChange(const std::string &name, const std::string &value)
302{
303    if (callback_ != nullptr) {
304        callback_(name.c_str(), value.c_str(), context_);
305    }
306}
307} // namespace init_param
308} // namespace OHOS
309
310static int PreHandleWatchParam(std::string &prefix)
311{
312    // clear space in head or tail
313    prefix.erase(0, prefix.find_first_not_of(" "));
314    prefix.erase(prefix.find_last_not_of(" ") + 1);
315    WATCHER_CHECK(!prefix.empty(), return PARAM_CODE_INVALID_PARAM, "Invalid prefix");
316    int ret = 0;
317    if (prefix.rfind(".*") == prefix.length() - 2) { // 2 last index
318        ret = WatchParamCheck(prefix.substr(0, prefix.length() - 2).c_str()); // 2 last index
319    } else if (prefix.rfind("*") == prefix.length() - 1) {
320        ret = WatchParamCheck(prefix.substr(0, prefix.length() - 1).c_str());
321    } else if (prefix.rfind(".") == prefix.length() - 1) {
322        ret = WatchParamCheck(prefix.substr(0, prefix.length() - 1).c_str());
323    } else {
324        ret = WatchParamCheck(prefix.c_str());
325    }
326    return ret;
327}
328
329int SystemWatchParameter(const char *keyPrefix, ParameterChangePtr callback, void *context)
330{
331    WATCHER_CHECK(keyPrefix != nullptr, return PARAM_CODE_INVALID_PARAM, "Invalid prefix");
332    std::string key(keyPrefix);
333    int ret = PreHandleWatchParam(key);
334    if (ret != 0) {
335        return ret;
336    }
337    OHOS::init_param::WatcherManagerKits &instance = OHOS::init_param::WatcherManagerKits::GetInstance();
338    if (callback != nullptr) {
339        ret = instance.AddWatcher(keyPrefix, callback, context);
340    } else {
341        ret = instance.DelWatcher(keyPrefix, nullptr, nullptr);
342    }
343
344    if (ret != 0) {
345        WATCHER_LOGE("SystemWatchParameter is failed! keyPrefix is:%s, errNum is:%d", keyPrefix, ret);
346    }
347    return ret;
348}
349
350int RemoveParameterWatcher(const char *keyPrefix, ParameterChgPtr callback, void *context)
351{
352    WATCHER_CHECK(keyPrefix != nullptr, return PARAM_CODE_INVALID_PARAM, "Invalid prefix");
353    std::string key(keyPrefix);
354    int ret = PreHandleWatchParam(key);
355    if (ret != 0) {
356        return ret;
357    }
358    OHOS::init_param::WatcherManagerKits &instance = OHOS::init_param::WatcherManagerKits::GetInstance();
359    ret = instance.DelWatcher(keyPrefix, (ParameterChangePtr)callback, context);
360    if (ret != 0) {
361        WATCHER_LOGE("RemoveParameterWatcher is failed! keyPrefix is:%s, errNum is:%d", keyPrefix, ret);
362    }
363    return ret;
364}