IProCameraUser.cpp revision 7b33a74bbc514b99c16be7fff9a34e892bc19264
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    GET_CAMERA_INFO,
48};
49
50/**
51  * Caller becomes the owner of the new metadata
52  * 'const Parcel' doesnt prevent us from calling the read functions.
53  *  which is interesting since it changes the internal state
54  */
55void readMetadata(const Parcel& data, camera_metadata_t** out) {
56    camera_metadata_t* metadata;
57
58    // arg0 = metadataSize (int32)
59    size_t metadataSize = static_cast<size_t>(data.readInt32());
60
61    if (metadataSize == 0) {
62        if (out) {
63            *out = NULL;
64        }
65        return;
66    }
67
68    // NOTE: this doesn't make sense to me. shouldnt the blob
69    // know how big it is? why do we have to specify the size
70    // to Parcel::readBlob ?
71
72    ReadableBlob blob;
73    // arg1 = metadata (blob)
74    {
75        data.readBlob(metadataSize, &blob);
76        const camera_metadata_t* tmp =
77                       reinterpret_cast<const camera_metadata_t*>(blob.data());
78        size_t entry_capacity = get_camera_metadata_entry_capacity(tmp);
79        size_t data_capacity = get_camera_metadata_data_capacity(tmp);
80
81        metadata = allocate_camera_metadata(entry_capacity, data_capacity);
82        copy_camera_metadata(metadata, metadataSize, tmp);
83    }
84    blob.release();
85
86    if (out) {
87        *out = metadata;
88    } else {
89        free_camera_metadata(metadata);
90    }
91}
92
93/**
94  * Caller retains ownership of metadata
95  * - Write 2 (int32 + blob) args in the current position
96  */
97void writeMetadata(Parcel& data, camera_metadata_t* metadata) {
98    // arg0 = metadataSize (int32)
99    size_t metadataSize;
100
101    if (metadata == NULL) {
102        data.writeInt32(0);
103        return;
104    }
105
106    metadataSize = get_camera_metadata_compact_size(metadata);
107    data.writeInt32(static_cast<int32_t>(metadataSize));
108
109    // arg1 = metadata (blob)
110    WritableBlob blob;
111    {
112        data.writeBlob(metadataSize, &blob);
113        copy_camera_metadata(blob.data(), metadataSize, metadata);
114    }
115    blob.release();
116}
117
118class BpProCameraUser: public BpInterface<IProCameraUser>
119{
120public:
121    BpProCameraUser(const sp<IBinder>& impl)
122        : BpInterface<IProCameraUser>(impl)
123    {
124    }
125
126    // disconnect from camera service
127    void disconnect()
128    {
129        ALOGV("disconnect");
130        Parcel data, reply;
131        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
132        remote()->transact(DISCONNECT, data, &reply);
133    }
134
135    virtual status_t connect(const sp<IProCameraCallbacks>& cameraClient)
136    {
137        Parcel data, reply;
138        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
139        data.writeStrongBinder(cameraClient->asBinder());
140        remote()->transact(CONNECT, data, &reply);
141        return reply.readInt32();
142    }
143
144    /* Shared ProCameraUser */
145
146    virtual status_t exclusiveTryLock()
147    {
148        Parcel data, reply;
149        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
150        remote()->transact(EXCLUSIVE_TRY_LOCK, data, &reply);
151        return reply.readInt32();
152    }
153    virtual status_t exclusiveLock()
154    {
155        Parcel data, reply;
156        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
157        remote()->transact(EXCLUSIVE_LOCK, data, &reply);
158        return reply.readInt32();
159    }
160
161    virtual status_t exclusiveUnlock()
162    {
163        Parcel data, reply;
164        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
165        remote()->transact(EXCLUSIVE_UNLOCK, data, &reply);
166        return reply.readInt32();
167    }
168
169    virtual bool hasExclusiveLock()
170    {
171        Parcel data, reply;
172        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
173        remote()->transact(HAS_EXCLUSIVE_LOCK, data, &reply);
174        return !!reply.readInt32();
175    }
176
177    virtual int submitRequest(camera_metadata_t* metadata, bool streaming)
178    {
179
180        Parcel data, reply;
181        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
182
183        // arg0+arg1
184        writeMetadata(data, metadata);
185
186        // arg2 = streaming (bool)
187        data.writeInt32(streaming);
188
189        remote()->transact(SUBMIT_REQUEST, data, &reply);
190        return reply.readInt32();
191    }
192
193    virtual status_t cancelRequest(int requestId)
194    {
195        Parcel data, reply;
196        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
197        data.writeInt32(requestId);
198
199        remote()->transact(CANCEL_REQUEST, data, &reply);
200        return reply.readInt32();
201    }
202
203    virtual status_t requestStream(int streamId)
204    {
205        Parcel data, reply;
206        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
207        data.writeInt32(streamId);
208
209        remote()->transact(REQUEST_STREAM, data, &reply);
210        return reply.readInt32();
211    }
212    virtual status_t cancelStream(int streamId)
213    {
214        Parcel data, reply;
215        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
216        data.writeInt32(streamId);
217
218        remote()->transact(CANCEL_STREAM, data, &reply);
219        return reply.readInt32();
220    }
221
222    virtual status_t createStream(int width, int height, int format,
223                          const sp<IGraphicBufferProducer>& bufferProducer,
224                          /*out*/
225                          int* streamId)
226    {
227        Parcel data, reply;
228        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
229        data.writeInt32(width);
230        data.writeInt32(height);
231        data.writeInt32(format);
232
233        sp<IBinder> b(bufferProducer->asBinder());
234        data.writeStrongBinder(b);
235
236        remote()->transact(CREATE_STREAM, data, &reply);
237
238        int sId = reply.readInt32();
239        if (streamId) {
240            *streamId = sId;
241        }
242        return reply.readInt32();
243    }
244
245    // Create a request object from a template.
246    virtual status_t createDefaultRequest(int templateId,
247                                 /*out*/
248                                  camera_metadata** request)
249    {
250        Parcel data, reply;
251        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
252        data.writeInt32(templateId);
253        remote()->transact(CREATE_DEFAULT_REQUEST, data, &reply);
254        readMetadata(reply, /*out*/request);
255        return reply.readInt32();
256    }
257
258
259    virtual status_t getCameraInfo(int cameraId, camera_metadata** info)
260    {
261        Parcel data, reply;
262        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
263        data.writeInt32(cameraId);
264        remote()->transact(GET_CAMERA_INFO, data, &reply);
265        readMetadata(reply, /*out*/info);
266        return reply.readInt32();
267    }
268
269
270private:
271
272
273};
274
275IMPLEMENT_META_INTERFACE(ProCameraUser, "android.hardware.IProCameraUser");
276
277// ----------------------------------------------------------------------
278
279status_t BnProCameraUser::onTransact(
280    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
281{
282    switch(code) {
283        case DISCONNECT: {
284            ALOGV("DISCONNECT");
285            CHECK_INTERFACE(IProCameraUser, data, reply);
286            disconnect();
287            return NO_ERROR;
288        } break;
289        case CONNECT: {
290            CHECK_INTERFACE(IProCameraUser, data, reply);
291            sp<IProCameraCallbacks> cameraClient =
292                   interface_cast<IProCameraCallbacks>(data.readStrongBinder());
293            reply->writeInt32(connect(cameraClient));
294            return NO_ERROR;
295        } break;
296
297        /* Shared ProCameraUser */
298        case EXCLUSIVE_TRY_LOCK: {
299            CHECK_INTERFACE(IProCameraUser, data, reply);
300            reply->writeInt32(exclusiveTryLock());
301            return NO_ERROR;
302        } break;
303        case EXCLUSIVE_LOCK: {
304            CHECK_INTERFACE(IProCameraUser, data, reply);
305            reply->writeInt32(exclusiveLock());
306            return NO_ERROR;
307        } break;
308        case EXCLUSIVE_UNLOCK: {
309            CHECK_INTERFACE(IProCameraUser, data, reply);
310            reply->writeInt32(exclusiveUnlock());
311            return NO_ERROR;
312        } break;
313        case HAS_EXCLUSIVE_LOCK: {
314            CHECK_INTERFACE(IProCameraUser, data, reply);
315            reply->writeInt32(hasExclusiveLock());
316            return NO_ERROR;
317        } break;
318        case SUBMIT_REQUEST: {
319            CHECK_INTERFACE(IProCameraUser, data, reply);
320            camera_metadata_t* metadata;
321            readMetadata(data, /*out*/&metadata);
322
323            // arg2 = streaming (bool)
324            bool streaming = data.readInt32();
325
326            // return code: requestId (int32)
327            reply->writeInt32(submitRequest(metadata, streaming));
328
329            return NO_ERROR;
330        } break;
331        case CANCEL_REQUEST: {
332            CHECK_INTERFACE(IProCameraUser, data, reply);
333            int requestId = data.readInt32();
334            reply->writeInt32(cancelRequest(requestId));
335            return NO_ERROR;
336        } break;
337        case REQUEST_STREAM: {
338            CHECK_INTERFACE(IProCameraUser, data, reply);
339            int streamId = data.readInt32();
340            reply->writeInt32(requestStream(streamId));
341            return NO_ERROR;
342        } break;
343        case CANCEL_STREAM: {
344            CHECK_INTERFACE(IProCameraUser, data, reply);
345            int streamId = data.readInt32();
346            reply->writeInt32(cancelStream(streamId));
347            return NO_ERROR;
348        } break;
349        case CREATE_STREAM: {
350            CHECK_INTERFACE(IProCameraUser, data, reply);
351            int width, height, format;
352
353            width = data.readInt32();
354            height = data.readInt32();
355            format = data.readInt32();
356
357            sp<IGraphicBufferProducer> bp =
358               interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
359
360            int streamId = -1;
361            status_t ret;
362            ret = createStream(width, height, format, bp, &streamId);
363
364            reply->writeInt32(streamId);
365            reply->writeInt32(ret);
366
367            return NO_ERROR;
368        } break;
369
370        case CREATE_DEFAULT_REQUEST: {
371            CHECK_INTERFACE(IProCameraUser, data, reply);
372
373            int templateId = data.readInt32();
374
375            camera_metadata_t* request = NULL;
376            status_t ret;
377            ret = createDefaultRequest(templateId, &request);
378
379            writeMetadata(*reply, request);
380            reply->writeInt32(ret);
381
382            free_camera_metadata(request);
383
384            return NO_ERROR;
385        } break;
386        case GET_CAMERA_INFO: {
387            CHECK_INTERFACE(IProCameraUser, data, reply);
388
389            int cameraId = data.readInt32();
390
391            camera_metadata_t* info = NULL;
392            status_t ret;
393            ret = getCameraInfo(cameraId, &info);
394
395            writeMetadata(*reply, info);
396            reply->writeInt32(ret);
397
398            free_camera_metadata(info);
399
400            return NO_ERROR;
401        } break;
402        default:
403            return BBinder::onTransact(code, data, reply, flags);
404    }
405}
406
407// ----------------------------------------------------------------------------
408
409}; // namespace android
410