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