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/RefBase.h> 22 #include <utils/Vector.h> 23 #include <utils/Timers.h> 24 25 #include <binder/Parcel.h> 26 #include <binder/IInterface.h> 27 28 #include <gui/IGraphicBufferProducer.h> 29 30 namespace android { 31 // ---------------------------------------------------------------------------- 32 33 enum { 34 REQUEST_BUFFER = IBinder::FIRST_CALL_TRANSACTION, 35 SET_BUFFER_COUNT, 36 DEQUEUE_BUFFER, 37 QUEUE_BUFFER, 38 CANCEL_BUFFER, 39 QUERY, 40 SET_SYNCHRONOUS_MODE, 41 CONNECT, 42 DISCONNECT, 43 }; 44 45 46 class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer> 47 { 48 public: 49 BpGraphicBufferProducer(const sp<IBinder>& impl) 50 : BpInterface<IGraphicBufferProducer>(impl) 51 { 52 } 53 54 virtual status_t requestBuffer(int bufferIdx, sp<GraphicBuffer>* buf) { 55 Parcel data, reply; 56 data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); 57 data.writeInt32(bufferIdx); 58 status_t result =remote()->transact(REQUEST_BUFFER, data, &reply); 59 if (result != NO_ERROR) { 60 return result; 61 } 62 bool nonNull = reply.readInt32(); 63 if (nonNull) { 64 *buf = new GraphicBuffer(); 65 reply.read(**buf); 66 } 67 result = reply.readInt32(); 68 return result; 69 } 70 71 virtual status_t setBufferCount(int bufferCount) 72 { 73 Parcel data, reply; 74 data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); 75 data.writeInt32(bufferCount); 76 status_t result =remote()->transact(SET_BUFFER_COUNT, data, &reply); 77 if (result != NO_ERROR) { 78 return result; 79 } 80 result = reply.readInt32(); 81 return result; 82 } 83 84 virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, 85 uint32_t w, uint32_t h, uint32_t format, uint32_t usage) { 86 Parcel data, reply; 87 data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); 88 data.writeInt32(w); 89 data.writeInt32(h); 90 data.writeInt32(format); 91 data.writeInt32(usage); 92 status_t result = remote()->transact(DEQUEUE_BUFFER, data, &reply); 93 if (result != NO_ERROR) { 94 return result; 95 } 96 *buf = reply.readInt32(); 97 bool fenceWasWritten = reply.readInt32(); 98 if (fenceWasWritten) { 99 // If the fence was written by the callee, then overwrite the 100 // caller's fence here. If it wasn't written then don't touch the 101 // caller's fence. 102 *fence = new Fence(); 103 reply.read(*(fence->get())); 104 } 105 result = reply.readInt32(); 106 return result; 107 } 108 109 virtual status_t queueBuffer(int buf, 110 const QueueBufferInput& input, QueueBufferOutput* output) { 111 Parcel data, reply; 112 data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); 113 data.writeInt32(buf); 114 data.write(input); 115 status_t result = remote()->transact(QUEUE_BUFFER, data, &reply); 116 if (result != NO_ERROR) { 117 return result; 118 } 119 memcpy(output, reply.readInplace(sizeof(*output)), sizeof(*output)); 120 result = reply.readInt32(); 121 return result; 122 } 123 124 virtual void cancelBuffer(int buf, const sp<Fence>& fence) { 125 Parcel data, reply; 126 data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); 127 data.writeInt32(buf); 128 data.write(*fence.get()); 129 remote()->transact(CANCEL_BUFFER, data, &reply); 130 } 131 132 virtual int query(int what, int* value) { 133 Parcel data, reply; 134 data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); 135 data.writeInt32(what); 136 status_t result = remote()->transact(QUERY, data, &reply); 137 if (result != NO_ERROR) { 138 return result; 139 } 140 value[0] = reply.readInt32(); 141 result = reply.readInt32(); 142 return result; 143 } 144 145 virtual status_t setSynchronousMode(bool enabled) { 146 Parcel data, reply; 147 data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); 148 data.writeInt32(enabled); 149 status_t result = remote()->transact(SET_SYNCHRONOUS_MODE, data, &reply); 150 if (result != NO_ERROR) { 151 return result; 152 } 153 result = reply.readInt32(); 154 return result; 155 } 156 157 virtual status_t connect(int api, QueueBufferOutput* output) { 158 Parcel data, reply; 159 data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); 160 data.writeInt32(api); 161 status_t result = remote()->transact(CONNECT, data, &reply); 162 if (result != NO_ERROR) { 163 return result; 164 } 165 memcpy(output, reply.readInplace(sizeof(*output)), sizeof(*output)); 166 result = reply.readInt32(); 167 return result; 168 } 169 170 virtual status_t disconnect(int api) { 171 Parcel data, reply; 172 data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); 173 data.writeInt32(api); 174 status_t result =remote()->transact(DISCONNECT, data, &reply); 175 if (result != NO_ERROR) { 176 return result; 177 } 178 result = reply.readInt32(); 179 return result; 180 } 181 }; 182 183 IMPLEMENT_META_INTERFACE(GraphicBufferProducer, "android.gui.IGraphicBufferProducer"); 184 185 // ---------------------------------------------------------------------- 186 187 status_t BnGraphicBufferProducer::onTransact( 188 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) 189 { 190 switch(code) { 191 case REQUEST_BUFFER: { 192 CHECK_INTERFACE(IGraphicBufferProducer, data, reply); 193 int bufferIdx = data.readInt32(); 194 sp<GraphicBuffer> buffer; 195 int result = requestBuffer(bufferIdx, &buffer); 196 reply->writeInt32(buffer != 0); 197 if (buffer != 0) { 198 reply->write(*buffer); 199 } 200 reply->writeInt32(result); 201 return NO_ERROR; 202 } break; 203 case SET_BUFFER_COUNT: { 204 CHECK_INTERFACE(IGraphicBufferProducer, data, reply); 205 int bufferCount = data.readInt32(); 206 int result = setBufferCount(bufferCount); 207 reply->writeInt32(result); 208 return NO_ERROR; 209 } break; 210 case DEQUEUE_BUFFER: { 211 CHECK_INTERFACE(IGraphicBufferProducer, data, reply); 212 uint32_t w = data.readInt32(); 213 uint32_t h = data.readInt32(); 214 uint32_t format = data.readInt32(); 215 uint32_t usage = data.readInt32(); 216 int buf; 217 sp<Fence> fence; 218 int result = dequeueBuffer(&buf, &fence, w, h, format, usage); 219 reply->writeInt32(buf); 220 reply->writeInt32(fence != NULL); 221 if (fence != NULL) { 222 reply->write(*fence.get()); 223 } 224 reply->writeInt32(result); 225 return NO_ERROR; 226 } break; 227 case QUEUE_BUFFER: { 228 CHECK_INTERFACE(IGraphicBufferProducer, data, reply); 229 int buf = data.readInt32(); 230 QueueBufferInput input(data); 231 QueueBufferOutput* const output = 232 reinterpret_cast<QueueBufferOutput *>( 233 reply->writeInplace(sizeof(QueueBufferOutput))); 234 status_t result = queueBuffer(buf, input, output); 235 reply->writeInt32(result); 236 return NO_ERROR; 237 } break; 238 case CANCEL_BUFFER: { 239 CHECK_INTERFACE(IGraphicBufferProducer, data, reply); 240 int buf = data.readInt32(); 241 sp<Fence> fence = new Fence(); 242 data.read(*fence.get()); 243 cancelBuffer(buf, fence); 244 return NO_ERROR; 245 } break; 246 case QUERY: { 247 CHECK_INTERFACE(IGraphicBufferProducer, data, reply); 248 int value; 249 int what = data.readInt32(); 250 int res = query(what, &value); 251 reply->writeInt32(value); 252 reply->writeInt32(res); 253 return NO_ERROR; 254 } break; 255 case SET_SYNCHRONOUS_MODE: { 256 CHECK_INTERFACE(IGraphicBufferProducer, data, reply); 257 bool enabled = data.readInt32(); 258 status_t res = setSynchronousMode(enabled); 259 reply->writeInt32(res); 260 return NO_ERROR; 261 } break; 262 case CONNECT: { 263 CHECK_INTERFACE(IGraphicBufferProducer, data, reply); 264 int api = data.readInt32(); 265 QueueBufferOutput* const output = 266 reinterpret_cast<QueueBufferOutput *>( 267 reply->writeInplace(sizeof(QueueBufferOutput))); 268 status_t res = connect(api, output); 269 reply->writeInt32(res); 270 return NO_ERROR; 271 } break; 272 case DISCONNECT: { 273 CHECK_INTERFACE(IGraphicBufferProducer, data, reply); 274 int api = data.readInt32(); 275 status_t res = disconnect(api); 276 reply->writeInt32(res); 277 return NO_ERROR; 278 } break; 279 } 280 return BBinder::onTransact(code, data, reply, flags); 281 } 282 283 // ---------------------------------------------------------------------------- 284 285 IGraphicBufferProducer::QueueBufferInput::QueueBufferInput(const Parcel& parcel) { 286 parcel.read(*this); 287 } 288 289 size_t IGraphicBufferProducer::QueueBufferInput::getFlattenedSize() const 290 { 291 return sizeof(timestamp) 292 + sizeof(crop) 293 + sizeof(scalingMode) 294 + sizeof(transform) 295 + fence->getFlattenedSize(); 296 } 297 298 size_t IGraphicBufferProducer::QueueBufferInput::getFdCount() const 299 { 300 return fence->getFdCount(); 301 } 302 303 status_t IGraphicBufferProducer::QueueBufferInput::flatten(void* buffer, size_t size, 304 int fds[], size_t count) const 305 { 306 status_t err = NO_ERROR; 307 char* p = (char*)buffer; 308 memcpy(p, ×tamp, sizeof(timestamp)); p += sizeof(timestamp); 309 memcpy(p, &crop, sizeof(crop)); p += sizeof(crop); 310 memcpy(p, &scalingMode, sizeof(scalingMode)); p += sizeof(scalingMode); 311 memcpy(p, &transform, sizeof(transform)); p += sizeof(transform); 312 err = fence->flatten(p, size - (p - (char*)buffer), fds, count); 313 return err; 314 } 315 316 status_t IGraphicBufferProducer::QueueBufferInput::unflatten(void const* buffer, 317 size_t size, int fds[], size_t count) 318 { 319 status_t err = NO_ERROR; 320 const char* p = (const char*)buffer; 321 memcpy(×tamp, p, sizeof(timestamp)); p += sizeof(timestamp); 322 memcpy(&crop, p, sizeof(crop)); p += sizeof(crop); 323 memcpy(&scalingMode, p, sizeof(scalingMode)); p += sizeof(scalingMode); 324 memcpy(&transform, p, sizeof(transform)); p += sizeof(transform); 325 fence = new Fence(); 326 err = fence->unflatten(p, size - (p - (const char*)buffer), fds, count); 327 return err; 328 } 329 330 }; // namespace android 331