• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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