1 /*
2 * Copyright (c) 2024-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_bundle_service.h"
17 
18 #include "ans_log_wrapper.h"
19 #include "notification_preferences.h"
20 #include "notification_clone_util.h"
21 #include "notification_clone_bundle_info.h"
22 #include "os_account_manager_helper.h"
23 
24 namespace OHOS {
25 namespace Notification {
GetInstance()26 std::shared_ptr<NotificationCloneBundle> NotificationCloneBundle::GetInstance()
27 {
28     static std::shared_ptr<NotificationCloneBundle> instance =
29         std::make_shared<NotificationCloneBundle>();
30     return instance;
31 }
32 
NotificationCloneBundle()33 NotificationCloneBundle::NotificationCloneBundle()
34 {
35     cloneBundleQueue_ = std::make_shared<ffrt::queue>("NotificationCloneBundleQueue");
36     if (!cloneBundleQueue_) {
37         ANS_LOGE("ffrt create failed!");
38         return;
39     }
40 }
41 
~NotificationCloneBundle()42 NotificationCloneBundle::~NotificationCloneBundle()
43 {
44 }
45 
OnBackup(nlohmann::json & jsonObject)46 ErrCode NotificationCloneBundle::OnBackup(nlohmann::json &jsonObject)
47 {
48     ANS_LOGI("Notification bundle backup.");
49     int32_t userId = NotificationCloneUtil::GetActiveUserId();
50     std::vector<NotificationCloneBundleInfo> cloneBundles;
51     NotificationPreferences::GetInstance()->GetAllCLoneBundlesInfo(userId, cloneBundles);
52 
53     if (cloneBundles.empty()) {
54         ANS_LOGI("Notification bundle list is empty.");
55         return ERR_OK;
56     }
57     jsonObject = nlohmann::json::array();
58     for (size_t index = 0; index < cloneBundles.size(); index++) {
59         nlohmann::json jsonNode;
60         cloneBundles[index].ToJson(jsonNode);
61         jsonObject.emplace_back(jsonNode);
62         ANS_LOGD("Event bundle backup %{public}s.", cloneBundles[index].Dump().c_str());
63     }
64     ANS_LOGD("Notification bundle list %{public}s", jsonObject.dump().c_str());
65     return ERR_OK;
66 }
67 
OnRestore(const nlohmann::json & jsonObject)68 void NotificationCloneBundle::OnRestore(const nlohmann::json &jsonObject)
69 {
70     ANS_LOGI("Notification bundle list on restore.");
71     if (jsonObject.is_null() || !jsonObject.is_array()) {
72         ANS_LOGI("Notification disturb profile list is null or not array.");
73         return;
74     }
75 
76     int32_t userId = NotificationCloneUtil::GetActiveUserId();
77     std::unique_lock lock(lock_);
78     bundlesInfo_.clear();
79     for (const auto &profile : jsonObject) {
80         NotificationCloneBundleInfo cloneBundleInfo;;
81         cloneBundleInfo.FromJson(profile);
82         bundlesInfo_.emplace_back(cloneBundleInfo);
83     }
84     ANS_LOGI("Notification bundle list size %{public}zu.", bundlesInfo_.size());
85     if (cloneBundleQueue_ == nullptr || bundlesInfo_.empty()) {
86         ANS_LOGE("Clone bundle is invalidated or empty.");
87         return;
88     }
89 
90     for (auto bundle = bundlesInfo_.begin(); bundle != bundlesInfo_.end();) {
91         int32_t uid = NotificationCloneUtil::GetBundleUid(bundle->GetBundleName(),
92             userId, bundle->GetAppIndex());
93         if (uid == -1) {
94             bundle++;
95             continue;
96         }
97         bundle->SetUid(uid);
98         NotificationPreferences::GetInstance()->UpdateCloneBundleInfo(userId, *bundle);
99         bundle = bundlesInfo_.erase(bundle);
100     }
101 
102     for (auto bundle = bundlesInfo_.begin(); bundle != bundlesInfo_.end(); bundle++) {
103         ANS_LOGI("Event bundle left %{public}s.", bundle->Dump().c_str());
104     }
105     ANS_LOGI("Notification bundle list on restore end.");
106 }
107 
OnBundleDataAdd(const sptr<NotificationBundleOption> & bundleOption)108 void NotificationCloneBundle::OnBundleDataAdd(const sptr<NotificationBundleOption> &bundleOption)
109 {
110     HandleBundleEvent(bundleOption->GetBundleName(), bundleOption->GetAppIndex(), bundleOption->GetUid());
111 }
112 
OnBundleDataUpdate(const sptr<NotificationBundleOption> & bundleOption)113 void NotificationCloneBundle::OnBundleDataUpdate(const sptr<NotificationBundleOption> &bundleOption)
114 {
115     HandleBundleEvent(bundleOption->GetBundleName(), bundleOption->GetAppIndex(), bundleOption->GetUid());
116 }
117 
HandleBundleEvent(const std::string bundleName,int32_t appIndex,int32_t uid)118 void NotificationCloneBundle::HandleBundleEvent(const std::string bundleName, int32_t appIndex, int32_t uid)
119 {
120     ANS_LOGI("Handle bundle event %{public}s %{public}d %{public}d %{public}zu.",
121         bundleName.c_str(), appIndex, uid, bundlesInfo_.size());
122     if (bundlesInfo_.empty()) {
123         return;
124     }
125 
126     int32_t userId = -1;
127     OsAccountManagerHelper::GetInstance().GetOsAccountLocalIdFromUid(uid, userId);
128     std::unique_lock lcck(lock_);
129     for (auto bundle = bundlesInfo_.begin(); bundle != bundlesInfo_.end();) {
130         if (bundle->GetBundleName() == bundleName && bundle->GetAppIndex() == appIndex) {
131             bundle->SetUid(uid);
132             NotificationPreferences::GetInstance()->UpdateCloneBundleInfo(userId, *bundle);
133             bundle = bundlesInfo_.erase(bundle);
134             break;
135         }
136         bundle++;
137     }
138     ANS_LOGI("Event bundle left %{public}zu.", bundlesInfo_.size());
139 }
140 
OnUserSwitch(int32_t userId)141 void NotificationCloneBundle::OnUserSwitch(int32_t userId)
142 {
143     ANS_LOGI("Handler user switch %{public}d", userId);
144     if (cloneBundleQueue_ == nullptr) {
145         ANS_LOGW("Clone bundle queue is null.");
146         return;
147     }
148     cloneBundleQueue_->submit_h(std::bind([&]() {
149         std::unique_lock lock(lock_);
150         bundlesInfo_.clear();
151     }));
152 }
153 
154 }
155 }
156