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 
16 #include "full_ime_info_manager.h"
17 
18 #include <algorithm>
19 
20 #include "common_timer_errors.h"
21 #include "ime_info_inquirer.h"
22 namespace OHOS {
23 namespace MiscServices {
24 constexpr uint32_t TIMER_TASK_INTERNAL = 3600000; // updated hourly
~FullImeInfoManager()25 FullImeInfoManager::~FullImeInfoManager()
26 {
27     timer_.Unregister(timerId_);
28     timer_.Shutdown();
29     fullImeInfos_.clear();
30 }
31 
FullImeInfoManager()32 FullImeInfoManager::FullImeInfoManager()
33 {
34     uint32_t ret = timer_.Setup();
35     if (ret != Utils::TIMER_ERR_OK) {
36         IMSA_HILOGE("failed to create timer");
37         return;
38     }
39     timerId_ = timer_.Register([this]() { Init(); }, TIMER_TASK_INTERNAL, false);
40 }
41 
GetInstance()42 FullImeInfoManager &FullImeInfoManager::GetInstance()
43 {
44     static FullImeInfoManager instance;
45     return instance;
46 }
47 
Init()48 int32_t FullImeInfoManager::Init()
49 {
50     std::vector<std::pair<int32_t, std::vector<FullImeInfo>>> fullImeInfos;
51     auto ret = ImeInfoInquirer::GetInstance().QueryFullImeInfo(fullImeInfos);
52     if (ret != ErrorCode::NO_ERROR) {
53         IMSA_HILOGW("failed to QueryFullImeInfo, ret:%{public}d", ret);
54         return ret;
55     }
56     std::lock_guard<std::mutex> lock(lock_);
57     fullImeInfos_.clear();
58     for (const auto &infos : fullImeInfos) {
59         fullImeInfos_.insert_or_assign(infos.first, infos.second);
60     }
61     return ErrorCode::NO_ERROR;
62 }
63 
Add(int32_t userId)64 int32_t FullImeInfoManager::Add(int32_t userId)
65 {
66     {
67         std::lock_guard<std::mutex> lock(lock_);
68         auto it = fullImeInfos_.find(userId);
69         if (it != fullImeInfos_.end()) {
70             return ErrorCode::NO_ERROR;
71         }
72     }
73     std::vector<FullImeInfo> infos;
74     auto ret = ImeInfoInquirer::GetInstance().QueryFullImeInfo(userId, infos);
75     if (ret != ErrorCode::NO_ERROR) {
76         IMSA_HILOGE("failed to QueryFullImeInfo, userId:%{public}d, ret:%{public}d", userId, ret);
77         return ret;
78     }
79     std::lock_guard<std::mutex> lock(lock_);
80     fullImeInfos_.insert_or_assign(userId, infos);
81     return ErrorCode::NO_ERROR;
82 }
83 
Update()84 int32_t FullImeInfoManager::Update()
85 {
86     auto ret = Init();
87     if (ret != ErrorCode::NO_ERROR) {
88         std::lock_guard<std::mutex> lock(lock_);
89         fullImeInfos_.clear();
90     }
91     return ErrorCode::NO_ERROR;
92 }
93 
Delete(int32_t userId)94 int32_t FullImeInfoManager::Delete(int32_t userId)
95 {
96     std::lock_guard<std::mutex> lock(lock_);
97     fullImeInfos_.erase(userId);
98     return ErrorCode::NO_ERROR;
99 }
100 
Add(int32_t userId,const std::string & bundleName)101 int32_t FullImeInfoManager::Add(int32_t userId, const std::string &bundleName)
102 {
103     FullImeInfo info;
104     auto ret = ImeInfoInquirer::GetInstance().GetFullImeInfo(userId, bundleName, info);
105     if (ret != ErrorCode::NO_ERROR) {
106         IMSA_HILOGE("failed to GetFullImeInfo, userId:%{public}d, bundleName:%{public}s, ret:%{public}d", userId,
107             bundleName.c_str(), ret);
108         return ret;
109     }
110     std::lock_guard<std::mutex> lock(lock_);
111     auto it = fullImeInfos_.find(userId);
112     if (it == fullImeInfos_.end()) {
113         fullImeInfos_.insert({ userId, { info } });
114         return ErrorCode::NO_ERROR;
115     }
116     auto iter = std::find_if(it->second.begin(), it->second.end(),
117         [&bundleName](const FullImeInfo &info) { return bundleName == info.prop.name; });
118     if (iter != it->second.end()) {
119         return ErrorCode::NO_ERROR;
120     }
121     it->second.push_back(info);
122     return ErrorCode::NO_ERROR;
123 }
124 
Delete(int32_t userId,const std::string & bundleName)125 int32_t FullImeInfoManager::Delete(int32_t userId, const std::string &bundleName)
126 {
127     std::lock_guard<std::mutex> lock(lock_);
128     auto it = fullImeInfos_.find(userId);
129     if (it == fullImeInfos_.end()) {
130         return ErrorCode::NO_ERROR;
131     }
132     auto iter = std::find_if(it->second.begin(), it->second.end(),
133         [&bundleName](const FullImeInfo &info) { return bundleName == info.prop.name; });
134     if (iter == it->second.end()) {
135         return ErrorCode::NO_ERROR;
136     }
137     it->second.erase(iter);
138     if (it->second.empty()) {
139         fullImeInfos_.erase(it->first);
140     }
141     return ErrorCode::NO_ERROR;
142 }
143 
Update(int32_t userId,const std::string & bundleName)144 int32_t FullImeInfoManager::Update(int32_t userId, const std::string &bundleName)
145 {
146     FullImeInfo info;
147     auto ret = ImeInfoInquirer::GetInstance().GetFullImeInfo(userId, bundleName, info);
148     if (ret != ErrorCode::NO_ERROR) {
149         IMSA_HILOGE("failed to GetFullImeInfo failed, userId:%{public}d, bundleName:%{public}s, ret:%{public}d",
150             userId, bundleName.c_str(), ret);
151         return ErrorCode::ERROR_PACKAGE_MANAGER;
152     }
153     std::lock_guard<std::mutex> lock(lock_);
154     auto it = fullImeInfos_.find(userId);
155     if (it == fullImeInfos_.end()) {
156         fullImeInfos_.insert({ userId, { info } });
157         return ErrorCode::NO_ERROR;
158     }
159     auto iter = std::find_if(it->second.begin(), it->second.end(),
160         [&bundleName](const FullImeInfo &info) { return bundleName == info.prop.name; });
161     if (iter != it->second.end()) {
162         it->second.erase(iter);
163     }
164     it->second.push_back(info);
165     return ErrorCode::NO_ERROR;
166 }
167 
Get(int32_t userId)168 std::vector<FullImeInfo> FullImeInfoManager::Get(int32_t userId)
169 {
170     std::lock_guard<std::mutex> lock(lock_);
171     auto it = fullImeInfos_.find(userId);
172     if (it == fullImeInfos_.end()) {
173         return {};
174     }
175     return it->second;
176 }
177 
Get(const std::string & bundleName,int32_t userId,FullImeInfo & fullImeInfo)178 bool FullImeInfoManager::Get(const std::string &bundleName, int32_t userId, FullImeInfo &fullImeInfo)
179 {
180     std::lock_guard<std::mutex> lock(lock_);
181     auto it = fullImeInfos_.find(userId);
182     if (it == fullImeInfos_.end()) {
183         IMSA_HILOGD("user %{public}d info", userId);
184         return false;
185     }
186     auto iter = std::find_if(it->second.begin(), it->second.end(),
187         [&bundleName](const FullImeInfo &info) { return bundleName == info.prop.name; });
188     if (iter == it->second.end()) {
189         IMSA_HILOGD("ime: %{public}s not in cache", bundleName.c_str());
190         return false;
191     }
192     fullImeInfo = *iter;
193     return true;
194 }
195 
Has(int32_t userId,const std::string & bundleName)196 bool FullImeInfoManager::Has(int32_t userId, const std::string &bundleName)
197 {
198     std::lock_guard<std::mutex> lock(lock_);
199     auto it = fullImeInfos_.find(userId);
200     if (it == fullImeInfos_.end()) {
201         return false;
202     }
203     auto iter = std::find_if(it->second.begin(), it->second.end(),
204         [&bundleName](const FullImeInfo &info) { return bundleName == info.prop.name; });
205     return iter != it->second.end();
206 }
207 
Get(int32_t userId,uint32_t tokenId)208 std::string FullImeInfoManager::Get(int32_t userId, uint32_t tokenId)
209 {
210     std::lock_guard<std::mutex> lock(lock_);
211     auto it = fullImeInfos_.find(userId);
212     if (it == fullImeInfos_.end()) {
213         return "";
214     }
215     auto iter = std::find_if(
216         it->second.begin(), it->second.end(), [&tokenId](const FullImeInfo &info) { return tokenId == info.tokenId; });
217     if (iter == it->second.end()) {
218         return "";
219     }
220     return (*iter).prop.name;
221 }
222 } // namespace MiscServices
223 } // namespace OHOS