blob: 6a10cb587be2a25c50ac5f858e0f2999ec6d3662 [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
19#include <android/hardware_buffer_jni.h>
20
21#include <errno.h>
22#include <sys/socket.h>
23
24#include <memory>
25
26#include <android_runtime/android_hardware_HardwareBuffer.h>
27#include <binder/Binder.h>
28#include <binder/Parcel.h>
29#include <cutils/native_handle.h>
30#include <binder/IServiceManager.h>
31#include <gui/ISurfaceComposer.h>
32#include <gui/IGraphicBufferAlloc.h>
33#include <ui/GraphicBuffer.h>
34#include <utils/Flattenable.h>
35#include <utils/Log.h>
36
37static constexpr int kDataBufferSize = 64 * sizeof(int); // 64 ints
38
39using namespace android;
40
41static inline const GraphicBuffer* AHardwareBuffer_to_GraphicBuffer(
42 const AHardwareBuffer* buffer) {
43 return reinterpret_cast<const GraphicBuffer*>(buffer);
44}
45
46static inline GraphicBuffer* AHardwareBuffer_to_GraphicBuffer(
47 AHardwareBuffer* buffer) {
48 return reinterpret_cast<GraphicBuffer*>(buffer);
49}
50
51static inline AHardwareBuffer* GraphicBuffer_to_AHardwareBuffer(
52 GraphicBuffer* buffer) {
53 return reinterpret_cast<AHardwareBuffer*>(buffer);
54}
55
56// ----------------------------------------------------------------------------
57// Public functions
58// ----------------------------------------------------------------------------
59
60int AHardwareBuffer_allocate(const AHardwareBuffer_Desc* desc,
61 AHardwareBuffer** outBuffer) {
62 if (!outBuffer || !desc) return BAD_VALUE;
63
64 // The holder is used to destroy the buffer if an error occurs.
65 sp<IServiceManager> sm = defaultServiceManager();
66 if (sm == nullptr) {
67 ALOGE("Unable to connect to ServiceManager");
68 return PERMISSION_DENIED;
69 }
70
71 // Get the SurfaceFlingerService.
72 sp<ISurfaceComposer> composer = interface_cast<ISurfaceComposer>(
73 sm->getService(String16("SurfaceFlinger")));
74 if (composer == nullptr) {
75 ALOGE("Unable to connect to surface composer");
76 return PERMISSION_DENIED;
77 }
78 // Get an IGraphicBufferAlloc to create the buffer.
79 sp<IGraphicBufferAlloc> allocator = composer->createGraphicBufferAlloc();
80 if (allocator == nullptr) {
81 ALOGE("Unable to obtain a buffer allocator");
82 return PERMISSION_DENIED;
83 }
84
85 int format = android_hardware_HardwareBuffer_convertToPixelFormat(
86 desc->format);
87 if (format == 0) {
88 ALOGE("Invalid pixel format");
89 return BAD_VALUE;
90 }
91
92 status_t err;
93 uint32_t usage = android_hardware_HardwareBuffer_convertToGrallocUsageBits(
94 desc->usage0, desc->usage1);
95 sp<GraphicBuffer> gbuffer = allocator->createGraphicBuffer(desc->width,
96 desc->height, format, desc->layers, usage, &err);
97 if (err != NO_ERROR) {
98 return err;
99 }
100
101 *outBuffer = GraphicBuffer_to_AHardwareBuffer(gbuffer.get());
102 // Ensure the buffer doesn't get destroyed with the sp<> goes away.
103 AHardwareBuffer_acquire(*outBuffer);
104 return NO_ERROR;
105}
106
107void AHardwareBuffer_acquire(AHardwareBuffer* buffer) {
108 AHardwareBuffer_to_GraphicBuffer(buffer)->incStrong(
109 (void*)AHardwareBuffer_acquire);
110}
111
112void AHardwareBuffer_release(AHardwareBuffer* buffer) {
113 AHardwareBuffer_to_GraphicBuffer(buffer)->decStrong(
114 (void*)AHardwareBuffer_acquire);
115}
116
117void AHardwareBuffer_describe(const AHardwareBuffer* buffer,
118 AHardwareBuffer_Desc* outDesc) {
119 if (!buffer || !outDesc) return;
120
121 const GraphicBuffer* gbuffer = AHardwareBuffer_to_GraphicBuffer(buffer);
122
123 outDesc->width = gbuffer->getWidth();
124 outDesc->height = gbuffer->getHeight();
125 outDesc->layers = gbuffer->getLayerCount();
126 outDesc->usage0 =
127 android_hardware_HardwareBuffer_convertFromGrallocUsageBits(
128 gbuffer->getUsage());
129 outDesc->usage1 = 0;
130 outDesc->format = android_hardware_HardwareBuffer_convertFromPixelFormat(
131 static_cast<uint32_t>(gbuffer->getPixelFormat()));
132}
133
134int AHardwareBuffer_lock(AHardwareBuffer* buffer, uint64_t usage0,
135 int32_t fence, const ARect* rect, void** outVirtualAddress) {
136 if (!buffer) return BAD_VALUE;
137
138 if (usage0 & ~(AHARDWAREBUFFER_USAGE0_CPU_READ_OFTEN |
139 AHARDWAREBUFFER_USAGE0_CPU_WRITE_OFTEN)) {
140 ALOGE("Invalid usage flags passed to AHardwareBuffer_lock; only "
141 " AHARDWAREBUFFER_USAGE0_CPU_* flags are allowed");
142 return BAD_VALUE;
143 }
144
145 uint32_t usage = android_hardware_HardwareBuffer_convertToGrallocUsageBits(
146 usage0, 0);
147 GraphicBuffer* gBuffer = AHardwareBuffer_to_GraphicBuffer(buffer);
148 if (!rect) {
149 return gBuffer->lockAsync(usage, outVirtualAddress, fence);
150 } else {
151 Rect bounds(rect->left, rect->top, rect->right, rect->bottom);
152 return gBuffer->lockAsync(usage, bounds, outVirtualAddress, fence);
153 }
154}
155
156int AHardwareBuffer_unlock(AHardwareBuffer* buffer, int32_t* fence) {
157 if (!buffer) return BAD_VALUE;
158
159 GraphicBuffer* gBuffer = AHardwareBuffer_to_GraphicBuffer(buffer);
160 return gBuffer->unlockAsync(fence);
161}
162
163int AHardwareBuffer_sendHandleToUnixSocket(const AHardwareBuffer* buffer,
164 int socketFd) {
165 if (!buffer) return BAD_VALUE;
166 const GraphicBuffer* gBuffer = AHardwareBuffer_to_GraphicBuffer(buffer);
167
168 size_t flattenedSize = gBuffer->getFlattenedSize();
169 size_t fdCount = gBuffer->getFdCount();
170
171 std::unique_ptr<uint8_t[]> data(new uint8_t[flattenedSize]);
172 std::unique_ptr<int[]> fds(new int[fdCount]);
173
174 // Make copies of needed items since flatten modifies them, and we don't
175 // want to send anything if there's an error during flatten.
176 size_t flattenedSizeCopy = flattenedSize;
177 size_t fdCountCopy = fdCount;
178 void* dataStart = data.get();
179 int* fdsStart = fds.get();
180 status_t err = gBuffer->flatten(dataStart, flattenedSizeCopy, fdsStart,
181 fdCountCopy);
182 if (err != NO_ERROR) {
183 return err;
184 }
185
186 struct iovec iov[1];
187 iov[0].iov_base = data.get();
188 iov[0].iov_len = flattenedSize;
189
190 char buf[CMSG_SPACE(kDataBufferSize)];
191 struct msghdr msg = {
192 .msg_control = buf,
193 .msg_controllen = sizeof(buf),
194 .msg_iov = &iov[0],
195 .msg_iovlen = 1,
196 };
197
198 struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
199 cmsg->cmsg_level = SOL_SOCKET;
200 cmsg->cmsg_type = SCM_RIGHTS;
201 cmsg->cmsg_len = CMSG_LEN(sizeof(int) * fdCount);
202 int* fdData = reinterpret_cast<int*>(CMSG_DATA(cmsg));
203 memcpy(fdData, fds.get(), sizeof(int) * fdCount);
204 msg.msg_controllen = cmsg->cmsg_len;
205
206 int result = sendmsg(socketFd, &msg, 0);
207 if (result <= 0) {
208 ALOGE("Error writing AHardwareBuffer to socket: error %#x (%s)",
209 result, strerror(errno));
210 return result;
211 }
212 return NO_ERROR;
213}
214
215int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd,
216 AHardwareBuffer** outBuffer) {
217 if (!outBuffer) return BAD_VALUE;
218
219 char dataBuf[CMSG_SPACE(kDataBufferSize)];
220 char fdBuf[CMSG_SPACE(kDataBufferSize)];
221 struct iovec iov[1];
222 iov[0].iov_base = dataBuf;
223 iov[0].iov_len = sizeof(dataBuf);
224
225 struct msghdr msg = {
226 .msg_control = fdBuf,
227 .msg_controllen = sizeof(fdBuf),
228 .msg_iov = &iov[0],
229 .msg_iovlen = 1,
230 };
231
232 int result = recvmsg(socketFd, &msg, 0);
233 if (result <= 0) {
234 ALOGE("Error reading AHardwareBuffer from socket: error %#x (%s)",
235 result, strerror(errno));
236 return result;
237 }
238
239 if (msg.msg_iovlen != 1) {
240 ALOGE("Error reading AHardwareBuffer from socket: bad data length");
241 return INVALID_OPERATION;
242 }
243
244 if (msg.msg_controllen % sizeof(int) != 0) {
245 ALOGE("Error reading AHardwareBuffer from socket: bad fd length");
246 return INVALID_OPERATION;
247 }
248
249 size_t dataLen = msg.msg_iov[0].iov_len;
250 const void* data = static_cast<const void*>(msg.msg_iov[0].iov_base);
251 if (!data) {
252 ALOGE("Error reading AHardwareBuffer from socket: no buffer data");
253 return INVALID_OPERATION;
254 }
255
256 struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
257 if (!cmsg) {
258 ALOGE("Error reading AHardwareBuffer from socket: no fd header");
259 return INVALID_OPERATION;
260 }
261
262 size_t fdCount = msg.msg_controllen >> 2;
263 const int* fdData = reinterpret_cast<const int*>(CMSG_DATA(cmsg));
264 if (!fdData) {
265 ALOGE("Error reading AHardwareBuffer from socket: no fd data");
266 return INVALID_OPERATION;
267 }
268
269 GraphicBuffer* gBuffer = new GraphicBuffer();
270 status_t err = gBuffer->unflatten(data, dataLen, fdData, fdCount);
271 if (err != NO_ERROR) {
272 return err;
273 }
274 *outBuffer = GraphicBuffer_to_AHardwareBuffer(gBuffer);
275 // Ensure the buffer has a positive ref-count.
276 AHardwareBuffer_acquire(*outBuffer);
277
278 return NO_ERROR;
279}
280
281const struct native_handle* AHardwareBuffer_getNativeHandle(
282 const AHardwareBuffer* buffer) {
283 if (!buffer) return nullptr;
284 const GraphicBuffer* gbuffer = AHardwareBuffer_to_GraphicBuffer(buffer);
285 return gbuffer->handle;
286}
287
288// ----------------------------------------------------------------------------
289// JNI functions
290// ----------------------------------------------------------------------------
291
292AHardwareBuffer* AHardwareBuffer_fromHardwareBuffer(JNIEnv* env,
293 jobject hardwareBufferObj) {
294 return android_hardware_HardwareBuffer_getNativeHardwareBuffer(env,
295 hardwareBufferObj);
296}
297
298jobject AHardwareBuffer_toHardwareBuffer(JNIEnv* env,
299 AHardwareBuffer* hardwareBuffer) {
300 return android_hardware_HardwareBuffer_createFromAHardwareBuffer(env,
301 hardwareBuffer);
302}