1/*
2 * Copyright (c) 2020-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 "surface_buffer_impl.h"
17#include "securec.h"
18
19namespace OHOS {
20const uint16_t MAX_USER_DATA_COUNT = 1000;
21
22SurfaceBufferImpl::SurfaceBufferImpl() : len_(0)
23{
24    struct SurfaceBufferData bufferData = {{0}, 0, 0, 0, BUFFER_STATE_NONE, NULL};
25    bufferData_ = bufferData;
26}
27
28int32_t SurfaceBufferImpl::SetInt32(uint32_t key, int32_t value)
29{
30    return SetData(key, BUFFER_DATA_TYPE_INT_32, &value, sizeof(value));
31}
32
33int32_t SurfaceBufferImpl::GetInt32(uint32_t key, int32_t& value)
34{
35    uint8_t type = BUFFER_DATA_TYPE_NONE;
36    void *data = nullptr;
37    uint8_t size;
38    if (GetData(key, &type, &data, &size) != SURFACE_ERROR_OK || type != BUFFER_DATA_TYPE_INT_32) {
39        return SURFACE_ERROR_INVALID_PARAM;
40    }
41    if (size != sizeof(value)) {
42        return SURFACE_ERROR_INVALID_PARAM;
43    }
44    value = *(reinterpret_cast<int32_t *>(data));
45    return SURFACE_ERROR_OK;
46}
47
48int32_t SurfaceBufferImpl::SetInt64(uint32_t key, int64_t value)
49{
50    return SetData(key, BUFFER_DATA_TYPE_INT_64, &value, sizeof(value));
51}
52
53int32_t SurfaceBufferImpl::GetInt64(uint32_t key, int64_t& value)
54{
55    uint8_t type = BUFFER_DATA_TYPE_NONE;
56    void *data = nullptr;
57    uint8_t size;
58    if (GetData(key, &type, &data, &size) != SURFACE_ERROR_OK || type != BUFFER_DATA_TYPE_INT_64) {
59        return SURFACE_ERROR_INVALID_PARAM;
60    }
61    if (size != sizeof(value)) {
62        return SURFACE_ERROR_INVALID_PARAM;
63    }
64    value = *(reinterpret_cast<int64_t *>(data));
65    return SURFACE_ERROR_OK;
66}
67
68int32_t SurfaceBufferImpl::SetData(uint32_t key, uint8_t type, const void* data, uint8_t size)
69{
70    if (type <= BUFFER_DATA_TYPE_NONE ||
71        type >= BUFFER_DATA_TYPE_MAX ||
72        size <= 0 ||
73        size > sizeof(int64_t)) {
74        GRAPHIC_LOGI("Invalid Param");
75        return SURFACE_ERROR_INVALID_PARAM;
76    }
77    if (extDatas_.size() > MAX_USER_DATA_COUNT) {
78        GRAPHIC_LOGI("No more data can be saved because the storage space is full.");
79        return SURFACE_ERROR_SYSTEM_ERROR;
80    }
81    ExtraData extData = {0};
82    std::map<uint32_t, ExtraData>::iterator iter = extDatas_.find(key);
83    if (iter != extDatas_.end()) {
84        extData = iter->second;
85        if (size != extData.size) {
86            free(extData.value);
87            extData.value = nullptr;
88        }
89    }
90    if (extData.value == nullptr) {
91        extData.value = malloc(size);
92        if (extData.value == nullptr) {
93            GRAPHIC_LOGE("Couldn't allocate %zu bytes for ext data", size);
94            return SURFACE_ERROR_SYSTEM_ERROR;
95        }
96    }
97    if (memcpy_s(extData.value, size, data, size) != EOK) {
98        free(extData.value);
99        GRAPHIC_LOGW("Couldn't copy %zu bytes for ext data", size);
100        return SURFACE_ERROR_SYSTEM_ERROR;
101    }
102    extData.size = size;
103    extData.type = type;
104    extDatas_[key] = extData;
105    return SURFACE_ERROR_OK;
106}
107
108int32_t SurfaceBufferImpl::GetData(uint32_t key, uint8_t* type, void** data, uint8_t* size)
109{
110    if ((type == nullptr) || (data == nullptr) || (size == nullptr)) {
111        return SURFACE_ERROR_INVALID_PARAM;
112    }
113
114    std::map<uint32_t, ExtraData>::iterator iter = extDatas_.find(key);
115    if (iter == extDatas_.end()) {
116        return SURFACE_ERROR_INVALID_PARAM;
117    }
118    ExtraData extData = extDatas_[key];
119    *data = extData.value;
120    *size = extData.size;
121    *type = extData.type;
122    return SURFACE_ERROR_OK;
123}
124
125void SurfaceBufferImpl::ReadFromIpcIo(IpcIo& io)
126{
127    ReadInt32(&io, &(bufferData_.handle.key));
128    ReadUint64(&io, &(bufferData_.handle.phyAddr));
129    ReadUint32(&io, &(bufferData_.handle.reserveFds));
130    ReadUint32(&io, &(bufferData_.handle.reserveInts));
131    ReadUint32(&io, &(bufferData_.size));
132    ReadUint32(&io, &(bufferData_.usage));
133    ReadUint32(&io, &len_);
134    uint32_t extDataSize;
135    ReadUint32(&io, &extDataSize);
136    if (extDataSize > 0 && extDataSize < MAX_USER_DATA_COUNT) {
137        for (uint32_t i = 0; i < extDataSize; i++) {
138            uint32_t key;
139            ReadUint32(&io, &key);
140            uint32_t type;
141            ReadUint32(&io, &type);
142            switch (type) {
143                case BUFFER_DATA_TYPE_INT_32: {
144                    int32_t value;
145                    ReadInt32(&io, &value);
146                    SetInt32(key, value);
147                    break;
148                }
149                case BUFFER_DATA_TYPE_INT_64: {
150                    int64_t value;
151                    ReadInt64(&io, &value);
152                    SetInt64(key, value);
153                    break;
154                }
155                default:
156                    break;
157            }
158        }
159    }
160}
161void SurfaceBufferImpl::WriteToIpcIo(IpcIo& io)
162{
163    WriteInt32(&io, bufferData_.handle.key);
164    WriteUint64(&io, bufferData_.handle.phyAddr);
165    WriteUint32(&io, bufferData_.handle.reserveFds);
166    WriteUint32(&io, bufferData_.handle.reserveInts);
167    WriteUint32(&io, bufferData_.size);
168    WriteUint32(&io, bufferData_.usage);
169    WriteUint32(&io, len_);
170    WriteUint32(&io, extDatas_.size());
171    if (!extDatas_.empty()) {
172        std::map<uint32_t, ExtraData>::iterator iter;
173        for (iter = extDatas_.begin(); iter != extDatas_.end(); ++iter) {
174            uint32_t key = iter->first;
175            ExtraData value = iter->second;
176            WriteUint32(&io, key);
177            WriteUint32(&io, value.type);
178            switch (value.type) {
179                case BUFFER_DATA_TYPE_INT_32:
180                    WriteInt32(&io, *(reinterpret_cast<int32_t *>(value.value)));
181                    break;
182                case BUFFER_DATA_TYPE_INT_64:
183                    WriteInt64(&io, *(reinterpret_cast<int64_t *>(value.value)));
184                    break;
185                default:
186                    break;
187            }
188        }
189    }
190}
191
192void SurfaceBufferImpl::CopyExtraData(SurfaceBufferImpl& buffer)
193{
194    len_ = buffer.len_;
195    extDatas_ = buffer.extDatas_;
196    buffer.extDatas_.clear();
197}
198
199void SurfaceBufferImpl::ClearExtraData()
200{
201    if (!extDatas_.empty()) {
202        std::map<uint32_t, ExtraData>::iterator iter;
203        for (iter = extDatas_.begin(); iter != extDatas_.end(); ++iter) {
204            ExtraData value = iter->second;
205            free(value.value);
206            value.value = nullptr;
207        }
208        extDatas_.clear();
209    }
210}
211
212SurfaceBufferImpl::~SurfaceBufferImpl()
213{
214    ClearExtraData();
215    struct SurfaceBufferData bufferData = {{0}, 0, 0, 0, BUFFER_STATE_NONE, NULL};
216    bufferData_ = bufferData;
217}
218}
219