1 /*
2 * Copyright (c) 2021-2022 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 "mission/snapshot.h"
17
18 #include <sstream>
19 #include "datetime_ex.h"
20 #include "dtbschedmgr_log.h"
21 #include "image_source.h"
22 #include "image_packer.h"
23 #include "parcel_helper.h"
24 #include "pixel_map_parcel.h"
25 #include "string_ex.h"
26
27 using namespace std;
28 using namespace OHOS::Media;
29
30 namespace OHOS {
31 namespace DistributedSchedule {
32 namespace {
33 const std::string TAG = "Snapshot";
34 constexpr int32_t COMPRESS_QUALITY = 85;
35 constexpr size_t PIXEL_MAP_MAX_BUFFER_SIZE = 600 * 1024;
36 constexpr size_t INT_BYTE = 4;
37 }
38
~Snapshot()39 Snapshot::~Snapshot()
40 {
41 HILOGD("Snapshot destruct!");
42 }
43
WriteToParcel(MessageParcel & data) const44 bool Snapshot::WriteToParcel(MessageParcel& data) const
45 {
46 PARCEL_WRITE_HELPER_RET(data, Int32, 1, false);
47 PARCEL_WRITE_HELPER_RET(data, Int32, orientation_, false);
48 if (rect_ != nullptr) {
49 PARCEL_WRITE_HELPER_RET(data, Parcelable, rect_.get(), false);
50 } else {
51 PARCEL_WRITE_HELPER_RET(data, Parcelable, nullptr, false);
52 }
53 PARCEL_WRITE_HELPER_RET(data, Bool, reducedResolution_, false);
54 PARCEL_WRITE_HELPER_RET(data, Float, scale_, false);
55 PARCEL_WRITE_HELPER_RET(data, Bool, isRealSnapshot_, false);
56 PARCEL_WRITE_HELPER_RET(data, Int32, windowingMode_, false);
57 PARCEL_WRITE_HELPER_RET(data, Int32, systemUiVisibility_, false);
58 PARCEL_WRITE_HELPER_RET(data, Bool, isTranslucent_, false);
59 if (windowBounds_ != nullptr) {
60 PARCEL_WRITE_HELPER_RET(data, Parcelable, windowBounds_.get(), false);
61 } else {
62 PARCEL_WRITE_HELPER_RET(data, Parcelable, nullptr, false);
63 }
64 PARCEL_WRITE_HELPER_RET(data, String16, appLabel_, false);
65 PARCEL_WRITE_HELPER_RET(data, String16, abilityLabel_, false);
66 PARCEL_WRITE_HELPER_RET(data, UInt8Vector, icon_, false);
67 PARCEL_WRITE_HELPER_RET(data, String16, secAppLabel_, false);
68 PARCEL_WRITE_HELPER_RET(data, String16, secAbilityLabel_, false);
69 PARCEL_WRITE_HELPER_RET(data, UInt8Vector, secIcon_, false);
70 PARCEL_WRITE_HELPER_RET(data, String16, sourceDeviceTips_, false);
71 if (pixelMap_ != nullptr) {
72 PARCEL_WRITE_HELPER_RET(data, Int32, 1, false);
73 bool ret = PixelMapParcel::WriteToParcel(pixelMap_.get(), data);
74 if (!ret) {
75 HILOGE("Snapshot WriteToParcel pixelMap failed!");
76 return false;
77 }
78 } else {
79 PARCEL_WRITE_HELPER_RET(data, Parcelable, nullptr, false);
80 }
81 return true;
82 }
83
FillSnapShot(MessageParcel & data)84 unique_ptr<Snapshot> Snapshot::FillSnapShot(MessageParcel& data)
85 {
86 int32_t version = 0;
87 PARCEL_READ_HELPER_RET(data, Int32, version, nullptr);
88 int32_t orientation = 0;
89 PARCEL_READ_HELPER_RET(data, Int32, orientation, nullptr);
90 unique_ptr<Rect> rect(data.ReadParcelable<Rect>());
91 bool reduced = false;
92 PARCEL_READ_HELPER_RET(data, Bool, reduced, nullptr);
93 float scale = 0.0;
94 PARCEL_READ_HELPER_RET(data, Float, scale, nullptr);
95 bool isRealSnapshot = false;
96 PARCEL_READ_HELPER_RET(data, Bool, isRealSnapshot, nullptr);
97 int32_t windowingMode = 0;
98 PARCEL_READ_HELPER_RET(data, Int32, windowingMode, nullptr);
99 int32_t systemUiVisibility = 0;
100 PARCEL_READ_HELPER_RET(data, Int32, systemUiVisibility, nullptr);
101 bool isTranslucent = false;
102 PARCEL_READ_HELPER_RET(data, Bool, isTranslucent, nullptr);
103 unique_ptr<Rect> windowBounds(data.ReadParcelable<Rect>());
104 std::u16string appLabel = data.ReadString16();
105 std::u16string abilityLabel = data.ReadString16();
106 std::vector<uint8_t> icon;
107 PARCEL_READ_HELPER_RET(data, UInt8Vector, &icon, nullptr);
108 std::u16string secAppLabel = data.ReadString16();
109 std::u16string secAbilityLabel = data.ReadString16();
110 std::vector<uint8_t> secIcon;
111 PARCEL_READ_HELPER_RET(data, UInt8Vector, &secIcon, nullptr);
112 std::u16string sourceDeviceTips = data.ReadString16();
113 unique_ptr<Snapshot> snapShot = make_unique<Snapshot>();
114 snapShot->version_ = version;
115 snapShot->orientation_ = orientation;
116 snapShot->rect_ = std::move(rect);
117 snapShot->reducedResolution_ = reduced;
118 snapShot->scale_ = scale;
119 snapShot->isRealSnapshot_ = isRealSnapshot;
120 snapShot->windowingMode_ = windowingMode;
121 snapShot->systemUiVisibility_ = systemUiVisibility;
122 snapShot->isTranslucent_ = isTranslucent;
123 snapShot->windowBounds_ = std::move(windowBounds);
124 snapShot->appLabel_ = appLabel;
125 snapShot->abilityLabel_ = abilityLabel;
126 snapShot->icon_ = icon;
127 snapShot->secAppLabel_ = secAppLabel;
128 snapShot->secAbilityLabel_ = secAbilityLabel;
129 snapShot->secIcon_ = secIcon;
130 snapShot->sourceDeviceTips_ = sourceDeviceTips;
131 return snapShot;
132 }
133
CreatePixelMap(const uint8_t * buffer,uint32_t bufferSize)134 unique_ptr<PixelMap> Snapshot::CreatePixelMap(const uint8_t* buffer, uint32_t bufferSize)
135 {
136 if (buffer == nullptr || bufferSize == 0) {
137 HILOGE("Snapshot CreatePixelMap invalid params!");
138 return nullptr;
139 }
140 SourceOptions opts;
141 uint32_t errCode = 0;
142 opts.formatHint = "image/jpeg";
143 unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(buffer, bufferSize, opts, errCode);
144 if (imageSource == nullptr) {
145 HILOGE("Snapshot CreatePixelMap create image source failed!");
146 return nullptr;
147 }
148 DecodeOptions decodeOpt;
149 decodeOpt.allocatorType = AllocatorType::SHARE_MEM_ALLOC;
150 decodeOpt.desiredPixelFormat = PixelFormat::RGBA_8888;
151 int64_t begin = GetTickCount();
152 unique_ptr<PixelMap> pixelMap = imageSource->CreatePixelMap(decodeOpt, errCode);
153 HILOGI("[PerformanceTest] Create PixelMap spend %{public}" PRId64 " ms", GetTickCount() - begin);
154 if (pixelMap == nullptr || errCode != 0) {
155 HILOGW("Snapshot: CreatePixelMap failed, errCode:%{public}u!", errCode);
156 return nullptr;
157 }
158 return pixelMap;
159 }
160
Create(const vector<uint8_t> & data)161 unique_ptr<Snapshot> Snapshot::Create(const vector<uint8_t>& data)
162 {
163 auto dataBuffer = data.data();
164 auto totalSize = data.size();
165 if (totalSize < sizeof(int32_t)) {
166 HILOGE("Snapshot invalid data !");
167 return nullptr;
168 }
169 uint32_t msgSize = *reinterpret_cast<const uint32_t *>(dataBuffer);
170 if (msgSize >= totalSize || msgSize + sizeof(uint32_t) >= totalSize) {
171 HILOGE("Snapshot dataParcel invalid data !");
172 return nullptr;
173 }
174 dataBuffer += sizeof(uint32_t);
175 MessageParcel dataParcel;
176 bool ret = dataParcel.WriteBuffer(dataBuffer, msgSize);
177 if (!ret) {
178 HILOGE("Snapshot dataParcel write failed!");
179 return nullptr;
180 }
181 unique_ptr<Snapshot> snapShot = FillSnapShot(dataParcel);
182 if (snapShot == nullptr) {
183 HILOGW("Snapshot: FillSnapShot failed!");
184 return nullptr;
185 }
186 dataBuffer += msgSize;
187 uint32_t remainSize = totalSize - msgSize - sizeof(uint32_t);
188 if (remainSize < sizeof(uint32_t)) {
189 HILOGE("Snapshot dataParcel remainSize invalid!");
190 return nullptr;
191 }
192 uint32_t pixelmapLen = *reinterpret_cast<const uint32_t *>(dataBuffer);
193 if (pixelmapLen >= remainSize || pixelmapLen + sizeof(uint32_t) > remainSize) {
194 HILOGE("Snapshot dataParcel buffer broken, should not happens!");
195 return nullptr;
196 }
197 dataBuffer += sizeof(uint32_t);
198 unique_ptr<PixelMap> pixelMap = CreatePixelMap(dataBuffer, pixelmapLen);
199 if (pixelMap != nullptr) {
200 HILOGD("create pixelMap width:%{public}d, height:%{public}d, byteCount:%{public}d, pixelformat:%{public}d",
201 pixelMap->GetWidth(), pixelMap->GetHeight(), pixelMap->GetByteCount(),
202 static_cast<int32_t>(pixelMap->GetPixelFormat()));
203 snapShot->pixelMap_ = std::move(pixelMap);
204 }
205 snapShot->createdTime_ = GetTickCount();
206 snapShot->lastAccessTime_ = snapShot->createdTime_;
207 return snapShot;
208 }
209
WriteSnapshotInfo(MessageParcel & data) const210 bool Snapshot::WriteSnapshotInfo(MessageParcel& data) const
211 {
212 MessageParcel parcel;
213 PARCEL_WRITE_HELPER_RET(parcel, Int32, version_, false); // for dms version
214 PARCEL_WRITE_HELPER_RET(parcel, Int32, orientation_, false); // for orientation
215 PARCEL_WRITE_HELPER_RET(parcel, Parcelable, rect_.get(), false); // for contentInsets
216 PARCEL_WRITE_HELPER_RET(parcel, Bool, reducedResolution_, false); // for reduceResolution
217 PARCEL_WRITE_HELPER_RET(parcel, Float, scale_, false); // for scale
218 PARCEL_WRITE_HELPER_RET(parcel, Bool, isRealSnapshot_, false); // for isRealSnapshot
219 PARCEL_WRITE_HELPER_RET(parcel, Int32, windowingMode_, false); // for windowingMode
220 PARCEL_WRITE_HELPER_RET(parcel, Int32, systemUiVisibility_, false); // for systemUiVisibility
221 PARCEL_WRITE_HELPER_RET(parcel, Bool, isTranslucent_, false); // for isTranslucent
222 PARCEL_WRITE_HELPER_RET(parcel, Parcelable, windowBounds_.get(), false); // for windowBounds
223 PARCEL_WRITE_HELPER_RET(parcel, String16, appLabel_, false); // for appLabel
224 PARCEL_WRITE_HELPER_RET(parcel, String16, abilityLabel_, false); // for abilityLabel
225 PARCEL_WRITE_HELPER_RET(parcel, UInt8Vector, icon_, false); // for icon
226 PARCEL_WRITE_HELPER_RET(parcel, String16, secAppLabel_, false); // for secAppLabel
227 PARCEL_WRITE_HELPER_RET(parcel, String16, secAbilityLabel_, false); // for secAbilityLabel
228 PARCEL_WRITE_HELPER_RET(parcel, UInt8Vector, secIcon_, false); // for secIcon
229 PARCEL_WRITE_HELPER_RET(parcel, String16, sourceDeviceTips_, false); // for sourceDeviceTips
230 size_t infoSize = parcel.GetReadableBytes();
231 const uint8_t* infoBuffer = parcel.ReadBuffer(infoSize);
232 PARCEL_WRITE_HELPER_RET(data, Uint32, infoSize, false); // for snapshot info size
233 bool ret = data.WriteBuffer(infoBuffer, infoSize); // for snapshot info buffer
234 if (!ret) {
235 HILOGE("snapshot info write parcel failed!");
236 return false;
237 }
238 return true;
239 }
240
WritePixelMap(MessageParcel & data) const241 bool Snapshot::WritePixelMap(MessageParcel& data) const
242 {
243 ImagePacker imagePacker;
244 PackOption option;
245 option.format = "image/jpeg";
246 option.quality = COMPRESS_QUALITY;
247 option.numberHint = 1;
248 stringstream ss;
249 std::ostream outputStream(ss.rdbuf());
250 imagePacker.StartPacking(outputStream, option);
251 imagePacker.AddImage(*pixelMap_);
252 imagePacker.FinalizePacking();
253 std::istream inputStream(outputStream.rdbuf());
254 inputStream.seekg(0, inputStream.end);
255 size_t len = inputStream.tellg();
256 inputStream.seekg(0);
257 HILOGD("pixelMap compress size:%{public}zu", len);
258 if (len > PIXEL_MAP_MAX_BUFFER_SIZE) {
259 HILOGD("pixelMap size is too big.");
260 return false;
261 }
262 std::unique_ptr<char[]> pixelMapBuffer = make_unique<char[]>(len);
263 inputStream.read(pixelMapBuffer.get(), len);
264 uint8_t* byteStream = reinterpret_cast<uint8_t*>(pixelMapBuffer.get());
265 size_t minCapacity = data.GetReadableBytes() + len + INT_BYTE;
266 if (minCapacity % INT_BYTE != 0) {
267 HILOGI("bytes are not aligned!");
268 minCapacity += INT_BYTE;
269 }
270 if (minCapacity > data.GetDataCapacity() && !data.SetDataCapacity(minCapacity)) {
271 HILOGE("setCapacity failed! length = %{public}zu.", minCapacity);
272 return false;
273 }
274 PARCEL_WRITE_HELPER_RET(data, Uint32, len, false); // for pixel map size
275 bool ret = data.WriteBuffer(byteStream, len); // for pixel map buffer
276 if (!ret) {
277 HILOGE("pixel map write parcel failed!");
278 return false;
279 }
280 return true;
281 }
282
GetCreatedTime() const283 int64_t Snapshot::GetCreatedTime() const
284 {
285 return createdTime_;
286 }
287
GetLastAccessTime() const288 int64_t Snapshot::GetLastAccessTime() const
289 {
290 return lastAccessTime_;
291 }
292
UpdateLastAccessTime(int64_t accessTime)293 void Snapshot::UpdateLastAccessTime(int64_t accessTime)
294 {
295 lastAccessTime_ = accessTime;
296 }
297 }
298 }
299