1 /*
2 * Copyright (c) 2021-2022 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 "configuration.h"
17
18 #include <mutex>
19 #include <nlohmann/json.hpp>
20
21 #include "ability_base_log_wrapper.h"
22 #include "string_ex.h"
23
24 namespace OHOS {
25 namespace AppExecFwk {
26 namespace {
27 constexpr int CYCLE_LIMIT = 1000;
28 }
29 using json = nlohmann::json;
Configuration()30 Configuration::Configuration()
31 {}
32
Configuration(const Configuration & other)33 Configuration::Configuration(const Configuration &other) : defaultDisplayId_(other.defaultDisplayId_)
34 {
35 std::lock_guard<std::recursive_mutex> lock(configParameterMutex_);
36 configParameter_ = other.configParameter_;
37 }
38
operator =(const Configuration & other)39 Configuration& Configuration::operator=(const Configuration &other)
40 {
41 if (this == &other) {
42 return *this;
43 }
44
45 defaultDisplayId_ = other.defaultDisplayId_;
46
47 std::lock_guard<std::recursive_mutex> lock(configParameterMutex_);
48 configParameter_.clear();
49 configParameter_ = other.configParameter_;
50 return *this;
51 }
52
~Configuration()53 Configuration::~Configuration()
54 {}
55
MakeTheKey(std::string & getKey,int id,const std::string & param) const56 bool Configuration::MakeTheKey(std::string &getKey, int id, const std::string ¶m) const
57 {
58 if (param.empty()) {
59 return false;
60 }
61
62 if (std::find(ConfigurationInner::SystemConfigurationKeyStore.begin(),
63 ConfigurationInner::SystemConfigurationKeyStore.end(), param) ==
64 ConfigurationInner::SystemConfigurationKeyStore.end()) {
65 return false;
66 }
67
68 getKey.clear();
69 getKey += std::to_string(id);
70 getKey += ConfigurationInner::CONNECTION_SYMBOL;
71 getKey += param;
72 ABILITYBASE_LOGD(" getKey [%{public}s]", getKey.c_str());
73
74 return true;
75 }
76
AddItem(int displayId,const std::string & key,const std::string & value)77 bool Configuration::AddItem(int displayId, const std::string &key, const std::string &value)
78 {
79 if (key.empty() || value.empty()) {
80 return false;
81 }
82
83 std::string getKey;
84 if (!MakeTheKey(getKey, displayId, key)) {
85 return false;
86 }
87
88 std::lock_guard<std::recursive_mutex> lock(configParameterMutex_);
89 configParameter_[getKey] = value;
90 return true;
91 }
92
GetItem(int displayId,const std::string & key) const93 std::string Configuration::GetItem(int displayId, const std::string &key) const
94 {
95 if (key.empty()) {
96 return ConfigurationInner::EMPTY_STRING;
97 }
98
99 std::string getKey;
100 if (!MakeTheKey(getKey, displayId, key)) {
101 return ConfigurationInner::EMPTY_STRING;
102 }
103
104 std::lock_guard<std::recursive_mutex> lock(configParameterMutex_);
105 auto iter = configParameter_.find(getKey);
106 if (iter != configParameter_.end()) {
107 return iter->second;
108 }
109
110 return ConfigurationInner::EMPTY_STRING;
111 }
112
GetItemSize() const113 int Configuration::GetItemSize() const
114 {
115 std::lock_guard<std::recursive_mutex> lock(configParameterMutex_);
116 return configParameter_.size();
117 }
118
GetAllKey(std::vector<std::string> & keychain) const119 void Configuration::GetAllKey(std::vector<std::string> &keychain) const
120 {
121 keychain.clear();
122
123 std::lock_guard<std::recursive_mutex> lock(configParameterMutex_);
124 for (const auto &it :configParameter_) {
125 keychain.push_back(it.first);
126 }
127 }
128
GetValue(const std::string & key) const129 std::string Configuration::GetValue(const std::string &key) const
130 {
131 std::lock_guard<std::recursive_mutex> lock(configParameterMutex_);
132 auto iter = configParameter_.find(key);
133 if (iter != configParameter_.end()) {
134 return iter->second;
135 }
136
137 return ConfigurationInner::EMPTY_STRING;
138 }
139
CompareDifferent(std::vector<std::string> & diffKeyV,const Configuration & other)140 void Configuration::CompareDifferent(std::vector<std::string> &diffKeyV, const Configuration &other)
141 {
142 if (other.GetItemSize() == 0) {
143 return;
144 }
145
146 diffKeyV.clear();
147 std::vector<std::string> otherk;
148 other.GetAllKey(otherk);
149
150 std::lock_guard<std::recursive_mutex> lock(configParameterMutex_);
151 for (const auto &iter : otherk) {
152 ABILITYBASE_LOGW(" iter : [%{public}s] | Val: [%{public}s]", iter.c_str(), other.GetValue(iter).c_str());
153 // Insert new content directly
154 auto pair = configParameter_.insert(std::make_pair(iter, other.GetValue(iter)));
155 if (pair.second) {
156 diffKeyV.push_back(iter); // One of the changes this time
157 continue;
158 }
159 // Compare what you already have
160 if (!other.GetValue(iter).empty() && other.GetValue(iter) != GetValue(iter)) {
161 diffKeyV.push_back(iter);
162 }
163 }
164 }
165
Merge(const std::vector<std::string> & diffKeyV,const Configuration & other)166 void Configuration::Merge(const std::vector<std::string> &diffKeyV, const Configuration &other)
167 {
168 if (diffKeyV.empty()) {
169 return;
170 }
171
172 std::lock_guard<std::recursive_mutex> lock(configParameterMutex_);
173 for (const auto &mergeItemKey : diffKeyV) {
174 auto myItem = GetValue(mergeItemKey);
175 auto otherItem = other.GetValue(mergeItemKey);
176 // myItem possible empty
177 if (!otherItem.empty() && otherItem != myItem) {
178 configParameter_[mergeItemKey] = otherItem;
179 }
180 }
181 }
182
RemoveItem(int displayId,const std::string & key)183 int Configuration::RemoveItem(int displayId, const std::string &key)
184 {
185 if (key.empty()) {
186 return 0;
187 }
188
189 std::string getKey;
190 if (!MakeTheKey(getKey, displayId, key)) {
191 return 0;
192 }
193
194 std::lock_guard<std::recursive_mutex> lock(configParameterMutex_);
195 return configParameter_.erase(getKey);
196 }
197
AddItem(const std::string & key,const std::string & value)198 bool Configuration::AddItem(const std::string &key, const std::string &value)
199 {
200 return AddItem(defaultDisplayId_, key, value);
201 }
202
GetItem(const std::string & key) const203 std::string Configuration::GetItem(const std::string &key) const
204 {
205 return GetItem(defaultDisplayId_, key);
206 }
207
RemoveItem(const std::string & key)208 int Configuration::RemoveItem(const std::string &key)
209 {
210 return RemoveItem(defaultDisplayId_, key);
211 }
212
GetName() const213 const std::string& Configuration::GetName() const
214 {
215 std::lock_guard<std::recursive_mutex> lock(configParameterMutex_);
216 json configArray(configParameter_);
217 toStrintg_ = configArray.dump();
218 return toStrintg_;
219 }
220
ReadFromParcel(Parcel & parcel)221 bool Configuration::ReadFromParcel(Parcel &parcel)
222 {
223 ABILITYBASE_LOGD("ReadFromParcel");
224 defaultDisplayId_ = parcel.ReadInt32();
225 int32_t configSize = parcel.ReadInt32();
226 std::vector<std::string> keys;
227 std::vector<std::string> values;
228 keys.clear();
229 values.clear();
230 if (!parcel.ReadStringVector(&keys)) {
231 ABILITYBASE_LOGE("ReadStringVector for keys failed.");
232 return false;
233 }
234 if (!parcel.ReadStringVector(&values)) {
235 ABILITYBASE_LOGE("ReadStringVector for values failed.");
236 return false;
237 }
238 size_t keySize = keys.size();
239 size_t valueSize = values.size();
240 if (keySize != valueSize || configSize != (int32_t)valueSize || configSize > CYCLE_LIMIT) {
241 ABILITYBASE_LOGE("ReadFromParcel failed, invalid size.");
242 return false;
243 }
244
245 std::string key;
246 std::string val;
247 std::lock_guard<std::recursive_mutex> lock(configParameterMutex_);
248 for (int32_t i = 0; i < configSize; i++) {
249 key = keys.at(i);
250 val = values.at(i);
251 configParameter_.emplace(key, val);
252 }
253 return true;
254 }
255
Unmarshalling(Parcel & parcel)256 Configuration *Configuration::Unmarshalling(Parcel &parcel)
257 {
258 Configuration *Configuration = new (std::nothrow) OHOS::AppExecFwk::Configuration();
259 if (Configuration && !Configuration->ReadFromParcel(parcel)) {
260 delete Configuration;
261 Configuration = nullptr;
262 }
263 return Configuration;
264 }
265
Marshalling(Parcel & parcel) const266 bool Configuration::Marshalling(Parcel &parcel) const
267 {
268 ABILITYBASE_LOGW("Marshalling");
269 std::vector<std::string> keys;
270 std::vector<std::string> values;
271 keys.clear();
272 values.clear();
273
274 parcel.WriteInt32(defaultDisplayId_);
275
276 std::lock_guard<std::recursive_mutex> lock(configParameterMutex_);
277 parcel.WriteInt32(configParameter_.size());
278 for (const auto &config : configParameter_) {
279 keys.emplace_back(config.first);
280 values.emplace_back(config.second);
281 }
282
283 parcel.WriteStringVector(keys);
284 parcel.WriteStringVector(values);
285 return true;
286 }
287 } // namespace AppExecFwk
288 } // namespace OHOS
289