1 /*
2  * Copyright (c) 2023 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 #include <sstream>
16 #include "settings_data_utils.h"
17 
18 #include "ime_info_inquirer.h"
19 #include "iservice_registry.h"
20 #include "system_ability_definition.h"
21 
22 namespace OHOS {
23 namespace MiscServices {
24 std::mutex SettingsDataUtils::instanceMutex_;
25 sptr<SettingsDataUtils> SettingsDataUtils::instance_ = nullptr;
~SettingsDataUtils()26 SettingsDataUtils::~SettingsDataUtils()
27 {
28     remoteObj_ = nullptr;
29     if (!observerList_.empty()) {
30         for (auto &iter : observerList_) {
31             UnregisterObserver(iter);
32         }
33         observerList_.clear();
34     }
35 }
36 
GetInstance()37 sptr<SettingsDataUtils> SettingsDataUtils::GetInstance()
38 {
39     if (instance_ == nullptr) {
40         std::lock_guard<std::mutex> autoLock(instanceMutex_);
41         if (instance_ == nullptr) {
42             IMSA_HILOGI("GetInstance need new SettingsDataUtils.");
43             instance_ = new (std::nothrow) SettingsDataUtils();
44             if (instance_ == nullptr) {
45                 IMSA_HILOGE("instance is nullptr!");
46                 return instance_;
47             }
48         }
49     }
50     return instance_;
51 }
52 
CreateAndRegisterObserver(const std::string & key,SettingsDataObserver::CallbackFunc func)53 int32_t SettingsDataUtils::CreateAndRegisterObserver(const std::string &key, SettingsDataObserver::CallbackFunc func)
54 {
55     IMSA_HILOGD("key: %{public}s.", key.c_str());
56     sptr<SettingsDataObserver> observer = new (std::nothrow) SettingsDataObserver(key, func);
57     if (observer == nullptr) {
58         IMSA_HILOGE("observer is nullptr!");
59         return ErrorCode::ERROR_NULL_POINTER;
60     }
61     return RegisterObserver(observer);
62 }
63 
RegisterObserver(const sptr<SettingsDataObserver> & observer)64 int32_t SettingsDataUtils::RegisterObserver(const sptr<SettingsDataObserver> &observer)
65 {
66     if (observer == nullptr) {
67         IMSA_HILOGE("observer is nullptr!");
68         return ErrorCode::ERROR_NULL_POINTER;
69     }
70 
71     auto uri = GenerateTargetUri(SETTING_URI_PROXY, observer->GetKey());
72     auto helper = SettingsDataUtils::CreateDataShareHelper(SETTING_URI_PROXY);
73     if (helper == nullptr) {
74         IMSA_HILOGE("helper is nullptr!");
75         return ErrorCode::ERROR_NULL_POINTER;
76     }
77     helper->RegisterObserver(uri, observer);
78     ReleaseDataShareHelper(helper);
79     IMSA_HILOGD("succeed to register observer of uri: %{public}s.", uri.ToString().c_str());
80 
81     std::lock_guard<decltype(observerListMutex_)> lock(observerListMutex_);
82     observerList_.push_back(observer);
83     return ErrorCode::NO_ERROR;
84 }
85 
UnregisterObserver(const sptr<SettingsDataObserver> & observer)86 int32_t SettingsDataUtils::UnregisterObserver(const sptr<SettingsDataObserver> &observer)
87 {
88     auto uri = GenerateTargetUri(SETTING_URI_PROXY, observer->GetKey());
89     auto helper = SettingsDataUtils::CreateDataShareHelper(SETTING_URI_PROXY);
90     if (helper == nullptr) {
91         return ErrorCode::ERROR_ENABLE_IME;
92     }
93     helper->UnregisterObserver(uri, observer);
94     ReleaseDataShareHelper(helper);
95     IMSA_HILOGD("succeed to unregister observer of uri: %{public}s.", uri.ToString().c_str());
96     return ErrorCode::NO_ERROR;
97 }
98 
CreateDataShareHelper(const std::string & uriProxy)99 std::shared_ptr<DataShare::DataShareHelper> SettingsDataUtils::CreateDataShareHelper(const std::string &uriProxy)
100 {
101     auto remoteObj = GetToken();
102     if (remoteObj == nullptr) {
103         IMSA_HILOGE("remoteObk is nullptr!");
104         return nullptr;
105     }
106 
107     auto helper = DataShare::DataShareHelper::Creator(remoteObj_, uriProxy, SETTINGS_DATA_EXT_URI);
108     if (helper == nullptr) {
109         IMSA_HILOGE("create helper failed, uri: %{public}s!", uriProxy.c_str());
110         return nullptr;
111     }
112     return helper;
113 }
114 
ReleaseDataShareHelper(std::shared_ptr<DataShare::DataShareHelper> & helper)115 bool SettingsDataUtils::ReleaseDataShareHelper(std::shared_ptr<DataShare::DataShareHelper> &helper)
116 {
117     if (helper == nullptr) {
118         IMSA_HILOGW("helper is nullptr.");
119         return true;
120     }
121     if (!helper->Release()) {
122         IMSA_HILOGE("release data share helper failed.");
123         return false;
124     }
125     return true;
126 }
127 
GenerateTargetUri(const std::string & uriProxy,const std::string & key)128 Uri SettingsDataUtils::GenerateTargetUri(const std::string &uriProxy, const std::string &key)
129 {
130     Uri uri(std::string(uriProxy) + "&key=" + key);
131     return uri;
132 }
133 
SetStringValue(const std::string & uriProxy,const std::string & key,const std::string & value)134 bool SettingsDataUtils::SetStringValue(const std::string &uriProxy, const std::string &key, const std::string &value)
135 {
136     IMSA_HILOGD("start.");
137     auto helper = CreateDataShareHelper(uriProxy);
138     if (helper == nullptr) {
139         IMSA_HILOGE("helper is nullptr.");
140         return false;
141     }
142     DataShare::DataShareValueObject keyObj(key);
143     DataShare::DataShareValueObject valueObj(value);
144     DataShare::DataShareValuesBucket bucket;
145     bucket.Put(SETTING_COLUMN_KEYWORD, keyObj);
146     bucket.Put(SETTING_COLUMN_VALUE, valueObj);
147     DataShare::DataSharePredicates predicates;
148     predicates.EqualTo(SETTING_COLUMN_KEYWORD, key);
149     Uri uri(GenerateTargetUri(uriProxy, key));
150     if (helper->Update(uri, predicates, bucket) <= 0) {
151         int index = helper->Insert(uri, bucket);
152         IMSA_HILOGI("no data exists, insert ret index: %{public}d", index);
153     } else {
154         IMSA_HILOGI("data exits");
155     }
156     bool ret = ReleaseDataShareHelper(helper);
157     IMSA_HILOGI("ReleaseDataShareHelper isSuccess: %{public}d", ret);
158     return ret;
159 }
160 
GetStringValue(const std::string & uriProxy,const std::string & key,std::string & value)161 int32_t SettingsDataUtils::GetStringValue(const std::string &uriProxy, const std::string &key, std::string &value)
162 {
163     IMSA_HILOGD("start.");
164     auto helper = CreateDataShareHelper(uriProxy);
165     if (helper == nullptr) {
166         IMSA_HILOGE("helper is nullptr.");
167         return ErrorCode::ERROR_NULL_POINTER;
168     }
169     std::vector<std::string> columns = { SETTING_COLUMN_VALUE };
170     DataShare::DataSharePredicates predicates;
171     predicates.EqualTo(SETTING_COLUMN_KEYWORD, key);
172     Uri uri(GenerateTargetUri(uriProxy, key));
173     auto resultSet = helper->Query(uri, predicates, columns);
174     ReleaseDataShareHelper(helper);
175     if (resultSet == nullptr) {
176         IMSA_HILOGE("resultSet is nullptr.");
177         return ErrorCode::ERROR_NULL_POINTER;
178     }
179 
180     int32_t count = 0;
181     resultSet->GetRowCount(count);
182     if (count <= 0) {
183         IMSA_HILOGW("not found keyword, key: %{public}s, count: %{public}d.", key.c_str(), count);
184         resultSet->Close();
185         return ErrorCode::ERROR_KEYWORD_NOT_FOUND;
186     }
187 
188     int32_t columIndex = 0;
189     resultSet->GoToFirstRow();
190     resultSet->GetColumnIndex(SETTING_COLUMN_VALUE, columIndex);
191     int32_t ret = resultSet->GetString(columIndex, value);
192     if (ret != DataShare::E_OK) {
193         IMSA_HILOGE("failed to GetString, ret: %{public}d!", ret);
194     }
195     resultSet->Close();
196     return ret;
197 }
198 
GetToken()199 sptr<IRemoteObject> SettingsDataUtils::GetToken()
200 {
201     std::lock_guard<std::mutex> autoLock(tokenMutex_);
202     if (remoteObj_ != nullptr) {
203         return remoteObj_;
204     }
205     auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
206     if (samgr == nullptr) {
207         IMSA_HILOGE("system ability manager is nullptr!");
208         return nullptr;
209     }
210     auto remoteObj = samgr->GetSystemAbility(INPUT_METHOD_SYSTEM_ABILITY_ID);
211     if (remoteObj == nullptr) {
212         IMSA_HILOGE("system ability is nullptr!");
213         return nullptr;
214     }
215     remoteObj_ = remoteObj;
216     return remoteObj_;
217 }
218 
EnableIme(int32_t userId,const std::string & bundleName)219 bool SettingsDataUtils::EnableIme(int32_t userId, const std::string &bundleName)
220 {
221     const int32_t mainUserId = 100;
222     if (userId != mainUserId) {
223         IMSA_HILOGE("user is not main.");
224         return false;
225     }
226     const char *SETTING_COLUMN_KEYWORD = "KEYWORD";
227     const char *SETTING_COLUMN_VALUE = "VALUE";
228     const char *settingKey = "settings.inputmethod.enable_ime";
229     std::string settingValue = "";
230     GetStringValue(SETTING_URI_PROXY, settingKey, settingValue);
231     IMSA_HILOGI("settingValue: %{public}s", settingValue.c_str());
232     std::string value = "";
233     if (settingValue == "") {
234         value = "{\"enableImeList\" : {\"100\" : [\"" + bundleName + "\"]}}";
235     } else {
236         value = SetSettingValues(settingValue, bundleName);
237     }
238     IMSA_HILOGI("value: %{public}s", value.c_str());
239     auto helper = CreateDataShareHelper(SETTING_URI_PROXY);
240     if (helper == nullptr) {
241         IMSA_HILOGE("helper is nullptr.");
242         return false;
243     }
244     DataShare::DataShareValueObject keyObj(settingKey);
245     DataShare::DataShareValueObject valueObj(value);
246     DataShare::DataShareValuesBucket bucket;
247     bucket.Put(SETTING_COLUMN_KEYWORD, keyObj);
248     bucket.Put(SETTING_COLUMN_VALUE, valueObj);
249     DataShare::DataSharePredicates predicates;
250     predicates.EqualTo(SETTING_COLUMN_KEYWORD, settingKey);
251     Uri uri(GenerateTargetUri(SETTING_URI_PROXY, settingKey));
252     if (helper->Update(uri, predicates, bucket) <= 0) {
253         int index = helper->Insert(uri, bucket);
254         IMSA_HILOGI("no data exists, insert ret index: %{public}d", index);
255     } else {
256         IMSA_HILOGI("data exits");
257     }
258     bool ret = ReleaseDataShareHelper(helper);
259     IMSA_HILOGI("ReleaseDataShareHelper isSuccess: %{public}d", ret);
260     return ret;
261 }
262 
split(const std::string & text,char delim)263 std::vector<std::string> SettingsDataUtils::split(const std::string &text, char delim)
264 {
265     std::vector<std::string> tokens;
266     std::stringstream ss(text);
267     std::string item;
268     while (std::getline(ss, item, delim)) {
269         if (!item.empty()) {
270             tokens.push_back(item);
271         }
272     }
273     return tokens;
274 }
275 
SetSettingValues(const std::string & settingValue,const std::string & bundleName)276 std::string SettingsDataUtils::SetSettingValues(const std::string &settingValue, const std::string &bundleName)
277 {
278     std::string value = "";
279     std::vector<std::string> settingValues = split(settingValue, ']');
280     for (uint32_t i = 0; i < settingValues.size(); ++i) {
281         if (i == 0) {
282             if (settingValues[0].back() == '[') {
283                 value += settingValues[i] + "\"" + bundleName + "\"" + "]";
284             } else {
285                 value += settingValues[i] + ",\"" + bundleName + "\"" + "]";
286             }
287         } else {
288             value += settingValues[i];
289         }
290     }
291     return value;
292 }
293 } // namespace MiscServices
294 } // namespace OHOS