• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 "session/host/include/scene_persistence.h"
17 
18 #include <hitrace_meter.h>
19 #include <image_packer.h>
20 
21 #include "window_manager_hilog.h"
22 
23 namespace OHOS::Rosen {
24 namespace {
25 constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, HILOG_DOMAIN_WINDOW, "ScenePersistence" };
26 constexpr const char* UNDERLINE_SEPARATOR = "_";
27 constexpr const char* IMAGE_SUFFIX = ".png";
28 constexpr uint8_t IMAGE_QUALITY = 100;
29 constexpr uint8_t SUCCESS = 0;
30 const std::string SNAPSHOT_THREAD = "OS_SnapshotThread";
31 } // namespace
32 
33 std::string ScenePersistence::snapshotDirectory_;
34 std::string ScenePersistence::updatedIconDirectory_;
35 std::shared_ptr<TaskScheduler> ScenePersistence::snapshotScheduler_;
36 
CreateSnapshotDir(const std::string & directory)37 bool ScenePersistence::CreateSnapshotDir(const std::string& directory)
38 {
39     snapshotDirectory_ = directory + "/SceneSnapShot/";
40     if (mkdir(snapshotDirectory_.c_str(), S_IRWXU)) {
41         WLOGFD("mkdir failed or the directory already exists");
42         return false;
43     }
44     return true;
45 }
46 
CreateUpdatedIconDir(const std::string & directory)47 bool ScenePersistence::CreateUpdatedIconDir(const std::string& directory)
48 {
49     updatedIconDirectory_ = directory + "/UpdatedIcon/";
50     if (mkdir(updatedIconDirectory_.c_str(), S_IRWXU)) {
51         WLOGFD("mkdir failed or the directory already exists");
52         return false;
53     }
54     return true;
55 }
56 
ScenePersistence(const std::string & bundleName,const int32_t & persistentId)57 ScenePersistence::ScenePersistence(const std::string& bundleName, const int32_t& persistentId)
58 {
59     bundleName_ = bundleName;
60     uint32_t fileID = static_cast<uint32_t>(persistentId) & 0x3fffffff;
61     snapshotPath_ = snapshotDirectory_ + bundleName + UNDERLINE_SEPARATOR + std::to_string(fileID) + IMAGE_SUFFIX;
62     updatedIconPath_ = updatedIconDirectory_ + bundleName + IMAGE_SUFFIX;
63     if (snapshotScheduler_ == nullptr) {
64         snapshotScheduler_ = std::make_shared<TaskScheduler>(SNAPSHOT_THREAD);
65     }
66 }
67 
SaveSnapshot(const std::shared_ptr<Media::PixelMap> & pixelMap,const std::function<void ()> resetSnapshotCallback)68 void ScenePersistence::SaveSnapshot(const std::shared_ptr<Media::PixelMap>& pixelMap,
69     const std::function<void()> resetSnapshotCallback)
70 {
71     savingSnapshotSum_.fetch_add(1);
72     isSavingSnapshot_.store(true);
73     auto task = [weakThis = wptr(this), pixelMap, resetSnapshotCallback,
74         savingSnapshotSum = savingSnapshotSum_.load()]() {
75         auto scenePersistence = weakThis.promote();
76         if (scenePersistence == nullptr || pixelMap == nullptr ||
77             scenePersistence->snapshotPath_.find('/') == std::string::npos) {
78             WLOGFE("scenePersistence is%{public}s nullptr, pixelMap is%{public}s nullptr",
79                 scenePersistence == nullptr ? "" : " not", pixelMap == nullptr ? "" : " not");
80             return;
81         }
82 
83         WLOGFD("Save snapshot begin");
84         HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "ScenePersistence:SaveSnapshot %s",
85             scenePersistence->snapshotPath_.c_str());
86         OHOS::Media::ImagePacker imagePacker;
87         OHOS::Media::PackOption option;
88         option.format = "image/png";
89         option.quality = IMAGE_QUALITY;
90         option.numberHint = 1;
91         std::set<std::string> formats;
92         if (imagePacker.GetSupportedFormats(formats)) {
93             WLOGFE("Failed to get supported formats");
94             return;
95         }
96 
97         if (remove(scenePersistence->snapshotPath_.c_str())) {
98             WLOGFE("Failed to delete old file");
99         }
100         scenePersistence->snapshotSize_ = { pixelMap->GetWidth(), pixelMap->GetHeight() };
101         imagePacker.StartPacking(scenePersistence->snapshotPath_, option);
102         imagePacker.AddImage(*pixelMap);
103         int64_t packedSize = 0;
104         imagePacker.FinalizePacking(packedSize);
105         // If the current num is equals to the latest num, it is the last saveSnapshot task
106         if (savingSnapshotSum == scenePersistence->savingSnapshotSum_.load()) {
107             resetSnapshotCallback();
108             scenePersistence->isSavingSnapshot_.store(false);
109         }
110         WLOGFD("Save snapshot end, packed size %{public}" PRIu64, packedSize);
111     };
112     snapshotScheduler_->RemoveTask("SaveSnapshot" + snapshotPath_);
113     snapshotScheduler_->PostAsyncTask(task, "SaveSnapshot" + snapshotPath_);
114 }
115 
IsSavingSnapshot()116 bool ScenePersistence::IsSavingSnapshot()
117 {
118     return isSavingSnapshot_.load();
119 }
120 
RenameSnapshotFromOldPersistentId(const int32_t & oldPersistentId)121 void ScenePersistence::RenameSnapshotFromOldPersistentId(const int32_t &oldPersistentId)
122 {
123     auto task = [weakThis = wptr(this), oldPersistentId]() {
124         auto scenePersistence = weakThis.promote();
125         if (scenePersistence == nullptr) {
126             WLOGFE("scenePersistence is nullptr");
127             return;
128         }
129         uint32_t oldfileID = static_cast<uint32_t>(oldPersistentId) & 0x3fffffff;
130         std::string oldSnapshotPath_ = snapshotDirectory_ + scenePersistence->bundleName_ + UNDERLINE_SEPARATOR +
131                                        std::to_string(oldfileID) + IMAGE_SUFFIX;
132         int ret = std::rename(oldSnapshotPath_.c_str(), scenePersistence->snapshotPath_.c_str());
133         if (ret == 0) {
134             WLOGFI("Rename snapshot from %{public}s to %{public}s.",
135                 oldSnapshotPath_.c_str(), scenePersistence->snapshotPath_.c_str());
136         } else {
137             WLOGFW("Failed to rename snapshot from %{public}s to %{public}s.",
138                 oldSnapshotPath_.c_str(), scenePersistence->snapshotPath_.c_str());
139         }
140     };
141     snapshotScheduler_->PostAsyncTask(task, "RenameSnapshotFromOldPersistentId");
142 }
143 
GetSnapshotFilePath()144 std::string ScenePersistence::GetSnapshotFilePath()
145 {
146     auto task = [weakThis = wptr(this)]() -> std::string {
147         auto scenePersistence = weakThis.promote();
148         if (scenePersistence == nullptr) {
149             WLOGFE("scenePersistence is nullptr");
150             return "";
151         }
152         return scenePersistence->snapshotPath_;
153     };
154     return snapshotScheduler_->PostSyncTask(task, "GetSnapshotFilePath");
155 }
156 
GetSnapshotFilePathFromAce()157 std::string ScenePersistence::GetSnapshotFilePathFromAce()
158 {
159     return snapshotPath_;
160 }
161 
SaveUpdatedIcon(const std::shared_ptr<Media::PixelMap> & pixelMap)162 void ScenePersistence::SaveUpdatedIcon(const std::shared_ptr<Media::PixelMap>& pixelMap)
163 {
164     if (pixelMap == nullptr || updatedIconPath_.find('/') == std::string::npos) {
165         return;
166     }
167 
168     OHOS::Media::ImagePacker imagePacker;
169     OHOS::Media::PackOption option;
170     option.format = "image/png";
171     option.quality = IMAGE_QUALITY;
172     option.numberHint = 1;
173     std::set<std::string> formats;
174     if (imagePacker.GetSupportedFormats(formats)) {
175         WLOGFE("Failed to get supported formats");
176         return;
177     }
178 
179     if (remove(updatedIconPath_.c_str())) {
180         WLOGFD("Failed to delete old file");
181     }
182     imagePacker.StartPacking(GetUpdatedIconPath(), option);
183     imagePacker.AddImage(*pixelMap);
184     int64_t packedSize = 0;
185     imagePacker.FinalizePacking(packedSize);
186     WLOGFD("SaveUpdatedIcon finished");
187 }
188 
GetUpdatedIconPath() const189 std::string ScenePersistence::GetUpdatedIconPath() const
190 {
191     return updatedIconPath_;
192 }
193 
GetSnapshotSize() const194 std::pair<uint32_t, uint32_t> ScenePersistence::GetSnapshotSize() const
195 {
196     return snapshotSize_;
197 }
198 
IsSnapshotExisted() const199 bool ScenePersistence::IsSnapshotExisted() const
200 {
201     struct stat buf;
202     if (stat(snapshotPath_.c_str(), &buf)) {
203         WLOGFD("Snapshot file %{public}s does not exist", snapshotPath_.c_str());
204         return false;
205     }
206     return S_ISREG(buf.st_mode);
207 }
208 
GetLocalSnapshotPixelMap(const float oriScale,const float newScale) const209 std::shared_ptr<Media::PixelMap> ScenePersistence::GetLocalSnapshotPixelMap(const float oriScale,
210     const float newScale) const
211 {
212     if (!IsSnapshotExisted()) {
213         WLOGE("local snapshot pic is not existed");
214         return nullptr;
215     }
216 
217     uint32_t errorCode = 0;
218     Media::SourceOptions sourceOpts;
219     sourceOpts.formatHint = "image/png";
220     auto imageSource = Media::ImageSource::CreateImageSource(snapshotPath_, sourceOpts, errorCode);
221     if (!imageSource) {
222         WLOGE("create image source fail, errCode : %{public}d", errorCode);
223         return nullptr;
224     }
225 
226     Media::ImageInfo info;
227     int32_t decoderWidth = 0;
228     int32_t decoderHeight = 0;
229     errorCode = imageSource->GetImageInfo(info);
230     if (errorCode == SUCCESS) {
231         decoderWidth = info.size.width;
232         decoderHeight = info.size.height;
233     }
234     Media::DecodeOptions decodeOpts;
235     decodeOpts.desiredPixelFormat = Media::PixelFormat::RGBA_8888;
236     if (oriScale != 0 && decoderWidth > 0 && decoderHeight > 0) {
237         auto isNeedToScale = newScale < oriScale;
238         decodeOpts.desiredSize.width = isNeedToScale ?
239             static_cast<int>(decoderWidth * newScale / oriScale) : decoderWidth;
240         decodeOpts.desiredSize.height = isNeedToScale ?
241             static_cast<int>(decoderHeight * newScale / oriScale) : decoderHeight;
242     }
243     return imageSource->CreatePixelMap(decodeOpts, errorCode);
244 }
245 } // namespace OHOS::Rosen
246