watcher_manager_kits.cpp 13.7 KB
Newer Older
S
sun_fan 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "watcher_manager_kits.h"

#include "if_system_ability_manager.h"
M
Mupceet 已提交
18
#include "init_param.h"
S
sun_fan 已提交
19 20 21 22 23
#include "iservice_registry.h"
#include "iwatcher.h"
#include "iwatcher_manager.h"
#include "system_ability_definition.h"
#include "watcher_utils.h"
C
cheng_jinsong 已提交
24
#include "parameter.h"
S
sun_fan 已提交
25 26 27

namespace OHOS {
namespace init_param {
C
watcher  
cheng_jinsong 已提交
28
WatcherManagerKits &WatcherManagerKits::GetInstance(void)
S
sun_fan 已提交
29 30 31 32
{
    return DelayedRefSingleton<WatcherManagerKits>::GetInstance();
}

C
watcher  
cheng_jinsong 已提交
33
WatcherManagerKits::WatcherManagerKits(void) {}
S
sun_fan 已提交
34

C
watcher  
cheng_jinsong 已提交
35
WatcherManagerKits::~WatcherManagerKits(void) {}
S
sun_fan 已提交
36 37 38 39

void WatcherManagerKits::ResetService(const wptr<IRemoteObject> &remote)
{
    WATCHER_LOGI("Remote is dead, reset service instance");
C
watcher  
cheng_jinsong 已提交
40 41 42 43 44 45 46 47 48 49 50 51 52
    std::lock_guard<std::mutex> lock(lock_);
    if (watcherManager_ != nullptr) {
        sptr<IRemoteObject> 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_;
X
add ut  
xionglei6 已提交
53
            }
C
watcher  
cheng_jinsong 已提交
54 55 56
            stop_ = false;
            threadForReWatch_ = new (std::nothrow)std::thread(&WatcherManagerKits::ReAddWatcher, this);
            WATCHER_CHECK(threadForReWatch_ != nullptr, return, "Failed to create thread");
S
sun_fan 已提交
57 58 59 60
        }
    }
}

C
watcher  
cheng_jinsong 已提交
61
sptr<IWatcherManager> WatcherManagerKits::GetService(void)
S
sun_fan 已提交
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
{
    std::lock_guard<std::mutex> lock(lock_);
    if (watcherManager_ != nullptr) {
        return watcherManager_;
    }

    sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
    WATCHER_CHECK(samgr != nullptr, return nullptr, "Get samgr failed");
    sptr<IRemoteObject> object = samgr->GetSystemAbility(PARAM_WATCHER_DISTRIBUTED_SERVICE_ID);
    WATCHER_CHECK(object != nullptr, return nullptr, "Get watcher manager object from samgr failed");
    if (deathRecipient_ == nullptr) {
        deathRecipient_ = new DeathRecipient();
    }

    if ((object->IsProxyObject()) && (!object->AddDeathRecipient(deathRecipient_))) {
        WATCHER_LOGE("Failed to add death recipient");
    }
    watcherManager_ = iface_cast<IWatcherManager>(object);
    return watcherManager_;
}

void WatcherManagerKits::DeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
{
    DelayedRefSingleton<WatcherManagerKits>::GetInstance().ResetService(remote);
}

