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