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