IProCameraUser.cpp revision 7cf9a7e7d19579565e0f9dba8be9c107f2dbf548
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  */
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 deleteStream(int streamId)
203    {
204        Parcel data, reply;
205        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
206        data.writeInt32(streamId);
207
208        remote()->transact(DELETE_STREAM, data, &reply);
209        return reply.readInt32();
210    }
211
212    virtual status_t createStream(int width, int height, int format,
213                          const sp<IGraphicBufferProducer>& bufferProducer,
214                          /*out*/
215                          int* streamId)
216    {
217        Parcel data, reply;
218        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
219        data.writeInt32(width);
220        data.writeInt32(height);
221        data.writeInt32(format);
222
223        sp<IBinder> b(bufferProducer->asBinder());
224        data.writeStrongBinder(b);
225
226        remote()->transact(CREATE_STREAM, data, &reply);
227
228        int sId = reply.readInt32();
229        if (streamId) {
230            *streamId = sId;
231        }
232        return reply.readInt32();
233    }
234
235    // Create a request object from a template.
236    virtual status_t createDefaultRequest(int templateId,
237                                 /*out*/
238                                  camera_metadata** request)
239    {
240        Parcel data, reply;
241        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
242        data.writeInt32(templateId);
243        remote()->transact(CREATE_DEFAULT_REQUEST, data, &reply);
244        readMetadata(reply, /*out*/request);
245        return reply.readInt32();
246    }
247
248
249    virtual status_t getCameraInfo(int cameraId, camera_metadata** info)
250    {
251        Parcel data, reply;
252        data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
253        data.writeInt32(cameraId);
254        remote()->transact(GET_CAMERA_INFO, data, &reply);
255        readMetadata(reply, /*out*/info);
256        return reply.readInt32();
257    }
258
259
260private:
261
262
263};
264
265IMPLEMENT_META_INTERFACE(ProCameraUser, "android.hardware.IProCameraUser");
266
267// ----------------------------------------------------------------------
268
269status_t BnProCameraUser::onTransact(
270    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
271{
272    switch(code) {
273        case DISCONNECT: {
274            ALOGV("DISCONNECT");
275            CHECK_INTERFACE(IProCameraUser, data, reply);
276            disconnect();
277            return NO_ERROR;
278        } break;
279        case CONNECT: {
280            CHECK_INTERFACE(IProCameraUser, data, reply);
281            sp<IProCameraCallbacks> cameraClient =
282                   interface_cast<IProCameraCallbacks>(data.readStrongBinder());
283            reply->writeInt32(connect(cameraClient));
284            return NO_ERROR;
285        } break;
286
287        /* Shared ProCameraUser */
288        case EXCLUSIVE_TRY_LOCK: {
289            CHECK_INTERFACE(IProCameraUser, data, reply);
290            reply->writeInt32(exclusiveTryLock());
291            return NO_ERROR;
292        } break;
293        case EXCLUSIVE_LOCK: {
294            CHECK_INTERFACE(IProCameraUser, data, reply);
295            reply->writeInt32(exclusiveLock());
296            return NO_ERROR;
297        } break;
298        case EXCLUSIVE_UNLOCK: {
299            CHECK_INTERFACE(IProCameraUser, data, reply);
300            reply->writeInt32(exclusiveUnlock());
301            return NO_ERROR;
302        } break;
303        case HAS_EXCLUSIVE_LOCK: {
304            CHECK_INTERFACE(IProCameraUser, data, reply);
305            reply->writeInt32(hasExclusiveLock());
306            return NO_ERROR;
307        } break;
308        case SUBMIT_REQUEST: {
309            CHECK_INTERFACE(IProCameraUser, data, reply);
310            camera_metadata_t* metadata;
311            readMetadata(data, /*out*/&metadata);
312
313            // arg2 = streaming (bool)
314            bool streaming = data.readInt32();
315
316            // return code: requestId (int32)
317            reply->writeInt32(submitRequest(metadata, streaming));
318
319            return NO_ERROR;
320        } break;
321        case CANCEL_REQUEST: {
322            CHECK_INTERFACE(IProCameraUser, data, reply);
323            int requestId = data.readInt32();
324            reply->writeInt32(cancelRequest(requestId));
325            return NO_ERROR;
326        } break;
327        case DELETE_STREAM: {
328            CHECK_INTERFACE(IProCameraUser, data, reply);
329            int streamId = data.readInt32();
330            reply->writeInt32(deleteStream(streamId));
331            return NO_ERROR;
332        } break;
333        case CREATE_STREAM: {
334            CHECK_INTERFACE(IProCameraUser, data, reply);
335            int width, height, format;
336
337            width = data.readInt32();
338            height = data.readInt32();
339            format = data.readInt32();
340
341            sp<IGraphicBufferProducer> bp =
342               interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
343
344            int streamId = -1;
345            status_t ret;
346            ret = createStream(width, height, format, bp, &streamId);
347
348            reply->writeInt32(streamId);
349            reply->writeInt32(ret);
350
351            return NO_ERROR;
352        } break;
353
354        case CREATE_DEFAULT_REQUEST: {
355            CHECK_INTERFACE(IProCameraUser, data, reply);
356
357            int templateId = data.readInt32();
358
359            camera_metadata_t* request = NULL;
360            status_t ret;
361            ret = createDefaultRequest(templateId, &request);
362
363            writeMetadata(*reply, request);
364            reply->writeInt32(ret);
365
366            free_camera_metadata(request);
367
368            return NO_ERROR;
369        } break;
370        case GET_CAMERA_INFO: {
371            CHECK_INTERFACE(IProCameraUser, data, reply);
372
373            int cameraId = data.readInt32();
374
375            camera_metadata_t* info = NULL;
376            status_t ret;
377            ret = getCameraInfo(cameraId, &info);
378
379            writeMetadata(*reply, info);
380            reply->writeInt32(ret);
381
382            free_camera_metadata(info);
383
384            return NO_ERROR;
385        } break;
386        default:
387            return BBinder::onTransact(code, data, reply, flags);
388    }
389}
390
391// ----------------------------------------------------------------------------
392
393}; // namespace android
394