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 #ifndef LOG_TAG
16 #define LOG_TAG "AudioSettingProvider"
17 #endif
18
19 #include "audio_setting_provider.h"
20
21 #include "iservice_registry.h"
22 #include "audio_errors.h"
23 #include "system_ability_definition.h"
24 #include "audio_utils.h"
25
26 namespace OHOS {
27 namespace AudioStandard {
28 AudioSettingProvider* AudioSettingProvider::instance_;
29 std::mutex AudioSettingProvider::mutex_;
30 std::atomic<bool> AudioSettingProvider::isDataShareReady_ = false;
31 sptr<IRemoteObject> AudioSettingProvider::remoteObj_;
32
33 const std::string SETTING_COLUMN_KEYWORD = "KEYWORD";
34 const std::string SETTING_COLUMN_VALUE = "VALUE";
35 const std::string SETTING_URI_PROXY = "datashare:///com.ohos.settingsdata/entry/settingsdata/SETTINGSDATA?Proxy=true";
36 const std::string SETTING_USER_URI_PROXY = "datashare:///com.ohos.settingsdata/entry/settingsdata/USER_SETTINGSDATA_";
37 const std::string SETTING_USER_SECURE_URI_PROXY =
38 "datashare:///com.ohos.settingsdata/entry/settingsdata/USER_SETTINGSDATA_SECURE_";
39 constexpr const char *SETTINGS_DATA_EXT_URI = "datashare:///com.ohos.settingsdata.DataAbility";
40 constexpr int32_t RETRY_TIMES = 5;
41 constexpr int64_t SLEEP_TIME = 1;
42
~AudioSettingProvider()43 AudioSettingProvider::~AudioSettingProvider()
44 {
45 instance_ = nullptr;
46 remoteObj_ = nullptr;
47 }
48
OnChange()49 void AudioSettingObserver::OnChange()
50 {
51 if (update_) {
52 update_(key_);
53 }
54 }
55
SetKey(const std::string & key)56 void AudioSettingObserver::SetKey(const std::string &key)
57 {
58 key_ = key;
59 }
60
GetKey()61 const std::string& AudioSettingObserver::GetKey()
62 {
63 return key_;
64 }
65
SetUpdateFunc(UpdateFunc & func)66 void AudioSettingObserver::SetUpdateFunc(UpdateFunc &func)
67 {
68 update_ = func;
69 }
70
GetInstance(int32_t systemAbilityId)71 AudioSettingProvider& AudioSettingProvider::GetInstance(
72 int32_t systemAbilityId)
73 {
74 if (instance_ == nullptr) {
75 std::lock_guard<std::mutex> lock(mutex_);
76 if (instance_ == nullptr) {
77 Initialize(systemAbilityId);
78 instance_ = new AudioSettingProvider();
79 }
80 }
81 return *instance_;
82 }
83
GetIntValue(const std::string & key,int32_t & value,std::string tableType)84 ErrCode AudioSettingProvider::GetIntValue(const std::string &key, int32_t &value,
85 std::string tableType)
86 {
87 int64_t valueLong;
88 ErrCode ret = GetLongValue(key, valueLong, tableType);
89 if (ret != ERR_OK) {
90 return ret;
91 }
92 value = static_cast<int32_t>(valueLong);
93 return ERR_OK;
94 }
95
GetLongValue(const std::string & key,int64_t & value,std::string tableType)96 ErrCode AudioSettingProvider::GetLongValue(const std::string &key, int64_t &value,
97 std::string tableType)
98 {
99 std::string valueStr;
100 ErrCode ret = GetStringValue(key, valueStr, tableType);
101 if (ret != ERR_OK) {
102 return ret;
103 }
104 value = static_cast<int64_t>(strtoll(valueStr.c_str(), nullptr, MAX_STRING_LENGTH));
105 return ERR_OK;
106 }
107
GetFloatValue(const std::string & key,float & value,std::string tableType)108 ErrCode AudioSettingProvider::GetFloatValue(const std::string &key, float &value,
109 std::string tableType)
110 {
111 std::string valueStr;
112 ErrCode ret = GetStringValue(key, valueStr, tableType);
113 if (ret != ERR_OK) {
114 return ret;
115 }
116 CHECK_AND_RETURN_RET_LOG(StringConverterFloat(valueStr, value), ERR_INVALID_PARAM,
117 "GetFloatValue error! invalid valueStr = %{public}s", valueStr.c_str());
118 return ERR_OK;
119 }
120
GetBoolValue(const std::string & key,bool & value,std::string tableType)121 ErrCode AudioSettingProvider::GetBoolValue(const std::string &key, bool &value,
122 std::string tableType)
123 {
124 std::string valueStr;
125 ErrCode ret = GetStringValue(key, valueStr, tableType);
126 if (ret != ERR_OK) {
127 return ret;
128 }
129 value = (valueStr == "true");
130 return ERR_OK;
131 }
132
PutIntValue(const std::string & key,int32_t value,std::string tableType,bool needNotify)133 ErrCode AudioSettingProvider::PutIntValue(const std::string &key, int32_t value,
134 std::string tableType, bool needNotify)
135 {
136 return PutStringValue(key, std::to_string(value), tableType, needNotify);
137 }
138
PutLongValue(const std::string & key,int64_t value,std::string tableType,bool needNotify)139 ErrCode AudioSettingProvider::PutLongValue(const std::string &key, int64_t value,
140 std::string tableType, bool needNotify)
141 {
142 return PutStringValue(key, std::to_string(value), tableType, needNotify);
143 }
144
PutBoolValue(const std::string & key,bool value,std::string tableType,bool needNotify)145 ErrCode AudioSettingProvider::PutBoolValue(const std::string &key, bool value,
146 std::string tableType, bool needNotify)
147 {
148 std::string valueStr = value ? "true" : "false";
149 return PutStringValue(key, valueStr, tableType, needNotify);
150 }
151
IsValidKey(const std::string & key)152 bool AudioSettingProvider::IsValidKey(const std::string &key)
153 {
154 std::string value;
155 ErrCode ret = GetStringValue(key, value);
156 return (ret != ERR_NAME_NOT_FOUND) && (!value.empty());
157 }
158
CreateObserver(const std::string & key,AudioSettingObserver::UpdateFunc & func)159 sptr<AudioSettingObserver> AudioSettingProvider::CreateObserver(
160 const std::string &key, AudioSettingObserver::UpdateFunc &func)
161 {
162 sptr<AudioSettingObserver> observer = new AudioSettingObserver();
163 observer->SetKey(key);
164 observer->SetUpdateFunc(func);
165 return observer;
166 }
167
ExecRegisterCb(const sptr<AudioSettingObserver> & observer)168 void AudioSettingProvider::ExecRegisterCb(const sptr<AudioSettingObserver> &observer)
169 {
170 if (observer == nullptr) {
171 AUDIO_ERR_LOG("observer is nullptr");
172 return;
173 }
174 observer->OnChange();
175 }
176
RegisterObserver(const sptr<AudioSettingObserver> & observer,std::string tableType)177 ErrCode AudioSettingProvider::RegisterObserver(const sptr<AudioSettingObserver> &observer, std::string tableType)
178 {
179 std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
180 auto uri = AssembleUri(observer->GetKey(), tableType);
181 if (!isDataShareReady_) {
182 AUDIO_WARNING_LOG("DataShareHelper is not ready");
183 return ERR_NO_INIT;
184 }
185 auto helper = CreateDataShareHelper(tableType);
186 if (helper == nullptr) {
187 IPCSkeleton::SetCallingIdentity(callingIdentity);
188 return ERR_NO_INIT;
189 }
190 helper->RegisterObserver(uri, observer);
191 helper->NotifyChange(uri);
192 auto execFirCb = ([observer] { ExecRegisterCb(observer); });
193 std::thread execCb(execFirCb);
194 execCb.detach();
195 ReleaseDataShareHelper(helper);
196 IPCSkeleton::SetCallingIdentity(callingIdentity);
197 AUDIO_DEBUG_LOG("succeed to register observer of uri=%{public}s", uri.ToString().c_str());
198 return ERR_OK;
199 }
200
UnregisterObserver(const sptr<AudioSettingObserver> & observer,std::string tableType)201 ErrCode AudioSettingProvider::UnregisterObserver(const sptr<AudioSettingObserver> &observer, std::string tableType)
202 {
203 std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
204 auto uri = AssembleUri(observer->GetKey(), tableType);
205 auto helper = CreateDataShareHelper(tableType);
206 if (helper == nullptr) {
207 IPCSkeleton::SetCallingIdentity(callingIdentity);
208 return ERR_NO_INIT;
209 }
210 helper->UnregisterObserver(uri, observer);
211 ReleaseDataShareHelper(helper);
212 IPCSkeleton::SetCallingIdentity(callingIdentity);
213 AUDIO_DEBUG_LOG("succeed to unregister observer of uri=%{public}s", uri.ToString().c_str());
214 return ERR_OK;
215 }
216
Initialize(int32_t systemAbilityId)217 void AudioSettingProvider::Initialize(int32_t systemAbilityId)
218 {
219 auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
220 if (sam == nullptr) {
221 AUDIO_ERR_LOG("GetSystemAbilityManager return nullptr");
222 return;
223 }
224 auto remoteObj = sam->GetSystemAbility(systemAbilityId);
225 if (remoteObj == nullptr) {
226 AUDIO_ERR_LOG("GetSystemAbility return nullptr, systemAbilityId=%{public}d", systemAbilityId);
227 return;
228 }
229 remoteObj_ = remoteObj;
230 }
231
GetStringValue(const std::string & key,std::string & value,std::string tableType)232 ErrCode AudioSettingProvider::GetStringValue(const std::string &key,
233 std::string &value, std::string tableType)
234 {
235 std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
236 auto helper = CreateDataShareHelper(tableType);
237 if (helper == nullptr) {
238 IPCSkeleton::SetCallingIdentity(callingIdentity);
239 return ERR_NO_INIT;
240 }
241 std::vector<std::string> columns = {SETTING_COLUMN_VALUE};
242 DataShare::DataSharePredicates predicates;
243 predicates.EqualTo(SETTING_COLUMN_KEYWORD, key);
244 Uri uri(AssembleUri(key, tableType));
245 auto resultSet = helper->Query(uri, predicates, columns);
246 ReleaseDataShareHelper(helper);
247 if (resultSet == nullptr) {
248 AUDIO_ERR_LOG("helper->Query return nullptr");
249 IPCSkeleton::SetCallingIdentity(callingIdentity);
250 return ERR_INVALID_OPERATION;
251 }
252 int32_t count;
253 resultSet->GetRowCount(count);
254 if (count == 0) {
255 AUDIO_WARNING_LOG("not found value, key=%{public}s, uri=%{public}s, count=%{public}d", key.c_str(),
256 uri.ToString().c_str(), count);
257 IPCSkeleton::SetCallingIdentity(callingIdentity);
258 resultSet->Close();
259 return ERR_NAME_NOT_FOUND;
260 }
261 const int32_t INDEX = 0;
262 resultSet->GoToRow(INDEX);
263 int32_t ret = resultSet->GetString(INDEX, value);
264 if (ret != SUCCESS) {
265 AUDIO_WARNING_LOG("resultSet->GetString return not ok, ret=%{public}d", ret);
266 IPCSkeleton::SetCallingIdentity(callingIdentity);
267 resultSet->Close();
268 return ERR_INVALID_VALUE;
269 } else {
270 AUDIO_INFO_LOG("Read audio_info_database with key: %{public}s value: %{public}s in uri=%{public}s ",
271 key.c_str(), value.c_str(), uri.ToString().c_str());
272 }
273 resultSet->Close();
274 IPCSkeleton::SetCallingIdentity(callingIdentity);
275 return ERR_OK;
276 }
277
PutStringValue(const std::string & key,const std::string & value,std::string tableType,bool needNotify)278 ErrCode AudioSettingProvider::PutStringValue(const std::string &key, const std::string &value,
279 std::string tableType, bool needNotify)
280 {
281 AUDIO_INFO_LOG("Write audio_info_database with key: %{public}s value: %{public}s", key.c_str(), value.c_str());
282 std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
283 auto helper = CreateDataShareHelper(tableType);
284 if (helper == nullptr) {
285 IPCSkeleton::SetCallingIdentity(callingIdentity);
286 return ERR_NO_INIT;
287 }
288 DataShare::DataShareValueObject keyObj(key);
289 DataShare::DataShareValueObject valueObj(value);
290 DataShare::DataShareValuesBucket bucket;
291 bucket.Put(SETTING_COLUMN_KEYWORD, keyObj);
292 bucket.Put(SETTING_COLUMN_VALUE, valueObj);
293 DataShare::DataSharePredicates predicates;
294 predicates.EqualTo(SETTING_COLUMN_KEYWORD, key);
295 Uri uri(AssembleUri(key, tableType));
296 if (helper->Update(uri, predicates, bucket) <= 0) {
297 AUDIO_INFO_LOG("audio_info_database no data exist, insert one row");
298 helper->Insert(uri, bucket);
299 }
300 if (needNotify) {
301 helper->NotifyChange(AssembleUri(key, tableType));
302 }
303 ReleaseDataShareHelper(helper);
304 IPCSkeleton::SetCallingIdentity(callingIdentity);
305 return ERR_OK;
306 }
307
GetCurrentUserId()308 int32_t AudioSettingProvider::GetCurrentUserId()
309 {
310 std::vector<int> ids;
311 int32_t currentuserId = -1;
312 ErrCode result;
313 int32_t retry = RETRY_TIMES;
314 while (retry--) {
315 result = AccountSA::OsAccountManager::QueryActiveOsAccountIds(ids);
316 if (result == ERR_OK && !ids.empty()) {
317 currentuserId = ids[0];
318 AUDIO_DEBUG_LOG("current userId is :%{public}d", currentuserId);
319 break;
320 }
321 // sleep and wait for 1 second
322 sleep(SLEEP_TIME);
323 }
324 if (result != ERR_OK || ids.empty()) {
325 AUDIO_WARNING_LOG("current userId is empty");
326 }
327 return currentuserId;
328 }
329
CheckOsAccountReady()330 bool AudioSettingProvider::CheckOsAccountReady()
331 {
332 std::vector<int> ids;
333 ErrCode result = AccountSA::OsAccountManager::QueryActiveOsAccountIds(ids);
334 return (result == ERR_OK && !ids.empty());
335 }
336
SetDataShareReady(std::atomic<bool> isDataShareReady)337 void AudioSettingProvider::SetDataShareReady(std::atomic<bool> isDataShareReady)
338 {
339 AUDIO_INFO_LOG("Receive event DATA_SHARE_READY");
340 isDataShareReady_.store(isDataShareReady);
341 }
342
CreateDataShareHelper(std::string tableType)343 std::shared_ptr<DataShare::DataShareHelper> AudioSettingProvider::CreateDataShareHelper(
344 std::string tableType)
345 {
346 CHECK_AND_RETURN_RET_LOG(isDataShareReady_.load(), nullptr,
347 "DATA_SHARE_READY not received, create DataShareHelper failed");
348 if (remoteObj_ == nullptr) {
349 std::lock_guard<std::mutex> lock(mutex_);
350 Initialize(AUDIO_POLICY_SERVICE_ID);
351 }
352 #ifdef SUPPORT_USER_ACCOUNT
353 int32_t currentuserId = GetCurrentUserId();
354 if (currentuserId < MIN_USER_ACCOUNT) {
355 currentuserId = MIN_USER_ACCOUNT;
356 }
357 #else
358 int32_t currentuserId = -1;
359 #endif
360 std::shared_ptr<DataShare::DataShareHelper> helper = nullptr;
361 std::string SettingSystemUrlProxy = "";
362 // deal with multi useraccount table
363 if (currentuserId > 0 && tableType == "system") {
364 SettingSystemUrlProxy =
365 SETTING_USER_URI_PROXY + std::to_string(currentuserId) + "?Proxy=true";
366 helper = DataShare::DataShareHelper::Creator(remoteObj_, SettingSystemUrlProxy, SETTINGS_DATA_EXT_URI);
367 } else if (currentuserId > 0 && tableType == "secure") {
368 SettingSystemUrlProxy =
369 SETTING_USER_SECURE_URI_PROXY + std::to_string(currentuserId) + "?Proxy=true";
370 WatchTimeout guard("DataShare::DataShareHelper::Creator:CreateDataShareHelper.SettingSystemUrlProxy");
371 helper = DataShare::DataShareHelper::Creator(remoteObj_, SettingSystemUrlProxy, SETTINGS_DATA_EXT_URI);
372 guard.CheckCurrTimeout();
373 } else {
374 WatchTimeout guard("DataShare::DataShareHelper::Creator:CreateDataShareHelper.SETTING_URI_PROXY");
375 helper = DataShare::DataShareHelper::Creator(remoteObj_, SETTING_URI_PROXY, SETTINGS_DATA_EXT_URI);
376 guard.CheckCurrTimeout();
377 }
378 if (helper == nullptr) {
379 AUDIO_WARNING_LOG("helper is nullptr, uri=%{public}s", SettingSystemUrlProxy.c_str());
380 return nullptr;
381 }
382 return helper;
383 }
384
ReleaseDataShareHelper(std::shared_ptr<DataShare::DataShareHelper> & helper)385 bool AudioSettingProvider::ReleaseDataShareHelper(
386 std::shared_ptr<DataShare::DataShareHelper> &helper)
387 {
388 if (!helper->Release()) {
389 AUDIO_WARNING_LOG("release helper fail");
390 return false;
391 }
392 return true;
393 }
394
AssembleUri(const std::string & key,std::string tableType)395 Uri AudioSettingProvider::AssembleUri(const std::string &key, std::string tableType)
396 {
397 #ifdef SUPPORT_USER_ACCOUNT
398 int32_t currentuserId = GetCurrentUserId();
399 if (currentuserId < MIN_USER_ACCOUNT) {
400 currentuserId = MIN_USER_ACCOUNT;
401 }
402 #else
403 int32_t currentuserId = -1;
404 #endif
405 std::string SettingSystemUrlProxy = "";
406
407 // deal with multi useraccount table
408 if (currentuserId > 0 && tableType == "system") {
409 SettingSystemUrlProxy = SETTING_USER_URI_PROXY + std::to_string(currentuserId) + "?Proxy=true";
410 Uri uri(SettingSystemUrlProxy + "&key=" + key);
411 return uri;
412 } else if (currentuserId > 0 && tableType == "secure") {
413 SettingSystemUrlProxy = SETTING_USER_SECURE_URI_PROXY + std::to_string(currentuserId) + "?Proxy=true";
414 Uri uri(SettingSystemUrlProxy + "&key=" + key);
415 return uri;
416 }
417 Uri uri(SETTING_URI_PROXY + "&key=" + key);
418 return uri;
419 }
420 } // namespace AudioStandard
421 } // namespace OHOS
422