1/*
2 * Copyright (c) 2021 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 "buffer_handle.h"
17#include "buffer_handle_utils.h"
18
19#include <cstdlib>
20#include <securec.h>
21
22#include <hilog/log.h>
23#include <message_parcel.h>
24#include <unistd.h>
25
26#undef LOG_DOMAIN
27#define LOG_DOMAIN 0xD001400
28#undef LOG_TAG
29#define LOG_TAG "graphicutils"
30#define UTILS_LOGF(...) (void)HILOG_FATAL(LOG_CORE, __VA_ARGS__)
31#define UTILS_LOGE(...) (void)HILOG_ERROR(LOG_CORE, __VA_ARGS__)
32#define UTILS_LOGW(...) (void)HILOG_WARN(LOG_CORE, __VA_ARGS__)
33#define UTILS_LOGI(...) (void)HILOG_INFO(LOG_CORE, __VA_ARGS__)
34#define UTILS_LOGD(...) (void)HILOG_DEBUG(LOG_CORE, __VA_ARGS__)
35#define BUFFER_HANDLE_RESERVE_MAX_SIZE 1024
36
37BufferHandle *AllocateBufferHandle(uint32_t reserveFds, uint32_t reserveInts)
38{
39    if (reserveFds > BUFFER_HANDLE_RESERVE_MAX_SIZE || reserveInts > BUFFER_HANDLE_RESERVE_MAX_SIZE) {
40        UTILS_LOGE("AllocateBufferHandle reserveFds or reserveInts too lager");
41        return nullptr;
42    }
43    size_t handleSize = sizeof(BufferHandle) + (sizeof(int32_t) * (reserveFds + reserveInts));
44    BufferHandle *handle = static_cast<BufferHandle *>(malloc(handleSize));
45    if (handle != nullptr) {
46        errno_t ret = memset_s(handle, handleSize, 0, handleSize);
47        if (ret != 0) {
48            UTILS_LOGE("memset_s error, ret is %{public}d", ret);
49            free(handle);
50            return nullptr;
51        }
52        handle->fd = -1;
53        for (uint32_t i = 0; i < reserveFds; i++) {
54            handle->reserve[i] = -1;
55        }
56        handle->reserveFds = reserveFds;
57        handle->reserveInts = reserveInts;
58    } else {
59        UTILS_LOGE("AllocateBufferHandle malloc %{public}zu failed", handleSize);
60    }
61    return handle;
62}
63
64int32_t FreeBufferHandle(BufferHandle *handle)
65{
66    if (handle == nullptr) {
67        UTILS_LOGW("FreeBufferHandle with nullptr handle");
68        return 0;
69    }
70    if (handle->fd >= 0) {
71        close(handle->fd);
72        handle->fd = -1;
73    }
74    const uint32_t reserveFds = handle->reserveFds;
75    for (uint32_t i = 0; i < reserveFds; i++) {
76        if (handle->reserve[i] >= 0) {
77            close(handle->reserve[i]);
78            handle->reserve[i] = -1;
79        }
80    }
81    free(handle);
82    return 0;
83}
84
85namespace OHOS {
86bool WriteBufferHandle(MessageParcel &parcel, const BufferHandle &handle)
87{
88    if (!parcel.WriteUint32(handle.reserveFds) || !parcel.WriteUint32(handle.reserveInts) ||
89        !parcel.WriteInt32(handle.width) || !parcel.WriteInt32(handle.stride) || !parcel.WriteInt32(handle.height) ||
90        !parcel.WriteInt32(handle.size) || !parcel.WriteInt32(handle.format) || !parcel.WriteInt64(handle.usage) ||
91        !parcel.WriteUint64(handle.phyAddr)) {
92        UTILS_LOGE("%{public}s a lot failed", __func__);
93        return false;
94    }
95    bool validFd = (handle.fd >= 0);
96    if (!parcel.WriteBool(validFd)) {
97        UTILS_LOGE("%{public}s parcel.WriteBool failed", __func__);
98        return false;
99    }
100    if (validFd && !parcel.WriteFileDescriptor(handle.fd)) {
101        UTILS_LOGE("%{public}s parcel.WriteFileDescriptor fd failed", __func__);
102        return false;
103    }
104
105    for (uint32_t i = 0; i < handle.reserveFds; i++) {
106        if (!parcel.WriteFileDescriptor(handle.reserve[i])) {
107            UTILS_LOGE("%{public}s parcel.WriteFileDescriptor reserveFds failed", __func__);
108            return false;
109        }
110    }
111    for (uint32_t j = 0; j < handle.reserveInts; j++) {
112        if (!parcel.WriteInt32(handle.reserve[handle.reserveFds + j])) {
113            UTILS_LOGE("%{public}s parcel.WriteInt32 reserve failed", __func__);
114            return false;
115        }
116    }
117    return true;
118}
119
120BufferHandle *ReadBufferHandle(MessageParcel &parcel)
121{
122    uint32_t reserveFds = 0;
123    uint32_t reserveInts = 0;
124    if (!parcel.ReadUint32(reserveFds) || !parcel.ReadUint32(reserveInts)) {
125        UTILS_LOGE("%{public}s parcel.ReadUint32 reserveFds failed", __func__);
126        return nullptr;
127    }
128
129    BufferHandle *handle = AllocateBufferHandle(reserveFds, reserveInts);
130    if (handle == nullptr) {
131        UTILS_LOGE("%{public}s AllocateBufferHandle failed", __func__);
132        return nullptr;
133    }
134
135    if (!parcel.ReadInt32(handle->width) || !parcel.ReadInt32(handle->stride) || !parcel.ReadInt32(handle->height) ||
136        !parcel.ReadInt32(handle->size) || !parcel.ReadInt32(handle->format) || !parcel.ReadUint64(handle->usage) ||
137        !parcel.ReadUint64(handle->phyAddr)) {
138        UTILS_LOGE("%{public}s a lot failed", __func__);
139        FreeBufferHandle(handle);
140        return nullptr;
141    }
142
143    bool validFd = false;
144    if (!parcel.ReadBool(validFd)) {
145        UTILS_LOGE("%{public}s ReadBool validFd failed", __func__);
146        FreeBufferHandle(handle);
147        return nullptr;
148    }
149    if (validFd) {
150        handle->fd = parcel.ReadFileDescriptor();
151        if (handle->fd == -1) {
152            UTILS_LOGE("%{public}s ReadFileDescriptor fd failed", __func__);
153            FreeBufferHandle(handle);
154            return nullptr;
155        }
156    }
157
158    for (uint32_t i = 0; i < handle->reserveFds; i++) {
159        handle->reserve[i] = parcel.ReadFileDescriptor();
160        if (handle->reserve[i] == -1) {
161            UTILS_LOGE("%{public}s ReadFileDescriptor reserve failed", __func__);
162            FreeBufferHandle(handle);
163            return nullptr;
164        }
165    }
166    for (uint32_t j = 0; j < handle->reserveInts; j++) {
167        if (!parcel.ReadInt32(handle->reserve[reserveFds + j])) {
168            UTILS_LOGE("%{public}s ReadInt32 reserve failed", __func__);
169            FreeBufferHandle(handle);
170            return nullptr;
171        }
172    }
173    return handle;
174}
175} // namespace OHOS
176