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 "setting_provider.h"
17#include <thread>
18#include <regex>
19#include "datashare_predicates.h"
20#include "datashare_result_set.h"
21#include "datashare_values_bucket.h"
22#include "ipc_skeleton.h"
23#include "iservice_registry.h"
24#include "os_account_manager.h"
25#include "power_log.h"
26#include "rdb_errno.h"
27#include "result_set.h"
28#include "uri.h"
29
30namespace OHOS {
31namespace PowerMgr {
32SettingProvider* SettingProvider::instance_;
33std::mutex SettingProvider::settingMutex_;
34sptr<IRemoteObject> SettingProvider::remoteObj_;
35const int32_t INITIAL_USER_ID = 100;
36int32_t SettingProvider::currentUserId_ = INITIAL_USER_ID;
37namespace {
38const std::string SETTING_COLUMN_KEYWORD = "KEYWORD";
39const std::string SETTING_COLUMN_VALUE = "VALUE";
40const std::string SETTING_URI_PROXY = "datashare:///com.ohos.settingsdata/entry/settingsdata/SETTINGSDATA?Proxy=true";
41const std::string SETTING_URI_PROXY_USER = "datashare:///com.ohos.settingsdata/entry/settingsdata/";
42const std::string SETTING_URI_PROXY_USER_ADAPT = "USER_SETTINGSDATA_SECURE_##USERID##?Proxy=true";
43constexpr const char *USERID_REPLACE = "##USERID##";
44constexpr const char *SETTINGS_DATA_EXT_URI = "datashare:///com.ohos.settingsdata.DataAbility";
45} // namespace
46
47SettingProvider::~SettingProvider()
48{
49    instance_ = nullptr;
50    remoteObj_ = nullptr;
51}
52
53SettingProvider& SettingProvider::GetInstance(int32_t systemAbilityId)
54{
55    if (instance_ == nullptr) {
56        std::lock_guard<std::mutex> lock(settingMutex_);
57        if (instance_ == nullptr) {
58            instance_ = new SettingProvider();
59            Initialize(systemAbilityId);
60        }
61    }
62    return *instance_;
63}
64
65ErrCode SettingProvider::GetIntValue(const std::string& key, int32_t& value)
66{
67    int64_t valueLong;
68    ErrCode ret = GetLongValue(key, valueLong);
69    if (ret != ERR_OK) {
70        return ret;
71    }
72    value = static_cast<int32_t>(valueLong);
73    return ERR_OK;
74}
75
76ErrCode SettingProvider::GetLongValue(const std::string& key, int64_t& value)
77{
78    std::string valueStr;
79    ErrCode ret = GetStringValue(key, valueStr);
80    if (ret != ERR_OK) {
81        return ret;
82    }
83    value = static_cast<int64_t>(strtoll(valueStr.c_str(), nullptr, 10));
84    return ERR_OK;
85}
86
87ErrCode SettingProvider::GetBoolValue(const std::string& key, bool& value)
88{
89    std::string valueStr;
90    ErrCode ret = GetStringValue(key, valueStr);
91    if (ret != ERR_OK) {
92        return ret;
93    }
94    value = (valueStr == "true");
95    return ERR_OK;
96}
97
98ErrCode SettingProvider::PutIntValue(const std::string& key, int32_t value, bool needNotify)
99{
100    return PutStringValue(key, std::to_string(value), needNotify);
101}
102
103ErrCode SettingProvider::PutLongValue(const std::string& key, int64_t value, bool needNotify)
104{
105    return PutStringValue(key, std::to_string(value), needNotify);
106}
107
108ErrCode SettingProvider::PutBoolValue(const std::string& key, bool value, bool needNotify)
109{
110    std::string valueStr = value ? "true" : "false";
111    return PutStringValue(key, valueStr, needNotify);
112}
113
114bool SettingProvider::IsValidKey(const std::string& key)
115{
116    std::string value;
117    ErrCode ret = GetStringValue(key, value);
118    if (!value.empty()) {
119        POWER_HILOGI(COMP_UTILS, "the getValue is:%{public}s", value.c_str());
120    }
121    POWER_HILOGI(COMP_UTILS, "the getRet is:%{public}u", ret);
122    return (ret != ERR_NAME_NOT_FOUND) && (!value.empty());
123}
124
125sptr<SettingObserver> SettingProvider::CreateObserver(const std::string& key, SettingObserver::UpdateFunc& func)
126{
127    sptr<SettingObserver> observer = new SettingObserver();
128    observer->SetKey(key);
129    observer->SetUpdateFunc(func);
130    return observer;
131}
132
133void SettingProvider::ExecRegisterCb(const sptr<SettingObserver>& observer)
134{
135    if (observer == nullptr) {
136        POWER_HILOGE(COMP_UTILS, "observer is nullptr");
137        return;
138    }
139    observer->OnChange();
140}
141
142ErrCode SettingProvider::RegisterObserver(const sptr<SettingObserver>& observer)
143{
144    std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
145    auto uri = AssembleUri(observer->GetKey());
146    auto helper = CreateDataShareHelper(observer->GetKey());
147    if (helper == nullptr) {
148        IPCSkeleton::SetCallingIdentity(callingIdentity);
149        return ERR_NO_INIT;
150    }
151    helper->RegisterObserver(uri, observer);
152    helper->NotifyChange(uri);
153    std::thread execCb([this, observer] { this->ExecRegisterCb(observer); });
154    execCb.detach();
155    ReleaseDataShareHelper(helper);
156    IPCSkeleton::SetCallingIdentity(callingIdentity);
157    POWER_HILOGD(COMP_UTILS, "succeed to register observer of uri=%{public}s", uri.ToString().c_str());
158    return ERR_OK;
159}
160
161ErrCode SettingProvider::UnregisterObserver(const sptr<SettingObserver>& observer)
162{
163    std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
164    auto uri = AssembleUri(observer->GetKey());
165    auto helper = CreateDataShareHelper(observer->GetKey());
166    if (helper == nullptr) {
167        IPCSkeleton::SetCallingIdentity(callingIdentity);
168        return ERR_NO_INIT;
169    }
170    helper->UnregisterObserver(uri, observer);
171    ReleaseDataShareHelper(helper);
172    IPCSkeleton::SetCallingIdentity(callingIdentity);
173    POWER_HILOGD(COMP_UTILS, "succeed to unregister observer of uri=%{public}s", uri.ToString().c_str());
174    return ERR_OK;
175}
176
177void SettingProvider::Initialize(int32_t systemAbilityId)
178{
179    auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
180    if (sam == nullptr) {
181        POWER_HILOGE(COMP_UTILS, "GetSystemAbilityManager return nullptr");
182        return;
183    }
184    auto remoteObj = sam->GetSystemAbility(systemAbilityId);
185    if (remoteObj == nullptr) {
186        POWER_HILOGE(COMP_UTILS, "GetSystemAbility return nullptr, systemAbilityId=%{public}d", systemAbilityId);
187        return;
188    }
189    remoteObj_ = remoteObj;
190}
191
192ErrCode SettingProvider::GetStringValue(const std::string& key, std::string& value)
193{
194    std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
195    auto helper = CreateDataShareHelper(key);
196    if (helper == nullptr) {
197        IPCSkeleton::SetCallingIdentity(callingIdentity);
198        return ERR_NO_INIT;
199    }
200    std::vector<std::string> columns = {SETTING_COLUMN_VALUE};
201    DataShare::DataSharePredicates predicates;
202    predicates.EqualTo(SETTING_COLUMN_KEYWORD, key);
203    Uri uri(AssembleUri(key));
204    auto resultSet = helper->Query(uri, predicates, columns);
205    ReleaseDataShareHelper(helper);
206    if (resultSet == nullptr) {
207        POWER_HILOGE(COMP_UTILS, "helper->Query return nullptr");
208        IPCSkeleton::SetCallingIdentity(callingIdentity);
209        return ERR_INVALID_OPERATION;
210    }
211    int32_t count;
212    resultSet->GetRowCount(count);
213    if (count == 0) {
214        POWER_HILOGW(COMP_UTILS, "not found value, key=%{public}s, count=%{public}d", key.c_str(), count);
215        IPCSkeleton::SetCallingIdentity(callingIdentity);
216        resultSet->Close();
217        return ERR_NAME_NOT_FOUND;
218    }
219    const int32_t INDEX = 0;
220    resultSet->GoToRow(INDEX);
221    int32_t ret = resultSet->GetString(INDEX, value);
222    if (ret != NativeRdb::E_OK) {
223        POWER_HILOGW(COMP_UTILS, "resultSet->GetString return not ok, ret=%{public}d", ret);
224        IPCSkeleton::SetCallingIdentity(callingIdentity);
225        resultSet->Close();
226        return ERR_INVALID_VALUE;
227    }
228    resultSet->Close();
229    IPCSkeleton::SetCallingIdentity(callingIdentity);
230    return ERR_OK;
231}
232
233ErrCode SettingProvider::PutStringValue(const std::string& key, const std::string& value, bool needNotify)
234{
235    std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
236    auto helper = CreateDataShareHelper(key);
237    if (helper == nullptr) {
238        IPCSkeleton::SetCallingIdentity(callingIdentity);
239        return ERR_NO_INIT;
240    }
241    DataShare::DataShareValueObject keyObj(key);
242    DataShare::DataShareValueObject valueObj(value);
243    DataShare::DataShareValuesBucket bucket;
244    bucket.Put(SETTING_COLUMN_KEYWORD, keyObj);
245    bucket.Put(SETTING_COLUMN_VALUE, valueObj);
246    DataShare::DataSharePredicates predicates;
247    predicates.EqualTo(SETTING_COLUMN_KEYWORD, key);
248    Uri uri(AssembleUri(key));
249    if (helper->Update(uri, predicates, bucket) <= 0) {
250        POWER_HILOGD(COMP_UTILS, "no data exist, insert one row");
251        helper->Insert(uri, bucket);
252    }
253    if (needNotify) {
254        helper->NotifyChange(AssembleUri(key));
255    }
256    ReleaseDataShareHelper(helper);
257    IPCSkeleton::SetCallingIdentity(callingIdentity);
258    return ERR_OK;
259}
260
261std::shared_ptr<DataShare::DataShareHelper> SettingProvider::CreateDataShareHelper(const std::string& key)
262{
263    std::lock_guard<std::mutex> lock(settingMutex_);
264    std::string uriProxyStr;
265    if (IsNeedMultiUser(key)) {
266        uriProxyStr = SETTING_URI_PROXY_USER + "USER_SETTINGSDATA_SECURE_" +
267            std::to_string(currentUserId_) + "?Proxy=true";
268        POWER_HILOGI(COMP_UTILS, "the uriProxyStr is %{public}s", uriProxyStr.c_str());
269    } else {
270        uriProxyStr = SETTING_URI_PROXY;
271    }
272    auto helper = DataShare::DataShareHelper::Creator(remoteObj_, uriProxyStr, SETTINGS_DATA_EXT_URI);
273    if (helper == nullptr) {
274        POWER_HILOGW(COMP_UTILS, "helper is nullptr, uri=%{public}s", uriProxyStr.c_str());
275        return nullptr;
276    }
277    return helper;
278}
279
280bool SettingProvider::ReleaseDataShareHelper(std::shared_ptr<DataShare::DataShareHelper>& helper)
281{
282    if (!helper->Release()) {
283        POWER_HILOGW(COMP_UTILS, "release helper fail");
284        return false;
285    }
286    return true;
287}
288
289Uri SettingProvider::AssembleUri(const std::string& key)
290{
291    std::lock_guard<std::mutex> lock(settingMutex_);
292    if (IsNeedMultiUser(key)) {
293        std::string userSetting = ReplaceUserIdForUri(currentUserId_);
294        std::string specialUri = SETTING_URI_PROXY_USER + userSetting + "&key=" + key;
295        POWER_HILOGI(COMP_UTILS, "the non-global uri is %{public}s", specialUri.c_str());
296        Uri uri(specialUri);
297        return uri;
298    }
299    Uri uri(SETTING_URI_PROXY + "&key=" + key);
300    return uri;
301}
302
303bool SettingProvider::IsNeedMultiUser(const std::string& key)
304{
305    std::vector<std::string> needMultiUserStrVec {
306        SETTING_POWER_WAKEUP_DOUBLE_KEY,
307        SETTING_POWER_WAKEUP_PICKUP_KEY,
308        SETTING_POWER_WAKEUP_SOURCES_KEY,
309#ifdef POWER_MANAGER_ENABLE_CHARGING_TYPE_SETTING
310        SETTING_DISPLAY_AC_OFF_TIME_KEY,
311        SETTING_DISPLAY_DC_OFF_TIME_KEY,
312        SETTING_POWER_AC_SUSPEND_SOURCES_KEY,
313        SETTING_POWER_DC_SUSPEND_SOURCES_KEY,
314#endif
315    };
316
317    if (std::count(needMultiUserStrVec.begin(), needMultiUserStrVec.end(), key)) {
318        return true;
319    }
320    return false;
321}
322
323std::string SettingProvider::ReplaceUserIdForUri(int32_t userId)
324{
325    std::string tempUri = SETTING_URI_PROXY_USER_ADAPT;
326    std::regex pattern(USERID_REPLACE);
327    return std::regex_replace(tempUri, pattern, std::to_string(userId));
328}
329
330void SettingProvider::UpdateCurrentUserId()
331{
332    std::lock_guard<std::mutex> lock(settingMutex_);
333    std::vector<int> activedIds;
334    int ret = AccountSA::OsAccountManager::QueryActiveOsAccountIds(activedIds);
335    if (ret != 0) {
336        POWER_HILOGE(COMP_UTILS, "QueryActivedOsAccountIds failed, ret is %{public}d", ret);
337        return;
338    }
339    if (activedIds.empty()) {
340        POWER_HILOGE(COMP_UTILS, "QueryActivedOsAccountIds is empty");
341        return;
342    }
343    currentUserId_ = activedIds[0];
344    POWER_HILOGI(COMP_UTILS, "currentUserId_ is %{public}d", currentUserId_);
345}
346} // namespace PowerMgr
347} // namespace OHOS