1 /*
2 * Copyright (c) 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 "reminder_datashare_helper.h"
17
18 #include "ans_log_wrapper.h"
19 #include "iservice_registry.h"
20 #include "reminder_calendar_share_table.h"
21 #include "system_ability_definition.h"
22 #include "reminder_request_calendar.h"
23 #include "reminder_data_manager.h"
24 #include "ability_manager_client.h"
25 #include "in_process_call_wrapper.h"
26 #include "reminder_bundle_manager_helper.h"
27 #include "reminder_utils.h"
28
29 namespace OHOS::Notification {
30 namespace {
31 constexpr int64_t DURATION_PRELOAD_TIME = 10 * 60 * 60 * 1000; // 10h, millisecond
32 constexpr int64_t DURATION_DELAY_TASK = 1 * 1000 * 1000; // 1s, microsecond
33 constexpr int64_t CYCLE_DATASHARE_TASK = 1; // 1s
34 constexpr int64_t DURATION_ONE_SECOND = 1000; // 1s, millisecond
35 }
36
37 template<typename T>
GetRdbValue(const std::shared_ptr<DataShare::DataShareResultSet> & resultSet,const std::string & name,T & value)38 void GetRdbValue(const std::shared_ptr<DataShare::DataShareResultSet>& resultSet,
39 const std::string& name, T& value)
40 {
41 value = T();
42 int32_t columnIndex = -1;
43 resultSet->GetColumnIndex(name, columnIndex);
44 if (columnIndex == -1) {
45 ANSR_LOGE("the column %{public}s does not exsit.", name.c_str());
46 return;
47 }
48
49 if constexpr (std::is_same_v<T, std::string>) {
50 resultSet->GetString(columnIndex, value);
51 } else if constexpr (std::is_same_v<T, int64_t>) {
52 resultSet->GetLong(columnIndex, value);
53 } else if constexpr (std::is_same_v<T, uint64_t>) {
54 int64_t t = 0;
55 resultSet->GetLong(columnIndex, t);
56 value = static_cast<uint64_t>(t);
57 } else if constexpr (std::is_integral_v<T>) {
58 int32_t t = 0;
59 resultSet->GetInt(columnIndex, t);
60 value = static_cast<T>(t);
61 }
62 }
63
GetInstance()64 ReminderDataShareHelper& ReminderDataShareHelper::GetInstance()
65 {
66 static ReminderDataShareHelper helper;
67 return helper;
68 }
69
RegisterObserver()70 bool ReminderDataShareHelper::RegisterObserver()
71 {
72 std::lock_guard<std::mutex> locker(mutex_);
73 if (observer_ != nullptr) {
74 return true;
75 }
76 auto helper = CreateDataShareHelper();
77 if (helper == nullptr) {
78 ANSR_LOGE("Create datashare helper failed.");
79 return false;
80 }
81 observer_ = std::make_shared<ReminderDataObserver>();
82 Uri uri(ReminderCalendarShareTable::PROXY);
83 helper->RegisterObserverExt(uri, observer_, false);
84 ReleaseDataShareHelper(helper);
85 return true;
86 }
87
UnRegisterObserver()88 bool ReminderDataShareHelper::UnRegisterObserver()
89 {
90 std::lock_guard<std::mutex> locker(mutex_);
91 if (observer_ == nullptr) {
92 return true;
93 }
94 auto helper = CreateDataShareHelper();
95 if (helper == nullptr) {
96 ANSR_LOGE("Create datashare helper failed.");
97 return false;
98 }
99 Uri uri(ReminderCalendarShareTable::PROXY);
100 helper->UnregisterObserverExt(uri, observer_);
101 ReleaseDataShareHelper(helper);
102 observer_ = nullptr;
103 return true;
104 }
105
Query(std::map<std::string,sptr<ReminderRequest>> & reminders)106 bool ReminderDataShareHelper::Query(std::map<std::string, sptr<ReminderRequest>>& reminders)
107 {
108 auto helper = CreateDataShareHelper();
109 if (helper == nullptr) {
110 ANSR_LOGE("Create datashare helper failed.");
111 return false;
112 }
113 int64_t timestamp = GetCurrentTime();
114 int64_t targetTimestamp = timestamp + DURATION_PRELOAD_TIME;
115
116 std::string proxy = ReminderCalendarShareTable::PROXY;
117 proxy.append("?user=").append(std::to_string(curUserId_));
118 Uri uri(proxy);
119 static std::vector<std::string> columns = GetColumns();
120 DataShare::DataSharePredicates predicates;
121 predicates.NotEqualTo(ReminderCalendarShareTable::STATE, ReminderCalendarShareTable::STATE_DISMISSED);
122 predicates.And();
123 predicates.BeginWrap();
124 predicates.BeginWrap();
125 predicates.LessThanOrEqualTo(ReminderCalendarShareTable::ALARM_TIME, timestamp);
126 predicates.And();
127 predicates.GreaterThanOrEqualTo(ReminderCalendarShareTable::END, timestamp);
128 predicates.EndWrap();
129 predicates.Or();
130 predicates.BeginWrap();
131 predicates.GreaterThanOrEqualTo(ReminderCalendarShareTable::ALARM_TIME, timestamp);
132 predicates.And();
133 predicates.LessThanOrEqualTo(ReminderCalendarShareTable::ALARM_TIME, targetTimestamp);
134 predicates.EndWrap();
135 predicates.EndWrap();
136 auto resultSet = helper->Query(uri, predicates, columns);
137 if (resultSet == nullptr) {
138 ReleaseDataShareHelper(helper);
139 return false;
140 }
141
142 bool isAtLastRow = false;
143 int32_t ret = resultSet->IsAtLastRow(isAtLastRow);
144 while (ret == 0 && !isAtLastRow) {
145 resultSet->GoToNextRow();
146 sptr<ReminderRequest> reminder = CreateReminder(resultSet);
147 if (reminder == nullptr) {
148 continue;
149 }
150 reminders[reminder->GetIdentifier()] = reminder;
151 ret = resultSet->IsAtLastRow(isAtLastRow);
152 }
153 ReleaseDataShareHelper(helper);
154 ANSR_LOGD("Query size: %{public}d.", static_cast<int32_t>(reminders.size()));
155 return true;
156 }
157
Update(const int32_t reminderId,const int32_t state)158 bool ReminderDataShareHelper::Update(const int32_t reminderId, const int32_t state)
159 {
160 auto helper = CreateDataShareHelper();
161 if (helper == nullptr) {
162 ANSR_LOGE("Create datashare helper failed.");
163 return false;
164 }
165 std::string proxy = ReminderCalendarShareTable::PROXY;
166 proxy.append("?user=").append(std::to_string(curUserId_));
167 Uri uri(proxy);
168
169 DataShare::DataSharePredicates predicates;
170 predicates.EqualTo(ReminderCalendarShareTable::ID, reminderId);
171 DataShare::DataShareValuesBucket valuesBucket;
172 valuesBucket.Put(ReminderCalendarShareTable::STATE, state);
173 helper->UpdateEx(uri, predicates, valuesBucket);
174 ReleaseDataShareHelper(helper);
175 return true;
176 }
177
StartDataExtension(const int32_t reason)178 void ReminderDataShareHelper::StartDataExtension(const int32_t reason)
179 {
180 AAFwk::Want want;
181 want.SetElementName(ReminderCalendarShareTable::DATA_NAME, ReminderCalendarShareTable::ENTRY);
182 want.SetParam(ReminderCalendarShareTable::PARAM_CALLBACK_TYPE, reason);
183 IN_PROCESS_CALL_WITHOUT_RET(AAFwk::AbilityManagerClient::GetInstance()->StartExtensionAbility(want, nullptr));
184 }
185
UpdateCalendarUid()186 void ReminderDataShareHelper::UpdateCalendarUid()
187 {
188 uid_ = ReminderBundleManagerHelper::GetInstance()->GetDefaultUidByBundleName(ReminderCalendarShareTable::NAME,
189 curUserId_);
190 dataUid_ = ReminderBundleManagerHelper::GetInstance()->GetDefaultUidByBundleName(
191 ReminderCalendarShareTable::DATA_NAME, curUserId_);
192 }
193
GetCacheReminders()194 std::map<std::string, sptr<ReminderRequest>> ReminderDataShareHelper::GetCacheReminders()
195 {
196 std::map<std::string, sptr<ReminderRequest>> results;
197 {
198 std::lock_guard<std::mutex> locker(cacheMutex_);
199 results = std::move(cache_);
200 }
201 return results;
202 }
203
InsertCacheReminders(const std::map<std::string,sptr<ReminderRequest>> & reminders)204 void ReminderDataShareHelper::InsertCacheReminders(const std::map<std::string, sptr<ReminderRequest>>& reminders)
205 {
206 std::lock_guard<std::mutex> locker(cacheMutex_);
207 for (auto& each : reminders) {
208 cache_[each.first] = each.second;
209 }
210 }
211
OnDataInsertOrDelete()212 void ReminderDataShareHelper::OnDataInsertOrDelete()
213 {
214 auto func = []() {
215 auto manager = ReminderDataManager::GetInstance();
216 if (manager == nullptr) {
217 ANSR_LOGE("ReminderDataManager is nullptr.");
218 return;
219 }
220 manager->OnDataShareInsertOrDelete();
221 };
222 int64_t timestamp =
223 std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
224 if (timestamp - insertTime_ > CYCLE_DATASHARE_TASK) {
225 insertTime_ = timestamp;
226 insertTask_ = false;
227 queue_->submit(func);
228 } else {
229 bool expected = false;
230 if (insertTask_.compare_exchange_strong(expected, true)) {
231 ffrt::task_attr taskAttr;
232 taskAttr.delay(DURATION_DELAY_TASK);
233 queue_->submit(func, taskAttr);
234 }
235 }
236 }
237
OnDataUpdate(const DataShare::DataShareObserver::ChangeInfo & info)238 void ReminderDataShareHelper::OnDataUpdate(const DataShare::DataShareObserver::ChangeInfo& info)
239 {
240 auto func = []() {
241 auto manager = ReminderDataManager::GetInstance();
242 if (manager == nullptr) {
243 ANSR_LOGE("ReminderDataManager is nullptr.");
244 return;
245 }
246 auto reminders = ReminderDataShareHelper::GetInstance().GetCacheReminders();
247 manager->OnDataShareUpdate(reminders);
248 };
249
250 std::map<std::string, sptr<ReminderRequest>> reminders = CreateReminder(info);
251 InsertCacheReminders(reminders);
252 int64_t timestamp =
253 std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
254 if (timestamp - updateTime_ > CYCLE_DATASHARE_TASK) {
255 updateTime_ = timestamp;
256 updateTask_ = false;
257 queue_->submit(func);
258 } else {
259 bool expected = false;
260 if (updateTask_.compare_exchange_strong(expected, true)) {
261 ffrt::task_attr taskAttr;
262 taskAttr.delay(DURATION_DELAY_TASK);
263 queue_->submit(func, taskAttr);
264 }
265 }
266 }
267
CreateDataShareHelper()268 std::shared_ptr<DataShare::DataShareHelper> ReminderDataShareHelper::CreateDataShareHelper()
269 {
270 sptr<ISystemAbilityManager> manager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
271 if (manager == nullptr) {
272 ANSR_LOGE("Get sa manager failed.");
273 return nullptr;
274 }
275 sptr<IRemoteObject> remoteObj = manager->GetSystemAbility(ADVANCED_NOTIFICATION_SERVICE_ABILITY_ID);
276 if (remoteObj == nullptr) {
277 ANSR_LOGE("Get system ability failed.");
278 return nullptr;
279 }
280
281 std::string proxy = ReminderCalendarShareTable::PROXY;
282 proxy.append("?user=").append(std::to_string(curUserId_));
283 std::pair<int, std::shared_ptr<DataShare::DataShareHelper>> ret =
284 DataShare::DataShareHelper::Create(remoteObj, proxy, "");
285 if (ret.first == 0 && ret.second != nullptr) {
286 return ret.second;
287 } else {
288 ANSR_LOGE("Create DataShareHelper failed.");
289 return nullptr;
290 }
291 }
292
ReleaseDataShareHelper(const std::shared_ptr<DataShare::DataShareHelper> & helper)293 bool ReminderDataShareHelper::ReleaseDataShareHelper(const std::shared_ptr<DataShare::DataShareHelper>& helper)
294 {
295 if (helper == nullptr) {
296 ANSR_LOGE("DataShareHelper is nullptr.");
297 return false;
298 }
299 return helper->Release();
300 }
301
GetColumns() const302 std::vector<std::string> ReminderDataShareHelper::GetColumns() const
303 {
304 return std::vector<std::string> {
305 ReminderCalendarShareTable::ID, ReminderCalendarShareTable::EVENT_ID,
306 ReminderCalendarShareTable::END, ReminderCalendarShareTable::ALARM_TIME,
307 ReminderCalendarShareTable::STATE, ReminderCalendarShareTable::TITLE,
308 ReminderCalendarShareTable::CONTENT, ReminderCalendarShareTable::WANT_AGENT,
309 ReminderCalendarShareTable::BUTTONS, ReminderCalendarShareTable::SLOT_TYPE,
310 ReminderCalendarShareTable::IDENTIFIER
311 };
312 }
313
CreateReminder(const std::shared_ptr<DataShare::DataShareResultSet> & result)314 sptr<ReminderRequest> ReminderDataShareHelper::CreateReminder(
315 const std::shared_ptr<DataShare::DataShareResultSet>& result)
316 {
317 sptr<ReminderRequest> reminder = sptr<ReminderRequestCalendar>::MakeSptr();
318 InitNormalInfo(reminder);
319 uint64_t triggerTime = 0;
320 GetRdbValue<uint64_t>(result, ReminderCalendarShareTable::ALARM_TIME, triggerTime);
321 reminder->SetTriggerTimeInMilli(triggerTime);
322
323 int32_t reminderId = 0;
324 GetRdbValue<int32_t>(result, ReminderCalendarShareTable::ID, reminderId);
325 reminder->SetReminderId(reminderId);
326 int32_t notificationId = 0;
327 GetRdbValue<int32_t>(result, ReminderCalendarShareTable::EVENT_ID, notificationId);
328 reminder->SetNotificationId(notificationId);
329
330 int32_t slotType = 0;
331 GetRdbValue<int32_t>(result, ReminderCalendarShareTable::SLOT_TYPE, slotType);
332 reminder->SetSlotType(NotificationConstant::SlotType(slotType));
333
334 std::string strValue;
335 GetRdbValue<std::string>(result, ReminderCalendarShareTable::TITLE, strValue);
336 reminder->SetTitle(strValue);
337 GetRdbValue<std::string>(result, ReminderCalendarShareTable::CONTENT, strValue);
338 reminder->SetContent(strValue);
339 GetRdbValue<std::string>(result, ReminderCalendarShareTable::BUTTONS, strValue);
340 reminder->DeserializeButtonInfoFromJson(strValue);
341 GetRdbValue<std::string>(result, ReminderCalendarShareTable::WANT_AGENT, strValue);
342 reminder->DeserializeWantAgent(strValue, 0);
343 GetRdbValue<std::string>(result, ReminderCalendarShareTable::IDENTIFIER, strValue);
344 reminder->SetIdentifier(strValue);
345 uint64_t endDateTime = 0;
346 GetRdbValue<uint64_t>(result, ReminderCalendarShareTable::END, endDateTime);
347 reminder->SetAutoDeletedTime(endDateTime);
348
349 ReminderRequestCalendar* calendar = static_cast<ReminderRequestCalendar*>(reminder.GetRefPtr());
350 calendar->SetDateTime(triggerTime);
351 calendar->SetEndDateTime(endDateTime);
352
353 time_t now = static_cast<time_t>(triggerTime / DURATION_ONE_SECOND);
354 struct tm nowTime;
355 (void)localtime_r(&now, &nowTime);
356 calendar->SetFirstDesignateYear(static_cast<uint16_t>(ReminderRequest::GetActualTime(
357 ReminderRequest::TimeTransferType::YEAR, nowTime.tm_year)));
358 calendar->SetFirstDesignageMonth(static_cast<uint16_t>(ReminderRequest::GetActualTime(
359 ReminderRequest::TimeTransferType::MONTH, nowTime.tm_mon)));
360 calendar->SetFirstDesignateDay(nowTime.tm_mday);
361 return reminder;
362 }
363
CreateReminder(const DataShare::DataShareObserver::ChangeInfo & info)364 std::map<std::string, sptr<ReminderRequest>> ReminderDataShareHelper::CreateReminder(
365 const DataShare::DataShareObserver::ChangeInfo& info)
366 {
367 std::map<std::string, sptr<ReminderRequest>> reminders;
368 for (auto& values : info.valueBuckets_) {
369 sptr<ReminderRequest> reminder = sptr<ReminderRequestCalendar>::MakeSptr();
370 InitNormalInfo(reminder);
371 uint64_t triggerTime = 0;
372 auto iter = values.find(ReminderCalendarShareTable::ALARM_TIME);
373 if (iter != values.end()) {
374 triggerTime = static_cast<uint64_t>(std::get<double>(iter->second));
375 reminder->SetTriggerTimeInMilli(triggerTime);
376 }
377 InitBaseInfo(values, reminder);
378 uint64_t endDateTime = 0;
379 iter = values.find(ReminderCalendarShareTable::END);
380 if (iter != values.end()) {
381 endDateTime = static_cast<uint64_t>(std::get<double>(iter->second));
382 reminder->SetAutoDeletedTime(endDateTime);
383 }
384
385 ReminderRequestCalendar* calendar = static_cast<ReminderRequestCalendar*>(reminder.GetRefPtr());
386 calendar->SetDateTime(triggerTime);
387 calendar->SetEndDateTime(endDateTime);
388
389 time_t now = static_cast<time_t>(calendar->GetDateTime() / DURATION_ONE_SECOND);
390 struct tm nowTime;
391 (void)localtime_r(&now, &nowTime);
392 calendar->SetFirstDesignateYear(static_cast<uint16_t>(ReminderRequest::GetActualTime(
393 ReminderRequest::TimeTransferType::YEAR, nowTime.tm_year)));
394 calendar->SetFirstDesignageMonth(static_cast<uint16_t>(ReminderRequest::GetActualTime(
395 ReminderRequest::TimeTransferType::MONTH, nowTime.tm_mon)));
396 calendar->SetFirstDesignateDay(nowTime.tm_mday);
397 reminders[reminder->GetIdentifier()] = reminder;
398 }
399 return reminders;
400 }
401
InitNormalInfo(sptr<ReminderRequest> & reminder)402 void ReminderDataShareHelper::InitNormalInfo(sptr<ReminderRequest>& reminder)
403 {
404 reminder->SetRingDuration(0);
405 reminder->InitUserId(curUserId_);
406 reminder->InitUid(uid_);
407 reminder->InitCreatorUid(dataUid_);
408 reminder->SetShare(true);
409 reminder->InitBundleName(ReminderCalendarShareTable::NAME);
410 reminder->InitCreatorBundleName(ReminderCalendarShareTable::DATA_NAME);
411 reminder->SetSystemApp(true);
412 reminder->SetTapDismissed(true);
413 }
414
InitBaseInfo(const DataShare::DataShareObserver::ChangeInfo::VBucket & info,sptr<ReminderRequest> & reminder)415 void ReminderDataShareHelper::InitBaseInfo(const DataShare::DataShareObserver::ChangeInfo::VBucket& info,
416 sptr<ReminderRequest>& reminder)
417 {
418 auto iter = info.find(ReminderCalendarShareTable::ID);
419 if (iter != info.end()) {
420 reminder->SetReminderId(static_cast<int32_t>(std::get<double>(iter->second)));
421 }
422 iter = info.find(ReminderCalendarShareTable::EVENT_ID);
423 if (iter != info.end()) {
424 reminder->SetNotificationId(static_cast<int32_t>(std::get<double>(iter->second)));
425 }
426 iter = info.find(ReminderCalendarShareTable::SLOT_TYPE);
427 if (iter != info.end()) {
428 reminder->SetSlotType(
429 NotificationConstant::SlotType(static_cast<int32_t>(std::get<double>(iter->second))));
430 }
431 iter = info.find(ReminderCalendarShareTable::TITLE);
432 if (iter != info.end()) {
433 reminder->SetTitle(std::get<std::string>(iter->second));
434 }
435 iter = info.find(ReminderCalendarShareTable::CONTENT);
436 if (iter != info.end()) {
437 reminder->SetContent(std::get<std::string>(iter->second));
438 }
439 iter = info.find(ReminderCalendarShareTable::BUTTONS);
440 if (iter != info.end()) {
441 reminder->DeserializeButtonInfoFromJson(std::get<std::string>(iter->second));
442 }
443 iter = info.find(ReminderCalendarShareTable::WANT_AGENT);
444 if (iter != info.end()) {
445 reminder->DeserializeWantAgent(std::get<std::string>(iter->second), 0);
446 }
447 iter = info.find(ReminderCalendarShareTable::IDENTIFIER);
448 if (iter != info.end()) {
449 reminder->SetIdentifier(std::get<std::string>(iter->second));
450 }
451 }
452
ReminderDataShareHelper()453 ReminderDataShareHelper::ReminderDataShareHelper()
454 {
455 queue_ = std::make_shared<ffrt::queue>("ReminderDataShareHelper");
456 insertTime_ =
457 std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
458 updateTime_.store(insertTime_.load());
459 }
460
OnChange(const ChangeInfo & info)461 void ReminderDataShareHelper::ReminderDataObserver::OnChange(const ChangeInfo& info)
462 {
463 switch (info.changeType_) {
464 case DataShare::DataShareObserver::ChangeType::INSERT: {
465 ReminderDataShareHelper::GetInstance().OnDataInsertOrDelete();
466 break;
467 }
468 case DataShare::DataShareObserver::ChangeType::UPDATE: {
469 ReminderDataShareHelper::GetInstance().OnDataUpdate(info);
470 break;
471 }
472 case DataShare::DataShareObserver::ChangeType::DELETE: {
473 ReminderDataShareHelper::GetInstance().OnDataInsertOrDelete();
474 break;
475 }
476 default: {
477 break;
478 }
479 }
480 }
481 }