blob: 77ebd52a06f4673818923f09cf39189dbd6f242d [file] [log] [blame]
Craig Donner0cff9d92016-12-16 14:07:03 -08001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "AHardwareBuffer"
18
Mathias Agopiane68b4f72017-02-08 18:48:32 -080019#include <android/hardware_buffer.h>
Craig Donner0cff9d92016-12-16 14:07:03 -080020
21#include <errno.h>
22#include <sys/socket.h>
23
24#include <memory>
25
Craig Donner90051062017-02-02 12:14:30 -080026#include <cutils/native_handle.h>
Mathias Agopiane68b4f72017-02-08 18:48:32 -080027
28#include <utils/Log.h>
29
30#include <ui/GraphicBuffer.h>
31
32#include <binder/IServiceManager.h>
Craig Donner0cff9d92016-12-16 14:07:03 -080033#include <gui/ISurfaceComposer.h>
34#include <gui/IGraphicBufferAlloc.h>
Mathias Agopiane68b4f72017-02-08 18:48:32 -080035
36#include <android_runtime/android_hardware_HardwareBuffer.h>
37
Craig Donner0cff9d92016-12-16 14:07:03 -080038
39static constexpr int kDataBufferSize = 64 * sizeof(int); // 64 ints
40
41using namespace android;
42
43static inline const GraphicBuffer* AHardwareBuffer_to_GraphicBuffer(
44 const AHardwareBuffer* buffer) {
45 return reinterpret_cast<const GraphicBuffer*>(buffer);
46}
47
48static inline GraphicBuffer* AHardwareBuffer_to_GraphicBuffer(
49 AHardwareBuffer* buffer) {
50 return reinterpret_cast<GraphicBuffer*>(buffer);
51}
52
53static inline AHardwareBuffer* GraphicBuffer_to_AHardwareBuffer(
54 GraphicBuffer* buffer) {
55 return reinterpret_cast<AHardwareBuffer*>(buffer);
56}
57
58// ----------------------------------------------------------------------------
59// Public functions
60// ----------------------------------------------------------------------------
61
62int AHardwareBuffer_allocate(const AHardwareBuffer_Desc* desc,
63 AHardwareBuffer** outBuffer) {
64 if (!outBuffer || !desc) return BAD_VALUE;
65
66 // The holder is used to destroy the buffer if an error occurs.
67 sp<IServiceManager> sm = defaultServiceManager();
68 if (sm == nullptr) {
69 ALOGE("Unable to connect to ServiceManager");
70 return PERMISSION_DENIED;
71 }
72
73 // Get the SurfaceFlingerService.
74 sp<ISurfaceComposer> composer = interface_cast<ISurfaceComposer>(
75 sm->getService(String16("SurfaceFlinger")));
76 if (composer == nullptr) {
77 ALOGE("Unable to connect to surface composer");
78 return PERMISSION_DENIED;
79 }
80 // Get an IGraphicBufferAlloc to create the buffer.
81 sp<IGraphicBufferAlloc> allocator = composer->createGraphicBufferAlloc();
82 if (allocator == nullptr) {
83 ALOGE("Unable to obtain a buffer allocator");
84 return PERMISSION_DENIED;
85 }
86
87 int format = android_hardware_HardwareBuffer_convertToPixelFormat(
88 desc->format);
89 if (format == 0) {
90 ALOGE("Invalid pixel format");
91 return BAD_VALUE;
92 }
93
Craig Donner2be5b9f2017-01-24 18:14:44 -080094 if (desc->format == AHARDWAREBUFFER_FORMAT_BLOB && desc->height != 1) {
95 ALOGE("Height must be 1 when using the AHARDWAREBUFFER_FORMAT_BLOB "
96 "format");
97 return BAD_VALUE;
98 }
99
Craig Donner0cff9d92016-12-16 14:07:03 -0800100 status_t err;
Craig Donner90051062017-02-02 12:14:30 -0800101 uint64_t producerUsage = 0;
102 uint64_t consumerUsage = 0;
103 android_hardware_HardwareBuffer_convertToGrallocUsageBits(desc->usage0,
104 desc->usage1, &producerUsage, &consumerUsage);
Craig Donner0cff9d92016-12-16 14:07:03 -0800105 sp<GraphicBuffer> gbuffer = allocator->createGraphicBuffer(desc->width,
Craig Donner90051062017-02-02 12:14:30 -0800106 desc->height, format, desc->layers, producerUsage, consumerUsage,
107 std::string("AHardwareBuffer pid [") + std::to_string(getpid()) +
108 "]", &err);
Craig Donner0cff9d92016-12-16 14:07:03 -0800109 if (err != NO_ERROR) {
110 return err;
111 }
112
113 *outBuffer = GraphicBuffer_to_AHardwareBuffer(gbuffer.get());
114 // Ensure the buffer doesn't get destroyed with the sp<> goes away.
115 AHardwareBuffer_acquire(*outBuffer);
116 return NO_ERROR;
117}
118
119void AHardwareBuffer_acquire(AHardwareBuffer* buffer) {
120 AHardwareBuffer_to_GraphicBuffer(buffer)->incStrong(
121 (void*)AHardwareBuffer_acquire);
122}
123
124void AHardwareBuffer_release(AHardwareBuffer* buffer) {
125 AHardwareBuffer_to_GraphicBuffer(buffer)->decStrong(
126 (void*)AHardwareBuffer_acquire);
127}
128
129void AHardwareBuffer_describe(const AHardwareBuffer* buffer,
130 AHardwareBuffer_Desc* outDesc) {
131 if (!buffer || !outDesc) return;
132
133 const GraphicBuffer* gbuffer = AHardwareBuffer_to_GraphicBuffer(buffer);
134
135 outDesc->width = gbuffer->getWidth();
136 outDesc->height = gbuffer->getHeight();
137 outDesc->layers = gbuffer->getLayerCount();
138 outDesc->usage0 =
139 android_hardware_HardwareBuffer_convertFromGrallocUsageBits(
Craig Donner90051062017-02-02 12:14:30 -0800140 gbuffer->getUsage(), gbuffer->getUsage());
Craig Donner0cff9d92016-12-16 14:07:03 -0800141 outDesc->usage1 = 0;
142 outDesc->format = android_hardware_HardwareBuffer_convertFromPixelFormat(
143 static_cast<uint32_t>(gbuffer->getPixelFormat()));
144}
145
146int AHardwareBuffer_lock(AHardwareBuffer* buffer, uint64_t usage0,
147 int32_t fence, const ARect* rect, void** outVirtualAddress) {
148 if (!buffer) return BAD_VALUE;
149
150 if (usage0 & ~(AHARDWAREBUFFER_USAGE0_CPU_READ_OFTEN |
151 AHARDWAREBUFFER_USAGE0_CPU_WRITE_OFTEN)) {
152 ALOGE("Invalid usage flags passed to AHardwareBuffer_lock; only "
153 " AHARDWAREBUFFER_USAGE0_CPU_* flags are allowed");
154 return BAD_VALUE;
155 }
156
Craig Donner90051062017-02-02 12:14:30 -0800157 uint64_t producerUsage = 0;
158 uint64_t consumerUsage = 0;
159 android_hardware_HardwareBuffer_convertToGrallocUsageBits(usage0, 0,
160 &producerUsage, &consumerUsage);
Craig Donner0cff9d92016-12-16 14:07:03 -0800161 GraphicBuffer* gBuffer = AHardwareBuffer_to_GraphicBuffer(buffer);
Craig Donner90051062017-02-02 12:14:30 -0800162 Rect bounds;
Craig Donner0cff9d92016-12-16 14:07:03 -0800163 if (!rect) {
Craig Donner90051062017-02-02 12:14:30 -0800164 bounds.set(Rect(gBuffer->getWidth(), gBuffer->getHeight()));
Craig Donner0cff9d92016-12-16 14:07:03 -0800165 } else {
Craig Donner90051062017-02-02 12:14:30 -0800166 bounds.set(Rect(rect->left, rect->top, rect->right, rect->bottom));
Craig Donner0cff9d92016-12-16 14:07:03 -0800167 }
Craig Donner90051062017-02-02 12:14:30 -0800168 return gBuffer->lockAsync(producerUsage, consumerUsage, bounds,
169 outVirtualAddress, fence);
Craig Donner0cff9d92016-12-16 14:07:03 -0800170}
171
172int AHardwareBuffer_unlock(AHardwareBuffer* buffer, int32_t* fence) {
173 if (!buffer) return BAD_VALUE;
174
175 GraphicBuffer* gBuffer = AHardwareBuffer_to_GraphicBuffer(buffer);
176 return gBuffer->unlockAsync(fence);
177}
178
179int AHardwareBuffer_sendHandleToUnixSocket(const AHardwareBuffer* buffer,
180 int socketFd) {
181 if (!buffer) return BAD_VALUE;
182 const GraphicBuffer* gBuffer = AHardwareBuffer_to_GraphicBuffer(buffer);
183
184 size_t flattenedSize = gBuffer->getFlattenedSize();
185 size_t fdCount = gBuffer->getFdCount();
186
187 std::unique_ptr<uint8_t[]> data(new uint8_t[flattenedSize]);
188 std::unique_ptr<int[]> fds(new int[fdCount]);
189
190 // Make copies of needed items since flatten modifies them, and we don't
191 // want to send anything if there's an error during flatten.
192 size_t flattenedSizeCopy = flattenedSize;
193 size_t fdCountCopy = fdCount;
194 void* dataStart = data.get();
195 int* fdsStart = fds.get();
196 status_t err = gBuffer->flatten(dataStart, flattenedSizeCopy, fdsStart,
197 fdCountCopy);
198 if (err != NO_ERROR) {
199 return err;
200 }
201
202 struct iovec iov[1];
203 iov[0].iov_base = data.get();
204 iov[0].iov_len = flattenedSize;
205
206 char buf[CMSG_SPACE(kDataBufferSize)];
207 struct msghdr msg = {
208 .msg_control = buf,
209 .msg_controllen = sizeof(buf),
210 .msg_iov = &iov[0],
211 .msg_iovlen = 1,
212 };
213
214 struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
215 cmsg->cmsg_level = SOL_SOCKET;
216 cmsg->cmsg_type = SCM_RIGHTS;
217 cmsg->cmsg_len = CMSG_LEN(sizeof(int) * fdCount);
218 int* fdData = reinterpret_cast<int*>(CMSG_DATA(cmsg));
219 memcpy(fdData, fds.get(), sizeof(int) * fdCount);
220 msg.msg_controllen = cmsg->cmsg_len;
221
222 int result = sendmsg(socketFd, &msg, 0);
223 if (result <= 0) {
224 ALOGE("Error writing AHardwareBuffer to socket: error %#x (%s)",
225 result, strerror(errno));
226 return result;
227 }
228 return NO_ERROR;
229}
230
231int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd,
232 AHardwareBuffer** outBuffer) {
233 if (!outBuffer) return BAD_VALUE;
234
235 char dataBuf[CMSG_SPACE(kDataBufferSize)];
236 char fdBuf[CMSG_SPACE(kDataBufferSize)];
237 struct iovec iov[1];
238 iov[0].iov_base = dataBuf;
239 iov[0].iov_len = sizeof(dataBuf);
240
241 struct msghdr msg = {
242 .msg_control = fdBuf,
243 .msg_controllen = sizeof(fdBuf),
244 .msg_iov = &iov[0],
245 .msg_iovlen = 1,
246 };
247
248 int result = recvmsg(socketFd, &msg, 0);
249 if (result <= 0) {
250 ALOGE("Error reading AHardwareBuffer from socket: error %#x (%s)",
251 result, strerror(errno));
252 return result;
253 }
254
255 if (msg.msg_iovlen != 1) {
256 ALOGE("Error reading AHardwareBuffer from socket: bad data length");
257 return INVALID_OPERATION;
258 }
259
260 if (msg.msg_controllen % sizeof(int) != 0) {
261 ALOGE("Error reading AHardwareBuffer from socket: bad fd length");
262 return INVALID_OPERATION;
263 }
264
265 size_t dataLen = msg.msg_iov[0].iov_len;
266 const void* data = static_cast<const void*>(msg.msg_iov[0].iov_base);
267 if (!data) {
268 ALOGE("Error reading AHardwareBuffer from socket: no buffer data");
269 return INVALID_OPERATION;
270 }
271
272 struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
273 if (!cmsg) {
274 ALOGE("Error reading AHardwareBuffer from socket: no fd header");
275 return INVALID_OPERATION;
276 }
277
278 size_t fdCount = msg.msg_controllen >> 2;
279 const int* fdData = reinterpret_cast<const int*>(CMSG_DATA(cmsg));
280 if (!fdData) {
281 ALOGE("Error reading AHardwareBuffer from socket: no fd data");
282 return INVALID_OPERATION;
283 }
284
285 GraphicBuffer* gBuffer = new GraphicBuffer();
286 status_t err = gBuffer->unflatten(data, dataLen, fdData, fdCount);
287 if (err != NO_ERROR) {
288 return err;
289 }
290 *outBuffer = GraphicBuffer_to_AHardwareBuffer(gBuffer);
291 // Ensure the buffer has a positive ref-count.
292 AHardwareBuffer_acquire(*outBuffer);
293
294 return NO_ERROR;
295}
296
297const struct native_handle* AHardwareBuffer_getNativeHandle(
298 const AHardwareBuffer* buffer) {
299 if (!buffer) return nullptr;
300 const GraphicBuffer* gbuffer = AHardwareBuffer_to_GraphicBuffer(buffer);
301 return gbuffer->handle;
302}