1 /*
2 * Copyright (c) 2025 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
16 #include "numkey_apps_manager.h"
17
18 #include "global.h"
19 #include "ime_info_inquirer.h"
20
21 namespace OHOS {
22 namespace MiscServices {
23 #define CHECK_FEATURE_DISABLED_RETURN(retVal) \
24 do { \
25 if (!isFeatureEnabled_) { \
26 IMSA_HILOGD("feature not enabled"); \
27 return retVal; \
28 } \
29 } while (0)
30
GetInstance()31 NumkeyAppsManager &NumkeyAppsManager::GetInstance()
32 {
33 static NumkeyAppsManager numkeyAppsManager;
34 return numkeyAppsManager;
35 }
36 // LCOV_EXCL_START
~NumkeyAppsManager()37 NumkeyAppsManager::~NumkeyAppsManager()
38 {
39 if (observers_.empty()) {
40 return;
41 }
42 std::map<int32_t, sptr<SettingsDataObserver>> observers;
43 {
44 std::lock_guard<std::mutex> lock(observersLock_);
45 observers = observers_;
46 observers_.clear();
47 }
48 for (auto &observer : observers) {
49 SettingsDataUtils::GetInstance().UnregisterObserver(observer.second);
50 }
51 }
52
Init(int32_t userId)53 int32_t NumkeyAppsManager::Init(int32_t userId)
54 {
55 IMSA_HILOGI("start, userId: %{public}d", userId);
56 isFeatureEnabled_ = ImeInfoInquirer::GetInstance().IsEnableNumKey();
57 {
58 std::lock_guard<std::mutex> lock(appDeviceTypeLock_);
59 disableNumKeyAppDeviceTypes_ = ImeInfoInquirer::GetInstance().GetDisableNumKeyAppDeviceTypes();
60 }
61 CHECK_FEATURE_DISABLED_RETURN(ErrorCode::NO_ERROR);
62
63 int32_t ret = InitWhiteList();
64 IMSA_HILOGI("InitWhiteList ret: %{public}d", ret);
65
66 ret = RegisterUserBlockListData(userId);
67 IMSA_HILOGI("RegisterUserBlockListData ret: %{public}d", ret);
68
69 ret = UpdateUserBlockList(userId);
70 IMSA_HILOGI("UpdateUserBlockList ret: %{public}d", ret);
71 return ret;
72 }
73
NeedAutoNumKeyInput(int32_t userId,const std::string & bundleName)74 bool NumkeyAppsManager::NeedAutoNumKeyInput(int32_t userId, const std::string &bundleName)
75 {
76 CHECK_FEATURE_DISABLED_RETURN(false);
77 if (IsInNumkeyBlockList(userId, bundleName)) {
78 return false;
79 }
80 if (IsInNumKeyWhiteList(bundleName)) {
81 return true;
82 }
83 {
84 std::lock_guard<std::mutex> lock(appDeviceTypeLock_);
85 if (disableNumKeyAppDeviceTypes_.empty()) {
86 IMSA_HILOGE("disableNumKeyAppDeviceTypes empty.");
87 return false;
88 }
89 }
90 std::string compatibleDeviceType;
91 bool ret = ImeInfoInquirer::GetInstance().GetCompatibleDeviceType(bundleName, compatibleDeviceType);
92 if (!ret || compatibleDeviceType.empty()) {
93 IMSA_HILOGE("getCompatibleDeviceType failed.");
94 return false;
95 }
96 std::transform(compatibleDeviceType.begin(), compatibleDeviceType.end(), compatibleDeviceType.begin(),
97 [](char c) { return static_cast<char>(std::tolower(static_cast<unsigned char>(c))); });
98 {
99 std::lock_guard<std::mutex> lock(appDeviceTypeLock_);
100 if (disableNumKeyAppDeviceTypes_.find(compatibleDeviceType) != disableNumKeyAppDeviceTypes_.end()) {
101 IMSA_HILOGE("bundleName: %{public}s, compatibleDeviceType not supported.", bundleName.c_str());
102 return false;
103 }
104 }
105 IMSA_HILOGD("bundleName: %{public}s, support auto numkey input.", bundleName.c_str());
106 return true;
107 }
108
OnUserSwitched(int32_t userId)109 int32_t NumkeyAppsManager::OnUserSwitched(int32_t userId)
110 {
111 CHECK_FEATURE_DISABLED_RETURN(ErrorCode::NO_ERROR);
112 IMSA_HILOGI("userId %{public}d", userId);
113 RegisterUserBlockListData(userId);
114 int32_t ret = UpdateUserBlockList(userId);
115 if (ret != ErrorCode::NO_ERROR) {
116 IMSA_HILOGE("UpdateUserBlockList failed, ret: %{public}d", ret);
117 return ret;
118 }
119 return ErrorCode::NO_ERROR;
120 }
121
OnUserRemoved(int32_t userId)122 int32_t NumkeyAppsManager::OnUserRemoved(int32_t userId)
123 {
124 CHECK_FEATURE_DISABLED_RETURN(ErrorCode::NO_ERROR);
125 IMSA_HILOGI("userId %{public}d", userId);
126 sptr<SettingsDataObserver> observer = nullptr;
127 {
128 std::lock_guard<std::mutex> lock(observersLock_);
129 auto iter = observers_.find(userId);
130 if (iter == observers_.end()) {
131 IMSA_HILOGD("observer not found");
132 return ErrorCode::NO_ERROR;
133 }
134 observer = iter->second;
135 }
136 int32_t ret = SettingsDataUtils::GetInstance().UnregisterObserver(observer);
137 {
138 std::lock_guard<std::mutex> lock(observersLock_);
139 observers_.erase(userId);
140 }
141 return ret;
142 }
143
InitWhiteList()144 int32_t NumkeyAppsManager::InitWhiteList()
145 {
146 if (isListInited_.load()) {
147 return ErrorCode::NO_ERROR;
148 }
149 std::unordered_set<std::string> whiteList;
150 int32_t ret = ParseWhiteList(whiteList);
151 if (ret != ErrorCode::NO_ERROR) {
152 IMSA_HILOGI("ParseWhiteList failed, ret: %{public}d", ret);
153 return ret;
154 }
155 std::lock_guard<std::mutex> lock(appListLock_);
156 numKeyAppList_ = whiteList;
157 IMSA_HILOGI("success, list size: %{public}zu", numKeyAppList_.size());
158 return ErrorCode::NO_ERROR;
159 }
160
UpdateUserBlockList(int32_t userId)161 int32_t NumkeyAppsManager::UpdateUserBlockList(int32_t userId)
162 {
163 std::unordered_set<std::string> blockList;
164 int32_t ret = ParseBlockList(userId, blockList);
165 if (ret != ErrorCode::NO_ERROR) {
166 IMSA_HILOGE("ParseBlockList failed, ret: %{public}d", ret);
167 return ret;
168 }
169 std::lock_guard<std::mutex> lock(blockListLock_);
170 usersBlockList_.insert_or_assign(userId, blockList);
171 IMSA_HILOGI("success, list size: %{public}zu", blockList.size());
172 return ErrorCode::NO_ERROR;
173 }
174
ParseWhiteList(std::unordered_set<std::string> & list)175 int32_t NumkeyAppsManager::ParseWhiteList(std::unordered_set<std::string> &list)
176 {
177 std::string valueStr;
178 int32_t ret = SettingsDataUtils::GetInstance().GetStringValue(SETTING_URI_PROXY, COMPATIBLE_APP_STRATEGY, valueStr);
179 if (ret != ErrorCode::NO_ERROR && ret != ErrorCode::ERROR_KEYWORD_NOT_FOUND) {
180 IMSA_HILOGE("failed to get white list from settings data, ret: %{public}d", ret);
181 return ret;
182 }
183 if (ret == ErrorCode::ERROR_KEYWORD_NOT_FOUND) {
184 IMSA_HILOGD("key not found");
185 return ErrorCode::NO_ERROR;
186 }
187 NumkeyAppListCfg whiteListCfg;
188 if (!whiteListCfg.Unmarshall(valueStr)) {
189 IMSA_HILOGE("unmarshall failed");
190 return ErrorCode::ERROR_PARSE_CONFIG_FILE;
191 }
192 for (const auto &app : whiteListCfg.numkeyApps) {
193 list.insert(app.name);
194 }
195 return ErrorCode::NO_ERROR;
196 }
197
ParseBlockList(int32_t userId,std::unordered_set<std::string> & list)198 int32_t NumkeyAppsManager::ParseBlockList(int32_t userId, std::unordered_set<std::string> &list)
199 {
200 std::string valueStr;
201 int32_t ret = SettingsDataUtils::GetInstance().GetStringValue(
202 SETTINGS_USER_DATA_URI + std::to_string(userId) + "?Proxy=true", COMPATIBLE_SETTING_STRATEGY, valueStr);
203 if (ret != ErrorCode::NO_ERROR && ret != ErrorCode::ERROR_KEYWORD_NOT_FOUND) {
204 IMSA_HILOGE("failed to get white list from settings data, ret: %{public}d", ret);
205 return ret;
206 }
207 if (ret == ErrorCode::ERROR_KEYWORD_NOT_FOUND) {
208 IMSA_HILOGD("key not found");
209 return ErrorCode::NO_ERROR;
210 }
211 UserBlockListCfg blockListCfg;
212 if (!blockListCfg.Unmarshall(valueStr)) {
213 IMSA_HILOGE("unmarshall failed");
214 return ErrorCode::ERROR_PARSE_CONFIG_FILE;
215 }
216 for (const auto &app : blockListCfg.blockApps) {
217 list.insert(app);
218 }
219 return ErrorCode::NO_ERROR;
220 }
221
RegisterUserBlockListData(int32_t userId)222 int32_t NumkeyAppsManager::RegisterUserBlockListData(int32_t userId)
223 {
224 {
225 std::lock_guard<std::mutex> lock(observersLock_);
226 auto iter = observers_.find(userId);
227 if (iter != observers_.end() && iter->second != nullptr) {
228 IMSA_HILOGI("already registered, userId: %{public}d", userId);
229 return ErrorCode::NO_ERROR;
230 }
231 }
232 auto func = [this, userId]() {
233 IMSA_HILOGI("on block list change, userId: %{public}d", userId);
234 UpdateUserBlockList(userId);
235 };
236 std::string uriProxy = SETTINGS_USER_DATA_URI + std::to_string(userId) + "?Proxy=true";
237 sptr<SettingsDataObserver> observer = nullptr;
238 int32_t ret =
239 SettingsDataUtils::GetInstance().RegisterObserver(uriProxy, COMPATIBLE_SETTING_STRATEGY, func, observer);
240 if (ret != ErrorCode::NO_ERROR || observer == nullptr) {
241 IMSA_HILOGE("RegisterObserver failed or observer nullptr, ret: %{public}d", ret);
242 return ret;
243 }
244 IMSA_HILOGI("end, userId: %{public}d ", userId);
245 std::lock_guard<std::mutex> lock(observersLock_);
246 observers_.insert_or_assign(userId, observer);
247 return ErrorCode::NO_ERROR;
248 }
249
IsInNumKeyWhiteList(const std::string & bundleName)250 bool NumkeyAppsManager::IsInNumKeyWhiteList(const std::string &bundleName)
251 {
252 std::lock_guard<std::mutex> lock(appListLock_);
253 if (numKeyAppList_.find(bundleName) == numKeyAppList_.end()) {
254 return false;
255 }
256 IMSA_HILOGD("%{public}s in white list.", bundleName.c_str());
257 return true;
258 }
259
IsInNumkeyBlockList(int32_t userId,const std::string & bundleName)260 bool NumkeyAppsManager::IsInNumkeyBlockList(int32_t userId, const std::string &bundleName)
261 {
262 std::lock_guard<std::mutex> lock(blockListLock_);
263 auto iter = usersBlockList_.find(userId);
264 if (iter == usersBlockList_.end()) {
265 IMSA_HILOGD("user %{public}d block list is empty.", userId);
266 return false;
267 }
268 auto blockList = iter->second;
269 if (blockList.find(bundleName) == blockList.end()) {
270 return false;
271 }
272 IMSA_HILOGD("%{public}s in block list.", bundleName.c_str());
273 return true;
274 }
275 // LCOV_EXCL_STOP
276 } // namespace MiscServices
277 } // namespace OHOS