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 
19 namespace OHOS {
20 const uint16_t MAX_USER_DATA_COUNT = 1000;
21 
SurfaceBufferImpl()22 SurfaceBufferImpl::SurfaceBufferImpl() : len_(0)
23 {
24     struct SurfaceBufferData bufferData = {{0}, 0, 0, 0, BUFFER_STATE_NONE, NULL};
25     bufferData_ = bufferData;
26 }
27 
SetInt32(uint32_t key,int32_t value)28 int32_t SurfaceBufferImpl::SetInt32(uint32_t key, int32_t value)
29 {
30     return SetData(key, BUFFER_DATA_TYPE_INT_32, &value, sizeof(value));
31 }
32 
GetInt32(uint32_t key,int32_t & value)33 int32_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 
SetInt64(uint32_t key,int64_t value)48 int32_t SurfaceBufferImpl::SetInt64(uint32_t key, int64_t value)
49 {
50     return SetData(key, BUFFER_DATA_TYPE_INT_64, &value, sizeof(value));
51 }
52 
GetInt64(uint32_t key,int64_t & value)53 int32_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 
SetData(uint32_t key,uint8_t type,const void * data,uint8_t size)68 int32_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 
GetData(uint32_t key,uint8_t * type,void ** data,uint8_t * size)108 int32_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 
ReadFromIpcIo(IpcIo & io)125 void 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 }
WriteToIpcIo(IpcIo & io)161 void 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 
CopyExtraData(SurfaceBufferImpl & buffer)192 void SurfaceBufferImpl::CopyExtraData(SurfaceBufferImpl& buffer)
193 {
194     len_ = buffer.len_;
195     extDatas_ = buffer.extDatas_;
196     buffer.extDatas_.clear();
197 }
198 
ClearExtraData()199 void 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 
~SurfaceBufferImpl()212 SurfaceBufferImpl::~SurfaceBufferImpl()
213 {
214     ClearExtraData();
215     struct SurfaceBufferData bufferData = {{0}, 0, 0, 0, BUFFER_STATE_NONE, NULL};
216     bufferData_ = bufferData;
217 }
218 }
219