• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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