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