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