OSDN Git Service

Fix security vulnerability am: 2ae83f4f62
[android-x86/frameworks-native.git] / libs / gui / IGraphicBufferProducer.cpp
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     CONNECT,
41     DISCONNECT,
42 };
43
44 class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
45 {
46 public:
47     BpGraphicBufferProducer(const sp<IBinder>& impl)
48         : BpInterface<IGraphicBufferProducer>(impl)
49     {
50     }
51
52     virtual status_t requestBuffer(int bufferIdx, sp<GraphicBuffer>* buf) {
53         Parcel data, reply;
54         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
55         data.writeInt32(bufferIdx);
56         status_t result =remote()->transact(REQUEST_BUFFER, data, &reply);
57         if (result != NO_ERROR) {
58             return result;
59         }
60         bool nonNull = reply.readInt32();
61         if (nonNull) {
62             *buf = new GraphicBuffer();
63             result = reply.read(**buf);
64             if(result != NO_ERROR) {
65                 (*buf).clear();
66                 return result;
67             }
68         }
69         result = reply.readInt32();
70         return result;
71     }
72
73     virtual status_t setBufferCount(int bufferCount)
74     {
75         Parcel data, reply;
76         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
77         data.writeInt32(bufferCount);
78         status_t result =remote()->transact(SET_BUFFER_COUNT, data, &reply);
79         if (result != NO_ERROR) {
80             return result;
81         }
82         result = reply.readInt32();
83         return result;
84     }
85
86     virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, bool async,
87             uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
88         Parcel data, reply;
89         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
90         data.writeInt32(async);
91         data.writeInt32(w);
92         data.writeInt32(h);
93         data.writeInt32(format);
94         data.writeInt32(usage);
95         status_t result = remote()->transact(DEQUEUE_BUFFER, data, &reply);
96         if (result != NO_ERROR) {
97             return result;
98         }
99         *buf = reply.readInt32();
100         bool nonNull = reply.readInt32();
101         if (nonNull) {
102             *fence = new Fence();
103             reply.read(**fence);
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 connect(const sp<IBinder>& token,
146             int api, bool producerControlledByApp, QueueBufferOutput* output) {
147         Parcel data, reply;
148         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
149         data.writeStrongBinder(token);
150         data.writeInt32(api);
151         data.writeInt32(producerControlledByApp);
152         status_t result = remote()->transact(CONNECT, data, &reply);
153         if (result != NO_ERROR) {
154             return result;
155         }
156         memcpy(output, reply.readInplace(sizeof(*output)), sizeof(*output));
157         result = reply.readInt32();
158         return result;
159     }
160
161     virtual status_t disconnect(int api) {
162         Parcel data, reply;
163         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
164         data.writeInt32(api);
165         status_t result =remote()->transact(DISCONNECT, data, &reply);
166         if (result != NO_ERROR) {
167             return result;
168         }
169         result = reply.readInt32();
170         return result;
171     }
172 };
173
174 IMPLEMENT_META_INTERFACE(GraphicBufferProducer, "android.gui.IGraphicBufferProducer");
175
176 // ----------------------------------------------------------------------
177
178 status_t BnGraphicBufferProducer::onTransact(
179     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
180 {
181     switch(code) {
182         case REQUEST_BUFFER: {
183             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
184             int bufferIdx   = data.readInt32();
185             sp<GraphicBuffer> buffer;
186             int result = requestBuffer(bufferIdx, &buffer);
187             reply->writeInt32(buffer != 0);
188             if (buffer != 0) {
189                 reply->write(*buffer);
190             }
191             reply->writeInt32(result);
192             return NO_ERROR;
193         } break;
194         case SET_BUFFER_COUNT: {
195             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
196             int bufferCount = data.readInt32();
197             int result = setBufferCount(bufferCount);
198             reply->writeInt32(result);
199             return NO_ERROR;
200         } break;
201         case DEQUEUE_BUFFER: {
202             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
203             bool async      = data.readInt32();
204             uint32_t w      = data.readInt32();
205             uint32_t h      = data.readInt32();
206             uint32_t format = data.readInt32();
207             uint32_t usage  = data.readInt32();
208             int buf = 0;
209             sp<Fence> fence;
210             int result = dequeueBuffer(&buf, &fence, async, w, h, format, usage);
211             reply->writeInt32(buf);
212             reply->writeInt32(fence != NULL);
213             if (fence != NULL) {
214                 reply->write(*fence);
215             }
216             reply->writeInt32(result);
217             return NO_ERROR;
218         } break;
219         case QUEUE_BUFFER: {
220             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
221             int buf = data.readInt32();
222             QueueBufferInput input(data);
223             QueueBufferOutput* const output =
224                     reinterpret_cast<QueueBufferOutput *>(
225                             reply->writeInplace(sizeof(QueueBufferOutput)));
226             memset(output, 0, sizeof(QueueBufferOutput));
227             status_t result = queueBuffer(buf, input, output);
228             reply->writeInt32(result);
229             return NO_ERROR;
230         } break;
231         case CANCEL_BUFFER: {
232             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
233             int buf = data.readInt32();
234             sp<Fence> fence = new Fence();
235             data.read(*fence.get());
236             cancelBuffer(buf, fence);
237             return NO_ERROR;
238         } break;
239         case QUERY: {
240             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
241             int value = 0;
242             int what = data.readInt32();
243             int res = query(what, &value);
244             reply->writeInt32(value);
245             reply->writeInt32(res);
246             return NO_ERROR;
247         } break;
248         case CONNECT: {
249             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
250             sp<IBinder> token = data.readStrongBinder();
251             int api = data.readInt32();
252             bool producerControlledByApp = data.readInt32();
253             QueueBufferOutput* const output =
254                     reinterpret_cast<QueueBufferOutput *>(
255                             reply->writeInplace(sizeof(QueueBufferOutput)));
256             memset(output, 0, sizeof(QueueBufferOutput));
257             status_t res = connect(token, api, producerControlledByApp, output);
258             reply->writeInt32(res);
259             return NO_ERROR;
260         } break;
261         case DISCONNECT: {
262             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
263             int api = data.readInt32();
264             status_t res = disconnect(api);
265             reply->writeInt32(res);
266             return NO_ERROR;
267         } break;
268     }
269     return BBinder::onTransact(code, data, reply, flags);
270 }
271
272 // ----------------------------------------------------------------------------
273
274 IGraphicBufferProducer::QueueBufferInput::QueueBufferInput(const Parcel& parcel) {
275     parcel.read(*this);
276 }
277
278 size_t IGraphicBufferProducer::QueueBufferInput::getFlattenedSize() const {
279     return sizeof(timestamp)
280          + sizeof(isAutoTimestamp)
281          + sizeof(crop)
282          + sizeof(scalingMode)
283          + sizeof(transform)
284          + sizeof(async)
285          + fence->getFlattenedSize();
286 }
287
288 size_t IGraphicBufferProducer::QueueBufferInput::getFdCount() const {
289     return fence->getFdCount();
290 }
291
292 status_t IGraphicBufferProducer::QueueBufferInput::flatten(
293         void*& buffer, size_t& size, int*& fds, size_t& count) const
294 {
295     if (size < getFlattenedSize()) {
296         return NO_MEMORY;
297     }
298     FlattenableUtils::write(buffer, size, timestamp);
299     FlattenableUtils::write(buffer, size, isAutoTimestamp);
300     FlattenableUtils::write(buffer, size, crop);
301     FlattenableUtils::write(buffer, size, scalingMode);
302     FlattenableUtils::write(buffer, size, transform);
303     FlattenableUtils::write(buffer, size, async);
304     return fence->flatten(buffer, size, fds, count);
305 }
306
307 status_t IGraphicBufferProducer::QueueBufferInput::unflatten(
308         void const*& buffer, size_t& size, int const*& fds, size_t& count)
309 {
310     size_t minNeeded =
311               sizeof(timestamp)
312             + sizeof(isAutoTimestamp)
313             + sizeof(crop)
314             + sizeof(scalingMode)
315             + sizeof(transform)
316             + sizeof(async);
317
318     if (size < minNeeded) {
319         return NO_MEMORY;
320     }
321
322     FlattenableUtils::read(buffer, size, timestamp);
323     FlattenableUtils::read(buffer, size, isAutoTimestamp);
324     FlattenableUtils::read(buffer, size, crop);
325     FlattenableUtils::read(buffer, size, scalingMode);
326     FlattenableUtils::read(buffer, size, transform);
327     FlattenableUtils::read(buffer, size, async);
328
329     fence = new Fence();
330     return fence->unflatten(buffer, size, fds, count);
331 }
332
333 }; // namespace android