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