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