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
16#include <unistd.h>
17
18#include "ashmem.h"
19#include "hilog_wrapper.h"
20#include "ipc_skeleton.h"
21#include "memory_guard.h"
22#include "parcel.h"
23#include "pixel_map.h"
24#include "wallpaper_common.h"
25#include "wallpaper_service_ipc_interface_code.h"
26#include "wallpaper_service_stub.h"
27
28namespace OHOS {
29namespace WallpaperMgrService {
30using namespace OHOS::HiviewDFX;
31using namespace OHOS::Media;
32
33WallpaperServiceStub::WallpaperServiceStub(bool serialInvokeFlag) : IRemoteStub(serialInvokeFlag)
34{
35    requestHandlers = {
36        { static_cast<uint32_t>(WallpaperServiceIpcInterfaceCode::SET_WALLPAPER),
37            [this](MessageParcel &data, MessageParcel &reply) { return OnSetWallpaper(data, reply); } },
38        { static_cast<uint32_t>(WallpaperServiceIpcInterfaceCode::GET_PIXELMAP),
39            [this](MessageParcel &data, MessageParcel &reply) { return OnGetPixelMap(data, reply); } },
40        { static_cast<uint32_t>(WallpaperServiceIpcInterfaceCode::GET_COLORS),
41            [this](MessageParcel &data, MessageParcel &reply) { return OnGetColors(data, reply); } },
42        { static_cast<uint32_t>(WallpaperServiceIpcInterfaceCode::GET_WALLPAPER_ID),
43            [this](MessageParcel &data, MessageParcel &reply) { return OnGetWallpaperId(data, reply); } },
44        { static_cast<uint32_t>(WallpaperServiceIpcInterfaceCode::GET_FILE),
45            [this](MessageParcel &data, MessageParcel &reply) { return OnGetFile(data, reply); } },
46        { static_cast<uint32_t>(WallpaperServiceIpcInterfaceCode::ON),
47            [this](MessageParcel &data, MessageParcel &reply) { return OnWallpaperOn(data, reply); } },
48        { static_cast<uint32_t>(WallpaperServiceIpcInterfaceCode::OFF),
49            [this](MessageParcel &data, MessageParcel &reply) { return OnWallpaperOff(data, reply); } },
50        { static_cast<uint32_t>(WallpaperServiceIpcInterfaceCode::IS_CHANGE_PERMITTED),
51            [this](MessageParcel &data, MessageParcel &reply) { return OnIsChangePermitted(data, reply); } },
52        { static_cast<uint32_t>(WallpaperServiceIpcInterfaceCode::IS_OPERATION_ALLOWED),
53            [this](MessageParcel &data, MessageParcel &reply) { return OnIsOperationAllowed(data, reply); } },
54        { static_cast<uint32_t>(WallpaperServiceIpcInterfaceCode::RESET_WALLPAPER),
55            [this](MessageParcel &data, MessageParcel &reply) { return OnResetWallpaper(data, reply); } },
56        { static_cast<uint32_t>(WallpaperServiceIpcInterfaceCode::REGISTER_CALLBACK),
57            [this](MessageParcel &data, MessageParcel &reply) { return OnRegisterWallpaperCallback(data, reply); } },
58        { static_cast<uint32_t>(WallpaperServiceIpcInterfaceCode::SET_WALLPAPER_V9),
59            [this](MessageParcel &data, MessageParcel &reply) { return OnSetWallpaperV9(data, reply); } },
60        { static_cast<uint32_t>(WallpaperServiceIpcInterfaceCode::GET_PIXELMAP_V9),
61            [this](MessageParcel &data, MessageParcel &reply) { return OnGetPixelMapV9(data, reply); } },
62        { static_cast<uint32_t>(WallpaperServiceIpcInterfaceCode::GET_COLORS_V9),
63            [this](MessageParcel &data, MessageParcel &reply) { return OnGetColorsV9(data, reply); } },
64        { static_cast<uint32_t>(WallpaperServiceIpcInterfaceCode::RESET_WALLPAPER_V9),
65            [this](MessageParcel &data, MessageParcel &reply) { return OnResetWallpaperV9(data, reply); } },
66        { static_cast<uint32_t>(WallpaperServiceIpcInterfaceCode::SET_VIDEO),
67            [this](MessageParcel &data, MessageParcel &reply) { return OnSetVideo(data, reply); } },
68        { static_cast<uint32_t>(WallpaperServiceIpcInterfaceCode::SET_CUSTOM),
69            [this](MessageParcel &data, MessageParcel &reply) { return OnSetCustomWallpaper(data, reply); } },
70        { static_cast<uint32_t>(WallpaperServiceIpcInterfaceCode::SEND_EVENT),
71            [this](MessageParcel &data, MessageParcel &reply) { return OnSendEvent(data, reply); } },
72        { static_cast<uint32_t>(WallpaperServiceIpcInterfaceCode::SET_WALLPAPER_PIXELMAP),
73            [this](MessageParcel &data, MessageParcel &reply) { return OnSetWallpaperByPixelMap(data, reply); } },
74        { static_cast<uint32_t>(WallpaperServiceIpcInterfaceCode::SET_WALLPAPER_PIXELMAP_V9),
75            [this](MessageParcel &data, MessageParcel &reply) { return OnSetWallpaperV9ByPixelMap(data, reply); } },
76    };
77}
78
79WallpaperServiceStub::~WallpaperServiceStub()
80{
81}
82
83int32_t WallpaperServiceStub::OnRemoteRequest(
84    uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
85{
86    MemoryGuard cacheGuard;
87    std::u16string myDescriptor = WallpaperServiceStub::GetDescriptor();
88    std::u16string remoteDescriptor = data.ReadInterfaceToken();
89    if (myDescriptor != remoteDescriptor) {
90        HILOG_ERROR("Remote descriptor not the same as local descriptor.");
91        return E_CHECK_DESCRIPTOR_ERROR;
92    }
93    return HandleWallpaperRequest(code, data, reply, option);
94}
95
96WallpaperRequestHandler WallpaperServiceStub::GetWallpaperRequestHandler(uint32_t code)
97{
98    auto it = requestHandlers.find(code);
99    if (it != requestHandlers.end()) {
100        return it->second;
101    }
102    return nullptr;
103}
104
105int32_t WallpaperServiceStub::HandleWallpaperRequest(
106    uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
107{
108    WallpaperRequestHandler handler = GetWallpaperRequestHandler(code);
109    if (handler) {
110        return handler(data, reply);
111    }
112    HILOG_ERROR("remote request unhandled: %{public}d", code);
113    return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
114}
115
116int32_t WallpaperServiceStub::OnSetWallpaper(MessageParcel &data, MessageParcel &reply)
117{
118    return OnSetWallpaperInner(data, reply, false);
119}
120
121int32_t WallpaperServiceStub::OnSetWallpaperV9(MessageParcel &data, MessageParcel &reply)
122{
123    return OnSetWallpaperInner(data, reply, true);
124}
125
126int32_t WallpaperServiceStub::OnSetWallpaperInner(MessageParcel &data, MessageParcel &reply, bool isSystemApi)
127{
128    HILOG_DEBUG("WallpaperServiceStub::SetWallpaper start.");
129    int32_t fd = data.ReadFileDescriptor();
130    if (fd < 0) {
131        HILOG_ERROR("ReadFileDescriptor fail. fd[%{public}d]", fd);
132        return IPC_STUB_INVALID_DATA_ERR;
133    }
134    int32_t wallpaperType = data.ReadInt32();
135    int32_t length = data.ReadInt32();
136    ErrorCode wallpaperErrorCode = E_UNKNOWN;
137    if (isSystemApi) {
138        wallpaperErrorCode = SetWallpaperV9(fd, wallpaperType, length);
139    } else {
140        wallpaperErrorCode = SetWallpaper(fd, wallpaperType, length);
141    }
142    close(fd);
143    if (!reply.WriteInt32(static_cast<int32_t>(wallpaperErrorCode))) {
144        HILOG_ERROR("WriteInt32 fail!");
145        return IPC_STUB_WRITE_PARCEL_ERR;
146    }
147    return ERR_NONE;
148}
149
150int32_t WallpaperServiceStub::OnSetWallpaperByPixelMap(MessageParcel &data, MessageParcel &reply)
151{
152    return OnSetWallpaperInnerByPixelMap(data, reply, false);
153}
154
155int32_t WallpaperServiceStub::OnSetWallpaperV9ByPixelMap(MessageParcel &data, MessageParcel &reply)
156{
157    return OnSetWallpaperInnerByPixelMap(data, reply, true);
158}
159
160int32_t WallpaperServiceStub::OnSetWallpaperInnerByPixelMap(MessageParcel &data, MessageParcel &reply, bool isSystemApi)
161{
162    HILOG_DEBUG("WallpaperServiceStub::SetWallpaper start.");
163    int32_t vectorPixelMapSize = data.ReadInt32();
164    if (vectorPixelMapSize <= 0) {
165        HILOG_ERROR("ReadInt32 fail!");
166        return IPC_STUB_INVALID_DATA_ERR;
167    }
168    auto *rawData = (uint8_t *)data.ReadRawData(vectorPixelMapSize);
169    if (rawData == nullptr) {
170        HILOG_ERROR("ReadRawData fail!");
171        return IPC_STUB_INVALID_DATA_ERR;
172    }
173    std::vector<uint8_t> VectorPixelMap(rawData, rawData + vectorPixelMapSize);
174    int32_t wallpaperType = data.ReadInt32();
175    std::shared_ptr<OHOS::Media::PixelMap> pixelMap = VectorToPixelMap(VectorPixelMap);
176    if (pixelMap == nullptr) {
177        HILOG_ERROR("VectorToPixelMap fail!");
178        return IPC_STUB_INVALID_DATA_ERR;
179    }
180    ErrorCode wallpaperErrorCode = E_UNKNOWN;
181    if (isSystemApi) {
182        wallpaperErrorCode = SetWallpaperV9ByPixelMap(pixelMap, wallpaperType);
183    } else {
184        wallpaperErrorCode = SetWallpaperByPixelMap(pixelMap, wallpaperType);
185    }
186    if (!reply.WriteInt32(static_cast<int32_t>(wallpaperErrorCode))) {
187        HILOG_ERROR("WriteInt32 fail!");
188        return IPC_STUB_WRITE_PARCEL_ERR;
189    }
190    return ERR_NONE;
191}
192
193int32_t WallpaperServiceStub::OnGetPixelMap(MessageParcel &data, MessageParcel &reply)
194{
195    return OnGetPixelMapInner(data, reply, false);
196}
197
198int32_t WallpaperServiceStub::OnSetVideo(MessageParcel &data, MessageParcel &reply)
199{
200    HILOG_DEBUG("WallpaperServiceStub::OnSetVideo start.");
201    int32_t fd = data.ReadFileDescriptor();
202    int32_t wallpaperType = data.ReadInt32();
203    int32_t length = data.ReadInt32();
204    ErrorCode wallpaperErrorCode = SetVideo(fd, wallpaperType, length);
205    close(fd);
206    if (!reply.WriteInt32(static_cast<int32_t>(wallpaperErrorCode))) {
207        HILOG_ERROR("Write int is failed!");
208        return IPC_STUB_WRITE_PARCEL_ERR;
209    }
210    return ERR_NONE;
211}
212
213int32_t WallpaperServiceStub::OnSetCustomWallpaper(MessageParcel &data, MessageParcel &reply)
214{
215    HILOG_DEBUG("WallpaperServiceStub::SetCustomWallpaper start.");
216    auto fd = data.ReadFileDescriptor();
217    int32_t wallpaperType = data.ReadInt32();
218    int32_t length = data.ReadInt32();
219    ErrorCode wallpaperErrorCode = SetCustomWallpaper(fd, wallpaperType, length);
220    close(fd);
221    if (!reply.WriteInt32(static_cast<int32_t>(wallpaperErrorCode))) {
222        HILOG_ERROR("Write int is failed!");
223        return IPC_STUB_WRITE_PARCEL_ERR;
224    }
225    return ERR_NONE;
226}
227
228int32_t WallpaperServiceStub::OnGetPixelMapV9(MessageParcel &data, MessageParcel &reply)
229{
230    return OnGetPixelMapInner(data, reply, true);
231}
232
233int32_t WallpaperServiceStub::OnGetPixelMapInner(MessageParcel &data, MessageParcel &reply, bool isSystemApi)
234{
235    HILOG_DEBUG("WallpaperServiceStub::GetPixelMap start.");
236    int32_t wallpaperType = data.ReadInt32();
237    IWallpaperService::FdInfo fdInfo;
238    ErrorCode wallpaperErrorCode = E_UNKNOWN;
239    if (isSystemApi) {
240        wallpaperErrorCode = GetPixelMapV9(wallpaperType, fdInfo);
241    } else {
242        wallpaperErrorCode = GetPixelMap(wallpaperType, fdInfo);
243    }
244    HILOG_INFO(" OnGetPixelMap wallpaperErrorCode = %{public}d", wallpaperErrorCode);
245    if (!reply.WriteInt32(static_cast<int32_t>(wallpaperErrorCode))) {
246        HILOG_ERROR("WriteInt32 fail!");
247        close(fdInfo.fd);
248        return IPC_STUB_WRITE_PARCEL_ERR;
249    }
250    if (wallpaperErrorCode == E_OK) {
251        if (!reply.WriteInt32(fdInfo.size)) {
252            HILOG_ERROR("WriteInt32 fail!");
253            close(fdInfo.fd);
254            return IPC_STUB_WRITE_PARCEL_ERR;
255        }
256        if (!reply.WriteFileDescriptor(fdInfo.fd)) {
257            HILOG_ERROR("WriteFileDescriptor fail!");
258            close(fdInfo.fd);
259            return IPC_STUB_WRITE_PARCEL_ERR;
260        }
261    }
262    close(fdInfo.fd);
263    return ERR_NONE;
264}
265
266int32_t WallpaperServiceStub::OnGetColors(MessageParcel &data, MessageParcel &reply)
267{
268    return OnGetColorsInner(data, reply, false);
269}
270
271int32_t WallpaperServiceStub::OnGetColorsV9(MessageParcel &data, MessageParcel &reply)
272{
273    return OnGetColorsInner(data, reply, true);
274}
275
276int32_t WallpaperServiceStub::OnGetColorsInner(MessageParcel &data, MessageParcel &reply, bool isSystemApi)
277{
278    HILOG_DEBUG("WallpaperServiceStub::OnGetColors start.");
279    int32_t wallpaperType = data.ReadInt32();
280    std::vector<uint64_t> vecWallpaperColors;
281    ErrorCode wallpaperErrorCode = E_UNKNOWN;
282    if (isSystemApi) {
283        wallpaperErrorCode = GetColorsV9(wallpaperType, vecWallpaperColors);
284    } else {
285        wallpaperErrorCode = GetColors(wallpaperType, vecWallpaperColors);
286    }
287    auto size = vecWallpaperColors.size();
288    if (!reply.WriteInt32(static_cast<int32_t>(wallpaperErrorCode))) {
289        HILOG_ERROR("WriteInt32 fail!");
290        return IPC_STUB_WRITE_PARCEL_ERR;
291    }
292    if (wallpaperErrorCode == E_OK) {
293        if (!reply.WriteUInt64Vector(vecWallpaperColors)) {
294            HILOG_ERROR("WallpaperServiceStub::OnGetColors WriteUInt64Vector error!");
295            return IPC_STUB_WRITE_PARCEL_ERR;
296        }
297    }
298    return (size == 0) ? IPC_STUB_INVALID_DATA_ERR : ERR_NONE;
299}
300
301int32_t WallpaperServiceStub::OnGetFile(MessageParcel &data, MessageParcel &reply)
302{
303    HILOG_DEBUG("WallpaperServiceStub::OnGetFile start.");
304    int32_t wallpaperType = data.ReadInt32();
305    int32_t wallpaperFd = INVALID_FD;
306    ErrorCode wallpaperErrorCode = GetFile(wallpaperType, wallpaperFd);
307    if (!reply.WriteInt32(static_cast<int32_t>(wallpaperErrorCode))) {
308        HILOG_ERROR("WriteInt32 fail!");
309        if (wallpaperFd > INVALID_FD) {
310            close(wallpaperFd);
311        }
312        return IPC_STUB_WRITE_PARCEL_ERR;
313    }
314    if (wallpaperErrorCode == E_OK && !reply.WriteFileDescriptor(wallpaperFd)) {
315        HILOG_ERROR("WriteFileDescriptor fail!");
316        close(wallpaperFd);
317        return IPC_STUB_WRITE_PARCEL_ERR;
318    }
319    if (wallpaperFd > INVALID_FD) {
320        close(wallpaperFd);
321    }
322    return ERR_NONE;
323}
324
325int32_t WallpaperServiceStub::OnGetWallpaperId(MessageParcel &data, MessageParcel &reply)
326{
327    HILOG_DEBUG("WallpaperServiceStub::OnGetWallpaperId start.");
328    int32_t wallpaperType = data.ReadInt32();
329    int32_t wallpaperId = GetWallpaperId(wallpaperType);
330    if (!reply.WriteInt32(wallpaperId)) {
331        HILOG_ERROR("Write result data failed!");
332        return IPC_STUB_WRITE_PARCEL_ERR;
333    }
334    HILOG_INFO("End. Id[%{public}d]", wallpaperId);
335    return ERR_NONE;
336}
337
338int32_t WallpaperServiceStub::OnIsChangePermitted(MessageParcel &data, MessageParcel &reply)
339{
340    HILOG_DEBUG("WallpaperServiceStub::OnIsChangePermitted start.");
341    auto bResult = IsChangePermitted();
342    if (!reply.WriteBool(bResult)) {
343        HILOG_ERROR("Write result data failed!");
344        return IPC_STUB_WRITE_PARCEL_ERR;
345    }
346    return ERR_NONE;
347}
348
349int32_t WallpaperServiceStub::OnIsOperationAllowed(MessageParcel &data, MessageParcel &reply)
350{
351    HILOG_DEBUG("WallpaperServiceStub::OnIsOperationAllowed start.");
352    auto bResult = IsOperationAllowed();
353    if (!reply.WriteBool(bResult)) {
354        HILOG_ERROR("Write result data failed!");
355        return IPC_STUB_WRITE_PARCEL_ERR;
356    }
357    return ERR_NONE;
358}
359
360int32_t WallpaperServiceStub::OnResetWallpaper(MessageParcel &data, MessageParcel &reply)
361{
362    return OnResetWallpaperInner(data, reply, false);
363}
364
365int32_t WallpaperServiceStub::OnResetWallpaperV9(MessageParcel &data, MessageParcel &reply)
366{
367    return OnResetWallpaperInner(data, reply, true);
368}
369
370int32_t WallpaperServiceStub::OnResetWallpaperInner(MessageParcel &data, MessageParcel &reply, bool isSystemApi)
371{
372    HILOG_DEBUG("WallpaperServiceStub::OnResetWallpaper start.");
373    int32_t wallpaperType = data.ReadInt32();
374    ErrorCode wallpaperErrorCode = E_UNKNOWN;
375    if (isSystemApi) {
376        wallpaperErrorCode = ResetWallpaperV9(wallpaperType);
377    } else {
378        wallpaperErrorCode = ResetWallpaper(wallpaperType);
379    }
380    if (!reply.WriteInt32(static_cast<int32_t>(wallpaperErrorCode))) {
381        HILOG_ERROR("Write result data failed!");
382        return IPC_STUB_WRITE_PARCEL_ERR;
383    }
384    return ERR_NONE;
385}
386
387int32_t WallpaperServiceStub::OnWallpaperOn(MessageParcel &data, MessageParcel &reply)
388{
389    HILOG_DEBUG("WallpaperServiceStub::OnWallpaperOn in.");
390    std::string type = data.ReadString();
391    if (type.empty()) {
392        HILOG_ERROR("OnWallpaperOn type is empty after ipc.");
393        return IPC_STUB_INVALID_DATA_ERR;
394    }
395    sptr<IRemoteObject> remote = data.ReadRemoteObject();
396    if (remote == nullptr) {
397        HILOG_ERROR("OnWallpaperOn nullptr after ipc.");
398        return IPC_STUB_INVALID_DATA_ERR;
399    }
400
401    sptr<IWallpaperEventListener> wallpaperListenerProxy = iface_cast<IWallpaperEventListener>(remote);
402    ErrorCode errorCode = On(type, std::move(wallpaperListenerProxy));
403    int32_t ret = static_cast<int32_t>(errorCode);
404    if (!reply.WriteInt32(ret)) {
405        HILOG_ERROR("WriteInt32 failed!");
406        return IPC_STUB_WRITE_PARCEL_ERR;
407    }
408    return ERR_NONE;
409}
410
411int32_t WallpaperServiceStub::OnWallpaperOff(MessageParcel &data, MessageParcel &reply)
412{
413    HILOG_DEBUG("WallpaperServiceStub::OnWallpaperOff in.");
414    std::string type = data.ReadString();
415    if (type.empty()) {
416        HILOG_ERROR("OnWallpaperOff type is empty after ipc.");
417        return IPC_STUB_INVALID_DATA_ERR;
418    }
419    sptr<IRemoteObject> remote = data.ReadRemoteObject();
420    ErrorCode errorCode = E_UNKNOWN;
421    if (remote == nullptr) {
422        errorCode = Off(type, nullptr);
423    } else {
424        sptr<IWallpaperEventListener> wallpaperListenerProxy = iface_cast<IWallpaperEventListener>(remote);
425        errorCode = Off(type, std::move(wallpaperListenerProxy));
426    }
427    int32_t ret = static_cast<int32_t>(errorCode);
428    if (!reply.WriteInt32(ret)) {
429        HILOG_ERROR("WriteInt32 failed!");
430        return IPC_STUB_WRITE_PARCEL_ERR;
431    }
432    return ERR_NONE;
433}
434
435int32_t WallpaperServiceStub::OnSendEvent(MessageParcel &data, MessageParcel &reply)
436{
437    HILOG_DEBUG("WallpaperServiceStub::OnSendEvent start.");
438    std::string eventType = data.ReadString();
439    auto result = SendEvent(eventType);
440    if (!reply.WriteInt32(result)) {
441        HILOG_ERROR("Write int is failed!");
442        return IPC_STUB_WRITE_PARCEL_ERR;
443    }
444    return ERR_NONE;
445}
446
447int32_t WallpaperServiceStub::OnRegisterWallpaperCallback(MessageParcel &data, MessageParcel &reply)
448{
449    HILOG_DEBUG("WallpaperServiceStub::OnRegisterWallpaperCallback start.");
450    sptr<IRemoteObject> object = data.ReadRemoteObject();
451    bool status = false;
452    if (object == nullptr) {
453        HILOG_ERROR("RegisterWallpaperCallback failed!");
454        return IPC_STUB_INVALID_DATA_ERR;
455    }
456    sptr<IWallpaperCallback> callbackProxy = iface_cast<IWallpaperCallback>(object);
457
458    status = RegisterWallpaperCallback(callbackProxy);
459    int32_t ret = status ? static_cast<int32_t>(E_OK) : static_cast<int32_t>(E_DEAL_FAILED);
460    if (!reply.WriteInt32(ret)) {
461        HILOG_ERROR("WriteInt32 failed!");
462        return IPC_STUB_WRITE_PARCEL_ERR;
463    }
464    return ERR_NONE;
465}
466
467std::shared_ptr<OHOS::Media::PixelMap> WallpaperServiceStub::VectorToPixelMap(std::vector<std::uint8_t> value)
468{
469    HILOG_DEBUG("VectorToPixelMap start.!");
470    if (value.size() == 0) {
471        return nullptr;
472    }
473    return std::shared_ptr<PixelMap>(PixelMap::DecodeTlv(value));
474}
475} // namespace WallpaperMgrService
476} // namespace OHOS