IGraphicBufferProducer.cpp revision 3559fbf93801e2c0d9d8fb246fb9b867a361b464
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    DEQUEUE_BUFFER,
38    DETACH_BUFFER,
39    DETACH_NEXT_BUFFER,
40    ATTACH_BUFFER,
41    QUEUE_BUFFER,
42    CANCEL_BUFFER,
43    QUERY,
44    CONNECT,
45    DISCONNECT,
46    SET_SIDEBAND_STREAM,
47    ALLOCATE_BUFFERS,
48    ALLOW_ALLOCATION,
49    SET_GENERATION_NUMBER,
50    GET_CONSUMER_NAME,
51    SET_MAX_DEQUEUED_BUFFER_COUNT,
52    SET_ASYNC_MODE,
53    GET_NEXT_FRAME_NUMBER,
54    SET_SHARED_BUFFER_MODE,
55    SET_AUTO_REFRESH,
56    SET_DEQUEUE_TIMEOUT,
57};
58
59class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
60{
61public:
62    BpGraphicBufferProducer(const sp<IBinder>& impl)
63        : BpInterface<IGraphicBufferProducer>(impl)
64    {
65    }
66
67    virtual ~BpGraphicBufferProducer();
68
69    virtual status_t requestBuffer(int bufferIdx, sp<GraphicBuffer>* buf) {
70        Parcel data, reply;
71        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
72        data.writeInt32(bufferIdx);
73        status_t result =remote()->transact(REQUEST_BUFFER, data, &reply);
74        if (result != NO_ERROR) {
75            return result;
76        }
77        bool nonNull = reply.readInt32();
78        if (nonNull) {
79            *buf = new GraphicBuffer();
80            result = reply.read(**buf);
81            if(result != NO_ERROR) {
82                (*buf).clear();
83                return result;
84            }
85        }
86        result = reply.readInt32();
87        return result;
88    }
89
90    virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers) {
91        Parcel data, reply;
92        data.writeInterfaceToken(
93                IGraphicBufferProducer::getInterfaceDescriptor());
94        data.writeInt32(maxDequeuedBuffers);
95        status_t result = remote()->transact(SET_MAX_DEQUEUED_BUFFER_COUNT,
96                data, &reply);
97        if (result != NO_ERROR) {
98            return result;
99        }
100        result = reply.readInt32();
101        return result;
102    }
103
104    virtual status_t setAsyncMode(bool async) {
105        Parcel data, reply;
106        data.writeInterfaceToken(
107                IGraphicBufferProducer::getInterfaceDescriptor());
108        data.writeInt32(async);
109        status_t result = remote()->transact(SET_ASYNC_MODE,
110                data, &reply);
111        if (result != NO_ERROR) {
112            return result;
113        }
114        result = reply.readInt32();
115        return result;
116    }
117
118    virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, uint32_t width,
119            uint32_t height, PixelFormat format, uint32_t usage) {
120        Parcel data, reply;
121        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
122        data.writeUint32(width);
123        data.writeUint32(height);
124        data.writeInt32(static_cast<int32_t>(format));
125        data.writeUint32(usage);
126        status_t result = remote()->transact(DEQUEUE_BUFFER, data, &reply);
127        if (result != NO_ERROR) {
128            return result;
129        }
130        *buf = reply.readInt32();
131        bool nonNull = reply.readInt32();
132        if (nonNull) {
133            *fence = new Fence();
134            reply.read(**fence);
135        }
136        result = reply.readInt32();
137        return result;
138    }
139
140    virtual status_t detachBuffer(int slot) {
141        Parcel data, reply;
142        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
143        data.writeInt32(slot);
144        status_t result = remote()->transact(DETACH_BUFFER, data, &reply);
145        if (result != NO_ERROR) {
146            return result;
147        }
148        result = reply.readInt32();
149        return result;
150    }
151
152    virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer,
153            sp<Fence>* outFence) {
154        if (outBuffer == NULL) {
155            ALOGE("detachNextBuffer: outBuffer must not be NULL");
156            return BAD_VALUE;
157        } else if (outFence == NULL) {
158            ALOGE("detachNextBuffer: outFence must not be NULL");
159            return BAD_VALUE;
160        }
161        Parcel data, reply;
162        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
163        status_t result = remote()->transact(DETACH_NEXT_BUFFER, data, &reply);
164        if (result != NO_ERROR) {
165            return result;
166        }
167        result = reply.readInt32();
168        if (result == NO_ERROR) {
169            bool nonNull = reply.readInt32();
170            if (nonNull) {
171                *outBuffer = new GraphicBuffer;
172                reply.read(**outBuffer);
173            }
174            nonNull = reply.readInt32();
175            if (nonNull) {
176                *outFence = new Fence;
177                reply.read(**outFence);
178            }
179        }
180        return result;
181    }
182
183    virtual status_t attachBuffer(int* slot, const sp<GraphicBuffer>& buffer) {
184        Parcel data, reply;
185        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
186        data.write(*buffer.get());
187        status_t result = remote()->transact(ATTACH_BUFFER, data, &reply);
188        if (result != NO_ERROR) {
189            return result;
190        }
191        *slot = reply.readInt32();
192        result = reply.readInt32();
193        return result;
194    }
195
196    virtual status_t queueBuffer(int buf,
197            const QueueBufferInput& input, QueueBufferOutput* output) {
198        Parcel data, reply;
199        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
200        data.writeInt32(buf);
201        data.write(input);
202        status_t result = remote()->transact(QUEUE_BUFFER, data, &reply);
203        if (result != NO_ERROR) {
204            return result;
205        }
206        memcpy(output, reply.readInplace(sizeof(*output)), sizeof(*output));
207        result = reply.readInt32();
208        return result;
209    }
210
211    virtual status_t cancelBuffer(int buf, const sp<Fence>& fence) {
212        Parcel data, reply;
213        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
214        data.writeInt32(buf);
215        data.write(*fence.get());
216        status_t result = remote()->transact(CANCEL_BUFFER, data, &reply);
217        if (result != NO_ERROR) {
218            return result;
219        }
220        result = reply.readInt32();
221        return result;
222    }
223
224    virtual int query(int what, int* value) {
225        Parcel data, reply;
226        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
227        data.writeInt32(what);
228        status_t result = remote()->transact(QUERY, data, &reply);
229        if (result != NO_ERROR) {
230            return result;
231        }
232        value[0] = reply.readInt32();
233        result = reply.readInt32();
234        return result;
235    }
236
237    virtual status_t connect(const sp<IProducerListener>& listener,
238            int api, bool producerControlledByApp, QueueBufferOutput* output) {
239        Parcel data, reply;
240        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
241        if (listener != NULL) {
242            data.writeInt32(1);
243            data.writeStrongBinder(IInterface::asBinder(listener));
244        } else {
245            data.writeInt32(0);
246        }
247        data.writeInt32(api);
248        data.writeInt32(producerControlledByApp);
249        status_t result = remote()->transact(CONNECT, data, &reply);
250        if (result != NO_ERROR) {
251            return result;
252        }
253        memcpy(output, reply.readInplace(sizeof(*output)), sizeof(*output));
254        result = reply.readInt32();
255        return result;
256    }
257
258    virtual status_t disconnect(int api) {
259        Parcel data, reply;
260        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
261        data.writeInt32(api);
262        status_t result =remote()->transact(DISCONNECT, data, &reply);
263        if (result != NO_ERROR) {
264            return result;
265        }
266        result = reply.readInt32();
267        return result;
268    }
269
270    virtual status_t setSidebandStream(const sp<NativeHandle>& stream) {
271        Parcel data, reply;
272        status_t result;
273        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
274        if (stream.get()) {
275            data.writeInt32(true);
276            data.writeNativeHandle(stream->handle());
277        } else {
278            data.writeInt32(false);
279        }
280        if ((result = remote()->transact(SET_SIDEBAND_STREAM, data, &reply)) == NO_ERROR) {
281            result = reply.readInt32();
282        }
283        return result;
284    }
285
286    virtual void allocateBuffers(uint32_t width, uint32_t height,
287            PixelFormat format, uint32_t usage) {
288        Parcel data, reply;
289        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
290        data.writeUint32(width);
291        data.writeUint32(height);
292        data.writeInt32(static_cast<int32_t>(format));
293        data.writeUint32(usage);
294        status_t result = remote()->transact(ALLOCATE_BUFFERS, data, &reply);
295        if (result != NO_ERROR) {
296            ALOGE("allocateBuffers failed to transact: %d", result);
297        }
298    }
299
300    virtual status_t allowAllocation(bool allow) {
301        Parcel data, reply;
302        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
303        data.writeInt32(static_cast<int32_t>(allow));
304        status_t result = remote()->transact(ALLOW_ALLOCATION, data, &reply);
305        if (result != NO_ERROR) {
306            return result;
307        }
308        result = reply.readInt32();
309        return result;
310    }
311
312    virtual status_t setGenerationNumber(uint32_t generationNumber) {
313        Parcel data, reply;
314        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
315        data.writeUint32(generationNumber);
316        status_t result = remote()->transact(SET_GENERATION_NUMBER, data, &reply);
317        if (result == NO_ERROR) {
318            result = reply.readInt32();
319        }
320        return result;
321    }
322
323    virtual String8 getConsumerName() const {
324        Parcel data, reply;
325        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
326        status_t result = remote()->transact(GET_CONSUMER_NAME, data, &reply);
327        if (result != NO_ERROR) {
328            ALOGE("getConsumerName failed to transact: %d", result);
329            return String8("TransactFailed");
330        }
331        return reply.readString8();
332    }
333
334    virtual uint64_t getNextFrameNumber() const {
335        Parcel data, reply;
336        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
337        status_t result = remote()->transact(GET_NEXT_FRAME_NUMBER, data, &reply);
338        if (result != NO_ERROR) {
339            ALOGE("getNextFrameNumber failed to transact: %d", result);
340            return 0;
341        }
342        uint64_t frameNumber = reply.readUint64();
343        return frameNumber;
344    }
345
346    virtual status_t setSharedBufferMode(bool sharedBufferMode) {
347        Parcel data, reply;
348        data.writeInterfaceToken(
349                IGraphicBufferProducer::getInterfaceDescriptor());
350        data.writeInt32(sharedBufferMode);
351        status_t result = remote()->transact(SET_SHARED_BUFFER_MODE, data,
352                &reply);
353        if (result == NO_ERROR) {
354            result = reply.readInt32();
355        }
356        return result;
357    }
358
359    virtual status_t setAutoRefresh(bool autoRefresh) {
360        Parcel data, reply;
361        data.writeInterfaceToken(
362                IGraphicBufferProducer::getInterfaceDescriptor());
363        data.writeInt32(autoRefresh);
364        status_t result = remote()->transact(SET_AUTO_REFRESH, data, &reply);
365        if (result == NO_ERROR) {
366            result = reply.readInt32();
367        }
368        return result;
369    }
370
371    virtual status_t setDequeueTimeout(nsecs_t timeout) {
372        Parcel data, reply;
373        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
374        data.writeInt64(timeout);
375        status_t result = remote()->transact(SET_DEQUEUE_TIMEOUT, data, &reply);
376        if (result != NO_ERROR) {
377            ALOGE("setDequeueTimeout failed to transact: %d", result);
378            return result;
379        }
380        return reply.readInt32();
381    }
382};
383
384// Out-of-line virtual method definition to trigger vtable emission in this
385// translation unit (see clang warning -Wweak-vtables)
386BpGraphicBufferProducer::~BpGraphicBufferProducer() {}
387
388IMPLEMENT_META_INTERFACE(GraphicBufferProducer, "android.gui.IGraphicBufferProducer");
389
390// ----------------------------------------------------------------------
391
392status_t BnGraphicBufferProducer::onTransact(
393    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
394{
395    switch(code) {
396        case REQUEST_BUFFER: {
397            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
398            int bufferIdx   = data.readInt32();
399            sp<GraphicBuffer> buffer;
400            int result = requestBuffer(bufferIdx, &buffer);
401            reply->writeInt32(buffer != 0);
402            if (buffer != 0) {
403                reply->write(*buffer);
404            }
405            reply->writeInt32(result);
406            return NO_ERROR;
407        }
408        case SET_MAX_DEQUEUED_BUFFER_COUNT: {
409            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
410            int maxDequeuedBuffers = data.readInt32();
411            int result = setMaxDequeuedBufferCount(maxDequeuedBuffers);
412            reply->writeInt32(result);
413            return NO_ERROR;
414        }
415        case SET_ASYNC_MODE: {
416            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
417            bool async = data.readInt32();
418            int result = setAsyncMode(async);
419            reply->writeInt32(result);
420            return NO_ERROR;
421        }
422        case DEQUEUE_BUFFER: {
423            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
424            uint32_t width = data.readUint32();
425            uint32_t height = data.readUint32();
426            PixelFormat format = static_cast<PixelFormat>(data.readInt32());
427            uint32_t usage = data.readUint32();
428            int buf = 0;
429            sp<Fence> fence;
430            int result = dequeueBuffer(&buf, &fence, width, height, format,
431                    usage);
432            reply->writeInt32(buf);
433            reply->writeInt32(fence != NULL);
434            if (fence != NULL) {
435                reply->write(*fence);
436            }
437            reply->writeInt32(result);
438            return NO_ERROR;
439        }
440        case DETACH_BUFFER: {
441            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
442            int slot = data.readInt32();
443            int result = detachBuffer(slot);
444            reply->writeInt32(result);
445            return NO_ERROR;
446        }
447        case DETACH_NEXT_BUFFER: {
448            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
449            sp<GraphicBuffer> buffer;
450            sp<Fence> fence;
451            int32_t result = detachNextBuffer(&buffer, &fence);
452            reply->writeInt32(result);
453            if (result == NO_ERROR) {
454                reply->writeInt32(buffer != NULL);
455                if (buffer != NULL) {
456                    reply->write(*buffer);
457                }
458                reply->writeInt32(fence != NULL);
459                if (fence != NULL) {
460                    reply->write(*fence);
461                }
462            }
463            return NO_ERROR;
464        }
465        case ATTACH_BUFFER: {
466            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
467            sp<GraphicBuffer> buffer = new GraphicBuffer();
468            data.read(*buffer.get());
469            int slot = 0;
470            int result = attachBuffer(&slot, buffer);
471            reply->writeInt32(slot);
472            reply->writeInt32(result);
473            return NO_ERROR;
474        }
475        case QUEUE_BUFFER: {
476            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
477            int buf = data.readInt32();
478            QueueBufferInput input(data);
479            QueueBufferOutput* const output =
480                    reinterpret_cast<QueueBufferOutput *>(
481                            reply->writeInplace(sizeof(QueueBufferOutput)));
482            memset(output, 0, sizeof(QueueBufferOutput));
483            status_t result = queueBuffer(buf, input, output);
484            reply->writeInt32(result);
485            return NO_ERROR;
486        }
487        case CANCEL_BUFFER: {
488            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
489            int buf = data.readInt32();
490            sp<Fence> fence = new Fence();
491            data.read(*fence.get());
492            status_t result = cancelBuffer(buf, fence);
493            reply->writeInt32(result);
494            return NO_ERROR;
495        }
496        case QUERY: {
497            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
498            int value = 0;
499            int what = data.readInt32();
500            int res = query(what, &value);
501            reply->writeInt32(value);
502            reply->writeInt32(res);
503            return NO_ERROR;
504        }
505        case CONNECT: {
506            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
507            sp<IProducerListener> listener;
508            if (data.readInt32() == 1) {
509                listener = IProducerListener::asInterface(data.readStrongBinder());
510            }
511            int api = data.readInt32();
512            bool producerControlledByApp = data.readInt32();
513            QueueBufferOutput* const output =
514                    reinterpret_cast<QueueBufferOutput *>(
515                            reply->writeInplace(sizeof(QueueBufferOutput)));
516            status_t res = connect(listener, api, producerControlledByApp, output);
517            reply->writeInt32(res);
518            return NO_ERROR;
519        }
520        case DISCONNECT: {
521            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
522            int api = data.readInt32();
523            status_t res = disconnect(api);
524            reply->writeInt32(res);
525            return NO_ERROR;
526        }
527        case SET_SIDEBAND_STREAM: {
528            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
529            sp<NativeHandle> stream;
530            if (data.readInt32()) {
531                stream = NativeHandle::create(data.readNativeHandle(), true);
532            }
533            status_t result = setSidebandStream(stream);
534            reply->writeInt32(result);
535            return NO_ERROR;
536        }
537        case ALLOCATE_BUFFERS: {
538            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
539            uint32_t width = data.readUint32();
540            uint32_t height = data.readUint32();
541            PixelFormat format = static_cast<PixelFormat>(data.readInt32());
542            uint32_t usage = data.readUint32();
543            allocateBuffers(width, height, format, usage);
544            return NO_ERROR;
545        }
546        case ALLOW_ALLOCATION: {
547            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
548            bool allow = static_cast<bool>(data.readInt32());
549            status_t result = allowAllocation(allow);
550            reply->writeInt32(result);
551            return NO_ERROR;
552        }
553        case SET_GENERATION_NUMBER: {
554            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
555            uint32_t generationNumber = data.readUint32();
556            status_t result = setGenerationNumber(generationNumber);
557            reply->writeInt32(result);
558            return NO_ERROR;
559        }
560        case GET_CONSUMER_NAME: {
561            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
562            reply->writeString8(getConsumerName());
563            return NO_ERROR;
564        }
565        case GET_NEXT_FRAME_NUMBER: {
566            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
567            uint64_t frameNumber = getNextFrameNumber();
568            reply->writeUint64(frameNumber);
569            return NO_ERROR;
570        }
571        case SET_SHARED_BUFFER_MODE: {
572            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
573            bool sharedBufferMode = data.readInt32();
574            status_t result = setSharedBufferMode(sharedBufferMode);
575            reply->writeInt32(result);
576            return NO_ERROR;
577        }
578        case SET_AUTO_REFRESH: {
579            CHECK_INTERFACE(IGraphicBuffer, data, reply);
580            bool autoRefresh = data.readInt32();
581            status_t result = setAutoRefresh(autoRefresh);
582            reply->writeInt32(result);
583            return NO_ERROR;
584        }
585        case SET_DEQUEUE_TIMEOUT: {
586            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
587            nsecs_t timeout = data.readInt64();
588            status_t result = setDequeueTimeout(timeout);
589            reply->writeInt32(result);
590            return NO_ERROR;
591        }
592    }
593    return BBinder::onTransact(code, data, reply, flags);
594}
595
596// ----------------------------------------------------------------------------
597
598IGraphicBufferProducer::QueueBufferInput::QueueBufferInput(const Parcel& parcel) {
599    parcel.read(*this);
600}
601
602size_t IGraphicBufferProducer::QueueBufferInput::getFlattenedSize() const {
603    return sizeof(timestamp)
604         + sizeof(isAutoTimestamp)
605         + sizeof(dataSpace)
606         + sizeof(crop)
607         + sizeof(scalingMode)
608         + sizeof(transform)
609         + sizeof(stickyTransform)
610         + fence->getFlattenedSize()
611         + surfaceDamage.getFlattenedSize();
612}
613
614size_t IGraphicBufferProducer::QueueBufferInput::getFdCount() const {
615    return fence->getFdCount();
616}
617
618status_t IGraphicBufferProducer::QueueBufferInput::flatten(
619        void*& buffer, size_t& size, int*& fds, size_t& count) const
620{
621    if (size < getFlattenedSize()) {
622        return NO_MEMORY;
623    }
624    FlattenableUtils::write(buffer, size, timestamp);
625    FlattenableUtils::write(buffer, size, isAutoTimestamp);
626    FlattenableUtils::write(buffer, size, dataSpace);
627    FlattenableUtils::write(buffer, size, crop);
628    FlattenableUtils::write(buffer, size, scalingMode);
629    FlattenableUtils::write(buffer, size, transform);
630    FlattenableUtils::write(buffer, size, stickyTransform);
631    status_t result = fence->flatten(buffer, size, fds, count);
632    if (result != NO_ERROR) {
633        return result;
634    }
635    return surfaceDamage.flatten(buffer, size);
636}
637
638status_t IGraphicBufferProducer::QueueBufferInput::unflatten(
639        void const*& buffer, size_t& size, int const*& fds, size_t& count)
640{
641    size_t minNeeded =
642              sizeof(timestamp)
643            + sizeof(isAutoTimestamp)
644            + sizeof(dataSpace)
645            + sizeof(crop)
646            + sizeof(scalingMode)
647            + sizeof(transform)
648            + sizeof(stickyTransform);
649
650    if (size < minNeeded) {
651        return NO_MEMORY;
652    }
653
654    FlattenableUtils::read(buffer, size, timestamp);
655    FlattenableUtils::read(buffer, size, isAutoTimestamp);
656    FlattenableUtils::read(buffer, size, dataSpace);
657    FlattenableUtils::read(buffer, size, crop);
658    FlattenableUtils::read(buffer, size, scalingMode);
659    FlattenableUtils::read(buffer, size, transform);
660    FlattenableUtils::read(buffer, size, stickyTransform);
661
662    fence = new Fence();
663    status_t result = fence->unflatten(buffer, size, fds, count);
664    if (result != NO_ERROR) {
665        return result;
666    }
667    return surfaceDamage.unflatten(buffer, size);
668}
669
670}; // namespace android
671