blob: 2f75c10d6764dddf94f5af2e4955546b2dce301b [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
Craig Donner2be5b9f2017-01-24 18:14:44 -080092 if (desc->format == AHARDWAREBUFFER_FORMAT_BLOB && desc->height != 1) {
93 ALOGE("Height must be 1 when using the AHARDWAREBUFFER_FORMAT_BLOB "
94 "format");
95 return BAD_VALUE;
96 }
97
Craig Donner0cff9d92016-12-16 14:07:03 -080098 status_t err;
99 uint32_t usage = android_hardware_HardwareBuffer_convertToGrallocUsageBits(
100 desc->usage0, desc->usage1);
101 sp<GraphicBuffer> gbuffer = allocator->createGraphicBuffer(desc->width,
102 desc->height, format, desc->layers, usage, &err);
103 if (err != NO_ERROR) {
104 return err;
105 }
106
107 *outBuffer = GraphicBuffer_to_AHardwareBuffer(gbuffer.get());
108 // Ensure the buffer doesn't get destroyed with the sp<> goes away.
109 AHardwareBuffer_acquire(*outBuffer);
110 return NO_ERROR;
111}
112
113void AHardwareBuffer_acquire(AHardwareBuffer* buffer) {
114 AHardwareBuffer_to_GraphicBuffer(buffer)->incStrong(
115 (void*)AHardwareBuffer_acquire);
116}
117
118void AHardwareBuffer_release(AHardwareBuffer* buffer) {
119 AHardwareBuffer_to_GraphicBuffer(buffer)->decStrong(
120 (void*)AHardwareBuffer_acquire);
121}
122
123void AHardwareBuffer_describe(const AHardwareBuffer* buffer,
124 AHardwareBuffer_Desc* outDesc) {
125 if (!buffer || !outDesc) return;
126
127 const GraphicBuffer* gbuffer = AHardwareBuffer_to_GraphicBuffer(buffer);
128
129 outDesc->width = gbuffer->getWidth();
130 outDesc->height = gbuffer->getHeight();
131 outDesc->layers = gbuffer->getLayerCount();
132 outDesc->usage0 =
133 android_hardware_HardwareBuffer_convertFromGrallocUsageBits(
134 gbuffer->getUsage());
135 outDesc->usage1 = 0;
136 outDesc->format = android_hardware_HardwareBuffer_convertFromPixelFormat(
137 static_cast<uint32_t>(gbuffer->getPixelFormat()));
138}
139
140int AHardwareBuffer_lock(AHardwareBuffer* buffer, uint64_t usage0,
141 int32_t fence, const ARect* rect, void** outVirtualAddress) {
142 if (!buffer) return BAD_VALUE;
143
144 if (usage0 & ~(AHARDWAREBUFFER_USAGE0_CPU_READ_OFTEN |
145 AHARDWAREBUFFER_USAGE0_CPU_WRITE_OFTEN)) {
146 ALOGE("Invalid usage flags passed to AHardwareBuffer_lock; only "
147 " AHARDWAREBUFFER_USAGE0_CPU_* flags are allowed");
148 return BAD_VALUE;
149 }
150
151 uint32_t usage = android_hardware_HardwareBuffer_convertToGrallocUsageBits(
152 usage0, 0);
153 GraphicBuffer* gBuffer = AHardwareBuffer_to_GraphicBuffer(buffer);
154 if (!rect) {
155 return gBuffer->lockAsync(usage, outVirtualAddress, fence);
156 } else {
157 Rect bounds(rect->left, rect->top, rect->right, rect->bottom);
158 return gBuffer->lockAsync(usage, bounds, outVirtualAddress, fence);
159 }
160}
161
162int AHardwareBuffer_unlock(AHardwareBuffer* buffer, int32_t* fence) {
163 if (!buffer) return BAD_VALUE;
164
165 GraphicBuffer* gBuffer = AHardwareBuffer_to_GraphicBuffer(buffer);
166 return gBuffer->unlockAsync(fence);
167}
168
169int AHardwareBuffer_sendHandleToUnixSocket(const AHardwareBuffer* buffer,
170 int socketFd) {
171 if (!buffer) return BAD_VALUE;
172 const GraphicBuffer* gBuffer = AHardwareBuffer_to_GraphicBuffer(buffer);
173
174 size_t flattenedSize = gBuffer->getFlattenedSize();
175 size_t fdCount = gBuffer->getFdCount();
176
177 std::unique_ptr<uint8_t[]> data(new uint8_t[flattenedSize]);
178 std::unique_ptr<int[]> fds(new int[fdCount]);
179
180 // Make copies of needed items since flatten modifies them, and we don't
181 // want to send anything if there's an error during flatten.
182 size_t flattenedSizeCopy = flattenedSize;
183 size_t fdCountCopy = fdCount;
184 void* dataStart = data.get();
185 int* fdsStart = fds.get();
186 status_t err = gBuffer->flatten(dataStart, flattenedSizeCopy, fdsStart,
187 fdCountCopy);
188 if (err != NO_ERROR) {
189 return err;
190 }
191
192 struct iovec iov[1];
193 iov[0].iov_base = data.get();
194 iov[0].iov_len = flattenedSize;
195
196 char buf[CMSG_SPACE(kDataBufferSize)];
197 struct msghdr msg = {
198 .msg_control = buf,
199 .msg_controllen = sizeof(buf),
200 .msg_iov = &iov[0],
201 .msg_iovlen = 1,
202 };
203
204 struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
205 cmsg->cmsg_level = SOL_SOCKET;
206 cmsg->cmsg_type = SCM_RIGHTS;
207 cmsg->cmsg_len = CMSG_LEN(sizeof(int) * fdCount);
208 int* fdData = reinterpret_cast<int*>(CMSG_DATA(cmsg));
209 memcpy(fdData, fds.get(), sizeof(int) * fdCount);
210 msg.msg_controllen = cmsg->cmsg_len;
211
212 int result = sendmsg(socketFd, &msg, 0);
213 if (result <= 0) {
214 ALOGE("Error writing AHardwareBuffer to socket: error %#x (%s)",
215 result, strerror(errno));
216 return result;
217 }
218 return NO_ERROR;
219}
220
221int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd,
222 AHardwareBuffer** outBuffer) {
223 if (!outBuffer) return BAD_VALUE;
224
225 char dataBuf[CMSG_SPACE(kDataBufferSize)];
226 char fdBuf[CMSG_SPACE(kDataBufferSize)];
227 struct iovec iov[1];
228 iov[0].iov_base = dataBuf;
229 iov[0].iov_len = sizeof(dataBuf);
230
231 struct msghdr msg = {
232 .msg_control = fdBuf,
233 .msg_controllen = sizeof(fdBuf),
234 .msg_iov = &iov[0],
235 .msg_iovlen = 1,
236 };
237
238 int result = recvmsg(socketFd, &msg, 0);
239 if (result <= 0) {
240 ALOGE("Error reading AHardwareBuffer from socket: error %#x (%s)",
241 result, strerror(errno));
242 return result;
243 }
244
245 if (msg.msg_iovlen != 1) {
246 ALOGE("Error reading AHardwareBuffer from socket: bad data length");
247 return INVALID_OPERATION;
248 }
249
250 if (msg.msg_controllen % sizeof(int) != 0) {
251 ALOGE("Error reading AHardwareBuffer from socket: bad fd length");
252 return INVALID_OPERATION;
253 }
254
255 size_t dataLen = msg.msg_iov[0].iov_len;
256 const void* data = static_cast<const void*>(msg.msg_iov[0].iov_base);
257 if (!data) {
258 ALOGE("Error reading AHardwareBuffer from socket: no buffer data");
259 return INVALID_OPERATION;
260 }
261
262 struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
263 if (!cmsg) {
264 ALOGE("Error reading AHardwareBuffer from socket: no fd header");
265 return INVALID_OPERATION;
266 }
267
268 size_t fdCount = msg.msg_controllen >> 2;
269 const int* fdData = reinterpret_cast<const int*>(CMSG_DATA(cmsg));
270 if (!fdData) {
271 ALOGE("Error reading AHardwareBuffer from socket: no fd data");
272 return INVALID_OPERATION;
273 }
274
275 GraphicBuffer* gBuffer = new GraphicBuffer();
276 status_t err = gBuffer->unflatten(data, dataLen, fdData, fdCount);
277 if (err != NO_ERROR) {
278 return err;
279 }
280 *outBuffer = GraphicBuffer_to_AHardwareBuffer(gBuffer);
281 // Ensure the buffer has a positive ref-count.
282 AHardwareBuffer_acquire(*outBuffer);
283
284 return NO_ERROR;
285}
286
287const struct native_handle* AHardwareBuffer_getNativeHandle(
288 const AHardwareBuffer* buffer) {
289 if (!buffer) return nullptr;
290 const GraphicBuffer* gbuffer = AHardwareBuffer_to_GraphicBuffer(buffer);
291 return gbuffer->handle;
292}
293
294// ----------------------------------------------------------------------------
295// JNI functions
296// ----------------------------------------------------------------------------
297
298AHardwareBuffer* AHardwareBuffer_fromHardwareBuffer(JNIEnv* env,
299 jobject hardwareBufferObj) {
300 return android_hardware_HardwareBuffer_getNativeHardwareBuffer(env,
301 hardwareBufferObj);
302}
303
304jobject AHardwareBuffer_toHardwareBuffer(JNIEnv* env,
305 AHardwareBuffer* hardwareBuffer) {
306 return android_hardware_HardwareBuffer_createFromAHardwareBuffer(env,
307 hardwareBuffer);
308}