C
watcher  
cheng_jinsong 已提交
88
void WatcherManagerKits::ReAddWatcher(void)
X
add ut  
xionglei6 已提交
89
{
C
watcher  
cheng_jinsong 已提交
90
    WATCHER_LOGV("ReAddWatcher");
X
add ut  
xionglei6 已提交
91 92 93 94 95
    int count = 0;
    const int maxRetryCount = 100;
    const int sleepTime = 100;
    auto watcherManager = GetService();
    while (watcherManager == nullptr && count < maxRetryCount) {
C
watcher  
cheng_jinsong 已提交
96 97 98
        if (stop_) {
            return;
        }
X
add ut  
xionglei6 已提交
99 100 101 102
        watcherManager = GetService();
        usleep(sleepTime);
        count++;
    }
C
watcher  
cheng_jinsong 已提交
103
    WATCHER_LOGV("ReAddWatcher count %d ", count);
X
add ut  
xionglei6 已提交
104
    WATCHER_CHECK(watcherManager != nullptr, return, "Failed to get watcher manager");
C
watcher  
cheng_jinsong 已提交
105 106 107
    // add or get remote agent
    uint32_t remoteWatcherId = GetRemoteWatcher();
    WATCHER_CHECK(remoteWatcherId > 0, return, "Failed to get remote agent");
X
add ut  
xionglei6 已提交
108 109
    std::lock_guard<std::mutex> lock(mutex_);
    for (auto iter = watchers_.begin(); iter != watchers_.end(); iter++) {
C
watcher  
cheng_jinsong 已提交
110 111 112 113 114 115 116 117 118 119 120 121
        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<std::mutex> lock(mutex_);
    auto iter = watchers_.find(keyPrefix);
    if (iter != watchers_.end()) {
        return iter->second.get();
X
add ut  
xionglei6 已提交
122
    }
C
watcher  
cheng_jinsong 已提交
123 124 125 126 127 128 129 130 131 132 133 134 135
    return nullptr;
}

uint32_t WatcherManagerKits::GetRemoteWatcher(void)
{
    std::lock_guard<std::mutex> 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");
C
test  
chengjinsong2 已提交
136
    WATCHER_LOGE("CJ WatcherManagerKits::GetRemoteWatcher remoteWatcher_ addr is:%p", static_cast<void*>(remoteWatcher_));
C
watcher  
cheng_jinsong 已提交
137 138 139
    remoteWatcherId_ = watcherManager->AddRemoteWatcher(getpid(), remoteWatcher_);
    WATCHER_CHECK(remoteWatcherId_ != 0, return 0, "Failed to add watcher");
    return remoteWatcherId_;
X
add ut  
xionglei6 已提交
140 141
}

S
sun_fan 已提交
142 143 144
int32_t WatcherManagerKits::AddWatcher(const std::string &keyPrefix, ParameterChangePtr callback, void *context)
{
    auto watcherManager = GetService();
M
codex  
Mupceet 已提交
145
    WATCHER_CHECK(watcherManager != nullptr, return -1, "Failed to get watcher manager");
C
cheng_jinsong 已提交
146

C
watcher  
cheng_jinsong 已提交
147 148 149
    // add or get remote agent
    uint32_t remoteWatcherId = GetRemoteWatcher();
    WATCHER_CHECK(remoteWatcherId > 0, return -1, "Failed to get remote agent");
C
cheng_jinsong 已提交
150 151 152
    ParamWatcherKitPtr watcher = nullptr;
    {
        std::lock_guard<std::mutex> lock(mutex_);
C
watcher  
cheng_jinsong 已提交
153 154
        // must check
        WATCHER_CHECK(remoteWatcherId > 0, return -1, "Failed to get remote agent");
C
cheng_jinsong 已提交
155
        if (watchers_.find(keyPrefix) == watchers_.end()) {
C
watcher  
cheng_jinsong 已提交
156
            watcher = std::make_shared<ParamWatcher>(keyPrefix);
C
cheng_jinsong 已提交
157 158 159
            WATCHER_CHECK(watcher != nullptr, return -1, "Failed to create watcher for %s", keyPrefix.c_str());
            int ret = watcher->AddParameterListener(callback, context);
            WATCHER_CHECK(ret == 0, return -1, "Failed to add callback for %s ", keyPrefix.c_str());
C
watcher  
cheng_jinsong 已提交
160 161 162
            ret = watcherManager->AddWatcher(keyPrefix, remoteWatcherId);
            WATCHER_CHECK(ret == 0, return -1, "Failed to add watcher for %s", keyPrefix.c_str());
            watchers_[keyPrefix] = watcher;
C
cheng_jinsong 已提交
163 164
        } else {
            watcher = watchers_[keyPrefix];
C
watcher  
cheng_jinsong 已提交
165 166 167 168 169
            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);
C
cheng_jinsong 已提交
170 171
        }
    }
C
watcher  
cheng_jinsong 已提交
172
    WATCHER_LOGI("Add watcher keyPrefix %s remoteWatcherId %u success", keyPrefix.c_str(), remoteWatcherId);
C
cheng_jinsong 已提交
173
    return 0;
S
sun_fan 已提交
174 175
}

