IProCameraUser.cpp revision 76f8b43909817179b317880202360863b8f976d0
1/*
2**
3** Copyright 2013, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9**     http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18//#define LOG_NDEBUG 0
19#define LOG_TAG "IProCameraUser"
20#include <utils/Log.h>
21#include <stdint.h>
22#include <sys/types.h>
23#include <binder/Parcel.h>
24#include <camera/IProCameraUser.h>
25#include <gui/IGraphicBufferProducer.h>
26#include <gui/Surface.h>
27#include <system/camera_metadata.h>
28
29namespace android {
30
31typedef Parcel::WritableBlob WritableBlob;
32typedef Parcel::ReadableBlob ReadableBlob;
33
34enum {
35    DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
36    CONNECT,
37    EXCLUSIVE_TRY_LOCK,
38    EXCLUSIVE_LOCK,
39    EXCLUSIVE_UNLOCK,
40    HAS_EXCLUSIVE_LOCK,
41    SUBMIT_REQUEST,
42    CANCEL_REQUEST,
43    REQUEST_STREAM,
44    CANCEL_STREAM,
45    CREATE_STREAM,
46    CREATE_DEFAULT_REQUEST,
47};
48
49/**
50  * Caller becomes the owner of the new metadata
51  * 'const Parcel' doesnt prevent us from calling the read functions.
52  *  which is interesting since it changes the internal state
53  */
54void readMetadata(const Parcel& data, camera_metadata_t** out) {
55    camera_metadata_t* metadata;
56
57    // arg0 = metadataSize (int32)
58    size_t metadataSize = static_cast<size_t>(data.readInt32());
59
60    if (metadataSize == 0) {
61        if (out) {
62            *out = NULL;
63        }
64        return;
65    }
66
67    // NOTE: this doesn't make sense to me. shouldnt the blob
68    // know how big it is? why do we have to specify the size
69    // to Parcel::readBlob ?
70
71    ReadableBlob blob;
72    // arg1 = metadata (blob)
73    {
74        data.readBlob(metadataSize, &blob);
75        const camera_metadata_t* tmp =
76                       reinterpret_cast<const camera_metadata_t*>(blob.data());
77        size_t entry_capacity = get_camera_metadata_entry_capacity(tmp);
78        size_t data_capacity = get_camera_metadata_data_capacity(tmp);
79
80        metadata = allocate_camera_metadata(entry_capacity, data_capacity);
81        copy_camera_metadata(metadata, metadataSize, tmp);
82    }
83    blob.release();
84
85    if (out) {
86        *out = metadata;
87    } else {
88        free_camera_metadata(metadata);
89    }
90}
91
92/**
93  * Caller retains ownership of metadata
94  * - Write 2 (int32 + blob) args in the current position
95  */
96void writeMetadata(Parcel& data, camera_metadata_t* metadata) {
97    // arg0 = metadataSize (int32)
98    size_t metadataSize;
99
100    if (metadata == NULL) {
101        data.writeInt32(0);
102        return;
103    }
104
105    metadataSize = get_camera_metadata_compact_size(metadata);
106    data.writeInt32(static_cast<int32_t>(metadataSize));
107
108    // arg1 = metadata (blob)
109    WritableBlob blob;
110    {
111        data.writeBlob(metadataSize, &blob);
112        copy_camera_metadata(blob.data(), metadataSize, metadata);
113    }
114    blob.release();
115}
116
117class BpProCameraUser: public BpInterface<IProCameraUser>
118{
119public:
120    BpProCameraUser(const sp<IBinder>& impl)
121        : BpInterface<IProCameraUser>(impl)
122    {
123    }
124
125    // disconnect from camera service
126    void disconnect()
127    {
128        ALOGV("disconnect");
129        Parcel data, reply;
130        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
131        remote()->transact(DISCONNECT, data, &reply);
132    }
133
134    virtual status_t connect(const sp<IProCameraCallbacks>& cameraClient)
135    {
136        Parcel data, reply;
137        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
138        data.writeStrongBinder(cameraClient->asBinder());
139        remote()->transact(CONNECT, data, &reply);
140        return reply.readInt32();
141    }
142
143    /* Shared ProCameraUser */
144
145    virtual status_t exclusiveTryLock()
146    {
147        Parcel data, reply;
148        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
149        remote()->transact(EXCLUSIVE_TRY_LOCK, data, &reply);
150        return reply.readInt32();
151    }
152    virtual status_t exclusiveLock()
153    {
154        Parcel data, reply;
155        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
156        remote()->transact(EXCLUSIVE_LOCK, data, &reply);
157        return reply.readInt32();
158    }
159
160    virtual status_t exclusiveUnlock()
161    {
162        Parcel data, reply;
163        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
164        remote()->transact(EXCLUSIVE_UNLOCK, data, &reply);
165        return reply.readInt32();
166    }
167
168    virtual bool hasExclusiveLock()
169    {
170        Parcel data, reply;
171        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
172        remote()->transact(HAS_EXCLUSIVE_LOCK, data, &reply);
173        return !!reply.readInt32();
174    }
175
176    virtual int submitRequest(camera_metadata_t* metadata, bool streaming)
177    {
178
179        Parcel data, reply;
180        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
181
182        // arg0+arg1
183        writeMetadata(data, metadata);
184
185        // arg2 = streaming (bool)
186        data.writeInt32(streaming);
187
188        remote()->transact(SUBMIT_REQUEST, data, &reply);
189        return reply.readInt32();
190    }
191
192    virtual status_t cancelRequest(int requestId)
193    {
194        Parcel data, reply;
195        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
196        data.writeInt32(requestId);
197
198        remote()->transact(CANCEL_REQUEST, data, &reply);
199        return reply.readInt32();
200    }
201
202    virtual status_t requestStream(int streamId)
203    {
204        Parcel data, reply;
205        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
206        data.writeInt32(streamId);
207
208        remote()->transact(REQUEST_STREAM, data, &reply);
209        return reply.readInt32();
210    }
211    virtual status_t cancelStream(int streamId)
212    {
213        Parcel data, reply;
214        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
215        data.writeInt32(streamId);
216
217        remote()->transact(CANCEL_STREAM, data, &reply);
218        return reply.readInt32();
219    }
220
221    virtual status_t createStream(int width, int height, int format,
222                          const sp<IGraphicBufferProducer>& bufferProducer,
223                          /*out*/
224                          int* streamId)
225    {
226        Parcel data, reply;
227        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
228        data.writeInt32(width);
229        data.writeInt32(height);
230        data.writeInt32(format);
231
232        sp<IBinder> b(bufferProducer->asBinder());
233        data.writeStrongBinder(b);
234
235        remote()->transact(CREATE_STREAM, data, &reply);
236
237        int sId = reply.readInt32();
238        if (streamId) {
239            *streamId = sId;
240        }
241        return reply.readInt32();
242    }
243
244    // Create a request object from a template.
245    virtual status_t createDefaultRequest(int templateId,
246                                 /*out*/
247                                  camera_metadata** request)
248    {
249        Parcel data, reply;
250        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
251        data.writeInt32(templateId);
252        remote()->transact(CREATE_DEFAULT_REQUEST, data, &reply);
253        readMetadata(reply, /*out*/request);
254        return reply.readInt32();
255    }
256
257
258private:
259
260
261};
262
263IMPLEMENT_META_INTERFACE(ProCameraUser, "android.hardware.IProCameraUser");
264
265// ----------------------------------------------------------------------
266
267status_t BnProCameraUser::onTransact(
268    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
269{
270    switch(code) {
271        case DISCONNECT: {
272            ALOGV("DISCONNECT");
273            CHECK_INTERFACE(IProCameraUser, data, reply);
274            disconnect();
275            return NO_ERROR;
276        } break;
277        case CONNECT: {
278            CHECK_INTERFACE(IProCameraUser, data, reply);
279            sp<IProCameraCallbacks> cameraClient =
280                   interface_cast<IProCameraCallbacks>(data.readStrongBinder());
281            reply->writeInt32(connect(cameraClient));
282            return NO_ERROR;
283        } break;
284
285        /* Shared ProCameraUser */
286        case EXCLUSIVE_TRY_LOCK: {
287            CHECK_INTERFACE(IProCameraUser, data, reply);
288            reply->writeInt32(exclusiveTryLock());
289            return NO_ERROR;
290        } break;
291        case EXCLUSIVE_LOCK: {
292            CHECK_INTERFACE(IProCameraUser, data, reply);
293            reply->writeInt32(exclusiveLock());
294            return NO_ERROR;
295        } break;
296        case EXCLUSIVE_UNLOCK: {
297            CHECK_INTERFACE(IProCameraUser, data, reply);
298            reply->writeInt32(exclusiveUnlock());
299            return NO_ERROR;
300        } break;
301        case HAS_EXCLUSIVE_LOCK: {
302            CHECK_INTERFACE(IProCameraUser, data, reply);
303            reply->writeInt32(hasExclusiveLock());
304            return NO_ERROR;
305        } break;
306        case SUBMIT_REQUEST: {
307            CHECK_INTERFACE(IProCameraUser, data, reply);
308            camera_metadata_t* metadata;
309            readMetadata(data, /*out*/&metadata);
310
311            // arg2 = streaming (bool)
312            bool streaming = data.readInt32();
313
314            // return code: requestId (int32)
315            reply->writeInt32(submitRequest(metadata, streaming));
316
317            return NO_ERROR;
318        } break;
319        case CANCEL_REQUEST: {
320            CHECK_INTERFACE(IProCameraUser, data, reply);
321            int requestId = data.readInt32();
322            reply->writeInt32(cancelRequest(requestId));
323            return NO_ERROR;
324        } break;
325        case REQUEST_STREAM: {
326            CHECK_INTERFACE(IProCameraUser, data, reply);
327            int streamId = data.readInt32();
328            reply->writeInt32(requestStream(streamId));
329            return NO_ERROR;
330        } break;
331        case CANCEL_STREAM: {
332            CHECK_INTERFACE(IProCameraUser, data, reply);
333            int streamId = data.readInt32();
334            reply->writeInt32(cancelStream(streamId));
335            return NO_ERROR;
336        } break;
337        case CREATE_STREAM: {
338            CHECK_INTERFACE(IProCameraUser, data, reply);
339            int width, height, format;
340
341            width = data.readInt32();
342            height = data.readInt32();
343            format = data.readInt32();
344
345            sp<IGraphicBufferProducer> bp =
346               interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
347
348            int streamId = -1;
349            status_t ret;
350            ret = createStream(width, height, format, bp, &streamId);
351
352            reply->writeInt32(streamId);
353            reply->writeInt32(ret);
354
355            return NO_ERROR;
356        } break;
357
358        case CREATE_DEFAULT_REQUEST: {
359            CHECK_INTERFACE(IProCameraUser, data, reply);
360
361            int templateId = data.readInt32();
362
363            camera_metadata_t* request = NULL;
364            status_t ret;
365            ret = createDefaultRequest(templateId, &request);
366
367            writeMetadata(*reply, request);
368            reply->writeInt32(ret);
369
370            return NO_ERROR;
371        } break;
372        default:
373            return BBinder::onTransact(code, data, reply, flags);
374    }
375}
376
377// ----------------------------------------------------------------------------
378
379}; // namespace android
380