• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
29 namespace android {
30 
31 typedef Parcel::WritableBlob WritableBlob;
32 typedef Parcel::ReadableBlob ReadableBlob;
33 
34 enum {
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   */
readMetadata(const Parcel & data,camera_metadata_t ** out)57 void 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   */
writeMetadata(Parcel & data,camera_metadata_t * metadata)111 void 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 
150 class BpProCameraUser: public BpInterface<IProCameraUser>
151 {
152 public:
BpProCameraUser(const sp<IBinder> & impl)153     BpProCameraUser(const sp<IBinder>& impl)
154         : BpInterface<IProCameraUser>(impl)
155     {
156     }
157 
158     // disconnect from camera service
disconnect()159     void disconnect()
160     {
161         ALOGV("disconnect");
162         Parcel data, reply;
163         data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
164         remote()->transact(DISCONNECT, data, &reply);
165     }
166 
connect(const sp<IProCameraCallbacks> & cameraClient)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 
exclusiveTryLock()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     }
exclusiveLock()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 
exclusiveUnlock()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 
hasExclusiveLock()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 
submitRequest(camera_metadata_t * metadata,bool streaming)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 
cancelRequest(int requestId)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 
deleteStream(int streamId)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 
createStream(int width,int height,int format,const sp<IGraphicBufferProducer> & bufferProducer,int * streamId)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.
createDefaultRequest(int templateId,camera_metadata ** request)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 
getCameraInfo(int cameraId,camera_metadata ** info)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 
293 private:
294 
295 
296 };
297 
298 IMPLEMENT_META_INTERFACE(ProCameraUser, "android.hardware.IProCameraUser");
299 
300 // ----------------------------------------------------------------------
301 
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)302 status_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