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