C
cheng_jinsong 已提交
176
int32_t WatcherManagerKits::DelWatcher(const std::string &keyPrefix, ParameterChangePtr callback, void *context)
S
sun_fan 已提交
177 178 179
{
    auto watcherManager = GetService();
    WATCHER_CHECK(watcherManager != nullptr, return -1, "Failed to get watcher manager");
C
watcher  
cheng_jinsong 已提交
180 181 182 183

    WatcherManagerKits::ParamWatcher *watcher = GetParamWatcher(keyPrefix);
    WATCHER_CHECK(watcher != nullptr, return -1, "Failed to get watcher");

C
cheng_jinsong 已提交
184 185
    int count = watcher->DelParameterListener(callback, context);
    WATCHER_LOGI("DelWatcher keyPrefix_ %s count %d", keyPrefix.c_str(), count);
C
watcher  
cheng_jinsong 已提交
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
    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<std::mutex> 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;
C
test  
chengjinsong2 已提交
201
            WATCHER_LOGE("CJ WatcherManagerKits::DelWatcher remoteWatcher_ addr is:%p", static_cast<void*>(remoteWatcher_));
C
watcher  
cheng_jinsong 已提交
202
            remoteWatcher_ = nullptr;
C
cheng_jinsong 已提交
203 204 205 206 207 208 209 210 211
        }
    }
    return 0;
}

WatcherManagerKits::ParameterChangeListener *WatcherManagerKits::ParamWatcher::GetParameterListener(uint32_t *idx)
{
    std::lock_guard<std::mutex> lock(mutex_);
    uint32_t index = *idx;
C
watcher  
cheng_jinsong 已提交
212 213 214 215
    if (parameterChangeListeners.empty()) {
        return nullptr;
    }
    while (index < listenerId_) {
C
cheng_jinsong 已提交
216 217 218 219 220 221 222 223 224 225 226 227 228
        auto it = parameterChangeListeners.find(index);
        if (it != parameterChangeListeners.end()) {
            *idx = index;
            return parameterChangeListeners[index].get();
        }
        index++;
    }
    return nullptr;
}

void WatcherManagerKits::ParamWatcher::RemoveParameterListener(uint32_t idx)
{
    std::lock_guard<std::mutex> lock(mutex_);
C
watcher  
cheng_jinsong 已提交
229 230 231
    auto it = parameterChangeListeners.find(idx);
    if (it != parameterChangeListeners.end()) {
        parameterChangeListeners.erase(it);
C
cheng_jinsong 已提交
232 233 234 235 236 237
    }
}

int WatcherManagerKits::ParamWatcher::AddParameterListener(ParameterChangePtr callback, void *context)
{
    WATCHER_CHECK(callback != nullptr, return -1, "Invalid callback ");
C
chengjinsong2 已提交
238
    WATCHER_LOGV("AddParameterListener %s listenerId_ %d", keyPrefix_.c_str(), listenerId_);
C
cheng_jinsong 已提交
239 240 241 242 243 244
    for (auto it = parameterChangeListeners.begin(); it != parameterChangeListeners.end(); it++) {
        if (it->second == nullptr) {
            continue;
        }
        if (it->second->IsEqual(callback, context)) {
            return -1;
X
xionglei6 已提交
245 246
        }
    }
C
cheng_jinsong 已提交
247 248 249 250 251
    std::shared_ptr<ParameterChangeListener> changeNode =
        std::make_shared<ParameterChangeListener>(callback, context);
    WATCHER_CHECK(changeNode != nullptr, return -1, "Failed to create listener");
    parameterChangeListeners[listenerId_] = changeNode;
    listenerId_++;
S
sun_fan 已提交
252 253 254
    return 0;
}

