1 /*
2 * Copyright (C) 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 #include "wallpaper_manager.h"
16
17 #include <cerrno>
18 #include <cstdio>
19 #include <cstdlib>
20 #include <cstring>
21 #include <fcntl.h>
22 #include <fstream>
23 #include <iostream>
24 #include <mutex>
25 #include <sstream>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <unistd.h>
29
30 #include "dfx_types.h"
31 #include "display_manager.h"
32 #include "file_deal.h"
33 #include "file_ex.h"
34 #include "hilog_wrapper.h"
35 #include "hitrace_meter.h"
36 #include "i_wallpaper_service.h"
37 #include "if_system_ability_manager.h"
38 #include "image_packer.h"
39 #include "image_source.h"
40 #include "image_type.h"
41 #include "iservice_registry.h"
42 #include "system_ability_definition.h"
43 #include "wallpaper_service_cb_stub.h"
44 #include "wallpaper_service_proxy.h"
45
46 namespace OHOS {
47 using namespace MiscServices;
48 namespace WallpaperMgrService {
49 constexpr int32_t OPTION_QUALITY = 100;
50 constexpr int32_t MIN_TIME = 0;
51 constexpr int32_t MAX_TIME = 5000;
52 constexpr int32_t MAX_VIDEO_SIZE = 104857600;
53
54 using namespace OHOS::Media;
55
WallpaperManager()56 WallpaperManager::WallpaperManager()
57 {
58 }
~WallpaperManager()59 WallpaperManager::~WallpaperManager()
60 {
61 std::map<int32_t, int32_t>::iterator iter = wallpaperFdMap_.begin();
62 while (iter != wallpaperFdMap_.end()) {
63 close(iter->second);
64 ++iter;
65 }
66 }
67
ResetService(const wptr<IRemoteObject> & remote)68 void WallpaperManager::ResetService(const wptr<IRemoteObject> &remote)
69 {
70 HILOG_INFO("Remote is dead, reset service instance");
71 std::lock_guard<std::mutex> lock(wallpaperProxyLock_);
72 if (wallpaperProxy_ != nullptr) {
73 sptr<IRemoteObject> object = wallpaperProxy_->AsObject();
74 if ((object != nullptr) && (remote == object)) {
75 object->RemoveDeathRecipient(deathRecipient_);
76 wallpaperProxy_ = nullptr;
77 }
78 }
79 }
80
GetService()81 sptr<IWallpaperService> WallpaperManager::GetService()
82 {
83 std::lock_guard<std::mutex> lock(wallpaperProxyLock_);
84 if (wallpaperProxy_ != nullptr) {
85 return wallpaperProxy_;
86 }
87
88 sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
89 if (samgr == nullptr) {
90 HILOG_ERROR("Get samgr failed");
91 return nullptr;
92 }
93 sptr<IRemoteObject> object = samgr->GetSystemAbility(WALLPAPER_MANAGER_SERVICE_ID);
94 if (object == nullptr) {
95 HILOG_ERROR("Get wallpaper object from samgr failed");
96 return nullptr;
97 }
98
99 if (deathRecipient_ == nullptr) {
100 deathRecipient_ = new DeathRecipient();
101 }
102
103 if ((object->IsProxyObject()) && (!object->AddDeathRecipient(deathRecipient_))) {
104 HILOG_ERROR("Failed to add death recipient");
105 }
106
107 HILOG_INFO("get remote object ok");
108 wallpaperProxy_ = iface_cast<WallpaperServiceProxy>(object);
109 if (wallpaperProxy_ == nullptr) {
110 HILOG_ERROR("iface_cast failed");
111 }
112 return wallpaperProxy_;
113 }
114
OnRemoteDied(const wptr<IRemoteObject> & remote)115 void WallpaperManager::DeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
116 {
117 DelayedRefSingleton<WallpaperManager>::GetInstance().ResetService(remote);
118 }
119
120 template<typename F, typename... Args>
CallService(F func,Args &&...args)121 ErrCode WallpaperManager::CallService(F func, Args &&...args)
122 {
123 auto service = GetService();
124 if (service == nullptr) {
125 HILOG_ERROR("get service failed");
126 return ERR_DEAD_OBJECT;
127 }
128
129 ErrCode result = (service->*func)(std::forward<Args>(args)...);
130 if (SUCCEEDED(result)) {
131 return ERR_OK;
132 }
133
134 // Reset service instance if 'ERR_DEAD_OBJECT' happened.
135 if (result == ERR_DEAD_OBJECT) {
136 ResetService(service);
137 }
138
139 HILOG_ERROR("Callservice failed with: %{public}d", result);
140 return result;
141 }
142
GetColors(int32_t wallpaperType,const ApiInfo & apiInfo,std::vector<uint64_t> & colors)143 ErrorCode WallpaperManager::GetColors(int32_t wallpaperType, const ApiInfo &apiInfo, std::vector<uint64_t> &colors)
144 {
145 auto wallpaperServerProxy = GetService();
146 if (wallpaperServerProxy == nullptr) {
147 HILOG_ERROR("Get proxy failed");
148 return E_DEAL_FAILED;
149 }
150 if (apiInfo.isSystemApi) {
151 return wallpaperServerProxy->GetColorsV9(wallpaperType, colors);
152 }
153 return wallpaperServerProxy->GetColors(wallpaperType, colors);
154 }
155
GetFile(int32_t wallpaperType,int32_t & wallpaperFd)156 ErrorCode WallpaperManager::GetFile(int32_t wallpaperType, int32_t &wallpaperFd)
157 {
158 auto wallpaperServerProxy = GetService();
159 if (wallpaperServerProxy == nullptr) {
160 HILOG_ERROR("Get proxy failed");
161 return E_DEAL_FAILED;
162 }
163 std::lock_guard<std::mutex> lock(wallpaperFdLock_);
164 std::map<int32_t, int32_t>::iterator iter = wallpaperFdMap_.find(wallpaperType);
165 if (iter != wallpaperFdMap_.end() && fcntl(iter->second, F_GETFL) != -1) {
166 close(iter->second);
167 wallpaperFdMap_.erase(iter);
168 }
169 ErrorCode wallpaperErrorCode = wallpaperServerProxy->GetFile(wallpaperType, wallpaperFd);
170 if (wallpaperErrorCode == E_OK && wallpaperFd != -1) {
171 wallpaperFdMap_.insert(std::pair<int32_t, int32_t>(wallpaperType, wallpaperFd));
172 }
173 return wallpaperErrorCode;
174 }
175
SetWallpaper(std::string uri,int32_t wallpaperType,const ApiInfo & apiInfo)176 ErrorCode WallpaperManager::SetWallpaper(std::string uri, int32_t wallpaperType, const ApiInfo &apiInfo)
177 {
178 auto wallpaperServerProxy = GetService();
179 if (wallpaperServerProxy == nullptr) {
180 HILOG_ERROR("Get proxy failed");
181 return E_DEAL_FAILED;
182 }
183 std::string fileRealPath;
184 if (!FileDeal::GetRealPath(uri, fileRealPath)) {
185 HILOG_ERROR("get real path file failed, len = %{public}zu", uri.size());
186 return E_FILE_ERROR;
187 }
188
189 long length = 0;
190 ErrorCode wallpaperErrorCode = CheckWallpaperFormat(fileRealPath, false, length);
191 if (wallpaperErrorCode != E_OK) {
192 HILOG_ERROR("Check wallpaper format failed!");
193 return wallpaperErrorCode;
194 }
195
196 int32_t fd = open(fileRealPath.c_str(), O_RDONLY, 0660);
197 if (fd < 0) {
198 HILOG_ERROR("open file failed, errno %{public}d", errno);
199 ReporterFault(FaultType::SET_WALLPAPER_FAULT, FaultCode::RF_FD_INPUT_FAILED);
200 return E_FILE_ERROR;
201 }
202 StartAsyncTrace(HITRACE_TAG_MISC, "SetWallpaper", static_cast<int32_t>(TraceTaskId::SET_WALLPAPER));
203 if (apiInfo.isSystemApi) {
204 wallpaperErrorCode = wallpaperServerProxy->SetWallpaperV9(fd, wallpaperType, length);
205 } else {
206 wallpaperErrorCode = wallpaperServerProxy->SetWallpaper(fd, wallpaperType, length);
207 }
208 close(fd);
209 if (wallpaperErrorCode == E_OK) {
210 CloseWallpaperFd(wallpaperType);
211 }
212 FinishAsyncTrace(HITRACE_TAG_MISC, "SetWallpaper", static_cast<int32_t>(TraceTaskId::SET_WALLPAPER));
213 return wallpaperErrorCode;
214 }
215
SetWallpaper(std::shared_ptr<OHOS::Media::PixelMap> pixelMap,int32_t wallpaperType,const ApiInfo & apiInfo)216 ErrorCode WallpaperManager::SetWallpaper(std::shared_ptr<OHOS::Media::PixelMap> pixelMap, int32_t wallpaperType,
217 const ApiInfo &apiInfo)
218 {
219 auto wallpaperServerProxy = GetService();
220 if (wallpaperServerProxy == nullptr) {
221 HILOG_ERROR("Get proxy failed");
222 return E_DEAL_FAILED;
223 }
224
225 std::stringbuf stringBuf;
226 std::ostream ostream(&stringBuf);
227 int32_t mapSize = WritePixelMapToStream(ostream, pixelMap);
228 if (mapSize <= 0) {
229 HILOG_ERROR("WritePixelMapToStream failed");
230 return E_WRITE_PARCEL_ERROR;
231 }
232 char *buffer = new (std::nothrow) char[mapSize]();
233 if (buffer == nullptr) {
234 return E_NO_MEMORY;
235 }
236 stringBuf.sgetn(buffer, mapSize);
237
238 int32_t fd[2];
239 pipe(fd);
240 fcntl(fd[1], F_SETPIPE_SZ, mapSize);
241 fcntl(fd[0], F_SETPIPE_SZ, mapSize);
242 int32_t writeSize = write(fd[1], buffer, mapSize);
243 if (writeSize != mapSize) {
244 HILOG_ERROR("Write file failed, errno %{public}d", errno);
245 ReporterFault(FaultType::SET_WALLPAPER_FAULT, FaultCode::RF_FD_INPUT_FAILED);
246 delete[] buffer;
247 close(fd[1]);
248 close(fd[0]);
249 return E_WRITE_PARCEL_ERROR;
250 }
251 close(fd[1]);
252 ErrorCode wallpaperErrorCode = E_UNKNOWN;
253 if (apiInfo.isSystemApi) {
254 wallpaperErrorCode = wallpaperServerProxy->SetWallpaperV9(fd[0], wallpaperType, mapSize);
255 } else {
256 wallpaperErrorCode = wallpaperServerProxy->SetWallpaper(fd[0], wallpaperType, mapSize);
257 }
258 close(fd[0]);
259 if (wallpaperErrorCode == static_cast<int32_t>(E_OK)) {
260 CloseWallpaperFd(wallpaperType);
261 }
262 delete[] buffer;
263 return wallpaperErrorCode;
264 }
265
SetVideo(const std::string & uri,const int32_t wallpaperType)266 ErrorCode WallpaperManager::SetVideo(const std::string &uri, const int32_t wallpaperType)
267 {
268 auto wallpaperServerProxy = GetService();
269 if (wallpaperServerProxy == nullptr) {
270 HILOG_ERROR("Get proxy failed");
271 return E_DEAL_FAILED;
272 }
273 std::string fileRealPath;
274 if (!FileDeal::GetRealPath(uri, fileRealPath)) {
275 HILOG_ERROR("Get real path failed, uri: %{public}s", uri.c_str());
276 return E_FILE_ERROR;
277 }
278
279 long length = 0;
280 ErrorCode wallpaperErrorCode = CheckWallpaperFormat(fileRealPath, true, length);
281 if (wallpaperErrorCode != E_OK) {
282 HILOG_ERROR("Check wallpaper format failed!");
283 return wallpaperErrorCode;
284 }
285 int32_t fd = open(fileRealPath.c_str(), O_RDONLY, 0660);
286 if (fd < 0) {
287 HILOG_ERROR("Open file failed, errno %{public}d", errno);
288 ReporterFault(FaultType::SET_WALLPAPER_FAULT, FaultCode::RF_FD_INPUT_FAILED);
289 return E_FILE_ERROR;
290 }
291 StartAsyncTrace(HITRACE_TAG_MISC, "SetVideo", static_cast<int32_t>(TraceTaskId::SET_VIDEO));
292 wallpaperErrorCode = wallpaperServerProxy->SetVideo(fd, wallpaperType, length);
293 close(fd);
294 FinishAsyncTrace(HITRACE_TAG_MISC, "SetVideo", static_cast<int32_t>(TraceTaskId::SET_VIDEO));
295 return wallpaperErrorCode;
296 }
297
SetCustomWallpaper(const std::string & uri,const int32_t wallpaperType)298 ErrorCode WallpaperManager::SetCustomWallpaper(const std::string &uri, const int32_t wallpaperType)
299 {
300 auto wallpaperServerProxy = GetService();
301 if (wallpaperServerProxy == nullptr) {
302 HILOG_ERROR("Get proxy failed");
303 return E_DEAL_FAILED;
304 }
305 std::string fileRealPath;
306 if (!FileDeal::GetRealPath(uri, fileRealPath)) {
307 HILOG_ERROR("Get real path failed, uri: %{public}s", uri.c_str());
308 return E_FILE_ERROR;
309 }
310 StartAsyncTrace(HITRACE_TAG_MISC, "SetCustomWallpaper", static_cast<int32_t>(TraceTaskId::SET_CUSTOM_WALLPAPER));
311 ErrorCode wallpaperErrorCode = wallpaperServerProxy->SetCustomWallpaper(uri, wallpaperType);
312 FinishAsyncTrace(HITRACE_TAG_MISC, "SetCustomWallpaper", static_cast<int32_t>(TraceTaskId::SET_CUSTOM_WALLPAPER));
313 return wallpaperErrorCode;
314 }
315
WritePixelMapToStream(std::ostream & outputStream,std::shared_ptr<OHOS::Media::PixelMap> pixelMap)316 int64_t WallpaperManager::WritePixelMapToStream(std::ostream &outputStream,
317 std::shared_ptr<OHOS::Media::PixelMap> pixelMap)
318 {
319 OHOS::Media::ImagePacker imagePacker;
320 OHOS::Media::PackOption option;
321 option.format = "image/jpeg";
322 option.quality = OPTION_QUALITY;
323 option.numberHint = 1;
324 std::set<std::string> formats;
325 uint32_t ret = imagePacker.GetSupportedFormats(formats);
326 if (ret != 0) {
327 HILOG_ERROR("image packer get supported format failed, ret=%{public}u.", ret);
328 }
329
330 imagePacker.StartPacking(outputStream, option);
331 imagePacker.AddImage(*pixelMap);
332 int64_t packedSize = 0;
333 imagePacker.FinalizePacking(packedSize);
334 HILOG_INFO("FrameWork WritePixelMapToStream End! packedSize=%{public}lld.", static_cast<long long>(packedSize));
335 return packedSize;
336 }
337
GetPixelMap(int32_t wallpaperType,const ApiInfo & apiInfo,std::shared_ptr<OHOS::Media::PixelMap> & pixelMap)338 ErrorCode WallpaperManager::GetPixelMap(int32_t wallpaperType, const ApiInfo &apiInfo,
339 std::shared_ptr<OHOS::Media::PixelMap> &pixelMap)
340 {
341 HILOG_INFO("FrameWork GetPixelMap Start by FD");
342 auto wallpaperServerProxy = GetService();
343 if (wallpaperServerProxy == nullptr) {
344 HILOG_ERROR("Get proxy failed");
345 return E_SA_DIED;
346 }
347 IWallpaperService::FdInfo fdInfo;
348 ErrorCode wallpaperErrorCode = E_UNKNOWN;
349 if (apiInfo.isSystemApi) {
350 wallpaperErrorCode = wallpaperServerProxy->GetPixelMapV9(wallpaperType, fdInfo);
351 } else {
352 wallpaperErrorCode = wallpaperServerProxy->GetPixelMap(wallpaperType, fdInfo);
353 }
354 if (wallpaperErrorCode != E_OK) {
355 return wallpaperErrorCode;
356 }
357 // current wallpaper is live video, not image
358 if (fdInfo.size == 0 && fdInfo.fd == -1) { // 0: empty file size; -1: invalid file description
359 pixelMap = nullptr;
360 return E_OK;
361 }
362 uint32_t errorCode = 0;
363 OHOS::Media::SourceOptions opts;
364 opts.formatHint = "image/jpeg";
365 HILOG_INFO(" CreateImageSource by FD");
366 std::unique_ptr<OHOS::Media::ImageSource> imageSource =
367 OHOS::Media::ImageSource::CreateImageSource(fdInfo.fd, opts, errorCode);
368 if (errorCode != 0) {
369 HILOG_ERROR("ImageSource::CreateImageSource failed,errcode= %{public}d", errorCode);
370 close(fdInfo.fd);
371 return E_IMAGE_ERRCODE;
372 }
373 close(fdInfo.fd);
374 OHOS::Media::DecodeOptions decodeOpts;
375 HILOG_INFO(" CreatePixelMap");
376 pixelMap = imageSource->CreatePixelMap(decodeOpts, errorCode);
377
378 if (errorCode != 0) {
379 HILOG_ERROR("ImageSource::CreatePixelMap failed,errcode= %{public}d", errorCode);
380 return E_IMAGE_ERRCODE;
381 }
382 return wallpaperErrorCode;
383 }
384
GetWallpaperId(int32_t wallpaperType)385 int32_t WallpaperManager::GetWallpaperId(int32_t wallpaperType)
386 {
387 auto wallpaperServerProxy = GetService();
388 if (wallpaperServerProxy == nullptr) {
389 HILOG_ERROR("Get proxy failed");
390 return -1;
391 }
392 return wallpaperServerProxy->GetWallpaperId(wallpaperType);
393 }
394
GetWallpaperMinHeight(const ApiInfo & apiInfo,int32_t & minHeight)395 ErrorCode WallpaperManager::GetWallpaperMinHeight(const ApiInfo &apiInfo, int32_t &minHeight)
396 {
397 auto display = Rosen::DisplayManager::GetInstance().GetDefaultDisplay();
398 if (display == nullptr) {
399 HILOG_ERROR("GetDefaultDisplay is nullptr");
400 return E_DEAL_FAILED;
401 }
402 minHeight = display->GetHeight();
403 return E_OK;
404 }
405
GetWallpaperMinWidth(const ApiInfo & apiInfo,int32_t & minWidth)406 ErrorCode WallpaperManager::GetWallpaperMinWidth(const ApiInfo &apiInfo, int32_t &minWidth)
407 {
408 auto display = Rosen::DisplayManager::GetInstance().GetDefaultDisplay();
409 if (display == nullptr) {
410 HILOG_ERROR("GetDefaultDisplay is nullptr");
411 return E_DEAL_FAILED;
412 }
413 minWidth = display->GetWidth();
414 return E_OK;
415 }
416
IsChangePermitted()417 bool WallpaperManager::IsChangePermitted()
418 {
419 auto wallpaperServerProxy = GetService();
420 if (wallpaperServerProxy == nullptr) {
421 HILOG_ERROR("Get proxy failed");
422 return false;
423 }
424 return wallpaperServerProxy->IsChangePermitted();
425 }
426
IsOperationAllowed()427 bool WallpaperManager::IsOperationAllowed()
428 {
429 auto wallpaperServerProxy = GetService();
430 if (wallpaperServerProxy == nullptr) {
431 HILOG_ERROR("Get proxy failed");
432 return false;
433 }
434 return wallpaperServerProxy->IsOperationAllowed();
435 }
ResetWallpaper(std::int32_t wallpaperType,const ApiInfo & apiInfo)436 ErrorCode WallpaperManager::ResetWallpaper(std::int32_t wallpaperType, const ApiInfo &apiInfo)
437 {
438 auto wallpaperServerProxy = GetService();
439 if (wallpaperServerProxy == nullptr) {
440 HILOG_ERROR("Get proxy failed");
441 return E_SA_DIED;
442 }
443 ErrorCode wallpaperErrorCode = E_UNKNOWN;
444 if (apiInfo.isSystemApi) {
445 wallpaperErrorCode = wallpaperServerProxy->ResetWallpaperV9(wallpaperType);
446 } else {
447 wallpaperErrorCode = wallpaperServerProxy->ResetWallpaper(wallpaperType);
448 }
449 if (wallpaperErrorCode == E_OK) {
450 CloseWallpaperFd(wallpaperType);
451 }
452 return wallpaperErrorCode;
453 }
454
On(const std::string & type,std::shared_ptr<WallpaperEventListener> listener)455 ErrorCode WallpaperManager::On(const std::string &type, std::shared_ptr<WallpaperEventListener> listener)
456 {
457 HILOG_DEBUG("WallpaperManager::On in");
458 auto wallpaperServerProxy = GetService();
459 if (wallpaperServerProxy == nullptr) {
460 HILOG_ERROR("Get proxy failed");
461 return E_SA_DIED;
462 }
463 if (listener == nullptr) {
464 HILOG_ERROR("listener is nullptr.");
465 return E_DEAL_FAILED;
466 }
467 sptr<WallpaperEventListenerClient> ipcListener = new (std::nothrow) WallpaperEventListenerClient(listener);
468 if (ipcListener == nullptr) {
469 HILOG_ERROR("new WallpaperEventListenerClient failed");
470 return E_NO_MEMORY;
471 }
472 HILOG_DEBUG("WallpaperManager::On out");
473 return wallpaperServerProxy->On(type, ipcListener);
474 }
475
Off(const std::string & type,std::shared_ptr<WallpaperEventListener> listener)476 ErrorCode WallpaperManager::Off(const std::string &type, std::shared_ptr<WallpaperEventListener> listener)
477 {
478 HILOG_DEBUG("WallpaperManager::Off in");
479 auto wallpaperServerProxy = GetService();
480 if (wallpaperServerProxy == nullptr) {
481 HILOG_ERROR("Get proxy failed");
482 return E_SA_DIED;
483 }
484 sptr<WallpaperEventListenerClient> ipcListener = nullptr;
485 if (listener != nullptr) {
486 ipcListener = new (std::nothrow) WallpaperEventListenerClient(listener);
487 if (ipcListener == nullptr) {
488 HILOG_ERROR("new WallpaperEventListenerClient failed");
489 return E_NO_MEMORY;
490 }
491 }
492 HILOG_DEBUG("WallpaperManager::Off out");
493 return wallpaperServerProxy->Off(type, ipcListener);
494 }
495
GetCallback()496 JScallback WallpaperManager::GetCallback()
497 {
498 return callback;
499 }
500
SetCallback(JScallback cb)501 void WallpaperManager::SetCallback(JScallback cb)
502 {
503 callback = cb;
504 }
505
RegisterWallpaperCallback(JScallback callback)506 bool WallpaperManager::RegisterWallpaperCallback(JScallback callback)
507 {
508 HILOG_ERROR(" WallpaperManager::RegisterWallpaperCallback statrt");
509 SetCallback(callback);
510 auto wallpaperServerProxy = GetService();
511 if (wallpaperServerProxy == nullptr) {
512 HILOG_ERROR("Get proxy failed");
513 return false;
514 }
515
516 if (callback == nullptr) {
517 HILOG_ERROR("callback is NULL.");
518 return false;
519 }
520 HILOG_INFO(" WallpaperManager::RegisterWallpaperCallback");
521
522 bool status = wallpaperServerProxy->RegisterWallpaperCallback(new WallpaperServiceCbStub());
523 if (!status) {
524 HILOG_ERROR("off failed code=%d.", ERR_NONE);
525 return false;
526 }
527
528 return 0;
529 }
530
ReporterFault(FaultType faultType,FaultCode faultCode)531 void WallpaperManager::ReporterFault(FaultType faultType, FaultCode faultCode)
532 {
533 MiscServices::FaultMsg msg;
534 msg.faultType = faultType;
535 msg.errorCode = faultCode;
536 FaultReporter::ReportRuntimeFault(msg);
537 }
538
CloseWallpaperFd(int32_t wallpaperType)539 void WallpaperManager::CloseWallpaperFd(int32_t wallpaperType)
540 {
541 std::lock_guard<std::mutex> lock(wallpaperFdLock_);
542 std::map<int32_t, int32_t>::iterator iter = wallpaperFdMap_.find(wallpaperType);
543 if (iter != wallpaperFdMap_.end() && fcntl(iter->second, F_GETFL) != -1) {
544 close(iter->second);
545 wallpaperFdMap_.erase(iter);
546 }
547 }
548
SendEvent(const std::string & eventType)549 ErrorCode WallpaperManager::SendEvent(const std::string &eventType)
550 {
551 auto wallpaperServerProxy = GetService();
552 if (wallpaperServerProxy == nullptr) {
553 HILOG_ERROR("Get proxy failed");
554 return E_DEAL_FAILED;
555 }
556 return wallpaperServerProxy->SendEvent(eventType);
557 }
558
CheckVideoFormat(const std::string & fileName)559 bool WallpaperManager::CheckVideoFormat(const std::string &fileName)
560 {
561 int32_t videoFd = -1;
562 int64_t length = 0;
563 if (!OpenFile(fileName, videoFd, length)) {
564 HILOG_ERROR("Open file: %{public}s failed.", fileName.c_str());
565 return false;
566 }
567 std::shared_ptr<Media::AVMetadataHelper> helper = Media::AVMetadataHelperFactory::CreateAVMetadataHelper();
568 if (helper == nullptr) {
569 HILOG_ERROR("Create metadata helper failed!");
570 close(videoFd);
571 return false;
572 }
573 int32_t offset = 0;
574 int32_t errorCode = helper->SetSource(videoFd, offset, length);
575 if (errorCode != 0) {
576 HILOG_ERROR("Set helper source failed");
577 close(videoFd);
578 return false;
579 }
580 auto metaData = helper->ResolveMetadata();
581 if (metaData.find(Media::AV_KEY_MIME_TYPE) != metaData.end()) {
582 if (metaData[Media::AV_KEY_MIME_TYPE] != "video/mp4") {
583 HILOG_ERROR("Video mime type is not video/mp4!");
584 close(videoFd);
585 return false;
586 }
587 } else {
588 HILOG_INFO("Cannot get video mime type!");
589 close(videoFd);
590 return false;
591 }
592
593 if (metaData.find(Media::AV_KEY_DURATION) != metaData.end()) {
594 int32_t videoDuration = std::stoi(metaData[Media::AV_KEY_DURATION]);
595 if (videoDuration < MIN_TIME || videoDuration > MAX_TIME) {
596 HILOG_ERROR("The durations of this vodeo is not between 0s ~ 5s!");
597 close(videoFd);
598 return false;
599 }
600 } else {
601 HILOG_INFO("Cannot get the duration of this video!");
602 close(videoFd);
603 return false;
604 }
605 close(videoFd);
606 return true;
607 }
608
OpenFile(const std::string & fileName,int32_t & fd,int64_t & fileSize)609 bool WallpaperManager::OpenFile(const std::string &fileName, int32_t &fd, int64_t &fileSize)
610 {
611 if (!OHOS::FileExists(fileName)) {
612 HILOG_ERROR("File is not exist, file: %{public}s", fileName.c_str());
613 return false;
614 }
615
616 fd = open(fileName.c_str(), O_RDONLY);
617 if (fd <= 0) {
618 HILOG_ERROR("Get video fd failed!");
619 return false;
620 }
621 struct stat64 st;
622 if (fstat64(fd, &st) != 0) {
623 HILOG_ERROR("Failed to fstat64");
624 close(fd);
625 return false;
626 }
627 fileSize = static_cast<int64_t>(st.st_size);
628 return true;
629 }
630
CheckWallpaperFormat(const std::string & realPath,bool isLive,long & length)631 ErrorCode WallpaperManager::CheckWallpaperFormat(const std::string &realPath, bool isLive, long &length)
632 {
633 if (isLive && (FileDeal::GetExtension(realPath) != ".mp4" || !CheckVideoFormat(realPath))) {
634 HILOG_ERROR("Check live wallpaper file failed!");
635 return E_PARAMETERS_INVALID;
636 }
637
638 FILE *file = std::fopen(realPath.c_str(), "rb");
639 if (file == nullptr) {
640 HILOG_ERROR("Fopen failed, %{public}s, %{public}s", realPath.c_str(), strerror(errno));
641 return E_FILE_ERROR;
642 }
643
644 int32_t fend = fseek(file, 0, SEEK_END);
645 length = ftell(file);
646 int32_t fset = fseek(file, 0, SEEK_SET);
647 if (length <= 0 || (isLive && length > MAX_VIDEO_SIZE) || fend != 0 || fset != 0) {
648 HILOG_ERROR("ftell file failed or fseek file failed, errno %{public}d", errno);
649 fclose(file);
650 return E_FILE_ERROR;
651 }
652 fclose(file);
653 return E_OK;
654 }
655
656 } // namespace WallpaperMgrService
657 } // namespace OHOS