• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (C) 2025 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 // LCOV_EXCL_START
16 #include "accessibility_notification_helper.h"
17 #include "timer_info.h"
18 #include "time_service_client.h"
19 
20 #include "notification_helper.h"
21 #include "want_agent_helper.h"
22 #include "want_agent_info.h"
23 #include "os_account_manager.h"
24 
25 #include "hilog_wrapper.h"
26 #include "locale_config.h"
27 #include "locale_info.h"
28 
29 #include <ctime>
30 
31 #include "pixel_map.h"
32 #include "image_source.h"
33 
34 namespace OHOS {
35 namespace Accessibility {
36 
37 namespace {
38 constexpr uint64_t TWELVE_CLOCK = 12 * 60 * 60 * 1000;
39 constexpr uint64_t NOTIFICATION_DATA_2 = 2 * 24 * 60 * 60 * 1000;
40 constexpr uint64_t NOTIFICATION_DATA_5 = 5 * 24 * 60 * 60 * 1000;
41 constexpr uint64_t NOTIFICATION_DATA_8 = 8 * 24 * 60 * 60 * 1000;
42 constexpr uint64_t NOTIFICATION_DATA_15 = 15 * 24 * 60 * 60 * 1000;
43 constexpr uint64_t NOTIFICATION_DATA_22 = 22 * 24 * 60 * 60 * 1000;
44 constexpr uint64_t NOTIFICATION_DATA_30 = static_cast<uint64_t>(29) * static_cast<uint64_t>(24) *
45                                         static_cast<uint64_t>(60) * static_cast<uint64_t>(60) *
46                                         static_cast<uint64_t>(1000);
47 std::vector<uint64_t> NOTIFICATION_DATE{NOTIFICATION_DATA_2,
48     NOTIFICATION_DATA_5,
49     NOTIFICATION_DATA_8,
50     NOTIFICATION_DATA_15,
51     NOTIFICATION_DATA_22,
52     NOTIFICATION_DATA_30};
53 
54 const std::string SETTING_BUNDLE_NAME = "com.ohos.settings";
55 const std::string SETTING_ABILITY_NAME = "com.ohos.settings.MainAbility";
56 const std::string SERVICE_EXTENSION_ABILITY_NAME = "IgnoreRepeatClickExtService";
57 const std::string ACCESSIBILITY_SCREEN_TOUCH_URI = "accessibility_touchscreen_entry";
58 const std::string HAP_PATH = "/system/app/Settings/Settings.hap";
59 const std::string ICON_NAME = "ic_accessibility_notify";
60 const std::string IGNORE_REPEAT_CLICK_NOTIFICATION = "ignore_repeat_click_notification";
61 constexpr int32_t REQUEST_CODE = 8;
62 const std::string IGNORE_REPEAT_CLICK_NOTIFICATION_TITLE = "ignore_repeat_click_notification_title";
63 const std::string IGNORE_REPEAT_CLICK_NOTIFICATION_CONTENT = "ignore_repeat_click_notification_content";
64 const std::string IGNORE_REPEAT_CLICK_NOTIFICATION_CONTENT_BUTTON_CANCEL =
65     "ignore_repeat_click_notification_button_cancel";
66 const std::string IGNORE_REPEAT_CLICK_NOTIFICATION_CONTENT_BUTTON_DISABLE =
67     "ignore_repeat_click_notification_button_disable";
68 const std::string INGORE_REPEAT_CLICK_KEY = "ignore_repeat_click_switch";
69 constexpr int ACCESSIBILITY_SA_UID = 1103;
70 constexpr int ACCESSIBILITY_NOTIFICATION_UID = 1103801;
71 constexpr uint32_t NOTIFICATION_FLAG = 1 << 9;
72 constexpr float ICON_SIZE = 0.3;
73 
74 std::map<std::string, std::string> notificationMap_ = {{IGNORE_REPEAT_CLICK_NOTIFICATION_TITLE, ""},
75     {IGNORE_REPEAT_CLICK_NOTIFICATION_CONTENT, ""},
76     {IGNORE_REPEAT_CLICK_NOTIFICATION_CONTENT_BUTTON_CANCEL, ""},
77     {IGNORE_REPEAT_CLICK_NOTIFICATION_CONTENT_BUTTON_DISABLE, ""}};
78 
79 std::vector<uint64_t> timersVec;
80 }  // namespace
81 
GetWantAgent()82 static std::shared_ptr<OHOS::AbilityRuntime::WantAgent::WantAgent> GetWantAgent()
83 {
84     std::shared_ptr<OHOS::AAFwk::Want> want = std::make_shared<OHOS::AAFwk::Want>();
85     want->SetElementName(SETTING_BUNDLE_NAME, SERVICE_EXTENSION_ABILITY_NAME);
86     want->SetAction("disableIgnoreRepeatClick");
87     std::vector<std::shared_ptr<OHOS::AAFwk::Want>> wants;
88     wants.push_back(want);
89     std::vector<OHOS::AbilityRuntime::WantAgent::WantAgentConstant::Flags> flags;
90     flags.push_back(OHOS::AbilityRuntime::WantAgent::WantAgentConstant::Flags::UPDATE_PRESENT_FLAG);
91     OHOS::AbilityRuntime::WantAgent::WantAgentInfo wantAgentInfo(REQUEST_CODE,
92         AbilityRuntime::WantAgent::WantAgentConstant::OperationType::START_ABILITY,
93         flags,
94         wants,
95         nullptr);
96     return OHOS::AbilityRuntime::WantAgent::WantAgentHelper::GetWantAgent(wantAgentInfo);
97 }
98 
GetCanceluttonWantAgent()99 static std::shared_ptr<OHOS::AbilityRuntime::WantAgent::WantAgent> GetCanceluttonWantAgent()
100 {
101     std::shared_ptr<OHOS::AAFwk::Want> want = std::make_shared<OHOS::AAFwk::Want>();
102     want->SetAction("disableNotificaiton");
103     want->SetElementName(SETTING_BUNDLE_NAME, SERVICE_EXTENSION_ABILITY_NAME);
104 
105     std::vector<std::shared_ptr<OHOS::AAFwk::Want>> wants;
106     wants.push_back(want);
107     std::vector<OHOS::AbilityRuntime::WantAgent::WantAgentConstant::Flags> flags;
108     flags.push_back(OHOS::AbilityRuntime::WantAgent::WantAgentConstant::Flags::UPDATE_PRESENT_FLAG);
109     OHOS::AbilityRuntime::WantAgent::WantAgentInfo wantAgentInfo(REQUEST_CODE,
110         AbilityRuntime::WantAgent::WantAgentConstant::OperationType::START_ABILITY,
111         flags,
112         wants,
113         nullptr);
114     return OHOS::AbilityRuntime::WantAgent::WantAgentHelper::GetWantAgent(wantAgentInfo);
115 }
116 
GetSettingsWantAgent()117 static std::shared_ptr<OHOS::AbilityRuntime::WantAgent::WantAgent> GetSettingsWantAgent()
118 {
119     std::shared_ptr<OHOS::AAFwk::Want> want = std::make_shared<OHOS::AAFwk::Want>();
120     want->SetElementName(SETTING_BUNDLE_NAME, SETTING_ABILITY_NAME);
121     want->SetUri(ACCESSIBILITY_SCREEN_TOUCH_URI);
122     std::vector<std::shared_ptr<OHOS::AAFwk::Want>> wants;
123     wants.push_back(want);
124     std::vector<OHOS::AbilityRuntime::WantAgent::WantAgentConstant::Flags> flags;
125     flags.push_back(OHOS::AbilityRuntime::WantAgent::WantAgentConstant::Flags::UPDATE_PRESENT_FLAG);
126     OHOS::AbilityRuntime::WantAgent::WantAgentInfo wantAgentInfo(REQUEST_CODE,
127         AbilityRuntime::WantAgent::WantAgentConstant::OperationType::START_ABILITY,
128         flags,
129         wants,
130         nullptr);
131     return OHOS::AbilityRuntime::WantAgent::WantAgentHelper::GetWantAgent(wantAgentInfo);
132 }
133 
134 
GetIcon()135 static std::shared_ptr<OHOS::Media::PixelMap> GetIcon()
136 {
137     std::shared_ptr<Global::Resource::ResourceManager> resourceManager(Global::Resource::CreateResourceManager());
138     if (resourceManager == nullptr) {
139         HILOG_ERROR("resourceManager is null");
140         return nullptr;
141     }
142     if (!resourceManager->AddResource(HAP_PATH.c_str())) {
143         HILOG_ERROR("AddResource failed");
144         return nullptr;
145     }
146     size_t len = 0;
147     std::unique_ptr<uint8_t[]> data;
148     resourceManager->GetMediaDataByName(ICON_NAME.c_str(), len, data);
149     Media::SourceOptions opts;
150     uint32_t errorCode = 0;
151     std::unique_ptr<Media::ImageSource> imageSource =
152         Media::ImageSource::CreateImageSource(data.get(), len, opts, errorCode);
153     Media::DecodeOptions decodeOpts;
154     std::shared_ptr<OHOS::Media::PixelMap> icon;
155     if (imageSource) {
156         auto pixelMapPtr = imageSource->CreatePixelMap(decodeOpts, errorCode);
157         icon = std::shared_ptr<Media::PixelMap>(pixelMapPtr.release());
158     }
159     if (errorCode != 0) {
160         HILOG_ERROR("Failed to get icon");
161         return nullptr;
162     }
163     if (icon == nullptr) {
164         HILOG_ERROR("icon is null");
165         return nullptr;
166     }
167     icon->scale(ICON_SIZE, ICON_SIZE);
168     return icon;
169 }
170 
GetReource()171 static void GetReource()
172 {
173     std::shared_ptr<Global::Resource::ResourceManager> resourceManager(Global::Resource::CreateResourceManager());
174     if (resourceManager == nullptr) {
175         HILOG_ERROR("resourceManager is null");
176         return;
177     }
178     std::unique_ptr<Global::Resource::ResConfig> resConfig(Global::Resource::CreateResConfig());
179     if (resConfig == nullptr) {
180         HILOG_ERROR("resConfig is null");
181         return;
182     }
183     std::map<std::string, std::string> configs;
184     OHOS::Global::I18n::LocaleInfo locale(Global::I18n::LocaleConfig::GetSystemLocale(), configs);
185     std::string language = locale.GetLanguage();
186     std::string script = locale.GetScript();
187     std::string region = locale.GetRegion();
188 
189     resConfig->SetLocaleInfo(language.c_str(), script.c_str(), region.c_str());
190     resourceManager->UpdateResConfig(*resConfig);
191     if (!resourceManager->AddResource(HAP_PATH.c_str())) {
192         HILOG_ERROR("AddResource failed");
193         return;
194     }
195     for (auto &iter : notificationMap_) {
196         std::string outValue;
197         resourceManager->GetStringByName(iter.first.c_str(), outValue);
198         HILOG_ERROR("outValue = %{public}s", outValue.c_str());
199         notificationMap_[iter.first] = outValue;
200     }
201 }
202 
CancelNotification()203 void IgnoreRepeatClickNotification::CancelNotification()
204 {
205     Notification::NotificationHelper::CancelNotification(ACCESSIBILITY_NOTIFICATION_UID);
206 }
207 
PublishIgnoreRepeatClickReminder()208 int32_t IgnoreRepeatClickNotification::PublishIgnoreRepeatClickReminder()
209 {
210     GetReource();
211     Notification::NotificationRequest request;
212     std::shared_ptr<Notification::NotificationActionButton> cancelButtion =
213         Notification::NotificationActionButton::Create(nullptr,
214             notificationMap_[IGNORE_REPEAT_CLICK_NOTIFICATION_CONTENT_BUTTON_CANCEL],
215             GetCanceluttonWantAgent());
216     request.AddActionButton(cancelButtion);
217     std::shared_ptr<Notification::NotificationActionButton> closeButton =
218         Notification::NotificationActionButton::Create(
219             nullptr, notificationMap_[IGNORE_REPEAT_CLICK_NOTIFICATION_CONTENT_BUTTON_DISABLE], GetWantAgent());
220     request.AddActionButton(closeButton);
221 
222     std::shared_ptr<Notification::NotificationLongTextContent> content =
223         std::make_shared<Notification::NotificationLongTextContent>();
224     content->SetTitle(notificationMap_[IGNORE_REPEAT_CLICK_NOTIFICATION_TITLE]);
225     content->SetLongText(notificationMap_[IGNORE_REPEAT_CLICK_NOTIFICATION_CONTENT]);
226     std::shared_ptr<Notification::NotificationContent> notificationContent =
227         std::make_shared<Notification::NotificationContent>(content);
228     request.SetContent(notificationContent);
229     request.SetCreatorUid(ACCESSIBILITY_SA_UID);
230     request.SetCreatorPid(getpid());
231     int32_t userId;
232     AccountSA::OsAccountManager::GetOsAccountLocalIdFromUid(ACCESSIBILITY_SA_UID, userId);
233 
234     request.SetCreatorUserId(userId);
235     request.SetCreatorBundleName("");
236     request.SetSlotType(OHOS::Notification::NotificationConstant::SlotType::SERVICE_REMINDER);
237     request.SetInProgress(true);
238     request.SetDistributed(true);
239     request.SetNotificationControlFlags(NOTIFICATION_FLAG);
240     request.SetNotificationId(ACCESSIBILITY_NOTIFICATION_UID);
241 
242     auto icon = GetIcon();
243     if (icon) {
244         request.SetLittleIcon(icon);
245     }
246 
247     request.SetWantAgent(GetSettingsWantAgent());
248 
249     ErrCode ret = Notification::NotificationHelper::PublishNotification(request);
250     HILOG_ERROR("PublishReminder ret = %{public}d", ret);
251     return 0;
252 }
253 
RegisterTimers(uint64_t beginTime)254 int32_t IgnoreRepeatClickNotification::RegisterTimers(uint64_t beginTime)
255 {
256     uint64_t millisecondsToMidnight = CalculateTimeToMidnight(beginTime);
257     for (const auto &interval : NOTIFICATION_DATE) {
258         uint64_t intervalMs = millisecondsToMidnight + TWELVE_CLOCK + interval + beginTime;
259         std::shared_ptr<TimerInfo> timer = std::make_shared<TimerInfo>();
260         timer->SetCallbackInfo(TimerCallback);
261         timer->SetDisposable(true);
262         timer->SetType(
263             static_cast<uint32_t>(timer->TIMER_TYPE_EXACT) | static_cast<uint32_t>(timer->TIMER_TYPE_WAKEUP));
264         uint64_t timerId = MiscServices::TimeServiceClient::GetInstance()->CreateTimer(timer);
265         if (!timerId) {
266             HILOG_ERROR("createTimerFailed");
267             continue;
268         }
269         HILOG_INFO("timeId = %{public}" PRId64 "", timerId);
270         MiscServices::TimeServiceClient::GetInstance()->StartTimer(timerId, intervalMs);
271         timersVec.emplace_back(timerId);
272     }
273     return 0;
274 }
275 
CalculateTimeToMidnight(uint64_t nowTime)276 uint64_t IgnoreRepeatClickNotification::CalculateTimeToMidnight(uint64_t nowTime)
277 {
278     time_t nowSec = static_cast<int64_t>(nowTime / 1000);
279     struct tm *utcTime = gmtime((const time_t *)&nowSec);
280     if (!utcTime) {
281         return 0;
282     }
283 
284     utcTime->tm_hour = 0;
285     utcTime->tm_min = 0;
286     utcTime->tm_sec = 0;
287     utcTime->tm_mday += 1;
288     time_t midnight_seconds = mktime(utcTime);
289     if (midnight_seconds < 0) {
290         return 0;
291     }
292     uint64_t midnight_millis = (uint64_t)midnight_seconds * 1000;
293     if (midnight_millis > nowTime) {
294         uint64_t millisecondsToMidnight = midnight_millis - nowTime;
295         return millisecondsToMidnight;
296     } else {
297         return 0;
298     }
299 }
300 
TimerCallback()301 void IgnoreRepeatClickNotification::TimerCallback()
302 {
303     IgnoreRepeatClickNotification::PublishIgnoreRepeatClickReminder();
304     HILOG_ERROR("IgnoreRepeatClickNotification::TimerCallback");
305 }
306 
DestoryTimers()307 void IgnoreRepeatClickNotification::DestoryTimers()
308 {
309     for (const auto &timerId : timersVec) {
310         MiscServices::TimeServiceClient::GetInstance()->DestroyTimer(timerId);
311     }
312     timersVec.clear();
313 }
314 }  // namespace Accessibility
315 }  // namespace OHOS
316 // LCOV_EXCL_STOP