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