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