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