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/ISurfaceTexture.h>
29
30namespace android {
31// ----------------------------------------------------------------------------
32
33enum {
34    REQUEST_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
35    SET_BUFFER_COUNT,
36    DEQUEUE_BUFFER,
37    QUEUE_BUFFER,
38    CANCEL_BUFFER,
39    SET_CROP,
40    SET_TRANSFORM,
41    QUERY,
42    SET_SYNCHRONOUS_MODE,
43    CONNECT,
44    DISCONNECT,
45    SET_SCALING_MODE,
46};
47
48
49class BpSurfaceTexture : public BpInterface<ISurfaceTexture>
50{
51public:
52    BpSurfaceTexture(const sp<IBinder>& impl)
53        : BpInterface<ISurfaceTexture>(impl)
54    {
55    }
56
57    virtual status_t requestBuffer(int bufferIdx, sp<GraphicBuffer>* buf) {
58        Parcel data, reply;
59        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
60        data.writeInt32(bufferIdx);
61        status_t result =remote()->transact(REQUEST_BUFFER, data, &reply);
62        if (result != NO_ERROR) {
63            return result;
64        }
65        bool nonNull = reply.readInt32();
66        if (nonNull) {
67            *buf = new GraphicBuffer();
68            reply.read(**buf);
69        }
70        result = reply.readInt32();
71        return result;
72    }
73
74    virtual status_t setBufferCount(int bufferCount)
75    {
76        Parcel data, reply;
77        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
78        data.writeInt32(bufferCount);
79        status_t result =remote()->transact(SET_BUFFER_COUNT, data, &reply);
80        if (result != NO_ERROR) {
81            return result;
82        }
83        result = reply.readInt32();
84        return result;
85    }
86
87    virtual status_t dequeueBuffer(int *buf, uint32_t w, uint32_t h,
88            uint32_t format, uint32_t usage) {
89        Parcel data, reply;
90        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
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        result = reply.readInt32();
101        return result;
102    }
103
104    virtual status_t queueBuffer(int buf, int64_t timestamp,
105            uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
106        Parcel data, reply;
107        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
108        data.writeInt32(buf);
109        data.writeInt64(timestamp);
110        status_t result = remote()->transact(QUEUE_BUFFER, data, &reply);
111        if (result != NO_ERROR) {
112            return result;
113        }
114        *outWidth = reply.readInt32();
115        *outHeight = reply.readInt32();
116        *outTransform = reply.readInt32();
117        result = reply.readInt32();
118        return result;
119    }
120
121    virtual void cancelBuffer(int buf) {
122        Parcel data, reply;
123        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
124        data.writeInt32(buf);
125        remote()->transact(CANCEL_BUFFER, data, &reply);
126    }
127
128    virtual status_t setCrop(const Rect& reg) {
129        Parcel data, reply;
130        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
131        data.writeFloat(reg.left);
132        data.writeFloat(reg.top);
133        data.writeFloat(reg.right);
134        data.writeFloat(reg.bottom);
135        status_t result = remote()->transact(SET_CROP, data, &reply);
136        if (result != NO_ERROR) {
137            return result;
138        }
139        result = reply.readInt32();
140        return result;
141    }
142
143    virtual status_t setTransform(uint32_t transform) {
144        Parcel data, reply;
145        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
146        data.writeInt32(transform);
147        status_t result = remote()->transact(SET_TRANSFORM, data, &reply);
148        if (result != NO_ERROR) {
149            return result;
150        }
151        result = reply.readInt32();
152        return result;
153    }
154
155    virtual status_t setScalingMode(int mode) {
156        Parcel data, reply;
157        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
158        data.writeInt32(mode);
159        status_t result = remote()->transact(SET_SCALING_MODE, data, &reply);
160        if (result != NO_ERROR) {
161            return result;
162        }
163        result = reply.readInt32();
164        return result;
165    }
166
167    virtual int query(int what, int* value) {
168        Parcel data, reply;
169        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
170        data.writeInt32(what);
171        status_t result = remote()->transact(QUERY, data, &reply);
172        if (result != NO_ERROR) {
173            return result;
174        }
175        value[0] = reply.readInt32();
176        result = reply.readInt32();
177        return result;
178    }
179
180    virtual status_t setSynchronousMode(bool enabled) {
181        Parcel data, reply;
182        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
183        data.writeInt32(enabled);
184        status_t result = remote()->transact(SET_SYNCHRONOUS_MODE, data, &reply);
185        if (result != NO_ERROR) {
186            return result;
187        }
188        result = reply.readInt32();
189        return result;
190    }
191
192    virtual status_t connect(int api,
193            uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
194        Parcel data, reply;
195        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
196        data.writeInt32(api);
197        status_t result = remote()->transact(CONNECT, data, &reply);
198        if (result != NO_ERROR) {
199            return result;
200        }
201        *outWidth = reply.readInt32();
202        *outHeight = reply.readInt32();
203        *outTransform = reply.readInt32();
204        result = reply.readInt32();
205        return result;
206    }
207
208    virtual status_t disconnect(int api) {
209        Parcel data, reply;
210        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
211        data.writeInt32(api);
212        status_t result =remote()->transact(DISCONNECT, data, &reply);
213        if (result != NO_ERROR) {
214            return result;
215        }
216        result = reply.readInt32();
217        return result;
218    }
219};
220
221IMPLEMENT_META_INTERFACE(SurfaceTexture, "android.gui.SurfaceTexture");
222
223// ----------------------------------------------------------------------
224
225status_t BnSurfaceTexture::onTransact(
226    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
227{
228    switch(code) {
229        case REQUEST_BUFFER: {
230            CHECK_INTERFACE(ISurfaceTexture, data, reply);
231            int bufferIdx   = data.readInt32();
232            sp<GraphicBuffer> buffer;
233            int result = requestBuffer(bufferIdx, &buffer);
234            reply->writeInt32(buffer != 0);
235            if (buffer != 0) {
236                reply->write(*buffer);
237            }
238            reply->writeInt32(result);
239            return NO_ERROR;
240        } break;
241        case SET_BUFFER_COUNT: {
242            CHECK_INTERFACE(ISurfaceTexture, data, reply);
243            int bufferCount = data.readInt32();
244            int result = setBufferCount(bufferCount);
245            reply->writeInt32(result);
246            return NO_ERROR;
247        } break;
248        case DEQUEUE_BUFFER: {
249            CHECK_INTERFACE(ISurfaceTexture, data, reply);
250            uint32_t w      = data.readInt32();
251            uint32_t h      = data.readInt32();
252            uint32_t format = data.readInt32();
253            uint32_t usage  = data.readInt32();
254            int buf;
255            int result = dequeueBuffer(&buf, w, h, format, usage);
256            reply->writeInt32(buf);
257            reply->writeInt32(result);
258            return NO_ERROR;
259        } break;
260        case QUEUE_BUFFER: {
261            CHECK_INTERFACE(ISurfaceTexture, data, reply);
262            int buf = data.readInt32();
263            int64_t timestamp = data.readInt64();
264            uint32_t outWidth, outHeight, outTransform;
265            status_t result = queueBuffer(buf, timestamp,
266                    &outWidth, &outHeight, &outTransform);
267            reply->writeInt32(outWidth);
268            reply->writeInt32(outHeight);
269            reply->writeInt32(outTransform);
270            reply->writeInt32(result);
271            return NO_ERROR;
272        } break;
273        case CANCEL_BUFFER: {
274            CHECK_INTERFACE(ISurfaceTexture, data, reply);
275            int buf = data.readInt32();
276            cancelBuffer(buf);
277            return NO_ERROR;
278        } break;
279        case SET_CROP: {
280            Rect reg;
281            CHECK_INTERFACE(ISurfaceTexture, data, reply);
282            reg.left = data.readFloat();
283            reg.top = data.readFloat();
284            reg.right = data.readFloat();
285            reg.bottom = data.readFloat();
286            status_t result = setCrop(reg);
287            reply->writeInt32(result);
288            return NO_ERROR;
289        } break;
290        case SET_TRANSFORM: {
291            CHECK_INTERFACE(ISurfaceTexture, data, reply);
292            uint32_t transform = data.readInt32();
293            status_t result = setTransform(transform);
294            reply->writeInt32(result);
295            return NO_ERROR;
296        } break;
297        case SET_SCALING_MODE: {
298            CHECK_INTERFACE(ISurfaceTexture, data, reply);
299            int mode = data.readInt32();
300            status_t result = setScalingMode(mode);
301            reply->writeInt32(result);
302            return NO_ERROR;
303        } break;
304        case QUERY: {
305            CHECK_INTERFACE(ISurfaceTexture, data, reply);
306            int value;
307            int what = data.readInt32();
308            int res = query(what, &value);
309            reply->writeInt32(value);
310            reply->writeInt32(res);
311            return NO_ERROR;
312        } break;
313        case SET_SYNCHRONOUS_MODE: {
314            CHECK_INTERFACE(ISurfaceTexture, data, reply);
315            bool enabled = data.readInt32();
316            status_t res = setSynchronousMode(enabled);
317            reply->writeInt32(res);
318            return NO_ERROR;
319        } break;
320        case CONNECT: {
321            CHECK_INTERFACE(ISurfaceTexture, data, reply);
322            int api = data.readInt32();
323            uint32_t outWidth, outHeight, outTransform;
324            status_t res = connect(api,
325                    &outWidth, &outHeight, &outTransform);
326            reply->writeInt32(outWidth);
327            reply->writeInt32(outHeight);
328            reply->writeInt32(outTransform);
329            reply->writeInt32(res);
330            return NO_ERROR;
331        } break;
332        case DISCONNECT: {
333            CHECK_INTERFACE(ISurfaceTexture, data, reply);
334            int api = data.readInt32();
335            status_t res = disconnect(api);
336            reply->writeInt32(res);
337            return NO_ERROR;
338        } break;
339    }
340    return BBinder::onTransact(code, data, reply, flags);
341}
342
343// ----------------------------------------------------------------------------
344
345}; // namespace android
346