• 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 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