From 5259f4b50149a36217ddeba0b31e74fcb17c46da Mon Sep 17 00:00:00 2001 From: wjh Date: Fri, 20 Oct 2023 10:34:28 +0800 Subject: [PATCH] Click the button to support data updates Signed-off-by: wjh --- bundle.json | 3 +- frameworks/ans/src/reminder_request.cpp | 62 +++++- .../test/unittest/reminder_request_test.cpp | 40 ++++ .../napi/include/reminder/reminder_common.h | 14 ++ frameworks/js/napi/src/reminder/publish.cpp | 128 ++++++++++- .../js/napi/src/reminder/reminder_common.cpp | 200 +++++++++++++++++- interfaces/inner_api/reminder_request.h | 12 +- services/ans/BUILD.gn | 2 + services/ans/include/reminder_data_manager.h | 44 ++++ services/ans/src/reminder_data_manager.cpp | 169 +++++++++++++++ services/ans/test/unittest/BUILD.gn | 4 + 11 files changed, 666 insertions(+), 12 deletions(-) diff --git a/bundle.json b/bundle.json index e0e66a09e..db0e04259 100644 --- a/bundle.json +++ b/bundle.json @@ -78,7 +78,8 @@ "device_manager", "kv_store", "ffrt", - "device_standby" + "device_standby", + "data_share" ], "third_party": [ "libuv" diff --git a/frameworks/ans/src/reminder_request.cpp b/frameworks/ans/src/reminder_request.cpp index 7563cbaf3..a5228c583 100644 --- a/frameworks/ans/src/reminder_request.cpp +++ b/frameworks/ans/src/reminder_request.cpp @@ -33,11 +33,16 @@ namespace Notification { namespace { const int32_t BASE_YEAR = 1900; const int32_t SINGLE_BUTTON_MIN_LEN = 2; -const int32_t SINGLE_BUTTON_MAX_LEN = 4; +const int32_t SINGLE_BUTTON_WANTAGENT_LEN = 4; +const int32_t SINGLE_BUTTON_DATASHARE_MIN_LEN = 5; +const int32_t SINGLE_BUTTON_DATASHARE_MAX_LEN = 7; const int32_t BUTTON_TYPE_INDEX = 0; const int32_t BUTTON_TITLE_INDEX = 1; -const int32_t BUTTON_PKG_INDEX = 2; -const int32_t BUTTON_ABILITY_INDEX = 3; +const int32_t BUTTON_INDEX_TWO = 2; +const int32_t BUTTON_INDEX_THREE = 3; +const int32_t BUTTON_INDEX_FOUR = 4; +const int32_t BUTTON_INDEX_FIVE = 5; +const int32_t BUTTON_INDEX_SIX = 6; } int32_t ReminderRequest::GLOBAL_ID = 0; @@ -185,7 +190,8 @@ std::string ReminderRequest::Dump() const } ReminderRequest& ReminderRequest::SetActionButton(const std::string &title, const ActionButtonType &type, - const std::shared_ptr &buttonWantAgent) + const std::shared_ptr &buttonWantAgent, + const std::shared_ptr &buttonDataShareUpdate) { if ((type != ActionButtonType::CLOSE) && (type != ActionButtonType::SNOOZE) && (type != ActionButtonType::CUSTOM)) { ANSR_LOGI("Button type is not support: %{public}d.", static_cast(type)); @@ -195,6 +201,7 @@ ReminderRequest& ReminderRequest::SetActionButton(const std::string &title, cons actionButtonInfo.type = type; actionButtonInfo.title = title; actionButtonInfo.wantAgent = buttonWantAgent; + actionButtonInfo.dataShareUpdate = buttonDataShareUpdate; actionButtonMap_.insert(std::pair(type, actionButtonInfo)); return *this; @@ -600,12 +607,23 @@ void ReminderRequest::RecoverActionButton(const std::shared_ptr(); - if (singleButton.size() == SINGLE_BUTTON_MAX_LEN) { - buttonWantAgent->pkgName = singleButton.at(BUTTON_PKG_INDEX); - buttonWantAgent->abilityName = singleButton.at(BUTTON_ABILITY_INDEX); + auto buttonDataShareUpdate = std::make_shared(); + if (singleButton.size() == SINGLE_BUTTON_WANTAGENT_LEN) { + buttonWantAgent->pkgName = singleButton.at(BUTTON_INDEX_TWO); + buttonWantAgent->abilityName = singleButton.at(BUTTON_INDEX_THREE); + } + if (singleButton.size() == SINGLE_BUTTON_DATASHARE_MIN_LEN) { + buttonDataShareUpdate->uri = singleButton.at(BUTTON_INDEX_TWO); + buttonDataShareUpdate->equalTo = singleButton.at(BUTTON_INDEX_THREE); + buttonDataShareUpdate->valuesBucket = singleButton.at(BUTTON_INDEX_FOUR); + } else if (singleButton.size() == SINGLE_BUTTON_DATASHARE_MAX_LEN) { + buttonDataShareUpdate->uri = singleButton.at(BUTTON_INDEX_FOUR); + buttonDataShareUpdate->equalTo = singleButton.at(BUTTON_INDEX_FIVE); + buttonDataShareUpdate->valuesBucket = singleButton.at(BUTTON_INDEX_SIX); } SetActionButton(singleButton.at(BUTTON_TITLE_INDEX), - ActionButtonType(std::stoi(singleButton.at(BUTTON_TYPE_INDEX), nullptr)), buttonWantAgent); + ActionButtonType(std::stoi(singleButton.at(BUTTON_TYPE_INDEX), nullptr)), + buttonWantAgent, buttonDataShareUpdate); ANSR_LOGI("RecoverButton title:%{public}s, pkgName:%{public}s, abilityName:%{public}s", singleButton.at(BUTTON_TITLE_INDEX).c_str(), buttonWantAgent->pkgName.c_str(), buttonWantAgent->abilityName.c_str()); @@ -1104,6 +1122,22 @@ bool ReminderRequest::Marshalling(Parcel &parcel) const ANSR_LOGE("Failed to write action button abilityName"); return false; } + if (button.second.dataShareUpdate == nullptr) { + ANSR_LOGE("button dataShareUpdate is null"); + return false; + } + if (!parcel.WriteString(button.second.dataShareUpdate->uri)) { + ANSR_LOGE("Failed to write action button dataShareUpdate uri"); + return false; + } + if (!parcel.WriteString(button.second.dataShareUpdate->equalTo)) { + ANSR_LOGE("Failed to write action button dataShareUpdate equalTo"); + return false; + } + if (!parcel.WriteString(button.second.dataShareUpdate->valuesBucket)) { + ANSR_LOGE("Failed to write action button dataShareUpdate valuesBucket"); + return false; + } } return true; } @@ -1258,12 +1292,19 @@ bool ReminderRequest::ReadFromParcel(Parcel &parcel) std::string title = parcel.ReadString(); std::string pkgName = parcel.ReadString(); std::string abilityName = parcel.ReadString(); + std::string uri = parcel.ReadString(); + std::string equalTo = parcel.ReadString(); + std::string valuesBucket = parcel.ReadString(); ActionButtonInfo info; info.type = type; info.title = title; info.wantAgent = std::make_shared(); info.wantAgent->pkgName = pkgName; info.wantAgent->abilityName = abilityName; + info.dataShareUpdate = std::make_shared(); + info.dataShareUpdate->uri = uri; + info.dataShareUpdate->equalTo = equalTo; + info.dataShareUpdate->valuesBucket = valuesBucket; actionButtonMap_.insert(std::pair(type, info)); } if (!InitNotificationRequest()) { @@ -1329,6 +1370,11 @@ std::string ReminderRequest::GetButtonInfo() const } info += (SEP_BUTTON_SINGLE + buttonInfo.wantAgent->pkgName + SEP_BUTTON_SINGLE + buttonInfo.wantAgent->abilityName); + if (buttonInfo.dataShareUpdate == nullptr) { + continue; + } + info += (SEP_BUTTON_SINGLE + buttonInfo.dataShareUpdate->uri + SEP_BUTTON_SINGLE + + buttonInfo.dataShareUpdate->equalTo + SEP_BUTTON_SINGLE + buttonInfo.dataShareUpdate->valuesBucket); isFirst = false; } return info; diff --git a/frameworks/ans/test/unittest/reminder_request_test.cpp b/frameworks/ans/test/unittest/reminder_request_test.cpp index d909f07a8..9d9d07327 100644 --- a/frameworks/ans/test/unittest/reminder_request_test.cpp +++ b/frameworks/ans/test/unittest/reminder_request_test.cpp @@ -1084,6 +1084,46 @@ HWTEST_F(ReminderRequestTest, SetActionButton_00003, Function | SmallTest | Leve reminderRequestChild->SetActionButton(title, type3); } +/** + * @tc.name: SetActionButton_00004 + * @tc.desc: Test SetActionButton parameters. + * @tc.type: FUNC + * @tc.require: issueI65R21 + */ +HWTEST_F(ReminderRequestTest, SetActionButton_00004, Function | SmallTest | Level1) +{ + std::shared_ptr reminderRequestChild = std::make_shared(); + ASSERT_NE(nullptr, reminderRequestChild); + std::string title = "this is title"; + Notification::ReminderRequest::ActionButtonType type2 = + Notification::ReminderRequest::ActionButtonType::CLOSE; + std::shared_ptr buttonWantAgent = + std::make_shared(); + std::shared_ptr buttonDataShareUpdate = + std::make_shared(); + reminderRequestChild->SetActionButton(title, type2, buttonWantAgent, buttonDataShareUpdate); +} + +/** + * @tc.name: SetActionButton_00005 + * @tc.desc: Test SetActionButton parameters. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(ReminderRequestTest, SetActionButton_00005, Function | SmallTest | Level1) +{ + std::shared_ptr reminderRequestChild = std::make_shared(); + ASSERT_NE(nullptr, reminderRequestChild); + std::string title = "this is title"; + Notification::ReminderRequest::ActionButtonType type3 = + Notification::ReminderRequest::ActionButtonType::SNOOZE; + std::shared_ptr buttonWantAgent = + std::make_shared(); + std::shared_ptr buttonDataShareUpdate = + std::make_shared(); + reminderRequestChild->SetActionButton(title, type3, buttonWantAgent, buttonDataShareUpdate); +} + /** * @tc.name: AddActionButtons_00001 * @tc.desc: Test AddActionButtons parameters. diff --git a/frameworks/js/napi/include/reminder/reminder_common.h b/frameworks/js/napi/include/reminder/reminder_common.h index a25febc7b..e0dbcc5ad 100644 --- a/frameworks/js/napi/include/reminder/reminder_common.h +++ b/frameworks/js/napi/include/reminder/reminder_common.h @@ -64,8 +64,15 @@ const char* BUTTON_WANT_AGENT = "wantAgent"; const char* BUTTON_WANT_AGENT_PKG = "pkgName"; const char* BUTTON_WANT_AGENT_ABILITY = "abilityName"; const char* BUTTON_WANT_AGENT_URI = "uri"; +const char* BUTTON_DATA_SHARE_UPDATE = "dataShareUpdate"; +const char* BUTTON_DATA_SHARE_UPDATE_URI = "uri"; +const char* BUTTON_DATA_SHARE_UPDATE_EQUALTO = "equalTo"; +const char* BUTTON_DATA_SHARE_UPDATE_VALUE = "value"; const char* TAPDISMISSED = "tapDismissed"; const char* AUTODELETEDTIME = "autoDeletedTime"; +const int INDEX_ZERO = 0; +const int INDEX_ONE = 1; +const int INDEX_TWO = 2; } struct CallbackPromiseInfo { @@ -156,6 +163,13 @@ private: static void GetButtonWantAgent(const napi_env &env, const napi_value &value, std::shared_ptr& reminder, std::shared_ptr& wantAgent); + static void GetButtonDataShareUpdate(const napi_env &env, const napi_value &value, + std::shared_ptr& reminder, + std::shared_ptr& buttonDataShareUpdate); + static bool GetValueBucketObject(std::string &ValueBucketString, const napi_env &env, const napi_value &arg); + static std::string GetStringFromJS(napi_env env, napi_value param, const std::string &defaultValue = ""); + static std::string Convert2Value(napi_env env, napi_value value, bool &status, std::string &type); + static std::vector Convert2U8Vector(napi_env env, napi_value input_array); static bool IsSelfSystemApp(std::shared_ptr& reminder); }; } // namespace OHOS diff --git a/frameworks/js/napi/src/reminder/publish.cpp b/frameworks/js/napi/src/reminder/publish.cpp index f75cd24f9..cc1751864 100644 --- a/frameworks/js/napi/src/reminder/publish.cpp +++ b/frameworks/js/napi/src/reminder/publish.cpp @@ -17,9 +17,11 @@ #include "ans_log_wrapper.h" #include "common.h" +#include "reminder_request.h" #include "reminder_request_alarm.h" #include "reminder_request_calendar.h" #include "reminder_request_timer.h" +#include "securec.h" namespace OHOS { namespace ReminderAgentNapi { @@ -504,6 +506,126 @@ void ParseReminder( } } +std::vector StringSplit(std::string source, const std::string &split) +{ + std::vector result; + if (source.empty()) { + return result; + } + size_t pos = 0; + while ((pos = source.find(split)) != std::string::npos) { + std::string token = source.substr(0, pos); + if (!token.empty()) { + result.push_back(token); + } + source.erase(0, pos + split.length()); + } + if (!source.empty()) { + result.push_back(source); + } + return result; +} + +napi_status ParseArray(const napi_env &env, std::vector& temp, napi_value &jsObject) +{ + if (temp.size() <= INDEX_TWO) { + return napi_invalid_arg; + } + // key + napi_value keyInfo = nullptr; + napi_create_string_utf8(env, temp[INDEX_ZERO].c_str(), NAPI_AUTO_LENGTH, &keyInfo); + // value + napi_value valueInfo = nullptr; + napi_status status = napi_ok; + if (temp[INDEX_ONE] == "string") { + napi_create_string_utf8(env, temp[INDEX_TWO].c_str(), NAPI_AUTO_LENGTH, &valueInfo); + } else if (temp[INDEX_ONE] == "double") { + napi_create_double(env, std::stod(temp[INDEX_TWO]), &valueInfo); + } else if (temp[INDEX_ONE] == "bool") { + bool valueBool = false; + if (temp[INDEX_TWO] == "1" || temp[INDEX_TWO] == "true" || temp[INDEX_TWO] == "True") { + valueBool = true; + } + napi_get_boolean(env, valueBool, &valueInfo); + } else if (temp[INDEX_ONE] == "null") { + napi_get_null(env, &valueInfo); + } else if (temp[INDEX_ONE] == "vector") { + std::vector arr = StringSplit(temp[INDEX_TWO], ","); + std::vector value; + for (auto &num : arr) { + value.push_back(static_cast(std::stoi(num))); + } + // napi_value <- vector + if (value.size() <= 0) { + return napi_invalid_arg; + } + void* data = nullptr; + napi_value buffer = nullptr; + status = napi_create_arraybuffer(env, value.size(), &data, &buffer); + if (status != napi_ok) { + ANSR_LOGW("create array buffer failed!"); + return napi_invalid_arg; + } + if (memcpy_s(data, value.size(), value.data(), value.size()) != EOK) { + ANSR_LOGW("memcpy_s not EOK"); + return napi_invalid_arg; + } + status = napi_create_typedarray(env, napi_uint8_array, value.size(), buffer, 0, &valueInfo); + if (status != napi_ok) { + ANSR_LOGW("napi_create_typedarray failed!"); + return napi_invalid_arg; + } + } + // write keyInfo and valueInfo + napi_set_property(env, jsObject, keyInfo, valueInfo); + return status; +} + +void ParseValueBucket(const napi_env &env, std::vector valueBucketVector, + napi_value &result, const std::string &arrayName) +{ + // create array + napi_value array = nullptr; + napi_create_array(env, &array); + napi_set_named_property(env, result, arrayName.c_str(), array); + int32_t index = 0; + // write equalTo or valuesBucket + for (auto &str : valueBucketVector) { + std::vector temp = StringSplit(str, ":"); + if (temp.size() <= INDEX_TWO) { + continue; + } + // key:value + napi_value jsObject = nullptr; + napi_create_object(env, &jsObject); + napi_status status = ParseArray(env, temp, jsObject); + if (status != napi_ok) { + continue; + } + // write object to array + napi_set_element(env, array, index++, jsObject); + } +} + +void ParseButtonDataShareUpdate(const napi_env &env, + std::shared_ptr &dataShareUpdate, napi_value &result) +{ + // create obj + napi_value buttonDataShareUpdate = nullptr; + napi_create_object(env, &buttonDataShareUpdate); + napi_set_named_property(env, result, BUTTON_DATA_SHARE_UPDATE, buttonDataShareUpdate); + // uri + napi_value uriInfo = nullptr; + napi_create_string_utf8(env, dataShareUpdate->uri.c_str(), NAPI_AUTO_LENGTH, &uriInfo); + napi_set_named_property(env, buttonDataShareUpdate, BUTTON_DATA_SHARE_UPDATE_URI, uriInfo); + // equalTo + std::vector equalToVector = StringSplit(dataShareUpdate->equalTo, ";"); + ParseValueBucket(env, equalToVector, buttonDataShareUpdate, BUTTON_DATA_SHARE_UPDATE_EQUALTO); + // valuesBucket + std::vector valuesBucketVector = StringSplit(dataShareUpdate->valuesBucket, ";"); + ParseValueBucket(env, valuesBucketVector, buttonDataShareUpdate, BUTTON_DATA_SHARE_UPDATE_VALUE); +} + void ParseActionButtons(const napi_env &env, ReminderRequest &reminder, napi_value &result) { auto actionButtonsMap = reminder.GetActionButtons(); @@ -539,7 +661,11 @@ void ParseActionButtons(const napi_env &env, ReminderRequest &reminder, napi_val napi_create_string_utf8(env, (reminder.GetCustomButtonUri()).c_str(), NAPI_AUTO_LENGTH, &info); napi_set_named_property(env, wantAgentInfo, BUTTON_WANT_AGENT_URI, info); } - + // Parse ButtonDataShareUpdate + if (it->second.type == ReminderRequest::ActionButtonType::CLOSE || + it->second.type == ReminderRequest::ActionButtonType::SNOOZE) { + ParseButtonDataShareUpdate(env, it->second.dataShareUpdate, actionButton); + } // add obj to array napi_set_element(env, array, index, actionButton); index++; diff --git a/frameworks/js/napi/src/reminder/reminder_common.cpp b/frameworks/js/napi/src/reminder/reminder_common.cpp index 69f6c869c..3f978e044 100644 --- a/frameworks/js/napi/src/reminder/reminder_common.cpp +++ b/frameworks/js/napi/src/reminder/reminder_common.cpp @@ -22,6 +22,7 @@ #include "reminder_request_calendar.h" #include "reminder_request_timer.h" #include "tokenid_kit.h" +#include "securec.h" namespace OHOS { namespace ReminderAgentNapi { @@ -88,8 +89,14 @@ bool ReminderCommon::GenActionButtons( if (ReminderRequest::ActionButtonType(buttonType) == ReminderRequest::ActionButtonType::CUSTOM) { GetButtonWantAgent(env, actionButton, reminder, buttonWantAgent); } + // gen buttonDataShareUpdate + auto buttonDataShareUpdate = std::make_shared(); + if (ReminderRequest::ActionButtonType(buttonType) == ReminderRequest::ActionButtonType::CLOSE || + ReminderRequest::ActionButtonType(buttonType) == ReminderRequest::ActionButtonType::SNOOZE) { + GetButtonDataShareUpdate(env, actionButton, reminder, buttonDataShareUpdate); + } reminder->SetActionButton(title, static_cast(buttonType), - buttonWantAgent); + buttonWantAgent, buttonDataShareUpdate); ANSR_LOGD("button title=%{public}s, type=%{public}d", title.c_str(), buttonType); } else { ANSR_LOGW("Parse action button error."); @@ -131,6 +138,197 @@ void ReminderCommon::GetButtonWantAgent(const napi_env &env, const napi_value &v } } +void ReminderCommon::GetButtonDataShareUpdate(const napi_env &env, const napi_value &value, + std::shared_ptr& reminder, + std::shared_ptr& buttonDataShareUpdate) +{ + napi_value dataShare = nullptr; + if (GetObject(env, value, BUTTON_DATA_SHARE_UPDATE, dataShare)) { + // dataShare uri + char str[NotificationNapi::STR_MAX_SIZE] = {0}; + if (GetStringUtf8(env, dataShare, BUTTON_DATA_SHARE_UPDATE_URI, str, NotificationNapi::STR_MAX_SIZE)) { + ANSR_LOGD("gen dataShareUri success"); + buttonDataShareUpdate->uri = str; + } + // dataShare equalTo + napi_value equalTo = nullptr; + std::string valueBucketString; + if (GetObject(env, dataShare, BUTTON_DATA_SHARE_UPDATE_EQUALTO, equalTo)) { + if (GetValueBucketObject(valueBucketString, env, equalTo)) { + ANSR_LOGD("gen dataShareEqualTo success"); + buttonDataShareUpdate->equalTo = valueBucketString; + } + } + // dataShare valuesBucket + napi_value valuesBucket = nullptr; + valueBucketString.clear(); + if (GetObject(env, dataShare, BUTTON_DATA_SHARE_UPDATE_VALUE, valuesBucket)) { + if (GetValueBucketObject(valueBucketString, env, valuesBucket)) { + ANSR_LOGD("gen dataShareValuesBucket success"); + buttonDataShareUpdate->valuesBucket = valueBucketString; + } + } + } +} + +bool ReminderCommon::GetValueBucketObject(std::string &valueBucketString, const napi_env &env, const napi_value &arg) +{ + // arrary + napi_value keys = 0; + napi_get_property_names(env, arg, &keys); + uint32_t arrlen = 0; + napi_status status = napi_get_array_length(env, keys, &arrlen); + if (status != napi_ok) { + ANSR_LOGW("valuesBucket err"); + return false; + } + for (size_t i = 0; i < arrlen; ++i) { + // key + napi_value key = 0; + status = napi_get_element(env, keys, i, &key); + if (status != napi_ok) { + ANSR_LOGW("valuesBucket err"); + continue; + } + std::string keyStr = GetStringFromJS(env, key); + // value + napi_value value = 0; + napi_get_property(env, arg, key, &value); + bool ret; + std::string type; + std::string valueObject = Convert2Value(env, value, ret, type); + if (!ret) { + ANSR_LOGW("valuesBucket err"); + continue; + } + valueBucketString += keyStr + ":" + type + ":" + valueObject; + if (i < arrlen - 1) { + valueBucketString += ";"; + } + } + return true; +} + +std::string ReminderCommon::GetStringFromJS(napi_env env, napi_value param, const std::string &defaultValue) +{ + size_t size = 0; + if (napi_get_value_string_utf8(env, param, nullptr, 0, &size) != napi_ok) { + return defaultValue; + } + std::string value(""); + if (size == 0) { + return defaultValue; + } + + char *buf = new (std::nothrow) char[size + 1]; + if (buf == nullptr) { + return value; + } + (void)memset_s(buf, size + 1, 0, size + 1); + bool rev = napi_get_value_string_utf8(env, param, buf, size + 1, &size) == napi_ok; + if (rev) { + value = buf; + } else { + value = defaultValue; + } + + if (buf != nullptr) { + delete[] buf; + buf = nullptr; + } + return value; +} + +std::string ReminderCommon::Convert2Value(napi_env env, napi_value value, bool &status, std::string &type) +{ + // array type + napi_valuetype valueType = napi_undefined; + napi_typeof(env, value, &valueType); + status = true; + // gen value + std::string valueString; + std::vector valueBlob; + switch (valueType) { + case napi_null: { + type = "null"; + valueString = type; + break; + } + case napi_boolean: { + type = "bool"; + bool valueBool = false; + napi_get_value_bool(env, value, &valueBool); + valueString = std::to_string(valueBool); + break; + } + case napi_number: { + type = "double"; + double valueNumber = 0; + napi_get_value_double(env, value, &valueNumber); + valueString = std::to_string(valueNumber); + break; + } + case napi_string: { + type = "string"; + valueString = GetStringFromJS(env, value); + break; + } + case napi_object: { + type = "vector"; + valueBlob = Convert2U8Vector(env, value); + for (auto it = valueBlob.begin(); it != valueBlob.end(); ++it) { + valueString += std::to_string(*it); + if (it != valueBlob.end()) { + valueString += ","; + } + } + break; + } + default: { + ANSR_LOGE("Convert2Value err"); + status = false; + break; + } + } + return valueString; +} + +std::vector ReminderCommon::Convert2U8Vector(napi_env env, napi_value input_array) +{ + bool isTypedArray = false; + bool isArrayBuffer = false; + // type is array? + napi_is_typedarray(env, input_array, &isTypedArray); + if (!isTypedArray) { + // buffer whether or not it exists? + napi_is_arraybuffer(env, input_array, &isArrayBuffer); + if (!isArrayBuffer) { + ANSR_LOGE("unknow type"); + return {}; + } + } + size_t length = 0; + void *data = nullptr; + // get array + if (isTypedArray) { + napi_typedarray_type type; + napi_value input_buffer = nullptr; + size_t byte_offset = 0; + napi_get_typedarray_info(env, input_array, &type, &length, &data, &input_buffer, &byte_offset); + if (type != napi_uint8_array || data == nullptr) { + ANSR_LOGW("napi_get_typedarray_info err"); + return {}; + } + } else { + napi_get_arraybuffer_info(env, input_array, &data, &length); + if (data == nullptr || length <= 0) { + ANSR_LOGW("napi_get_arraybuffer_info err"); + return {}; + } + } + return std::vector((uint8_t *)data, ((uint8_t *)data) + length); +} + bool ReminderCommon::GenWantAgent( const napi_env &env, const napi_value &value, std::shared_ptr& reminder, bool isSysApp) { diff --git a/interfaces/inner_api/reminder_request.h b/interfaces/inner_api/reminder_request.h index 3cec37b15..f9a3eb696 100644 --- a/interfaces/inner_api/reminder_request.h +++ b/interfaces/inner_api/reminder_request.h @@ -110,6 +110,11 @@ public: std::string abilityName = ""; }; + struct ButtonDataShareUpdate { + std::string uri = ""; + std::string equalTo = ""; + std::string valuesBucket = ""; + }; /** * @brief Attributes of action button. */ @@ -128,6 +133,10 @@ public: * The ability that is redirected to when the button is clicked. */ std::shared_ptr wantAgent; + /** + * The ability that is updata App rdb. + */ + std::shared_ptr dataShareUpdate; }; /** @@ -450,7 +459,8 @@ public: * @return Current reminder self. */ ReminderRequest& SetActionButton(const std::string &title, const ActionButtonType &type, - const std::shared_ptr &buttonWantAgent = nullptr); + const std::shared_ptr &buttonWantAgent = nullptr, + const std::shared_ptr &buttonDataShareUpdate = nullptr); /** * @brief Sets reminder content. diff --git a/services/ans/BUILD.gn b/services/ans/BUILD.gn index edc6d381a..1fe187cdc 100644 --- a/services/ans/BUILD.gn +++ b/services/ans/BUILD.gn @@ -87,6 +87,8 @@ ohos_shared_library("libans") { "access_token:libaccesstoken_sdk", "access_token:libtokenid_sdk", "c_utils:utils", + "data_share:datashare_common", + "data_share:datashare_consumer", "device_manager:devicemanagersdk", "ffrt:libffrt", "hitrace:hitrace_meter", diff --git a/services/ans/include/reminder_data_manager.h b/services/ans/include/reminder_data_manager.h index 7b37c57a9..b6022cf49 100644 --- a/services/ans/include/reminder_data_manager.h +++ b/services/ans/include/reminder_data_manager.h @@ -27,6 +27,8 @@ #include "reminder_request.h" #include "reminder_store.h" #include "reminder_timer_info.h" +#include "datashare_predicates.h" +#include "datashare_values_bucket.h" namespace OHOS { namespace Notification { @@ -207,6 +209,48 @@ private: void CancelAllReminders(const int32_t &userId); + /** + * @brief update app database. + * + * @param reminder Indicates the showed reminder. + * @param actionButtonType Button type of the button. + */ + void UpdateAppStore(const sptr &reminder, + const ReminderRequest::ActionButtonType &actionButtonType); + + /** + * @brief generate Predicates for dataShare. + * + * @param predicates find fields from database. + * @param equalToVector Split from dataShareUpdate->equaleTo. + */ + void GenPredicates(DataShare::DataSharePredicates &predicates, const std::vector &equalToVector); + + /** + * @brief generate ValuesBucket for dataShare. + * + * @param valuesBucket update fields at database. + * @param valuesBucketVector Split from dataShareUpdate->valuesBucket. + */ + void GenValuesBucket(DataShare::DataShareValuesBucket &valuesBucket, + const std::vector &valuesBucketVector); + + /** + * @brief get bundleName from uri. + * + * @param dstBundleName The package name required to update the database. + * @param uri Database address. + */ + void GenDstBundleName(std::string &dstBundleName, const std::string &uri) const; + + /** + * @brief Split string. + * + * @param source The string to split. + * @param split separator. + * @return Split the results. + */ + std::vector StringSplit(std::string source, const std::string &split) const; /** * @brief Cancels all the reminders of the target bundle or user. * diff --git a/services/ans/src/reminder_data_manager.cpp b/services/ans/src/reminder_data_manager.cpp index a2c646ab5..7e5615938 100644 --- a/services/ans/src/reminder_data_manager.cpp +++ b/services/ans/src/reminder_data_manager.cpp @@ -30,6 +30,10 @@ #include "reminder_event_manager.h" #include "time_service_client.h" #include "singleton.h" +#include "datashare_predicates_object.h" +#include "datashare_value_object.h" +#include "datashare_helper.h" +#include "datashare_template.h" namespace OHOS { namespace Notification { @@ -39,6 +43,9 @@ const int32_t MAIN_USER_ID = 100; #ifdef DEVICE_STANDBY_ENABLE const int REASON_APP_API = 1; #endif +const int INDEX_ZERO = 0; +const int INDEX_ONE = 1; +const int INDEX_TWO = 2; } /** @@ -491,6 +498,7 @@ void ReminderDataManager::CloseReminder(const sptr &reminder, b } reminder->OnClose(true); RemoveFromShowedReminders(reminder); + UpdateAppStore(reminder, ReminderRequest::ActionButtonType::CLOSE); store_->UpdateOrInsert(reminder, FindNotificationBundleOption(reminder->GetReminderId())); if (cancelNotification) { CancelNotification(reminder); @@ -513,6 +521,166 @@ std::shared_ptr ReminderDataManager::InitInstance( return REMINDER_DATA_MANAGER; } +void ReminderDataManager::UpdateAppStore(const sptr &reminder, + const ReminderRequest::ActionButtonType &actionButtonType) +{ + if (!reminder->IsSystemApp()) { + ANSR_LOGI("UpdateAppStore faild, is not SystemApp"); + return; + } + if (actionButtonType == ReminderRequest::ActionButtonType::CUSTOM || + actionButtonType == ReminderRequest::ActionButtonType::INVALID) { + ANSR_LOGI("actionButtonType is CUSTOM or INVALID"); + return; + } + auto actionButtonMap = reminder->GetActionButtons(); + if (actionButtonMap.at(actionButtonType).dataShareUpdate == nullptr) { + ANSR_LOGI("dataShareUpdate is null"); + return; + } + if (actionButtonMap.at(actionButtonType).dataShareUpdate->uri == "" || + actionButtonMap.at(actionButtonType).dataShareUpdate->equalTo == "" || + actionButtonMap.at(actionButtonType).dataShareUpdate->valuesBucket == "") { + ANSR_LOGI("not have uri"); + return; + } + // init default dstBundleName + std::string dstBundleName; + auto mit = notificationBundleOptionMap_.find(reminder->GetReminderId()); + if (mit != notificationBundleOptionMap_.end()) { + dstBundleName = mit->second->GetBundleName(); + } + GenDstBundleName(dstBundleName, actionButtonMap.at(actionButtonType).dataShareUpdate->uri); + + DataShare::CreateOptions options; + options.enabled_ = true; + auto userID = reminder->GetUserId(); + auto tokenID = IPCSkeleton::GetSelfTokenID(); + std::string uriStr = actionButtonMap.at(actionButtonType).dataShareUpdate->uri + "?user=" + std::to_string(userID) + + "&srcToken=" + std::to_string(tokenID) + "&dstBundleName=" + dstBundleName; + + // create datashareHelper + std::shared_ptr dataShareHelper = DataShare::DataShareHelper::Creator(uriStr, options); + if (dataShareHelper == nullptr) { + ANSR_LOGE("create datashareHelper failed"); + return; + } + // gen uri equalTo valuesBucket + Uri uri(uriStr); + + DataShare::DataSharePredicates predicates; + std::vector equalToVector = + StringSplit(actionButtonMap.at(actionButtonType).dataShareUpdate->equalTo, ";"); + GenPredicates(predicates, equalToVector); + + DataShare::DataShareValuesBucket valuesBucket; + std::vector valuesBucketVector = + StringSplit(actionButtonMap.at(actionButtonType).dataShareUpdate->valuesBucket, ";"); + GenValuesBucket(valuesBucket, valuesBucketVector); + + // update app store + int retVal = dataShareHelper->Update(uri, predicates, valuesBucket); + if (retVal > 0) { + // update success + ANSR_LOGI("update app store success retval:%{public}d", retVal); + } +} + +void ReminderDataManager::GenPredicates(DataShare::DataSharePredicates & predicates, + const std::vector &equalToVector) +{ + // predicates + for (auto &it : equalToVector) { + std::vector temp = StringSplit(it, ":"); + if (temp.size() <= INDEX_TWO) { + continue; + } + if (temp[INDEX_ONE] == "string") { + predicates.EqualTo(temp[INDEX_ZERO], temp[INDEX_TWO]); + } else if (temp[INDEX_ONE] == "double") { + predicates.EqualTo(temp[INDEX_ZERO], std::stod(temp[INDEX_TWO])); + } else if (temp[INDEX_ONE] == "bool") { + bool valueBool = false; + if (temp[INDEX_TWO] == "1" || temp[INDEX_TWO] == "true" || temp[INDEX_TWO] == "True") { + valueBool = true; + } + predicates.EqualTo(temp[INDEX_ZERO], valueBool); + } + } +} + +void ReminderDataManager::GenValuesBucket(DataShare::DataShareValuesBucket & valuesBucket, + const std::vector &valuesBucketVector) +{ + // valuesBucket + for (auto &it : valuesBucketVector) { + std::vector temp = StringSplit(it, ":"); + if (temp.size() <= INDEX_TWO) { + continue; + } + if (temp[INDEX_ONE] == "string") { + valuesBucket.Put(temp[INDEX_ZERO], temp[INDEX_TWO]); + } else if (temp[INDEX_ONE] == "double") { + valuesBucket.Put(temp[INDEX_ZERO], std::stod(temp[INDEX_TWO])); + } else if (temp[INDEX_ONE] == "bool") { + bool valueBool = false; + if (temp[INDEX_TWO] == "1" || temp[INDEX_TWO] == "true" || temp[INDEX_TWO] == "True") { + valueBool = true; + } + valuesBucket.Put(temp[INDEX_ZERO], valueBool); + } else if (temp[INDEX_ONE] == "null") { + valuesBucket.Put(temp[INDEX_ZERO]); + } else if (temp[INDEX_ONE] == "vector") { + std::vector arr = StringSplit(temp[INDEX_TWO], ","); + std::vector value; + for (auto &num : arr) { + value.push_back(static_cast(std::stoi(num))); + } + valuesBucket.Put(temp[INDEX_ZERO], value); + } + } +} + +std::vector ReminderDataManager::StringSplit(std::string source, const std::string &split) const +{ + std::vector result; + if (source.empty()) { + return result; + } + size_t pos = 0; + while ((pos = source.find(split)) != std::string::npos) { + std::string token = source.substr(0, pos); + if (!token.empty()) { + result.push_back(token); + } + source.erase(0, pos + split.length()); + } + if (!source.empty()) { + result.push_back(source); + } + return result; +} + +void ReminderDataManager::GenDstBundleName(std::string &dstBundleName, const std::string &uri) const +{ + size_t left = 0; + size_t right = 0; + left = uri.find("/", left); + right = uri.find("/", left + 1); + while (right != std::string::npos && right - left <= 1) { + left = right + 1; + right = uri.find("/", left); + } + if (left == std::string::npos) { + return; + } + if (right != std::string::npos) { + dstBundleName = uri.substr(left, right - left); + } else { + dstBundleName = uri.substr(left); + } +} + void ReminderDataManager::RefreshRemindersDueToSysTimeChange(uint8_t type) { std::string typeInfo = type == TIME_ZONE_CHANGE ? "timeZone" : "dateTime"; @@ -838,6 +1006,7 @@ void ReminderDataManager::SnoozeReminderImpl(sptr &reminder) StopTimerLocked(TimerType::ALERTING_TIMER); } reminder->OnSnooze(); + UpdateAppStore(reminder, ReminderRequest::ActionButtonType::SNOOZE); store_->UpdateOrInsert(reminder, FindNotificationBundleOption(reminder->GetReminderId())); // 2) Show the notification dialog in the systemUI diff --git a/services/ans/test/unittest/BUILD.gn b/services/ans/test/unittest/BUILD.gn index c060b245f..a6cffabcc 100644 --- a/services/ans/test/unittest/BUILD.gn +++ b/services/ans/test/unittest/BUILD.gn @@ -63,6 +63,8 @@ ohos_unittest("reminder_unit_test") { "bundle_framework:appexecfwk_core", "c_utils:utils", "common_event_service:cesfwk_innerkits", + "data_share:datashare_common", + "data_share:datashare_consumer", "device_manager:devicemanagersdk", "eventhandler:libeventhandler", "ffrt:libffrt", @@ -310,6 +312,8 @@ ohos_unittest("notification_preferences_test") { "bundle_framework:appexecfwk_core", "c_utils:utils", "common_event_service:cesfwk_innerkits", + "data_share:datashare_common", + "data_share:datashare_consumer", "device_manager:devicemanagersdk", "eventhandler:libeventhandler", "ffrt:libffrt", -- Gitee