1 /*
2 * Copyright (c) 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 "oh_preferences.h"
17
18 #include "application_context.h"
19 #include "oh_convertor.h"
20 #include "log_print.h"
21 #include "oh_preferences_err_code.h"
22 #include "oh_preferences_impl.h"
23 #include "oh_preferences_value_impl.h"
24 #include "oh_preferences_value.h"
25 #include "preferences_file_operation.h"
26 #include "preferences_helper.h"
27 #include "securec.h"
28
29 using namespace OHOS::PreferencesNdk;
30 using namespace OHOS::AbilityRuntime;
31
OH_PreferencesImpl(std::shared_ptr<OHOS::NativePreferences::Preferences> preferences)32 OH_PreferencesImpl::OH_PreferencesImpl
33 (std::shared_ptr<OHOS::NativePreferences::Preferences> preferences) : preferences_(preferences)
34 {
35 }
36
PreferencesStructValidCheck(int64_t originCid,int64_t targetCid)37 bool NDKPreferencesUtils::PreferencesStructValidCheck(int64_t originCid, int64_t targetCid)
38 {
39 if (originCid != targetCid) {
40 LOG_ERROR("cid check failed, ori cid: %{public}ld, target cid: %{public}ld", static_cast<long>(originCid),
41 static_cast<long>(targetCid));
42 return false;
43 }
44 return true;
45 }
46
GetPreferencesDir(OH_PreferencesOption * options)47 std::pair<int, std::string> GetPreferencesDir(OH_PreferencesOption *options)
48 {
49 auto context = OHOS::AbilityRuntime::Context::GetApplicationContext();
50 if (context == nullptr) {
51 LOG_ERROR("get application context go wrong");
52 return { OH_Preferences_ErrCode::PREFERENCES_ERROR_STORAGE, "" };
53 }
54 if (options->GetDataGroupId().empty()) {
55 return { OH_Preferences_ErrCode::PREFERENCES_OK, context->GetPreferencesDir() };
56 }
57 std::string stagePreferencesDir;
58 int err = context->GetSystemPreferencesDir(options->GetDataGroupId(), false, stagePreferencesDir);
59 if (err != 0) {
60 LOG_ERROR("get system preferences dir failed, err: %{public}d", err);
61 return { OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM, stagePreferencesDir };
62 }
63 return { OH_Preferences_ErrCode::PREFERENCES_OK, stagePreferencesDir };
64 }
65
OH_Preferences_Open(OH_PreferencesOption * option,int * errCode)66 OH_Preferences *OH_Preferences_Open(OH_PreferencesOption *option, int *errCode)
67 {
68 if (option == nullptr || option->fileName.empty() || !NDKPreferencesUtils::PreferencesStructValidCheck(
69 option->cid, PreferencesNdkStructId::PREFERENCES_OH_OPTION_CID) || errCode == nullptr) {
70 LOG_ERROR("open preference cfg error, option is null: %{public}d, fileName is null: %{public}d, "
71 "errCode is null: %{public}d, err:%{public}d",
72 (option == nullptr), (option == nullptr) ? 1 : option->fileName.empty(), (errCode == nullptr),
73 OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM);
74 if (errCode != nullptr) {
75 *errCode = OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
76 }
77 return nullptr;
78 }
79
80 auto dirRes = GetPreferencesDir(option);
81 if (dirRes.first != OH_Preferences_ErrCode::PREFERENCES_OK) {
82 *errCode = dirRes.first;
83 return nullptr;
84 }
85 std::string filePath = dirRes.second + "/" + option->GetFileName();
86
87 Preferences_StorageType type = option->GetStorageType();
88 OHOS::NativePreferences::Options nativeOptions(filePath, option->GetBundleName(),
89 option->GetDataGroupId(), type == PREFERENCES_STORAGE_GSKV);
90
91 int nativeErr = OHOS::NativePreferences::E_OK;
92 std::shared_ptr<OHOS::NativePreferences::Preferences> innerPreferences=
93 OHOS::NativePreferences::PreferencesHelper::GetPreferences(nativeOptions, nativeErr);
94 *errCode = OHConvertor::NativeErrToNdk(nativeErr);
95 if (innerPreferences == nullptr || *errCode != OH_Preferences_ErrCode::PREFERENCES_OK) {
96 LOG_ERROR("Get native Preferences failed: %{public}s, errcode: %{public}d",
97 OHOS::NativePreferences::ExtractFileName(nativeOptions.filePath).c_str(), *errCode);
98 return nullptr;
99 }
100 OH_PreferencesImpl *preferenceImpl = new (std::nothrow) OH_PreferencesImpl(innerPreferences);
101 if (preferenceImpl == nullptr) {
102 innerPreferences = nullptr;
103 LOG_ERROR("new impl object failed");
104 *errCode = OH_Preferences_ErrCode::PREFERENCES_ERROR_MALLOC;
105 return nullptr;
106 }
107 preferenceImpl->SetPreferencesStoreFilePath(filePath);
108 preferenceImpl->cid = PreferencesNdkStructId::PREFERENCES_OH_PREFERENCES_CID;
109 return static_cast<OH_Preferences *>(preferenceImpl);
110 }
111
GetPreferencesImpl(OH_Preferences * preference)112 static OH_PreferencesImpl *GetPreferencesImpl(OH_Preferences *preference)
113 {
114 if (preference == nullptr ||
115 !NDKPreferencesUtils::PreferencesStructValidCheck(
116 preference->cid, PreferencesNdkStructId::PREFERENCES_OH_PREFERENCES_CID)) {
117 LOG_ERROR("preference invalid, is null: %{public}d", preference == nullptr);
118 return nullptr;
119 }
120 return static_cast<OH_PreferencesImpl *>(preference);
121 }
122
GetNativePreferencesFromOH(OH_Preferences * preference)123 static std::shared_ptr<OHOS::NativePreferences::Preferences> GetNativePreferencesFromOH(OH_Preferences *preference)
124 {
125 auto preferencesImpl = GetPreferencesImpl(preference);
126 if (preferencesImpl == nullptr ||
127 !NDKPreferencesUtils::PreferencesStructValidCheck(
128 preference->cid, PreferencesNdkStructId::PREFERENCES_OH_PREFERENCES_CID)) {
129 LOG_ERROR("preferences is null: %{public}d when get native preferences from ohPreferences",
130 (preferencesImpl == nullptr));
131 return nullptr;
132 }
133 std::shared_ptr<OHOS::NativePreferences::Preferences> innerPreferences= preferencesImpl->GetNativePreferences();
134 if (innerPreferences== nullptr) {
135 LOG_ERROR("preference not open yet");
136 return nullptr;
137 }
138 return innerPreferences;
139 }
140
SetPreferencesStoreFilePath(const std::string & filePath)141 void OH_PreferencesImpl::SetPreferencesStoreFilePath(const std::string &filePath)
142 {
143 std::unique_lock<std::shared_mutex> writeLock(mutex_);
144 filePath_ = filePath;
145 }
146
GetPreferencesStoreFilePath()147 std::string OH_PreferencesImpl::GetPreferencesStoreFilePath()
148 {
149 std::shared_lock<std::shared_mutex> readLock(mutex_);
150 return filePath_;
151 }
152
OH_Preferences_Close(OH_Preferences * preference)153 int OH_Preferences_Close(OH_Preferences *preference)
154 {
155 auto preferencesImpl = GetPreferencesImpl(preference);
156 if (preferencesImpl == nullptr) {
157 LOG_ERROR("preferences close failed, preferences is null");
158 return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
159 }
160 std::shared_ptr<OHOS::NativePreferences::Preferences> innerPreferences= preferencesImpl->GetNativePreferences();
161 if (innerPreferences== nullptr) {
162 LOG_ERROR("preference not open yet");
163 return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
164 }
165
166 innerPreferences->FlushSync();
167
168 int errCode = OHOS::NativePreferences::PreferencesHelper::RemovePreferencesFromCache(
169 preferencesImpl->GetPreferencesStoreFilePath());
170 if (errCode != OHOS::NativePreferences::E_OK) {
171 LOG_ERROR("preference close failed: %{public}d", errCode);
172 return OHConvertor::NativeErrToNdk(errCode);
173 }
174 delete preferencesImpl;
175 return OH_Preferences_ErrCode::PREFERENCES_OK;
176 }
177
OH_Preferences_GetInt(OH_Preferences * preference,const char * key,int * value)178 int OH_Preferences_GetInt(OH_Preferences *preference, const char *key, int *value)
179 {
180 std::shared_ptr<OHOS::NativePreferences::Preferences> innerPreferences= GetNativePreferencesFromOH(preference);
181 if (innerPreferences== nullptr || key == nullptr || value == nullptr) {
182 LOG_ERROR("get int failed, preference not open yet: %{public}d, key is null: %{public}d, "
183 "value is null: %{public}d, err: %{public}d", (innerPreferences== nullptr), (key == nullptr),
184 (value == nullptr), OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM);
185 return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
186 }
187
188 auto res = innerPreferences->GetValue(key, OHOS::NativePreferences::PreferencesValue());
189 if (res.first != OHOS::NativePreferences::E_OK) {
190 LOG_ERROR("Get Int failed, %{public}d", res.first);
191 return OHConvertor::NativeErrToNdk(res.first);
192 }
193
194 if (res.second.IsInt()) {
195 *value = (int)(res.second);
196 } else {
197 LOG_ERROR("Get Int failed, value's type is not int");
198 if (res.first == OHOS::NativePreferences::E_OK) {
199 return OH_Preferences_ErrCode::PREFERENCES_ERROR_KEY_NOT_FOUND;
200 }
201 }
202
203 return OHConvertor::NativeErrToNdk(res.first);
204 }
205
OH_Preferences_GetString(OH_Preferences * preference,const char * key,char ** value,uint32_t * valueLen)206 int OH_Preferences_GetString(OH_Preferences *preference, const char *key, char **value,
207 uint32_t *valueLen)
208 {
209 std::shared_ptr<OHOS::NativePreferences::Preferences> innerPreferences= GetNativePreferencesFromOH(preference);
210 if (innerPreferences== nullptr || key == nullptr || value == nullptr || valueLen == nullptr) {
211 LOG_ERROR("get str failed, preference not open yet: %{public}d, key is null: %{public}d, "
212 "value is null: %{public}d, valueLen is null: %{public}d, err: %{public}d",
213 (innerPreferences== nullptr), (key == nullptr), (value == nullptr), (valueLen == nullptr),
214 OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM);
215 return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
216 }
217
218 auto res = innerPreferences->GetValue(key, OHOS::NativePreferences::PreferencesValue());
219 if (res.first != OHOS::NativePreferences::E_OK) {
220 LOG_ERROR("Get string failed, %{public}d", res.first);
221 return OHConvertor::NativeErrToNdk(res.first);
222 }
223
224 if (res.second.IsString()) {
225 std::string str = (std::string)(res.second);
226 size_t strLen = str.size();
227 if (strLen >= SIZE_MAX) {
228 LOG_ERROR(" string length overlimit: %{public}zu", strLen);
229 return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
230 }
231 void *ptr = malloc(strLen + 1); // free by caller
232 if (ptr == nullptr) {
233 LOG_ERROR("malloc failed when get string, errno: %{public}d", errno);
234 return OH_Preferences_ErrCode::PREFERENCES_ERROR_MALLOC;
235 }
236 int sysErr = memset_s(ptr, (strLen + 1), 0, (strLen + 1));
237 if (sysErr != EOK) {
238 LOG_ERROR("memset failed when get string, errCode: %{public}d", sysErr);
239 }
240 if (strLen > 0) {
241 sysErr = memcpy_s(ptr, strLen, str.c_str(), strLen);
242 if (sysErr != EOK) {
243 LOG_ERROR("memcpy failed when get string, errCode: %{public}d", sysErr);
244 free(ptr);
245 return OH_Preferences_ErrCode::PREFERENCES_ERROR_MALLOC;
246 }
247 }
248 *value = reinterpret_cast<char *>(ptr);
249 *valueLen = strLen + 1;
250 } else {
251 LOG_ERROR("Get string failed, value's type is not string, err: %{public}d", res.first);
252 if (res.first == OHOS::NativePreferences::E_OK) {
253 return OH_Preferences_ErrCode::PREFERENCES_ERROR_KEY_NOT_FOUND;
254 }
255 }
256
257 return OHConvertor::NativeErrToNdk(res.first);
258 }
259
OH_Preferences_FreeString(char * string)260 void OH_Preferences_FreeString(char *string)
261 {
262 free(string);
263 }
264
OH_Preferences_GetBool(OH_Preferences * preference,const char * key,bool * value)265 int OH_Preferences_GetBool(OH_Preferences *preference, const char *key, bool *value)
266 {
267 std::shared_ptr<OHOS::NativePreferences::Preferences> innerPreferences= GetNativePreferencesFromOH(preference);
268 if (innerPreferences== nullptr || key == nullptr || value == nullptr) {
269 LOG_ERROR("get bool failed, preference not open yet: %{public}d, key is null: %{public}d, "
270 "value is null: %{public}d, err: %{public}d", (innerPreferences== nullptr), (key == nullptr),
271 (value == nullptr), OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM);
272 return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
273 }
274
275 auto res = innerPreferences->GetValue(key, OHOS::NativePreferences::PreferencesValue());
276 if (res.first != OHOS::NativePreferences::E_OK) {
277 LOG_ERROR("Get bool failed, %{public}d", res.first);
278 return OHConvertor::NativeErrToNdk(res.first);
279 }
280
281 if (res.second.IsBool()) {
282 *value = (bool)(res.second);
283 } else {
284 LOG_ERROR("Get bool failed, value's type is not bool, err: %{public}d", res.first);
285 if (res.first == OHOS::NativePreferences::E_OK) {
286 return OH_Preferences_ErrCode::PREFERENCES_ERROR_KEY_NOT_FOUND;
287 }
288 }
289
290 return OHConvertor::NativeErrToNdk(res.first);
291 }
292
OH_Preferences_SetInt(OH_Preferences * preference,const char * key,int value)293 int OH_Preferences_SetInt(OH_Preferences *preference, const char *key, int value)
294 {
295 std::shared_ptr<OHOS::NativePreferences::Preferences> innerPreferences= GetNativePreferencesFromOH(preference);
296 if (innerPreferences== nullptr || key == nullptr) {
297 LOG_ERROR("set int failed, preference not open yet: %{public}d, key is null: %{public}d, err: %{public}d",
298 (innerPreferences== nullptr), (key == nullptr), OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM);
299 return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
300 }
301
302 int errCode = innerPreferences->PutInt(key, value);
303 if (errCode != OHOS::NativePreferences::E_OK) {
304 LOG_ERROR("preference put int failed, err: %{public}d", errCode);
305 }
306 return OHConvertor::NativeErrToNdk(errCode);
307 }
308
OH_Preferences_SetBool(OH_Preferences * preference,const char * key,bool value)309 int OH_Preferences_SetBool(OH_Preferences *preference, const char *key, bool value)
310 {
311 std::shared_ptr<OHOS::NativePreferences::Preferences> innerPreferences= GetNativePreferencesFromOH(preference);
312 if (innerPreferences== nullptr || key == nullptr) {
313 LOG_ERROR("set bool failed, preference not open yet: %{public}d, key is null: %{public}d, err: %{public}d",
314 (innerPreferences== nullptr), (key == nullptr), OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM);
315 return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
316 }
317
318 int errCode = innerPreferences->PutBool(key, value);
319 if (errCode != OHOS::NativePreferences::E_OK) {
320 LOG_ERROR("preference put bool failed, err: %{public}d", errCode);
321 }
322 return OHConvertor::NativeErrToNdk(errCode);
323 }
324
OH_Preferences_SetString(OH_Preferences * preference,const char * key,const char * value)325 int OH_Preferences_SetString(OH_Preferences *preference, const char *key, const char *value)
326 {
327 std::shared_ptr<OHOS::NativePreferences::Preferences> innerPreferences= GetNativePreferencesFromOH(preference);
328 if (innerPreferences== nullptr || key == nullptr || value == nullptr) {
329 LOG_ERROR("set str failed, preference not open yet: %{public}d, key is null: %{public}d, "
330 "value is null: %{public}d, err: %{public}d", (innerPreferences== nullptr), (key == nullptr),
331 (value == nullptr), OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM);
332 return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
333 }
334
335 int errCode = innerPreferences->PutString(key, value);
336 if (errCode != OHOS::NativePreferences::E_OK) {
337 LOG_ERROR("preference put string failed, err: %{public}d", errCode);
338 }
339 return OHConvertor::NativeErrToNdk(errCode);
340 }
341
OH_Preferences_Delete(OH_Preferences * preference,const char * key)342 int OH_Preferences_Delete(OH_Preferences *preference, const char *key)
343 {
344 std::shared_ptr<OHOS::NativePreferences::Preferences> innerPreferences= GetNativePreferencesFromOH(preference);
345 if (innerPreferences== nullptr || key == nullptr) {
346 LOG_ERROR("delete failed, preference not open yet: %{public}d, key is null: %{public}d, err: %{public}d",
347 (innerPreferences== nullptr), (key == nullptr), OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM);
348 return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
349 }
350
351 int errCode = innerPreferences->Delete(key);
352 if (errCode != OHOS::NativePreferences::E_OK) {
353 LOG_ERROR("preference delete value failed, err: %{public}d", errCode);
354 }
355 return OHConvertor::NativeErrToNdk(errCode);
356 }
357
OH_Preferences_RegisterDataObserver(OH_Preferences * preference,void * context,OH_PreferencesDataObserver observer,const char * keys[],uint32_t keyCount)358 int OH_Preferences_RegisterDataObserver(OH_Preferences *preference, void *context,
359 OH_PreferencesDataObserver observer, const char *keys[], uint32_t keyCount)
360 {
361 auto preferencesImpl = GetPreferencesImpl(preference);
362 if (preferencesImpl == nullptr || observer == nullptr || keys == nullptr) {
363 LOG_ERROR("register failed, sp is null ? %{public}d, obs is null ? %{public}d, "
364 "keys is null: %{public}d, err: %{public}d", (preferencesImpl == nullptr), (observer == nullptr),
365 (keys == nullptr), OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM);
366 return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
367 }
368
369 std::vector<std::string> keysVec;
370 for (uint32_t i = 0; i < keyCount; i++) {
371 keysVec.push_back(keys[i]);
372 }
373
374 return OHConvertor::NativeErrToNdk(preferencesImpl->RegisterDataObserver(observer, context, keysVec));
375 }
376
OH_Preferences_UnregisterDataObserver(OH_Preferences * preference,void * context,OH_PreferencesDataObserver observer,const char * keys[],uint32_t keyCount)377 int OH_Preferences_UnregisterDataObserver(OH_Preferences *preference, void *context,
378 OH_PreferencesDataObserver observer, const char *keys[], uint32_t keyCount)
379 {
380 auto preferencesImpl = GetPreferencesImpl(preference);
381 if (preferencesImpl == nullptr || observer == nullptr || keys == nullptr) {
382 LOG_ERROR("unregister failed, sp is null ? %{public}d, obs is null ? %{public}d, "
383 "keys is null: %{public}d, err: %{public}d", (preferencesImpl == nullptr), (observer == nullptr),
384 (keys == nullptr), OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM);
385 return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
386 }
387 std::vector<std::string> keysVec;
388 for (uint32_t i = 0; i < keyCount; i++) {
389 keysVec.push_back(keys[i]);
390 }
391 return OHConvertor::NativeErrToNdk(preferencesImpl->UnregisterDataObserver(observer, context, keysVec));
392 }
393
OH_Preferences_IsStorageTypeSupported(Preferences_StorageType type,bool * isSupported)394 int OH_Preferences_IsStorageTypeSupported(Preferences_StorageType type, bool *isSupported)
395 {
396 if (type < Preferences_StorageType::PREFERENCES_STORAGE_XML ||
397 type > Preferences_StorageType::PREFERENCES_STORAGE_GSKV || isSupported == nullptr) {
398 LOG_ERROR("param check failed, type: %{public}d, isSupported is null: %{public}d", static_cast<int>(type),
399 isSupported == nullptr);
400 return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM;
401 }
402
403 *isSupported = OHOS::NativePreferences::PreferencesHelper::
404 IsStorageTypeSupported(OHConvertor::NdkStorageTypeToNative(type));
405 if (!*isSupported) {
406 LOG_WARN("current type not supported on this platform");
407 }
408 return OH_Preferences_ErrCode::PREFERENCES_OK;
409 }
410
RegisterDataObserver(OH_PreferencesDataObserver observer,void * context,const std::vector<std::string> & keys)411 int OH_PreferencesImpl::RegisterDataObserver(
412 OH_PreferencesDataObserver observer, void *context, const std::vector<std::string> &keys)
413 {
414 std::unique_lock<std::shared_mutex> writeLock(obsMutex_);
415
416 auto ndkObserver = std::make_shared<NDKPreferencesObserver>(observer, context);
417 int errCode = preferences_->RegisterDataObserver(ndkObserver, keys);
418 if (errCode != OHOS::NativePreferences::E_OK) {
419 LOG_ERROR("register failed, err: %{public}d", errCode);
420 } else {
421 dataObservers_.emplace_back(std::make_pair(std::move(ndkObserver), context));
422 }
423 return OHConvertor::NativeErrToNdk(errCode);
424 }
425
NDKPreferencesObserver(OH_PreferencesDataObserver observer,void * context)426 NDKPreferencesObserver::NDKPreferencesObserver(OH_PreferencesDataObserver observer, void *context)
427 : dataObserver_(observer), context_(context) {}
428
FreePairValue(OH_PreferencesPair * pairs,size_t count)429 inline void FreePairValue(OH_PreferencesPair *pairs, size_t count)
430 {
431 for (size_t i = 0; i < count; i++) {
432 delete pairs[i].value;
433 }
434 }
435
OnChange(const std::map<std::string,OHOS::NativePreferences::PreferencesValue> & records)436 void NDKPreferencesObserver::OnChange(const std::map<std::string, OHOS::NativePreferences::PreferencesValue> &records)
437 {
438 if (dataObserver_ == nullptr) {
439 LOG_ERROR("failed to trigger change, data observer is null");
440 return;
441 }
442 auto count = records.size();
443 if (count == 0) {
444 return;
445 }
446 OH_PreferencesPair *pairs = new (std::nothrow) OH_PreferencesPair[count];
447 if (pairs == nullptr) {
448 LOG_ERROR("malloc pairs failed when on change, count: %{public}d, errno:%{public}d", static_cast<int>(count),
449 errno);
450 return;
451 }
452 int i = 0;
453 for (const auto &[key, value] : records) {
454 OH_PreferencesValueImpl *valueImpl = new (std::nothrow) OH_PreferencesValueImpl();
455 if (valueImpl == nullptr) {
456 LOG_ERROR("new value object failed");
457 FreePairValue(pairs, i);
458 delete []pairs;
459 return;
460 }
461 valueImpl->cid = PreferencesNdkStructId::PREFERENCES_OH_VALUE_CID;
462 valueImpl->value_ = value;
463 pairs[i++] = OH_PreferencesPair { PreferencesNdkStructId::PREFERENCES_OH_PAIR_CID, key.c_str(),
464 static_cast<OH_PreferencesValue *>(valueImpl), count};
465 }
466 (dataObserver_)(context_, pairs, count);
467 FreePairValue(pairs, count);
468 delete []pairs;
469 }
470
OnChange(const std::string & key)471 void NDKPreferencesObserver::OnChange(const std::string &key)
472 {
473 }
474
UnregisterDataObserver(OH_PreferencesDataObserver observer,void * context,const std::vector<std::string> & keys)475 int OH_PreferencesImpl::UnregisterDataObserver(OH_PreferencesDataObserver observer, void *context,
476 const std::vector<std::string> &keys)
477 {
478 std::unique_lock<std::shared_mutex> writeLock(obsMutex_);
479 for (size_t i = 0; i < dataObservers_.size(); i++) {
480 if (!dataObservers_[i].first->ObserverCompare(observer) || dataObservers_[i].second != context) {
481 continue;
482 }
483
484 int errCode = preferences_->UnRegisterDataObserver(dataObservers_[i].first, keys);
485 if (errCode != OHOS::NativePreferences::E_OK) {
486 LOG_ERROR("un register observer failed, err: %{public}d", errCode);
487 return OHConvertor::NativeErrToNdk(errCode);
488 }
489 if (keys.empty()) {
490 dataObservers_[i] = { nullptr, nullptr };
491 dataObservers_.erase(dataObservers_.begin() + i);
492 }
493 }
494 return OH_Preferences_ErrCode::PREFERENCES_OK;
495 }
496
ObserverCompare(OH_PreferencesDataObserver other)497 bool NDKPreferencesObserver::ObserverCompare(OH_PreferencesDataObserver other)
498 {
499 if (other == nullptr) {
500 return false;
501 }
502 return other == dataObserver_;
503 }
504