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