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