• 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(int wallpaperType)134 std::vector<uint64_t> WallpaperManager::GetColors(int wallpaperType)
135 {
136     auto wpServerProxy = GetService();
137     if (wpServerProxy == nullptr) {
138         HILOG_ERROR("Get proxy failed");
139         return {};
140     }
141     return wpServerProxy->GetColors(wallpaperType);
142 }
143 
GetFile(int32_t wallpaperType,int32_t & wallpaperFd)144 int32_t WallpaperManager::GetFile(int32_t wallpaperType, int32_t &wallpaperFd)
145 {
146     auto wpServerProxy = GetService();
147     if (wpServerProxy == nullptr) {
148         HILOG_ERROR("Get proxy failed");
149         return -1;
150     }
151     std::lock_guard<std::mutex> lock(wpFdLock_);
152     std::map<int32_t, int32_t>::iterator iter = wallpaperFdMap_.find(wallpaperType);
153     if (iter != wallpaperFdMap_.end() && fcntl(iter->second, F_GETFL) != -1) {
154         close(iter->second);
155         wallpaperFdMap_.erase(iter);
156     }
157     int32_t wallpaperErrorCode = wpServerProxy->GetFile(wallpaperType, wallpaperFd);
158     if (wallpaperErrorCode == static_cast<int32_t>(E_OK) && wallpaperFd != -1) {
159         wallpaperFdMap_.insert(std::pair<int32_t, int32_t>(wallpaperType, wallpaperFd));
160     }
161     return wallpaperErrorCode;
162 }
163 
SetWallpaper(std::string url,int wallpaperType)164 int32_t WallpaperManager::SetWallpaper(std::string url, int wallpaperType)
165 {
166     auto wpServerProxy = GetService();
167     if (wpServerProxy == nullptr) {
168         HILOG_ERROR("Get proxy failed");
169         return static_cast<int32_t>(E_DEAL_FAILED);
170     }
171     std::string fileRealPath;
172     if (!GetRealPath(url, fileRealPath)) {
173         HILOG_ERROR("get real path file failed, len = %{public}zu", url.size());
174         return static_cast<int32_t>(E_FILE_ERROR);
175     }
176     FILE *pixMap = std::fopen(fileRealPath.c_str(), "rb");
177     if (pixMap == nullptr) {
178         HILOG_ERROR("fopen faild, %{public}s, %{public}s", fileRealPath.c_str(), strerror(errno));
179         return static_cast<int32_t>(E_FILE_ERROR);
180     }
181     int fend = fseek(pixMap, 0, SEEK_END);
182     if (fend != 0) {
183         HILOG_ERROR("fseek file failed, errno %{public}d", errno);
184         fclose(pixMap);
185         return static_cast<int32_t>(E_FILE_ERROR);
186     }
187     int length = ftell(pixMap);
188     if (length <= 0) {
189         HILOG_ERROR("ftell file failed, errno %{public}d", errno);
190         fclose(pixMap);
191         return static_cast<int32_t>(E_FILE_ERROR);
192     }
193     int fset = fseek(pixMap, 0, SEEK_SET);
194     if (fset != 0) {
195         HILOG_ERROR("fseek file failed, errno %{public}d", errno);
196         fclose(pixMap);
197         return static_cast<int32_t>(E_FILE_ERROR);
198     }
199     fclose(pixMap);
200     int fd = open(fileRealPath.c_str(), O_RDONLY, 0660);
201     if (fd < 0) {
202         HILOG_ERROR("open file failed, errno %{public}d", errno);
203         ReporterFault(FaultType::SET_WALLPAPER_FAULT, FaultCode::RF_FD_INPUT_FAILED);
204         return static_cast<int32_t>(E_FILE_ERROR);
205     }
206     StartAsyncTrace(HITRACE_TAG_MISC, "SetWallpaper", static_cast<int32_t>(TraceTaskId::SET_WALLPAPER));
207     int32_t wallpaperErrorCode = wpServerProxy->SetWallpaperByFD(fd, wallpaperType, length);
208     close(fd);
209     if (wallpaperErrorCode == static_cast<int32_t>(E_OK)) {
210         CloseWallpaperFd(wallpaperType);
211     }
212     FinishAsyncTrace(HITRACE_TAG_MISC, "SetWallpaper", static_cast<int32_t>(TraceTaskId::SET_WALLPAPER));
213     return wallpaperErrorCode;
214 }
215 
SetWallpaper(std::shared_ptr<OHOS::Media::PixelMap> pixelMap,int wallpaperType)216 int32_t WallpaperManager::SetWallpaper(std::shared_ptr<OHOS::Media::PixelMap> pixelMap, int wallpaperType)
217 {
218     auto wpServerProxy = GetService();
219     if (wpServerProxy == nullptr) {
220         HILOG_ERROR("Get proxy failed");
221         return static_cast<int32_t>(E_DEAL_FAILED);
222     }
223 
224     std::stringbuf stringBuf;
225     std::ostream ostream(&stringBuf);
226     int mapSize = WritePixelMapToStream(ostream, pixelMap);
227     if (mapSize <= 0) {
228         HILOG_ERROR("WritePixelMapToStream faild");
229         return static_cast<int32_t>(E_WRITE_PARCEL_ERROR);
230     }
231     char *buffer = new (std::nothrow) char[mapSize]();
232     if (buffer == nullptr) {
233         return static_cast<int32_t>(E_NO_MEMORY);
234     }
235     stringBuf.sgetn(buffer, mapSize);
236 
237     int fd[2];
238     pipe(fd);
239     fcntl(fd[1], F_SETPIPE_SZ, mapSize);
240     fcntl(fd[0], F_SETPIPE_SZ, mapSize);
241     int32_t writeSize = write(fd[1], buffer, mapSize);
242     if (writeSize != mapSize) {
243         HILOG_ERROR("Write file failed, errno %{public}d", errno);
244         ReporterFault(FaultType::SET_WALLPAPER_FAULT, FaultCode::RF_FD_INPUT_FAILED);
245         delete[] buffer;
246         return static_cast<int32_t>(E_WRITE_PARCEL_ERROR);
247     }
248     close(fd[1]);
249     int32_t wallpaperErrorCode = wpServerProxy->SetWallpaperByMap(fd[0], wallpaperType, mapSize);
250     close(fd[0]);
251     if (wallpaperErrorCode == static_cast<int32_t>(E_OK)) {
252         CloseWallpaperFd(wallpaperType);
253     }
254     delete[] buffer;
255     return wallpaperErrorCode;
256 }
257 
WritePixelMapToStream(std::ostream & outputStream,std::shared_ptr<OHOS::Media::PixelMap> pixelMap)258 int64_t WallpaperManager::WritePixelMapToStream(std::ostream &outputStream,
259     std::shared_ptr<OHOS::Media::PixelMap> pixelMap)
260 {
261     OHOS::Media::ImagePacker imagePacker;
262     OHOS::Media::PackOption option;
263     option.format = "image/jpeg";
264     option.quality = OPTION_QUALITY;
265     option.numberHint = 1;
266     std::set<std::string> formats;
267     uint32_t ret = imagePacker.GetSupportedFormats(formats);
268     if (ret != 0) {
269         HILOG_ERROR("image packer get supported format failed, ret=%{public}u.", ret);
270     }
271 
272     imagePacker.StartPacking(outputStream, option);
273     imagePacker.AddImage(*pixelMap);
274     int64_t packedSize = 0;
275     imagePacker.FinalizePacking(packedSize);
276     HILOG_INFO("FrameWork WritePixelMapToStream End! packedSize=%{public}lld.", static_cast<long long>(packedSize));
277     return packedSize;
278 }
279 
GetPixelMap(int wallpaperType,std::shared_ptr<OHOS::Media::PixelMap> & pixelMap)280 int32_t WallpaperManager::GetPixelMap(int wallpaperType, std::shared_ptr<OHOS::Media::PixelMap> &pixelMap)
281 {
282     HILOG_INFO("FrameWork GetPixelMap Start by FD");
283     auto wpServerProxy = GetService();
284     if (wpServerProxy == nullptr) {
285         HILOG_ERROR("Get proxy failed");
286         return static_cast<int32_t>(E_SA_DIED);
287     }
288     IWallpaperService::FdInfo fdInfo;
289     int32_t wallpaperErrorCode = wpServerProxy->GetPixelMap(wallpaperType, fdInfo);
290     if (wallpaperErrorCode != static_cast<int32_t>(E_OK)) {
291         return wallpaperErrorCode;
292     }
293     uint32_t errorCode = 0;
294     OHOS::Media::SourceOptions opts;
295     opts.formatHint = "image/jpeg";
296     HILOG_INFO(" CreateImageSource by FD");
297     std::unique_ptr<OHOS::Media::ImageSource> imageSource =
298         OHOS::Media::ImageSource::CreateImageSource(fdInfo.fd, opts, errorCode);
299     if (errorCode != 0) {
300         HILOG_ERROR("ImageSource::CreateImageSource failed,errcode= %{public}d", errorCode);
301         return static_cast<int32_t>(E_IMAGE_ERRCODE);
302     }
303     OHOS::Media::DecodeOptions decodeOpts;
304     HILOG_INFO(" CreatePixelMap");
305     pixelMap = imageSource->CreatePixelMap(decodeOpts, errorCode);
306 
307     if (errorCode != 0) {
308         HILOG_ERROR("ImageSource::CreatePixelMap failed,errcode= %{public}d", errorCode);
309         return static_cast<int32_t>(E_IMAGE_ERRCODE);
310     }
311     close(fdInfo.fd);
312     return wallpaperErrorCode;
313 }
314 
GetWallpaperId(int wallpaperType)315 int WallpaperManager::GetWallpaperId(int wallpaperType)
316 {
317     auto wpServerProxy = GetService();
318     if (wpServerProxy == nullptr) {
319         HILOG_ERROR("Get proxy failed");
320         return -1;
321     }
322     return wpServerProxy->GetWallpaperId(wallpaperType);
323 }
324 
GetWallpaperMinHeight()325 int WallpaperManager::GetWallpaperMinHeight()
326 {
327     auto wpServerProxy = GetService();
328     if (wpServerProxy == nullptr) {
329         HILOG_ERROR("Get proxy failed");
330         return -1;
331     }
332     return wpServerProxy->GetWallpaperMinHeight();
333 }
334 
GetWallpaperMinWidth()335 int WallpaperManager::GetWallpaperMinWidth()
336 {
337     auto wpServerProxy = GetService();
338     if (wpServerProxy == nullptr) {
339         HILOG_ERROR("Get proxy failed");
340         return -1;
341     }
342     return wpServerProxy->GetWallpaperMinWidth();
343 }
344 
IsChangePermitted()345 bool WallpaperManager::IsChangePermitted()
346 {
347     auto wpServerProxy = GetService();
348     if (wpServerProxy == nullptr) {
349         HILOG_ERROR("Get proxy failed");
350         return false;
351     }
352     return wpServerProxy->IsChangePermitted();
353 }
354 
IsOperationAllowed()355 bool WallpaperManager::IsOperationAllowed()
356 {
357     auto wpServerProxy = GetService();
358     if (wpServerProxy == nullptr) {
359         HILOG_ERROR("Get proxy failed");
360         return false;
361     }
362     return wpServerProxy->IsOperationAllowed();
363 }
ResetWallpaper(std::int32_t wallpaperType)364 int32_t WallpaperManager::ResetWallpaper(std::int32_t wallpaperType)
365 {
366     auto wpServerProxy = GetService();
367     if (wpServerProxy == nullptr) {
368         HILOG_ERROR("Get proxy failed");
369         return static_cast<int32_t>(E_SA_DIED);
370     }
371     int32_t wallpaperErrorCode = wpServerProxy->ResetWallpaper(wallpaperType);
372     if (wallpaperErrorCode == static_cast<int32_t>(E_OK)) {
373         CloseWallpaperFd(wallpaperType);
374     }
375     return wallpaperErrorCode;
376 }
377 
On(const std::string & type,std::shared_ptr<WallpaperColorChangeListener> listener)378 bool WallpaperManager::On(const std::string &type, std::shared_ptr<WallpaperColorChangeListener> listener)
379 {
380     HILOG_DEBUG("WallpaperManager::On in");
381     auto wpServerProxy = GetService();
382     if (wpServerProxy == nullptr) {
383         HILOG_ERROR("Get proxy failed");
384         return false;
385     }
386     if (listener == nullptr) {
387         HILOG_ERROR("listener is nullptr.");
388         return false;
389     }
390     std::lock_guard<std::mutex> lck(listenerMapMutex_);
391 
392     sptr<WallpaperColorChangeListenerClient> ipcListener = new (std::nothrow)
393         WallpaperColorChangeListenerClient(listener);
394     if (ipcListener == nullptr) {
395         HILOG_ERROR("new WallpaperColorChangeListenerClient failed");
396         return false;
397     }
398     HILOG_DEBUG("WallpaperManager::On out");
399     return wpServerProxy->On(ipcListener);
400 }
401 
Off(const std::string & type,std::shared_ptr<WallpaperColorChangeListener> listener)402 bool WallpaperManager::Off(const std::string &type, std::shared_ptr<WallpaperColorChangeListener> listener)
403 {
404     HILOG_DEBUG("WallpaperManager::Off in");
405     auto wpServerProxy = GetService();
406     if (wpServerProxy == nullptr) {
407         HILOG_ERROR("Get proxy failed");
408         return false;
409     }
410     std::lock_guard<std::mutex> lck(listenerMapMutex_);
411     bool status = false;
412     if (listener != nullptr) {
413         sptr<WallpaperColorChangeListenerClient> ipcListener = new (std::nothrow)
414             WallpaperColorChangeListenerClient(listener);
415         if (ipcListener == nullptr) {
416             HILOG_ERROR("new WallpaperColorChangeListenerClient failed");
417             return false;
418         }
419         status = wpServerProxy->Off(ipcListener);
420     } else {
421         status = wpServerProxy->Off(nullptr);
422     }
423     if (status == false) {
424         HILOG_ERROR("off failed");
425         return false;
426     }
427     HILOG_DEBUG("WallpaperManager::Off out");
428     return true;
429 }
430 
GetCallback()431 JScallback WallpaperManager::GetCallback()
432 {
433     return callback;
434 }
435 
SetCallback(bool (* cb)(int))436 void WallpaperManager::SetCallback(bool (*cb)(int))
437 {
438     callback = cb;
439 }
440 
RegisterWallpaperCallback(bool (* callback)(int))441 bool WallpaperManager::RegisterWallpaperCallback(bool (*callback)(int))
442 {
443     HILOG_ERROR("  WallpaperManager::RegisterWallpaperCallback statrt");
444     SetCallback(callback);
445     auto wpServerProxy = GetService();
446     if (wpServerProxy == nullptr) {
447         HILOG_ERROR("Get proxy failed");
448         return false;
449     }
450 
451     if (callback == nullptr) {
452         HILOG_ERROR("callback is NULL.");
453         return false;
454     }
455     HILOG_INFO("  WallpaperManager::RegisterWallpaperCallback");
456 
457     bool status = wpServerProxy->RegisterWallpaperCallback(new WallpaperServiceCbStub());
458     if (status == false) {
459         HILOG_ERROR("off failed code=%d.", ERR_NONE);
460         return false;
461     }
462 
463     return 0;
464 }
465 
ReporterFault(FaultType faultType,FaultCode faultCode)466 void WallpaperManager::ReporterFault(FaultType faultType, FaultCode faultCode)
467 {
468     MiscServices::FaultMsg msg;
469     msg.faultType = faultType;
470     msg.errorCode = faultCode;
471     FaultReporter::ReportRuntimeFault(msg);
472 }
473 
CloseWallpaperFd(int32_t wallpaperType)474 void WallpaperManager::CloseWallpaperFd(int32_t wallpaperType)
475 {
476     std::lock_guard<std::mutex> lock(wpFdLock_);
477     std::map<int32_t, int32_t>::iterator iter = wallpaperFdMap_.find(wallpaperType);
478     if (iter != wallpaperFdMap_.end() && fcntl(iter->second, F_GETFL) != -1) {
479         close(iter->second);
480         wallpaperFdMap_.erase(iter);
481     }
482 }
483 
GetRealPath(const std::string & inOriPath,std::string & outRealPath)484 bool WallpaperManager::GetRealPath(const std::string &inOriPath, std::string &outRealPath)
485 {
486     char realPath[PATH_MAX + 1] = { 0x00 };
487     if (inOriPath.size() > PATH_MAX || realpath(inOriPath.c_str(), realPath) == nullptr) {
488         HILOG_ERROR("get real path fail");
489         return false;
490     }
491     outRealPath = std::string(realPath);
492     if (!OHOS::FileExists(outRealPath)) {
493         HILOG_ERROR("real path file is not exist! %{public}s", outRealPath.c_str());
494         return false;
495     }
496     return true;
497 }
498 } // namespace WallpaperMgrService
499 } // namespace OHOS