From 7570eb1d5625d7e15138da6ad41194287e93c567 Mon Sep 17 00:00:00 2001 From: zhaoshenghua Date: Wed, 15 Jan 2025 10:17:52 +0800 Subject: [PATCH 1/3] impl cj picker ffi Signed-off-by: zhaoshenghua --- interfaces/kits/picker/BUILD.gn | 43 ++++ interfaces/kits/picker/cj/include/cj_picker.h | 81 ++++++ interfaces/kits/picker/cj/src/cj_picker.cpp | 241 ++++++++++++++++++ 3 files changed, 365 insertions(+) create mode 100644 interfaces/kits/picker/cj/include/cj_picker.h create mode 100644 interfaces/kits/picker/cj/src/cj_picker.cpp diff --git a/interfaces/kits/picker/BUILD.gn b/interfaces/kits/picker/BUILD.gn index 664cb8ae..f1a464fe 100644 --- a/interfaces/kits/picker/BUILD.gn +++ b/interfaces/kits/picker/BUILD.gn @@ -103,3 +103,46 @@ ohos_shared_library("picker") { subsystem_name = "filemanagement" part_name = "user_file_service" } + +ohos_shared_library("cj_picker_ffi") { + branch_protector_ret = "pac_ret" + ldflags = [ "-Wl" ] + + include_dirs = [ "cj/include" ] + + sources = [ + "cj/src/cj_picker.cpp", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_context_native", + "ability_runtime:ability_manager", + "ability_runtime:abilitykit_native", + "ability_runtime:app_context", + "ability_runtime:dataobs_manager", + "ability_runtime:runtime", + "ability_runtime:service_extension", + "ability_runtime:ui_extension", + "ace_engine:ace_uicontent", + "file_api:filemgmt_libhilog", + "file_api:filemgmt_libn", + "hilog:libhilog", + "napi:cj_bind_ffi", + "napi:cj_bind_native", + ] + + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + + innerapi_tags = [ "platformsdk" ] + subsystem_name = "filemanagement" + part_name = "user_file_service" +} diff --git a/interfaces/kits/picker/cj/include/cj_picker.h b/interfaces/kits/picker/cj/include/cj_picker.h new file mode 100644 index 00000000..c81043fb --- /dev/null +++ b/interfaces/kits/picker/cj/include/cj_picker.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef INTERFACES_KITS_CJ_PICKER_H +#define INTERFACES_KITS_CJ_PICKER_H + +#include +#include +#include +#include +#include "cj_lambda.h" +#include "cj_common_ffi.h" +#include "context.h" +#include "data_ability_helper.h" +#include "data_ability_observer_stub.h" +#include "data_ability_predicates.h" +#include "filemgmt_libn.h" +#include "ui_extension_context.h" +#include "ability_context.h" +#include "want.h" +#include "want_params.h" +#include "ui_content.h" +#include "hilog_wrapper.h" + +namespace OHOS { +namespace CjPicker { + +using WantHandle = void*; +static sptr window_; + +struct CjPickerCallBack { + bool ready = false; + int32_t resultCode; + OHOS::AAFwk::Want want; +}; + +extern "C" { +struct PickerResult { + int32_t resultCode; + int32_t userSuffixIndex; + bool isOriginal; + CArrString ability_params_stream; + CArrString uriArr; + CArrString photoUris; +}; + +FFI_EXPORT int32_t FfiOHOSFilePickerModalPicker(OHOS::AbilityRuntime::Context* context, WantHandle config, char* windowName, void (*callback)(PickerResult)); +} + +class CjModalUICallback { +public: + explicit CjModalUICallback(Ace::UIContent* uiContent, std::shared_ptr pickerCallBack, void (*callback)(PickerResult)); + void OnRelease(int32_t releaseCode); + void OnResultForModal(int32_t resultCode, const OHOS::AAFwk::Want& result); + void OnReceive(const OHOS::AAFwk::WantParams& request); + void OnError(int32_t code, const std::string& name, const std::string& message); + void OnDestroy(); + void SetSessionId(int32_t sessionId); + +private: + int32_t sessionId_ = 0; + std::function callback{nullptr}; + Ace::UIContent* uiContent; + std::shared_ptr pickerCallBack_; +}; + +} // namespace CjPicker +} // namespace OHOS + +#endif // INTERFACES_KITS_CJ_PICKER_H \ No newline at end of file diff --git a/interfaces/kits/picker/cj/src/cj_picker.cpp b/interfaces/kits/picker/cj/src/cj_picker.cpp new file mode 100644 index 00000000..025ff428 --- /dev/null +++ b/interfaces/kits/picker/cj/src/cj_picker.cpp @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define ABILITY_WANT_PARAMS_UIEXTENSIONTARGETTYPE "ability.want.params.uiExtensionTargetType" + +#include "cj_picker.h" + +#include "modal_ui_extension_config.h" +#include "ability.h" +#include "ui_extension_context.h" + +namespace OHOS { +namespace CjPicker { + +using namespace OHOS::Ace; + +const int32_t ERR_OK = 0; +const int32_t ERR_INVALID_ARG = 13900020; +const int32_t ERR_INV = -1; + +static Ace::UIContent* GetUIContextByContext(OHOS::AbilityRuntime::Context* context) +{ + auto contextsptr = context->shared_from_this(); + auto abilityContext = AbilityRuntime::Context::ConvertTo(contextsptr); + if (abilityContext == nullptr) { + auto uiExtensionContext = AbilityRuntime::Context::ConvertTo(contextsptr); + if (uiExtensionContext == nullptr) { + HILOG_ERROR("[picker]: Fail to convert to abilityContext or uiExtensionContext"); + return nullptr; + } + return uiExtensionContext->GetUIContent(); + } + return abilityContext->GetUIContent(); +} + +static int32_t StartCjPickerExtension(OHOS::AbilityRuntime::Context* context, WantHandle want, void (*cjCallback)(PickerResult)) +{ + HILOG_INFO("[picker]: StartPickerExtension begin."); + Ace::UIContent *uiContent; + if (window_) { + HILOG_INFO("[picker] Will get uiContent by window."); + uiContent = window_->GetUIContent(); + } else { + HILOG_INFO("[picker] Will get uiContent by context."); + uiContent = GetUIContextByContext(context); + } + + if (uiContent == nullptr) { + HILOG_ERROR("[picker]: get uiContent failed"); + return ERR_INVALID_ARG; + } + AAFwk::Want request = *reinterpret_cast(want); + + std::string targetType = request.GetStringParam("extType"); + std::string pickerType; + if (request.GetParams().HasParam("pickerType")) { + pickerType = request.GetStringParam("pickerType"); + } + request.SetParam(ABILITY_WANT_PARAMS_UIEXTENSIONTARGETTYPE, targetType); + auto pickerCallback = std::make_shared(); + auto callback = std::make_shared(uiContent, pickerCallback, cjCallback); + Ace::ModalUIExtensionCallbacks extensionCallback = { + .onRelease = std::bind(&CjModalUICallback::OnRelease, callback, std::placeholders::_1), + .onResult = std::bind(&CjModalUICallback::OnResultForModal, callback, std::placeholders::_1, + std::placeholders::_2), + .onReceive = std::bind(&CjModalUICallback::OnReceive, callback, std::placeholders::_1), + .onError = std::bind(&CjModalUICallback::OnError, callback, std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3), + .onDestroy = std::bind(&CjModalUICallback::OnDestroy, callback), + }; + Ace::ModalUIExtensionConfig config; + config.prohibitedRemoveByNavigation = false; + config.prohibitedRemoveByRouter = false; + HILOG_INFO("[picker]: will CreateModalUIExtension by extType: %{public}s, pickerType: %{public}s", + targetType.c_str(), pickerType.c_str()); + int sessionId = uiContent->CreateModalUIExtension(request, extensionCallback, config); + if (sessionId == 0) { + HILOG_ERROR("[picker]: create modalUIExtension failed"); + return ERR_INVALID_ARG; + } + callback->SetSessionId(sessionId); + return ERR_OK; +} + +static int32_t GetWindow(char* windowName, sptr &window) +{ + auto customWindow = Rosen::Window::Find(windowName); + if (!customWindow) { + HILOG_ERROR("[picker] Window find fail."); + return ERR_INV; + } + window = customWindow; + HILOG_INFO("[picker] Window found: %{public}s", windowName); + return ERR_OK; +} + +static char* MallocCString(const std::string &origin) +{ + if (origin.empty()) { + return nullptr; + } + auto length = origin.length() + 1; + char *res = static_cast(malloc(sizeof(char) * length)); + if (res == nullptr) { + return nullptr; + } + return std::char_traits::copy(res, origin.c_str(), length); +} + +static CArrString MallocStringVec(std::vector &origin) +{ + CArrString res{}; + if (origin.empty()) { + return res; + } + + size_t size = origin.size(); + if (size == 0 || size > std::numeric_limits::max() / sizeof(char *)) { + return res; + } + res.head = static_cast(malloc(sizeof(char *) * size)); + if (res.head == nullptr) { + return res; + } + size_t i = 0; + for (; i < size; ++i) { + res.head[i] = MallocCString(origin[i]); + } + res.size = static_cast(i); + + return res; +} + +static PickerResult MakePickerResult(std::shared_ptr pickerCallback) +{ + PickerResult ret{}; + ret.resultCode = pickerCallback->resultCode; + ret.userSuffixIndex = pickerCallback->want.GetIntParam("userSuffixIndex", -1); + ret.isOriginal = pickerCallback->want.GetBoolParam("isOriginal", false); + if (pickerCallback->want.GetParams().HasParam("ability.params.stream")) { + auto list = pickerCallback->want.GetStringArrayParam("ability.params.stream"); + ret.ability_params_stream = MallocStringVec(list); + } + if (pickerCallback->want.GetParams().HasParam("uriArr")) { + auto list = pickerCallback->want.GetStringArrayParam("uriArr"); + ret.uriArr = MallocStringVec(list); + } + if (pickerCallback->want.GetParams().HasParam("select-item-list")) { + auto list = pickerCallback->want.GetStringArrayParam("select-item-list"); + ret.photoUris = MallocStringVec(list); + } + return ret; +} + +extern "C" { +int32_t FfiOHOSFilePickerModalPicker(OHOS::AbilityRuntime::Context* context, WantHandle config, char* windowName, void (*callback)(PickerResult)) +{ + if (!context || !config) { + HILOG_ERROR("[picker] context or config is nullptr."); + return ERR_INVALID_ARG; + } + if (windowName) { + int32_t status = GetWindow(windowName, window_); + if (status != ERR_OK) { + return status; + } + } + return StartCjPickerExtension(context, config, callback); +} +} + +CjModalUICallback::CjModalUICallback(Ace::UIContent* uiContent, std::shared_ptr pickerCallBack, void (*callback)(PickerResult)) +{ + this->uiContent = uiContent; + this->pickerCallBack_ = pickerCallBack; + this->callback = CJLambda::Create(callback); +} + +void CjModalUICallback::SetSessionId(int32_t sessionId) +{ + this->sessionId_ = sessionId; +} + +void CjModalUICallback::OnRelease(int32_t releaseCode) +{ + HILOG_INFO("[picker] OnRelease enter. release code is %{public}d", releaseCode); + if (!pickerCallBack_) { + HILOG_ERROR("[picker] OnRelease error"); + return; + } + this->uiContent->CloseModalUIExtension(this->sessionId_); + pickerCallBack_->ready = true; + + auto ret = MakePickerResult(pickerCallBack_); + this->callback(ret); + if (window_) { + window_ = nullptr; + } +} + +void CjModalUICallback::OnError(int32_t code, const std::string& name, const std::string& message) +{ + HILOG_ERROR("[picker] OnError enter. errorCode=%{public}d, name=%{public}s, message=%{public}s", + code, name.c_str(), message.c_str()); + this->uiContent->CloseModalUIExtension(this->sessionId_); +} + +void CjModalUICallback::OnResultForModal(int32_t resultCode, const OHOS::AAFwk::Want &result) +{ + HILOG_INFO("[picker] OnResultForModal enter. resultCode is %{public}d,", resultCode); + if (!pickerCallBack_) { + HILOG_ERROR("[picker] OnResultForModal error."); + return; + } + pickerCallBack_->resultCode = resultCode; + pickerCallBack_->want = result; +} + +void CjModalUICallback::OnReceive(const OHOS::AAFwk::WantParams &request) +{ + HILOG_INFO("[picker] OnReceive enter."); +} + +void CjModalUICallback::OnDestroy() +{ + HILOG_INFO("[picker] OnDestroy enter."); +} + +} // namespace CjPicker +} // namespace OHOS \ No newline at end of file -- Gitee From b6889dc10617dd4376ae70a06051ceb7927fc9ef Mon Sep 17 00:00:00 2001 From: zhaoshenghua Date: Wed, 15 Jan 2025 11:12:36 +0800 Subject: [PATCH 2/3] format gn & fix codecheck Signed-off-by: zhaoshenghua --- interfaces/kits/picker/BUILD.gn | 4 +--- interfaces/kits/picker/cj/include/cj_picker.h | 6 ++++-- interfaces/kits/picker/cj/src/cj_picker.cpp | 9 ++++++--- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/interfaces/kits/picker/BUILD.gn b/interfaces/kits/picker/BUILD.gn index f1a464fe..ff3a31c3 100644 --- a/interfaces/kits/picker/BUILD.gn +++ b/interfaces/kits/picker/BUILD.gn @@ -110,9 +110,7 @@ ohos_shared_library("cj_picker_ffi") { include_dirs = [ "cj/include" ] - sources = [ - "cj/src/cj_picker.cpp", - ] + sources = [ "cj/src/cj_picker.cpp" ] external_deps = [ "ability_base:want", diff --git a/interfaces/kits/picker/cj/include/cj_picker.h b/interfaces/kits/picker/cj/include/cj_picker.h index c81043fb..0d8ddbf0 100644 --- a/interfaces/kits/picker/cj/include/cj_picker.h +++ b/interfaces/kits/picker/cj/include/cj_picker.h @@ -55,12 +55,14 @@ struct PickerResult { CArrString photoUris; }; -FFI_EXPORT int32_t FfiOHOSFilePickerModalPicker(OHOS::AbilityRuntime::Context* context, WantHandle config, char* windowName, void (*callback)(PickerResult)); +FFI_EXPORT int32_t FfiOHOSFilePickerModalPicker(OHOS::AbilityRuntime::Context* context, + WantHandle config, char* windowName, void (*callback)(PickerResult)); } class CjModalUICallback { public: - explicit CjModalUICallback(Ace::UIContent* uiContent, std::shared_ptr pickerCallBack, void (*callback)(PickerResult)); + explicit CjModalUICallback(Ace::UIContent* uiContent, + std::shared_ptr pickerCallBack, void (*callback)(PickerResult)); void OnRelease(int32_t releaseCode); void OnResultForModal(int32_t resultCode, const OHOS::AAFwk::Want& result); void OnReceive(const OHOS::AAFwk::WantParams& request); diff --git a/interfaces/kits/picker/cj/src/cj_picker.cpp b/interfaces/kits/picker/cj/src/cj_picker.cpp index 025ff428..60c39fef 100644 --- a/interfaces/kits/picker/cj/src/cj_picker.cpp +++ b/interfaces/kits/picker/cj/src/cj_picker.cpp @@ -44,7 +44,8 @@ static Ace::UIContent* GetUIContextByContext(OHOS::AbilityRuntime::Context* cont return abilityContext->GetUIContent(); } -static int32_t StartCjPickerExtension(OHOS::AbilityRuntime::Context* context, WantHandle want, void (*cjCallback)(PickerResult)) +static int32_t StartCjPickerExtension(OHOS::AbilityRuntime::Context* context, + WantHandle want, void (*cjCallback)(PickerResult)) { HILOG_INFO("[picker]: StartPickerExtension begin."); Ace::UIContent *uiContent; @@ -164,7 +165,8 @@ static PickerResult MakePickerResult(std::shared_ptr pickerCal } extern "C" { -int32_t FfiOHOSFilePickerModalPicker(OHOS::AbilityRuntime::Context* context, WantHandle config, char* windowName, void (*callback)(PickerResult)) +int32_t FfiOHOSFilePickerModalPicker(OHOS::AbilityRuntime::Context* context, + WantHandle config, char* windowName, void (*callback)(PickerResult)) { if (!context || !config) { HILOG_ERROR("[picker] context or config is nullptr."); @@ -180,7 +182,8 @@ int32_t FfiOHOSFilePickerModalPicker(OHOS::AbilityRuntime::Context* context, Wan } } -CjModalUICallback::CjModalUICallback(Ace::UIContent* uiContent, std::shared_ptr pickerCallBack, void (*callback)(PickerResult)) +CjModalUICallback::CjModalUICallback(Ace::UIContent* uiContent, + std::shared_ptr pickerCallBack, void (*callback)(PickerResult)) { this->uiContent = uiContent; this->pickerCallBack_ = pickerCallBack; -- Gitee From cb1e62b37dfaa098d76d8e69518034b217908de7 Mon Sep 17 00:00:00 2001 From: zhaoshenghua Date: Tue, 21 Jan 2025 20:05:35 +0800 Subject: [PATCH 3/3] add cj dep Signed-off-by: zhaoshenghua --- bundle.json | 1 + interfaces/kits/picker/BUILD.gn | 2 +- interfaces/kits/picker/cj/include/cj_picker.h | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bundle.json b/bundle.json index a3be8dd5..70cea83e 100644 --- a/bundle.json +++ b/bundle.json @@ -47,6 +47,7 @@ "group_type":{ "fwk_group": [ "//foundation/filemanagement/user_file_service/interfaces/kits/picker:picker", + "//foundation/filemanagement/user_file_service/interfaces/kits/picker:cj_picker_ffi", "//foundation/filemanagement/user_file_service/interfaces/kits/native/recent:recent", "//foundation/filemanagement/user_file_service/interfaces/kits/native/trash:trash" ], diff --git a/interfaces/kits/picker/BUILD.gn b/interfaces/kits/picker/BUILD.gn index ff3a31c3..0cd1605e 100644 --- a/interfaces/kits/picker/BUILD.gn +++ b/interfaces/kits/picker/BUILD.gn @@ -125,8 +125,8 @@ ohos_shared_library("cj_picker_ffi") { "ability_runtime:ui_extension", "ace_engine:ace_uicontent", "file_api:filemgmt_libhilog", - "file_api:filemgmt_libn", "hilog:libhilog", + "napi:ace_napi", "napi:cj_bind_ffi", "napi:cj_bind_native", ] diff --git a/interfaces/kits/picker/cj/include/cj_picker.h b/interfaces/kits/picker/cj/include/cj_picker.h index 0d8ddbf0..30f38d58 100644 --- a/interfaces/kits/picker/cj/include/cj_picker.h +++ b/interfaces/kits/picker/cj/include/cj_picker.h @@ -25,7 +25,6 @@ #include "data_ability_helper.h" #include "data_ability_observer_stub.h" #include "data_ability_predicates.h" -#include "filemgmt_libn.h" #include "ui_extension_context.h" #include "ability_context.h" #include "want.h" -- Gitee