• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 std::mutex AudioSettingProvider::mutex_;
29 std::atomic<bool> AudioSettingProvider::isDataShareReady_ = false;
30 sptr<IRemoteObject> AudioSettingProvider::remoteObj_;
31 
32 const std::string SETTING_COLUMN_KEYWORD = "KEYWORD";
33 const std::string SETTING_COLUMN_VALUE = "VALUE";
34 const std::string SETTING_URI_PROXY = "datashare:///com.ohos.settingsdata/entry/settingsdata/SETTINGSDATA?Proxy=true";
35 const std::string SETTING_USER_URI_PROXY = "datashare:///com.ohos.settingsdata/entry/settingsdata/USER_SETTINGSDATA_";
36 const std::string SETTING_USER_SECURE_URI_PROXY =
37     "datashare:///com.ohos.settingsdata/entry/settingsdata/USER_SETTINGSDATA_SECURE_";
38 constexpr const char *SETTINGS_DATA_EXT_URI = "datashare:///com.ohos.settingsdata.DataAbility";
39 constexpr int32_t RETRY_TIMES = 5;
40 constexpr int64_t SLEEP_TIME = 1;
41 
~AudioSettingProvider()42 AudioSettingProvider::~AudioSettingProvider()
43 {
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     static AudioSettingProvider instance_;
73     std::lock_guard<std::mutex> lock(mutex_);
74     if (remoteObj_ == nullptr) {
75         Initialize(systemAbilityId);
76     }
77     return instance_;
78 }
79 
GetIntValue(const std::string & key,int32_t & value,std::string tableType)80 ErrCode AudioSettingProvider::GetIntValue(const std::string &key, int32_t &value,
81     std::string tableType)
82 {
83     int64_t valueLong;
84     ErrCode ret = GetLongValue(key, valueLong, tableType);
85     if (ret != ERR_OK) {
86         return ret;
87     }
88     value = static_cast<int32_t>(valueLong);
89     return ERR_OK;
90 }
91 
GetLongValue(const std::string & key,int64_t & value,std::string tableType)92 ErrCode AudioSettingProvider::GetLongValue(const std::string &key, int64_t &value,
93     std::string tableType)
94 {
95     std::string valueStr;
96     ErrCode ret = GetStringValue(key, valueStr, tableType);
97     if (ret != ERR_OK) {
98         return ret;
99     }
100     value = static_cast<int64_t>(strtoll(valueStr.c_str(), nullptr, MAX_STRING_LENGTH));
101     return ERR_OK;
102 }
103 
GetFloatValue(const std::string & key,float & value,std::string tableType)104 ErrCode AudioSettingProvider::GetFloatValue(const std::string &key, float &value,
105     std::string tableType)
106 {
107     std::string valueStr;
108     ErrCode ret = GetStringValue(key, valueStr, tableType);
109     if (ret != ERR_OK) {
110         return ret;
111     }
112     CHECK_AND_RETURN_RET_LOG(StringConverterFloat(valueStr, value), ERR_INVALID_PARAM,
113         "GetFloatValue error! invalid valueStr = %{public}s", valueStr.c_str());
114     return ERR_OK;
115 }
116 
GetBoolValue(const std::string & key,bool & value,std::string tableType,int32_t userId)117 ErrCode AudioSettingProvider::GetBoolValue(const std::string &key, bool &value,
118     std::string tableType, int32_t userId)
119 {
120     std::string valueStr;
121     ErrCode ret = GetStringValue(key, valueStr, tableType, userId);
122     if (ret != ERR_OK) {
123         return ret;
124     }
125     value = (valueStr == "true");
126     return ERR_OK;
127 }
128 
GetMapValue(const std::string & key,std::vector<std::map<std::string,std::string>> & value,std::string tableType)129 ErrCode AudioSettingProvider::GetMapValue(const std::string &key,
130     std::vector<std::map<std::string, std::string>> &value, std::string tableType)
131 {
132     std::string valueStr;
133     ErrCode ret = GetStringValue(key, valueStr, tableType);
134     if (ret != ERR_OK) {
135         return ret;
136     }
137     value = ParseJsonArray(valueStr);
138     return ERR_OK;
139 }
140 
ParseJsonArray(const std::string & input)141 std::vector<std::map<std::string, std::string>> AudioSettingProvider::ParseJsonArray(const std::string& input)
142 {
143     std::vector<std::map<std::string, std::string>> result;
144     size_t pos = 0;
145     const size_t len = input.length();
146     //skip the space value
147     auto skipWhitespace = [&]() {
148         while (pos < len && isspace(input[pos])) pos++;
149     };
150 
151     skipWhitespace();
152     if (input[pos++] != '[') return {};
153     while (pos < len) {
154         skipWhitespace();
155         if (input[pos] == ']') break;
156         if (input[pos++]!= '{') return {};
157         std::map<std::string, std::string> obj;
158         while (pos < len) {
159             skipWhitespace();
160             if (input[pos] == '}') {
161                 pos++;
162                 break;
163             }
164             std::string key = ParseFirstOfKey(pos, len, input);
165             if (key != "uid" && input.find(',', pos) != std::string::npos) {
166                 pos = input.find(',', pos);
167                 pos++;
168                 continue;
169             }
170             if (key != "uid") {
171                 continue;
172             }
173             skipWhitespace();
174             if (input[pos++] != ':') return {};
175             std::string value = ParseSecondOfValue(pos, len, input);
176             if (!key.empty() || !value.empty()) {
177                 obj[value] = "1";
178             }
179             skipWhitespace();
180             if (input[pos] == ',') pos++;
181         }
182         result.push_back(obj);
183         skipWhitespace();
184         if (input[pos] == ',') pos++;
185     }
186     return result;
187 }
188 
ParseFirstOfKey(size_t & pos,size_t len,std::string input)189 std::string AudioSettingProvider::ParseFirstOfKey(size_t &pos, size_t len, std::string input)
190 {
191     // parse the key of input
192     while (pos < len && isspace(input[pos])) {
193         pos++;
194     }
195     if (pos >= len) {
196         return "";
197     }
198     size_t start = ++pos;
199     while (pos < len && input[pos] != '"') {
200         pos++;
201     }
202     std::string str = input.substr(start, pos - start);
203     if (pos < len) {
204         pos++;
205     }
206     return str;
207 }
208 
ParseSecondOfValue(size_t & pos,size_t len,std::string input)209 std::string AudioSettingProvider::ParseSecondOfValue(size_t &pos, size_t len, std::string input)
210 {
211     // parse the value of input
212     while (pos < len && isspace(input[pos])) {
213         pos++;
214     }
215     if (pos >= len) {
216         return "";
217     }
218     size_t start = pos;
219     while (pos < len && input[pos] != ',') {
220         pos++;
221     }
222     std::string str = input.substr(start, pos - start);
223     if (pos < len) {
224         pos++;
225     }
226     return str;
227 }
228 
PutIntValue(const std::string & key,int32_t value,std::string tableType,bool needNotify)229 ErrCode AudioSettingProvider::PutIntValue(const std::string &key, int32_t value,
230     std::string tableType, bool needNotify)
231 {
232     return PutStringValue(key, std::to_string(value), tableType, needNotify);
233 }
234 
PutLongValue(const std::string & key,int64_t value,std::string tableType,bool needNotify)235 ErrCode AudioSettingProvider::PutLongValue(const std::string &key, int64_t value,
236     std::string tableType, bool needNotify)
237 {
238     return PutStringValue(key, std::to_string(value), tableType, needNotify);
239 }
240 
PutBoolValue(const std::string & key,bool value,std::string tableType,bool needNotify,int32_t userId)241 ErrCode AudioSettingProvider::PutBoolValue(const std::string &key, bool value,
242     std::string tableType, bool needNotify, int32_t userId)
243 {
244     std::string valueStr = value ? "true" : "false";
245     return PutStringValue(key, valueStr, tableType, needNotify, userId);
246 }
247 
IsValidKey(const std::string & key)248 bool AudioSettingProvider::IsValidKey(const std::string &key)
249 {
250     std::string value;
251     ErrCode ret = GetStringValue(key, value);
252     return (ret != ERR_NAME_NOT_FOUND) && (!value.empty());
253 }
254 
CreateObserver(const std::string & key,AudioSettingObserver::UpdateFunc & func)255 sptr<AudioSettingObserver> AudioSettingProvider::CreateObserver(
256     const std::string &key, AudioSettingObserver::UpdateFunc &func)
257 {
258     sptr<AudioSettingObserver> observer = new AudioSettingObserver();
259     observer->SetKey(key);
260     observer->SetUpdateFunc(func);
261     return observer;
262 }
263 
ExecRegisterCb(const sptr<AudioSettingObserver> & observer)264 void AudioSettingProvider::ExecRegisterCb(const sptr<AudioSettingObserver> &observer)
265 {
266     if (observer == nullptr) {
267         AUDIO_ERR_LOG("observer is nullptr");
268         return;
269     }
270     observer->OnChange();
271 }
272 
RegisterObserver(const sptr<AudioSettingObserver> & observer,std::string tableType)273 ErrCode AudioSettingProvider::RegisterObserver(const sptr<AudioSettingObserver> &observer, std::string tableType)
274 {
275     std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
276     auto uri = AssembleUri(observer->GetKey(), tableType);
277     if (!isDataShareReady_) {
278         AUDIO_WARNING_LOG("DataShareHelper is not ready");
279         return ERR_NO_INIT;
280     }
281     auto helper = CreateDataShareHelper(tableType);
282     if (helper == nullptr) {
283         IPCSkeleton::SetCallingIdentity(callingIdentity);
284         return ERR_NO_INIT;
285     }
286     helper->RegisterObserver(uri, observer);
287     helper->NotifyChange(uri);
288     auto execFirCb = ([observer] { ExecRegisterCb(observer); });
289     std::thread execCb(execFirCb);
290     execCb.detach();
291     ReleaseDataShareHelper(helper);
292     IPCSkeleton::SetCallingIdentity(callingIdentity);
293     AUDIO_DEBUG_LOG("succeed to register observer of uri=%{public}s", uri.ToString().c_str());
294     return ERR_OK;
295 }
296 
UnregisterObserver(const sptr<AudioSettingObserver> & observer,std::string tableType)297 ErrCode AudioSettingProvider::UnregisterObserver(const sptr<AudioSettingObserver> &observer, std::string tableType)
298 {
299     std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
300     auto uri = AssembleUri(observer->GetKey(), tableType);
301     auto helper = CreateDataShareHelper(tableType);
302     if (helper == nullptr) {
303         IPCSkeleton::SetCallingIdentity(callingIdentity);
304         return ERR_NO_INIT;
305     }
306     helper->UnregisterObserver(uri, observer);
307     ReleaseDataShareHelper(helper);
308     IPCSkeleton::SetCallingIdentity(callingIdentity);
309     AUDIO_DEBUG_LOG("succeed to unregister observer of uri=%{public}s", uri.ToString().c_str());
310     return ERR_OK;
311 }
312 
Initialize(int32_t systemAbilityId)313 void AudioSettingProvider::Initialize(int32_t systemAbilityId)
314 {
315     auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
316     if (sam == nullptr) {
317         AUDIO_ERR_LOG("GetSystemAbilityManager return nullptr");
318         return;
319     }
320     auto remoteObj = sam->GetSystemAbility(systemAbilityId);
321     if (remoteObj == nullptr) {
322         AUDIO_ERR_LOG("GetSystemAbility return nullptr, systemAbilityId=%{public}d", systemAbilityId);
323         return;
324     }
325     remoteObj_ = remoteObj;
326 }
327 
GetStringValue(const std::string & key,std::string & value,std::string tableType,int32_t userId)328 ErrCode AudioSettingProvider::GetStringValue(const std::string &key,
329     std::string &value, std::string tableType, int32_t userId)
330 {
331     std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
332     auto helper = CreateDataShareHelper(tableType, userId);
333     if (helper == nullptr) {
334         IPCSkeleton::SetCallingIdentity(callingIdentity);
335         return ERR_NO_INIT;
336     }
337     std::vector<std::string> columns = {SETTING_COLUMN_VALUE};
338     DataShare::DataSharePredicates predicates;
339     predicates.EqualTo(SETTING_COLUMN_KEYWORD, key);
340     Uri uri(AssembleUri(key, tableType, userId));
341     auto resultSet = helper->Query(uri, predicates, columns);
342     ReleaseDataShareHelper(helper);
343     if (resultSet == nullptr) {
344         AUDIO_ERR_LOG("helper->Query return nullptr");
345         IPCSkeleton::SetCallingIdentity(callingIdentity);
346         return ERR_INVALID_OPERATION;
347     }
348     int32_t count;
349     resultSet->GetRowCount(count);
350     if (count == 0) {
351         AUDIO_WARNING_LOG("not found value, key=%{public}s, uri=%{public}s, count=%{public}d", key.c_str(),
352             uri.ToString().c_str(), count);
353         IPCSkeleton::SetCallingIdentity(callingIdentity);
354         resultSet->Close();
355         return ERR_NAME_NOT_FOUND;
356     }
357     const int32_t INDEX = 0;
358     resultSet->GoToRow(INDEX);
359     int32_t ret = resultSet->GetString(INDEX, value);
360     if (ret != SUCCESS) {
361         AUDIO_WARNING_LOG("resultSet->GetString return not ok, ret=%{public}d", ret);
362         IPCSkeleton::SetCallingIdentity(callingIdentity);
363         resultSet->Close();
364         return ERR_INVALID_VALUE;
365     } else {
366         AUDIO_INFO_LOG("Read audio_info_database with key: %{public}s value: %{public}s in uri=%{public}s ",
367             key.c_str(), value.c_str(), uri.ToString().c_str());
368     }
369     resultSet->Close();
370     IPCSkeleton::SetCallingIdentity(callingIdentity);
371     return ERR_OK;
372 }
373 
PutStringValue(const std::string & key,const std::string & value,std::string tableType,bool needNotify,int32_t userId)374 ErrCode AudioSettingProvider::PutStringValue(const std::string &key, const std::string &value,
375     std::string tableType, bool needNotify, int32_t userId)
376 {
377     AUDIO_INFO_LOG("Write audio_info_database with key: %{public}s value: %{public}s", key.c_str(), value.c_str());
378     std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
379     auto helper = CreateDataShareHelper(tableType, userId);
380     if (helper == nullptr) {
381         IPCSkeleton::SetCallingIdentity(callingIdentity);
382         return ERR_NO_INIT;
383     }
384     DataShare::DataShareValueObject keyObj(key);
385     DataShare::DataShareValueObject valueObj(value);
386     DataShare::DataShareValuesBucket bucket;
387     bucket.Put(SETTING_COLUMN_KEYWORD, keyObj);
388     bucket.Put(SETTING_COLUMN_VALUE, valueObj);
389     DataShare::DataSharePredicates predicates;
390     predicates.EqualTo(SETTING_COLUMN_KEYWORD, key);
391     Uri uri(AssembleUri(key, tableType, userId));
392     if (helper->Update(uri, predicates, bucket) <= 0) {
393         AUDIO_INFO_LOG("audio_info_database no data exist, insert one row");
394         helper->Insert(uri, bucket);
395     }
396     if (needNotify) {
397         helper->NotifyChange(AssembleUri(key, tableType, userId));
398     }
399     ReleaseDataShareHelper(helper);
400     IPCSkeleton::SetCallingIdentity(callingIdentity);
401     return ERR_OK;
402 }
403 
GetCurrentUserId(int32_t specificUserId)404 int32_t AudioSettingProvider::GetCurrentUserId(int32_t specificUserId)
405 {
406     if (specificUserId != INVALID_ACCOUNT_ID && specificUserId >= MIN_USER_ACCOUNT) {
407         AUDIO_INFO_LOG("just use specific id: %{public}d", specificUserId);
408         return specificUserId;
409     }
410     std::vector<int> ids;
411     int32_t currentuserId = -1;
412     ErrCode result;
413     int32_t retry = RETRY_TIMES;
414     while (retry--) {
415         result = AccountSA::OsAccountManager::QueryActiveOsAccountIds(ids);
416         if (result == ERR_OK && !ids.empty()) {
417             currentuserId = ids[0];
418             AUDIO_DEBUG_LOG("current userId is :%{public}d", currentuserId);
419             break;
420         }
421         // sleep and wait for 1 second
422         sleep(SLEEP_TIME);
423     }
424     if (result != ERR_OK || ids.empty()) {
425         AUDIO_WARNING_LOG("current userId is empty");
426     }
427     return currentuserId;
428 }
429 
CheckOsAccountReady()430 bool AudioSettingProvider::CheckOsAccountReady()
431 {
432     std::vector<int> ids;
433     ErrCode result = AccountSA::OsAccountManager::QueryActiveOsAccountIds(ids);
434     return (result == ERR_OK && !ids.empty());
435 }
436 
SetDataShareReady(std::atomic<bool> isDataShareReady)437 void AudioSettingProvider::SetDataShareReady(std::atomic<bool> isDataShareReady)
438 {
439     AUDIO_INFO_LOG("Receive event DATA_SHARE_READY");
440     isDataShareReady_.store(isDataShareReady);
441 }
442 
CreateDataShareHelper(std::string tableType,int32_t userId)443 std::shared_ptr<DataShare::DataShareHelper> AudioSettingProvider::CreateDataShareHelper(
444     std::string tableType, int32_t userId)
445 {
446     CHECK_AND_RETURN_RET_LOG(isDataShareReady_.load(), nullptr,
447         "DATA_SHARE_READY not received, create DataShareHelper failed");
448     {
449         std::lock_guard<std::mutex> lock(mutex_);
450         if (remoteObj_ == nullptr) {
451             AUDIO_WARNING_LOG("remoteObj_ is nullptr");
452             Initialize(AUDIO_POLICY_SERVICE_ID);
453         }
454     }
455 #ifdef SUPPORT_USER_ACCOUNT
456     int32_t currentuserId = GetCurrentUserId(userId);
457     if (currentuserId < MIN_USER_ACCOUNT) {
458         currentuserId = MIN_USER_ACCOUNT;
459     }
460 #else
461     int32_t currentuserId = -1;
462 #endif
463     std::shared_ptr<DataShare::DataShareHelper> helper = nullptr;
464     std::string SettingSystemUrlProxy = "";
465     // deal with multi useraccount table
466     if (currentuserId > 0 && tableType == "system") {
467         SettingSystemUrlProxy =
468             SETTING_USER_URI_PROXY + std::to_string(currentuserId) + "?Proxy=true";
469         helper = DataShare::DataShareHelper::Creator(remoteObj_, SettingSystemUrlProxy, SETTINGS_DATA_EXT_URI);
470     } else if (currentuserId > 0 && tableType == "secure") {
471         SettingSystemUrlProxy =
472             SETTING_USER_SECURE_URI_PROXY + std::to_string(currentuserId) + "?Proxy=true";
473         WatchTimeout guard("DataShare::DataShareHelper::Creator:CreateDataShareHelper.SettingSystemUrlProxy");
474         helper = DataShare::DataShareHelper::Creator(remoteObj_, SettingSystemUrlProxy, SETTINGS_DATA_EXT_URI);
475         guard.CheckCurrTimeout();
476     } else {
477         WatchTimeout guard("DataShare::DataShareHelper::Creator:CreateDataShareHelper.SETTING_URI_PROXY");
478         helper = DataShare::DataShareHelper::Creator(remoteObj_, SETTING_URI_PROXY, SETTINGS_DATA_EXT_URI);
479         guard.CheckCurrTimeout();
480     }
481     if (helper == nullptr) {
482         AUDIO_WARNING_LOG("helper is nullptr, uri=%{public}s", SettingSystemUrlProxy.c_str());
483         return nullptr;
484     }
485     return helper;
486 }
487 
ReleaseDataShareHelper(std::shared_ptr<DataShare::DataShareHelper> & helper)488 bool AudioSettingProvider::ReleaseDataShareHelper(
489     std::shared_ptr<DataShare::DataShareHelper> &helper)
490 {
491     if (!helper->Release()) {
492         AUDIO_WARNING_LOG("release helper fail");
493         return false;
494     }
495     return true;
496 }
497 
AssembleUri(const std::string & key,std::string tableType,int32_t userId)498 Uri AudioSettingProvider::AssembleUri(const std::string &key, std::string tableType, int32_t userId)
499 {
500 #ifdef SUPPORT_USER_ACCOUNT
501     int32_t currentuserId = GetCurrentUserId(userId);
502     if (currentuserId < MIN_USER_ACCOUNT) {
503         currentuserId = MIN_USER_ACCOUNT;
504     }
505 #else
506     int32_t currentuserId = -1;
507 #endif
508     std::string SettingSystemUrlProxy = "";
509 
510     // deal with multi useraccount table
511     if (currentuserId > 0 && tableType == "system") {
512         SettingSystemUrlProxy = SETTING_USER_URI_PROXY + std::to_string(currentuserId) + "?Proxy=true";
513         Uri uri(SettingSystemUrlProxy + "&key=" + key);
514         return uri;
515     } else if (currentuserId > 0 && tableType == "secure") {
516         SettingSystemUrlProxy = SETTING_USER_SECURE_URI_PROXY + std::to_string(currentuserId) + "?Proxy=true";
517         Uri uri(SettingSystemUrlProxy + "&key=" + key);
518         return uri;
519     }
520     Uri uri(SETTING_URI_PROXY + "&key=" + key);
521     return uri;
522 }
523 } // namespace AudioStandard
524 } // namespace OHOS
525