• 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 
31 namespace OHOS {
32 namespace Notification {
33 
34 const int ANS_CLONE_ERROR = -1;
35 constexpr const char *CLONE_ITEM_BUNDLE_INFO = "notificationBundle";
36 constexpr const char *CLONE_ITEM_DISTURB = "notificationDisturb";
37 constexpr const char *BACKUP_CONFIG_FILE_PATH = "/data/service/el1/public/notification/backup_config.conf";
38 
GetInstance()39 NotificationCloneManager& NotificationCloneManager::GetInstance()
40 {
41     static NotificationCloneManager notificationCloneManager;
42     return notificationCloneManager;
43 }
44 
SetBackUpReply()45 static std::string SetBackUpReply()
46 {
47     nlohmann::json reply;
48     nlohmann::json resultInfo = nlohmann::json::array();
49     nlohmann::json errorInfo;
50 
51     errorInfo["type"] = "ErrorInfo";
52     errorInfo["errorCode"] = std::to_string(ERR_OK);
53     errorInfo["errorInfo"] = "";
54 
55     resultInfo.emplace_back(errorInfo);
56     reply["resultInfo"] = resultInfo;
57 
58     return reply.dump();
59 }
60 
OnBackup(MessageParcel & data,MessageParcel & reply)61 int32_t NotificationCloneManager::OnBackup(MessageParcel& data, MessageParcel& reply)
62 {
63     if (cloneTemplates.empty()) {
64         ANS_LOGI("Notification no need Backup.");
65         return ERR_OK;
66     }
67 
68     nlohmann::json jsonObject;
69     for (auto iter = cloneTemplates.begin(); iter != cloneTemplates.end(); ++iter) {
70         nlohmann::json jsonItem;
71         auto cloneTemplate = iter->second;
72         if (cloneTemplate == nullptr) {
73             ANS_LOGW("Notification OnBackup %{public}s funtion is null.", iter->first.c_str());
74             continue;
75         }
76         if (iter->second->OnBackup(jsonItem) != ERR_OK) {
77             ANS_LOGW("Notification OnBackup %{public}s failed.", iter->first.c_str());
78             continue;
79         }
80         jsonObject[iter->first] = jsonItem;
81     }
82 
83     if (SaveConfig(jsonObject.dump()) != ERR_OK) {
84         return ANS_CLONE_ERROR;
85     }
86 
87     UniqueFd fd = UniqueFd(open(BACKUP_CONFIG_FILE_PATH, O_RDONLY));
88     if (fd.Get() < 0) {
89         ANS_LOGW("Notification open file failed.");
90         return ANS_CLONE_ERROR;
91     }
92 
93     if (reply.WriteFileDescriptor(fd) == false) {
94         close(fd.Release());
95         ANS_LOGW("Notification write file descriptor failed!");
96         return ANS_CLONE_ERROR;
97     }
98 
99     ANS_LOGI("Notification OnBackup end fd: %{public}d.", fd.Get());
100     close(fd.Release());
101     return ERR_OK;
102 }
103 
OnRestore(MessageParcel & data,MessageParcel & reply)104 int32_t NotificationCloneManager::OnRestore(MessageParcel& data, MessageParcel& reply)
105 {
106     reply.WriteString(SetBackUpReply());
107     std::string storeMessage;
108     UniqueFd fd(data.ReadFileDescriptor());
109     if (LoadConfig(fd, storeMessage) != ERR_OK) {
110         close(fd.Release());
111         RemoveBackUpFile();
112         return ANS_CLONE_ERROR;
113     }
114 
115     RemoveBackUpFile();
116     nlohmann::json jsonObject = nlohmann::json::parse(storeMessage, nullptr, false);
117     if (jsonObject.is_null() || !jsonObject.is_object()) {
118         ANS_LOGE("Invalid JSON object");
119         return ANS_CLONE_ERROR;
120     }
121     for (auto iter = cloneTemplates.begin(); iter != cloneTemplates.end(); ++iter) {
122         if (jsonObject.contains(iter->first) && iter->second != nullptr) {
123             iter->second->OnRestore(jsonObject.at(iter->first));
124         }
125     }
126     return ERR_OK;
127 }
128 
NotificationCloneManager()129 NotificationCloneManager::NotificationCloneManager()
130 {
131     ANS_LOGI("Notification clone manager init.");
132     cloneTemplates.insert_or_assign(CLONE_ITEM_BUNDLE_INFO, NotificationCloneBundle::GetInstance());
133     cloneTemplates.insert_or_assign(CLONE_ITEM_DISTURB, NotificationCloneDisturb::GetInstance());
134 }
135 
~NotificationCloneManager()136 NotificationCloneManager::~NotificationCloneManager()
137 {
138     ANS_LOGI("Notification clone manager destory.");
139 }
140 
LoadConfig(UniqueFd & fd,std::string & config)141 ErrCode NotificationCloneManager::LoadConfig(UniqueFd &fd, std::string& config)
142 {
143     ANS_LOGI("Load notification config.");
144     struct stat statBuf;
145     if (fstat(fd.Get(), &statBuf) < 0) {
146         ANS_LOGW("LoadConfig fstat fd fail %{public}d.", fd.Get());
147         return ANS_CLONE_ERROR;
148     }
149     int destFd = open(BACKUP_CONFIG_FILE_PATH, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
150     if (destFd < 0) {
151         ANS_LOGW("LoadConfig open file fail.");
152         return ANS_CLONE_ERROR;
153     }
154     if (sendfile(destFd, fd.Get(), nullptr, statBuf.st_size) < 0) {
155         ANS_LOGW("LoadConfig fd sendfile(size: %{public}d) to destFd fail.", static_cast<int>(statBuf.st_size));
156         close(destFd);
157         return ANS_CLONE_ERROR;
158     }
159     close(destFd);
160     std::ifstream fs(BACKUP_CONFIG_FILE_PATH);
161     if (!fs.is_open()) {
162         ANS_LOGW("Loading config file%{public}s is_open() failed!", BACKUP_CONFIG_FILE_PATH);
163         return ANS_CLONE_ERROR;
164     }
165     config.clear();
166     std::string line;
167     while (std::getline(fs, line)) {
168         config.append(line);
169     }
170     fs.close();
171     return ERR_OK;
172 }
173 
SaveConfig(const std::string & config)174 ErrCode NotificationCloneManager::SaveConfig(const std::string& config)
175 {
176     ANS_LOGD("Save config file %{public}s", config.c_str());
177     RemoveBackUpFile();
178     FILE* fp = fopen(BACKUP_CONFIG_FILE_PATH, "w");
179     if (!fp) {
180         ANS_LOGW("Save config file: %{public}s, fopen() failed!", BACKUP_CONFIG_FILE_PATH);
181         return ANS_CLONE_ERROR;
182     }
183 
184     int ret = fwrite(config.c_str(), 1, config.length(), fp);
185     if (ret != (int)config.length()) {
186         ANS_LOGW("Save config file: %{public}s, fwrite %{public}d failed!", BACKUP_CONFIG_FILE_PATH, ret);
187     }
188     (void)fflush(fp);
189     (void)fsync(fileno(fp));
190     (void)fclose(fp);
191     ANS_LOGI("Save config file %{public}zu", config.size());
192     return ERR_OK;
193 }
194 
RemoveBackUpFile()195 void NotificationCloneManager::RemoveBackUpFile()
196 {
197     remove(BACKUP_CONFIG_FILE_PATH);
198 }
199 
OnUserSwitch(int32_t userId)200 void NotificationCloneManager::OnUserSwitch(int32_t userId)
201 {
202     for (auto iter = cloneTemplates.begin(); iter != cloneTemplates.end(); ++iter) {
203         if (iter->second != nullptr) {
204             iter->second->OnUserSwitch(userId);
205         }
206     }
207 }
208 
OnRestoreStart(EventFwk::Want want)209 void NotificationCloneManager::OnRestoreStart(EventFwk::Want want)
210 {
211     int32_t appIndex = want.GetIntParam("index", -1);
212     std::string bundleName = want.GetStringParam("bundleName");
213     int32_t userId = NotificationCloneUtil::GetActiveUserId();
214     if (appIndex == -1 || bundleName.empty()) {
215         ANS_LOGW("Invalid restore data %{public}d %{public}d %{public}s",
216             appIndex, userId, bundleName.c_str());
217         return;
218     }
219     int32_t uid = NotificationCloneUtil::GetBundleUid(bundleName, userId, appIndex);
220     for (auto iter = cloneTemplates.begin(); iter != cloneTemplates.end(); ++iter) {
221         if (iter->second != nullptr) {
222             iter->second->OnRestoreStart(bundleName, appIndex, userId, uid);
223         }
224     }
225 }
226 }
227 }
228