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