• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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