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 "core/common/ai/ai_write_adapter.h" 17 18#include "array_wrapper.h" 19#include "bool_wrapper.h" 20#include "int_wrapper.h" 21#include "want.h" 22#include "want_params.h" 23#include "core/components_ng/layout/layout_property.h" 24#include "core/components_ng/pattern/text/span/span_string.h" 25#include "core/components_ng/pattern/ui_extension/session_wrapper.h" 26#include "core/components_ng/pattern/ui_extension/session_wrapper_factory.h" 27#include "core/components_ng/pattern/ui_extension/ui_extension_pattern.h" 28#include "core/components_ng/pattern/ui_extension/modal_ui_extension_proxy_impl.h" 29 30namespace OHOS::Ace { 31const std::pair<std::string, std::string> UI_ENTENSION_TYPE = {"ability.want.params.uiExtensionType", "sys/commonUI"}; 32const std::wstring BOUNDARY_SYMBOLS = L",.?,。?!"; 33const std::string API_VERSION = "apiVersion"; 34const std::string RESULT_BUFFER = "resultBuffer"; 35const std::string SHEET_DISMISS = "sheetDismiss"; 36const std::string PROCESS_ID = "processId"; 37const std::string MAX_CONTENT_LENGTH = "maxContentLength"; 38const std::string FIRST_HANDLE_RECT = "firstHandleRect"; 39const std::string SECOND_HANDLE_RECT = "secondHandleRect"; 40const std::string IS_AI_SUPPORT_METADATA = "isAiSupport"; 41const std::string SELECT_CONTENT_LENGTH = "selectContentLength"; 42const std::string REQUEST_LONG_CONTENT = "requestLongContent"; 43const std::string LONG_SENTENCE_BUFFER = "longSentenceBuffer"; 44const std::string LONG_SELECT_START = "longSelectStart"; 45const std::string LONG_SELECT_END = "longSelectEnd"; 46const std::string KEY_PACKAGE_NAME = "keyPackageApp"; 47const std::string START_COMPONONT_TYPE = "startComponentType"; 48 49bool AIWriteAdapter::IsSentenceBoundary(const wchar_t value) 50{ 51 for (wchar_t item: BOUNDARY_SYMBOLS) { 52 if (value == item) { 53 return true; 54 } 55 } 56 return false; 57} 58 59uint32_t AIWriteAdapter::GetSelectLengthOnlyText(const std::wstring& content) 60{ 61 uint32_t length = 0; 62 for (uint32_t i = 0; i < content.length(); i++) { 63 if (content[i] != L' ' && content[i] != L'\n') { 64 length++; 65 } 66 } 67 return length; 68} 69 70void AIWriteAdapter::CloseModalUIExtension() 71{ 72 TAG_LOGI(AceLogTag::ACE_RICH_TEXT, "CloseModalUIExtension."); 73 auto context = pipelineContext_.Upgrade(); 74 CHECK_NULL_VOID(context); 75 auto overlayManager = context->GetOverlayManager(); 76 CHECK_NULL_VOID(overlayManager); 77 overlayManager->CloseModalUIExtension(sessionId_); 78 SetAIWrite(false); 79} 80 81void AIWriteAdapter::ShowModalUIExtension(const AIWriteInfo& info, 82 std::function<void(std::vector<uint8_t>&)> resultCallback) 83{ 84 TAG_LOGI(AceLogTag::ACE_RICH_TEXT, "ShowModalUIExtension."); 85 AAFwk::Want want; 86 SetWantParams(info, want); 87 Ace::ModalUIExtensionCallbacks callbacks; 88 BindModalUIExtensionCallback(callbacks, resultCallback); 89 90 auto context = pipelineContext_.Upgrade(); 91 CHECK_NULL_VOID(context); 92 auto overlayManager = context->GetOverlayManager(); 93 CHECK_NULL_VOID(overlayManager); 94 Ace::ModalUIExtensionConfig config; 95 sessionId_ = overlayManager->CreateModalUIExtension(want, callbacks, config); 96 aiWriteInfo_ = info; 97} 98 99void AIWriteAdapter::SetWantParams(const AIWriteInfo& info, AAFwk::Want& want) 100{ 101 auto apiVersion = AceApplicationInfo::GetInstance().GetApiTargetVersion(); 102 want.SetElementName(bundleName_, abilityName_); 103 want.SetParam(UI_ENTENSION_TYPE.first, UI_ENTENSION_TYPE.second); 104 want.SetParam(API_VERSION, static_cast<int>(apiVersion)); 105 want.SetParam(PROCESS_ID, getpid()); 106 want.SetParam(MAX_CONTENT_LENGTH, info.maxLength); 107 want.SetParam(SELECT_CONTENT_LENGTH, info.selectLength); 108 want.SetParam(FIRST_HANDLE_RECT, info.firstHandle); 109 want.SetParam(SECOND_HANDLE_RECT, info.secondHandle); 110 want.SetParam(KEY_PACKAGE_NAME, AceApplicationInfo::GetInstance().GetPackageName()); 111 want.SetParam(START_COMPONONT_TYPE, info.componentType); 112} 113 114void AIWriteAdapter::BindModalUIExtensionCallback( 115 Ace::ModalUIExtensionCallbacks& callbacks, std::function<void(std::vector<uint8_t>&)> resultCallback) 116{ 117 callbacks.onResult = [](int32_t code, const AAFwk::Want& want) { 118 TAG_LOGD(AceLogTag::ACE_UIEXTENSIONCOMPONENT, "UIExtension onResult, code: %{public}d", code); 119 }; 120 callbacks.onDestroy = [weak = WeakClaim(this)]() { 121 TAG_LOGD(AceLogTag::ACE_UIEXTENSIONCOMPONENT, "UIExtension onDestroy."); 122 auto aiWriteAdapter = weak.Upgrade(); 123 CHECK_NULL_VOID(aiWriteAdapter); 124 aiWriteAdapter->CloseModalUIExtension(); 125 }; 126 callbacks.onError = [weak = WeakClaim(this)](int32_t code, const std::string& name, const std::string& message) { 127 TAG_LOGE(AceLogTag::ACE_UIEXTENSIONCOMPONENT, 128 "UIExtension onError, code: %{public}d, name: %{public}s, message: %{public}s", 129 code, name.c_str(), message.c_str()); 130 auto aiWriteAdapter = weak.Upgrade(); 131 CHECK_NULL_VOID(aiWriteAdapter); 132 aiWriteAdapter->CloseModalUIExtension(); 133 }; 134 callbacks.onRelease = [](int32_t code) { 135 TAG_LOGD(AceLogTag::ACE_UIEXTENSIONCOMPONENT, "UIExtension onRelease, code: %{public}d", code); 136 }; 137 callbacks.onRemoteReady = [weak = WeakClaim(this)](const std::shared_ptr<Ace::ModalUIExtensionProxy>& proxy) { 138 TAG_LOGD(AceLogTag::ACE_UIEXTENSIONCOMPONENT, "UIExtension onRemoteReady."); 139 auto aiWriteAdapter = weak.Upgrade(); 140 CHECK_NULL_VOID(aiWriteAdapter); 141 aiWriteAdapter->SetModalUIExtensionProxy(proxy); 142 }; 143 callbacks.onReceive = [weak = WeakClaim(this), cb = std::move(resultCallback)] 144 (const AAFwk::WantParams& wantParams) { 145 auto aiWriteAdapter = weak.Upgrade(); 146 CHECK_NULL_VOID(aiWriteAdapter); 147 auto isSheetClose = false; 148 auto isRequest = false; 149 auto result = aiWriteAdapter->GetBufferParam(RESULT_BUFFER, wantParams); 150 isSheetClose = aiWriteAdapter->GetBoolParam(SHEET_DISMISS, wantParams); 151 isRequest = aiWriteAdapter->GetBoolParam(REQUEST_LONG_CONTENT, wantParams); 152 if (isRequest) { 153 aiWriteAdapter->SendData(); 154 return; 155 } 156 if (cb && !result.empty()) { 157 cb(result); 158 return; 159 } 160 if (isSheetClose) { 161 aiWriteAdapter->CloseModalUIExtension(); 162 } 163 }; 164} 165 166void AIWriteAdapter::SendData() 167{ 168 auto proxy = GetModalUIExtensionProxy(); 169 AAFwk::WantParams wantParams; 170 SetArrayParam(wantParams, LONG_SENTENCE_BUFFER, aiWriteInfo_.sentenceBuffer); 171 wantParams.SetParam(LONG_SELECT_START, AAFwk::Integer::Box(aiWriteInfo_.start)); 172 wantParams.SetParam(LONG_SELECT_END, AAFwk::Integer::Box(aiWriteInfo_.end)); 173 proxy->SendData(wantParams); 174} 175 176void AIWriteAdapter::SetArrayParam( 177 AAFwk::WantParams& wantParams, const std::string& key, const std::vector<uint8_t>& value) 178{ 179 std::vector<int> valueVec(value.size()); 180 std::transform(value.begin(), value.end(), valueVec.begin(), 181 [](uint8_t x) { return static_cast<int>(x); }); 182 size_t size = valueVec.size(); 183 sptr<AAFwk::IArray> ao = new (std::nothrow) AAFwk::Array(size, AAFwk::g_IID_IInteger); 184 if (ao == nullptr) { 185 return; 186 } 187 for (size_t i = 0; i < size; i++) { 188 ao->Set(i, AAFwk::Integer::Box(value[i])); 189 } 190 wantParams.SetParam(key, ao); 191} 192 193std::vector<uint8_t> AIWriteAdapter::GetBufferParam(const std::string& key, const AAFwk::WantParams& wantParams) 194{ 195 std::vector<uint8_t> array; 196 auto value = wantParams.GetParam(key); 197 AAFwk::IArray *ao = AAFwk::IArray::Query(value); 198 if (ao != nullptr && AAFwk::Array::IsIntegerArray(ao)) { 199 auto func = [&](AAFwk::IInterface *object) { 200 CHECK_NULL_VOID(object); 201 AAFwk::IInteger *value = AAFwk::IInteger::Query(object); 202 CHECK_NULL_VOID(value); 203 array.emplace_back(AAFwk::Integer::Unbox(value)); 204 }; 205 AAFwk::Array::ForEach(ao, func); 206 } 207 return array; 208} 209 210bool AIWriteAdapter::GetBoolParam(const std::string& key, const AAFwk::WantParams& wantParams) 211{ 212 auto value = wantParams.GetParam(key); 213 AAFwk::IBoolean *bo = AAFwk::IBoolean::Query(value); 214 if (bo != nullptr) { 215 return AAFwk::Boolean::Unbox(bo); 216 } 217 return false; 218} 219}