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