1 /*
2  * Copyright 2014 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 <binder/Parcel.h>
18 #include <gui/bufferqueue/1.0/H2BProducerListener.h>
19 #include <gui/bufferqueue/2.0/H2BProducerListener.h>
20 #include <gui/IProducerListener.h>
21 
22 namespace android {
23 
24 enum {
25     ON_BUFFER_RELEASED = IBinder::FIRST_CALL_TRANSACTION,
26     NEEDS_RELEASE_NOTIFY,
27     ON_BUFFERS_DISCARDED,
28 };
29 
30 class BpProducerListener : public BpInterface<IProducerListener>
31 {
32 public:
BpProducerListener(const sp<IBinder> & impl)33     explicit BpProducerListener(const sp<IBinder>& impl)
34         : BpInterface<IProducerListener>(impl) {}
35 
36     virtual ~BpProducerListener();
37 
onBufferReleased()38     virtual void onBufferReleased() {
39         Parcel data, reply;
40         data.writeInterfaceToken(IProducerListener::getInterfaceDescriptor());
41         remote()->transact(ON_BUFFER_RELEASED, data, &reply, IBinder::FLAG_ONEWAY);
42     }
43 
needsReleaseNotify()44     virtual bool needsReleaseNotify() {
45         bool result;
46         Parcel data, reply;
47         data.writeInterfaceToken(IProducerListener::getInterfaceDescriptor());
48         status_t err = remote()->transact(NEEDS_RELEASE_NOTIFY, data, &reply);
49         if (err != NO_ERROR) {
50             ALOGE("IProducerListener: binder call \'needsReleaseNotify\' failed");
51             return true;
52         }
53         err = reply.readBool(&result);
54         if (err != NO_ERROR) {
55             ALOGE("IProducerListener: malformed binder reply");
56             return true;
57         }
58         return result;
59     }
60 
onBuffersDiscarded(const std::vector<int> & discardedSlots)61     virtual void onBuffersDiscarded(const std::vector<int>& discardedSlots) {
62         Parcel data, reply;
63         data.writeInterfaceToken(IProducerListener::getInterfaceDescriptor());
64         data.writeInt32Vector(discardedSlots);
65         remote()->transact(ON_BUFFERS_DISCARDED, data, &reply, IBinder::FLAG_ONEWAY);
66     }
67 };
68 
69 // Out-of-line virtual method definition to trigger vtable emission in this
70 // translation unit (see clang warning -Wweak-vtables)
~BpProducerListener()71 BpProducerListener::~BpProducerListener() {}
72 
73 class HpProducerListener : public HpInterface<
74         BpProducerListener,
75         hardware::graphics::bufferqueue::V1_0::utils::H2BProducerListener,
76         hardware::graphics::bufferqueue::V2_0::utils::H2BProducerListener> {
77 public:
HpProducerListener(const sp<IBinder> & base)78     explicit HpProducerListener(const sp<IBinder>& base) : PBase{base} {}
79 
onBufferReleased()80     virtual void onBufferReleased() override {
81         mBase->onBufferReleased();
82     }
83 
needsReleaseNotify()84     virtual bool needsReleaseNotify() override {
85         return mBase->needsReleaseNotify();
86     }
87 
onBuffersDiscarded(const std::vector<int32_t> & discardedSlots)88     virtual void onBuffersDiscarded(const std::vector<int32_t>& discardedSlots) override {
89         return mBase->onBuffersDiscarded(discardedSlots);
90     }
91 };
92 
93 IMPLEMENT_HYBRID_META_INTERFACE(ProducerListener,
94         "android.gui.IProducerListener")
95 
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)96 status_t BnProducerListener::onTransact(uint32_t code, const Parcel& data,
97         Parcel* reply, uint32_t flags) {
98     switch (code) {
99         case ON_BUFFER_RELEASED:
100             CHECK_INTERFACE(IProducerListener, data, reply);
101             onBufferReleased();
102             return NO_ERROR;
103         case NEEDS_RELEASE_NOTIFY:
104             CHECK_INTERFACE(IProducerListener, data, reply);
105             reply->writeBool(needsReleaseNotify());
106             return NO_ERROR;
107         case ON_BUFFERS_DISCARDED: {
108             CHECK_INTERFACE(IProducerListener, data, reply);
109             std::vector<int32_t> discardedSlots;
110             status_t result = data.readInt32Vector(&discardedSlots);
111             if (result != NO_ERROR) {
112                 ALOGE("ON_BUFFERS_DISCARDED failed to read discardedSlots: %d", result);
113                 return result;
114             }
115             onBuffersDiscarded(discardedSlots);
116             return NO_ERROR;
117         }
118     }
119     return BBinder::onTransact(code, data, reply, flags);
120 }
121 
122 StubProducerListener::~StubProducerListener() = default;
123 
needsReleaseNotify()124 bool BnProducerListener::needsReleaseNotify() {
125     return true;
126 }
127 
onBuffersDiscarded(const std::vector<int32_t> &)128 void BnProducerListener::onBuffersDiscarded(const std::vector<int32_t>& /*discardedSlots*/) {
129 }
130 
131 } // namespace android
132