diff --git a/adapter/ohos/entrance/data_ability_helper_standard.cpp b/adapter/ohos/entrance/data_ability_helper_standard.cpp index 86f050cd..ebc592ad 100644 --- a/adapter/ohos/entrance/data_ability_helper_standard.cpp +++ b/adapter/ohos/entrance/data_ability_helper_standard.cpp @@ -12,12 +12,51 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#if !defined(WINDOWS_PLATFORM) and !defined(MAC_PLATFORM) +#include +#endif #include "adapter/ohos/entrance/data_ability_helper_standard.h" #include "data_ability_helper.h" +#include "pixel_map.h" + namespace OHOS::Ace { +namespace { + +#if !defined(WINDOWS_PLATFORM) and !defined(MAC_PLATFORM) +using ThumbnaiNapiEntry = void* (*)(const char*, void*); +ThumbnaiNapiEntry GetThumbnailNapiEntry() +{ + static ThumbnaiNapiEntry thumbnailNapiEntry = nullptr; + if (!thumbnailNapiEntry) { +#ifdef _ARM64_ + std::string prefix = "/system/lib64/module/"; +#else + std::string prefix = "/system/lib/module/"; +#endif +#ifdef OHOS_STANDARD_SYSTEM + std::string napiPluginName = "multimedia/libmedialibrary.z.so"; +#endif + auto napiPluginPath = prefix.append(napiPluginName); + void* handle = dlopen(napiPluginPath.c_str(), RTLD_LAZY); + if (handle == nullptr) { + LOGE("Failed to open shared library %{public}s, reason: %{public}s", napiPluginPath.c_str(), dlerror()); + return nullptr; + } + thumbnailNapiEntry = reinterpret_cast(dlsym(handle, "OHOS_MEDIA_NativeGetThumbnail")); + if (thumbnailNapiEntry == nullptr) { + dlclose(handle); + LOGE("Failed to get symbol OHOS_MEDIA_NativeGetThumbnail in %{public}s", napiPluginPath.c_str()); + return nullptr; + } + } + return thumbnailNapiEntry; +} +#endif + +} DataAbilityHelperStandard::DataAbilityHelperStandard(const std::shared_ptr& context, const std::shared_ptr& runtimeContext, bool useStageModel) @@ -25,10 +64,46 @@ DataAbilityHelperStandard::DataAbilityHelperStandard(const std::shared_ptr std::unique_ptr { + ThumbnaiNapiEntry thumbnailNapiEntry = GetThumbnailNapiEntry(); + if (!thumbnailNapiEntry) { + LOGE("thumbnailNapiEntry is null"); + return nullptr; + } + auto runtimeContextSptr = runtimeContextWp.lock(); + if (runtimeContextSptr == nullptr) { + LOGE("runtimeContext lock fail, uri: %{private}s", uri.c_str()); + return nullptr; + } + void* resPtr = thumbnailNapiEntry(uri.c_str(), &runtimeContextSptr); + if (resPtr == nullptr) { + LOGW("resPtr from native thumbnail is nullptr, uri: %{private}s", uri.c_str()); + return nullptr; + } + return std::unique_ptr(reinterpret_cast(resPtr)); + }; +#endif } else { dataAbilityHelper_ = AppExecFwk::DataAbilityHelper::Creator(context); } } + +void* DataAbilityHelperStandard::QueryThumbnailResFromDataAbility(const std::string& uri) +{ + if (!dataAbilityThumbnailQueryImpl_) { + LOGW("no impl for thumbnail data query, please make sure you are using thumbnail resource on stage mode. " + "uri: %{private}s", uri.c_str()); + return nullptr; + } + pixmap_ = dataAbilityThumbnailQueryImpl_(uri); + if (!pixmap_) { + LOGW("pixel map from thumb nail is nullptr, uri: %{public}s", uri.c_str()); + return nullptr; + } + return reinterpret_cast(&pixmap_); +} int32_t DataAbilityHelperStandard::OpenFile(const std::string& uriStr, const std::string& mode) { diff --git a/adapter/ohos/entrance/data_ability_helper_standard.h b/adapter/ohos/entrance/data_ability_helper_standard.h index 4ed44ff9..de671e37 100644 --- a/adapter/ohos/entrance/data_ability_helper_standard.h +++ b/adapter/ohos/entrance/data_ability_helper_standard.h @@ -18,6 +18,8 @@ #include "base/resource/data_ability_helper.h" +#include "pixel_map.h" + namespace OHOS::AppExecFwk { class DataAbilityHelper; class Context; @@ -33,6 +35,7 @@ namespace OHOS { namespace OHOS::Ace { +using DataAbilityThumbnailQueryImpl = std::function(const std::string&)>; class DataAbilityHelperStandard : public DataAbilityHelper { DECLARE_ACE_TYPE(DataAbilityHelperStandard, DataAbilityHelper) @@ -42,12 +45,15 @@ public: ~DataAbilityHelperStandard() override = default; int32_t OpenFile(const std::string& uriStr, const std::string& mode) override; + void* QueryThumbnailResFromDataAbility(const std::string& uri) override; private: bool useStageModel_ = false; std::shared_ptr dataAbilityHelper_; std::weak_ptr runtimeContext_; std::shared_ptr uri_; + DataAbilityThumbnailQueryImpl dataAbilityThumbnailQueryImpl_; + std::unique_ptr pixmap_; }; } // namespace OHOS::Ace diff --git a/adapter/ohos/osal/pixel_map_ohos.cpp b/adapter/ohos/osal/pixel_map_ohos.cpp index 202dde74..58d12d83 100644 --- a/adapter/ohos/osal/pixel_map_ohos.cpp +++ b/adapter/ohos/osal/pixel_map_ohos.cpp @@ -68,11 +68,23 @@ AlphaType PixelMapOhos::AlphaTypeConverter(Media::AlphaType alphaType) RefPtr PixelMap::CreatePixelMap(void* rawPtr) { std::shared_ptr* pixmapPtr = reinterpret_cast*>(rawPtr); - if (*pixmapPtr == nullptr) { - LOGE("pixmap pointer is nullptr."); + if (pixmapPtr == nullptr || *pixmapPtr == nullptr) { + LOGW("pixmap pointer is nullptr when CreatePixelMap."); + return nullptr; } return AceType::MakeRefPtr(*pixmapPtr); } + +RefPtr PixelMap::CreatePixelMapFromDataAbility(void* uniquePtr) +{ + std::unique_ptr* pixmapPtr = reinterpret_cast*>(uniquePtr); + if (pixmapPtr == nullptr || *pixmapPtr == nullptr) { + LOGW("pixmap pointer is nullptr when CreatePixelMapFromDataAbility."); + return nullptr; + } + auto rawPtr = (*pixmapPtr).release(); + return AceType::MakeRefPtr(std::shared_ptr(rawPtr)); +} int32_t PixelMapOhos::GetWidth() const { diff --git a/frameworks/base/image/pixel_map.h b/frameworks/base/image/pixel_map.h index 361e855d..71c54605 100644 --- a/frameworks/base/image/pixel_map.h +++ b/frameworks/base/image/pixel_map.h @@ -46,6 +46,7 @@ class ACE_EXPORT PixelMap : public AceType { public: static RefPtr CreatePixelMap(void* sptrAddr); + static RefPtr CreatePixelMapFromDataAbility(void* uniquePtr); virtual int32_t GetWidth() const = 0; virtual int32_t GetHeight() const = 0; virtual const uint8_t* GetPixels() const = 0; diff --git a/frameworks/base/resource/data_ability_helper.h b/frameworks/base/resource/data_ability_helper.h index 18474f1f..b47b4134 100644 --- a/frameworks/base/resource/data_ability_helper.h +++ b/frameworks/base/resource/data_ability_helper.h @@ -28,6 +28,7 @@ public: ~DataAbilityHelper() override = default; virtual int32_t OpenFile(const std::string& uriStr, const std::string& mode) = 0; + virtual void* QueryThumbnailResFromDataAbility(const std::string& uri) = 0; }; } // namespace OHOS::Ace diff --git a/frameworks/base/resource/data_provider_manager.cpp b/frameworks/base/resource/data_provider_manager.cpp index 80b8318b..2fe98c6a 100644 --- a/frameworks/base/resource/data_provider_manager.cpp +++ b/frameworks/base/resource/data_provider_manager.cpp @@ -28,6 +28,16 @@ std::unique_ptr DataProviderManager::GetDataProviderResFromUri( } return nullptr; } + +void* DataProviderManagerStandard::GetDataProviderThumbnailResFromUri(const std::string& uriStr) +{ + InitHelper(); + if (!helper_) { + LOGE("data ability helper is null when try query thumbnail resource, uri: %{private}s", uriStr.c_str()); + return nullptr; + } + return helper_->QueryThumbnailResFromDataAbility(uriStr); +} std::unique_ptr DataProviderManagerStandard::GetDataProviderResFromUri(const std::string& uriStr) { diff --git a/frameworks/base/resource/data_provider_manager.h b/frameworks/base/resource/data_provider_manager.h index 96eef86f..fcdf6b48 100644 --- a/frameworks/base/resource/data_provider_manager.h +++ b/frameworks/base/resource/data_provider_manager.h @@ -48,6 +48,7 @@ public: ~DataProviderManagerInterface() override = default; virtual std::unique_ptr GetDataProviderResFromUri(const std::string& uriStr) = 0; + virtual void* GetDataProviderThumbnailResFromUri(const std::string& uriStr) = 0; }; using DataProviderImpl = std::function(const std::string& uriStr)>; @@ -58,6 +59,10 @@ public: ~DataProviderManager() override = default; std::unique_ptr GetDataProviderResFromUri(const std::string& uriStr) override; + void* GetDataProviderThumbnailResFromUri(const std::string& uriStr) override + { + return nullptr; + }; private: DataProviderImpl platformImpl_; @@ -73,6 +78,7 @@ public: ~DataProviderManagerStandard() override = default; std::unique_ptr GetDataProviderResFromUri(const std::string& uriStr) override; + void* GetDataProviderThumbnailResFromUri(const std::string& uriStr) override; const RefPtr& GetDataAbilityHelper() { diff --git a/frameworks/core/common/window.cpp b/frameworks/core/common/window.cpp index 2e4ac497..fc14ea61 100644 --- a/frameworks/core/common/window.cpp +++ b/frameworks/core/common/window.cpp @@ -36,7 +36,7 @@ Window::Window(std::unique_ptr platformWindow) : platformWindow_ void Window::RequestFrame() { if (!onShow_) { - LOGI("window is not show, stop request frame"); + LOGD("window is not show, stop request frame"); return; } if (!isRequestVsync_ && platformWindow_ != nullptr) { diff --git a/frameworks/core/components/common/layout/constants.h b/frameworks/core/components/common/layout/constants.h index 1b248cd5..7c4d4977 100644 --- a/frameworks/core/components/common/layout/constants.h +++ b/frameworks/core/components/common/layout/constants.h @@ -304,6 +304,7 @@ enum class SrcType { INTERNAL, // internal cached file resource RESOURCE, DATA_ABILITY, + DATA_ABILITY_DECODED, RESOURCE_ID, // default resource which src is internal resource id PIXMAP, }; diff --git a/frameworks/core/components/image/rosen_render_image.cpp b/frameworks/core/components/image/rosen_render_image.cpp index e96dc8d0..24057697 100644 --- a/frameworks/core/components/image/rosen_render_image.cpp +++ b/frameworks/core/components/image/rosen_render_image.cpp @@ -22,7 +22,10 @@ #include "third_party/skia/include/core/SkRect.h" #include "third_party/skia/include/core/SkShader.h" +#include "base/image/pixel_map.h" +#include "base/thread/background_task_executor.h" #include "base/utils/utils.h" +#include "core/common/container.h" #include "core/common/frontend.h" #include "core/components/align/render_align.h" #include "core/components/common/properties/radius.h" @@ -298,6 +301,60 @@ void RosenRenderImage::Update(const RefPtr& component) FetchImageObject(); } +std::function RosenRenderImage::GenerateThumbnailLoadTask() +{ + return [sourceInfo = sourceInfo_, pipelineContext = GetContext(), weak = AceType::WeakClaim(this), + id = Container::CurrentId()]() { + ContainerScope scope(id); + auto context = pipelineContext.Upgrade(); + if (!context) { + LOGE("pipeline context is null when try start thumbnailLoadTask, uri: %{private}s", + sourceInfo.GetSrc().c_str()); + return; + } + auto dataProvider = context->GetDataProviderManager(); + if (!dataProvider) { + LOGE("the data provider is null when try load thumbnail resource, uri: %{private}s", + sourceInfo.GetSrc().c_str()); + return; + } + void* pixmapMediaUniquePtr = dataProvider->GetDataProviderThumbnailResFromUri(sourceInfo.GetSrc()); + auto pixmapOhos = PixelMap::CreatePixelMapFromDataAbility(pixmapMediaUniquePtr); + auto taskExecutor = context->GetTaskExecutor(); + if (!taskExecutor) { + return; + } + if (!pixmapOhos) { + LOGW("pixmapOhos is null, uri: %{private}s", sourceInfo.GetSrc().c_str()); + taskExecutor->PostTask( + [weak, sourceInfo] { + auto renderImage = weak.Upgrade(); + if (!renderImage) { + LOGE("renderImage is null when try trigger load thumbnail fail event, " + "uri: %{private}s", + sourceInfo.GetSrc().c_str()); + return; + } + renderImage->failedCallback_(sourceInfo); + }, + TaskExecutor::TaskType::UI); + return; + } + taskExecutor->PostTask( + [weak, pixmapOhos, sourceInfo] { + auto renderImage = weak.Upgrade(); + if (!renderImage) { + LOGE("renderImage is null when try load thumbnail data ability, " + "uri: %{private}s", + sourceInfo.GetSrc().c_str()); + return; + } + renderImage->UpdatePixmap(pixmapOhos); + }, + TaskExecutor::TaskType::UI); + }; +} + void RosenRenderImage::FetchImageObject() { LOGD("fetch obj : %{public}s", sourceInfo_.ToString().c_str()); @@ -321,6 +378,10 @@ void RosenRenderImage::FetchImageObject() rawImageSizeUpdated_ = false; SrcType srcType = sourceInfo_.GetSrcType(); switch (srcType) { + case SrcType::DATA_ABILITY_DECODED: { + BackgroundTaskExecutor::GetInstance().PostTask(GenerateThumbnailLoadTask()); + break; + } case SrcType::PIXMAP: { UpdatePixmap(sourceInfo_.GetPixmap()); break; @@ -330,19 +391,11 @@ void RosenRenderImage::FetchImageObject() break; } default: { - bool syncMode = (context->IsBuildingFirstPage() && - frontend->GetType() == FrontendType::JS_CARD && - sourceInfo_.GetSrcType() != SrcType::NETWORK) || syncMode_; - ImageProvider::FetchImageObject( - sourceInfo_, - imageObjSuccessCallback_, - uploadSuccessCallback_, - failedCallback_, - GetContext(), - syncMode, - useSkiaSvg_, - autoResize_, - renderTaskHolder_, + bool syncMode = (context->IsBuildingFirstPage() && frontend->GetType() == FrontendType::JS_CARD && + sourceInfo_.GetSrcType() != SrcType::NETWORK) || + syncMode_; + ImageProvider::FetchImageObject(sourceInfo_, imageObjSuccessCallback_, uploadSuccessCallback_, + failedCallback_, GetContext(), syncMode, useSkiaSvg_, autoResize_, renderTaskHolder_, onPostBackgroundTask_); break; } @@ -411,6 +464,7 @@ void RosenRenderImage::ProcessPixmapForPaint() return; } FireLoadEvent(rawImageSize_); + RemoveChild(renderAltImage_); renderAltImage_ = nullptr; } diff --git a/frameworks/core/components/image/rosen_render_image.h b/frameworks/core/components/image/rosen_render_image.h index c3aa563a..662ae697 100644 --- a/frameworks/core/components/image/rosen_render_image.h +++ b/frameworks/core/components/image/rosen_render_image.h @@ -116,6 +116,7 @@ private: void UpdatePixmap(const RefPtr& pixmap); void UpdateSharedMemoryImage(const RefPtr& context); void ProcessPixmapForPaint(); + std::function GenerateThumbnailLoadTask(); sk_sp skiaDom_; RefPtr svgDom_; diff --git a/frameworks/core/image/image_source_info.cpp b/frameworks/core/image/image_source_info.cpp index 93d59159..7c077f64 100644 --- a/frameworks/core/image/image_source_info.cpp +++ b/frameworks/core/image/image_source_info.cpp @@ -40,6 +40,12 @@ bool ImageSourceInfo::IsValidBase64Head(const std::string& uri, const std::strin return std::regex_match(base64Head, regular); } +bool ImageSourceInfo::IsUriOfDataAbilityEncoded(const std::string& uri, const std::string& pattern) +{ + std::regex regular(pattern); + return std::regex_match(uri, regular); +} + SrcType ImageSourceInfo::ResolveURIType(const std::string& uri) { if (uri.empty()) { @@ -68,6 +74,9 @@ SrcType ImageSourceInfo::ResolveURIType(const std::string& uri) } else if (head == "resource") { return SrcType::RESOURCE; } else if (head == "dataability") { + if (IsUriOfDataAbilityEncoded(uri, "^dataability://.*?/media/.*/thumbnail/.*$")) { + return SrcType::DATA_ABILITY_DECODED; + } return SrcType::DATA_ABILITY; } else { return SrcType::UNSUPPORTED; diff --git a/frameworks/core/image/image_source_info.h b/frameworks/core/image/image_source_info.h index f2f4df2d..e8827ac5 100644 --- a/frameworks/core/image/image_source_info.h +++ b/frameworks/core/image/image_source_info.h @@ -31,6 +31,7 @@ public: static bool IsSVGSource(const std::string& imageSrc, InternalResource::ResourceId resourceId); static SrcType ResolveURIType(const std::string& uri); static bool IsValidBase64Head(const std::string& uri, const std::string& pattern); + static bool IsUriOfDataAbilityEncoded(const std::string& uri, const std::string& pattern); explicit ImageSourceInfo( const std::string& imageSrc, diff --git a/frameworks/core/pipeline/base/render_node.cpp b/frameworks/core/pipeline/base/render_node.cpp index d0367caa..b3223b3c 100644 --- a/frameworks/core/pipeline/base/render_node.cpp +++ b/frameworks/core/pipeline/base/render_node.cpp @@ -2037,7 +2037,7 @@ void RenderNode::RSNodeAddChild(const RefPtr& child) { #ifdef ENABLE_ROSEN_BACKEND if (!rsNode_) { - LOGW("Parent render_node has no RSNode, creating now."); + LOGD("Parent render_node has no RSNode, creating now."); SyncRSNodeBoundary(true, true); } if (IsTailRenderNode()) {