1 /*
2  * Copyright (c) 2023-2024 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 
16 #include "static_subscriber_data_manager.h"
17 
18 #include <unistd.h>
19 
20 #include "ces_inner_error_code.h"
21 #include "event_log_wrapper.h"
22 #include "nlohmann/json.hpp"
23 
24 namespace OHOS {
25 namespace EventFwk {
26 namespace {
27 constexpr int32_t CHECK_INTERVAL = 100000; // 100ms
28 constexpr int32_t MAX_TIMES = 5;           // 5 * 100ms = 500ms
29 constexpr const char *STATIC_SUBSCRIBER_STORAGE_DIR = "/data/service/el1/public/database/common_event_service";
30 const std::string STATIC_SUBSCRIBER_VALUE_DEFAULT = "0";
31 } // namespace
StaticSubscriberDataManager()32 StaticSubscriberDataManager::StaticSubscriberDataManager() {}
33 
~StaticSubscriberDataManager()34 StaticSubscriberDataManager::~StaticSubscriberDataManager()
35 {
36     if (kvStorePtr_ != nullptr) {
37         dataManager_.CloseKvStore(appId_, kvStorePtr_);
38     }
39 }
40 
GetKvStore()41 DistributedKv::Status StaticSubscriberDataManager::GetKvStore()
42 {
43     DistributedKv::Options options = {
44         .createIfMissing = true,
45         .encrypt = false,
46         .autoSync = false,
47         .syncable = false,
48         .securityLevel = DistributedKv::SecurityLevel::S1,
49         .area = DistributedKv::EL1,
50         .kvStoreType = DistributedKv::KvStoreType::SINGLE_VERSION,
51         .baseDir = STATIC_SUBSCRIBER_STORAGE_DIR
52     };
53 
54     DistributedKv::Status status = dataManager_.GetSingleKvStore(options, appId_, storeId_, kvStorePtr_);
55     if (status != DistributedKv::Status::SUCCESS) {
56         EVENT_LOGE("return error: %{public}d", status);
57     }
58     return status;
59 }
60 
CheckKvStore()61 bool StaticSubscriberDataManager::CheckKvStore()
62 {
63     if (kvStorePtr_ != nullptr) {
64         return true;
65     }
66     int32_t tryTimes = MAX_TIMES;
67     while (tryTimes > 0) {
68         DistributedKv::Status status = GetKvStore();
69         if (status == DistributedKv::Status::SUCCESS && kvStorePtr_ != nullptr) {
70             return true;
71         }
72         EVENT_LOGI("try times: %{public}d", tryTimes);
73         usleep(CHECK_INTERVAL);
74         tryTimes--;
75     }
76     return kvStorePtr_ != nullptr;
77 }
78 
UpdateStaticSubscriberState(const std::map<std::string,std::vector<std::string>> & disableEvents)79 int32_t StaticSubscriberDataManager::UpdateStaticSubscriberState(
80     const std::map<std::string, std::vector<std::string>> &disableEvents)
81 {
82     std::map<std::string, std::vector<std::string>> disableEventsDatabase;
83     std::set<std::string> bundleList;
84     int32_t ret = QueryStaticSubscriberStateData(disableEventsDatabase, bundleList);
85     if (ret != ERR_OK) {
86         EVENT_LOGE("Query static subscriber state data failed.");
87         return ret;
88     }
89 
90     std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
91     if (!CheckKvStore()) {
92         EVENT_LOGE("Kvstore is nullptr.");
93         return ERR_NO_INIT;
94     }
95 
96     for (auto &disableEventsDatabaseIt : disableEventsDatabase) {
97         DistributedKv::Key key(disableEventsDatabaseIt.first);
98         if (kvStorePtr_->Delete(key) != DistributedKv::Status::SUCCESS) {
99             EVENT_LOGE("Update data from kvstore failed.");
100             dataManager_.CloseKvStore(appId_, kvStorePtr_);
101             kvStorePtr_ = nullptr;
102             return ERR_INVALID_OPERATION;
103         }
104     }
105 
106     for (auto &disableEventsIt : disableEvents) {
107         DistributedKv::Key key(disableEventsIt.first);
108         DistributedKv::Value value = ConvertEventsToValue(disableEventsIt.second);
109         if (kvStorePtr_->Put(key, value) != DistributedKv::Status::SUCCESS) {
110             EVENT_LOGE("Update data from kvstore failed.");
111             dataManager_.CloseKvStore(appId_, kvStorePtr_);
112             kvStorePtr_ = nullptr;
113             return ERR_INVALID_OPERATION;
114         }
115     }
116 
117     dataManager_.CloseKvStore(appId_, kvStorePtr_);
118     kvStorePtr_ = nullptr;
119     return ERR_OK;
120 }
121 
QueryStaticSubscriberStateData(std::map<std::string,std::vector<std::string>> & disableEvents,std::set<std::string> & bundleList)122 int32_t StaticSubscriberDataManager::QueryStaticSubscriberStateData(
123     std::map<std::string, std::vector<std::string>> &disableEvents, std::set<std::string> &bundleList)
124 
125 {
126     std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
127     if (!CheckKvStore()) {
128         EVENT_LOGE("Kvstore is nullptr.");
129         return ERR_NO_INIT;
130     }
131 
132     std::vector<DistributedKv::Entry> allEntries;
133     if (kvStorePtr_->GetEntries(nullptr, allEntries) != DistributedKv::Status::SUCCESS) {
134         EVENT_LOGE("Get entries failed.");
135         return ERR_INVALID_OPERATION;
136     }
137 
138     if (allEntries.empty()) {
139         dataManager_.CloseKvStore(appId_, kvStorePtr_);
140         kvStorePtr_ = nullptr;
141         EVENT_LOGD("The all entries is empty.");
142         return ERR_OK;
143     }
144 
145     auto result = ERR_OK;
146     for (const auto &item : allEntries) {
147         if (item.value.ToString() == STATIC_SUBSCRIBER_VALUE_DEFAULT) {
148             bundleList.emplace(item.key.ToString());
149         } else {
150             std::vector<std::string> values;
151             if (!ConvertValueToEvents(item.value, values)) {
152                 EVENT_LOGE("Failed to convert vector from value.");
153                 result = ERR_INVALID_OPERATION;
154                 break;
155             }
156             disableEvents.emplace(item.key.ToString(), values);
157         }
158     }
159 
160     dataManager_.CloseKvStore(appId_, kvStorePtr_);
161     kvStorePtr_ = nullptr;
162     return result;
163 }
164 
DeleteDisableEventElementByBundleName(const std::string & bundleName)165 int32_t StaticSubscriberDataManager::DeleteDisableEventElementByBundleName(const std::string &bundleName)
166 {
167     if (bundleName.empty()) {
168         EVENT_LOGE("Bundle name is invalid value.");
169         return ERR_INVALID_VALUE;
170     }
171 
172     std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
173     if (!CheckKvStore()) {
174         EVENT_LOGE("Kvstore is nullptr.");
175         return ERR_NO_INIT;
176     }
177 
178     EVENT_LOGD("Bundle name is %{public}s.", bundleName.c_str());
179     DistributedKv::Key key(bundleName);
180     if (kvStorePtr_->Delete(key) != DistributedKv::Status::SUCCESS) {
181         EVENT_LOGE("Delete data [%{public}s] from kvstore failed.", bundleName.c_str());
182         return ERR_INVALID_OPERATION;
183     }
184 
185     dataManager_.CloseKvStore(appId_, kvStorePtr_);
186     kvStorePtr_ = nullptr;
187     return ERR_OK;
188 }
189 
ConvertEventsToValue(const std::vector<std::string> & events)190 DistributedKv::Value StaticSubscriberDataManager::ConvertEventsToValue(const std::vector<std::string> &events)
191 {
192     nlohmann::json jsonNodes = nlohmann::json::array();
193     for (size_t index = 0; index < events.size(); index++) {
194         jsonNodes.emplace_back(events[index]);
195     }
196     return jsonNodes.dump();
197 }
198 
ConvertValueToEvents(const DistributedKv::Value & value,std::vector<std::string> & events)199 bool StaticSubscriberDataManager::ConvertValueToEvents(
200     const DistributedKv::Value &value, std::vector<std::string> &events)
201 {
202     nlohmann::json jsonObject = nlohmann::json::parse(value.ToString(), nullptr, false);
203     if (jsonObject.is_null() || !jsonObject.is_array() || jsonObject.empty()) {
204         EVENT_LOGE("invalid common event obj size");
205         return false;
206     }
207     if (jsonObject.is_discarded()) {
208         EVENT_LOGE("Failed to parse json string.");
209         return false;
210     }
211     for (size_t index = 0; index < jsonObject.size(); index++) {
212         if (jsonObject[index].is_string()) {
213             events.emplace_back(jsonObject[index]);
214         }
215     }
216     return true;
217 }
218 } // namespace EventFwk
219 } // namespace OHOS
220