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 &param) const
57 {
58     if (param.empty()) {
59         return false;
60     }
61 
62     const std::vector<std::string> SystemConfigurationKeyStore {
63         OHOS::AAFwk::GlobalConfigurationKey::SYSTEM_LANGUAGE,
64         OHOS::AAFwk::GlobalConfigurationKey::IS_PREFERRED_LANGUAGE,
65         OHOS::AAFwk::GlobalConfigurationKey::SYSTEM_HOUR,
66         OHOS::AAFwk::GlobalConfigurationKey::SYSTEM_COLORMODE,
67         OHOS::AAFwk::GlobalConfigurationKey::INPUT_POINTER_DEVICE,
68         OHOS::AAFwk::GlobalConfigurationKey::DEVICE_TYPE,
69         OHOS::AAFwk::GlobalConfigurationKey::THEME,
70         OHOS::AAFwk::GlobalConfigurationKey::THEME_ID,
71         OHOS::AAFwk::GlobalConfigurationKey::COLORMODE_IS_SET_BY_SA,
72         OHOS::AAFwk::GlobalConfigurationKey::COLORMODE_IS_SET_BY_APP,
73         OHOS::AAFwk::GlobalConfigurationKey::SYSTEM_FONT_SIZE_SCALE,
74         OHOS::AAFwk::GlobalConfigurationKey::SYSTEM_FONT_WEIGHT_SCALE,
75         OHOS::AAFwk::GlobalConfigurationKey::SYSTEM_MCC,
76         OHOS::AAFwk::GlobalConfigurationKey::SYSTEM_MNC,
77         OHOS::AppExecFwk::ConfigurationInner::APPLICATION_DIRECTION,
78         OHOS::AppExecFwk::ConfigurationInner::APPLICATION_DENSITYDPI,
79         OHOS::AppExecFwk::ConfigurationInner::APPLICATION_DISPLAYID,
80         OHOS::AppExecFwk::ConfigurationInner::APPLICATION_FONT,
81         OHOS::AAFwk::GlobalConfigurationKey::APP_FONT_SIZE_SCALE,
82         OHOS::AAFwk::GlobalConfigurationKey::APP_FONT_MAX_SCALE,
83     };
84     if (std::find(SystemConfigurationKeyStore.begin(), SystemConfigurationKeyStore.end(), param) ==
85         SystemConfigurationKeyStore.end()) {
86         return false;
87     }
88 
89     getKey.clear();
90     getKey += std::to_string(id);
91     getKey += ConfigurationInner::CONNECTION_SYMBOL;
92     getKey += param;
93     ABILITYBASE_LOGD("key: %{public}s", getKey.c_str());
94 
95     return true;
96 }
97 
AddItem(int displayId, const std::string &key, const std::string &value)98 bool Configuration::AddItem(int displayId, const std::string &key, const std::string &value)
99 {
100     if (key.empty() || value.empty()) {
101         return false;
102     }
103 
104     std::string getKey;
105     if (!MakeTheKey(getKey, displayId, key)) {
106         return false;
107     }
108 
109     std::lock_guard<std::recursive_mutex> lock(configParameterMutex_);
110     configParameter_[getKey] = value;
111     return true;
112 }
113 
GetItem(int displayId, const std::string &key) const114 std::string Configuration::GetItem(int displayId, const std::string &key) const
115 {
116     if (key.empty()) {
117         return ConfigurationInner::EMPTY_STRING;
118     }
119 
120     std::string getKey;
121     if (!MakeTheKey(getKey, displayId, key)) {
122         return ConfigurationInner::EMPTY_STRING;
123     }
124 
125     std::lock_guard<std::recursive_mutex> lock(configParameterMutex_);
126     auto iter = configParameter_.find(getKey);
127     if (iter != configParameter_.end()) {
128         return iter->second;
129     }
130 
131     return ConfigurationInner::EMPTY_STRING;
132 }
133 
GetItemSize() const134 int Configuration::GetItemSize() const
135 {
136     std::lock_guard<std::recursive_mutex> lock(configParameterMutex_);
137     return configParameter_.size();
138 }
139 
GetAllKey(std::vector<std::string> &keychain) const140 void Configuration::GetAllKey(std::vector<std::string> &keychain) const
141 {
142     keychain.clear();
143 
144     std::lock_guard<std::recursive_mutex> lock(configParameterMutex_);
145     for (const auto &it :configParameter_) {
146         keychain.push_back(it.first);
147     }
148 }
149 
GetValue(const std::string &key) const150 std::string Configuration::GetValue(const std::string &key) const
151 {
152     std::lock_guard<std::recursive_mutex> lock(configParameterMutex_);
153     auto iter = configParameter_.find(key);
154     if (iter != configParameter_.end()) {
155         return iter->second;
156     }
157 
158     return ConfigurationInner::EMPTY_STRING;
159 }
160 
CompareDifferent(std::vector<std::string> &diffKeyV, const Configuration &other)161 void Configuration::CompareDifferent(std::vector<std::string> &diffKeyV, const Configuration &other)
162 {
163     if (other.GetItemSize() == 0) {
164         return;
165     }
166 
167     diffKeyV.clear();
168     std::vector<std::string> otherk;
169     other.GetAllKey(otherk);
170 
171     std::lock_guard<std::recursive_mutex> lock(configParameterMutex_);
172     for (const auto &iter : otherk) {
173         ABILITYBASE_LOGD("iter:%{public}s,Val:%{public}s", iter.c_str(), other.GetValue(iter).c_str());
174         // Insert new content directly
175         auto pair = configParameter_.insert(std::make_pair(iter, other.GetValue(iter)));
176         if (pair.second) {
177             diffKeyV.push_back(iter); // One of the changes this time
178             continue;
179         }
180         // Compare what you already have
181         if (!other.GetValue(iter).empty() && other.GetValue(iter) != GetValue(iter)) {
182             diffKeyV.push_back(iter);
183         }
184     }
185 }
186 
Merge(const std::vector<std::string> &diffKeyV, const Configuration &other)187 void Configuration::Merge(const std::vector<std::string> &diffKeyV, const Configuration &other)
188 {
189     if (diffKeyV.empty()) {
190         return;
191     }
192 
193     std::lock_guard<std::recursive_mutex> lock(configParameterMutex_);
194     for (const auto &mergeItemKey : diffKeyV) {
195         auto myItem = GetValue(mergeItemKey);
196         auto otherItem = other.GetValue(mergeItemKey);
197         // myItem possible empty
198         if (!otherItem.empty() && otherItem != myItem) {
199             configParameter_[mergeItemKey] = otherItem;
200         }
201     }
202 }
203 
RemoveItem(int displayId, const std::string &key)204 int Configuration::RemoveItem(int displayId, const std::string &key)
205 {
206     if (key.empty()) {
207         return 0;
208     }
209 
210     std::string getKey;
211     if (!MakeTheKey(getKey, displayId, key)) {
212         return 0;
213     }
214 
215     std::lock_guard<std::recursive_mutex> lock(configParameterMutex_);
216     return configParameter_.erase(getKey);
217 }
218 
AddItem(const std::string &key, const std::string &value)219 bool Configuration::AddItem(const std::string &key, const std::string &value)
220 {
221     return AddItem(defaultDisplayId_, key, value);
222 }
223 
GetItem(const std::string &key) const224 std::string Configuration::GetItem(const std::string &key) const
225 {
226     return GetItem(defaultDisplayId_, key);
227 }
228 
RemoveItem(const std::string &key)229 int Configuration::RemoveItem(const std::string &key)
230 {
231     return RemoveItem(defaultDisplayId_, key);
232 }
233 
GetName() const234 const std::string Configuration::GetName() const
235 {
236     std::lock_guard<std::recursive_mutex> lock(configParameterMutex_);
237     json configArray(configParameter_);
238     return configArray.dump();
239 }
240 
ReadFromParcel(Parcel &parcel)241 bool Configuration::ReadFromParcel(Parcel &parcel)
242 {
243     ABILITYBASE_LOGD("ReadFromParcel");
244     defaultDisplayId_ = parcel.ReadInt32();
245     int32_t configSize = parcel.ReadInt32();
246     std::vector<std::string> keys;
247     std::vector<std::string> values;
248     keys.clear();
249     values.clear();
250     if (!parcel.ReadStringVector(&keys)) {
251         ABILITYBASE_LOGE("read keys failed");
252         return false;
253     }
254     if (!parcel.ReadStringVector(&values)) {
255         ABILITYBASE_LOGE("read values failed");
256         return false;
257     }
258     size_t keySize = keys.size();
259     size_t valueSize = values.size();
260     if (keySize != valueSize || configSize != (int32_t)valueSize || configSize > CYCLE_LIMIT) {
261         ABILITYBASE_LOGE("invalid size");
262         return false;
263     }
264 
265     std::string key;
266     std::string val;
267     std::lock_guard<std::recursive_mutex> lock(configParameterMutex_);
268     for (int32_t i = 0; i < configSize; i++) {
269         key = keys.at(i);
270         val = values.at(i);
271         configParameter_.emplace(key, val);
272     }
273     return true;
274 }
275 
Unmarshalling(Parcel &parcel)276 Configuration *Configuration::Unmarshalling(Parcel &parcel)
277 {
278     Configuration *Configuration = new (std::nothrow) OHOS::AppExecFwk::Configuration();
279     if (Configuration && !Configuration->ReadFromParcel(parcel)) {
280         delete Configuration;
281         Configuration = nullptr;
282     }
283     return Configuration;
284 }
285 
Marshalling(Parcel &parcel) const286 bool Configuration::Marshalling(Parcel &parcel) const
287 {
288     ABILITYBASE_LOGD("called");
289     std::vector<std::string> keys;
290     std::vector<std::string> values;
291     keys.clear();
292     values.clear();
293 
294     parcel.WriteInt32(defaultDisplayId_);
295 
296     std::lock_guard<std::recursive_mutex> lock(configParameterMutex_);
297     parcel.WriteInt32(configParameter_.size());
298     for (const auto &config : configParameter_) {
299         keys.emplace_back(config.first);
300         values.emplace_back(config.second);
301     }
302 
303     parcel.WriteStringVector(keys);
304     parcel.WriteStringVector(values);
305     return true;
306 }
307 }  // namespace AppExecFwk
308 }  // namespace OHOS
309