1/* 2 * Copyright (c) 2023 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_datashare.h" 17 18#include <thread> 19 20#include "datashare_predicates.h" 21#include "datashare_result_set.h" 22#include "datashare_values_bucket.h" 23#include "ipc_skeleton.h" 24#include "iservice_registry.h" 25#include "mmi_log.h" 26#include "rdb_errno.h" 27#include "result_set.h" 28#include "system_ability_definition.h" 29#include "uri.h" 30 31#undef MMI_LOG_DOMAIN 32#define MMI_LOG_DOMAIN MMI_LOG_HANDLER 33#undef MMI_LOG_TAG 34#define MMI_LOG_TAG "setting_DataShare" 35 36namespace OHOS { 37namespace MMI { 38std::shared_ptr<SettingDataShare> SettingDataShare::instance_ = nullptr; 39std::mutex SettingDataShare::mutex_; 40sptr<IRemoteObject> SettingDataShare::remoteObj_; 41namespace { 42const std::string SETTING_COLUMN_KEYWORD { "KEYWORD" }; 43const std::string SETTING_COLUMN_VALUE { "VALUE" }; 44const std::string SETTING_URI_PROXY { "datashare:///com.ohos.settingsdata/entry/settingsdata/SETTINGSDATA?Proxy=true" }; 45const std::string SETTING_URI_USER_PROXY { 46 "datashare:///com.ohos.settingsdata/entry/settingsdata/USER_SETTINGSDATA_SECURE_100?Proxy=true" }; 47const std::string SETTINGS_DATA_EXT_URI { "datashare:///com.ohos.settingsdata.DataAbility" }; 48constexpr int32_t DECIMAL_BASE { 10 }; 49constexpr const int32_t E_OK{ 0 }; 50constexpr const int32_t E_DATA_SHARE_NOT_READY { 1055 }; 51} // namespace 52 53SettingDataShare::~SettingDataShare() {} 54 55SettingDataShare& SettingDataShare::GetInstance(int32_t systemAbilityId) 56{ 57 if (instance_ == nullptr) { 58 std::lock_guard<std::mutex> lock(mutex_); 59 if (instance_ == nullptr) { 60 instance_ = std::make_shared<SettingDataShare>(); 61 } 62 } 63 return *instance_; 64} 65 66ErrCode SettingDataShare::GetIntValue(const std::string& key, int32_t& value, const std::string &strUri) 67{ 68 int64_t valueLong; 69 ErrCode ret = GetLongValue(key, valueLong, strUri); 70 if (ret != ERR_OK) { 71 MMI_HILOGE("Get int value fail"); 72 return ret; 73 } 74 value = static_cast<int32_t>(valueLong); 75 return ERR_OK; 76} 77 78ErrCode SettingDataShare::GetLongValue(const std::string& key, int64_t& value, const std::string &strUri) 79{ 80 std::string valueStr; 81 ErrCode ret = GetStringValue(key, valueStr, strUri); 82 if (ret == ERR_NAME_NOT_FOUND) { 83 MMI_HILOGW("Not found this property"); 84 return ERR_OK; 85 } 86 if (ret != ERR_OK) { 87 MMI_HILOGE("Get long value fail, ret:%{public}d", ret); 88 return ret; 89 } 90 value = static_cast<int64_t>(strtoll(valueStr.c_str(), nullptr, DECIMAL_BASE)); 91 return ERR_OK; 92} 93 94ErrCode SettingDataShare::GetBoolValue(const std::string& key, bool& value, const std::string &strUri) 95{ 96 std::string valueStr; 97 ErrCode ret = GetStringValue(key, valueStr, strUri); 98 if (ret == ERR_NAME_NOT_FOUND) { 99 MMI_HILOGW("Not found this property"); 100 return ERR_OK; 101 } 102 if (ret != ERR_OK) { 103 MMI_HILOGE("Get bool value fail, ret:%{public}d", ret); 104 return ret; 105 } 106 value = ((valueStr == "true") || (valueStr == "1")); 107 return ERR_OK; 108} 109 110ErrCode SettingDataShare::PutIntValue( 111 const std::string& key, int32_t value, bool needNotify, const std::string &strUri) 112{ 113 return PutStringValue(key, std::to_string(value), needNotify, strUri); 114} 115 116ErrCode SettingDataShare::PutLongValue( 117 const std::string& key, int64_t value, bool needNotify, const std::string &strUri) 118{ 119 return PutStringValue(key, std::to_string(value), needNotify, strUri); 120} 121 122ErrCode SettingDataShare::PutBoolValue( 123 const std::string& key, bool value, bool needNotify, const std::string &strUri) 124{ 125 std::string valueStr = value ? "true" : "false"; 126 return PutStringValue(key, valueStr, needNotify, strUri); 127} 128 129bool SettingDataShare::IsValidKey(const std::string& key, const std::string &strUri) 130{ 131 std::string value; 132 ErrCode ret = GetStringValue(key, value, strUri); 133 return (ret != ERR_NAME_NOT_FOUND) && (!value.empty()); 134} 135 136sptr<SettingObserver> SettingDataShare::CreateObserver(const std::string& key, SettingObserver::UpdateFunc& func) 137{ 138 sptr<SettingObserver> observer = new (std::nothrow) SettingObserver(); 139 CHKPP(observer); 140 observer->SetKey(key); 141 observer->SetUpdateFunc(func); 142 return observer; 143} 144 145void SettingDataShare::ExecRegisterCb(const sptr<SettingObserver>& observer) 146{ 147 CHKPV(observer); 148 observer->OnChange(); 149} 150 151ErrCode SettingDataShare::RegisterObserver(const sptr<SettingObserver>& observer, const std::string &strUri) 152{ 153 if (!isDataShareReady_) { 154 MMI_HILOGI("Data share not ready!"); 155 return RET_ERR; 156 } 157 CHKPR(observer, RET_ERR); 158 std::string callingIdentity = IPCSkeleton::ResetCallingIdentity(); 159 auto uri = AssembleUri(observer->GetKey(), strUri); 160 auto helper = CreateDataShareHelper(strUri); 161 if (helper == nullptr) { 162 IPCSkeleton::SetCallingIdentity(callingIdentity); 163 return ERR_NO_INIT; 164 } 165 helper->RegisterObserver(uri, observer); 166 helper->NotifyChange(uri); 167 std::thread execCb([this, observer] { this->ExecRegisterCb(observer); }); 168 execCb.detach(); 169 ReleaseDataShareHelper(helper); 170 IPCSkeleton::SetCallingIdentity(callingIdentity); 171 return ERR_OK; 172} 173 174ErrCode SettingDataShare::UnregisterObserver(const sptr<SettingObserver>& observer, const std::string &strUri) 175{ 176 if (!isDataShareReady_) { 177 MMI_HILOGI("Data share not ready!"); 178 return RET_ERR; 179 } 180 CHKPR(observer, RET_ERR); 181 std::string callingIdentity = IPCSkeleton::ResetCallingIdentity(); 182 auto uri = AssembleUri(observer->GetKey(), strUri); 183 auto helper = CreateDataShareHelper(strUri); 184 if (helper == nullptr) { 185 IPCSkeleton::SetCallingIdentity(callingIdentity); 186 return ERR_NO_INIT; 187 } 188 helper->UnregisterObserver(uri, observer); 189 ReleaseDataShareHelper(helper); 190 IPCSkeleton::SetCallingIdentity(callingIdentity); 191 return ERR_OK; 192} 193 194ErrCode SettingDataShare::GetStringValue(const std::string& key, std::string& value, const std::string &strUri) 195{ 196 if (!isDataShareReady_) { 197 MMI_HILOGI("Data share not ready!"); 198 return RET_ERR; 199 } 200 std::string callingIdentity = IPCSkeleton::ResetCallingIdentity(); 201 auto helper = CreateDataShareHelper(strUri); 202 if (helper == nullptr) { 203 IPCSkeleton::SetCallingIdentity(callingIdentity); 204 return ERR_NO_INIT; 205 } 206 std::vector<std::string> columns = {SETTING_COLUMN_VALUE}; 207 DataShare::DataSharePredicates predicates; 208 predicates.EqualTo(SETTING_COLUMN_KEYWORD, key); 209 Uri uri(AssembleUri(key, strUri)); 210 auto resultSet = helper->Query(uri, predicates, columns); 211 ReleaseDataShareHelper(helper); 212 if (resultSet == nullptr) { 213 IPCSkeleton::SetCallingIdentity(callingIdentity); 214 return ERR_INVALID_OPERATION; 215 } 216 int32_t count = 0; 217 resultSet->GetRowCount(count); 218 if (count == 0) { 219 IPCSkeleton::SetCallingIdentity(callingIdentity); 220 return ERR_NAME_NOT_FOUND; 221 } 222 const int32_t tmpRow = 0; 223 resultSet->GoToRow(tmpRow); 224 int32_t ret = resultSet->GetString(tmpRow, value); 225 if (ret != RET_OK) { 226 IPCSkeleton::SetCallingIdentity(callingIdentity); 227 return ERR_INVALID_VALUE; 228 } 229 resultSet->Close(); 230 IPCSkeleton::SetCallingIdentity(callingIdentity); 231 return ERR_OK; 232} 233 234ErrCode SettingDataShare::PutStringValue( 235 const std::string& key, const std::string& value, bool needNotify, const std::string &strUri) 236{ 237 if (!isDataShareReady_) { 238 MMI_HILOGI("Data share not ready!"); 239 return RET_ERR; 240 } 241 std::string callingIdentity = IPCSkeleton::ResetCallingIdentity(); 242 auto helper = CreateDataShareHelper(strUri); 243 if (helper == nullptr) { 244 IPCSkeleton::SetCallingIdentity(callingIdentity); 245 return ERR_NO_INIT; 246 } 247 DataShare::DataShareValueObject keyObj(key); 248 DataShare::DataShareValueObject valueObj(value); 249 DataShare::DataShareValuesBucket bucket; 250 bucket.Put(SETTING_COLUMN_KEYWORD, keyObj); 251 bucket.Put(SETTING_COLUMN_VALUE, valueObj); 252 DataShare::DataSharePredicates predicates; 253 predicates.EqualTo(SETTING_COLUMN_KEYWORD, key); 254 Uri uri(AssembleUri(key, strUri)); 255 if (helper->Update(uri, predicates, bucket) <= 0) { 256 helper->Insert(uri, bucket); 257 } 258 if (needNotify) { 259 helper->NotifyChange(AssembleUri(key, strUri)); 260 } 261 ReleaseDataShareHelper(helper); 262 IPCSkeleton::SetCallingIdentity(callingIdentity); 263 return ERR_OK; 264} 265 266std::shared_ptr<DataShare::DataShareHelper> SettingDataShare::CreateDataShareHelper(const std::string &strUri) 267{ 268 if (remoteObj_ == nullptr) { 269 std::lock_guard<std::mutex> lock(mutex_); 270 if (remoteObj_ == nullptr) { 271 auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); 272 CHKPP(sam); 273 remoteObj_ = sam->CheckSystemAbility(MULTIMODAL_INPUT_SERVICE_ID); 274 } 275 } 276 std::pair<int, std::shared_ptr<DataShare::DataShareHelper>> ret; 277 if (strUri.empty()) { 278 ret = DataShare::DataShareHelper::Create(remoteObj_, SETTING_URI_PROXY, SETTINGS_DATA_EXT_URI.c_str()); 279 } else { 280 ret = DataShare::DataShareHelper::Create(remoteObj_, strUri, ""); 281 } 282 return ret.second; 283} 284 285bool SettingDataShare::ReleaseDataShareHelper(std::shared_ptr<DataShare::DataShareHelper>& helper) 286{ 287 if (!helper->Release()) { 288 return false; 289 } 290 return true; 291} 292 293Uri SettingDataShare::AssembleUri(const std::string& key, const std::string &strUri) 294{ 295 if (strUri.empty()) { 296 if (key == "close_fingerprint_nav_event_key" || key == "close_fingerprint_event_key") { 297 return Uri(SETTING_URI_USER_PROXY + "&key=" + key); 298 } 299 return Uri(SETTING_URI_PROXY + "&key=" + key); 300 } else { 301 return Uri(strUri + "&key=" + key); 302 } 303} 304 305bool SettingDataShare::CheckIfSettingsDataReady() 306{ 307 if (isDataShareReady_) { 308 return true; 309 } 310 if (remoteObj_ == nullptr) { 311 std::lock_guard<std::mutex> lock(mutex_); 312 if (remoteObj_ == nullptr) { 313 auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); 314 CHKPF(sam); 315 remoteObj_ = sam->CheckSystemAbility(MULTIMODAL_INPUT_SERVICE_ID); 316 } 317 } 318 CHKPF(remoteObj_); 319 std::pair<int, std::shared_ptr<DataShare::DataShareHelper>> ret = 320 DataShare::DataShareHelper::Create(remoteObj_, SETTING_URI_PROXY, SETTINGS_DATA_EXT_URI); 321 MMI_HILOGD("Create data_share helper, ret=%{public}d", ret.first); 322 if (ret.first == E_OK) { 323 MMI_HILOGD("Create data_share helper success"); 324 auto helper = ret.second; 325 if (helper != nullptr) { 326 bool releaseRet = helper->Release(); 327 MMI_HILOGD("Release data_share helper, releaseRet=%{public}d", releaseRet); 328 } 329 isDataShareReady_ = true; 330 return true; 331 } else if (ret.first == E_DATA_SHARE_NOT_READY) { 332 MMI_HILOGE("Create data_share helper failed"); 333 isDataShareReady_ = false; 334 return false; 335 } 336 MMI_HILOGE("data_share unknown"); 337 return true; 338} 339} 340} // namespace OHOS