1 /*
2 * Copyright (c) 2021 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 "util.h"
17
18 #include <event_handler.h>
19 #include <fstream>
20 #include <securec.h>
21 #include <sstream>
22 #include <parameters.h>
23
24 namespace OHOS {
25
PostTask(std::function<void ()> func,uint32_t delayTime)26 void PostTask(std::function<void()> func, uint32_t delayTime)
27 {
28 auto handler = AppExecFwk::EventHandler::Current();
29 if (handler) {
30 handler->PostTask(func, delayTime);
31 }
32 }
33
IsFileExisted(const std::string & filePath)34 bool IsFileExisted(const std::string& filePath)
35 {
36 if (filePath.empty()) {
37 LOGE("check filepath is empty");
38 return false;
39 }
40 char newpath[PATH_MAX + 1] = { 0x00 };
41 if (strlen(filePath.c_str()) > PATH_MAX || realpath(filePath.c_str(), newpath) == nullptr) {
42 LOGE("check filepath fail! %{public}s %{public}d %{public}s", filePath.c_str(), errno, ::strerror(errno));
43 return false;
44 }
45 struct stat info = {0};
46 if (stat(newpath, &info) != 0) {
47 LOGE("stat filepath fail! %{public}s %{public}d %{public}s", filePath.c_str(), errno, ::strerror(errno));
48 return false;
49 }
50 return true;
51 }
52
ParseBootConfig(const std::string & path,int32_t & duration,bool & isCompatible,bool & isMultiDisplay,std::vector<BootAnimationConfig> & configs)53 bool ParseBootConfig(const std::string& path, int32_t& duration, bool& isCompatible, bool& isMultiDisplay,
54 std::vector<BootAnimationConfig>& configs)
55 {
56 cJSON* overallData = ParseFileConfig(path);
57 if (overallData == nullptr) {
58 LOGE("can not parse config to json");
59 return false;
60 }
61 cJSON_bool isNewConfig = cJSON_HasObjectItem(overallData, "screen_config");
62 if (!isNewConfig) {
63 isCompatible = true;
64 ParseOldConfigFile(overallData, configs);
65 } else {
66 ParseNewConfigFile(overallData, isMultiDisplay, configs);
67 }
68 ParseBootDuration(overallData, duration);
69 cJSON_Delete(overallData);
70 return true;
71 }
72
ParseOldConfigFile(cJSON * data,std::vector<BootAnimationConfig> & configs)73 void ParseOldConfigFile(cJSON* data, std::vector<BootAnimationConfig>& configs)
74 {
75 LOGD("ParseOldConfigFile");
76 BootAnimationConfig config;
77 cJSON* custPicPath = cJSON_GetObjectItem(data, "cust.bootanimation.pics");
78 if (custPicPath != nullptr && cJSON_IsString(custPicPath)) {
79 config.picZipPath = custPicPath->valuestring;
80 }
81 cJSON* custSoundPath = cJSON_GetObjectItem(data, "cust.bootanimation.sounds");
82 if (custSoundPath != nullptr && cJSON_IsString(custSoundPath)) {
83 config.soundPath = custSoundPath->valuestring;
84 }
85 cJSON* custVideoDefaultPath = cJSON_GetObjectItem(data, "cust.bootanimation.video");
86 if (custVideoDefaultPath != nullptr && cJSON_IsString(custVideoDefaultPath)) {
87 config.videoDefaultPath = custVideoDefaultPath->valuestring;
88 }
89 cJSON* custVideoExtraPath = cJSON_GetObjectItem(data, "cust.bootanimation.video.extra");
90 if (custVideoExtraPath != nullptr && cJSON_IsString(custVideoExtraPath)) {
91 config.videoExtraPath = custVideoExtraPath->valuestring;
92 }
93 cJSON* rotateScreenJson = cJSON_GetObjectItem(data, "cust.bootanimation.rotate.screenid");
94 if (rotateScreenJson != nullptr && cJSON_IsString(rotateScreenJson)) {
95 config.rotateScreenId = std::atoi(rotateScreenJson->valuestring);
96 LOGI("cust rotateScreenId: %{public}d", config.rotateScreenId);
97 }
98 cJSON* rotateDegreeJson = cJSON_GetObjectItem(data, "cust.bootanimation.rotate.degree");
99 if (rotateDegreeJson != nullptr && cJSON_IsString(rotateDegreeJson)) {
100 config.rotateDegree = std::atoi(rotateDegreeJson->valuestring);
101 LOGI("cust rotateDegree: %{public}d", config.rotateDegree);
102 }
103 cJSON* extraVideoPath = cJSON_GetObjectItem(data, "cust.bootanimation.video_extensions");
104 if (extraVideoPath != nullptr && cJSON_IsObject(extraVideoPath)) {
105 ParseVideoExtraPath(extraVideoPath, config);
106 }
107 configs.emplace_back(config);
108 }
109
ParseNewConfigFile(cJSON * data,bool & isMultiDisplay,std::vector<BootAnimationConfig> & configs)110 void ParseNewConfigFile(cJSON* data, bool& isMultiDisplay, std::vector<BootAnimationConfig>& configs)
111 {
112 LOGD("ParseNewConfigFile");
113 cJSON* isSupport = cJSON_GetObjectItem(data, "cust.bootanimation.multi_display");
114 if (isSupport != nullptr && cJSON_IsBool(isSupport)) {
115 if (cJSON_IsTrue(isSupport)) {
116 isMultiDisplay = true;
117 }
118 }
119 LOGI("isMultiDisplay: %{public}d", isMultiDisplay);
120
121 cJSON* screens = cJSON_GetObjectItem(data, "screen_config");
122 if (screens != nullptr) {
123 BootAnimationConfig config;
124 cJSON* item = screens->child;
125 while (item != nullptr) {
126 cJSON* screenIdJson = cJSON_GetObjectItem(item, "cust.bootanimation.screen_id");
127 if (screenIdJson != nullptr && cJSON_IsString(screenIdJson)) {
128 config.screenId = std::strtoul(screenIdJson->valuestring, nullptr, 0);
129 LOGI("screenId: " BPUBU64 "", config.screenId);
130 }
131 cJSON* custPicPath = cJSON_GetObjectItem(item, "cust.bootanimation.pics");
132 if (custPicPath != nullptr && cJSON_IsString(custPicPath)) {
133 config.picZipPath = custPicPath->valuestring;
134 }
135 cJSON* custSoundPath = cJSON_GetObjectItem(item, "cust.bootanimation.sounds");
136 if (custSoundPath != nullptr && cJSON_IsString(custSoundPath)) {
137 config.soundPath = custSoundPath->valuestring;
138 }
139 cJSON* custVideoDefaultPath = cJSON_GetObjectItem(item, "cust.bootanimation.video_default");
140 if (custVideoDefaultPath != nullptr && cJSON_IsString(custVideoDefaultPath)) {
141 config.videoDefaultPath = custVideoDefaultPath->valuestring;
142 }
143 cJSON* rotateDegreeJson = cJSON_GetObjectItem(item, "cust.bootanimation.rotate_degree");
144 if (rotateDegreeJson != nullptr && cJSON_IsString(rotateDegreeJson)) {
145 config.rotateDegree = std::atoi(rotateDegreeJson->valuestring);
146 LOGI("cust rotateDegree: %{public}d", config.rotateDegree);
147 }
148 cJSON* extraVideoPath = cJSON_GetObjectItem(item, "cust.bootanimation.video_extensions");
149 if (extraVideoPath != nullptr && cJSON_IsObject(extraVideoPath)) {
150 ParseVideoExtraPath(extraVideoPath, config);
151 }
152 configs.emplace_back(config);
153 item = item->next;
154 }
155 }
156 }
157
ParseProgressData(cJSON * data,std::map<int32_t,BootAnimationProgressConfig> & configs)158 void ParseProgressData(cJSON* data, std::map<int32_t, BootAnimationProgressConfig>& configs)
159 {
160 LOGI("ParseProgressData");
161 cJSON* progressConfigs = cJSON_GetObjectItem(data, "progress_config");
162 if (progressConfigs != nullptr) {
163 BootAnimationProgressConfig config;
164 cJSON* item = progressConfigs->child;
165 while (item != nullptr) {
166 cJSON* progressScreenIdJson = cJSON_GetObjectItem(item, "cust.bootanimation.progress_screen_id");
167 if (progressScreenIdJson != nullptr && cJSON_IsString(progressScreenIdJson)) {
168 config.progressScreenId = std::atoi(progressScreenIdJson->valuestring);
169 }
170 cJSON* progressHeightJson = cJSON_GetObjectItem(item, "cust.bootanimation.progress_height");
171 if (progressHeightJson != nullptr && cJSON_IsString(progressHeightJson)) {
172 config.progressHeight = std::atoi(progressHeightJson->valuestring);
173 }
174 cJSON* progressFrameHeightJson = cJSON_GetObjectItem(item, "cust.bootanimation.progress_frame_height");
175 if (progressFrameHeightJson != nullptr && cJSON_IsString(progressFrameHeightJson)) {
176 config.progressFrameHeight = std::atoi(progressFrameHeightJson->valuestring);
177 }
178 cJSON* progressOffsetJson = cJSON_GetObjectItem(item, "cust.bootanimation.progress_x_offset");
179 if (progressOffsetJson != nullptr && cJSON_IsString(progressOffsetJson)) {
180 config.progressOffset = std::atoi(progressOffsetJson->valuestring);
181 }
182 cJSON* progressFontSizeJson = cJSON_GetObjectItem(item, "cust.bootanimation.progress_font_size");
183 if (progressFontSizeJson != nullptr && cJSON_IsString(progressFontSizeJson)) {
184 config.progressFontSize = std::atoi(progressFontSizeJson->valuestring);
185 }
186 cJSON* progressRadiusSizeJson = cJSON_GetObjectItem(item, "cust.bootanimation.progress_radius_size");
187 if (progressRadiusSizeJson != nullptr && cJSON_IsString(progressRadiusSizeJson)) {
188 config.progressRadiusSize = std::atoi(progressRadiusSizeJson->valuestring);
189 }
190 cJSON* progressDegreeJson = cJSON_GetObjectItem(item, "cust.bootanimation.progress_degree");
191 if (progressDegreeJson != nullptr && cJSON_IsString(progressDegreeJson)) {
192 config.progressDegree = std::atoi(progressDegreeJson->valuestring);
193 }
194 configs.emplace(config.progressScreenId, config);
195 item = item->next;
196 }
197 }
198 }
199
ParseProgressConfig(const std::string & path,std::map<int32_t,BootAnimationProgressConfig> & configs)200 void ParseProgressConfig(const std::string& path, std::map<int32_t, BootAnimationProgressConfig>& configs)
201 {
202 LOGI("ParseProgressConfig");
203 cJSON* overallData = ParseFileConfig(path);
204 if (overallData == nullptr) {
205 LOGE("can not parse config to json");
206 return;
207 }
208 cJSON_bool hasProgressConfig = cJSON_HasObjectItem(overallData, "progress_config");
209 if (!hasProgressConfig) {
210 LOGE("has no progress config");
211 cJSON_Delete(overallData);
212 return;
213 }
214 ParseProgressData(overallData, configs);
215 cJSON_Delete(overallData);
216 }
217
ParseFileConfig(const std::string & path)218 cJSON* ParseFileConfig(const std::string& path)
219 {
220 char newpath[PATH_MAX + 1] = { 0x00 };
221 if (strlen(path.c_str()) > PATH_MAX || realpath(path.c_str(), newpath) == nullptr) {
222 LOGE("check config path fail! %{public}s %{public}d %{public}s", path.c_str(), errno, ::strerror(errno));
223 return nullptr;
224 }
225
226 std::ifstream configFile;
227 configFile.open(newpath);
228 std::stringstream JFilterParamsStream;
229 JFilterParamsStream << configFile.rdbuf();
230 configFile.close();
231 std::string JParamsString = JFilterParamsStream.str();
232
233 return cJSON_Parse(JParamsString.c_str());
234 }
235
ParseVideoExtraPath(cJSON * data,BootAnimationConfig & config)236 void ParseVideoExtraPath(cJSON* data, BootAnimationConfig& config)
237 {
238 int size = cJSON_GetArraySize(data);
239 for (int index = 0; index < size; index++) {
240 cJSON* extraPath = cJSON_GetArrayItem(data, index);
241 if (extraPath != nullptr && extraPath->string != nullptr && extraPath->valuestring != nullptr
242 && strlen(extraPath->string) != 0) {
243 config.videoExtPath.emplace(extraPath->string, extraPath->valuestring);
244 }
245 }
246 }
247
ParseBootDuration(cJSON * data,int32_t & duration)248 void ParseBootDuration(cJSON* data, int32_t& duration)
249 {
250 cJSON* durationJson = cJSON_GetObjectItem(data, "cust.bootanimation.duration");
251 if (durationJson != nullptr && cJSON_IsString(durationJson)) {
252 duration = std::atoi(durationJson->valuestring);
253 LOGI("cust duration: %{public}d", duration);
254 }
255 }
256
ReadZipFile(const std::string & srcFilePath,ImageStructVec & imgVec,FrameRateConfig & frameConfig)257 bool ReadZipFile(const std::string& srcFilePath, ImageStructVec& imgVec, FrameRateConfig& frameConfig)
258 {
259 unzFile zipFile = unzOpen2(srcFilePath.c_str(), nullptr);
260 if (zipFile == nullptr) {
261 LOGE("Open zipFile fail: %{public}s", srcFilePath.c_str());
262 return false;
263 }
264
265 unz_global_info globalInfo;
266 if (unzGetGlobalInfo(zipFile, &globalInfo) != UNZ_OK) {
267 LOGE("Get ZipGlobalInfo fail");
268 return CloseZipFile(zipFile, false);
269 }
270
271 LOGD("read zip file num: %{public}ld", globalInfo.number_entry);
272 for (unsigned long i = 0; i < globalInfo.number_entry; ++i) {
273 unz_file_info fileInfo;
274 char filename[MAX_FILE_NAME] = {0};
275 if (unzGetCurrentFileInfo(zipFile, &fileInfo, filename, MAX_FILE_NAME, nullptr, 0, nullptr, 0) != UNZ_OK) {
276 return CloseZipFile(zipFile, false);
277 }
278 size_t length = strlen(filename);
279 if (length > MAX_FILE_NAME || length == 0) {
280 return CloseZipFile(zipFile, false);
281 }
282 if (filename[length - 1] != '/') {
283 if (unzOpenCurrentFile(zipFile) != UNZ_OK) {
284 return CloseZipFile(zipFile, false);
285 }
286 std::string name = std::string(filename);
287 size_t npos = name.find_last_of("//");
288 if (npos != std::string::npos) {
289 name = name.substr(npos + 1, name.length());
290 }
291 if (!ReadImageFile(zipFile, name, imgVec, frameConfig, fileInfo.uncompressed_size)) {
292 LOGE("read zip deal single file failed");
293 unzCloseCurrentFile(zipFile);
294 return CloseZipFile(zipFile, false);
295 }
296 unzCloseCurrentFile(zipFile);
297 }
298 if (i < (globalInfo.number_entry - 1)) {
299 if (unzGoToNextFile(zipFile) != UNZ_OK) {
300 return CloseZipFile(zipFile, false);
301 }
302 }
303 }
304 return CloseZipFile(zipFile, true);
305 }
306
CloseZipFile(const unzFile zipFile,bool ret)307 bool CloseZipFile(const unzFile zipFile, bool ret)
308 {
309 unzClose(zipFile);
310 return ret;
311 }
312
SortZipFile(ImageStructVec & imgVec)313 void SortZipFile(ImageStructVec& imgVec)
314 {
315 if (imgVec.size() == 0) {
316 return;
317 }
318
319 sort(imgVec.begin(), imgVec.end(), [](std::shared_ptr<ImageStruct> image1,
320 std::shared_ptr<ImageStruct> image2)
321 -> bool {return image1->fileName < image2->fileName;});
322 }
323
ReadImageFile(const unzFile zipFile,const std::string & fileName,ImageStructVec & imgVec,FrameRateConfig & frameConfig,unsigned long fileSize)324 bool ReadImageFile(const unzFile zipFile, const std::string& fileName, ImageStructVec& imgVec,
325 FrameRateConfig& frameConfig, unsigned long fileSize)
326 {
327 if (zipFile == nullptr) {
328 LOGE("ReadImageFile failed, zip is null");
329 return false;
330 }
331 int readLen = UNZ_OK;
332 int totalLen = 0;
333 int size = static_cast<int>(fileSize);
334 char readBuffer[READ_SIZE] = {0};
335 std::shared_ptr<ImageStruct> imageStruct = std::make_shared<ImageStruct>();
336 imageStruct->memPtr.SetBufferSize(fileSize);
337 do {
338 readLen = unzReadCurrentFile(zipFile, readBuffer, READ_SIZE);
339 if (readLen < 0) {
340 LOGE("unzReadCurrentFile length error");
341 return false;
342 }
343 if (imageStruct->memPtr.memBuffer == nullptr) {
344 LOGE("ReadImageFile memPtr is null");
345 return false;
346 }
347 if (memcpy_s(imageStruct->memPtr.memBuffer + totalLen, size - totalLen, \
348 readBuffer, readLen) == EOK) {
349 totalLen += readLen;
350 }
351 } while (readLen > 0);
352
353 if (totalLen > 0) {
354 LOGD("fileName: %{public}s, fileSize: %{public}d, totalLen: %{public}d", fileName.c_str(), size, totalLen);
355 if (strstr(fileName.c_str(), BOOT_PIC_CONFIG_FILE.c_str()) != nullptr) {
356 ParseImageConfig(imageStruct->memPtr.memBuffer, totalLen, frameConfig);
357 } else {
358 CheckImageData(fileName, imageStruct, totalLen, imgVec);
359 }
360 }
361 return true;
362 }
363
ParseImageConfig(const char * fileBuffer,int totalsize,FrameRateConfig & frameConfig)364 bool ParseImageConfig(const char* fileBuffer, int totalsize, FrameRateConfig& frameConfig)
365 {
366 std::string JParamsString;
367 JParamsString.assign(fileBuffer, totalsize);
368 cJSON* overallData = cJSON_Parse(JParamsString.c_str());
369 if (overallData == nullptr) {
370 LOGE("parse image config failed");
371 return false;
372 }
373 cJSON* frameRate = cJSON_GetObjectItem(overallData, "FrameRate");
374 if (frameRate != nullptr && cJSON_IsNumber(frameRate)) {
375 frameConfig.frameRate = frameRate->valueint;
376 LOGI("freq: %{public}d", frameConfig.frameRate);
377 }
378 cJSON_Delete(overallData);
379 return true;
380 }
381
CheckImageData(const std::string & fileName,std::shared_ptr<ImageStruct> imageStruct,int32_t bufferLen,ImageStructVec & imgVec)382 bool CheckImageData(const std::string& fileName, std::shared_ptr<ImageStruct> imageStruct,
383 int32_t bufferLen, ImageStructVec& imgVec)
384 {
385 if (imageStruct->memPtr.memBuffer == nullptr) {
386 LOGE("json file buffer is null");
387 return false;
388 }
389 auto data = std::make_shared<Rosen::Drawing::Data>();
390 data->BuildFromMalloc(imageStruct->memPtr.memBuffer, bufferLen);
391 if (data->GetData() == nullptr) {
392 LOGE("data memory data is null. update data failed");
393 return false;
394 }
395 imageStruct->memPtr.setOwnerShip(data);
396 imageStruct->fileName = fileName;
397 imageStruct->imageData = std::make_shared<Rosen::Drawing::Image>();
398 #ifdef RS_ENABLE_GPU
399 imageStruct->imageData->MakeFromEncoded(data);
400 #endif
401 imgVec.push_back(imageStruct);
402 return true;
403 }
404
405 /**
406 * Transate vp to pixel.
407 *
408 * @param sideLen The short side length of screen.
409 * @param vp vp value.
410 * @return Returns the font size.
411 */
TranslateVp2Pixel(const int32_t sideLen,const int32_t vp)412 int32_t TranslateVp2Pixel(const int32_t sideLen, const int32_t vp)
413 {
414 std::string deviceType = GetDeviceType();
415 float ratio = RATIO_PHONE;
416 if (DEVICE_TYPE_PHONE != deviceType && DEVICE_TYPE_WEARABLE != deviceType) {
417 ratio = RATIO_OTHER;
418 }
419 return TranslateVp2Pixel(sideLen, vp, ratio);
420 }
421
422 /**
423 * Transate vp to pixel.
424 *
425 * @param sideLen The short side length of screen.
426 * @param vp vp value.
427 * @param ratio ratio value.
428 * @return Returns the font size.
429 */
TranslateVp2Pixel(const int32_t sideLen,const int32_t vp,const float ratio)430 int32_t TranslateVp2Pixel(const int32_t sideLen, const int32_t vp, const float ratio)
431 {
432 if (ratio == 0) {
433 LOGE("invalid ratio");
434 return 0;
435 }
436 return static_cast<int32_t>(std::ceil(sideLen * HALF / ratio) / HALF * vp);
437 }
438
ReadFile(const std::string & filePath)439 std::string ReadFile(const std::string &filePath)
440 {
441 std::string content;
442 if (filePath.empty() || filePath.length() > PATH_MAX) {
443 LOGE("filepath check failed.");
444 return content;
445 }
446 char tmpPath[PATH_MAX] = {0};
447 if (realpath(filePath.c_str(), tmpPath) == nullptr) {
448 LOGE("filepath check failed! %{public}s %{public}d %{public}s", filePath.c_str(), errno, ::strerror(errno));
449 return content;
450 }
451 std::ifstream infile;
452 infile.open(tmpPath);
453 if (!infile.is_open()) {
454 LOGE("failed to open file");
455 return content;
456 }
457
458 getline(infile, content);
459 infile.close();
460 return content;
461 }
462
GetHingeStatus()463 std::string GetHingeStatus()
464 {
465 if (!IsFileExisted(HING_STATUS_INFO_PATH)) {
466 LOGE("failed not exist");
467 return "";
468 }
469
470 return ReadFile(HING_STATUS_INFO_PATH);
471 }
472
GetSystemCurrentTime()473 int64_t GetSystemCurrentTime()
474 {
475 auto currentTime = std::chrono::duration_cast<std::chrono::milliseconds>
476 (std::chrono::steady_clock::now().time_since_epoch()).count();
477 return currentTime;
478 }
479
GetDeviceType()480 std::string GetDeviceType()
481 {
482 return system::GetParameter("const.product.devicetype", "phone");
483 }
484 } // namespace OHOS
485