1/* 2 * Copyright (C) 2010 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#include <stdint.h> 18#include <sys/types.h> 19 20#include <utils/Errors.h> 21#include <utils/NativeHandle.h> 22#include <utils/RefBase.h> 23#include <utils/Timers.h> 24#include <utils/Vector.h> 25 26#include <binder/Parcel.h> 27#include <binder/IInterface.h> 28 29#include <gui/IGraphicBufferProducer.h> 30#include <gui/IProducerListener.h> 31 32namespace android { 33// ---------------------------------------------------------------------------- 34 35enum { 36 REQUEST_BUFFER = IBinder::FIRST_CALL_TRANSACTION, 37 SET_BUFFER_COUNT, 38 DEQUEUE_BUFFER, 39 DETACH_BUFFER, 40 DETACH_NEXT_BUFFER, 41 ATTACH_BUFFER, 42 QUEUE_BUFFER, 43 CANCEL_BUFFER, 44 QUERY, 45 CONNECT, 46 DISCONNECT, 47 SET_SIDEBAND_STREAM, 48 ALLOCATE_BUFFERS, 49}; 50 51class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer> 52{ 53public: 54 BpGraphicBufferProducer(const sp<IBinder>& impl) 55 : BpInterface<IGraphicBufferProducer>(impl) 56 { 57 } 58 59 virtual status_t requestBuffer(int bufferIdx, sp<GraphicBuffer>* buf) { 60 Parcel data, reply; 61 data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); 62 data.writeInt32(bufferIdx); 63 status_t result =remote()->transact(REQUEST_BUFFER, data, &reply); 64 if (result != NO_ERROR) { 65 return result; 66 } 67 bool nonNull = reply.readInt32(); 68 if (nonNull) { 69 *buf = new GraphicBuffer(); 70 result = reply.read(**buf); 71 if(result != NO_ERROR) { 72 (*buf).clear(); 73 return result; 74 } 75 } 76 result = reply.readInt32(); 77 return result; 78 } 79 80 virtual status_t setBufferCount(int bufferCount) 81 { 82 Parcel data, reply; 83 data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); 84 data.writeInt32(bufferCount); 85 status_t result =remote()->transact(SET_BUFFER_COUNT, data, &reply); 86 if (result != NO_ERROR) { 87 return result; 88 } 89 result = reply.readInt32(); 90 return result; 91 } 92 93 virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, bool async, 94 uint32_t w, uint32_t h, uint32_t format, uint32_t usage) { 95 Parcel data, reply; 96 data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); 97 data.writeInt32(async); 98 data.writeInt32(w); 99 data.writeInt32(h); 100 data.writeInt32(format); 101 data.writeInt32(usage); 102 status_t result = remote()->transact(DEQUEUE_BUFFER, data, &reply); 103 if (result != NO_ERROR) { 104 return result; 105 } 106 *buf = reply.readInt32(); 107 bool nonNull = reply.readInt32(); 108 if (nonNull) { 109 *fence = new Fence(); 110 reply.read(**fence); 111 } 112 result = reply.readInt32(); 113 return result; 114 } 115 116 virtual status_t detachBuffer(int slot) { 117 Parcel data, reply; 118 data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); 119 data.writeInt32(slot); 120 status_t result = remote()->transact(DETACH_BUFFER, data, &reply); 121 if (result != NO_ERROR) { 122 return result; 123 } 124 result = reply.readInt32(); 125 return result; 126 } 127 128 virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer, 129 sp<Fence>* outFence) { 130 if (outBuffer == NULL) { 131 ALOGE("detachNextBuffer: outBuffer must not be NULL"); 132 return BAD_VALUE; 133 } else if (outFence == NULL) { 134 ALOGE("detachNextBuffer: outFence must not be NULL"); 135 return BAD_VALUE; 136 } 137 Parcel data, reply; 138 data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); 139 status_t result = remote()->transact(DETACH_NEXT_BUFFER, data, &reply); 140 if (result != NO_ERROR) { 141 return result; 142 } 143 result = reply.readInt32(); 144 if (result == NO_ERROR) { 145 bool nonNull = reply.readInt32(); 146 if (nonNull) { 147 *outBuffer = new GraphicBuffer; 148 reply.read(**outBuffer); 149 } 150 nonNull = reply.readInt32(); 151 if (nonNull) { 152 *outFence = new Fence; 153 reply.read(**outFence); 154 } 155 } 156 return result; 157 } 158 159 virtual status_t attachBuffer(int* slot, const sp<GraphicBuffer>& buffer) { 160 Parcel data, reply; 161 data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); 162 data.write(*buffer.get()); 163 status_t result = remote()->transact(ATTACH_BUFFER, data, &reply); 164 if (result != NO_ERROR) { 165 return result; 166 } 167 *slot = reply.readInt32(); 168 result = reply.readInt32(); 169 return result; 170 } 171 172 virtual status_t queueBuffer(int buf, 173 const QueueBufferInput& input, QueueBufferOutput* output) { 174 Parcel data, reply; 175 data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); 176 data.writeInt32(buf); 177 data.write(input); 178 status_t result = remote()->transact(QUEUE_BUFFER, data, &reply); 179 if (result != NO_ERROR) { 180 return result; 181 } 182 memcpy(output, reply.readInplace(sizeof(*output)), sizeof(*output)); 183 result = reply.readInt32(); 184 return result; 185 } 186 187 virtual void cancelBuffer(int buf, const sp<Fence>& fence) { 188 Parcel data, reply; 189 data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); 190 data.writeInt32(buf); 191 data.write(*fence.get()); 192 remote()->transact(CANCEL_BUFFER, data, &reply); 193 } 194 195 virtual int query(int what, int* value) { 196 Parcel data, reply; 197 data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); 198 data.writeInt32(what); 199 status_t result = remote()->transact(QUERY, data, &reply); 200 if (result != NO_ERROR) { 201 return result; 202 } 203 value[0] = reply.readInt32(); 204 result = reply.readInt32(); 205 return result; 206 } 207 208 virtual status_t connect(const sp<IProducerListener>& listener, 209 int api, bool producerControlledByApp, QueueBufferOutput* output) { 210 Parcel data, reply; 211 data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); 212 if (listener != NULL) { 213 data.writeInt32(1); 214 data.writeStrongBinder(listener->asBinder()); 215 } else { 216 data.writeInt32(0); 217 } 218 data.writeInt32(api); 219 data.writeInt32(producerControlledByApp); 220 status_t result = remote()->transact(CONNECT, data, &reply); 221 if (result != NO_ERROR) { 222 return result; 223 } 224 memcpy(output, reply.readInplace(sizeof(*output)), sizeof(*output)); 225 result = reply.readInt32(); 226 return result; 227 } 228 229 virtual status_t disconnect(int api) { 230 Parcel data, reply; 231 data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); 232 data.writeInt32(api); 233 status_t result =remote()->transact(DISCONNECT, data, &reply); 234 if (result != NO_ERROR) { 235 return result; 236 } 237 result = reply.readInt32(); 238 return result; 239 } 240 241 virtual status_t setSidebandStream(const sp<NativeHandle>& stream) { 242 Parcel data, reply; 243 status_t result; 244 data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); 245 if (stream.get()) { 246 data.writeInt32(true); 247 data.writeNativeHandle(stream->handle()); 248 } else { 249 data.writeInt32(false); 250 } 251 if ((result = remote()->transact(SET_SIDEBAND_STREAM, data, &reply)) == NO_ERROR) { 252 result = reply.readInt32(); 253 } 254 return result; 255 } 256 257 virtual void allocateBuffers(bool async, uint32_t width, uint32_t height, 258 uint32_t format, uint32_t usage) { 259 Parcel data, reply; 260 data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); 261 data.writeInt32(static_cast<int32_t>(async)); 262 data.writeInt32(static_cast<int32_t>(width)); 263 data.writeInt32(static_cast<int32_t>(height)); 264 data.writeInt32(static_cast<int32_t>(format)); 265 data.writeInt32(static_cast<int32_t>(usage)); 266 status_t result = remote()->transact(ALLOCATE_BUFFERS, data, &reply); 267 if (result != NO_ERROR) { 268 ALOGE("allocateBuffers failed to transact: %d", result); 269 } 270 } 271}; 272 273IMPLEMENT_META_INTERFACE(GraphicBufferProducer, "android.gui.IGraphicBufferProducer"); 274 275// ---------------------------------------------------------------------- 276 277status_t BnGraphicBufferProducer::onTransact( 278 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) 279{ 280 switch(code) { 281 case REQUEST_BUFFER: { 282 CHECK_INTERFACE(IGraphicBufferProducer, data, reply); 283 int bufferIdx = data.readInt32(); 284 sp<GraphicBuffer> buffer; 285 int result = requestBuffer(bufferIdx, &buffer); 286 reply->writeInt32(buffer != 0); 287 if (buffer != 0) { 288 reply->write(*buffer); 289 } 290 reply->writeInt32(result); 291 return NO_ERROR; 292 } break; 293 case SET_BUFFER_COUNT: { 294 CHECK_INTERFACE(IGraphicBufferProducer, data, reply); 295 int bufferCount = data.readInt32(); 296 int result = setBufferCount(bufferCount); 297 reply->writeInt32(result); 298 return NO_ERROR; 299 } break; 300 case DEQUEUE_BUFFER: { 301 CHECK_INTERFACE(IGraphicBufferProducer, data, reply); 302 bool async = data.readInt32(); 303 uint32_t w = data.readInt32(); 304 uint32_t h = data.readInt32(); 305 uint32_t format = data.readInt32(); 306 uint32_t usage = data.readInt32(); 307 int buf; 308 sp<Fence> fence; 309 int result = dequeueBuffer(&buf, &fence, async, w, h, format, usage); 310 reply->writeInt32(buf); 311 reply->writeInt32(fence != NULL); 312 if (fence != NULL) { 313 reply->write(*fence); 314 } 315 reply->writeInt32(result); 316 return NO_ERROR; 317 } break; 318 case DETACH_BUFFER: { 319 CHECK_INTERFACE(IGraphicBufferProducer, data, reply); 320 int slot = data.readInt32(); 321 int result = detachBuffer(slot); 322 reply->writeInt32(result); 323 return NO_ERROR; 324 } break; 325 case DETACH_NEXT_BUFFER: { 326 CHECK_INTERFACE(IGraphicBufferProducer, data, reply); 327 sp<GraphicBuffer> buffer; 328 sp<Fence> fence; 329 int32_t result = detachNextBuffer(&buffer, &fence); 330 reply->writeInt32(result); 331 if (result == NO_ERROR) { 332 reply->writeInt32(buffer != NULL); 333 if (buffer != NULL) { 334 reply->write(*buffer); 335 } 336 reply->writeInt32(fence != NULL); 337 if (fence != NULL) { 338 reply->write(*fence); 339 } 340 } 341 return NO_ERROR; 342 } break; 343 case ATTACH_BUFFER: { 344 CHECK_INTERFACE(IGraphicBufferProducer, data, reply); 345 sp<GraphicBuffer> buffer = new GraphicBuffer(); 346 data.read(*buffer.get()); 347 int slot; 348 int result = attachBuffer(&slot, buffer); 349 reply->writeInt32(slot); 350 reply->writeInt32(result); 351 return NO_ERROR; 352 } break; 353 case QUEUE_BUFFER: { 354 CHECK_INTERFACE(IGraphicBufferProducer, data, reply); 355 int buf = data.readInt32(); 356 QueueBufferInput input(data); 357 QueueBufferOutput* const output = 358 reinterpret_cast<QueueBufferOutput *>( 359 reply->writeInplace(sizeof(QueueBufferOutput))); 360 status_t result = queueBuffer(buf, input, output); 361 reply->writeInt32(result); 362 return NO_ERROR; 363 } break; 364 case CANCEL_BUFFER: { 365 CHECK_INTERFACE(IGraphicBufferProducer, data, reply); 366 int buf = data.readInt32(); 367 sp<Fence> fence = new Fence(); 368 data.read(*fence.get()); 369 cancelBuffer(buf, fence); 370 return NO_ERROR; 371 } break; 372 case QUERY: { 373 CHECK_INTERFACE(IGraphicBufferProducer, data, reply); 374 int value; 375 int what = data.readInt32(); 376 int res = query(what, &value); 377 reply->writeInt32(value); 378 reply->writeInt32(res); 379 return NO_ERROR; 380 } break; 381 case CONNECT: { 382 CHECK_INTERFACE(IGraphicBufferProducer, data, reply); 383 sp<IProducerListener> listener; 384 if (data.readInt32() == 1) { 385 listener = IProducerListener::asInterface(data.readStrongBinder()); 386 } 387 int api = data.readInt32(); 388 bool producerControlledByApp = data.readInt32(); 389 QueueBufferOutput* const output = 390 reinterpret_cast<QueueBufferOutput *>( 391 reply->writeInplace(sizeof(QueueBufferOutput))); 392 status_t res = connect(listener, api, producerControlledByApp, output); 393 reply->writeInt32(res); 394 return NO_ERROR; 395 } break; 396 case DISCONNECT: { 397 CHECK_INTERFACE(IGraphicBufferProducer, data, reply); 398 int api = data.readInt32(); 399 status_t res = disconnect(api); 400 reply->writeInt32(res); 401 return NO_ERROR; 402 } break; 403 case SET_SIDEBAND_STREAM: { 404 CHECK_INTERFACE(IGraphicBufferProducer, data, reply); 405 sp<NativeHandle> stream; 406 if (data.readInt32()) { 407 stream = NativeHandle::create(data.readNativeHandle(), true); 408 } 409 status_t result = setSidebandStream(stream); 410 reply->writeInt32(result); 411 return NO_ERROR; 412 } break; 413 case ALLOCATE_BUFFERS: 414 CHECK_INTERFACE(IGraphicBufferProducer, data, reply); 415 bool async = static_cast<bool>(data.readInt32()); 416 uint32_t width = static_cast<uint32_t>(data.readInt32()); 417 uint32_t height = static_cast<uint32_t>(data.readInt32()); 418 uint32_t format = static_cast<uint32_t>(data.readInt32()); 419 uint32_t usage = static_cast<uint32_t>(data.readInt32()); 420 allocateBuffers(async, width, height, format, usage); 421 return NO_ERROR; 422 } 423 return BBinder::onTransact(code, data, reply, flags); 424} 425 426// ---------------------------------------------------------------------------- 427 428IGraphicBufferProducer::QueueBufferInput::QueueBufferInput(const Parcel& parcel) { 429 parcel.read(*this); 430} 431 432size_t IGraphicBufferProducer::QueueBufferInput::getFlattenedSize() const { 433 return sizeof(timestamp) 434 + sizeof(isAutoTimestamp) 435 + sizeof(crop) 436 + sizeof(scalingMode) 437 + sizeof(transform) 438 + sizeof(stickyTransform) 439 + sizeof(async) 440 + fence->getFlattenedSize(); 441} 442 443size_t IGraphicBufferProducer::QueueBufferInput::getFdCount() const { 444 return fence->getFdCount(); 445} 446 447status_t IGraphicBufferProducer::QueueBufferInput::flatten( 448 void*& buffer, size_t& size, int*& fds, size_t& count) const 449{ 450 if (size < getFlattenedSize()) { 451 return NO_MEMORY; 452 } 453 FlattenableUtils::write(buffer, size, timestamp); 454 FlattenableUtils::write(buffer, size, isAutoTimestamp); 455 FlattenableUtils::write(buffer, size, crop); 456 FlattenableUtils::write(buffer, size, scalingMode); 457 FlattenableUtils::write(buffer, size, transform); 458 FlattenableUtils::write(buffer, size, stickyTransform); 459 FlattenableUtils::write(buffer, size, async); 460 return fence->flatten(buffer, size, fds, count); 461} 462 463status_t IGraphicBufferProducer::QueueBufferInput::unflatten( 464 void const*& buffer, size_t& size, int const*& fds, size_t& count) 465{ 466 size_t minNeeded = 467 sizeof(timestamp) 468 + sizeof(isAutoTimestamp) 469 + sizeof(crop) 470 + sizeof(scalingMode) 471 + sizeof(transform) 472 + sizeof(stickyTransform) 473 + sizeof(async); 474 475 if (size < minNeeded) { 476 return NO_MEMORY; 477 } 478 479 FlattenableUtils::read(buffer, size, timestamp); 480 FlattenableUtils::read(buffer, size, isAutoTimestamp); 481 FlattenableUtils::read(buffer, size, crop); 482 FlattenableUtils::read(buffer, size, scalingMode); 483 FlattenableUtils::read(buffer, size, transform); 484 FlattenableUtils::read(buffer, size, stickyTransform); 485 FlattenableUtils::read(buffer, size, async); 486 487 fence = new Fence(); 488 return fence->unflatten(buffer, size, fds, count); 489} 490 491}; // namespace android 492