1eace7efcSopenharmony_ci/*
2eace7efcSopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3eace7efcSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4eace7efcSopenharmony_ci * you may not use this file except in compliance with the License.
5eace7efcSopenharmony_ci * You may obtain a copy of the License at
6eace7efcSopenharmony_ci *
7eace7efcSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8eace7efcSopenharmony_ci *
9eace7efcSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10eace7efcSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11eace7efcSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12eace7efcSopenharmony_ci * See the License for the specific language governing permissions and
13eace7efcSopenharmony_ci * limitations under the License.
14eace7efcSopenharmony_ci */
15eace7efcSopenharmony_ci#include "dataobs_mgr_inner.h"
16eace7efcSopenharmony_ci
17eace7efcSopenharmony_ci#include "data_ability_observer_stub.h"
18eace7efcSopenharmony_ci#include "dataobs_mgr_errors.h"
19eace7efcSopenharmony_ci#include "hilog_tag_wrapper.h"
20eace7efcSopenharmony_ci#include "common_utils.h"
21eace7efcSopenharmony_ci
22eace7efcSopenharmony_cinamespace OHOS {
23eace7efcSopenharmony_cinamespace AAFwk {
24eace7efcSopenharmony_ci
25eace7efcSopenharmony_ciDataObsMgrInner::DataObsMgrInner() {}
26eace7efcSopenharmony_ci
27eace7efcSopenharmony_ciDataObsMgrInner::~DataObsMgrInner() {}
28eace7efcSopenharmony_ci
29eace7efcSopenharmony_ciint DataObsMgrInner::HandleRegisterObserver(const Uri &uri, sptr<IDataAbilityObserver> dataObserver)
30eace7efcSopenharmony_ci{
31eace7efcSopenharmony_ci    std::lock_guard<ffrt::mutex> lock(innerMutex_);
32eace7efcSopenharmony_ci
33eace7efcSopenharmony_ci    auto [obsPair, flag] = observers_.try_emplace(uri.ToString(), std::list<sptr<IDataAbilityObserver>>());
34eace7efcSopenharmony_ci    if (!flag && obsPair->second.size() > OBS_NUM_MAX) {
35eace7efcSopenharmony_ci        TAG_LOGE(AAFwkTag::DBOBSMGR,
36eace7efcSopenharmony_ci            "subscribers num:%{public}s maxed",
37eace7efcSopenharmony_ci            CommonUtils::Anonymous(uri.ToString()).c_str());
38eace7efcSopenharmony_ci        return DATAOBS_SERVICE_OBS_LIMMIT;
39eace7efcSopenharmony_ci    }
40eace7efcSopenharmony_ci
41eace7efcSopenharmony_ci    for (auto obs = obsPair->second.begin(); obs != obsPair->second.end(); obs++) {
42eace7efcSopenharmony_ci        if ((*obs)->AsObject() == dataObserver->AsObject()) {
43eace7efcSopenharmony_ci            TAG_LOGE(AAFwkTag::DBOBSMGR, "obs registered:%{public}s",
44eace7efcSopenharmony_ci                CommonUtils::Anonymous(uri.ToString()).c_str());
45eace7efcSopenharmony_ci            return OBS_EXIST;
46eace7efcSopenharmony_ci        }
47eace7efcSopenharmony_ci    }
48eace7efcSopenharmony_ci
49eace7efcSopenharmony_ci    obsPair->second.push_back(dataObserver);
50eace7efcSopenharmony_ci
51eace7efcSopenharmony_ci    AddObsDeathRecipient(dataObserver);
52eace7efcSopenharmony_ci
53eace7efcSopenharmony_ci    return NO_ERROR;
54eace7efcSopenharmony_ci}
55eace7efcSopenharmony_ci
56eace7efcSopenharmony_ciint DataObsMgrInner::HandleUnregisterObserver(const Uri &uri, sptr<IDataAbilityObserver> dataObserver)
57eace7efcSopenharmony_ci{
58eace7efcSopenharmony_ci    std::lock_guard<ffrt::mutex> lock(innerMutex_);
59eace7efcSopenharmony_ci
60eace7efcSopenharmony_ci    auto obsPair = observers_.find(uri.ToString());
61eace7efcSopenharmony_ci    if (obsPair == observers_.end()) {
62eace7efcSopenharmony_ci        TAG_LOGW(
63eace7efcSopenharmony_ci            AAFwkTag::DBOBSMGR, "uri no obs:%{public}s", CommonUtils::Anonymous(uri.ToString()).c_str());
64eace7efcSopenharmony_ci        return NO_OBS_FOR_URI;
65eace7efcSopenharmony_ci    }
66eace7efcSopenharmony_ci
67eace7efcSopenharmony_ci    TAG_LOGD(AAFwkTag::DBOBSMGR, "obs num:%{public}zu:%{public}s", obsPair->second.size(),
68eace7efcSopenharmony_ci        CommonUtils::Anonymous(uri.ToString()).c_str());
69eace7efcSopenharmony_ci    auto obs = obsPair->second.begin();
70eace7efcSopenharmony_ci    for (; obs != obsPair->second.end(); obs++) {
71eace7efcSopenharmony_ci        if ((*obs)->AsObject() == dataObserver->AsObject()) {
72eace7efcSopenharmony_ci            break;
73eace7efcSopenharmony_ci        }
74eace7efcSopenharmony_ci    }
75eace7efcSopenharmony_ci    if (obs == obsPair->second.end()) {
76eace7efcSopenharmony_ci        TAG_LOGW(
77eace7efcSopenharmony_ci            AAFwkTag::DBOBSMGR, "uri no obs:%{public}s", CommonUtils::Anonymous(uri.ToString()).c_str());
78eace7efcSopenharmony_ci        return NO_OBS_FOR_URI;
79eace7efcSopenharmony_ci    }
80eace7efcSopenharmony_ci    obsPair->second.remove(*obs);
81eace7efcSopenharmony_ci    if (obsPair->second.empty()) {
82eace7efcSopenharmony_ci        observers_.erase(obsPair);
83eace7efcSopenharmony_ci    }
84eace7efcSopenharmony_ci
85eace7efcSopenharmony_ci    if (!HaveRegistered(dataObserver)) {
86eace7efcSopenharmony_ci        RemoveObsDeathRecipient(dataObserver->AsObject());
87eace7efcSopenharmony_ci    }
88eace7efcSopenharmony_ci
89eace7efcSopenharmony_ci    return NO_ERROR;
90eace7efcSopenharmony_ci}
91eace7efcSopenharmony_ci
92eace7efcSopenharmony_ciint DataObsMgrInner::HandleNotifyChange(const Uri &uri)
93eace7efcSopenharmony_ci{
94eace7efcSopenharmony_ci    std::list<sptr<IDataAbilityObserver>> obsList;
95eace7efcSopenharmony_ci    std::lock_guard<ffrt::mutex> lock(innerMutex_);
96eace7efcSopenharmony_ci    {
97eace7efcSopenharmony_ci        auto obsPair = observers_.find(uri.ToString());
98eace7efcSopenharmony_ci        if (obsPair == observers_.end()) {
99eace7efcSopenharmony_ci            TAG_LOGD(AAFwkTag::DBOBSMGR, "uri no obs:%{public}s",
100eace7efcSopenharmony_ci                CommonUtils::Anonymous(uri.ToString()).c_str());
101eace7efcSopenharmony_ci            return NO_OBS_FOR_URI;
102eace7efcSopenharmony_ci        }
103eace7efcSopenharmony_ci        obsList = obsPair->second;
104eace7efcSopenharmony_ci    }
105eace7efcSopenharmony_ci
106eace7efcSopenharmony_ci    for (auto &obs : obsList) {
107eace7efcSopenharmony_ci        if (obs != nullptr) {
108eace7efcSopenharmony_ci            obs->OnChange();
109eace7efcSopenharmony_ci        }
110eace7efcSopenharmony_ci    }
111eace7efcSopenharmony_ci
112eace7efcSopenharmony_ci    TAG_LOGD(AAFwkTag::DBOBSMGR, "uri end:%{public}s,obs num:%{public}zu",
113eace7efcSopenharmony_ci        CommonUtils::Anonymous(uri.ToString()).c_str(), obsList.size());
114eace7efcSopenharmony_ci    return NO_ERROR;
115eace7efcSopenharmony_ci}
116eace7efcSopenharmony_ci
117eace7efcSopenharmony_civoid DataObsMgrInner::AddObsDeathRecipient(sptr<IDataAbilityObserver> dataObserver)
118eace7efcSopenharmony_ci{
119eace7efcSopenharmony_ci    if ((dataObserver == nullptr) || dataObserver->AsObject() == nullptr) {
120eace7efcSopenharmony_ci        return;
121eace7efcSopenharmony_ci    }
122eace7efcSopenharmony_ci
123eace7efcSopenharmony_ci    auto it = obsRecipient_.find(dataObserver->AsObject());
124eace7efcSopenharmony_ci    if (it != obsRecipient_.end()) {
125eace7efcSopenharmony_ci        TAG_LOGW(AAFwkTag::DBOBSMGR, "called");
126eace7efcSopenharmony_ci        return;
127eace7efcSopenharmony_ci    } else {
128eace7efcSopenharmony_ci        std::weak_ptr<DataObsMgrInner> thisWeakPtr(shared_from_this());
129eace7efcSopenharmony_ci        sptr<IRemoteObject::DeathRecipient> deathRecipient =
130eace7efcSopenharmony_ci            new DataObsCallbackRecipient([thisWeakPtr](const wptr<IRemoteObject> &remote) {
131eace7efcSopenharmony_ci                auto dataObsMgrInner = thisWeakPtr.lock();
132eace7efcSopenharmony_ci                if (dataObsMgrInner) {
133eace7efcSopenharmony_ci                    dataObsMgrInner->OnCallBackDied(remote);
134eace7efcSopenharmony_ci                }
135eace7efcSopenharmony_ci            });
136eace7efcSopenharmony_ci        if (!dataObserver->AsObject()->AddDeathRecipient(deathRecipient)) {
137eace7efcSopenharmony_ci            TAG_LOGE(AAFwkTag::DBOBSMGR, "failed");
138eace7efcSopenharmony_ci        }
139eace7efcSopenharmony_ci        obsRecipient_.emplace(dataObserver->AsObject(), deathRecipient);
140eace7efcSopenharmony_ci    }
141eace7efcSopenharmony_ci}
142eace7efcSopenharmony_ci
143eace7efcSopenharmony_civoid DataObsMgrInner::RemoveObsDeathRecipient(sptr<IRemoteObject> dataObserver)
144eace7efcSopenharmony_ci{
145eace7efcSopenharmony_ci    if (dataObserver == nullptr) {
146eace7efcSopenharmony_ci        return;
147eace7efcSopenharmony_ci    }
148eace7efcSopenharmony_ci
149eace7efcSopenharmony_ci    auto it = obsRecipient_.find(dataObserver);
150eace7efcSopenharmony_ci    if (it != obsRecipient_.end()) {
151eace7efcSopenharmony_ci        it->first->RemoveDeathRecipient(it->second);
152eace7efcSopenharmony_ci        obsRecipient_.erase(it);
153eace7efcSopenharmony_ci        return;
154eace7efcSopenharmony_ci    }
155eace7efcSopenharmony_ci}
156eace7efcSopenharmony_ci
157eace7efcSopenharmony_civoid DataObsMgrInner::OnCallBackDied(const wptr<IRemoteObject> &remote)
158eace7efcSopenharmony_ci{
159eace7efcSopenharmony_ci    auto dataObserver = remote.promote();
160eace7efcSopenharmony_ci    if (dataObserver == nullptr) {
161eace7efcSopenharmony_ci        return;
162eace7efcSopenharmony_ci    }
163eace7efcSopenharmony_ci    std::lock_guard<ffrt::mutex> lock(innerMutex_);
164eace7efcSopenharmony_ci
165eace7efcSopenharmony_ci    if (dataObserver == nullptr) {
166eace7efcSopenharmony_ci        TAG_LOGE(AAFwkTag::DBOBSMGR, "null dataObserver");
167eace7efcSopenharmony_ci        return;
168eace7efcSopenharmony_ci    }
169eace7efcSopenharmony_ci
170eace7efcSopenharmony_ci    RemoveObs(dataObserver);
171eace7efcSopenharmony_ci}
172eace7efcSopenharmony_ci
173eace7efcSopenharmony_civoid DataObsMgrInner::RemoveObs(sptr<IRemoteObject> dataObserver)
174eace7efcSopenharmony_ci{
175eace7efcSopenharmony_ci    for (auto iter = observers_.begin(); iter != observers_.end();) {
176eace7efcSopenharmony_ci        auto &obsList = iter->second;
177eace7efcSopenharmony_ci        for (auto it = obsList.begin(); it != obsList.end(); it++) {
178eace7efcSopenharmony_ci            if ((*it)->AsObject() == dataObserver) {
179eace7efcSopenharmony_ci                TAG_LOGD(AAFwkTag::DBOBSMGR, "erase");
180eace7efcSopenharmony_ci                obsList.erase(it);
181eace7efcSopenharmony_ci                break;
182eace7efcSopenharmony_ci            }
183eace7efcSopenharmony_ci        }
184eace7efcSopenharmony_ci        if (obsList.size() == 0) {
185eace7efcSopenharmony_ci            iter = observers_.erase(iter);
186eace7efcSopenharmony_ci        } else {
187eace7efcSopenharmony_ci            iter++;
188eace7efcSopenharmony_ci        }
189eace7efcSopenharmony_ci    }
190eace7efcSopenharmony_ci    RemoveObsDeathRecipient(dataObserver);
191eace7efcSopenharmony_ci}
192eace7efcSopenharmony_ci
193eace7efcSopenharmony_cibool DataObsMgrInner::HaveRegistered(sptr<IDataAbilityObserver> dataObserver)
194eace7efcSopenharmony_ci{
195eace7efcSopenharmony_ci    for (auto &[key, value] : observers_) {
196eace7efcSopenharmony_ci        auto obs = std::find(value.begin(), value.end(), dataObserver);
197eace7efcSopenharmony_ci        if (obs != value.end()) {
198eace7efcSopenharmony_ci            return true;
199eace7efcSopenharmony_ci        }
200eace7efcSopenharmony_ci    }
201eace7efcSopenharmony_ci    return false;
202eace7efcSopenharmony_ci}
203eace7efcSopenharmony_ci}  // namespace AAFwk
204eace7efcSopenharmony_ci}  // namespace OHOS
205