1 /*
2 * Copyright (c) 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 "distributed_preferences.h"
17
18 #include <map>
19
20 #include "ans_log_wrapper.h"
21
22 namespace OHOS {
23 namespace Notification {
24 namespace {
25 const std::string DISTRIBUTED_LABEL = "distributed";
26 const std::string DELIMITER = "|";
27 const std::string MAIN_LABEL = "ans_main";
28 const std::string BUNDLE_LABEL = "bundle";
29 const std::string WITHOUT_APP = "without_app";
30 } // namespace
31
GetBoolFromString(const std::string & str)32 inline bool GetBoolFromString(const std::string &str)
33 {
34 return static_cast<bool>(atoi(str.data()));
35 }
36
DistributedPreferences()37 DistributedPreferences::DistributedPreferences()
38 {
39 database_ = std::make_unique<DistributedPreferencesDatabase>();
40 preferencesInfo_ = std::make_unique<DistributedPreferencesInfo>();
41 InitDistributedAllInfo();
42 }
43
~DistributedPreferences()44 DistributedPreferences::~DistributedPreferences()
45 {}
46
InitDistributedAllInfo()47 bool DistributedPreferences::InitDistributedAllInfo()
48 {
49 std::vector<DistributedPreferencesDatabase::Entry> entries;
50 if (!database_->GetEntriesFromDistributedDB(DISTRIBUTED_LABEL, entries)) {
51 return false;
52 }
53
54 for (auto entry : entries) {
55 if (!ResolveDistributedKey(entry)) {
56 ANS_LOGE("key <%{public}s> is invalid.", entry.key.ToString().c_str());
57 }
58 }
59
60 return true;
61 }
62
GetDistributedMainKey(std::string & key)63 void DistributedPreferences::GetDistributedMainKey(std::string &key)
64 {
65 key = DISTRIBUTED_LABEL + DELIMITER + MAIN_LABEL + DELIMITER;
66 }
67
GetDistributedBundleKey(const sptr<NotificationBundleOption> & bundleOption,std::string & key)68 void DistributedPreferences::GetDistributedBundleKey(
69 const sptr<NotificationBundleOption> &bundleOption, std::string &key)
70 {
71 if (bundleOption) {
72 key = DISTRIBUTED_LABEL + DELIMITER + BUNDLE_LABEL + DELIMITER + bundleOption->GetBundleName() + DELIMITER +
73 std::to_string(bundleOption->GetUid());
74 }
75 }
76
ResolveDistributedKey(const DistributedKv::Entry & entry)77 bool DistributedPreferences::ResolveDistributedKey(const DistributedKv::Entry &entry)
78 {
79 std::string key = entry.key.ToString();
80 std::size_t distributedLabelPosition = 0;
81 std::size_t distributedLabelEndPosition = key.find(DELIMITER, distributedLabelPosition);
82 if (distributedLabelEndPosition == std::string::npos) {
83 return false;
84 }
85 std::size_t typeLabelPosition = distributedLabelEndPosition + DELIMITER.size();
86 std::size_t typeLabelEndPosition = key.find(DELIMITER, typeLabelPosition);
87 if (typeLabelPosition == std::string::npos) {
88 return false;
89 }
90
91 std::string sign = key.substr(typeLabelPosition, typeLabelEndPosition - typeLabelPosition);
92 if (sign == MAIN_LABEL) {
93 return ResolveDistributedEnable(entry.value.ToString());
94 }
95 if (sign == WITHOUT_APP) {
96 return ResolveSyncWithoutAppEnable(key, typeLabelEndPosition, entry.value.ToString());
97 }
98 return ResolveDistributedBundleEnable(key, typeLabelEndPosition, entry.value.ToString());
99 }
100
ResolveDistributedEnable(const std::string & value)101 bool DistributedPreferences::ResolveDistributedEnable(const std::string &value)
102 {
103 int32_t enabled = atoi(value.data());
104 preferencesInfo_->SetDistributedEnable(static_cast<bool>(enabled));
105
106 return true;
107 }
108
ResolveDistributedBundleEnable(const std::string & key,const int32_t startPos,const std::string & value)109 bool DistributedPreferences::ResolveDistributedBundleEnable(const std::string &key,
110 const int32_t startPos, const std::string &value)
111 {
112 std::size_t bundleNamePosition = startPos + DELIMITER.size();
113 std::size_t bundleNameEndPosition = key.find(DELIMITER, bundleNamePosition);
114 if (bundleNameEndPosition == std::string::npos) {
115 return false;
116 }
117
118 std::size_t uidPosition = key.find_last_of(DELIMITER) + DELIMITER.size();
119 if (uidPosition < bundleNameEndPosition) {
120 return false;
121 }
122
123 std::string bundleName = key.substr(bundleNamePosition, bundleNameEndPosition - bundleNamePosition);
124 int32_t uid = atoi(&key[uidPosition]);
125 preferencesInfo_->SetDistributedBundleEnable(bundleName, uid, GetBoolFromString(value));
126
127 return true;
128 }
129
ResolveSyncWithoutAppEnable(const std::string & key,const int32_t startPos,const std::string & value)130 bool DistributedPreferences::ResolveSyncWithoutAppEnable(const std::string &key,
131 const int32_t startPos, const std::string &value)
132 {
133 std::size_t pos = startPos + DELIMITER.size();
134 int32_t userId = atoi(&key[pos]);
135 preferencesInfo_->SetSyncEnabledWithoutApp(userId, GetBoolFromString(value));
136
137 return true;
138 }
139
SetDistributedEnable(bool isEnable)140 ErrCode DistributedPreferences::SetDistributedEnable(bool isEnable)
141 {
142 ANS_LOGI("start");
143 std::string key;
144 GetDistributedMainKey(key);
145
146 if (!database_->PutToDistributedDB(key, std::to_string(isEnable))) {
147 ANS_LOGE("put to distributed DB failed. key:%{public}s", key.c_str());
148 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
149 }
150
151 preferencesInfo_->SetDistributedEnable(isEnable);
152
153 return ERR_OK;
154 }
155
GetDistributedEnable(bool & isEnable)156 ErrCode DistributedPreferences::GetDistributedEnable(bool &isEnable)
157 {
158 ANS_LOGI("start");
159
160 isEnable = preferencesInfo_->GetDistributedEnable();
161
162 return ERR_OK;
163 }
164
SetDistributedBundleEnable(const sptr<NotificationBundleOption> & bundleOption,bool isEnable)165 ErrCode DistributedPreferences::SetDistributedBundleEnable(
166 const sptr<NotificationBundleOption> &bundleOption, bool isEnable)
167 {
168 ANS_LOGI("start");
169 if (bundleOption == nullptr) {
170 ANS_LOGE("bundleOption is nullptr.");
171 return ERR_ANS_INVALID_PARAM;
172 }
173
174 std::string key;
175 GetDistributedBundleKey(bundleOption, key);
176
177 if (!database_->PutToDistributedDB(key, std::to_string(isEnable))) {
178 ANS_LOGE("put to distributed DB failed. key:%{public}s", key.c_str());
179 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
180 }
181
182 preferencesInfo_->SetDistributedBundleEnable(bundleOption->GetBundleName(), bundleOption->GetUid(), isEnable);
183
184 return ERR_OK;
185 }
186
GetDistributedBundleEnable(const sptr<NotificationBundleOption> & bundleOption,bool & isEnable)187 ErrCode DistributedPreferences::GetDistributedBundleEnable(
188 const sptr<NotificationBundleOption> &bundleOption, bool &isEnable)
189 {
190 if (bundleOption == nullptr) {
191 ANS_LOGE("bundleOption is nullptr.");
192 return ERR_ANS_INVALID_PARAM;
193 }
194
195 if (preferencesInfo_ == nullptr) {
196 ANS_LOGE("preferencesInfo is nullptr");
197 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
198 }
199
200 isEnable = preferencesInfo_->GetDistributedBundleEnable(bundleOption->GetBundleName(), bundleOption->GetUid());
201
202 return ERR_OK;
203 }
204
DeleteDistributedBundleInfo(const sptr<NotificationBundleOption> & bundleOption)205 ErrCode DistributedPreferences::DeleteDistributedBundleInfo(const sptr<NotificationBundleOption> &bundleOption)
206 {
207 if (bundleOption == nullptr) {
208 ANS_LOGE("bundleOption is nullptr.");
209 return ERR_ANS_INVALID_PARAM;
210 }
211
212 if (database_ == nullptr || preferencesInfo_ == nullptr) {
213 ANS_LOGE("database or preferencesInfo is nullptr");
214 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
215 }
216
217 std::string key;
218 GetDistributedBundleKey(bundleOption, key);
219
220 if (!database_->DeleteToDistributedDB(key)) {
221 ANS_LOGE("delete to distributed DB failed. key:%{public}s", key.c_str());
222 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
223 }
224
225 preferencesInfo_->DeleteDistributedBundleInfo(bundleOption->GetBundleName(), bundleOption->GetUid());
226
227 return ERR_OK;
228 }
229
ClearDataInRestoreFactorySettings()230 ErrCode DistributedPreferences::ClearDataInRestoreFactorySettings()
231 {
232 if (database_ == nullptr) {
233 ANS_LOGE("database is nullptr");
234 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
235 }
236
237 if (!database_->ClearDatabase()) {
238 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
239 }
240
241 SetDistributedEnable(false);
242
243 preferencesInfo_ = std::make_unique<DistributedPreferencesInfo>();
244
245 return ERR_OK;
246 }
247
GetEnabledWithoutApp(const int32_t userId,std::string & key)248 void DistributedPreferences::GetEnabledWithoutApp(const int32_t userId, std::string &key)
249 {
250 key = DISTRIBUTED_LABEL + DELIMITER + WITHOUT_APP + DELIMITER + std::to_string(userId) + DELIMITER;
251 }
252
SetSyncEnabledWithoutApp(const int32_t userId,const bool enabled)253 ErrCode DistributedPreferences::SetSyncEnabledWithoutApp(const int32_t userId, const bool enabled)
254 {
255 if (database_ == nullptr || preferencesInfo_ == nullptr) {
256 ANS_LOGE("database or preferencesInfo is nullptr");
257 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
258 }
259 std::string key;
260 GetEnabledWithoutApp(userId, key);
261 if (!database_->PutToDistributedDB(key, std::to_string(enabled))) {
262 ANS_LOGE("put to distributed DB failed. key:%{public}s", key.c_str());
263 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
264 }
265 preferencesInfo_->SetSyncEnabledWithoutApp(userId, enabled);
266 return ERR_OK;
267 }
268
GetSyncEnabledWithoutApp(const int32_t userId,bool & enabled)269 ErrCode DistributedPreferences::GetSyncEnabledWithoutApp(const int32_t userId, bool &enabled)
270 {
271 return preferencesInfo_ == nullptr ?
272 ERR_ANS_DISTRIBUTED_OPERATION_FAILED : preferencesInfo_->GetSyncEnabledWithoutApp(userId, enabled);
273 }
274 } // namespace Notification
275 } // namespace OHOS