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