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