* Copyright (c) 2023 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.
*/
#include "session/host/include/scene_persistence.h"
#include <sys/stat.h>
#include <hitrace_meter.h>
#include <image_packer.h>
#include <parameters.h>
#include "window_manager_hilog.h"
namespace OHOS::Rosen {
namespace {
constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, HILOG_DOMAIN_WINDOW, "ScenePersistence" };
constexpr const char* UNDERLINE_SEPARATOR = "_";
constexpr const char* SCALED_SNAPSHOT_FLAG = "s";
constexpr const char* ASTC_IMAGE_FORMAT_LOW = "image/astc/8*8";
constexpr const char* ASTC_IMAGE_FORMAT_HIGH = "image/astc/4*4";
constexpr const char* ASTC_IMAGE_SUFFIX = ".astc";
constexpr uint8_t ASTC_IMAGE_QUALITY = 20;
constexpr const char* IMAGE_FORMAT = "image/png";
constexpr const char* IMAGE_SUFFIX = ".png";
constexpr uint8_t IMAGE_QUALITY = 100;
constexpr int32_t ICON_IMAGE_WIDTH_HEIGHT_SIZE = 1024;
constexpr double ICON_IMAGE_MAX_SCALE = 1;
constexpr uint8_t SUCCESS = 0;
}
std::string ScenePersistence::snapshotDirectory_;
std::string ScenePersistence::updatedIconDirectory_;
std::string ScenePersistence::abilityIconDirectory_;
std::string ScenePersistence::startWindowDirectory_;
std::shared_ptr<WSFFRTHelper> ScenePersistence::snapshotFfrtHelper_;
bool ScenePersistence::isAstcEnabled_ = false;
bool ScenePersistence::CreateSnapshotDir(const std::string& directory)
{
snapshotDirectory_ = directory + "/SceneSnapShot/";
if (mkdir(snapshotDirectory_.c_str(), S_IRWXU)) {
TLOGD(WmsLogTag::WMS_PATTERN, "mkdir failed or the directory already exists");
return false;
}
return true;
}
bool ScenePersistence::CreateUpdatedIconDir(const std::string& directory)
{
updatedIconDirectory_ = directory + "/UpdatedIcon/";
if (mkdir(updatedIconDirectory_.c_str(), S_IRWXU)) {
TLOGD(WmsLogTag::DEFAULT, "mkdir failed or the directory already exists");
return false;
}
return true;
}
bool ScenePersistence::CreateAbilityIconDir(const std::string& directory)
{
abilityIconDirectory_ = directory + "/AbilityIcon/";
if (mkdir(abilityIconDirectory_.c_str(), S_IRWXU)) {
TLOGD(WmsLogTag::DEFAULT, "mkdir failed or the directory already exists");
return false;
}
return true;
}
bool ScenePersistence::CreateStartWindowDir(const std::string& directory)
{
startWindowDirectory_ = directory + "/StartWindow/";
if (mkdir(startWindowDirectory_.c_str(), S_IRWXU)) {
TLOGD(WmsLogTag::DEFAULT, "mkdir failed or the start window directory already exists");
return false;
}
return true;
}
void ScenePersistence::SaveStartWindow(const std::shared_ptr<Media::PixelMap>& pixelMap,
const std::string& saveStartWindowKey,
const std::function<void(std::string, std::string)>& saveStartWindowCallback)
{
std::string startWindowPath = startWindowDirectory_ + saveStartWindowKey + IMAGE_SUFFIX;
auto task = [weakThis = wptr(this), pixelMap, startWindowPath, saveStartWindowKey, saveStartWindowCallback]() {
auto scenePersistence = weakThis.promote();
if (scenePersistence == nullptr || pixelMap == nullptr || startWindowPath.find('/') == std::string::npos) {
TLOGNE(WmsLogTag::WMS_PATTERN,
"SaveStartWindow scenePersistence %{public}s nullptr or pixelMap %{public}s null",
scenePersistence == nullptr ? "" : "not", pixelMap == nullptr ? "" : "not");
return;
}
OHOS::Media::ImagePacker imagePacker;
OHOS::Media::PackOption option;
option.format = IMAGE_FORMAT;
option.quality = IMAGE_QUALITY;
if (remove(startWindowPath.c_str())) {
TLOGND(WmsLogTag::WMS_PATTERN, "SaveStartWindow remove old file failed");
}
TLOGNI(WmsLogTag::WMS_PATTERN, "SaveStartWindow begin");
HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "ScenePersistence::SaveStartWindow %s", startWindowPath.c_str());
std::lock_guard lock(scenePersistence->savingStartWindowMutex_);
if (imagePacker.StartPacking(startWindowPath, option)) {
TLOGNE(WmsLogTag::WMS_PATTERN, "SaveStartWindow failed, start packing error");
return;
}
if (imagePacker.AddImage(*pixelMap)) {
TLOGNE(WmsLogTag::WMS_PATTERN, "SaveStartWindow failed, add image error");
return;
}
int64_t packedSize = 0;
if (imagePacker.FinalizePacking(packedSize)) {
TLOGNE(WmsLogTag::WMS_PATTERN, "SaveStartWindow failed, finish packing error, size: %{public}" PRIu64,
packedSize);
return;
}
saveStartWindowCallback(startWindowPath, saveStartWindowKey);
TLOGNI(WmsLogTag::WMS_PATTERN, "SaveStartWindow success, size: %{public}" PRIu64,
packedSize);
};
snapshotFfrtHelper_->SubmitTask(std::move(task), startWindowPath);
}
void ScenePersistence::SetSnapshotCapacity(SnapshotStatus capacity)
{
capacity_ = capacity;
}
ScenePersistence::ScenePersistence(const std::string& bundleName, int32_t persistentId, SnapshotStatus capacity)
: bundleName_(bundleName), persistentId_(persistentId), capacity_(capacity)
{
InitAstcEnabled();
auto suffix = isAstcEnabled_ ? ASTC_IMAGE_SUFFIX : IMAGE_SUFFIX;
for (int32_t screenStatus = SCREEN_UNKNOWN; screenStatus < SCREEN_COUNT; screenStatus++) {
snapshotPath_[screenStatus] = snapshotDirectory_ + bundleName + UNDERLINE_SEPARATOR +
std::to_string(persistentId) + UNDERLINE_SEPARATOR + std::to_string(screenStatus) + suffix;
}
snapshotScaledPath_ = snapshotDirectory_ + bundleName + UNDERLINE_SEPARATOR +
std::to_string(persistentId) + UNDERLINE_SEPARATOR + SCALED_SNAPSHOT_FLAG + suffix;
snapshotFreeMultiWindowPath_ = snapshotDirectory_ + bundleName + UNDERLINE_SEPARATOR +
std::to_string(persistentId) + suffix;
updatedIconPath_ = updatedIconDirectory_ + bundleName + IMAGE_SUFFIX;
abilityIconPath_ = abilityIconDirectory_ + bundleName + UNDERLINE_SEPARATOR +
std::to_string(persistentId) + IMAGE_SUFFIX;
if (snapshotFfrtHelper_ == nullptr) {
snapshotFfrtHelper_ = std::make_shared<WSFFRTHelper>();
}
const std::string multiWindowUIType = system::GetParameter("const.window.multiWindowUIType", "HandsetSmartWindow");
isPcWindow_ = (multiWindowUIType == "FreeFormMultiWindow");
}
ScenePersistence::~ScenePersistence()
{
ClearSnapshotPath();
ClearAbilityIconPath();
}
void ScenePersistence::ClearSnapshotPath()
{
auto task = [snapshotPaths = std::vector<std::string>(snapshotPath_, snapshotPath_ + SCREEN_COUNT),
snapshotFreeMultiWindowPath = snapshotFreeMultiWindowPath_, snapshotScaledPath = snapshotScaledPath_,
persistentId = persistentId_, where = __func__]() {
TLOGI(WmsLogTag::WMS_PATTERN, "%{public}s persistentId: %{public}d", where, persistentId);
for (const auto& snapshotPath: snapshotPaths) {
remove(snapshotPath.c_str());
}
remove(snapshotScaledPath.c_str());
remove(snapshotFreeMultiWindowPath.c_str());
};
snapshotFfrtHelper_->SubmitTask(std::move(task), "ClearSnapshotPath" + std::to_string(persistentId_));
}
void ScenePersistence::ClearAbilityIconPath()
{
TLOGI(WmsLogTag::WMS_PATTERN, "clear icon, persistentId: %{public}d", persistentId_);
remove(abilityIconPath_.c_str());
}
std::shared_ptr<WSFFRTHelper> ScenePersistence::GetSnapshotFfrtHelper() const
{
return snapshotFfrtHelper_;
}
void ScenePersistence::InitAstcEnabled()
{
static bool isAstcEnabled = system::GetBoolParameter("persist.multimedia.image.astc.enabled", true);
isAstcEnabled_ = isAstcEnabled;
}
bool ScenePersistence::IsAstcEnabled()
{
return isAstcEnabled_;
}
void ScenePersistence::SaveSnapshot(const std::shared_ptr<Media::PixelMap>& pixelMap,
const std::function<void()> resetSnapshotCallback, SnapshotStatus key, DisplayOrientation rotate,
bool freeMultiWindow)
{
savingSnapshotSum_.fetch_add(1);
SetIsSavingSnapshot(true);
TLOGI(WmsLogTag::WMS_PATTERN, "isSavingSnapshot:%{public}d", isSavingSnapshot_.load());
std::string path = freeMultiWindow ? snapshotFreeMultiWindowPath_ : snapshotPath_[key];
float scaleValue = snapshotScaleLow_ / snapshotScale_;
auto task = [weakThis = wptr(this), pixelMap, resetSnapshotCallback, savingSnapshotSum = savingSnapshotSum_.load(),
key, rotate, path, freeMultiWindow, scaledPath = snapshotScaledPath_, scaleValue,
enablePersistentScaledSnapshot = enablePersistentScaledSnapshot_]() {
auto scenePersistence = weakThis.promote();
if (scenePersistence == nullptr || pixelMap == nullptr ||
path.find('/') == std::string::npos) {
TLOGNE(WmsLogTag::WMS_PATTERN, "scenePersistence %{public}s nullptr, pixelMap %{public}s nullptr",
scenePersistence == nullptr ? "" : "not", pixelMap == nullptr ? "" : "not");
resetSnapshotCallback();
return;
}
if (!scenePersistence->PersistSnapshot(path, pixelMap)) {
resetSnapshotCallback();
return;
}
scenePersistence->SetSnapshotSize(key, freeMultiWindow, false,
{ pixelMap->GetWidth(), pixelMap->GetHeight() });
scenePersistence->rotate_[key] = rotate;
if (enablePersistentScaledSnapshot) {
if (scaledPath.find('/') == std::string::npos) {
TLOGNE(WmsLogTag::WMS_PATTERN, "scaledPath invalid");
resetSnapshotCallback();
return;
}
pixelMap->scale(scaleValue, scaleValue);
if (!scenePersistence->PersistSnapshot(scaledPath, pixelMap)) {
TLOGNE(WmsLogTag::WMS_PATTERN, "Save scaledSnapshot failed");
resetSnapshotCallback();
return;
}
scenePersistence->SetSnapshotSize(key, false, true, { pixelMap->GetWidth(), pixelMap->GetHeight() });
}
if (savingSnapshotSum == scenePersistence->savingSnapshotSum_.load()) {
resetSnapshotCallback();
}
};
snapshotFfrtHelper_->SubmitTask(std::move(task), "SaveSnapshot" + path);
}
bool ScenePersistence::PersistSnapshot(std::string path, const std::shared_ptr<Media::PixelMap>& pixelMap)
{
TLOGI(WmsLogTag::WMS_PATTERN, "Save snapshot begin");
HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "SaveSnapshot %s", path.c_str());
OHOS::Media::ImagePacker imagePacker;
OHOS::Media::PackOption option;
const char *astcImageFormat = isPcWindow_ ? ASTC_IMAGE_FORMAT_LOW : ASTC_IMAGE_FORMAT_HIGH;
option.format = IsAstcEnabled() ? astcImageFormat : IMAGE_FORMAT;
option.quality = IsAstcEnabled() ? ASTC_IMAGE_QUALITY : IMAGE_QUALITY;
option.numberHint = 1;
std::lock_guard lock(savingSnapshotMutex_);
if (auto ret = remove(path.c_str())) {
TLOGD(WmsLogTag::WMS_PATTERN, "Remove %{public}s failed ret:%{public}d", path.c_str(), ret);
}
if (imagePacker.StartPacking(path, option)) {
TLOGE(WmsLogTag::WMS_PATTERN, "Save snapshot failed, starting packing error");
return false;
}
if (imagePacker.AddImage(*pixelMap)) {
TLOGE(WmsLogTag::WMS_PATTERN, "Save snapshot failed, adding image error");
return false;
}
int64_t packedSize = 0;
if (imagePacker.FinalizePacking(packedSize)) {
TLOGE(WmsLogTag::WMS_PATTERN, "Save snapshot failed, finalizing packing error");
return false;
}
TLOGI(WmsLogTag::WMS_PATTERN, "Save snapshot end, packed size %{public}" PRId64, packedSize);
return true;
}
bool ScenePersistence::IsSavingSnapshot()
{
return isSavingSnapshot_.load();
}
void ScenePersistence::SetIsSavingSnapshot(bool isSavingSnapshot)
{
isSavingSnapshot_.store(isSavingSnapshot);
}
void ScenePersistence::ResetSnapshotCache()
{
isSavingSnapshot_.store(false);
}
void ScenePersistence::RenameSnapshotFromOldPersistentId(const int32_t& oldPersistentId)
{
auto task = [weakThis = wptr(this), oldPersistentId]() {
auto scenePersistence = weakThis.promote();
if (scenePersistence == nullptr) {
TLOGNE(WmsLogTag::WMS_PATTERN, "scenePersistence is nullptr");
return;
}
for (int32_t screenStatus = SCREEN_UNKNOWN; screenStatus < SCREEN_COUNT; screenStatus++) {
scenePersistence->RenameSnapshotFromOldPersistentId(oldPersistentId, screenStatus);
}
auto suffix = scenePersistence->isAstcEnabled_ ? ASTC_IMAGE_SUFFIX : IMAGE_SUFFIX;
std::string oldSnapshotFreeMultiWindowPath = snapshotDirectory_ + scenePersistence->bundleName_ +
UNDERLINE_SEPARATOR + std::to_string(oldPersistentId) + suffix;
auto& snapshotPath = scenePersistence->snapshotFreeMultiWindowPath_;
std::lock_guard lock(scenePersistence->savingSnapshotMutex_);
int ret = std::rename(oldSnapshotFreeMultiWindowPath.c_str(), snapshotPath.c_str());
if (ret == 0) {
TLOGNI(WmsLogTag::WMS_PATTERN, "Rename snapshot from %{public}s to %{public}s.",
oldSnapshotFreeMultiWindowPath.c_str(), snapshotPath.c_str());
} else {
TLOGNW(WmsLogTag::WMS_PATTERN, "Failed to rename snapshot from %{public}s to %{public}s.",
oldSnapshotFreeMultiWindowPath.c_str(), snapshotPath.c_str());
}
std::string oldSnapshotScaledPath = snapshotDirectory_ + scenePersistence->bundleName_ + UNDERLINE_SEPARATOR +
std::to_string(oldPersistentId) + UNDERLINE_SEPARATOR + SCALED_SNAPSHOT_FLAG + suffix;
auto& snapshotScaledPath = scenePersistence->snapshotScaledPath_;
ret = std::rename(oldSnapshotScaledPath.c_str(), snapshotScaledPath.c_str());
if (ret == 0) {
TLOGNI(WmsLogTag::WMS_PATTERN, "Rename snapshot from %{public}s to %{public}s.",
oldSnapshotScaledPath.c_str(), snapshotScaledPath.c_str());
} else {
TLOGNW(WmsLogTag::WMS_PATTERN, "Failed to rename snapshot from %{public}s to %{public}s.",
oldSnapshotScaledPath.c_str(), snapshotScaledPath.c_str());
}
};
snapshotFfrtHelper_->SubmitTask(std::move(task), "RenameSnapshotFromOldPersistentId"
+ std::to_string(oldPersistentId));
}
void ScenePersistence::RenameSnapshotFromOldPersistentId(const int32_t& oldPersistentId, SnapshotStatus key)
{
auto& snapshotPath = snapshotPath_[key];
auto suffix = isAstcEnabled_ ? ASTC_IMAGE_SUFFIX : IMAGE_SUFFIX;
std::string oldSnapshotPath = snapshotDirectory_ + bundleName_ + UNDERLINE_SEPARATOR +
std::to_string(oldPersistentId) + UNDERLINE_SEPARATOR + std::to_string(key) + suffix;
std::lock_guard lock(savingSnapshotMutex_);
int ret = std::rename(oldSnapshotPath.c_str(), snapshotPath.c_str());
if (ret == 0) {
TLOGI(WmsLogTag::WMS_PATTERN, "Rename snapshot from %{public}s to %{public}s.",
oldSnapshotPath.c_str(), snapshotPath.c_str());
} else {
TLOGW(WmsLogTag::WMS_PATTERN, "Failed to rename snapshot from %{public}s to %{public}s.",
oldSnapshotPath.c_str(), snapshotPath.c_str());
}
}
std::string ScenePersistence::GetSnapshotFilePath(SnapshotStatus& key, bool useKey, bool freeMultiWindow)
{
if (freeMultiWindow) {
return snapshotFreeMultiWindowPath_;
}
if (useKey || HasSnapshot(key, false)) {
return snapshotPath_[key];
}
if (FindClosestFormSnapshot(key)) {
TLOGW(WmsLogTag::WMS_PATTERN, "FindClosestFormSnapshot:%{public}d", key);
return snapshotPath_[key];
}
TLOGW(WmsLogTag::WMS_PATTERN, "Failed");
return snapshotPath_[SCREEN_UNKNOWN];
}
bool ScenePersistence::FindClosestFormSnapshot(SnapshotStatus& key)
{
std::lock_guard lock(hasSnapshotMutex_);
if (hasSnapshot_[key]) {
return true;
}
bool isFolded = (key == SCREEN_FOLDED);
if (isFolded) {
for (int32_t screenStatus = SCREEN_EXPAND; screenStatus >= SCREEN_UNKNOWN; screenStatus--) {
if (hasSnapshot_[screenStatus]) {
key = screenStatus;
return true;
}
}
return false;
}
for (int32_t screenStatus = SCREEN_UNKNOWN; screenStatus < SCREEN_COUNT; screenStatus++) {
if (hasSnapshot_[screenStatus]) {
key = screenStatus;
return true;
}
}
return false;
}
void ScenePersistence::SaveUpdatedIcon(const std::shared_ptr<Media::PixelMap>& pixelMap)
{
if (pixelMap == nullptr || updatedIconPath_.find('/') == std::string::npos) {
return;
}
SaveIcon(pixelMap, updatedIconPath_);
}
std::string ScenePersistence::GetUpdatedIconPath() const
{
return updatedIconPath_;
}
void ScenePersistence::SaveAbilityIcon(const std::shared_ptr<Media::PixelMap>& pixelMap)
{
if (pixelMap == nullptr || abilityIconPath_.find('/') == std::string::npos) {
return;
}
SaveIcon(pixelMap, abilityIconPath_);
}
std::string ScenePersistence::GetAbilityIconPath() const
{
return abilityIconPath_;
}
void ScenePersistence::SaveIcon(const std::shared_ptr<Media::PixelMap>& pixelMap, std::string iconPath)
{
OHOS::Media::ImagePacker imagePacker;
OHOS::Media::PackOption option;
option.format = IMAGE_FORMAT;
option.quality = IMAGE_QUALITY;
option.numberHint = 1;
if (pixelMap->GetWidth() > ICON_IMAGE_WIDTH_HEIGHT_SIZE || pixelMap->GetHeight() > ICON_IMAGE_WIDTH_HEIGHT_SIZE) {
double xScale = pixelMap->GetWidth() > ICON_IMAGE_WIDTH_HEIGHT_SIZE ?
ICON_IMAGE_WIDTH_HEIGHT_SIZE / ((double) pixelMap->GetWidth()) : ICON_IMAGE_MAX_SCALE;
double yScale = pixelMap->GetHeight() > ICON_IMAGE_WIDTH_HEIGHT_SIZE ?
ICON_IMAGE_WIDTH_HEIGHT_SIZE / ((double) pixelMap->GetHeight()) : ICON_IMAGE_MAX_SCALE;
pixelMap->scale(xScale, yScale, Media::AntiAliasingOption::MEDIUM);
}
if (remove(iconPath.c_str())) {
TLOGD(WmsLogTag::DEFAULT, "Failed to delete old file");
}
if (imagePacker.StartPacking(iconPath, option)) {
TLOGE(WmsLogTag::DEFAULT, "Save icon failed, starting packing error");
return;
}
if (imagePacker.AddImage(*pixelMap)) {
TLOGE(WmsLogTag::DEFAULT, "Save icon failed, adding image error");
return;
}
int64_t packedSize = 0;
if (imagePacker.FinalizePacking(packedSize)) {
TLOGE(WmsLogTag::DEFAULT, "Save icon failed, finalizing packing error");
return;
}
TLOGD(WmsLogTag::DEFAULT, "SaveIcon finished");
}
void ScenePersistence::SetSnapshotSize(SnapshotStatus key, bool freeMultiWindow, bool isScaledSnapshot,
std::pair<uint32_t, uint32_t> size)
{
std::lock_guard lock(snapshotSizeMutex_);
if (isScaledSnapshot) {
snapshotScaledSize_ = size;
return;
}
if (freeMultiWindow) {
snapshotFreeMultiWindowSize_ = size;
return;
}
snapshotSize_[key] = size;
}
std::pair<uint32_t, uint32_t> ScenePersistence::GetSnapshotSize(SnapshotStatus key, bool freeMultiWindow,
bool isScaledSnapshot) const
{
std::lock_guard lock(snapshotSizeMutex_);
if (isScaledSnapshot) {
return snapshotScaledSize_;
}
if (freeMultiWindow) {
return snapshotFreeMultiWindowSize_;
}
return snapshotSize_[key];
}
void ScenePersistence::SetHasSnapshot(bool hasSnapshot, SnapshotStatus key)
{
std::lock_guard lock(hasSnapshotMutex_);
hasSnapshot_[key] = hasSnapshot;
}
void ScenePersistence::SetHasSnapshotFreeMultiWindow(bool hasSnapshot)
{
std::lock_guard lock(hasSnapshotMutex_);
hasSnapshotFreeMultiWindow_ = hasSnapshot;
}
bool ScenePersistence::HasSnapshot() const
{
std::lock_guard lock(hasSnapshotMutex_);
for (const auto& hasSnapshot : hasSnapshot_) {
if (hasSnapshot) {
return true;
}
}
return hasSnapshotFreeMultiWindow_;
}
bool ScenePersistence::HasSnapshot(SnapshotStatus key, bool freeMultiWindow) const
{
std::lock_guard lock(hasSnapshotMutex_);
if (freeMultiWindow) {
return hasSnapshotFreeMultiWindow_;
}
return hasSnapshot_[key];
}
void ScenePersistence::ClearSnapshot()
{
std::lock_guard lock(hasSnapshotMutex_);
for (auto& hasSnapshot : hasSnapshot_) {
hasSnapshot = false;
}
hasSnapshotFreeMultiWindow_ = false;
}
bool ScenePersistence::IsSnapshotExisted(SnapshotStatus key, bool freeMultiWindow)
{
HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "IsSnapshotExisted");
struct stat buf;
auto snapshotPath = GetSnapshotFilePath(key, true, freeMultiWindow);
if (stat(snapshotPath.c_str(), &buf)) {
TLOGD(WmsLogTag::WMS_PATTERN, "Snapshot file %{public}s does not exist",
snapshotPath.c_str());
return false;
}
if (!S_ISREG(buf.st_mode)) {
return false;
}
SetHasSnapshot(true, key);
return true;
}
std::shared_ptr<Media::PixelMap> ScenePersistence::GetLocalSnapshotPixelMap(const float oriScale,
const float newScale, SnapshotStatus key, bool freeMultiWindow)
{
if (!IsSnapshotExisted(key, freeMultiWindow)) {
TLOGE(WmsLogTag::WMS_PATTERN, "local snapshot pic is not existed");
return nullptr;
}
uint32_t errorCode = 0;
Media::SourceOptions sourceOpts;
const char *astcImageFormat = this->isPcWindow_ ? ASTC_IMAGE_FORMAT_LOW : ASTC_IMAGE_FORMAT_HIGH;
sourceOpts.formatHint = IsAstcEnabled() ? astcImageFormat : IMAGE_FORMAT;
std::string path = GetSnapshotFilePath(key, true, freeMultiWindow);
std::lock_guard lock(savingSnapshotMutex_);
auto imageSource = Media::ImageSource::CreateImageSource(path, sourceOpts, errorCode);
if (!imageSource) {
TLOGE(WmsLogTag::WMS_PATTERN, "create image source fail, errCode: %{public}u", errorCode);
return nullptr;
}
Media::ImageInfo info;
int32_t decoderWidth = 0;
int32_t decoderHeight = 0;
errorCode = imageSource->GetImageInfo(info);
if (errorCode == Rosen::SUCCESS) {
decoderWidth = info.size.width;
decoderHeight = info.size.height;
}
Media::DecodeOptions decodeOpts;
decodeOpts.desiredPixelFormat = Media::PixelFormat::RGBA_8888;
if (oriScale != 0 && decoderWidth > 0 && decoderHeight > 0) {
auto isNeedToScale = newScale < oriScale;
decodeOpts.desiredSize.width = isNeedToScale ?
static_cast<int>(decoderWidth * newScale / oriScale) : decoderWidth;
decodeOpts.desiredSize.height = isNeedToScale ?
static_cast<int>(decoderHeight * newScale / oriScale) : decoderHeight;
}
return imageSource->CreatePixelMap(decodeOpts, errorCode);
}
}