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 #include "ability_runtime/cj_ability_context.h" 16 #include "calendar_manager_ffi.h" 17 #include "cj_calendar_manager.h" 18 #include "cj_calendar.h" 19 #include "cj_event_filter.h" 20 #include "native/ffi_remote_data.h" 21 #include "ipc_skeleton.h" 22 #include "calendar_define.h" 23 #include "calendar_log.h" 24 #include "calendar_env.h" 25 26 using namespace OHOS; 27 using namespace OHOS::AbilityRuntime; 28 using namespace OHOS::CalendarApi; 29 using namespace OHOS::FFI; 30 using namespace OHOS::DataShare; 31 32 namespace OHOS { 33 namespace CalendarApi { ArrayI64ToVector(CArrI64 arr)34 std::vector<int64_t> ArrayI64ToVector(CArrI64 arr) 35 { 36 std::vector<int64_t> vec; 37 for (int64_t i = 0; i < arr.size; i++) { 38 vec.push_back(arr.head[i]); 39 } 40 return vec; 41 } 42 VectorToArrayI64(const std::vector<int64_t> & vec,int32_t * errcode)43 CArrI64 VectorToArrayI64(const std::vector<int64_t> &vec, int32_t* errcode) 44 { 45 CArrI64 arr = {}; 46 arr.size = vec.size(); 47 if (arr.size == 0) { 48 return arr; 49 } 50 arr.head = static_cast<int64_t *>(malloc(sizeof(int64_t) * vec.size())); 51 if (arr.head == nullptr) { 52 *errcode = CJ_ERR_OUT_OF_MEMORY; 53 LOG_ERROR("CArrI64 malloc failed"); 54 return arr; 55 } 56 for (size_t i = 0; i < vec.size(); i++) { 57 arr.head[i] = vec[i]; 58 } 59 return arr; 60 } 61 IMallocCString(const std::string & origin)62 char* IMallocCString(const std::string &origin) 63 { 64 if (origin.empty()) { 65 return nullptr; 66 } 67 auto length = origin.length() + 1; 68 char *res = static_cast<char *>(malloc(sizeof(char) * length)); 69 if (res == nullptr) { 70 return nullptr; 71 } 72 return std::char_traits<char>::copy(res, origin.c_str(), length); 73 } 74 BuildNativeRecurrenceRule(CRecurrenceRule recurrenceRule)75 RecurrenceRule CJCalendar::BuildNativeRecurrenceRule(CRecurrenceRule recurrenceRule) 76 { 77 RecurrenceRule nativeRecurrenceRule; 78 nativeRecurrenceRule.recurrenceFrequency = RecurrenceType(recurrenceRule.recurrenceFrequency); 79 nativeRecurrenceRule.expire = std::make_optional<int64_t>(recurrenceRule.expire); 80 nativeRecurrenceRule.count = std::make_optional<int64_t>(recurrenceRule.count); 81 nativeRecurrenceRule.interval = std::make_optional<int64_t>(recurrenceRule.interval); 82 nativeRecurrenceRule.excludedDates = 83 std::make_optional<std::vector<int64_t>>(ArrayI64ToVector(recurrenceRule.excludedDates)); 84 nativeRecurrenceRule.daysOfWeek = 85 std::make_optional<std::vector<int64_t>>(ArrayI64ToVector(recurrenceRule.daysOfWeek)); 86 nativeRecurrenceRule.daysOfMonth = 87 std::make_optional<std::vector<int64_t>>(ArrayI64ToVector(recurrenceRule.daysOfMonth)); 88 nativeRecurrenceRule.daysOfYear = 89 std::make_optional<std::vector<int64_t>>(ArrayI64ToVector(recurrenceRule.daysOfYear)); 90 nativeRecurrenceRule.weeksOfMonth = 91 std::make_optional<std::vector<int64_t>>(ArrayI64ToVector(recurrenceRule.weeksOfMonth)); 92 nativeRecurrenceRule.weeksOfYear = 93 std::make_optional<std::vector<int64_t>>(ArrayI64ToVector(recurrenceRule.weeksOfYear)); 94 nativeRecurrenceRule.monthsOfYear = 95 std::make_optional<std::vector<int64_t>>(ArrayI64ToVector(recurrenceRule.monthsOfYear)); 96 return nativeRecurrenceRule; 97 } 98 BuildCRecurrenceRule(RecurrenceRule nativeRecurrenceRule,int32_t * errcode)99 CRecurrenceRule CJCalendar::BuildCRecurrenceRule(RecurrenceRule nativeRecurrenceRule, int32_t* errcode) 100 { 101 CRecurrenceRule cRecurrenceRule; 102 cRecurrenceRule.recurrenceFrequency = nativeRecurrenceRule.recurrenceFrequency; 103 if (nativeRecurrenceRule.expire.has_value()) { 104 cRecurrenceRule.expire = nativeRecurrenceRule.expire.value(); 105 } 106 if (nativeRecurrenceRule.count.has_value()) { 107 cRecurrenceRule.count = nativeRecurrenceRule.count.value(); 108 } 109 if (nativeRecurrenceRule.interval.has_value()) { 110 cRecurrenceRule.interval = nativeRecurrenceRule.interval.value(); 111 } 112 113 if (nativeRecurrenceRule.excludedDates.has_value()) { 114 cRecurrenceRule.excludedDates = VectorToArrayI64(nativeRecurrenceRule.excludedDates.value(), errcode); 115 } 116 if (nativeRecurrenceRule.daysOfWeek.has_value()) { 117 cRecurrenceRule.daysOfWeek = VectorToArrayI64(nativeRecurrenceRule.daysOfWeek.value(), errcode); 118 } 119 if (nativeRecurrenceRule.daysOfMonth.has_value()) { 120 cRecurrenceRule.daysOfMonth = VectorToArrayI64(nativeRecurrenceRule.daysOfMonth.value(), errcode); 121 } 122 if (nativeRecurrenceRule.daysOfYear.has_value()) { 123 cRecurrenceRule.daysOfYear = VectorToArrayI64(nativeRecurrenceRule.daysOfYear.value(), errcode); 124 } 125 if (nativeRecurrenceRule.weeksOfMonth.has_value()) { 126 cRecurrenceRule.weeksOfMonth = VectorToArrayI64(nativeRecurrenceRule.weeksOfMonth.value(), errcode); 127 } 128 if (nativeRecurrenceRule.weeksOfYear.has_value()) { 129 cRecurrenceRule.weeksOfYear = VectorToArrayI64(nativeRecurrenceRule.weeksOfYear.value(), errcode); 130 } 131 if (nativeRecurrenceRule.monthsOfYear.has_value()) { 132 cRecurrenceRule.monthsOfYear = VectorToArrayI64(nativeRecurrenceRule.monthsOfYear.value(), errcode); 133 } 134 return cRecurrenceRule; 135 } 136 BuildCLocation(Location location)137 CLocation CJCalendar::BuildCLocation(Location location) 138 { 139 CLocation clocation; 140 if (location.location.has_value()) { 141 clocation.location = IMallocCString(location.location.value()); 142 } 143 if (location.longitude.has_value()) { 144 clocation.longitude = location.longitude.value(); 145 } 146 if (location.latitude.has_value()) { 147 clocation.latitude = location.latitude.value(); 148 } 149 return clocation; 150 } 151 BuildCArrAttendee(vector<Attendee> attendees,int32_t * errcode)152 CArrAttendee CJCalendar::BuildCArrAttendee(vector<Attendee> attendees, int32_t* errcode) 153 { 154 CArrAttendee arr = {}; 155 arr.size = attendees.size(); 156 if (arr.size == 0) { 157 LOG_ERROR("Invalid size for memory allocation"); 158 *errcode = CJ_ERR_OUT_OF_MEMORY; 159 return arr; 160 } 161 arr.head = static_cast<CAttendee *>(malloc(sizeof(CAttendee) * attendees.size())); 162 if (arr.head == nullptr) { 163 *errcode = CJ_ERR_OUT_OF_MEMORY; 164 LOG_ERROR("CAttendee malloc failed"); 165 return arr; 166 } 167 for (size_t j = 0; j < attendees.size(); j++) { 168 arr.head[j].name = IMallocCString(attendees[j].name); 169 arr.head[j].email = IMallocCString(attendees[j].email); 170 if (attendees[j].role.has_value()) { 171 arr.head[j].role = attendees[j].role.value(); 172 } 173 } 174 return arr; 175 } 176 CEventToEvent(CEvent event)177 Event CJCalendar::CEventToEvent(CEvent event) 178 { 179 Event nativeEvent = {}; 180 nativeEvent.id = event.id; 181 nativeEvent.type = event.type == 0 ? Normal : Important; 182 nativeEvent.startTime = event.startTime; 183 nativeEvent.endTime = event.endTime; 184 nativeEvent.title = std::make_optional<std::string>(event.title); 185 nativeEvent.location->location = event.location.location; 186 nativeEvent.location->longitude = event.location.longitude; 187 nativeEvent.location->latitude = event.location.latitude; 188 nativeEvent.isAllDay = std::make_optional<bool>(event.isAllDay); 189 for (int64_t i = 0; i < event.attendee.size; i++) { 190 Attendee attendee; 191 attendee.name = event.attendee.head[i].name; 192 attendee.email = event.attendee.head[i].email; 193 attendee.role = std::make_optional<RoleType>(RoleType(event.attendee.head[i].role)); 194 nativeEvent.attendees.push_back(attendee); 195 } 196 if (event.timeZone != nullptr && strlen(event.timeZone) > 0) { 197 nativeEvent.timeZone = std::make_optional<std::string>(event.timeZone); 198 } 199 std::vector<int> vec; 200 for (int64_t i = 0; i < event.reminderTime.size; i++) { 201 vec.push_back(static_cast<int>(event.reminderTime.head[i])); 202 } 203 nativeEvent.reminderTime = vec; 204 nativeEvent.recurrenceRule = 205 std::make_optional<RecurrenceRule>(BuildNativeRecurrenceRule(event.recurrenceRule)); 206 207 if (event.description != nullptr && strlen(event.description) > 0) { 208 nativeEvent.description = std::make_optional<std::string>(event.description); 209 } 210 nativeEvent.service->type = event.service.type; 211 nativeEvent.service->uri = event.service.uri; 212 if (event.service.description != nullptr && strlen(event.service.description) > 0) { 213 nativeEvent.service->description = std::make_optional<std::string>(event.service.description); 214 } 215 if (event.identifier != nullptr && strlen(event.identifier) > 0) { 216 nativeEvent.identifier = std::make_optional<std::string>(event.identifier); 217 } 218 nativeEvent.isLunar = std::make_optional<bool>(event.isLunar); 219 return nativeEvent; 220 } 221 CRecurrenceRuleFree(CRecurrenceRule cRecurrenceRule)222 void CJCalendar::CRecurrenceRuleFree(CRecurrenceRule cRecurrenceRule) 223 { 224 if (cRecurrenceRule.excludedDates.head != nullptr) { 225 free(cRecurrenceRule.excludedDates.head); 226 } 227 if (cRecurrenceRule.daysOfWeek.head != nullptr) { 228 free(cRecurrenceRule.daysOfWeek.head); 229 } 230 if (cRecurrenceRule.daysOfMonth.head != nullptr) { 231 free(cRecurrenceRule.daysOfMonth.head); 232 } 233 if (cRecurrenceRule.daysOfYear.head != nullptr) { 234 free(cRecurrenceRule.daysOfYear.head); 235 } 236 if (cRecurrenceRule.weeksOfMonth.head != nullptr) { 237 free(cRecurrenceRule.weeksOfMonth.head); 238 } 239 if (cRecurrenceRule.weeksOfYear.head != nullptr) { 240 free(cRecurrenceRule.weeksOfYear.head); 241 } 242 if (cRecurrenceRule.monthsOfYear.head != nullptr) { 243 free(cRecurrenceRule.monthsOfYear.head); 244 } 245 } 246 CArrAttendeeFree(CArrAttendee cArrAttendee)247 void CJCalendar::CArrAttendeeFree(CArrAttendee cArrAttendee) 248 { 249 for (int64_t j = 0; j < cArrAttendee.size; j++) { 250 if (cArrAttendee.head[j].name!= nullptr) { 251 free(cArrAttendee.head[j].name); 252 } 253 if (cArrAttendee.head[j].email!= nullptr) { 254 free(cArrAttendee.head[j].email); 255 } 256 } 257 } 258 CArrEventfree(CArrEvents arr)259 void CJCalendar::CArrEventfree(CArrEvents arr) 260 { 261 if (arr.head == nullptr) { 262 return; 263 } 264 for (int64_t i = 0; i < arr.size; i++) { 265 if (arr.head[i].title != nullptr) { 266 free(arr.head[i].title); 267 } 268 if (arr.head[i].timeZone != nullptr) { 269 free(arr.head[i].timeZone); 270 } 271 if (arr.head[i].description != nullptr) { 272 free(arr.head[i].description); 273 } 274 if (arr.head[i].service.description != nullptr) { 275 free(arr.head[i].service.description); 276 } 277 if (arr.head[i].service.type != nullptr) { 278 free(arr.head[i].service.type); 279 } 280 if (arr.head[i].service.uri != nullptr) { 281 free(arr.head[i].service.uri); 282 } 283 if (arr.head[i].identifier != nullptr) { 284 free(arr.head[i].identifier); 285 } 286 if (arr.head[i].reminderTime.head != nullptr) { 287 free(arr.head[i].reminderTime.head); 288 } 289 if (arr.head[i].attendee.head != nullptr) { 290 CArrAttendeeFree(arr.head[i].attendee); 291 free(arr.head[i].attendee.head); 292 } 293 if (arr.head[i].location.location != nullptr) { 294 free(arr.head[i].location.location); 295 } 296 CRecurrenceRuleFree(arr.head[i].recurrenceRule); 297 free(&arr.head[i]); 298 } 299 } 300 VectorToCArrEvents(std::vector<Event> events,int32_t * errcode)301 CArrEvents CJCalendar::VectorToCArrEvents(std::vector<Event> events, int32_t* errcode) 302 { 303 CArrEvents arr = {}; 304 arr.head = static_cast<CEvent *>(malloc(sizeof(CEvent) * events.size())); 305 if (arr.head == nullptr) { 306 *errcode = CJ_ERR_OUT_OF_MEMORY; 307 return arr; 308 } 309 arr.size = static_cast<int64_t>(events.size()); 310 for (size_t i = 0; i < events.size(); i++) { 311 memset_s(&arr.head[i], sizeof(arr.head[i]), 0, sizeof(arr.head[i])); 312 arr.head[i].id = static_cast<int64_t>(events[i].id.value()); 313 arr.head[i].type = events[i].type; 314 arr.head[i].startTime = events[i].startTime; 315 arr.head[i].endTime = events[i].endTime; 316 arr.head[i].title = IMallocCString(events[i].title.value_or("")); 317 if (events[i].location.has_value()) { 318 arr.head[i].location = BuildCLocation(events[i].location.value()); 319 } 320 arr.head[i].isAllDay = events[i].isAllDay.value_or(false); 321 arr.head[i].attendee = BuildCArrAttendee(events[i].attendees, errcode); 322 arr.head[i].timeZone = IMallocCString(events[i].timeZone.value_or("")); 323 if (events[i].reminderTime.has_value() && events[i].reminderTime.value().size() > 0) { 324 vector<int> reminderTime = events[i].reminderTime.value(); 325 arr.head[i].reminderTime.size = static_cast<int64_t>(reminderTime.size()); 326 arr.head[i].reminderTime.head = static_cast<int64_t *>(malloc(sizeof(int64_t) * reminderTime.size())); 327 if (arr.head[i].reminderTime.head == nullptr) { 328 *errcode = CJ_ERR_OUT_OF_MEMORY; 329 return arr; 330 } 331 for (int64_t j = 0; j < arr.head[i].reminderTime.size; j++) { 332 arr.head[i].reminderTime.head[j] = static_cast<int64_t>(reminderTime[j]); 333 } 334 } 335 if (events[i].recurrenceRule.has_value()) { 336 arr.head[i].recurrenceRule = BuildCRecurrenceRule(events[i].recurrenceRule.value(), errcode); 337 } 338 arr.head[i].description = IMallocCString(events[i].description.value_or("")); 339 if (events[i].service.has_value()) { 340 arr.head[i].service.type = IMallocCString(events[i].service.value().type); 341 arr.head[i].service.uri = IMallocCString(events[i].service.value().uri); 342 arr.head[i].service.description = IMallocCString(events[i].service.value().description.value_or("")); 343 } 344 arr.head[i].identifier = IMallocCString(events[i].identifier.value_or("")); 345 arr.head[i].isLunar = events[i].isLunar.value_or(false); 346 } 347 return arr; 348 } 349 CJCalendar(std::shared_ptr<Native::CJNativeCalendar> calendar)350 CJCalendar::CJCalendar(std::shared_ptr<Native::CJNativeCalendar> calendar) 351 { 352 calendar_ = calendar; 353 } 354 GetNative()355 std::shared_ptr<Native::CJNativeCalendar>& CJCalendar::GetNative() 356 { 357 return calendar_; 358 } 359 AddEvent(CEvent event,int32_t * errcode)360 int64_t CJCalendar::AddEvent(CEvent event, int32_t* errcode) 361 { 362 Event nativeEvent = CEventToEvent(event); 363 auto cnative = GetNative(); 364 if (cnative == nullptr) { 365 LOG_ERROR("cnative is nullptr"); 366 *errcode = CJ_ERR_NULL_PTR; 367 return -1; 368 } 369 Native::DumpEvent(nativeEvent); 370 int64_t eventId = cnative->AddEvent(nativeEvent); 371 return eventId; 372 } 373 AddEvents(CArrEvents event,int32_t * errcode)374 void CJCalendar::AddEvents(CArrEvents event, int32_t* errcode) 375 { 376 std::vector<Event> nativeEvents; 377 for (int64_t i = 0; i < event.size; i++) { 378 nativeEvents.push_back(CEventToEvent(event.head[i])); 379 } 380 if (calendar_ == nullptr) { 381 LOG_ERROR("calendar_ is nullptr"); 382 *errcode = CJ_ERR_NULL_PTR; 383 return; 384 } 385 int count = calendar_->AddEvents(nativeEvents); 386 if (count < 0) { 387 LOG_ERROR("add events failed"); 388 *errcode = CJ_ERR_NULL_PTR; 389 return; 390 } 391 } 392 DeleteEvent(int64_t eventId,int32_t * errcode)393 void CJCalendar::DeleteEvent(int64_t eventId, int32_t* errcode) 394 { 395 if (calendar_ == nullptr) { 396 LOG_ERROR("calendar_ is nullptr"); 397 *errcode = CJ_ERR_NULL_PTR; 398 return; 399 } 400 bool ret = calendar_->DeleteEvent(eventId); 401 if (!ret) { 402 LOG_ERROR("delete event failed"); 403 *errcode = CJ_ERR_NULL_PTR; 404 return; 405 } 406 } 407 DeleteEvents(CArrI64 eventIds,int32_t * errcode)408 void CJCalendar::DeleteEvents(CArrI64 eventIds, int32_t* errcode) 409 { 410 std::vector<int> ids; 411 for (int64_t i = 0; i < eventIds.size; i++) { 412 ids.push_back(static_cast<int>(eventIds.head[i])); 413 } 414 if (calendar_ == nullptr) { 415 LOG_ERROR("calendar_ is nullptr"); 416 *errcode = CJ_ERR_NULL_PTR; 417 return; 418 } 419 int count = calendar_->DeleteEvents(ids); 420 if (count < 0) { 421 LOG_ERROR("delete events failed"); 422 *errcode = CJ_ERR_NULL_PTR; 423 return; 424 } 425 } 426 UpdateEvent(CEvent event,int32_t * errcode)427 void CJCalendar::UpdateEvent(CEvent event, int32_t* errcode) 428 { 429 Event nativeEvent = CEventToEvent(event); 430 if (calendar_ == nullptr) { 431 LOG_ERROR("calendar_ is nullptr"); 432 *errcode = CJ_ERR_NULL_PTR; 433 return; 434 } 435 bool ret = calendar_->UpdateEvent(nativeEvent); 436 if (!ret) { 437 LOG_ERROR("update event failed"); 438 *errcode = CJ_ERR_NULL_PTR; 439 return; 440 } 441 } 442 GetEvents(int64_t eventFilterId,CArrString eventKey,int32_t * errcode)443 CArrEvents CJCalendar::GetEvents(int64_t eventFilterId, CArrString eventKey, int32_t* errcode) 444 { 445 std::vector<std::string> keys; 446 for (int64_t i = 0; i < eventKey.size; i++) { 447 keys.push_back(eventKey.head[i]); 448 } 449 auto instance = FFIData::GetData<CJEventFilter>(eventFilterId); 450 std::shared_ptr<Native::EventFilter> eventFilter = nullptr; 451 if (instance!= nullptr && instance->eventFilter_!= nullptr) { 452 eventFilter = instance->eventFilter_; 453 } 454 CArrEvents arr = {}; 455 if (calendar_ == nullptr) { 456 LOG_ERROR("calendar_ is nullptr"); 457 *errcode = CJ_ERR_NULL_PTR; 458 return arr; 459 } 460 std::vector<Event> events = calendar_->GetEvents(eventFilter, keys); 461 arr = VectorToCArrEvents(events, errcode); 462 if (*errcode != 0) { 463 CArrEventfree(arr); 464 } 465 return arr; 466 } 467 GetConfig(int32_t * errcode)468 CCalendarConfig CJCalendar::GetConfig(int32_t* errcode) 469 { 470 CCalendarConfig config = {}; 471 if (calendar_ == nullptr) { 472 LOG_ERROR("calendar_ is nullptr"); 473 *errcode = CJ_ERR_NULL_PTR; 474 return config; 475 } 476 CalendarConfig nativeConfig = calendar_->GetConfig(); 477 config.enableReminder = nativeConfig.enableReminder.value(); 478 config.color = std::get<int64_t>(nativeConfig.color); 479 return config; 480 } 481 SetConfig(CCalendarConfig config,int32_t * errcode)482 void CJCalendar::SetConfig(CCalendarConfig config, int32_t* errcode) 483 { 484 CalendarConfig nativeConfig; 485 nativeConfig.enableReminder = config.enableReminder; 486 nativeConfig.color = config.color; 487 if (calendar_ == nullptr) { 488 LOG_ERROR("calendar_ is nullptr"); 489 *errcode = CJ_ERR_NULL_PTR; 490 return; 491 } 492 493 bool ret = calendar_->SetConfig(nativeConfig); 494 if (!ret) { 495 LOG_ERROR("set config failed"); 496 *errcode = CJ_ERR_NULL_PTR; 497 return; 498 } 499 } 500 GetAccount(int32_t * errcode)501 CCalendarAccount CJCalendar::GetAccount(int32_t* errcode) 502 { 503 CCalendarAccount account; 504 if (calendar_ == nullptr) { 505 LOG_ERROR("calendar_ is nullptr"); 506 *errcode = CJ_ERR_NULL_PTR; 507 return account; 508 } 509 CalendarAccount nativeAccount = calendar_->GetAccount(); 510 account.name = IMallocCString(nativeAccount.name); 511 account.type = IMallocCString(nativeAccount.type); 512 account.displayName = IMallocCString(nativeAccount.displayName.value()); 513 return account; 514 } 515 } 516 }