1686862fbSopenharmony_ci/*
2686862fbSopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3686862fbSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4686862fbSopenharmony_ci * you may not use this file except in compliance with the License.
5686862fbSopenharmony_ci * You may obtain a copy of the License at
6686862fbSopenharmony_ci *
7686862fbSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8686862fbSopenharmony_ci *
9686862fbSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10686862fbSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11686862fbSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12686862fbSopenharmony_ci * See the License for the specific language governing permissions and
13686862fbSopenharmony_ci * limitations under the License.
14686862fbSopenharmony_ci */
15686862fbSopenharmony_ci
16686862fbSopenharmony_ci#include "mission/snapshot.h"
17686862fbSopenharmony_ci
18686862fbSopenharmony_ci#include <sstream>
19686862fbSopenharmony_ci#include "datetime_ex.h"
20686862fbSopenharmony_ci#include "dtbschedmgr_log.h"
21686862fbSopenharmony_ci#include "image_source.h"
22686862fbSopenharmony_ci#include "image_packer.h"
23686862fbSopenharmony_ci#include "parcel_helper.h"
24686862fbSopenharmony_ci#include "pixel_map_parcel.h"
25686862fbSopenharmony_ci#include "string_ex.h"
26686862fbSopenharmony_ci
27686862fbSopenharmony_ciusing namespace std;
28686862fbSopenharmony_ciusing namespace OHOS::Media;
29686862fbSopenharmony_ci
30686862fbSopenharmony_cinamespace OHOS {
31686862fbSopenharmony_cinamespace DistributedSchedule {
32686862fbSopenharmony_cinamespace {
33686862fbSopenharmony_ciconst std::string TAG = "Snapshot";
34686862fbSopenharmony_ciconstexpr int32_t COMPRESS_QUALITY = 85;
35686862fbSopenharmony_ciconstexpr size_t PIXEL_MAP_MAX_BUFFER_SIZE = 600 * 1024;
36686862fbSopenharmony_ciconstexpr size_t INT_BYTE = 4;
37686862fbSopenharmony_ci}
38686862fbSopenharmony_ci
39686862fbSopenharmony_ciSnapshot::~Snapshot()
40686862fbSopenharmony_ci{
41686862fbSopenharmony_ci    HILOGD("Snapshot destruct!");
42686862fbSopenharmony_ci}
43686862fbSopenharmony_ci
44686862fbSopenharmony_cibool Snapshot::WriteToParcel(MessageParcel& data) const
45686862fbSopenharmony_ci{
46686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(data, Int32, 1, false);
47686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(data, Int32, orientation_, false);
48686862fbSopenharmony_ci    if (rect_ != nullptr) {
49686862fbSopenharmony_ci        PARCEL_WRITE_HELPER_RET(data, Parcelable, rect_.get(), false);
50686862fbSopenharmony_ci    } else {
51686862fbSopenharmony_ci        PARCEL_WRITE_HELPER_RET(data, Parcelable, nullptr, false);
52686862fbSopenharmony_ci    }
53686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(data, Bool, reducedResolution_, false);
54686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(data, Float, scale_, false);
55686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(data, Bool, isRealSnapshot_, false);
56686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(data, Int32, windowingMode_, false);
57686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(data, Int32, systemUiVisibility_, false);
58686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(data, Bool, isTranslucent_, false);
59686862fbSopenharmony_ci    if (windowBounds_ != nullptr) {
60686862fbSopenharmony_ci        PARCEL_WRITE_HELPER_RET(data, Parcelable, windowBounds_.get(), false);
61686862fbSopenharmony_ci    } else {
62686862fbSopenharmony_ci        PARCEL_WRITE_HELPER_RET(data, Parcelable, nullptr, false);
63686862fbSopenharmony_ci    }
64686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(data, String16, appLabel_, false);
65686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(data, String16, abilityLabel_, false);
66686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(data, UInt8Vector, icon_, false);
67686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(data, String16, secAppLabel_, false);
68686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(data, String16, secAbilityLabel_, false);
69686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(data, UInt8Vector, secIcon_, false);
70686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(data, String16, sourceDeviceTips_, false);
71686862fbSopenharmony_ci    if (pixelMap_ != nullptr) {
72686862fbSopenharmony_ci        PARCEL_WRITE_HELPER_RET(data, Int32, 1, false);
73686862fbSopenharmony_ci        bool ret = PixelMapParcel::WriteToParcel(pixelMap_.get(), data);
74686862fbSopenharmony_ci        if (!ret) {
75686862fbSopenharmony_ci            HILOGE("Snapshot WriteToParcel pixelMap failed!");
76686862fbSopenharmony_ci            return false;
77686862fbSopenharmony_ci        }
78686862fbSopenharmony_ci    } else {
79686862fbSopenharmony_ci        PARCEL_WRITE_HELPER_RET(data, Parcelable, nullptr, false);
80686862fbSopenharmony_ci    }
81686862fbSopenharmony_ci    return true;
82686862fbSopenharmony_ci}
83686862fbSopenharmony_ci
84686862fbSopenharmony_ciunique_ptr<Snapshot> Snapshot::FillSnapshot(MessageParcel& data)
85686862fbSopenharmony_ci{
86686862fbSopenharmony_ci    int32_t version = 0;
87686862fbSopenharmony_ci    PARCEL_READ_HELPER_RET(data, Int32, version, nullptr);
88686862fbSopenharmony_ci    int32_t orientation = 0;
89686862fbSopenharmony_ci    PARCEL_READ_HELPER_RET(data, Int32, orientation, nullptr);
90686862fbSopenharmony_ci    unique_ptr<Rect> rect(data.ReadParcelable<Rect>());
91686862fbSopenharmony_ci    bool reduced = false;
92686862fbSopenharmony_ci    PARCEL_READ_HELPER_RET(data, Bool, reduced, nullptr);
93686862fbSopenharmony_ci    float scale = 0.0;
94686862fbSopenharmony_ci    PARCEL_READ_HELPER_RET(data, Float, scale, nullptr);
95686862fbSopenharmony_ci    bool isRealSnapshot = false;
96686862fbSopenharmony_ci    PARCEL_READ_HELPER_RET(data, Bool, isRealSnapshot, nullptr);
97686862fbSopenharmony_ci    int32_t windowingMode = 0;
98686862fbSopenharmony_ci    PARCEL_READ_HELPER_RET(data, Int32, windowingMode, nullptr);
99686862fbSopenharmony_ci    int32_t systemUiVisibility = 0;
100686862fbSopenharmony_ci    PARCEL_READ_HELPER_RET(data, Int32, systemUiVisibility, nullptr);
101686862fbSopenharmony_ci    bool isTranslucent = false;
102686862fbSopenharmony_ci    PARCEL_READ_HELPER_RET(data, Bool, isTranslucent, nullptr);
103686862fbSopenharmony_ci    unique_ptr<Rect> windowBounds(data.ReadParcelable<Rect>());
104686862fbSopenharmony_ci    std::u16string appLabel = data.ReadString16();
105686862fbSopenharmony_ci    std::u16string abilityLabel = data.ReadString16();
106686862fbSopenharmony_ci    std::vector<uint8_t> icon;
107686862fbSopenharmony_ci    PARCEL_READ_HELPER_RET(data, UInt8Vector, &icon, nullptr);
108686862fbSopenharmony_ci    std::u16string secAppLabel = data.ReadString16();
109686862fbSopenharmony_ci    std::u16string secAbilityLabel = data.ReadString16();
110686862fbSopenharmony_ci    std::vector<uint8_t> secIcon;
111686862fbSopenharmony_ci    PARCEL_READ_HELPER_RET(data, UInt8Vector, &secIcon, nullptr);
112686862fbSopenharmony_ci    std::u16string sourceDeviceTips = data.ReadString16();
113686862fbSopenharmony_ci    unique_ptr<Snapshot> snapShot = make_unique<Snapshot>();
114686862fbSopenharmony_ci    snapShot->version_ = version;
115686862fbSopenharmony_ci    snapShot->orientation_ = orientation;
116686862fbSopenharmony_ci    snapShot->rect_ = std::move(rect);
117686862fbSopenharmony_ci    snapShot->reducedResolution_ = reduced;
118686862fbSopenharmony_ci    snapShot->scale_ = scale;
119686862fbSopenharmony_ci    snapShot->isRealSnapshot_ = isRealSnapshot;
120686862fbSopenharmony_ci    snapShot->windowingMode_ = windowingMode;
121686862fbSopenharmony_ci    snapShot->systemUiVisibility_ = systemUiVisibility;
122686862fbSopenharmony_ci    snapShot->isTranslucent_ = isTranslucent;
123686862fbSopenharmony_ci    snapShot->windowBounds_ = std::move(windowBounds);
124686862fbSopenharmony_ci    snapShot->appLabel_ = appLabel;
125686862fbSopenharmony_ci    snapShot->abilityLabel_ = abilityLabel;
126686862fbSopenharmony_ci    snapShot->icon_ = icon;
127686862fbSopenharmony_ci    snapShot->secAppLabel_ = secAppLabel;
128686862fbSopenharmony_ci    snapShot->secAbilityLabel_ = secAbilityLabel;
129686862fbSopenharmony_ci    snapShot->secIcon_ = secIcon;
130686862fbSopenharmony_ci    snapShot->sourceDeviceTips_ = sourceDeviceTips;
131686862fbSopenharmony_ci    return snapShot;
132686862fbSopenharmony_ci}
133686862fbSopenharmony_ci
134686862fbSopenharmony_ciunique_ptr<PixelMap> Snapshot::CreatePixelMap(const uint8_t* buffer, uint32_t bufferSize)
135686862fbSopenharmony_ci{
136686862fbSopenharmony_ci    if (buffer == nullptr || bufferSize == 0) {
137686862fbSopenharmony_ci        HILOGE("Snapshot CreatePixelMap invalid params!");
138686862fbSopenharmony_ci        return nullptr;
139686862fbSopenharmony_ci    }
140686862fbSopenharmony_ci    SourceOptions opts;
141686862fbSopenharmony_ci    uint32_t errCode = 0;
142686862fbSopenharmony_ci    opts.formatHint = "image/jpeg";
143686862fbSopenharmony_ci    unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(buffer, bufferSize, opts, errCode);
144686862fbSopenharmony_ci    if (imageSource == nullptr) {
145686862fbSopenharmony_ci        HILOGE("Snapshot CreatePixelMap create image source failed!");
146686862fbSopenharmony_ci        return nullptr;
147686862fbSopenharmony_ci    }
148686862fbSopenharmony_ci    DecodeOptions decodeOpt;
149686862fbSopenharmony_ci    decodeOpt.allocatorType = AllocatorType::SHARE_MEM_ALLOC;
150686862fbSopenharmony_ci    decodeOpt.desiredPixelFormat = PixelFormat::RGBA_8888;
151686862fbSopenharmony_ci    int64_t begin = GetTickCount();
152686862fbSopenharmony_ci    unique_ptr<PixelMap> pixelMap = imageSource->CreatePixelMap(decodeOpt, errCode);
153686862fbSopenharmony_ci    HILOGI("[PerformanceTest] Create PixelMap spend %{public}" PRId64 " ms", GetTickCount() - begin);
154686862fbSopenharmony_ci    if (pixelMap == nullptr || errCode != 0) {
155686862fbSopenharmony_ci        HILOGW("Snapshot: CreatePixelMap failed, errCode:%{public}u!", errCode);
156686862fbSopenharmony_ci        return nullptr;
157686862fbSopenharmony_ci    }
158686862fbSopenharmony_ci    return pixelMap;
159686862fbSopenharmony_ci}
160686862fbSopenharmony_ci
161686862fbSopenharmony_ciunique_ptr<Snapshot> Snapshot::Create(const vector<uint8_t>& data)
162686862fbSopenharmony_ci{
163686862fbSopenharmony_ci    auto dataBuffer = data.data();
164686862fbSopenharmony_ci    auto totalSize = data.size();
165686862fbSopenharmony_ci    if (totalSize < sizeof(int32_t)) {
166686862fbSopenharmony_ci        HILOGE("Snapshot invalid data !");
167686862fbSopenharmony_ci        return nullptr;
168686862fbSopenharmony_ci    }
169686862fbSopenharmony_ci    uint32_t msgSize = *reinterpret_cast<const uint32_t *>(dataBuffer);
170686862fbSopenharmony_ci    if (msgSize >= totalSize || msgSize + sizeof(uint32_t) >= totalSize) {
171686862fbSopenharmony_ci        HILOGE("Snapshot dataParcel invalid data !");
172686862fbSopenharmony_ci        return nullptr;
173686862fbSopenharmony_ci    }
174686862fbSopenharmony_ci    dataBuffer += sizeof(uint32_t);
175686862fbSopenharmony_ci    MessageParcel dataParcel;
176686862fbSopenharmony_ci    bool ret = dataParcel.WriteBuffer(dataBuffer, msgSize);
177686862fbSopenharmony_ci    if (!ret) {
178686862fbSopenharmony_ci        HILOGE("Snapshot dataParcel write failed!");
179686862fbSopenharmony_ci        return nullptr;
180686862fbSopenharmony_ci    }
181686862fbSopenharmony_ci    unique_ptr<Snapshot> snapShot = FillSnapshot(dataParcel);
182686862fbSopenharmony_ci    if (snapShot == nullptr) {
183686862fbSopenharmony_ci        HILOGW("Snapshot: FillSnapshot failed!");
184686862fbSopenharmony_ci        return nullptr;
185686862fbSopenharmony_ci    }
186686862fbSopenharmony_ci    dataBuffer += msgSize;
187686862fbSopenharmony_ci    uint32_t remainSize = totalSize - msgSize - sizeof(uint32_t);
188686862fbSopenharmony_ci    if (remainSize < sizeof(uint32_t)) {
189686862fbSopenharmony_ci        HILOGE("Snapshot dataParcel remainSize invalid!");
190686862fbSopenharmony_ci        return nullptr;
191686862fbSopenharmony_ci    }
192686862fbSopenharmony_ci    uint32_t pixelmapLen = *reinterpret_cast<const uint32_t *>(dataBuffer);
193686862fbSopenharmony_ci    if (pixelmapLen >= remainSize || pixelmapLen + sizeof(uint32_t) > remainSize) {
194686862fbSopenharmony_ci        HILOGE("Snapshot dataParcel buffer broken, should not happens!");
195686862fbSopenharmony_ci        return nullptr;
196686862fbSopenharmony_ci    }
197686862fbSopenharmony_ci    dataBuffer += sizeof(uint32_t);
198686862fbSopenharmony_ci    unique_ptr<PixelMap> pixelMap = CreatePixelMap(dataBuffer, pixelmapLen);
199686862fbSopenharmony_ci    if (pixelMap != nullptr) {
200686862fbSopenharmony_ci        HILOGD("create pixelMap width:%{public}d, height:%{public}d, byteCount:%{public}d, pixelformat:%{public}d",
201686862fbSopenharmony_ci            pixelMap->GetWidth(), pixelMap->GetHeight(), pixelMap->GetByteCount(),
202686862fbSopenharmony_ci            static_cast<int32_t>(pixelMap->GetPixelFormat()));
203686862fbSopenharmony_ci        snapShot->pixelMap_ = std::move(pixelMap);
204686862fbSopenharmony_ci    }
205686862fbSopenharmony_ci    snapShot->createdTime_ = GetTickCount();
206686862fbSopenharmony_ci    snapShot->lastAccessTime_ = snapShot->createdTime_;
207686862fbSopenharmony_ci    return snapShot;
208686862fbSopenharmony_ci}
209686862fbSopenharmony_ci
210686862fbSopenharmony_cibool Snapshot::WriteSnapshotInfo(MessageParcel& data) const
211686862fbSopenharmony_ci{
212686862fbSopenharmony_ci    MessageParcel parcel;
213686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(parcel, Int32, version_, false); // for dms version
214686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(parcel, Int32, orientation_, false); // for orientation
215686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(parcel, Parcelable, rect_.get(), false); // for contentInsets
216686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(parcel, Bool, reducedResolution_, false); // for reduceResolution
217686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(parcel, Float, scale_, false); // for scale
218686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(parcel, Bool, isRealSnapshot_, false); // for isRealSnapshot
219686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(parcel, Int32, windowingMode_, false); // for windowingMode
220686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(parcel, Int32, systemUiVisibility_, false); // for systemUiVisibility
221686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(parcel, Bool, isTranslucent_, false); // for isTranslucent
222686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(parcel, Parcelable, windowBounds_.get(), false); // for windowBounds
223686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(parcel, String16, appLabel_, false); // for appLabel
224686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(parcel, String16, abilityLabel_, false); // for abilityLabel
225686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(parcel, UInt8Vector, icon_, false); // for icon
226686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(parcel, String16, secAppLabel_, false); // for secAppLabel
227686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(parcel, String16, secAbilityLabel_, false); // for secAbilityLabel
228686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(parcel, UInt8Vector, secIcon_, false); // for secIcon
229686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(parcel, String16, sourceDeviceTips_, false); // for sourceDeviceTips
230686862fbSopenharmony_ci    size_t infoSize = parcel.GetReadableBytes();
231686862fbSopenharmony_ci    const uint8_t* infoBuffer = parcel.ReadBuffer(infoSize);
232686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(data, Uint32, infoSize, false); // for snapshot info size
233686862fbSopenharmony_ci    bool ret = data.WriteBuffer(infoBuffer, infoSize); // for snapshot info buffer
234686862fbSopenharmony_ci    if (!ret) {
235686862fbSopenharmony_ci        HILOGE("snapshot info write parcel failed!");
236686862fbSopenharmony_ci        return false;
237686862fbSopenharmony_ci    }
238686862fbSopenharmony_ci    return true;
239686862fbSopenharmony_ci}
240686862fbSopenharmony_ci
241686862fbSopenharmony_cibool Snapshot::WritePixelMap(MessageParcel& data) const
242686862fbSopenharmony_ci{
243686862fbSopenharmony_ci    ImagePacker imagePacker;
244686862fbSopenharmony_ci    PackOption option;
245686862fbSopenharmony_ci    option.format = "image/jpeg";
246686862fbSopenharmony_ci    option.quality = COMPRESS_QUALITY;
247686862fbSopenharmony_ci    option.numberHint = 1;
248686862fbSopenharmony_ci    stringstream ss;
249686862fbSopenharmony_ci    std::ostream outputStream(ss.rdbuf());
250686862fbSopenharmony_ci    imagePacker.StartPacking(outputStream, option);
251686862fbSopenharmony_ci    imagePacker.AddImage(*pixelMap_);
252686862fbSopenharmony_ci    imagePacker.FinalizePacking();
253686862fbSopenharmony_ci    std::istream inputStream(outputStream.rdbuf());
254686862fbSopenharmony_ci    inputStream.seekg(0, inputStream.end);
255686862fbSopenharmony_ci    size_t len = inputStream.tellg();
256686862fbSopenharmony_ci    inputStream.seekg(0);
257686862fbSopenharmony_ci    HILOGD("pixelMap compress size:%{public}zu", len);
258686862fbSopenharmony_ci    if (len > PIXEL_MAP_MAX_BUFFER_SIZE) {
259686862fbSopenharmony_ci        HILOGD("pixelMap size is too big.");
260686862fbSopenharmony_ci        return false;
261686862fbSopenharmony_ci    }
262686862fbSopenharmony_ci    std::unique_ptr<char[]> pixelMapBuffer = make_unique<char[]>(len);
263686862fbSopenharmony_ci    inputStream.read(pixelMapBuffer.get(), len);
264686862fbSopenharmony_ci    uint8_t* byteStream = reinterpret_cast<uint8_t*>(pixelMapBuffer.get());
265686862fbSopenharmony_ci    size_t minCapacity = data.GetReadableBytes() + len + INT_BYTE;
266686862fbSopenharmony_ci    if (minCapacity % INT_BYTE != 0) {
267686862fbSopenharmony_ci        HILOGI("bytes are not aligned!");
268686862fbSopenharmony_ci        minCapacity += INT_BYTE;
269686862fbSopenharmony_ci    }
270686862fbSopenharmony_ci    if (minCapacity > data.GetDataCapacity() && !data.SetDataCapacity(minCapacity)) {
271686862fbSopenharmony_ci        HILOGE("setCapacity failed! length = %{public}zu.", minCapacity);
272686862fbSopenharmony_ci        return false;
273686862fbSopenharmony_ci    }
274686862fbSopenharmony_ci    PARCEL_WRITE_HELPER_RET(data, Uint32, len, false); // for pixel map size
275686862fbSopenharmony_ci    bool ret = data.WriteBuffer(byteStream, len); // for pixel map buffer
276686862fbSopenharmony_ci    if (!ret) {
277686862fbSopenharmony_ci        HILOGE("pixel map write parcel failed!");
278686862fbSopenharmony_ci        return false;
279686862fbSopenharmony_ci    }
280686862fbSopenharmony_ci    return true;
281686862fbSopenharmony_ci}
282686862fbSopenharmony_ci
283686862fbSopenharmony_ciint64_t Snapshot::GetCreatedTime() const
284686862fbSopenharmony_ci{
285686862fbSopenharmony_ci    return createdTime_;
286686862fbSopenharmony_ci}
287686862fbSopenharmony_ci
288686862fbSopenharmony_ciint64_t Snapshot::GetLastAccessTime() const
289686862fbSopenharmony_ci{
290686862fbSopenharmony_ci    return lastAccessTime_;
291686862fbSopenharmony_ci}
292686862fbSopenharmony_ci
293686862fbSopenharmony_civoid Snapshot::UpdateLastAccessTime(int64_t accessTime)
294686862fbSopenharmony_ci{
295686862fbSopenharmony_ci    lastAccessTime_ = accessTime;
296686862fbSopenharmony_ci}
297686862fbSopenharmony_ci}
298686862fbSopenharmony_ci}
299