C
cheng_jinsong 已提交
255 256
int WatcherManagerKits::ParamWatcher::DelParameterListener(ParameterChangePtr callback, void *context)
{
C
watcher  
cheng_jinsong 已提交
257 258 259 260
    if (callback == nullptr) {
        parameterChangeListeners.clear();
        return 0;
    }
C
cheng_jinsong 已提交
261 262
    uint32_t index = 0;
    ParameterChangeListener *listener = GetParameterListener(&index);
C
codex  
chengjinsong 已提交
263
    while (listener != nullptr) {
C
watcher  
cheng_jinsong 已提交
264
        if (listener->IsEqual(callback, context)) {
C
chengjinsong2 已提交
265
            WATCHER_LOGV("DelParameterListener listenerId_ %d", index);
C
cheng_jinsong 已提交
266 267 268 269 270 271 272 273 274
            RemoveParameterListener(index);
            break;
        }
        index++;
        listener = GetParameterListener(&index);
    }
    return static_cast<int>(parameterChangeListeners.size());
}

C
watcher  
cheng_jinsong 已提交
275
void WatcherManagerKits::RemoteWatcher::OnParameterChange(
C
codex  
chengjinsong 已提交
276
    const std::string &prefix, const std::string &name, const std::string &value)
C
watcher  
cheng_jinsong 已提交
277
{
C
cheng_jinsong 已提交
278
    Watcher::OnParameterChange(prefix, name, value);
C
watcher  
cheng_jinsong 已提交
279 280 281 282 283 284 285 286 287 288 289 290 291 292
    // 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) {
C
cheng_jinsong 已提交
293
        if (!listener->CheckValueChange(name, value)) {
C
watcher  
cheng_jinsong 已提交
294 295 296 297 298 299 300
            listener->OnParameterChange(name, value);
        }
        index++;
        listener = GetParameterListener(&index);
    }
}

C
cheng_jinsong 已提交
301
void WatcherManagerKits::ParameterChangeListener::OnParameterChange(const std::string &name, const std::string &value)
S
sun_fan 已提交
302 303 304 305 306 307 308 309
{
    if (callback_ != nullptr) {
        callback_(name.c_str(), value.c_str(), context_);
    }
}
} // namespace init_param
} // namespace OHOS

C
watcher  
cheng_jinsong 已提交
310
static int PreHandleWatchParam(std::string &prefix)
S
sun_fan 已提交
311
{
C
watcher  
cheng_jinsong 已提交
312 313 314 315 316 317 318 319 320 321 322
    // 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());
S
sun_fan 已提交
323
    } else {
C
watcher  
cheng_jinsong 已提交
324
        ret = WatchParamCheck(prefix.c_str());
S
sun_fan 已提交
325
    }
C
watcher  
cheng_jinsong 已提交
326
    return ret;
C
chengjinsong 已提交
327 328 329 330 331
}

int SystemWatchParameter(const char *keyPrefix, ParameterChangePtr callback, void *context)
{
    WATCHER_CHECK(keyPrefix != nullptr, return PARAM_CODE_INVALID_PARAM, "Invalid prefix");
C
watcher  
cheng_jinsong 已提交
332 333
    std::string key(keyPrefix);
    int ret = PreHandleWatchParam(key);
S
sun_fan 已提交
334 335 336 337 338
    if (ret != 0) {
        return ret;
    }
    OHOS::init_param::WatcherManagerKits &instance = OHOS::init_param::WatcherManagerKits::GetInstance();
    if (callback != nullptr) {
C
cheng_jinsong 已提交
339
        ret = instance.AddWatcher(keyPrefix, callback, context);
S
sun_fan 已提交
340
    } else {
C
cheng_jinsong 已提交
341
        ret = instance.DelWatcher(keyPrefix, nullptr, nullptr);
S
sun_fan 已提交
342 343 344
    }
    return ret;
}
C
cheng_jinsong 已提交
345 346 347 348

int RemoveParameterWatcher(const char *keyPrefix, ParameterChgPtr callback, void *context)
{
    WATCHER_CHECK(keyPrefix != nullptr, return PARAM_CODE_INVALID_PARAM, "Invalid prefix");
C
watcher  
cheng_jinsong 已提交
349 350
    std::string key(keyPrefix);
    int ret = PreHandleWatchParam(key);
C
cheng_jinsong 已提交
351 352 353 354 355 356
    if (ret != 0) {
        return ret;
    }
    OHOS::init_param::WatcherManagerKits &instance = OHOS::init_param::WatcherManagerKits::GetInstance();
    return instance.DelWatcher(keyPrefix, (ParameterChangePtr)callback, context);
}