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/String8.h>
24 #include <utils/Timers.h>
25 #include <utils/Vector.h>
26 
27 #include <binder/Parcel.h>
28 #include <binder/IInterface.h>
29 
30 #ifndef NO_BUFFERHUB
31 #include <gui/BufferHubProducer.h>
32 #endif
33 
34 #include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h>
35 #include <gui/bufferqueue/2.0/H2BGraphicBufferProducer.h>
36 #include <gui/BufferQueueDefs.h>
37 #include <gui/IGraphicBufferProducer.h>
38 #include <gui/IProducerListener.h>
39 
40 namespace android {
41 // ----------------------------------------------------------------------------
42 
43 using H2BGraphicBufferProducerV1_0 =
44         ::android::hardware::graphics::bufferqueue::V1_0::utils::
45         H2BGraphicBufferProducer;
46 using H2BGraphicBufferProducerV2_0 =
47         ::android::hardware::graphics::bufferqueue::V2_0::utils::
48         H2BGraphicBufferProducer;
49 
50 enum {
51     REQUEST_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
52     DEQUEUE_BUFFER,
53     DETACH_BUFFER,
54     DETACH_NEXT_BUFFER,
55     ATTACH_BUFFER,
56     QUEUE_BUFFER,
57     CANCEL_BUFFER,
58     QUERY,
59     CONNECT,
60     DISCONNECT,
61     SET_SIDEBAND_STREAM,
62     ALLOCATE_BUFFERS,
63     ALLOW_ALLOCATION,
64     SET_GENERATION_NUMBER,
65     GET_CONSUMER_NAME,
66     SET_MAX_DEQUEUED_BUFFER_COUNT,
67     SET_ASYNC_MODE,
68     SET_SHARED_BUFFER_MODE,
69     SET_AUTO_REFRESH,
70     SET_DEQUEUE_TIMEOUT,
71     GET_LAST_QUEUED_BUFFER,
72     GET_FRAME_TIMESTAMPS,
73     GET_UNIQUE_ID,
74     GET_CONSUMER_USAGE,
75     SET_LEGACY_BUFFER_DROP,
76 };
77 
78 class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
79 {
80 public:
BpGraphicBufferProducer(const sp<IBinder> & impl)81     explicit BpGraphicBufferProducer(const sp<IBinder>& impl)
82         : BpInterface<IGraphicBufferProducer>(impl)
83     {
84     }
85 
86     ~BpGraphicBufferProducer() override;
87 
requestBuffer(int bufferIdx,sp<GraphicBuffer> * buf)88     virtual status_t requestBuffer(int bufferIdx, sp<GraphicBuffer>* buf) {
89         Parcel data, reply;
90         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
91         data.writeInt32(bufferIdx);
92         status_t result =remote()->transact(REQUEST_BUFFER, data, &reply);
93         if (result != NO_ERROR) {
94             return result;
95         }
96         bool nonNull = reply.readInt32();
97         if (nonNull) {
98             *buf = new GraphicBuffer();
99             result = reply.read(**buf);
100             if(result != NO_ERROR) {
101                 (*buf).clear();
102                 return result;
103             }
104         }
105         result = reply.readInt32();
106         return result;
107     }
108 
setMaxDequeuedBufferCount(int maxDequeuedBuffers)109     virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers) {
110         Parcel data, reply;
111         data.writeInterfaceToken(
112                 IGraphicBufferProducer::getInterfaceDescriptor());
113         data.writeInt32(maxDequeuedBuffers);
114         status_t result = remote()->transact(SET_MAX_DEQUEUED_BUFFER_COUNT,
115                 data, &reply);
116         if (result != NO_ERROR) {
117             return result;
118         }
119         result = reply.readInt32();
120         return result;
121     }
122 
setAsyncMode(bool async)123     virtual status_t setAsyncMode(bool async) {
124         Parcel data, reply;
125         data.writeInterfaceToken(
126                 IGraphicBufferProducer::getInterfaceDescriptor());
127         data.writeInt32(async);
128         status_t result = remote()->transact(SET_ASYNC_MODE,
129                 data, &reply);
130         if (result != NO_ERROR) {
131             return result;
132         }
133         result = reply.readInt32();
134         return result;
135     }
136 
dequeueBuffer(int * buf,sp<Fence> * fence,uint32_t width,uint32_t height,PixelFormat format,uint64_t usage,uint64_t * outBufferAge,FrameEventHistoryDelta * outTimestamps)137     virtual status_t dequeueBuffer(int* buf, sp<Fence>* fence, uint32_t width, uint32_t height,
138                                    PixelFormat format, uint64_t usage, uint64_t* outBufferAge,
139                                    FrameEventHistoryDelta* outTimestamps) {
140         Parcel data, reply;
141         bool getFrameTimestamps = (outTimestamps != nullptr);
142 
143         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
144         data.writeUint32(width);
145         data.writeUint32(height);
146         data.writeInt32(static_cast<int32_t>(format));
147         data.writeUint64(usage);
148         data.writeBool(getFrameTimestamps);
149 
150         status_t result = remote()->transact(DEQUEUE_BUFFER, data, &reply);
151         if (result != NO_ERROR) {
152             return result;
153         }
154 
155         *buf = reply.readInt32();
156         *fence = new Fence();
157         result = reply.read(**fence);
158         if (result != NO_ERROR) {
159             fence->clear();
160             return result;
161         }
162         if (outBufferAge) {
163             result = reply.readUint64(outBufferAge);
164         } else {
165             // Read the value even if outBufferAge is nullptr:
166             uint64_t bufferAge;
167             result = reply.readUint64(&bufferAge);
168         }
169         if (result != NO_ERROR) {
170             ALOGE("IGBP::dequeueBuffer failed to read buffer age: %d", result);
171             return result;
172         }
173         if (getFrameTimestamps) {
174             result = reply.read(*outTimestamps);
175             if (result != NO_ERROR) {
176                 ALOGE("IGBP::dequeueBuffer failed to read timestamps: %d",
177                         result);
178                 return result;
179             }
180         }
181         result = reply.readInt32();
182         return result;
183     }
184 
detachBuffer(int slot)185     virtual status_t detachBuffer(int slot) {
186         Parcel data, reply;
187         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
188         data.writeInt32(slot);
189         status_t result = remote()->transact(DETACH_BUFFER, data, &reply);
190         if (result != NO_ERROR) {
191             return result;
192         }
193         result = reply.readInt32();
194         return result;
195     }
196 
detachNextBuffer(sp<GraphicBuffer> * outBuffer,sp<Fence> * outFence)197     virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer,
198             sp<Fence>* outFence) {
199         if (outBuffer == nullptr) {
200             ALOGE("detachNextBuffer: outBuffer must not be NULL");
201             return BAD_VALUE;
202         } else if (outFence == nullptr) {
203             ALOGE("detachNextBuffer: outFence must not be NULL");
204             return BAD_VALUE;
205         }
206         Parcel data, reply;
207         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
208         status_t result = remote()->transact(DETACH_NEXT_BUFFER, data, &reply);
209         if (result != NO_ERROR) {
210             return result;
211         }
212         result = reply.readInt32();
213         if (result == NO_ERROR) {
214             bool nonNull = reply.readInt32();
215             if (nonNull) {
216                 *outBuffer = new GraphicBuffer;
217                 result = reply.read(**outBuffer);
218                 if (result != NO_ERROR) {
219                     outBuffer->clear();
220                     return result;
221                 }
222             }
223             nonNull = reply.readInt32();
224             if (nonNull) {
225                 *outFence = new Fence;
226                 result = reply.read(**outFence);
227                 if (result != NO_ERROR) {
228                     outBuffer->clear();
229                     outFence->clear();
230                     return result;
231                 }
232             }
233         }
234         return result;
235     }
236 
attachBuffer(int * slot,const sp<GraphicBuffer> & buffer)237     virtual status_t attachBuffer(int* slot, const sp<GraphicBuffer>& buffer) {
238         Parcel data, reply;
239         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
240         data.write(*buffer.get());
241         status_t result = remote()->transact(ATTACH_BUFFER, data, &reply);
242         if (result != NO_ERROR) {
243             return result;
244         }
245 
246         *slot = reply.readInt32();
247         result = reply.readInt32();
248         if (result == NO_ERROR &&
249                 (*slot < 0 || *slot >= BufferQueueDefs::NUM_BUFFER_SLOTS)) {
250             ALOGE("attachBuffer returned invalid slot %d", *slot);
251             android_errorWriteLog(0x534e4554, "37478824");
252             return UNKNOWN_ERROR;
253         }
254 
255         return result;
256     }
257 
queueBuffer(int buf,const QueueBufferInput & input,QueueBufferOutput * output)258     virtual status_t queueBuffer(int buf,
259             const QueueBufferInput& input, QueueBufferOutput* output) {
260         Parcel data, reply;
261 
262         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
263         data.writeInt32(buf);
264         data.write(input);
265 
266         status_t result = remote()->transact(QUEUE_BUFFER, data, &reply);
267         if (result != NO_ERROR) {
268             return result;
269         }
270 
271         result = reply.read(*output);
272         if (result != NO_ERROR) {
273             return result;
274         }
275 
276         result = reply.readInt32();
277         return result;
278     }
279 
cancelBuffer(int buf,const sp<Fence> & fence)280     virtual status_t cancelBuffer(int buf, const sp<Fence>& fence) {
281         Parcel data, reply;
282         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
283         data.writeInt32(buf);
284         data.write(*fence.get());
285         status_t result = remote()->transact(CANCEL_BUFFER, data, &reply);
286         if (result != NO_ERROR) {
287             return result;
288         }
289         result = reply.readInt32();
290         return result;
291     }
292 
query(int what,int * value)293     virtual int query(int what, int* value) {
294         Parcel data, reply;
295         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
296         data.writeInt32(what);
297         status_t result = remote()->transact(QUERY, data, &reply);
298         if (result != NO_ERROR) {
299             return result;
300         }
301         value[0] = reply.readInt32();
302         result = reply.readInt32();
303         return result;
304     }
305 
connect(const sp<IProducerListener> & listener,int api,bool producerControlledByApp,QueueBufferOutput * output)306     virtual status_t connect(const sp<IProducerListener>& listener,
307             int api, bool producerControlledByApp, QueueBufferOutput* output) {
308         Parcel data, reply;
309         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
310         if (listener != nullptr) {
311             data.writeInt32(1);
312             data.writeStrongBinder(IInterface::asBinder(listener));
313         } else {
314             data.writeInt32(0);
315         }
316         data.writeInt32(api);
317         data.writeInt32(producerControlledByApp);
318         status_t result = remote()->transact(CONNECT, data, &reply);
319         if (result != NO_ERROR) {
320             return result;
321         }
322         reply.read(*output);
323         result = reply.readInt32();
324         return result;
325     }
326 
disconnect(int api,DisconnectMode mode)327     virtual status_t disconnect(int api, DisconnectMode mode) {
328         Parcel data, reply;
329         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
330         data.writeInt32(api);
331         data.writeInt32(static_cast<int32_t>(mode));
332         status_t result =remote()->transact(DISCONNECT, data, &reply);
333         if (result != NO_ERROR) {
334             return result;
335         }
336         result = reply.readInt32();
337         return result;
338     }
339 
setSidebandStream(const sp<NativeHandle> & stream)340     virtual status_t setSidebandStream(const sp<NativeHandle>& stream) {
341         Parcel data, reply;
342         status_t result;
343         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
344         if (stream.get()) {
345             data.writeInt32(true);
346             data.writeNativeHandle(stream->handle());
347         } else {
348             data.writeInt32(false);
349         }
350         if ((result = remote()->transact(SET_SIDEBAND_STREAM, data, &reply)) == NO_ERROR) {
351             result = reply.readInt32();
352         }
353         return result;
354     }
355 
allocateBuffers(uint32_t width,uint32_t height,PixelFormat format,uint64_t usage)356     virtual void allocateBuffers(uint32_t width, uint32_t height,
357             PixelFormat format, uint64_t usage) {
358         Parcel data, reply;
359         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
360         data.writeUint32(width);
361         data.writeUint32(height);
362         data.writeInt32(static_cast<int32_t>(format));
363         data.writeUint64(usage);
364         status_t result = remote()->transact(ALLOCATE_BUFFERS, data, &reply, IBinder::FLAG_ONEWAY);
365         if (result != NO_ERROR) {
366             ALOGE("allocateBuffers failed to transact: %d", result);
367         }
368     }
369 
allowAllocation(bool allow)370     virtual status_t allowAllocation(bool allow) {
371         Parcel data, reply;
372         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
373         data.writeInt32(static_cast<int32_t>(allow));
374         status_t result = remote()->transact(ALLOW_ALLOCATION, data, &reply);
375         if (result != NO_ERROR) {
376             return result;
377         }
378         result = reply.readInt32();
379         return result;
380     }
381 
setGenerationNumber(uint32_t generationNumber)382     virtual status_t setGenerationNumber(uint32_t generationNumber) {
383         Parcel data, reply;
384         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
385         data.writeUint32(generationNumber);
386         status_t result = remote()->transact(SET_GENERATION_NUMBER, data, &reply);
387         if (result == NO_ERROR) {
388             result = reply.readInt32();
389         }
390         return result;
391     }
392 
getConsumerName() const393     virtual String8 getConsumerName() const {
394         Parcel data, reply;
395         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
396         status_t result = remote()->transact(GET_CONSUMER_NAME, data, &reply);
397         if (result != NO_ERROR) {
398             ALOGE("getConsumerName failed to transact: %d", result);
399             return String8("TransactFailed");
400         }
401         return reply.readString8();
402     }
403 
setSharedBufferMode(bool sharedBufferMode)404     virtual status_t setSharedBufferMode(bool sharedBufferMode) {
405         Parcel data, reply;
406         data.writeInterfaceToken(
407                 IGraphicBufferProducer::getInterfaceDescriptor());
408         data.writeInt32(sharedBufferMode);
409         status_t result = remote()->transact(SET_SHARED_BUFFER_MODE, data,
410                 &reply);
411         if (result == NO_ERROR) {
412             result = reply.readInt32();
413         }
414         return result;
415     }
416 
setAutoRefresh(bool autoRefresh)417     virtual status_t setAutoRefresh(bool autoRefresh) {
418         Parcel data, reply;
419         data.writeInterfaceToken(
420                 IGraphicBufferProducer::getInterfaceDescriptor());
421         data.writeInt32(autoRefresh);
422         status_t result = remote()->transact(SET_AUTO_REFRESH, data, &reply);
423         if (result == NO_ERROR) {
424             result = reply.readInt32();
425         }
426         return result;
427     }
428 
setDequeueTimeout(nsecs_t timeout)429     virtual status_t setDequeueTimeout(nsecs_t timeout) {
430         Parcel data, reply;
431         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
432         data.writeInt64(timeout);
433         status_t result = remote()->transact(SET_DEQUEUE_TIMEOUT, data, &reply);
434         if (result != NO_ERROR) {
435             ALOGE("setDequeueTimeout failed to transact: %d", result);
436             return result;
437         }
438         return reply.readInt32();
439     }
440 
setLegacyBufferDrop(bool drop)441     virtual status_t setLegacyBufferDrop(bool drop) {
442         Parcel data, reply;
443         data.writeInterfaceToken(
444                 IGraphicBufferProducer::getInterfaceDescriptor());
445         data.writeInt32(drop);
446         status_t result = remote()->transact(SET_LEGACY_BUFFER_DROP,
447                 data, &reply);
448         if (result != NO_ERROR) {
449             return result;
450         }
451         result = reply.readInt32();
452         return result;
453     }
454 
getLastQueuedBuffer(sp<GraphicBuffer> * outBuffer,sp<Fence> * outFence,float outTransformMatrix[16])455     virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
456             sp<Fence>* outFence, float outTransformMatrix[16]) override {
457         Parcel data, reply;
458         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
459         status_t result = remote()->transact(GET_LAST_QUEUED_BUFFER, data,
460                 &reply);
461         if (result != NO_ERROR) {
462             ALOGE("getLastQueuedBuffer failed to transact: %d", result);
463             return result;
464         }
465         result = reply.readInt32();
466         if (result != NO_ERROR) {
467             return result;
468         }
469         bool hasBuffer = reply.readBool();
470         sp<GraphicBuffer> buffer;
471         if (hasBuffer) {
472             buffer = new GraphicBuffer();
473             result = reply.read(*buffer);
474             if (result == NO_ERROR) {
475                 result = reply.read(outTransformMatrix, sizeof(float) * 16);
476             }
477         }
478         if (result != NO_ERROR) {
479             ALOGE("getLastQueuedBuffer failed to read buffer: %d", result);
480             return result;
481         }
482         sp<Fence> fence(new Fence);
483         result = reply.read(*fence);
484         if (result != NO_ERROR) {
485             ALOGE("getLastQueuedBuffer failed to read fence: %d", result);
486             return result;
487         }
488         *outBuffer = buffer;
489         *outFence = fence;
490         return result;
491     }
492 
getFrameTimestamps(FrameEventHistoryDelta * outDelta)493     virtual void getFrameTimestamps(FrameEventHistoryDelta* outDelta) {
494         Parcel data, reply;
495         status_t result = data.writeInterfaceToken(
496                 IGraphicBufferProducer::getInterfaceDescriptor());
497         if (result != NO_ERROR) {
498             ALOGE("IGBP::getFrameTimestamps failed to write token: %d", result);
499             return;
500         }
501         result = remote()->transact(GET_FRAME_TIMESTAMPS, data, &reply);
502         if (result != NO_ERROR) {
503             ALOGE("IGBP::getFrameTimestamps failed to transact: %d", result);
504             return;
505         }
506         result = reply.read(*outDelta);
507         if (result != NO_ERROR) {
508             ALOGE("IGBP::getFrameTimestamps failed to read timestamps: %d",
509                     result);
510         }
511     }
512 
getUniqueId(uint64_t * outId) const513     virtual status_t getUniqueId(uint64_t* outId) const {
514         Parcel data, reply;
515         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
516         status_t result = remote()->transact(GET_UNIQUE_ID, data, &reply);
517         if (result != NO_ERROR) {
518             ALOGE("getUniqueId failed to transact: %d", result);
519         }
520         status_t actualResult = NO_ERROR;
521         result = reply.readInt32(&actualResult);
522         if (result != NO_ERROR) {
523             return result;
524         }
525         result = reply.readUint64(outId);
526         if (result != NO_ERROR) {
527             return result;
528         }
529         return actualResult;
530     }
531 
getConsumerUsage(uint64_t * outUsage) const532     virtual status_t getConsumerUsage(uint64_t* outUsage) const {
533         Parcel data, reply;
534         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
535         status_t result = remote()->transact(GET_CONSUMER_USAGE, data, &reply);
536         if (result != NO_ERROR) {
537             ALOGE("getConsumerUsage failed to transact: %d", result);
538         }
539         status_t actualResult = NO_ERROR;
540         result = reply.readInt32(&actualResult);
541         if (result != NO_ERROR) {
542             return result;
543         }
544         result = reply.readUint64(outUsage);
545         if (result != NO_ERROR) {
546             return result;
547         }
548         return actualResult;
549     }
550 };
551 
552 // Out-of-line virtual method definition to trigger vtable emission in this
553 // translation unit (see clang warning -Wweak-vtables)
~BpGraphicBufferProducer()554 BpGraphicBufferProducer::~BpGraphicBufferProducer() {}
555 
556 class HpGraphicBufferProducer : public HpInterface<
557         BpGraphicBufferProducer,
558         H2BGraphicBufferProducerV1_0,
559         H2BGraphicBufferProducerV2_0> {
560 public:
HpGraphicBufferProducer(const sp<IBinder> & base)561     explicit HpGraphicBufferProducer(const sp<IBinder>& base) : PBase(base) {}
562 
requestBuffer(int slot,sp<GraphicBuffer> * buf)563     status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) override {
564         return mBase->requestBuffer(slot, buf);
565     }
566 
setMaxDequeuedBufferCount(int maxDequeuedBuffers)567     status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers) override {
568         return mBase->setMaxDequeuedBufferCount(maxDequeuedBuffers);
569     }
570 
setAsyncMode(bool async)571     status_t setAsyncMode(bool async) override {
572         return mBase->setAsyncMode(async);
573     }
574 
dequeueBuffer(int * slot,sp<Fence> * fence,uint32_t w,uint32_t h,PixelFormat format,uint64_t usage,uint64_t * outBufferAge,FrameEventHistoryDelta * outTimestamps)575     status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w, uint32_t h, PixelFormat format,
576                            uint64_t usage, uint64_t* outBufferAge,
577                            FrameEventHistoryDelta* outTimestamps) override {
578         return mBase->dequeueBuffer(slot, fence, w, h, format, usage, outBufferAge, outTimestamps);
579     }
580 
detachBuffer(int slot)581     status_t detachBuffer(int slot) override {
582         return mBase->detachBuffer(slot);
583     }
584 
detachNextBuffer(sp<GraphicBuffer> * outBuffer,sp<Fence> * outFence)585     status_t detachNextBuffer(
586             sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence) override {
587         return mBase->detachNextBuffer(outBuffer, outFence);
588     }
589 
attachBuffer(int * outSlot,const sp<GraphicBuffer> & buffer)590     status_t attachBuffer(
591             int* outSlot, const sp<GraphicBuffer>& buffer) override {
592         return mBase->attachBuffer(outSlot, buffer);
593     }
594 
queueBuffer(int slot,const QueueBufferInput & input,QueueBufferOutput * output)595     status_t queueBuffer(
596             int slot,
597             const QueueBufferInput& input,
598             QueueBufferOutput* output) override {
599         return mBase->queueBuffer(slot, input, output);
600     }
601 
cancelBuffer(int slot,const sp<Fence> & fence)602     status_t cancelBuffer(int slot, const sp<Fence>& fence) override {
603         return mBase->cancelBuffer(slot, fence);
604     }
605 
query(int what,int * value)606     int query(int what, int* value) override {
607         return mBase->query(what, value);
608     }
609 
connect(const sp<IProducerListener> & listener,int api,bool producerControlledByApp,QueueBufferOutput * output)610     status_t connect(
611             const sp<IProducerListener>& listener,
612             int api, bool producerControlledByApp,
613             QueueBufferOutput* output) override {
614         return mBase->connect(listener, api, producerControlledByApp, output);
615     }
616 
disconnect(int api,DisconnectMode mode=DisconnectMode::Api)617     status_t disconnect(
618             int api, DisconnectMode mode = DisconnectMode::Api) override {
619         return mBase->disconnect(api, mode);
620     }
621 
setSidebandStream(const sp<NativeHandle> & stream)622     status_t setSidebandStream(const sp<NativeHandle>& stream) override {
623         return mBase->setSidebandStream(stream);
624     }
625 
allocateBuffers(uint32_t width,uint32_t height,PixelFormat format,uint64_t usage)626     void allocateBuffers(uint32_t width, uint32_t height,
627             PixelFormat format, uint64_t usage) override {
628         return mBase->allocateBuffers(width, height, format, usage);
629     }
630 
allowAllocation(bool allow)631     status_t allowAllocation(bool allow) override {
632         return mBase->allowAllocation(allow);
633     }
634 
setGenerationNumber(uint32_t generationNumber)635     status_t setGenerationNumber(uint32_t generationNumber) override {
636         return mBase->setGenerationNumber(generationNumber);
637     }
638 
getConsumerName() const639     String8 getConsumerName() const override {
640         return mBase->getConsumerName();
641     }
642 
setSharedBufferMode(bool sharedBufferMode)643     status_t setSharedBufferMode(bool sharedBufferMode) override {
644         return mBase->setSharedBufferMode(sharedBufferMode);
645     }
646 
setAutoRefresh(bool autoRefresh)647     status_t setAutoRefresh(bool autoRefresh) override {
648         return mBase->setAutoRefresh(autoRefresh);
649     }
650 
setDequeueTimeout(nsecs_t timeout)651     status_t setDequeueTimeout(nsecs_t timeout) override {
652         return mBase->setDequeueTimeout(timeout);
653     }
654 
setLegacyBufferDrop(bool drop)655     status_t setLegacyBufferDrop(bool drop) override {
656         return mBase->setLegacyBufferDrop(drop);
657     }
658 
getLastQueuedBuffer(sp<GraphicBuffer> * outBuffer,sp<Fence> * outFence,float outTransformMatrix[16])659     status_t getLastQueuedBuffer(
660             sp<GraphicBuffer>* outBuffer,
661             sp<Fence>* outFence,
662             float outTransformMatrix[16]) override {
663         return mBase->getLastQueuedBuffer(
664                 outBuffer, outFence, outTransformMatrix);
665     }
666 
getFrameTimestamps(FrameEventHistoryDelta * outDelta)667     void getFrameTimestamps(FrameEventHistoryDelta* outDelta) override {
668         return mBase->getFrameTimestamps(outDelta);
669     }
670 
getUniqueId(uint64_t * outId) const671     status_t getUniqueId(uint64_t* outId) const override {
672         return mBase->getUniqueId(outId);
673     }
674 
getConsumerUsage(uint64_t * outUsage) const675     status_t getConsumerUsage(uint64_t* outUsage) const override {
676         return mBase->getConsumerUsage(outUsage);
677     }
678 };
679 
680 IMPLEMENT_HYBRID_META_INTERFACE(GraphicBufferProducer,
681         "android.gui.IGraphicBufferProducer");
682 
683 // ----------------------------------------------------------------------
684 
setLegacyBufferDrop(bool drop)685 status_t IGraphicBufferProducer::setLegacyBufferDrop(bool drop) {
686     // No-op for IGBP other than BufferQueue.
687     (void) drop;
688     return INVALID_OPERATION;
689 }
690 
exportToParcel(Parcel * parcel)691 status_t IGraphicBufferProducer::exportToParcel(Parcel* parcel) {
692     status_t res = OK;
693     res = parcel->writeUint32(USE_BUFFER_QUEUE);
694     if (res != NO_ERROR) {
695         ALOGE("exportToParcel: Cannot write magic, res=%d.", res);
696         return res;
697     }
698 
699     return parcel->writeStrongBinder(IInterface::asBinder(this));
700 }
701 
702 /* static */
exportToParcel(const sp<IGraphicBufferProducer> & producer,Parcel * parcel)703 status_t IGraphicBufferProducer::exportToParcel(const sp<IGraphicBufferProducer>& producer,
704                                                 Parcel* parcel) {
705     if (parcel == nullptr) {
706         ALOGE("exportToParcel: Invalid parcel object.");
707         return BAD_VALUE;
708     }
709 
710     if (producer == nullptr) {
711         status_t res = OK;
712         res = parcel->writeUint32(IGraphicBufferProducer::USE_BUFFER_QUEUE);
713         if (res != NO_ERROR) return res;
714         return parcel->writeStrongBinder(nullptr);
715     } else {
716         return producer->exportToParcel(parcel);
717     }
718 }
719 
720 /* static */
createFromParcel(const Parcel * parcel)721 sp<IGraphicBufferProducer> IGraphicBufferProducer::createFromParcel(const Parcel* parcel) {
722     uint32_t outMagic = 0;
723     status_t res = NO_ERROR;
724 
725     res = parcel->readUint32(&outMagic);
726     if (res != NO_ERROR) {
727         ALOGE("createFromParcel: Failed to read magic, error=%d.", res);
728         return nullptr;
729     }
730 
731     switch (outMagic) {
732         case USE_BUFFER_QUEUE: {
733             sp<IBinder> binder;
734             res = parcel->readNullableStrongBinder(&binder);
735             if (res != NO_ERROR) {
736                 ALOGE("createFromParcel: Can't read strong binder.");
737                 return nullptr;
738             }
739             return interface_cast<IGraphicBufferProducer>(binder);
740         }
741         case USE_BUFFER_HUB: {
742             ALOGE("createFromParcel: BufferHub not implemented.");
743 #ifndef NO_BUFFERHUB
744             dvr::ProducerQueueParcelable producerParcelable;
745             res = producerParcelable.readFromParcel(parcel);
746             if (res != NO_ERROR) {
747                 ALOGE("createFromParcel: Failed to read from parcel, error=%d", res);
748                 return nullptr;
749             }
750             return BufferHubProducer::Create(std::move(producerParcelable));
751 #else
752             return nullptr;
753 #endif
754         }
755         default: {
756             ALOGE("createFromParcel: Unexpected mgaic: 0x%x.", outMagic);
757             return nullptr;
758         }
759     }
760 }
761 
762 // ----------------------------------------------------------------------------
763 
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)764 status_t BnGraphicBufferProducer::onTransact(
765     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
766 {
767     switch(code) {
768         case REQUEST_BUFFER: {
769             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
770             int bufferIdx   = data.readInt32();
771             sp<GraphicBuffer> buffer;
772             int result = requestBuffer(bufferIdx, &buffer);
773             reply->writeInt32(buffer != nullptr);
774             if (buffer != nullptr) {
775                 reply->write(*buffer);
776             }
777             reply->writeInt32(result);
778             return NO_ERROR;
779         }
780         case SET_MAX_DEQUEUED_BUFFER_COUNT: {
781             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
782             int maxDequeuedBuffers = data.readInt32();
783             int result = setMaxDequeuedBufferCount(maxDequeuedBuffers);
784             reply->writeInt32(result);
785             return NO_ERROR;
786         }
787         case SET_ASYNC_MODE: {
788             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
789             bool async = data.readInt32();
790             int result = setAsyncMode(async);
791             reply->writeInt32(result);
792             return NO_ERROR;
793         }
794         case DEQUEUE_BUFFER: {
795             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
796             uint32_t width = data.readUint32();
797             uint32_t height = data.readUint32();
798             PixelFormat format = static_cast<PixelFormat>(data.readInt32());
799             uint64_t usage = data.readUint64();
800             uint64_t bufferAge = 0;
801             bool getTimestamps = data.readBool();
802 
803             int buf = 0;
804             sp<Fence> fence = Fence::NO_FENCE;
805             FrameEventHistoryDelta frameTimestamps;
806             int result = dequeueBuffer(&buf, &fence, width, height, format, usage, &bufferAge,
807                                        getTimestamps ? &frameTimestamps : nullptr);
808 
809             if (fence == nullptr) {
810                 ALOGE("dequeueBuffer returned a NULL fence, setting to Fence::NO_FENCE");
811                 fence = Fence::NO_FENCE;
812             }
813             reply->writeInt32(buf);
814             reply->write(*fence);
815             reply->writeUint64(bufferAge);
816             if (getTimestamps) {
817                 reply->write(frameTimestamps);
818             }
819             reply->writeInt32(result);
820             return NO_ERROR;
821         }
822         case DETACH_BUFFER: {
823             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
824             int slot = data.readInt32();
825             int result = detachBuffer(slot);
826             reply->writeInt32(result);
827             return NO_ERROR;
828         }
829         case DETACH_NEXT_BUFFER: {
830             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
831             sp<GraphicBuffer> buffer;
832             sp<Fence> fence;
833             int32_t result = detachNextBuffer(&buffer, &fence);
834             reply->writeInt32(result);
835             if (result == NO_ERROR) {
836                 reply->writeInt32(buffer != nullptr);
837                 if (buffer != nullptr) {
838                     reply->write(*buffer);
839                 }
840                 reply->writeInt32(fence != nullptr);
841                 if (fence != nullptr) {
842                     reply->write(*fence);
843                 }
844             }
845             return NO_ERROR;
846         }
847         case ATTACH_BUFFER: {
848             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
849             sp<GraphicBuffer> buffer = new GraphicBuffer();
850             status_t result = data.read(*buffer.get());
851             int slot = 0;
852             if (result == NO_ERROR) {
853                 result = attachBuffer(&slot, buffer);
854             }
855             reply->writeInt32(slot);
856             reply->writeInt32(result);
857             return NO_ERROR;
858         }
859         case QUEUE_BUFFER: {
860             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
861 
862             int buf = data.readInt32();
863             QueueBufferInput input(data);
864             QueueBufferOutput output;
865             status_t result = queueBuffer(buf, input, &output);
866             reply->write(output);
867             reply->writeInt32(result);
868 
869             return NO_ERROR;
870         }
871         case CANCEL_BUFFER: {
872             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
873             int buf = data.readInt32();
874             sp<Fence> fence = new Fence();
875             status_t result = data.read(*fence.get());
876             if (result == NO_ERROR) {
877                 result = cancelBuffer(buf, fence);
878             }
879             reply->writeInt32(result);
880             return NO_ERROR;
881         }
882         case QUERY: {
883             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
884             int value = 0;
885             int what = data.readInt32();
886             int res = query(what, &value);
887             reply->writeInt32(value);
888             reply->writeInt32(res);
889             return NO_ERROR;
890         }
891         case CONNECT: {
892             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
893             sp<IProducerListener> listener;
894             if (data.readInt32() == 1) {
895                 listener = IProducerListener::asInterface(data.readStrongBinder());
896             }
897             int api = data.readInt32();
898             bool producerControlledByApp = data.readInt32();
899             QueueBufferOutput output;
900             status_t res = connect(listener, api, producerControlledByApp, &output);
901             reply->write(output);
902             reply->writeInt32(res);
903             return NO_ERROR;
904         }
905         case DISCONNECT: {
906             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
907             int api = data.readInt32();
908             DisconnectMode mode = static_cast<DisconnectMode>(data.readInt32());
909             status_t res = disconnect(api, mode);
910             reply->writeInt32(res);
911             return NO_ERROR;
912         }
913         case SET_SIDEBAND_STREAM: {
914             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
915             sp<NativeHandle> stream;
916             if (data.readInt32()) {
917                 stream = NativeHandle::create(data.readNativeHandle(), true);
918             }
919             status_t result = setSidebandStream(stream);
920             reply->writeInt32(result);
921             return NO_ERROR;
922         }
923         case ALLOCATE_BUFFERS: {
924             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
925             uint32_t width = data.readUint32();
926             uint32_t height = data.readUint32();
927             PixelFormat format = static_cast<PixelFormat>(data.readInt32());
928             uint64_t usage = data.readUint64();
929             allocateBuffers(width, height, format, usage);
930             return NO_ERROR;
931         }
932         case ALLOW_ALLOCATION: {
933             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
934             bool allow = static_cast<bool>(data.readInt32());
935             status_t result = allowAllocation(allow);
936             reply->writeInt32(result);
937             return NO_ERROR;
938         }
939         case SET_GENERATION_NUMBER: {
940             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
941             uint32_t generationNumber = data.readUint32();
942             status_t result = setGenerationNumber(generationNumber);
943             reply->writeInt32(result);
944             return NO_ERROR;
945         }
946         case GET_CONSUMER_NAME: {
947             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
948             reply->writeString8(getConsumerName());
949             return NO_ERROR;
950         }
951         case SET_SHARED_BUFFER_MODE: {
952             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
953             bool sharedBufferMode = data.readInt32();
954             status_t result = setSharedBufferMode(sharedBufferMode);
955             reply->writeInt32(result);
956             return NO_ERROR;
957         }
958         case SET_AUTO_REFRESH: {
959             CHECK_INTERFACE(IGraphicBuffer, data, reply);
960             bool autoRefresh = data.readInt32();
961             status_t result = setAutoRefresh(autoRefresh);
962             reply->writeInt32(result);
963             return NO_ERROR;
964         }
965         case SET_DEQUEUE_TIMEOUT: {
966             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
967             nsecs_t timeout = data.readInt64();
968             status_t result = setDequeueTimeout(timeout);
969             reply->writeInt32(result);
970             return NO_ERROR;
971         }
972         case GET_LAST_QUEUED_BUFFER: {
973             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
974             sp<GraphicBuffer> buffer(nullptr);
975             sp<Fence> fence(Fence::NO_FENCE);
976             float transform[16] = {};
977             status_t result = getLastQueuedBuffer(&buffer, &fence, transform);
978             reply->writeInt32(result);
979             if (result != NO_ERROR) {
980                 return result;
981             }
982             if (!buffer.get()) {
983                 reply->writeBool(false);
984             } else {
985                 reply->writeBool(true);
986                 result = reply->write(*buffer);
987                 if (result == NO_ERROR) {
988                     reply->write(transform, sizeof(float) * 16);
989                 }
990             }
991             if (result != NO_ERROR) {
992                 ALOGE("getLastQueuedBuffer failed to write buffer: %d", result);
993                 return result;
994             }
995             if (fence == nullptr) {
996                 ALOGE("getLastQueuedBuffer returned a NULL fence, setting to Fence::NO_FENCE");
997                 fence = Fence::NO_FENCE;
998             }
999             result = reply->write(*fence);
1000             if (result != NO_ERROR) {
1001                 ALOGE("getLastQueuedBuffer failed to write fence: %d", result);
1002                 return result;
1003             }
1004             return NO_ERROR;
1005         }
1006         case GET_FRAME_TIMESTAMPS: {
1007             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
1008             FrameEventHistoryDelta frameTimestamps;
1009             getFrameTimestamps(&frameTimestamps);
1010             status_t result = reply->write(frameTimestamps);
1011             if (result != NO_ERROR) {
1012                 ALOGE("BnGBP::GET_FRAME_TIMESTAMPS failed to write buffer: %d",
1013                         result);
1014                 return result;
1015             }
1016             return NO_ERROR;
1017         }
1018         case GET_UNIQUE_ID: {
1019             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
1020             uint64_t outId = 0;
1021             status_t actualResult = getUniqueId(&outId);
1022             status_t result = reply->writeInt32(actualResult);
1023             if (result != NO_ERROR) {
1024                 return result;
1025             }
1026             result = reply->writeUint64(outId);
1027             if (result != NO_ERROR) {
1028                 return result;
1029             }
1030             return NO_ERROR;
1031         }
1032         case GET_CONSUMER_USAGE: {
1033             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
1034             uint64_t outUsage = 0;
1035             status_t actualResult = getConsumerUsage(&outUsage);
1036             status_t result = reply->writeInt32(actualResult);
1037             if (result != NO_ERROR) {
1038                 return result;
1039             }
1040             result = reply->writeUint64(outUsage);
1041             if (result != NO_ERROR) {
1042                 return result;
1043             }
1044             return NO_ERROR;
1045         }
1046         case SET_LEGACY_BUFFER_DROP: {
1047             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
1048             bool drop = data.readInt32();
1049             int result = setLegacyBufferDrop(drop);
1050             reply->writeInt32(result);
1051             return NO_ERROR;
1052         }
1053     }
1054     return BBinder::onTransact(code, data, reply, flags);
1055 }
1056 
1057 // ----------------------------------------------------------------------------
1058 
QueueBufferInput(const Parcel & parcel)1059 IGraphicBufferProducer::QueueBufferInput::QueueBufferInput(const Parcel& parcel) {
1060     parcel.read(*this);
1061 }
1062 
minFlattenedSize()1063 constexpr size_t IGraphicBufferProducer::QueueBufferInput::minFlattenedSize() {
1064     return sizeof(timestamp) +
1065             sizeof(isAutoTimestamp) +
1066             sizeof(dataSpace) +
1067             sizeof(crop) +
1068             sizeof(scalingMode) +
1069             sizeof(transform) +
1070             sizeof(stickyTransform) +
1071             sizeof(getFrameTimestamps);
1072 }
1073 
getFlattenedSize() const1074 size_t IGraphicBufferProducer::QueueBufferInput::getFlattenedSize() const {
1075     return minFlattenedSize() +
1076             fence->getFlattenedSize() +
1077             surfaceDamage.getFlattenedSize() +
1078             hdrMetadata.getFlattenedSize();
1079 }
1080 
getFdCount() const1081 size_t IGraphicBufferProducer::QueueBufferInput::getFdCount() const {
1082     return fence->getFdCount();
1083 }
1084 
flatten(void * & buffer,size_t & size,int * & fds,size_t & count) const1085 status_t IGraphicBufferProducer::QueueBufferInput::flatten(
1086         void*& buffer, size_t& size, int*& fds, size_t& count) const
1087 {
1088     if (size < getFlattenedSize()) {
1089         return NO_MEMORY;
1090     }
1091 
1092     FlattenableUtils::write(buffer, size, timestamp);
1093     FlattenableUtils::write(buffer, size, isAutoTimestamp);
1094     FlattenableUtils::write(buffer, size, dataSpace);
1095     FlattenableUtils::write(buffer, size, crop);
1096     FlattenableUtils::write(buffer, size, scalingMode);
1097     FlattenableUtils::write(buffer, size, transform);
1098     FlattenableUtils::write(buffer, size, stickyTransform);
1099     FlattenableUtils::write(buffer, size, getFrameTimestamps);
1100 
1101     status_t result = fence->flatten(buffer, size, fds, count);
1102     if (result != NO_ERROR) {
1103         return result;
1104     }
1105     result = surfaceDamage.flatten(buffer, size);
1106     if (result != NO_ERROR) {
1107         return result;
1108     }
1109     FlattenableUtils::advance(buffer, size, surfaceDamage.getFlattenedSize());
1110     return hdrMetadata.flatten(buffer, size);
1111 }
1112 
unflatten(void const * & buffer,size_t & size,int const * & fds,size_t & count)1113 status_t IGraphicBufferProducer::QueueBufferInput::unflatten(
1114         void const*& buffer, size_t& size, int const*& fds, size_t& count)
1115 {
1116     if (size < minFlattenedSize()) {
1117         return NO_MEMORY;
1118     }
1119 
1120     FlattenableUtils::read(buffer, size, timestamp);
1121     FlattenableUtils::read(buffer, size, isAutoTimestamp);
1122     FlattenableUtils::read(buffer, size, dataSpace);
1123     FlattenableUtils::read(buffer, size, crop);
1124     FlattenableUtils::read(buffer, size, scalingMode);
1125     FlattenableUtils::read(buffer, size, transform);
1126     FlattenableUtils::read(buffer, size, stickyTransform);
1127     FlattenableUtils::read(buffer, size, getFrameTimestamps);
1128 
1129     fence = new Fence();
1130     status_t result = fence->unflatten(buffer, size, fds, count);
1131     if (result != NO_ERROR) {
1132         return result;
1133     }
1134     result = surfaceDamage.unflatten(buffer, size);
1135     if (result != NO_ERROR) {
1136         return result;
1137     }
1138     FlattenableUtils::advance(buffer, size, surfaceDamage.getFlattenedSize());
1139     return hdrMetadata.unflatten(buffer, size);
1140 }
1141 
1142 // ----------------------------------------------------------------------------
minFlattenedSize()1143 constexpr size_t IGraphicBufferProducer::QueueBufferOutput::minFlattenedSize() {
1144     return sizeof(width) +
1145             sizeof(height) +
1146             sizeof(transformHint) +
1147             sizeof(numPendingBuffers) +
1148             sizeof(nextFrameNumber) +
1149             sizeof(bufferReplaced);
1150 }
1151 
getFlattenedSize() const1152 size_t IGraphicBufferProducer::QueueBufferOutput::getFlattenedSize() const {
1153     return minFlattenedSize() + frameTimestamps.getFlattenedSize();
1154 }
1155 
getFdCount() const1156 size_t IGraphicBufferProducer::QueueBufferOutput::getFdCount() const {
1157     return frameTimestamps.getFdCount();
1158 }
1159 
flatten(void * & buffer,size_t & size,int * & fds,size_t & count) const1160 status_t IGraphicBufferProducer::QueueBufferOutput::flatten(
1161         void*& buffer, size_t& size, int*& fds, size_t& count) const
1162 {
1163     if (size < getFlattenedSize()) {
1164         return NO_MEMORY;
1165     }
1166 
1167     FlattenableUtils::write(buffer, size, width);
1168     FlattenableUtils::write(buffer, size, height);
1169     FlattenableUtils::write(buffer, size, transformHint);
1170     FlattenableUtils::write(buffer, size, numPendingBuffers);
1171     FlattenableUtils::write(buffer, size, nextFrameNumber);
1172     FlattenableUtils::write(buffer, size, bufferReplaced);
1173 
1174     return frameTimestamps.flatten(buffer, size, fds, count);
1175 }
1176 
unflatten(void const * & buffer,size_t & size,int const * & fds,size_t & count)1177 status_t IGraphicBufferProducer::QueueBufferOutput::unflatten(
1178         void const*& buffer, size_t& size, int const*& fds, size_t& count)
1179 {
1180     if (size < minFlattenedSize()) {
1181         return NO_MEMORY;
1182     }
1183 
1184     FlattenableUtils::read(buffer, size, width);
1185     FlattenableUtils::read(buffer, size, height);
1186     FlattenableUtils::read(buffer, size, transformHint);
1187     FlattenableUtils::read(buffer, size, numPendingBuffers);
1188     FlattenableUtils::read(buffer, size, nextFrameNumber);
1189     FlattenableUtils::read(buffer, size, bufferReplaced);
1190 
1191     return frameTimestamps.unflatten(buffer, size, fds, count);
1192 }
1193 
1194 }; // namespace android
1195