• 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 "wallpaper_manager.h"
16 
17 #include <fcntl.h>
18 #include <sys/stat.h>
19 #include <sys/types.h>
20 #include <unistd.h>
21 
22 #include <cerrno>
23 #include <cstdio>
24 #include <cstdlib>
25 #include <cstring>
26 #include <fstream>
27 #include <iostream>
28 #include <mutex>
29 #include <sstream>
30 
31 #include "dfx_types.h"
32 #include "file_deal.h"
33 #include "file_ex.h"
34 #include "hilog_wrapper.h"
35 #include "hitrace_meter.h"
36 #include "i_wallpaper_service.h"
37 #include "if_system_ability_manager.h"
38 #include "image_packer.h"
39 #include "image_source.h"
40 #include "image_type.h"
41 #include "iservice_registry.h"
42 #include "system_ability_definition.h"
43 #include "wallpaper_service_cb_stub.h"
44 #include "wallpaper_service_proxy.h"
45 
46 namespace OHOS {
47 using namespace MiscServices;
48 namespace WallpaperMgrService {
49 constexpr int OPTION_QUALITY = 100;
WallpaperManager()50 WallpaperManager::WallpaperManager() {}
~WallpaperManager()51 WallpaperManager::~WallpaperManager()
52 {
53     std::map<int32_t, int32_t>::iterator iter = wallpaperFdMap_.begin();
54     while (iter != wallpaperFdMap_.end()) {
55         close(iter->second);
56         ++iter;
57     }
58 }
59 
ResetService(const wptr<IRemoteObject> & remote)60 void WallpaperManager::ResetService(const wptr<IRemoteObject> &remote)
61 {
62     HILOG_INFO("Remote is dead, reset service instance");
63     std::lock_guard<std::mutex> lock(wpProxyLock_);
64     if (wpProxy_ != nullptr) {
65         sptr<IRemoteObject> object = wpProxy_->AsObject();
66         if ((object != nullptr) && (remote == object)) {
67             object->RemoveDeathRecipient(deathRecipient_);
68             wpProxy_ = nullptr;
69         }
70     }
71 }
72 
GetService()73 sptr<IWallpaperService> WallpaperManager::GetService()
74 {
75     std::lock_guard<std::mutex> lock(wpProxyLock_);
76     if (wpProxy_ != nullptr) {
77         return wpProxy_;
78     }
79 
80     sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
81     if (samgr == nullptr) {
82         HILOG_ERROR("Get samgr failed");
83         return nullptr;
84     }
85     sptr<IRemoteObject> object = samgr->GetSystemAbility(WALLPAPER_MANAGER_SERVICE_ID);
86     if (object == nullptr) {
87         HILOG_ERROR("Get wallpaper object from samgr failed");
88         return nullptr;
89     }
90 
91     if (deathRecipient_ == nullptr) {
92         deathRecipient_ = new DeathRecipient();
93     }
94 
95     if ((object->IsProxyObject()) && (!object->AddDeathRecipient(deathRecipient_))) {
96         HILOG_ERROR("Failed to add death recipient");
97     }
98 
99     HILOG_INFO("get remote object ok");
100     wpProxy_ = iface_cast<WallpaperServiceProxy>(object);
101     if (wpProxy_ == nullptr) {
102         HILOG_ERROR("iface_cast failed");
103     }
104     return wpProxy_;
105 }
106 
OnRemoteDied(const wptr<IRemoteObject> & remote)107 void WallpaperManager::DeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
108 {
109     DelayedRefSingleton<WallpaperManager>::GetInstance().ResetService(remote);
110 }
111 
CallService(F func,Args &&...args)112 template<typename F, typename... Args> ErrCode WallpaperManager::CallService(F func, Args &&...args)
113 {
114     auto service = GetService();
115     if (service == nullptr) {
116         HILOG_ERROR("get service failed");
117         return ERR_DEAD_OBJECT;
118     }
119 
120     ErrCode result = (service->*func)(std::forward<Args>(args)...);
121     if (SUCCEEDED(result)) {
122         return ERR_OK;
123     }
124 
125     // Reset service instance if 'ERR_DEAD_OBJECT' happened.
126     if (result == ERR_DEAD_OBJECT) {
127         ResetService(service);
128     }
129 
130     HILOG_ERROR("Callservice failed with: %{public}d", result);
131     return result;
132 }
133 
GetColors(int32_t wallpaperType,const ApiInfo & apiInfo,std::vector<uint64_t> & colors)134 int32_t WallpaperManager::GetColors(int32_t wallpaperType, const ApiInfo &apiInfo, std::vector<uint64_t> &colors)
135 {
136     auto wpServerProxy = GetService();
137     if (wpServerProxy == nullptr) {
138         HILOG_ERROR("Get proxy failed");
139         return static_cast<int32_t>(E_DEAL_FAILED);
140     }
141     if (apiInfo.isSystemApi) {
142         return wpServerProxy->GetColorsV9(wallpaperType, colors);
143     }
144     return wpServerProxy->GetColors(wallpaperType, colors);
145 }
146 
GetFile(int32_t wallpaperType,int32_t & wallpaperFd)147 int32_t WallpaperManager::GetFile(int32_t wallpaperType, int32_t &wallpaperFd)
148 {
149     auto wpServerProxy = GetService();
150     if (wpServerProxy == nullptr) {
151         HILOG_ERROR("Get proxy failed");
152         return -1;
153     }
154     std::lock_guard<std::mutex> lock(wpFdLock_);
155     std::map<int32_t, int32_t>::iterator iter = wallpaperFdMap_.find(wallpaperType);
156     if (iter != wallpaperFdMap_.end() && fcntl(iter->second, F_GETFL) != -1) {
157         close(iter->second);
158         wallpaperFdMap_.erase(iter);
159     }
160     int32_t wallpaperErrorCode = wpServerProxy->GetFile(wallpaperType, wallpaperFd);
161     if (wallpaperErrorCode == static_cast<int32_t>(E_OK) && wallpaperFd != -1) {
162         wallpaperFdMap_.insert(std::pair<int32_t, int32_t>(wallpaperType, wallpaperFd));
163     }
164     return wallpaperErrorCode;
165 }
166 
SetWallpaper(std::string url,int32_t wallpaperType,const ApiInfo & apiInfo)167 int32_t WallpaperManager::SetWallpaper(std::string url, int32_t wallpaperType, const ApiInfo &apiInfo)
168 {
169     auto wpServerProxy = GetService();
170     if (wpServerProxy == nullptr) {
171         HILOG_ERROR("Get proxy failed");
172         return static_cast<int32_t>(E_DEAL_FAILED);
173     }
174     std::string fileRealPath;
175     if (!GetRealPath(url, fileRealPath)) {
176         HILOG_ERROR("get real path file failed, len = %{public}zu", url.size());
177         return static_cast<int32_t>(E_FILE_ERROR);
178     }
179     FILE *pixMap = std::fopen(fileRealPath.c_str(), "rb");
180     if (pixMap == nullptr) {
181         HILOG_ERROR("fopen faild, %{public}s, %{public}s", fileRealPath.c_str(), strerror(errno));
182         return static_cast<int32_t>(E_FILE_ERROR);
183     }
184     int32_t fend = fseek(pixMap, 0, SEEK_END);
185     int32_t length = ftell(pixMap);
186     int32_t fset = fseek(pixMap, 0, SEEK_SET);
187     if (length <= 0 || fend != 0 || fset != 0) {
188         HILOG_ERROR("ftell file failed or fseek file failed, errno %{public}d", errno);
189         fclose(pixMap);
190         return static_cast<int32_t>(E_FILE_ERROR);
191     }
192     fclose(pixMap);
193     int fd = open(fileRealPath.c_str(), O_RDONLY, 0660);
194     if (fd < 0) {
195         HILOG_ERROR("open file failed, errno %{public}d", errno);
196         ReporterFault(FaultType::SET_WALLPAPER_FAULT, FaultCode::RF_FD_INPUT_FAILED);
197         return static_cast<int32_t>(E_FILE_ERROR);
198     }
199     StartAsyncTrace(HITRACE_TAG_MISC, "SetWallpaper", static_cast<int32_t>(TraceTaskId::SET_WALLPAPER));
200     int32_t wallpaperErrorCode = 0;
201     if (apiInfo.isSystemApi) {
202         wallpaperErrorCode = wpServerProxy->SetWallpaperByFDV9(fd, wallpaperType, length);
203     } else {
204         wallpaperErrorCode = wpServerProxy->SetWallpaperByFD(fd, wallpaperType, length);
205     }
206     close(fd);
207     if (wallpaperErrorCode == static_cast<int32_t>(E_OK)) {
208         CloseWallpaperFd(wallpaperType);
209     }
210     FinishAsyncTrace(HITRACE_TAG_MISC, "SetWallpaper", static_cast<int32_t>(TraceTaskId::SET_WALLPAPER));
211     return wallpaperErrorCode;
212 }
213 
SetWallpaper(std::shared_ptr<OHOS::Media::PixelMap> pixelMap,int32_t wallpaperType,const ApiInfo & apiInfo)214 int32_t WallpaperManager::SetWallpaper(std::shared_ptr<OHOS::Media::PixelMap> pixelMap, int32_t wallpaperType,
215     const ApiInfo &apiInfo)
216 {
217     auto wpServerProxy = GetService();
218     if (wpServerProxy == nullptr) {
219         HILOG_ERROR("Get proxy failed");
220         return static_cast<int32_t>(E_DEAL_FAILED);
221     }
222 
223     std::stringbuf stringBuf;
224     std::ostream ostream(&stringBuf);
225     int mapSize = WritePixelMapToStream(ostream, pixelMap);
226     if (mapSize <= 0) {
227         HILOG_ERROR("WritePixelMapToStream faild");
228         return static_cast<int32_t>(E_WRITE_PARCEL_ERROR);
229     }
230     char *buffer = new (std::nothrow) char[mapSize]();
231     if (buffer == nullptr) {
232         return static_cast<int32_t>(E_NO_MEMORY);
233     }
234     stringBuf.sgetn(buffer, mapSize);
235 
236     int fd[2];
237     pipe(fd);
238     fcntl(fd[1], F_SETPIPE_SZ, mapSize);
239     fcntl(fd[0], F_SETPIPE_SZ, mapSize);
240     int32_t writeSize = write(fd[1], buffer, mapSize);
241     if (writeSize != mapSize) {
242         HILOG_ERROR("Write file failed, errno %{public}d", errno);
243         ReporterFault(FaultType::SET_WALLPAPER_FAULT, FaultCode::RF_FD_INPUT_FAILED);
244         delete[] buffer;
245         return static_cast<int32_t>(E_WRITE_PARCEL_ERROR);
246     }
247     close(fd[1]);
248     int32_t wallpaperErrorCode = 0;
249     if (apiInfo.isSystemApi) {
250         wallpaperErrorCode = wpServerProxy->SetWallpaperByMapV9(fd[0], wallpaperType, mapSize);
251     } else {
252         wallpaperErrorCode = wpServerProxy->SetWallpaperByMap(fd[0], wallpaperType, mapSize);
253     }
254     close(fd[0]);
255     if (wallpaperErrorCode == static_cast<int32_t>(E_OK)) {
256         CloseWallpaperFd(wallpaperType);
257     }
258     delete[] buffer;
259     return wallpaperErrorCode;
260 }
261 
WritePixelMapToStream(std::ostream & outputStream,std::shared_ptr<OHOS::Media::PixelMap> pixelMap)262 int64_t WallpaperManager::WritePixelMapToStream(std::ostream &outputStream,
263     std::shared_ptr<OHOS::Media::PixelMap> pixelMap)
264 {
265     OHOS::Media::ImagePacker imagePacker;
266     OHOS::Media::PackOption option;
267     option.format = "image/jpeg";
268     option.quality = OPTION_QUALITY;
269     option.numberHint = 1;
270     std::set<std::string> formats;
271     uint32_t ret = imagePacker.GetSupportedFormats(formats);
272     if (ret != 0) {
273         HILOG_ERROR("image packer get supported format failed, ret=%{public}u.", ret);
274     }
275 
276     imagePacker.StartPacking(outputStream, option);
277     imagePacker.AddImage(*pixelMap);
278     int64_t packedSize = 0;
279     imagePacker.FinalizePacking(packedSize);
280     HILOG_INFO("FrameWork WritePixelMapToStream End! packedSize=%{public}lld.", static_cast<long long>(packedSize));
281     return packedSize;
282 }
283 
GetPixelMap(int32_t wallpaperType,const ApiInfo & apiInfo,std::shared_ptr<OHOS::Media::PixelMap> & pixelMap)284 int32_t WallpaperManager::GetPixelMap(int32_t wallpaperType, const ApiInfo &apiInfo,
285     std::shared_ptr<OHOS::Media::PixelMap> &pixelMap)
286 {
287     HILOG_INFO("FrameWork GetPixelMap Start by FD");
288     auto wpServerProxy = GetService();
289     if (wpServerProxy == nullptr) {
290         HILOG_ERROR("Get proxy failed");
291         return static_cast<int32_t>(E_SA_DIED);
292     }
293     IWallpaperService::FdInfo fdInfo;
294     int32_t wallpaperErrorCode = 0;
295     if (apiInfo.isSystemApi) {
296         wallpaperErrorCode = wpServerProxy->GetPixelMapV9(wallpaperType, fdInfo);
297     } else {
298         wallpaperErrorCode = wpServerProxy->GetPixelMap(wallpaperType, fdInfo);
299     }
300     if (wallpaperErrorCode != static_cast<int32_t>(E_OK)) {
301         return wallpaperErrorCode;
302     }
303     uint32_t errorCode = 0;
304     OHOS::Media::SourceOptions opts;
305     opts.formatHint = "image/jpeg";
306     HILOG_INFO(" CreateImageSource by FD");
307     std::unique_ptr<OHOS::Media::ImageSource> imageSource =
308         OHOS::Media::ImageSource::CreateImageSource(fdInfo.fd, opts, errorCode);
309     if (errorCode != 0) {
310         HILOG_ERROR("ImageSource::CreateImageSource failed,errcode= %{public}d", errorCode);
311         return static_cast<int32_t>(E_IMAGE_ERRCODE);
312     }
313     OHOS::Media::DecodeOptions decodeOpts;
314     HILOG_INFO(" CreatePixelMap");
315     pixelMap = imageSource->CreatePixelMap(decodeOpts, errorCode);
316 
317     if (errorCode != 0) {
318         HILOG_ERROR("ImageSource::CreatePixelMap failed,errcode= %{public}d", errorCode);
319         return static_cast<int32_t>(E_IMAGE_ERRCODE);
320     }
321     close(fdInfo.fd);
322     return wallpaperErrorCode;
323 }
324 
GetWallpaperId(int wallpaperType)325 int WallpaperManager::GetWallpaperId(int wallpaperType)
326 {
327     auto wpServerProxy = GetService();
328     if (wpServerProxy == nullptr) {
329         HILOG_ERROR("Get proxy failed");
330         return -1;
331     }
332     return wpServerProxy->GetWallpaperId(wallpaperType);
333 }
334 
GetWallpaperMinHeight(const ApiInfo & apiInfo,int32_t & minHeight)335 int32_t WallpaperManager::GetWallpaperMinHeight(const ApiInfo &apiInfo, int32_t &minHeight)
336 {
337     auto wpServerProxy = GetService();
338     if (wpServerProxy == nullptr) {
339         HILOG_ERROR("Get proxy failed");
340         return E_DEAL_FAILED;
341     }
342     if (apiInfo.isSystemApi) {
343         return wpServerProxy->GetWallpaperMinHeightV9(minHeight);
344     }
345     return wpServerProxy->GetWallpaperMinHeight(minHeight);
346 }
347 
GetWallpaperMinWidth(const ApiInfo & apiInfo,int32_t & minWidth)348 int32_t WallpaperManager::GetWallpaperMinWidth(const ApiInfo &apiInfo, int32_t &minWidth)
349 {
350     auto wpServerProxy = GetService();
351     if (wpServerProxy == nullptr) {
352         HILOG_ERROR("Get proxy failed");
353         return E_DEAL_FAILED;
354     }
355     if (apiInfo.isSystemApi) {
356         return wpServerProxy->GetWallpaperMinWidthV9(minWidth);
357     }
358     return wpServerProxy->GetWallpaperMinWidth(minWidth);
359 }
360 
IsChangePermitted()361 bool WallpaperManager::IsChangePermitted()
362 {
363     auto wpServerProxy = GetService();
364     if (wpServerProxy == nullptr) {
365         HILOG_ERROR("Get proxy failed");
366         return false;
367     }
368     return wpServerProxy->IsChangePermitted();
369 }
370 
IsOperationAllowed()371 bool WallpaperManager::IsOperationAllowed()
372 {
373     auto wpServerProxy = GetService();
374     if (wpServerProxy == nullptr) {
375         HILOG_ERROR("Get proxy failed");
376         return false;
377     }
378     return wpServerProxy->IsOperationAllowed();
379 }
380 
ResetWallpaper(std::int32_t wallpaperType,const ApiInfo & apiInfo)381 int32_t WallpaperManager::ResetWallpaper(std::int32_t wallpaperType, const ApiInfo &apiInfo)
382 {
383     auto wpServerProxy = GetService();
384     if (wpServerProxy == nullptr) {
385         HILOG_ERROR("Get proxy failed");
386         return static_cast<int32_t>(E_SA_DIED);
387     }
388     int32_t wallpaperErrorCode = 0;
389     if (apiInfo.isSystemApi) {
390         wallpaperErrorCode = wpServerProxy->ResetWallpaperV9(wallpaperType);
391     } else {
392         wallpaperErrorCode = wpServerProxy->ResetWallpaper(wallpaperType);
393     }
394     if (wallpaperErrorCode == static_cast<int32_t>(E_OK)) {
395         CloseWallpaperFd(wallpaperType);
396     }
397     return wallpaperErrorCode;
398 }
399 
On(const std::string & type,std::shared_ptr<WallpaperColorChangeListener> listener)400 bool WallpaperManager::On(const std::string &type, std::shared_ptr<WallpaperColorChangeListener> listener)
401 {
402     HILOG_DEBUG("WallpaperManager::On in");
403     auto wpServerProxy = GetService();
404     if (wpServerProxy == nullptr) {
405         HILOG_ERROR("Get proxy failed");
406         return false;
407     }
408     if (listener == nullptr) {
409         HILOG_ERROR("listener is nullptr.");
410         return false;
411     }
412     std::lock_guard<std::mutex> lck(listenerMapMutex_);
413 
414     sptr<WallpaperColorChangeListenerClient> ipcListener = new (std::nothrow)
415         WallpaperColorChangeListenerClient(listener);
416     if (ipcListener == nullptr) {
417         HILOG_ERROR("new WallpaperColorChangeListenerClient failed");
418         return false;
419     }
420     HILOG_DEBUG("WallpaperManager::On out");
421     return wpServerProxy->On(ipcListener);
422 }
423 
Off(const std::string & type,std::shared_ptr<WallpaperColorChangeListener> listener)424 bool WallpaperManager::Off(const std::string &type, std::shared_ptr<WallpaperColorChangeListener> listener)
425 {
426     HILOG_DEBUG("WallpaperManager::Off in");
427     auto wpServerProxy = GetService();
428     if (wpServerProxy == nullptr) {
429         HILOG_ERROR("Get proxy failed");
430         return false;
431     }
432     std::lock_guard<std::mutex> lck(listenerMapMutex_);
433     bool status = false;
434     if (listener != nullptr) {
435         sptr<WallpaperColorChangeListenerClient> ipcListener = new (std::nothrow)
436             WallpaperColorChangeListenerClient(listener);
437         if (ipcListener == nullptr) {
438             HILOG_ERROR("new WallpaperColorChangeListenerClient failed");
439             return false;
440         }
441         status = wpServerProxy->Off(ipcListener);
442     } else {
443         status = wpServerProxy->Off(nullptr);
444     }
445     if (status == false) {
446         HILOG_ERROR("off failed");
447         return false;
448     }
449     HILOG_DEBUG("WallpaperManager::Off out");
450     return true;
451 }
452 
GetCallback()453 JScallback WallpaperManager::GetCallback()
454 {
455     return callback;
456 }
457 
SetCallback(bool (* cb)(int))458 void WallpaperManager::SetCallback(bool (*cb)(int))
459 {
460     callback = cb;
461 }
462 
RegisterWallpaperCallback(bool (* callback)(int))463 bool WallpaperManager::RegisterWallpaperCallback(bool (*callback)(int))
464 {
465     HILOG_ERROR("  WallpaperManager::RegisterWallpaperCallback statrt");
466     SetCallback(callback);
467     auto wpServerProxy = GetService();
468     if (wpServerProxy == nullptr) {
469         HILOG_ERROR("Get proxy failed");
470         return false;
471     }
472 
473     if (callback == nullptr) {
474         HILOG_ERROR("callback is NULL.");
475         return false;
476     }
477     HILOG_INFO("  WallpaperManager::RegisterWallpaperCallback");
478 
479     bool status = wpServerProxy->RegisterWallpaperCallback(new WallpaperServiceCbStub());
480     if (status == false) {
481         HILOG_ERROR("off failed code=%d.", ERR_NONE);
482         return false;
483     }
484 
485     return 0;
486 }
487 
ReporterFault(FaultType faultType,FaultCode faultCode)488 void WallpaperManager::ReporterFault(FaultType faultType, FaultCode faultCode)
489 {
490     MiscServices::FaultMsg msg;
491     msg.faultType = faultType;
492     msg.errorCode = faultCode;
493     FaultReporter::ReportRuntimeFault(msg);
494 }
495 
CloseWallpaperFd(int32_t wallpaperType)496 void WallpaperManager::CloseWallpaperFd(int32_t wallpaperType)
497 {
498     std::lock_guard<std::mutex> lock(wpFdLock_);
499     std::map<int32_t, int32_t>::iterator iter = wallpaperFdMap_.find(wallpaperType);
500     if (iter != wallpaperFdMap_.end() && fcntl(iter->second, F_GETFL) != -1) {
501         close(iter->second);
502         wallpaperFdMap_.erase(iter);
503     }
504 }
505 
GetRealPath(const std::string & inOriPath,std::string & outRealPath)506 bool WallpaperManager::GetRealPath(const std::string &inOriPath, std::string &outRealPath)
507 {
508     char realPath[PATH_MAX + 1] = { 0x00 };
509     if (inOriPath.size() > PATH_MAX || realpath(inOriPath.c_str(), realPath) == nullptr) {
510         HILOG_ERROR("get real path fail");
511         return false;
512     }
513     outRealPath = std::string(realPath);
514     if (!OHOS::FileExists(outRealPath)) {
515         HILOG_ERROR("real path file is not exist! %{public}s", outRealPath.c_str());
516         return false;
517     }
518     return true;
519 }
520 } // namespace WallpaperMgrService
521 } // namespace OHOS