1 /*
2 * Copyright (c) 2021-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 "notification_clone_manager.h"
17
18 #include <fcntl.h>
19 #include <unistd.h>
20 #include <fstream>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <sys/sendfile.h>
24
25 #include "ans_log_wrapper.h"
26 #include "nlohmann/json.hpp"
27 #include "notification_clone_disturb_service.h"
28 #include "notification_clone_bundle_service.h"
29 #include "notification_clone_util.h"
30 #include "dh_notification_clone_bundle_service.h"
31 #include "common_event_manager.h"
32 #include "notification_analytics_util.h"
33
34 namespace OHOS {
35 namespace Notification {
36
37 const int ANS_CLONE_ERROR = -1;
38 const int32_t DEFAULT_APP_INDEX = -1;
39 constexpr int32_t DEFAULT_ANCO_APP_INDEX = 0;
40 constexpr uint64_t NOTIFICATION_FDSAN_TAG = 0xD001203;
41 constexpr uint64_t COMMON_FDSAN_TAG = 0;
42 constexpr const char *CLONE_ITEM_BUNDLE_INFO = "notificationBundle";
43 constexpr const char *DH_CLONE_ITEM_BUNDLE_INFO = "dhNotificationBundle";
44 constexpr const char *CLONE_ITEM_DISTURB = "notificationDisturb";
45 constexpr const char *BACKUP_CONFIG_FILE_PATH = "/data/service/el1/public/notification/backup_config.conf";
46
create()47 std::shared_ptr<AncoRestoreStartEventSubscriber> AncoRestoreStartEventSubscriber::create()
48 {
49 ANS_LOGD("start");
50 EventFwk::MatchingSkills matchingSkills;
51 matchingSkills.AddEvent(AncoRestoreStartEventSubscriber::EVENT_NAME);
52 EventFwk::CommonEventSubscribeInfo subscriberInfo(matchingSkills);
53 subscriberInfo.SetPermission(AncoRestoreStartEventSubscriber::EVENT_PUBLISHER_PERMISSION);
54 return std::make_shared<AncoRestoreStartEventSubscriber>(subscriberInfo);
55 ANS_LOGD("end");
56 }
57
AncoRestoreStartEventSubscriber(const EventFwk::CommonEventSubscribeInfo & subscribeInfo)58 AncoRestoreStartEventSubscriber::AncoRestoreStartEventSubscriber(
59 const EventFwk::CommonEventSubscribeInfo &subscribeInfo)
60 : EventFwk::CommonEventSubscriber(subscribeInfo)
61 {
62 }
63
~AncoRestoreStartEventSubscriber()64 AncoRestoreStartEventSubscriber::~AncoRestoreStartEventSubscriber()
65 {
66 ANS_LOGD("called");
67 }
68
OnReceiveEvent(const EventFwk::CommonEventData & data)69 void AncoRestoreStartEventSubscriber::OnReceiveEvent(const EventFwk::CommonEventData& data)
70 {
71 HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_22, EventBranchId::BRANCH_4);
72 std::string bundleName = data.GetWant().GetStringParam("bundleName");
73 int32_t uid = data.GetWant().GetIntParam("uid", 0);
74 ANS_LOGI("AncoRestoreStartEventSubscriber Get Data %{public}s %{public}d",
75 bundleName.c_str(), uid);
76 if (uid <= 0) {
77 message.Message("dh restoreStart uid error" + bundleName);
78 NotificationAnalyticsUtil::ReportModifyEvent(message);
79 ANS_LOGE("AncoRestoreStartEventSubscriber uid error");
80 return;
81 }
82 NotificationCloneManager::GetInstance().OnDhRestoreStart(bundleName, uid);
83 }
84
GetInstance()85 NotificationCloneManager& NotificationCloneManager::GetInstance()
86 {
87 static NotificationCloneManager notificationCloneManager;
88 return notificationCloneManager;
89 }
90
SetBackUpReply()91 static std::string SetBackUpReply()
92 {
93 nlohmann::json reply;
94 nlohmann::json resultInfo = nlohmann::json::array();
95 nlohmann::json errorInfo;
96
97 errorInfo["type"] = "ErrorInfo";
98 errorInfo["errorCode"] = std::to_string(ERR_OK);
99 errorInfo["errorInfo"] = "";
100
101 resultInfo.emplace_back(errorInfo);
102 reply["resultInfo"] = resultInfo;
103
104 return reply.dump();
105 }
106
OnBackup(MessageParcel & data,MessageParcel & reply)107 int32_t NotificationCloneManager::OnBackup(MessageParcel& data, MessageParcel& reply)
108 {
109 ANS_LOGD("called");
110 HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_22, EventBranchId::BRANCH_1);
111 if (cloneTemplates.empty()) {
112 ANS_LOGI("Notification no need Backup.");
113 return ERR_OK;
114 }
115
116 nlohmann::json jsonObject;
117 for (auto iter = cloneTemplates.begin(); iter != cloneTemplates.end(); ++iter) {
118 nlohmann::json jsonItem;
119 auto cloneTemplate = iter->second;
120 if (cloneTemplate == nullptr) {
121 ANS_LOGW("null cloneTemplate %{public}s", iter->first.c_str());
122 continue;
123 }
124 if (iter->second->OnBackup(jsonItem) != ERR_OK) {
125 ANS_LOGW("Notification OnBackup %{public}s failed.", iter->first.c_str());
126 continue;
127 }
128 jsonObject[iter->first] = jsonItem;
129 }
130
131 if (SaveConfig(jsonObject.dump()) != ERR_OK) {
132 message.Message("SaveConfig failed.");
133 NotificationAnalyticsUtil::ReportModifyEvent(message);
134 return ANS_CLONE_ERROR;
135 }
136
137 FILE *fdfile = fopen(BACKUP_CONFIG_FILE_PATH, "r");
138 if (fdfile == nullptr) {
139 ANS_LOGE("null fdfile");
140 message.Message("Notification open file failed.");
141 NotificationAnalyticsUtil::ReportModifyEvent(message);
142 return ANS_CLONE_ERROR;
143 }
144 auto fd = fileno(fdfile);
145 if (reply.WriteFileDescriptor(fd) == false) {
146 (void)fclose(fdfile);
147 ANS_LOGE("Notification write file descriptor failed!");
148 message.Message("Notification write file descriptor failed!");
149 NotificationAnalyticsUtil::ReportModifyEvent(message);
150 return ANS_CLONE_ERROR;
151 }
152
153 ANS_LOGI("Notification OnBackup end fd: %{public}d.", fd);
154 (void)fclose(fdfile);
155 return ERR_OK;
156 }
157
OnRestore(MessageParcel & data,MessageParcel & reply)158 int32_t NotificationCloneManager::OnRestore(MessageParcel& data, MessageParcel& reply)
159 {
160 ANS_LOGD("start");
161 HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_22, EventBranchId::BRANCH_2);
162 reply.WriteString(SetBackUpReply());
163 std::string storeMessage;
164 UniqueFd fd(data.ReadFileDescriptor());
165 if (LoadConfig(fd, storeMessage) != ERR_OK) {
166 close(fd.Release());
167 RemoveBackUpFile();
168 message.Message("LoadConfig failed!");
169 NotificationAnalyticsUtil::ReportModifyEvent(message);
170 return ANS_CLONE_ERROR;
171 }
172
173 RemoveBackUpFile();
174 if (storeMessage.empty() || !nlohmann::json::accept(storeMessage)) {
175 ANS_LOGE("Invalid JSON");
176 message.Message("Invalid JSON");
177 NotificationAnalyticsUtil::ReportModifyEvent(message);
178 return ANS_CLONE_ERROR;
179 }
180 nlohmann::json jsonObject = nlohmann::json::parse(storeMessage, nullptr, false);
181 if (jsonObject.is_null() || !jsonObject.is_object()) {
182 ANS_LOGE("Invalid JSON object");
183 message.Message("Invalid JSON object");
184 NotificationAnalyticsUtil::ReportModifyEvent(message);
185 return ANS_CLONE_ERROR;
186 }
187 for (auto iter = cloneTemplates.begin(); iter != cloneTemplates.end(); ++iter) {
188 if (jsonObject.contains(iter->first) && iter->second != nullptr) {
189 iter->second->OnRestore(jsonObject.at(iter->first));
190 }
191 }
192 ANS_LOGD("end");
193 return ERR_OK;
194 }
195
NotificationCloneManager()196 NotificationCloneManager::NotificationCloneManager()
197 {
198 ANS_LOGD("start");
199 // not change push sequence, ensure [clone item] before [dh clone item]
200 cloneTemplates.push_back(std::make_pair(CLONE_ITEM_BUNDLE_INFO, NotificationCloneBundle::GetInstance()));
201 cloneTemplates.push_back(std::make_pair(DH_CLONE_ITEM_BUNDLE_INFO, DhNotificationCloneBundle::GetInstance()));
202 cloneTemplates.push_back(std::make_pair(CLONE_ITEM_DISTURB, NotificationCloneDisturb::GetInstance()));
203
204 restoreStartEventSubscriber_ = AncoRestoreStartEventSubscriber::create();
205 if (!EventFwk::CommonEventManager::SubscribeCommonEvent(restoreStartEventSubscriber_)) {
206 ANS_LOGE("Subscribe AncoRestoreStartEventSubscriber Failed.");
207 restoreStartEventSubscriber_ = nullptr;
208 }
209 ANS_LOGD("end");
210 }
211
~NotificationCloneManager()212 NotificationCloneManager::~NotificationCloneManager()
213 {
214 ANS_LOGD("called");
215 }
216
LoadConfig(UniqueFd & fd,std::string & config)217 ErrCode NotificationCloneManager::LoadConfig(UniqueFd &fd, std::string& config)
218 {
219 ANS_LOGD("called");
220 struct stat statBuf;
221 if (fstat(fd.Get(), &statBuf) < 0) {
222 ANS_LOGE("LoadConfig fstat fd fail %{public}d.", fd.Get());
223 return ANS_CLONE_ERROR;
224 }
225 int destFd = open(BACKUP_CONFIG_FILE_PATH, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
226 if (destFd < 0) {
227 ANS_LOGE("LoadConfig open file fail.");
228 return ANS_CLONE_ERROR;
229 }
230 fdsan_exchange_owner_tag(destFd, COMMON_FDSAN_TAG, NOTIFICATION_FDSAN_TAG);
231 if (sendfile(destFd, fd.Get(), nullptr, statBuf.st_size) < 0) {
232 ANS_LOGE("LoadConfig fd sendfile(size: %{public}d) to destFd fail.", static_cast<int>(statBuf.st_size));
233 fdsan_close_with_tag(destFd, NOTIFICATION_FDSAN_TAG);
234 return ANS_CLONE_ERROR;
235 }
236 fdsan_close_with_tag(destFd, NOTIFICATION_FDSAN_TAG);
237 std::ifstream fs(BACKUP_CONFIG_FILE_PATH);
238 if (!fs.is_open()) {
239 ANS_LOGE("Loading config file is_open() failed!");
240 return ANS_CLONE_ERROR;
241 }
242 config.clear();
243 std::string line;
244 while (std::getline(fs, line)) {
245 config.append(line);
246 }
247 fs.close();
248 return ERR_OK;
249 }
250
SaveConfig(const std::string & config)251 ErrCode NotificationCloneManager::SaveConfig(const std::string& config)
252 {
253 ANS_LOGD("Save config file %{public}s", config.c_str());
254 RemoveBackUpFile();
255 FILE* fp = fopen(BACKUP_CONFIG_FILE_PATH, "w");
256 if (!fp) {
257 ANS_LOGE("Save config file fopen() failed!");
258 return ANS_CLONE_ERROR;
259 }
260
261 int ret = static_cast<int>(fwrite(config.c_str(), 1, config.length(), fp));
262 if (ret != (int)config.length()) {
263 ANS_LOGE("Save config file, fwrite %{public}d failed!", ret);
264 }
265 (void)fflush(fp);
266 (void)fsync(fileno(fp));
267 (void)fclose(fp);
268 ANS_LOGI("Save config file %{public}zu", config.size());
269 return ERR_OK;
270 }
271
RemoveBackUpFile()272 void NotificationCloneManager::RemoveBackUpFile()
273 {
274 remove(BACKUP_CONFIG_FILE_PATH);
275 }
276
OnUserSwitch(int32_t userId)277 void NotificationCloneManager::OnUserSwitch(int32_t userId)
278 {
279 for (auto iter = cloneTemplates.begin(); iter != cloneTemplates.end(); ++iter) {
280 if (iter->second != nullptr) {
281 iter->second->OnUserSwitch(userId);
282 }
283 }
284 }
285
OnRestoreStart(EventFwk::Want want)286 void NotificationCloneManager::OnRestoreStart(EventFwk::Want want)
287 {
288 HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_22, EventBranchId::BRANCH_3);
289 int32_t appIndex = want.GetIntParam("index", -1);
290 std::string bundleName = want.GetStringParam("bundleName");
291 int32_t userId = NotificationCloneUtil::GetActiveUserId();
292 if (appIndex == -1 || bundleName.empty()) {
293 ANS_LOGW("Invalid restore data %{public}d %{public}d %{public}s",
294 appIndex, userId, bundleName.c_str());
295 message.Message("Invalid restore data");
296 NotificationAnalyticsUtil::ReportModifyEvent(message);
297 return;
298 }
299 int32_t uid = NotificationCloneUtil::GetBundleUid(bundleName, userId, appIndex);
300 for (auto iter = cloneTemplates.begin(); iter != cloneTemplates.end(); ++iter) {
301 if (iter->second != nullptr && !iter->second->isDhSource()) {
302 iter->second->OnRestoreStart(bundleName, appIndex, userId, uid);
303 }
304 }
305 }
306
OnDhRestoreStart(const std::string bundleName,const int32_t uid)307 void NotificationCloneManager::OnDhRestoreStart(const std::string bundleName, const int32_t uid)
308 {
309 for (auto iter = cloneTemplates.begin(); iter != cloneTemplates.end(); ++iter) {
310 if (iter->second != nullptr && iter->second->isDhSource()) {
311 iter->second->OnRestoreStart(bundleName, DEFAULT_APP_INDEX, ZERO_USERID, uid);
312 }
313 if (iter->first == CLONE_ITEM_DISTURB && iter->second != nullptr) {
314 iter->second->OnRestoreStart(bundleName, DEFAULT_ANCO_APP_INDEX, DEFAULT_USER_ID, uid);
315 }
316 }
317 }
318 }
319 }
320