1 /* 2 * Copyright (c) 2022-2023 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 "distributed_notification_manager.h" 17 18 #include <vector> 19 20 #include "ans_inner_errors.h" 21 #include "ans_log_wrapper.h" 22 #include "ans_watchdog.h" 23 #include "hitrace_meter_adapter.h" 24 25 namespace OHOS { 26 namespace Notification { 27 namespace { 28 const std::string DELIMITER = "|"; 29 } // namespace 30 DistributedNotificationManager()31 DistributedNotificationManager::DistributedNotificationManager() 32 { 33 ANS_LOGI("constructor"); 34 distributedQueue_ = std::make_shared<ffrt::queue>("NotificationDistributedMgr"); 35 36 DistributedDatabaseCallback::IDatabaseChange databaseCallback = { 37 .OnInsert = std::bind(&DistributedNotificationManager::OnDatabaseInsert, 38 this, 39 std::placeholders::_1, 40 std::placeholders::_2, 41 std::placeholders::_3), 42 .OnUpdate = std::bind(&DistributedNotificationManager::OnDatabaseUpdate, 43 this, 44 std::placeholders::_1, 45 std::placeholders::_2, 46 std::placeholders::_3), 47 .OnDelete = std::bind(&DistributedNotificationManager::OnDatabaseDelete, 48 this, 49 std::placeholders::_1, 50 std::placeholders::_2, 51 std::placeholders::_3), 52 }; 53 databaseCb_ = std::make_shared<DistributedDatabaseCallback>(databaseCallback); 54 55 DistributedDeviceCallback::IDeviceChange deviceCallback = { 56 .OnConnected = std::bind(&DistributedNotificationManager::OnDeviceConnected, this, std::placeholders::_1), 57 .OnDisconnected = std::bind(&DistributedNotificationManager::OnDeviceDisconnected, this, std::placeholders::_1), 58 }; 59 deviceCb_ = std::make_shared<DistributedDeviceCallback>(deviceCallback); 60 database_ = std::make_shared<DistributedDatabase>(databaseCb_, deviceCb_); 61 } 62 ~DistributedNotificationManager()63 DistributedNotificationManager::~DistributedNotificationManager() 64 { 65 ANS_LOGI("deconstructor"); 66 if (distributedQueue_ != nullptr) { 67 ffrt::task_handle handler = distributedQueue_->submit_h(std::bind([&]() { callback_ = {}; })); 68 distributedQueue_->wait(handler); 69 } 70 } 71 ResetFfrtQueue()72 void DistributedNotificationManager::ResetFfrtQueue() 73 { 74 if (distributedQueue_ != nullptr) { 75 distributedQueue_.reset(); 76 } 77 } 78 GenerateDistributedKey(const std::string & deviceId,const std::string & bundleName,const std::string & label,int32_t id,std::string & key)79 void DistributedNotificationManager::GenerateDistributedKey( 80 const std::string &deviceId, const std::string &bundleName, const std::string &label, int32_t id, std::string &key) 81 { 82 key = deviceId + DELIMITER + bundleName + DELIMITER + label + DELIMITER + ToString(id); 83 } 84 GenerateLocalDistributedKey(const std::string & bundleName,const std::string & label,int32_t id,std::string & key)85 bool DistributedNotificationManager::GenerateLocalDistributedKey( 86 const std::string &bundleName, const std::string &label, int32_t id, std::string &key) 87 { 88 std::string deviceId; 89 if (database_ == nullptr) { 90 ANS_LOGE("database_ is invalid."); 91 return false; 92 } 93 if (!database_->GetLocalDeviceId(deviceId)) { 94 return false; 95 } 96 97 GenerateDistributedKey(deviceId, bundleName, label, id, key); 98 return true; 99 } 100 ResolveDistributedKey(const std::string & key,ResolveKey & resolveKey)101 bool DistributedNotificationManager::ResolveDistributedKey(const std::string &key, ResolveKey &resolveKey) 102 { 103 std::size_t deviceIdPosition = 0; 104 std::size_t deviceIdEndPosition = key.find(DELIMITER, deviceIdPosition); 105 if (deviceIdEndPosition == std::string::npos) { 106 return false; 107 } 108 std::size_t bundleNamePosition = deviceIdEndPosition + DELIMITER.size(); 109 std::size_t bundleNameEndPosition = key.find(DELIMITER, bundleNamePosition); 110 if (bundleNameEndPosition == std::string::npos) { 111 return false; 112 } 113 std::size_t labelPosition = bundleNameEndPosition + DELIMITER.size(); 114 std::size_t labelEndPosition = key.find_last_of(DELIMITER) - DELIMITER.size() + 1; 115 if (labelEndPosition < labelPosition) { 116 return false; 117 } 118 std::size_t idPosition = key.find_last_of(DELIMITER) + DELIMITER.size(); 119 120 resolveKey.deviceId = key.substr(deviceIdPosition, deviceIdEndPosition - deviceIdPosition); 121 resolveKey.bundleName = key.substr(bundleNamePosition, bundleNameEndPosition - bundleNamePosition); 122 resolveKey.label = key.substr(labelPosition, labelEndPosition - labelPosition); 123 resolveKey.id = atoi(&key[idPosition]); 124 125 return true; 126 } 127 CheckDeviceId(const std::string & deviceId,const std::string & key)128 bool DistributedNotificationManager::CheckDeviceId(const std::string &deviceId, const std::string &key) 129 { 130 ResolveKey resolveKey; 131 if (!ResolveDistributedKey(key, resolveKey)) { 132 ANS_LOGE("key <%{public}s> is invalid.", key.c_str()); 133 return false; 134 } 135 136 return deviceId == resolveKey.deviceId; 137 } 138 OnDatabaseInsert(const std::string & deviceId,const std::string & key,const std::string & value)139 void DistributedNotificationManager::OnDatabaseInsert( 140 const std::string &deviceId, const std::string &key, const std::string &value) 141 { 142 ANS_LOGD("start"); 143 if (distributedQueue_ == nullptr) { 144 ANS_LOGE("Serial queue is nullptr."); 145 return; 146 } 147 distributedQueue_->submit(std::bind([=]() { 148 if (!CheckDeviceId(deviceId, key)) { 149 ANS_LOGD("device id is distinct. deviceId:%{public}s key:%{public}s", deviceId.c_str(), key.c_str()); 150 } 151 152 ResolveKey resolveKey; 153 if (!ResolveDistributedKey(key, resolveKey)) { 154 ANS_LOGE("key <%{public}s> is invalidity.", key.c_str()); 155 return; 156 } 157 158 sptr<NotificationRequest> request = 159 NotificationJsonConverter::ConvertFromJsonString<NotificationRequest>(value); 160 if (request == nullptr) { 161 ANS_LOGE("convert json to request failed. key:%{public}s", key.c_str()); 162 return; 163 } 164 165 PublishCallback(resolveKey.deviceId, resolveKey.bundleName, request); 166 })); 167 } 168 OnDatabaseUpdate(const std::string & deviceId,const std::string & key,const std::string & value)169 void DistributedNotificationManager::OnDatabaseUpdate( 170 const std::string &deviceId, const std::string &key, const std::string &value) 171 { 172 ANS_LOGD("start"); 173 if (distributedQueue_ == nullptr) { 174 ANS_LOGE("Serial queue is invalid."); 175 return; 176 } 177 ffrt::task_handle handler = distributedQueue_->submit_h(std::bind([=]() { 178 if (!CheckDeviceId(deviceId, key)) { 179 ANS_LOGD("device id are not the same. deviceId:%{public}s key:%{public}s", deviceId.c_str(), key.c_str()); 180 } 181 182 ResolveKey resolveKey; 183 if (!ResolveDistributedKey(key, resolveKey)) { 184 ANS_LOGE("key <%{public}s> is invalid.", key.c_str()); 185 return; 186 } 187 188 sptr<NotificationRequest> request = 189 NotificationJsonConverter::ConvertFromJsonString<NotificationRequest>(value); 190 if (request == nullptr) { 191 ANS_LOGE("convert json to request failed. key:%{public}s", key.c_str()); 192 return; 193 } 194 195 UpdateCallback(resolveKey.deviceId, resolveKey.bundleName, request); 196 })); 197 } 198 OnDatabaseDelete(const std::string & deviceId,const std::string & key,const std::string & value)199 void DistributedNotificationManager::OnDatabaseDelete( 200 const std::string &deviceId, const std::string &key, const std::string &value) 201 { 202 ANS_LOGD("start"); 203 if (distributedQueue_ == nullptr) { 204 ANS_LOGE("Serial queue is invalid."); 205 return; 206 } 207 distributedQueue_->submit(std::bind([=]() { 208 if (!CheckDeviceId(deviceId, key)) { 209 ANS_LOGD("device id are not the same. deviceId:%{public}s key:%{public}s", deviceId.c_str(), key.c_str()); 210 } 211 212 ResolveKey resolveKey; 213 if (!ResolveDistributedKey(key, resolveKey)) { 214 ANS_LOGE("key <%{public}s> is invalid.", key.c_str()); 215 return; 216 } 217 218 DeleteCallback(resolveKey.deviceId, resolveKey.bundleName, resolveKey.label, resolveKey.id); 219 })); 220 } 221 OnDeviceConnected(const std::string & deviceId)222 void DistributedNotificationManager::OnDeviceConnected(const std::string &deviceId) 223 { 224 ANS_LOGD("start"); 225 if (distributedQueue_ == nullptr) { 226 ANS_LOGE("Serial queue is invalid."); 227 return; 228 } 229 distributedQueue_->submit(std::bind([=]() { 230 if (database_ == nullptr) { 231 ANS_LOGE("OnDeviceConnected failed: database is null"); 232 return; 233 } 234 if (!database_->OnDeviceConnected()) { 235 ANS_LOGE("OnDeviceConnected failed."); 236 } 237 })); 238 } 239 OnDeviceDisconnected(const std::string & deviceId)240 void DistributedNotificationManager::OnDeviceDisconnected(const std::string &deviceId) 241 { 242 ANS_LOGD("start"); 243 if (distributedQueue_ == nullptr) { 244 ANS_LOGE("Serial queue is invalid."); 245 return; 246 } 247 distributedQueue_->submit(std::bind([=]() { 248 std::string prefixKey = deviceId + DELIMITER; 249 std::vector<DistributedDatabase::Entry> entries; 250 if (database_ == nullptr) { 251 ANS_LOGE("database_ is invalid."); 252 return; 253 } 254 if (!database_->GetEntriesFromDistributedDB(prefixKey, entries)) { 255 ANS_LOGE("GetEntriesFromDistributedDB failed."); 256 return; 257 } 258 259 for (auto index : entries) { 260 ResolveKey resolveKey; 261 if (!ResolveDistributedKey(index.key.ToString(), resolveKey)) { 262 ANS_LOGE("key <%{public}s> is invalid.", index.key.ToString().c_str()); 263 continue; 264 } 265 266 DeleteCallback(resolveKey.deviceId, resolveKey.bundleName, resolveKey.label, resolveKey.id); 267 } 268 269 database_->ClearDataByDevice(deviceId); 270 271 std::vector<DistributedDatabase::DeviceInfo> deviceList; 272 if (database_->GetDeviceInfoList(deviceList) == ERR_OK && deviceList.empty()) { 273 database_->RecreateDistributedDB(); 274 } 275 })); 276 } 277 PublishCallback(const std::string & deviceId,const std::string & bundleName,sptr<NotificationRequest> & request)278 bool DistributedNotificationManager::PublishCallback( 279 const std::string &deviceId, const std::string &bundleName, sptr<NotificationRequest> &request) 280 { 281 ANS_LOGI("start"); 282 if (callback_.OnPublish) { 283 callback_.OnPublish(deviceId, bundleName, request); 284 } 285 ANS_LOGD("end"); 286 287 return true; 288 } 289 UpdateCallback(const std::string & deviceId,const std::string & bundleName,sptr<NotificationRequest> & request)290 bool DistributedNotificationManager::UpdateCallback( 291 const std::string &deviceId, const std::string &bundleName, sptr<NotificationRequest> &request) 292 { 293 ANS_LOGI("start"); 294 if (callback_.OnUpdate) { 295 callback_.OnUpdate(deviceId, bundleName, request); 296 } 297 ANS_LOGD("end"); 298 299 return true; 300 } 301 DeleteCallback(const std::string & deviceId,const std::string & bundleName,const std::string & label,int32_t id)302 bool DistributedNotificationManager::DeleteCallback( 303 const std::string &deviceId, const std::string &bundleName, const std::string &label, int32_t id) 304 { 305 ANS_LOGI("start"); 306 if (callback_.OnDelete) { 307 callback_.OnDelete(deviceId, bundleName, label, id); 308 } 309 ANS_LOGD("end"); 310 311 return true; 312 } 313 Publish(const std::string & bundleName,const std::string & label,int32_t id,const sptr<NotificationRequest> & request)314 ErrCode DistributedNotificationManager::Publish( 315 const std::string &bundleName, const std::string &label, int32_t id, const sptr<NotificationRequest> &request) 316 { 317 HITRACE_METER_NAME(HITRACE_TAG_NOTIFICATION, __PRETTY_FUNCTION__); 318 ANS_LOGD("start"); 319 std::string key; 320 if (!GenerateLocalDistributedKey(bundleName, label, id, key)) { 321 ANS_LOGE("Failed to generate distributed key."); 322 return ERR_ANS_DISTRIBUTED_GET_INFO_FAILED; 323 } 324 325 std::string value; 326 if (!NotificationJsonConverter::ConvertToJsonString(request, value)) { 327 ANS_LOGE("convert request to json failed. key:%{public}s", key.c_str()); 328 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED; 329 } 330 331 if (database_ == nullptr) { 332 ANS_LOGE("database_ is nullptr."); 333 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED; 334 } 335 if (!database_->PutToDistributedDB(key, value)) { 336 ANS_LOGE("put to distributed DB failed. key:%{public}s", key.c_str()); 337 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED; 338 } 339 340 return ERR_OK; 341 } 342 Update(const std::string & bundleName,const std::string & label,int32_t id,const sptr<NotificationRequest> & request)343 ErrCode DistributedNotificationManager::Update( 344 const std::string &bundleName, const std::string &label, int32_t id, const sptr<NotificationRequest> &request) 345 { 346 ANS_LOGD("start"); 347 std::string key; 348 if (!GenerateLocalDistributedKey(bundleName, label, id, key)) { 349 ANS_LOGE("Generate distributed key failed."); 350 return ERR_ANS_DISTRIBUTED_GET_INFO_FAILED; 351 } 352 353 std::string value; 354 if (!NotificationJsonConverter::ConvertToJsonString(request, value)) { 355 ANS_LOGE("convert request to json failed. key:%{public}s", key.c_str()); 356 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED; 357 } 358 359 if (database_ == nullptr) { 360 ANS_LOGE("database_ is invalid."); 361 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED; 362 } 363 if (!database_->PutToDistributedDB(key, value)) { 364 ANS_LOGE("put to distributed DB failed. key:%{public}s", key.c_str()); 365 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED; 366 } 367 return ERR_OK; 368 } 369 Delete(const std::string & bundleName,const std::string & label,int32_t id)370 ErrCode DistributedNotificationManager::Delete(const std::string &bundleName, const std::string &label, int32_t id) 371 { 372 HITRACE_METER_NAME(HITRACE_TAG_NOTIFICATION, __PRETTY_FUNCTION__); 373 ANS_LOGD("start"); 374 std::string key; 375 if (!GenerateLocalDistributedKey(bundleName, label, id, key)) { 376 ANS_LOGE("Generate distributed key failed."); 377 return ERR_ANS_DISTRIBUTED_GET_INFO_FAILED; 378 } 379 380 if (database_ == nullptr) { 381 ANS_LOGE("database_ is nullptr."); 382 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED; 383 } 384 if (!database_->DeleteToDistributedDB(key)) { 385 ANS_LOGE("Failed to DeleteToDistributedDB. key:%{public}s", key.c_str()); 386 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED; 387 } 388 return ERR_OK; 389 } 390 DeleteRemoteNotification(const std::string & deviceId,const std::string & bundleName,const std::string & label,int32_t id)391 ErrCode DistributedNotificationManager::DeleteRemoteNotification( 392 const std::string &deviceId, const std::string &bundleName, const std::string &label, int32_t id) 393 { 394 HITRACE_METER_NAME(HITRACE_TAG_NOTIFICATION, __PRETTY_FUNCTION__); 395 ANS_LOGD("start"); 396 397 std::string key; 398 GenerateDistributedKey(deviceId, bundleName, label, id, key); 399 400 if (database_ == nullptr) { 401 ANS_LOGE("database_ is invalid."); 402 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED; 403 } 404 if (!database_->DeleteToDistributedDB(key)) { 405 ANS_LOGE("delete to distributed DB failed. key:%{public}s", key.c_str()); 406 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED; 407 } 408 return ERR_OK; 409 } 410 RegisterCallback(const IDistributedCallback & callback)411 ErrCode DistributedNotificationManager::RegisterCallback(const IDistributedCallback &callback) 412 { 413 ANS_LOGD("start"); 414 if (distributedQueue_ == nullptr) { 415 ANS_LOGE("Serial queue is invalid."); 416 return ERR_ANS_INVALID_PARAM; 417 } 418 ffrt::task_handle handler = distributedQueue_->submit_h(std::bind([&]() { callback_ = callback; })); 419 distributedQueue_->wait(handler); 420 return ERR_OK; 421 } 422 UngegisterCallback()423 ErrCode DistributedNotificationManager::UngegisterCallback() 424 { 425 ANS_LOGD("start"); 426 if (distributedQueue_ == nullptr) { 427 ANS_LOGE("Serial queue is invalid."); 428 return ERR_ANS_INVALID_PARAM; 429 } 430 ffrt::task_handle handler = distributedQueue_->submit_h(std::bind([&]() { callback_ = {}; })); 431 distributedQueue_->wait(handler); 432 return ERR_OK; 433 } 434 GetCurrentDistributedNotification(std::vector<sptr<NotificationRequest>> & requestList)435 ErrCode DistributedNotificationManager::GetCurrentDistributedNotification( 436 std::vector<sptr<NotificationRequest>> &requestList) 437 { 438 ANS_LOGD("start"); 439 std::string prefixKey = ""; 440 std::vector<DistributedDatabase::Entry> entries; 441 if (database_ == nullptr) { 442 ANS_LOGE("database_ is invalid."); 443 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED; 444 } 445 if (!database_->GetEntriesFromDistributedDB(prefixKey, entries)) { 446 ANS_LOGE("GetEntriesFromDistributedDB failed."); 447 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED; 448 } 449 450 for (auto index : entries) { 451 ResolveKey resolveKey; 452 if (!ResolveDistributedKey(index.key.ToString(), resolveKey)) { 453 ANS_LOGE("key <%{public}s> is invalid.", index.key.ToString().c_str()); 454 continue; 455 } 456 457 sptr<NotificationRequest> request = 458 NotificationJsonConverter::ConvertFromJsonString<NotificationRequest>(index.value.ToString()); 459 if (request == nullptr) { 460 ANS_LOGE("convert json to request failed. key:%{public}s", index.key.ToString().c_str()); 461 continue; 462 } 463 464 PublishCallback(resolveKey.deviceId, resolveKey.bundleName, request); 465 } 466 467 return ERR_OK; 468 } 469 GetLocalDeviceInfo(DistributedDatabase::DeviceInfo & deviceInfo)470 ErrCode DistributedNotificationManager::GetLocalDeviceInfo(DistributedDatabase::DeviceInfo &deviceInfo) 471 { 472 ANS_LOGD("start"); 473 if (database_ == nullptr) { 474 ANS_LOGE("database_ is invalid."); 475 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED; 476 } 477 if (!database_->GetLocalDeviceInfo(deviceInfo)) { 478 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED; 479 } 480 481 return ERR_OK; 482 } 483 OnDistributedKvStoreDeathRecipient()484 ErrCode DistributedNotificationManager::OnDistributedKvStoreDeathRecipient() 485 { 486 ANS_LOGD("start"); 487 database_ = std::make_shared<DistributedDatabase>(databaseCb_, deviceCb_); 488 if (!database_->RecreateDistributedDB()) { 489 ANS_LOGE("RecreateDistributedDB failed."); 490 return ERR_ANS_DISTRIBUTED_OPERATION_FAILED; 491 } 492 return ERR_OK; 493 } 494 } // namespace Notification 495 } // namespace OHOS