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 <fcntl.h>
16 #include <sys/stat.h>
17 #include <sys/types.h>
18 #include <unistd.h>
19 
20 #include <cerrno>
21 #include <cstdint>
22 #include <cstdio>
23 #include <cstdlib>
24 #include <cstring>
25 #include <fstream>
26 #include <iostream>
27 #include <mutex>
28 #include <sstream>
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_manager.h"
44 #include "wallpaper_service_cb_stub.h"
45 #include "wallpaper_service_proxy.h"
46 
47 namespace OHOS {
48 using namespace MiscServices;
49 namespace WallpaperMgrService {
50 constexpr int32_t MIN_TIME = 0;
51 constexpr int32_t MAX_TIME = 5000;
52 constexpr int32_t MAX_VIDEO_SIZE = 104857600;
53 constexpr int32_t MAX_RETRY_TIMES = 10;
54 constexpr int32_t TIME_INTERVAL = 500000;
55 constexpr mode_t MODE = 0660;
56 
57 using namespace OHOS::Media;
58 
WallpaperManager()59 WallpaperManager::WallpaperManager()
60 {
61 }
~WallpaperManager()62 WallpaperManager::~WallpaperManager()
63 {
64     std::map<int32_t, int32_t>::iterator iter = wallpaperFdMap_.begin();
65     while (iter != wallpaperFdMap_.end()) {
66         close(iter->second);
67         ++iter;
68     }
69 }
GetInstance()70 WallpaperManager &WallpaperManager::GetInstance()
71 {
72     static WallpaperManager wallpaperManager;
73     return wallpaperManager;
74 }
75 
DeathRecipient()76 WallpaperManager::DeathRecipient::DeathRecipient()
77 {
78 }
~DeathRecipient()79 WallpaperManager::DeathRecipient::~DeathRecipient()
80 {
81 }
ResetService(const wptr<IRemoteObject> & remote)82 void WallpaperManager::ResetService(const wptr<IRemoteObject> &remote)
83 {
84     HILOG_INFO("Remote is dead, reset service instance.");
85     std::lock_guard<std::mutex> lock(wallpaperProxyLock_);
86     if (wallpaperProxy_ != nullptr) {
87         sptr<IRemoteObject> object = wallpaperProxy_->AsObject();
88         if ((object != nullptr) && (remote == object)) {
89             object->RemoveDeathRecipient(deathRecipient_);
90             wallpaperProxy_ = nullptr;
91         }
92     }
93 }
94 
GetService()95 sptr<IWallpaperService> WallpaperManager::GetService()
96 {
97     std::lock_guard<std::mutex> lock(wallpaperProxyLock_);
98     if (wallpaperProxy_ != nullptr) {
99         return wallpaperProxy_;
100     }
101 
102     sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
103     if (samgr == nullptr) {
104         HILOG_ERROR("Get samgr failed!");
105         return nullptr;
106     }
107     sptr<IRemoteObject> object = samgr->GetSystemAbility(WALLPAPER_MANAGER_SERVICE_ID);
108     if (object == nullptr) {
109         HILOG_ERROR("Get wallpaper object from samgr failed!");
110         return nullptr;
111     }
112 
113     if (deathRecipient_ == nullptr) {
114         deathRecipient_ = new DeathRecipient();
115     }
116 
117     if ((object->IsProxyObject()) && (!object->AddDeathRecipient(deathRecipient_))) {
118         HILOG_ERROR("Failed to add death recipient!");
119     }
120 
121     wallpaperProxy_ = iface_cast<WallpaperServiceProxy>(object);
122     if (wallpaperProxy_ == nullptr) {
123         HILOG_ERROR("iface_cast failed!");
124     }
125     return wallpaperProxy_;
126 }
127 
OnRemoteDied(const wptr<IRemoteObject> & remote)128 void WallpaperManager::DeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
129 {
130     WallpaperManager::GetInstance().ResetService(remote);
131     int32_t times = 0;
132     bool result = false;
133     do {
134         times++;
135         result = WallpaperManager::GetInstance().RegisterWallpaperListener();
136         if (result != true) {
137             usleep(TIME_INTERVAL);
138         }
139     } while (result != true && times < MAX_RETRY_TIMES);
140     HILOG_INFO("Register WallpaperListener result:%{public}d.", result);
141 }
142 
CallService(F func,Args &&...args)143 template<typename F, typename... Args> ErrCode WallpaperManager::CallService(F func, Args &&...args)
144 {
145     auto service = GetService();
146     if (service == nullptr) {
147         HILOG_ERROR("get service failed!");
148         return ERR_DEAD_OBJECT;
149     }
150 
151     ErrCode result = (service->*func)(std::forward<Args>(args)...);
152     if (SUCCEEDED(result)) {
153         return ERR_OK;
154     }
155 
156     // Reset service instance if 'ERR_DEAD_OBJECT' happened.
157     if (result == ERR_DEAD_OBJECT) {
158         ResetService(service);
159     }
160 
161     HILOG_ERROR("Callservice failed with: %{public}d.", result);
162     return result;
163 }
164 
GetColors(int32_t wallpaperType,const ApiInfo & apiInfo,std::vector<uint64_t> & colors)165 ErrorCode WallpaperManager::GetColors(int32_t wallpaperType, const ApiInfo &apiInfo, std::vector<uint64_t> &colors)
166 {
167     auto wallpaperServerProxy = GetService();
168     if (wallpaperServerProxy == nullptr) {
169         HILOG_ERROR("Get proxy failed!");
170         return E_DEAL_FAILED;
171     }
172     if (apiInfo.isSystemApi) {
173         return wallpaperServerProxy->GetColorsV9(wallpaperType, colors);
174     }
175     return wallpaperServerProxy->GetColors(wallpaperType, colors);
176 }
177 
GetFile(int32_t wallpaperType,int32_t & wallpaperFd)178 ErrorCode WallpaperManager::GetFile(int32_t wallpaperType, int32_t &wallpaperFd)
179 {
180     auto wallpaperServerProxy = GetService();
181     if (wallpaperServerProxy == nullptr) {
182         HILOG_ERROR("Get proxy failed!");
183         return E_DEAL_FAILED;
184     }
185     std::lock_guard<std::mutex> lock(wallpaperFdLock_);
186     std::map<int32_t, int32_t>::iterator iter = wallpaperFdMap_.find(wallpaperType);
187     if (iter != wallpaperFdMap_.end() && fcntl(iter->second, F_GETFL) != -1) {
188         close(iter->second);
189         wallpaperFdMap_.erase(iter);
190     }
191     ErrorCode wallpaperErrorCode = wallpaperServerProxy->GetFile(wallpaperType, wallpaperFd);
192     if (wallpaperErrorCode == E_OK && wallpaperFd != -1) {
193         wallpaperFdMap_.insert(std::pair<int32_t, int32_t>(wallpaperType, wallpaperFd));
194     }
195     return wallpaperErrorCode;
196 }
197 
SetWallpaper(std::string uri,int32_t wallpaperType,const ApiInfo & apiInfo)198 ErrorCode WallpaperManager::SetWallpaper(std::string uri, int32_t wallpaperType, const ApiInfo &apiInfo)
199 {
200     auto wallpaperServerProxy = GetService();
201     if (wallpaperServerProxy == nullptr) {
202         HILOG_ERROR("Get proxy failed!");
203         return E_DEAL_FAILED;
204     }
205     std::string fileRealPath;
206     if (!FileDeal::GetRealPath(uri, fileRealPath)) {
207         HILOG_ERROR("get real path file failed, len = %{public}zu.", uri.size());
208         return E_PARAMETERS_INVALID;
209     }
210 
211     long length = 0;
212     ErrorCode wallpaperErrorCode = CheckWallpaperFormat(fileRealPath, false, length);
213     if (wallpaperErrorCode != E_OK) {
214         HILOG_ERROR("Check wallpaper format failed!");
215         return wallpaperErrorCode;
216     }
217 
218     int32_t fd = open(fileRealPath.c_str(), O_RDONLY, MODE);
219     if (fd < 0) {
220         HILOG_ERROR("open file failed, errno %{public}d!", errno);
221         ReporterFault(FaultType::SET_WALLPAPER_FAULT, FaultCode::RF_FD_INPUT_FAILED);
222         return E_FILE_ERROR;
223     }
224     StartAsyncTrace(HITRACE_TAG_MISC, "SetWallpaper", static_cast<int32_t>(TraceTaskId::SET_WALLPAPER));
225     if (apiInfo.isSystemApi) {
226         wallpaperErrorCode = wallpaperServerProxy->SetWallpaperV9(fd, wallpaperType, length);
227     } else {
228         wallpaperErrorCode = wallpaperServerProxy->SetWallpaper(fd, wallpaperType, length);
229     }
230     close(fd);
231     if (wallpaperErrorCode == E_OK) {
232         CloseWallpaperFd(wallpaperType);
233     }
234     FinishAsyncTrace(HITRACE_TAG_MISC, "SetWallpaper", static_cast<int32_t>(TraceTaskId::SET_WALLPAPER));
235     return wallpaperErrorCode;
236 }
237 
SetWallpaper(std::shared_ptr<OHOS::Media::PixelMap> pixelMap,int32_t wallpaperType,const ApiInfo & apiInfo)238 ErrorCode WallpaperManager::SetWallpaper(
239     std::shared_ptr<OHOS::Media::PixelMap> pixelMap, int32_t wallpaperType, const ApiInfo &apiInfo)
240 {
241     auto wallpaperServerProxy = GetService();
242     if (wallpaperServerProxy == nullptr) {
243         HILOG_ERROR("Get proxy failed!");
244         return E_DEAL_FAILED;
245     }
246 
247     ErrorCode wallpaperErrorCode = E_UNKNOWN;
248     if (apiInfo.isSystemApi) {
249         wallpaperErrorCode = wallpaperServerProxy->SetWallpaperV9ByPixelMap(pixelMap, wallpaperType);
250     } else {
251         wallpaperErrorCode = wallpaperServerProxy->SetWallpaperByPixelMap(pixelMap, wallpaperType);
252     }
253     if (wallpaperErrorCode == static_cast<int32_t>(E_OK)) {
254         CloseWallpaperFd(wallpaperType);
255     }
256     return wallpaperErrorCode;
257 }
258 
SetVideo(const std::string & uri,const int32_t wallpaperType)259 ErrorCode WallpaperManager::SetVideo(const std::string &uri, const int32_t wallpaperType)
260 {
261     auto wallpaperServerProxy = GetService();
262     if (wallpaperServerProxy == nullptr) {
263         HILOG_ERROR("Get proxy failed!");
264         return E_DEAL_FAILED;
265     }
266     std::string fileRealPath;
267     if (!FileDeal::GetRealPath(uri, fileRealPath)) {
268         HILOG_ERROR("Get real path failed, uri: %{public}s!", uri.c_str());
269         return E_PARAMETERS_INVALID;
270     }
271 
272     long length = 0;
273     ErrorCode wallpaperErrorCode = CheckWallpaperFormat(fileRealPath, true, length);
274     if (wallpaperErrorCode != E_OK) {
275         HILOG_ERROR("Check wallpaper format failed!");
276         return wallpaperErrorCode;
277     }
278     int32_t fd = open(fileRealPath.c_str(), O_RDONLY, MODE);
279     if (fd < 0) {
280         HILOG_ERROR("Open file failed, errno %{public}d!", errno);
281         ReporterFault(FaultType::SET_WALLPAPER_FAULT, FaultCode::RF_FD_INPUT_FAILED);
282         return E_FILE_ERROR;
283     }
284     StartAsyncTrace(HITRACE_TAG_MISC, "SetVideo", static_cast<int32_t>(TraceTaskId::SET_VIDEO));
285     wallpaperErrorCode = wallpaperServerProxy->SetVideo(fd, wallpaperType, length);
286     close(fd);
287     FinishAsyncTrace(HITRACE_TAG_MISC, "SetVideo", static_cast<int32_t>(TraceTaskId::SET_VIDEO));
288     return wallpaperErrorCode;
289 }
290 
SetCustomWallpaper(const std::string & uri,const int32_t wallpaperType)291 ErrorCode WallpaperManager::SetCustomWallpaper(const std::string &uri, const int32_t wallpaperType)
292 {
293     auto wallpaperServerProxy = GetService();
294     if (wallpaperServerProxy == nullptr) {
295         HILOG_ERROR("Get proxy failed!");
296         return E_DEAL_FAILED;
297     }
298     std::string fileRealPath;
299     if (!FileDeal::GetRealPath(uri, fileRealPath)) {
300         HILOG_ERROR("Get real path failed, uri: %{public}s!", uri.c_str());
301         return E_PARAMETERS_INVALID;
302     }
303     if (!FileDeal::IsZipFile(uri)) {
304         return E_FILE_ERROR;
305     }
306     long length = 0;
307     ErrorCode wallpaperErrorCode = CheckWallpaperFormat(fileRealPath, false, length);
308     if (wallpaperErrorCode != E_OK) {
309         HILOG_ERROR("Check wallpaper format failed!");
310         return wallpaperErrorCode;
311     }
312     int32_t fd = open(fileRealPath.c_str(), O_RDONLY, MODE);
313     if (fd < 0) {
314         HILOG_ERROR("Open file failed, errno %{public}d!", errno);
315         ReporterFault(FaultType::SET_WALLPAPER_FAULT, FaultCode::RF_FD_INPUT_FAILED);
316         return E_FILE_ERROR;
317     }
318     StartAsyncTrace(HITRACE_TAG_MISC, "SetCustomWallpaper", static_cast<int32_t>(TraceTaskId::SET_CUSTOM_WALLPAPER));
319     wallpaperErrorCode = wallpaperServerProxy->SetCustomWallpaper(fd, wallpaperType, length);
320     close(fd);
321     FinishAsyncTrace(HITRACE_TAG_MISC, "SetCustomWallpaper", static_cast<int32_t>(TraceTaskId::SET_CUSTOM_WALLPAPER));
322     return wallpaperErrorCode;
323 }
324 
GetPixelMap(int32_t wallpaperType,const ApiInfo & apiInfo,std::shared_ptr<OHOS::Media::PixelMap> & pixelMap)325 ErrorCode WallpaperManager::GetPixelMap(
326     int32_t wallpaperType, const ApiInfo &apiInfo, std::shared_ptr<OHOS::Media::PixelMap> &pixelMap)
327 {
328     HILOG_INFO("FrameWork GetPixelMap Start by FD.");
329     auto wallpaperServerProxy = GetService();
330     if (wallpaperServerProxy == nullptr) {
331         HILOG_ERROR("Get proxy failed!");
332         return E_SA_DIED;
333     }
334     IWallpaperService::FdInfo fdInfo;
335     ErrorCode wallpaperErrorCode = E_UNKNOWN;
336     if (apiInfo.isSystemApi) {
337         wallpaperErrorCode = wallpaperServerProxy->GetPixelMapV9(wallpaperType, fdInfo);
338     } else {
339         wallpaperErrorCode = wallpaperServerProxy->GetPixelMap(wallpaperType, fdInfo);
340     }
341     if (wallpaperErrorCode != E_OK) {
342         return wallpaperErrorCode;
343     }
344     // current wallpaper is live video, not image
345     if (fdInfo.size == 0 && fdInfo.fd == -1) { // 0: empty file size; -1: invalid file description
346         pixelMap = nullptr;
347         return E_OK;
348     }
349     wallpaperErrorCode = CreatePixelMapByFd(fdInfo.fd, fdInfo.size, pixelMap);
350     if (wallpaperErrorCode != E_OK) {
351         pixelMap = nullptr;
352         return wallpaperErrorCode;
353     }
354     return wallpaperErrorCode;
355 }
356 
CreatePixelMapByFd(int32_t fd,int32_t size,std::shared_ptr<OHOS::Media::PixelMap> & pixelMap)357 ErrorCode WallpaperManager::CreatePixelMapByFd(
358     int32_t fd, int32_t size, std::shared_ptr<OHOS::Media::PixelMap> &pixelMap)
359 {
360     if (size <= 0 && fd < 0) {
361         HILOG_ERROR("Size or fd error!");
362         return E_IMAGE_ERRCODE;
363     }
364     uint8_t *buffer = new uint8_t[size];
365     ssize_t bytesRead = read(fd, buffer, size);
366     if (bytesRead < 0) {
367         HILOG_ERROR("Read fd to buffer fail!");
368         delete[] buffer;
369         close(fd);
370         return E_IMAGE_ERRCODE;
371     }
372     uint32_t errorCode = 0;
373     OHOS::Media::SourceOptions opts;
374     opts.formatHint = "image/jpeg";
375     std::unique_ptr<OHOS::Media::ImageSource> imageSource =
376         OHOS::Media::ImageSource::CreateImageSource(buffer, size, opts, errorCode);
377     if (errorCode != 0 || imageSource == nullptr) {
378         HILOG_ERROR("ImageSource::CreateImageSource failed, errcode= %{public}d!", errorCode);
379         delete[] buffer;
380         close(fd);
381         return E_IMAGE_ERRCODE;
382     }
383     OHOS::Media::DecodeOptions decodeOpts;
384     pixelMap = imageSource->CreatePixelMap(decodeOpts, errorCode);
385     if (errorCode != 0) {
386         HILOG_ERROR("ImageSource::CreatePixelMap failed, errcode= %{public}d!", errorCode);
387         delete[] buffer;
388         close(fd);
389         return E_IMAGE_ERRCODE;
390     }
391     delete[] buffer;
392     close(fd);
393     return E_OK;
394 }
395 
GetWallpaperId(int32_t wallpaperType)396 int32_t WallpaperManager::GetWallpaperId(int32_t wallpaperType)
397 {
398     auto wallpaperServerProxy = GetService();
399     if (wallpaperServerProxy == nullptr) {
400         HILOG_ERROR("Get proxy failed!");
401         return -1;
402     }
403     return wallpaperServerProxy->GetWallpaperId(wallpaperType);
404 }
405 
GetWallpaperMinHeight(const ApiInfo & apiInfo,int32_t & minHeight)406 ErrorCode WallpaperManager::GetWallpaperMinHeight(const ApiInfo &apiInfo, int32_t &minHeight)
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     minHeight = display->GetHeight();
414     return E_OK;
415 }
416 
GetWallpaperMinWidth(const ApiInfo & apiInfo,int32_t & minWidth)417 ErrorCode WallpaperManager::GetWallpaperMinWidth(const ApiInfo &apiInfo, int32_t &minWidth)
418 {
419     auto display = Rosen::DisplayManager::GetInstance().GetDefaultDisplay();
420     if (display == nullptr) {
421         HILOG_ERROR("GetDefaultDisplay is nullptr.");
422         return E_DEAL_FAILED;
423     }
424     minWidth = display->GetWidth();
425     return E_OK;
426 }
427 
IsChangePermitted()428 bool WallpaperManager::IsChangePermitted()
429 {
430     auto wallpaperServerProxy = GetService();
431     if (wallpaperServerProxy == nullptr) {
432         HILOG_ERROR("Get proxy failed!");
433         return false;
434     }
435     return wallpaperServerProxy->IsChangePermitted();
436 }
437 
IsOperationAllowed()438 bool WallpaperManager::IsOperationAllowed()
439 {
440     auto wallpaperServerProxy = GetService();
441     if (wallpaperServerProxy == nullptr) {
442         HILOG_ERROR("Get proxy failed!");
443         return false;
444     }
445     return wallpaperServerProxy->IsOperationAllowed();
446 }
ResetWallpaper(std::int32_t wallpaperType,const ApiInfo & apiInfo)447 ErrorCode WallpaperManager::ResetWallpaper(std::int32_t wallpaperType, const ApiInfo &apiInfo)
448 {
449     auto wallpaperServerProxy = GetService();
450     if (wallpaperServerProxy == nullptr) {
451         HILOG_ERROR("Get proxy failed!");
452         return E_SA_DIED;
453     }
454     ErrorCode wallpaperErrorCode = E_UNKNOWN;
455     if (apiInfo.isSystemApi) {
456         wallpaperErrorCode = wallpaperServerProxy->ResetWallpaperV9(wallpaperType);
457     } else {
458         wallpaperErrorCode = wallpaperServerProxy->ResetWallpaper(wallpaperType);
459     }
460     if (wallpaperErrorCode == E_OK) {
461         CloseWallpaperFd(wallpaperType);
462     }
463     return wallpaperErrorCode;
464 }
465 
On(const std::string & type,std::shared_ptr<WallpaperEventListener> listener)466 ErrorCode WallpaperManager::On(const std::string &type, std::shared_ptr<WallpaperEventListener> listener)
467 {
468     HILOG_DEBUG("WallpaperManager::On in.");
469     auto wallpaperServerProxy = GetService();
470     if (wallpaperServerProxy == nullptr) {
471         HILOG_ERROR("Get proxy failed!");
472         return E_SA_DIED;
473     }
474     if (listener == nullptr) {
475         HILOG_ERROR("listener is nullptr.");
476         return E_DEAL_FAILED;
477     }
478     sptr<WallpaperEventListenerClient> ipcListener = new (std::nothrow) WallpaperEventListenerClient(listener);
479     if (ipcListener == nullptr) {
480         HILOG_ERROR("new WallpaperEventListenerClient failed!");
481         return E_NO_MEMORY;
482     }
483     {
484         std::lock_guard<std::mutex> lock(listenerMapLock_);
485         listenerMap_.insert_or_assign(type, ipcListener);
486     }
487     return wallpaperServerProxy->On(type, ipcListener);
488 }
489 
Off(const std::string & type,std::shared_ptr<WallpaperEventListener> listener)490 ErrorCode WallpaperManager::Off(const std::string &type, std::shared_ptr<WallpaperEventListener> listener)
491 {
492     HILOG_DEBUG("WallpaperManager::Off in.");
493     auto wallpaperServerProxy = GetService();
494     if (wallpaperServerProxy == nullptr) {
495         HILOG_ERROR("Get proxy failed!");
496         return E_SA_DIED;
497     }
498     sptr<WallpaperEventListenerClient> ipcListener = nullptr;
499     if (listener != nullptr) {
500         ipcListener = new (std::nothrow) WallpaperEventListenerClient(listener);
501         if (ipcListener == nullptr) {
502             HILOG_ERROR("new WallpaperEventListenerClient failed!");
503             return E_NO_MEMORY;
504         }
505     }
506     return wallpaperServerProxy->Off(type, ipcListener);
507 }
508 
GetCallback()509 JScallback WallpaperManager::GetCallback()
510 {
511     return callback;
512 }
513 
SetCallback(JScallback cb)514 void WallpaperManager::SetCallback(JScallback cb)
515 {
516     callback = cb;
517 }
518 
RegisterWallpaperCallback(JScallback callback)519 bool WallpaperManager::RegisterWallpaperCallback(JScallback callback)
520 {
521     HILOG_INFO("  WallpaperManager::RegisterWallpaperCallback statrt.");
522     SetCallback(callback);
523     auto wallpaperServerProxy = GetService();
524     if (wallpaperServerProxy == nullptr) {
525         HILOG_ERROR("Get proxy failed");
526         return false;
527     }
528 
529     if (callback == nullptr) {
530         HILOG_ERROR("callback is NULL.");
531         return false;
532     }
533 
534     bool status = wallpaperServerProxy->RegisterWallpaperCallback(new WallpaperServiceCbStub());
535     if (!status) {
536         HILOG_ERROR("off failed code=%d.", ERR_NONE);
537         return false;
538     }
539     return true;
540 }
541 
ReporterFault(FaultType faultType,FaultCode faultCode)542 void WallpaperManager::ReporterFault(FaultType faultType, FaultCode faultCode)
543 {
544     MiscServices::FaultMsg msg;
545     msg.faultType = faultType;
546     msg.errorCode = faultCode;
547     FaultReporter::ReportRuntimeFault(msg);
548 }
549 
CloseWallpaperFd(int32_t wallpaperType)550 void WallpaperManager::CloseWallpaperFd(int32_t wallpaperType)
551 {
552     std::lock_guard<std::mutex> lock(wallpaperFdLock_);
553     std::map<int32_t, int32_t>::iterator iter = wallpaperFdMap_.find(wallpaperType);
554     if (iter != wallpaperFdMap_.end() && fcntl(iter->second, F_GETFL) != -1) {
555         close(iter->second);
556         wallpaperFdMap_.erase(iter);
557     }
558 }
559 
RegisterWallpaperListener()560 bool WallpaperManager::RegisterWallpaperListener()
561 {
562     auto service = GetService();
563     if (service == nullptr) {
564         HILOG_ERROR("Get proxy failed!");
565         return false;
566     }
567 
568     std::lock_guard<std::mutex> lock(listenerMapLock_);
569     for (const auto &iter : listenerMap_) {
570         auto ret = service->On(iter.first, iter.second);
571         if (ret != E_OK) {
572             HILOG_ERROR(
573                 "Register WallpaperListener failed type:%{public}s, errcode:%{public}d", iter.first.c_str(), ret);
574             return false;
575         }
576     }
577     return true;
578 }
SendEvent(const std::string & eventType)579 ErrorCode WallpaperManager::SendEvent(const std::string &eventType)
580 {
581     auto wallpaperServerProxy = GetService();
582     if (wallpaperServerProxy == nullptr) {
583         HILOG_ERROR("Get proxy failed!");
584         return E_DEAL_FAILED;
585     }
586     return wallpaperServerProxy->SendEvent(eventType);
587 }
588 
CheckVideoFormat(const std::string & fileName)589 bool WallpaperManager::CheckVideoFormat(const std::string &fileName)
590 {
591     int32_t videoFd = -1;
592     int64_t length = 0;
593     if (!OpenFile(fileName, videoFd, length)) {
594         HILOG_ERROR("Open file: %{public}s failed!", fileName.c_str());
595         return false;
596     }
597     std::shared_ptr<Media::AVMetadataHelper> helper = Media::AVMetadataHelperFactory::CreateAVMetadataHelper();
598     if (helper == nullptr) {
599         HILOG_ERROR("Create metadata helper failed!");
600         close(videoFd);
601         return false;
602     }
603     int32_t offset = 0;
604     int32_t errorCode = helper->SetSource(videoFd, offset, length);
605     if (errorCode != 0) {
606         HILOG_ERROR("Set helper source failed!");
607         close(videoFd);
608         return false;
609     }
610     auto metaData = helper->ResolveMetadata();
611     if (metaData.find(Media::AV_KEY_MIME_TYPE) != metaData.end()) {
612         if (metaData[Media::AV_KEY_MIME_TYPE] != "video/mp4") {
613             HILOG_ERROR("Video mime type is not video/mp4!");
614             close(videoFd);
615             return false;
616         }
617     } else {
618         HILOG_ERROR("Cannot get video mime type!");
619         close(videoFd);
620         return false;
621     }
622 
623     if (metaData.find(Media::AV_KEY_DURATION) != metaData.end()) {
624         int32_t videoDuration = std::stoi(metaData[Media::AV_KEY_DURATION]);
625         if (videoDuration < MIN_TIME || videoDuration > MAX_TIME) {
626             HILOG_ERROR("The durations of this vodeo is not between 0s ~ 5s!");
627             close(videoFd);
628             return false;
629         }
630     } else {
631         HILOG_ERROR("Cannot get the duration of this video!");
632         close(videoFd);
633         return false;
634     }
635     close(videoFd);
636     return true;
637 }
638 
OpenFile(const std::string & fileName,int32_t & fd,int64_t & fileSize)639 bool WallpaperManager::OpenFile(const std::string &fileName, int32_t &fd, int64_t &fileSize)
640 {
641     if (!OHOS::FileExists(fileName)) {
642         HILOG_ERROR("File is not exist, file: %{public}s.", fileName.c_str());
643         return false;
644     }
645 
646     fd = open(fileName.c_str(), O_RDONLY);
647     if (fd <= 0) {
648         HILOG_ERROR("Get video fd failed!");
649         return false;
650     }
651     struct stat64 st;
652     if (fstat64(fd, &st) != 0) {
653         HILOG_ERROR("Failed to fstat64!");
654         close(fd);
655         return false;
656     }
657     fileSize = static_cast<int64_t>(st.st_size);
658     return true;
659 }
660 
CheckWallpaperFormat(const std::string & realPath,bool isLive,long & length)661 ErrorCode WallpaperManager::CheckWallpaperFormat(const std::string &realPath, bool isLive, long &length)
662 {
663     if (isLive && (FileDeal::GetExtension(realPath) != ".mp4" || !CheckVideoFormat(realPath))) {
664         HILOG_ERROR("Check live wallpaper file failed!");
665         return E_PARAMETERS_INVALID;
666     }
667 
668     FILE *file = std::fopen(realPath.c_str(), "rb");
669     if (file == nullptr) {
670         HILOG_ERROR("Fopen failed, %{public}s, %{public}s!", realPath.c_str(), strerror(errno));
671         return E_FILE_ERROR;
672     }
673 
674     int32_t fend = fseek(file, 0, SEEK_END);
675     length = ftell(file);
676     int32_t fset = fseek(file, 0, SEEK_SET);
677     if (length <= 0 || (isLive && length > MAX_VIDEO_SIZE) || fend != 0 || fset != 0) {
678         HILOG_ERROR("ftell file failed or fseek file failed, errno %{public}d!", errno);
679         fclose(file);
680         return E_FILE_ERROR;
681     }
682     fclose(file);
683     return E_OK;
684 }
685 
SetAllWallpapers(std::vector<WallpaperInfo> allWallpaperInfos,int32_t wallpaperType)686 ErrorCode WallpaperManager::SetAllWallpapers(std::vector<WallpaperInfo> allWallpaperInfos, int32_t wallpaperType)
687 {
688     auto wallpaperServerProxy = GetService();
689     if (wallpaperServerProxy == nullptr) {
690         HILOG_ERROR("Get proxy failed!");
691         return E_DEAL_FAILED;
692     }
693     WallpaperPictureInfo wallpaperPictureInfo;
694     std::vector<WallpaperPictureInfo> WallpaperPictureInfos;
695     ErrorCode wallpaperCode;
696     for (const auto &wallpaperInfo : allWallpaperInfos) {
697         std::string fileRealPath;
698         if (!FileDeal::GetRealPath(wallpaperInfo.source, fileRealPath)) {
699             HILOG_ERROR("get real path file failed, len = %{public}zu.", wallpaperInfo.source.size());
700             return E_PARAMETERS_INVALID;
701         }
702         wallpaperCode = GetFdByPath(wallpaperInfo, wallpaperPictureInfo, fileRealPath);
703         if (wallpaperCode != E_OK) {
704             CloseWallpaperInfoFd(WallpaperPictureInfos);
705             HILOG_ERROR("PathConvertFd failed");
706             return wallpaperCode;
707         }
708         WallpaperPictureInfos.push_back(wallpaperPictureInfo);
709     }
710 
711     StartAsyncTrace(HITRACE_TAG_MISC, "SetAllWallpapers", static_cast<int32_t>(TraceTaskId::SET_ALL_WALLPAPERS));
712     ErrorCode wallpaperErrorCode = wallpaperServerProxy->SetAllWallpapers(WallpaperPictureInfos, wallpaperType);
713     if (wallpaperErrorCode == E_OK) {
714         CloseWallpaperFd(wallpaperType);
715     }
716     CloseWallpaperInfoFd(WallpaperPictureInfos);
717     FinishAsyncTrace(HITRACE_TAG_MISC, "SetAllWallpapers", static_cast<int32_t>(TraceTaskId::SET_ALL_WALLPAPERS));
718     return wallpaperErrorCode;
719 }
720 
GetFdByPath(const WallpaperInfo & wallpaperInfo,WallpaperPictureInfo & wallpaperPictureInfo,std::string fileRealPath)721 ErrorCode WallpaperManager::GetFdByPath(
722     const WallpaperInfo &wallpaperInfo, WallpaperPictureInfo &wallpaperPictureInfo, std::string fileRealPath)
723 {
724     wallpaperPictureInfo.foldState = wallpaperInfo.foldState;
725     wallpaperPictureInfo.rotateState = wallpaperInfo.rotateState;
726     wallpaperPictureInfo.fd = open(fileRealPath.c_str(), O_RDONLY, MODE);
727     if (wallpaperPictureInfo.fd < 0) {
728         HILOG_ERROR("open file failed, errno %{public}d!", errno);
729         ReporterFault(FaultType::SET_WALLPAPER_FAULT, FaultCode::RF_FD_INPUT_FAILED);
730         return E_FILE_ERROR;
731     }
732     ErrorCode wallpaperErrorCode = CheckWallpaperFormat(fileRealPath, false, wallpaperPictureInfo.length);
733     if (wallpaperErrorCode != E_OK) {
734         HILOG_ERROR("Check wallpaper format failed!");
735         return wallpaperErrorCode;
736     }
737     uint32_t errorCode = 0;
738     OHOS::Media::SourceOptions opts;
739     std::unique_ptr<OHOS::Media::ImageSource> imageSource =
740         OHOS::Media::ImageSource::CreateImageSource(fileRealPath, opts, errorCode);
741     if (errorCode != 0 || imageSource == nullptr) {
742         HILOG_ERROR("CreateImageSource failed!");
743         return E_PARAMETERS_INVALID;
744     }
745     ImageInfo imageInfo;
746     if (imageSource->GetImageInfo(imageInfo) != 0) {
747         HILOG_ERROR("GetImageInfo failed!");
748         return E_PARAMETERS_INVALID;
749     }
750     return wallpaperErrorCode;
751 }
752 
GetCorrespondWallpaper(int32_t wallpaperType,int32_t foldState,int32_t rotateState,std::shared_ptr<OHOS::Media::PixelMap> & pixelMap)753 ErrorCode WallpaperManager::GetCorrespondWallpaper(
754     int32_t wallpaperType, int32_t foldState, int32_t rotateState, std::shared_ptr<OHOS::Media::PixelMap> &pixelMap)
755 {
756     HILOG_INFO("GetCorrespondWallpaper start.");
757     auto wallpaperServerProxy = GetService();
758     if (wallpaperServerProxy == nullptr) {
759         HILOG_ERROR("Get proxy failed!");
760         return E_SA_DIED;
761     }
762     IWallpaperService::FdInfo fdInfo;
763     ErrorCode wallpaperErrorCode = E_UNKNOWN;
764     wallpaperErrorCode = wallpaperServerProxy->GetCorrespondWallpaper(wallpaperType, foldState, rotateState, fdInfo);
765     if (wallpaperErrorCode != E_OK) {
766         return wallpaperErrorCode;
767     }
768     // current wallpaper is live video, not image
769     if (fdInfo.size == 0 && fdInfo.fd == -1) { // 0: empty file size; -1: invalid file description
770         pixelMap = nullptr;
771         return E_OK;
772     }
773     wallpaperErrorCode = CreatePixelMapByFd(fdInfo.fd, fdInfo.size, pixelMap);
774     if (wallpaperErrorCode != E_OK) {
775         pixelMap = nullptr;
776         return wallpaperErrorCode;
777     }
778     return wallpaperErrorCode;
779 }
780 
CloseWallpaperInfoFd(std::vector<WallpaperPictureInfo> wallpaperPictureInfos)781 void WallpaperManager::CloseWallpaperInfoFd(std::vector<WallpaperPictureInfo> wallpaperPictureInfos)
782 {
783     for (auto &wallpaperInfo : wallpaperPictureInfos) {
784         if (wallpaperInfo.fd >= 0) {
785             close(wallpaperInfo.fd);
786         }
787     }
788 }
789 } // namespace WallpaperMgrService
790 } // namespace OHOS