blob: 015cb5c0d6f91b9705bbf150e30a3a5a9e5a4cf8 [file] [log] [blame]
Igor Murashkin634a5152013-02-20 17:15:11 -08001/*
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,
Igor Murashkinfa4cf9d2013-03-04 16:14:23 -080043 DELETE_STREAM,
Igor Murashkin985fd302013-02-20 18:24:43 -080044 CREATE_STREAM,
45 CREATE_DEFAULT_REQUEST,
Igor Murashkin7b33a742013-02-21 13:49:26 -080046 GET_CAMERA_INFO,
Igor Murashkin634a5152013-02-20 17:15:11 -080047};
48
Igor Murashkin985fd302013-02-20 18:24:43 -080049/**
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
Igor Murashkine2d1e3d2013-04-30 18:18:06 -070053 *
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).
Igor Murashkin985fd302013-02-20 18:24:43 -080056 */
57void readMetadata(const Parcel& data, camera_metadata_t** out) {
Igor Murashkine2d1e3d2013-04-30 18:18:06 -070058
59 status_t err = OK;
60
61 camera_metadata_t* metadata = NULL;
62
63 if (out) {
64 *out = NULL;
65 }
Igor Murashkin985fd302013-02-20 18:24:43 -080066
67 // arg0 = metadataSize (int32)
Igor Murashkine2d1e3d2013-04-30 18:18:06 -070068 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);
Igor Murashkin985fd302013-02-20 18:24:43 -080075
76 if (metadataSize == 0) {
Igor Murashkin985fd302013-02-20 18:24:43 -080077 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)
Igor Murashkine2d1e3d2013-04-30 18:18:06 -070086 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 }
Igor Murashkin985fd302013-02-20 18:24:43 -080093 const camera_metadata_t* tmp =
94 reinterpret_cast<const camera_metadata_t*>(blob.data());
Igor Murashkin985fd302013-02-20 18:24:43 -080095
Igor Murashkine2d1e3d2013-04-30 18:18:06 -070096 metadata = allocate_copy_camera_metadata_checked(tmp, metadataSize);
97 } while(0);
Igor Murashkin985fd302013-02-20 18:24:43 -080098 blob.release();
99
100 if (out) {
101 *out = metadata;
Igor Murashkine2d1e3d2013-04-30 18:18:06 -0700102 } else if (metadata != NULL) {
Igor Murashkin985fd302013-02-20 18:24:43 -0800103 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)
Igor Murashkin985fd302013-02-20 18:24:43 -0800113
114 if (metadata == NULL) {
115 data.writeInt32(0);
116 return;
117 }
118
Igor Murashkine2d1e3d2013-04-30 18:18:06 -0700119 const size_t metadataSize = get_camera_metadata_compact_size(metadata);
Igor Murashkin985fd302013-02-20 18:24:43 -0800120 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);
Igor Murashkine2d1e3d2013-04-30 18:18:06 -0700127
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
Igor Murashkin985fd302013-02-20 18:24:43 -0800146 }
147 blob.release();
148}
149
Igor Murashkin634a5152013-02-20 17:15:11 -0800150class 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);
Igor Murashkinbef3f232013-05-30 17:47:38 -0700165 reply.readExceptionCode();
Igor Murashkin634a5152013-02-20 17:15:11 -0800166 }
167
168 virtual status_t connect(const sp<IProCameraCallbacks>& cameraClient)
169 {
170 Parcel data, reply;
171 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
172 data.writeStrongBinder(cameraClient->asBinder());
173 remote()->transact(CONNECT, data, &reply);
174 return reply.readInt32();
175 }
176
177 /* Shared ProCameraUser */
178
179 virtual status_t exclusiveTryLock()
180 {
181 Parcel data, reply;
182 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
183 remote()->transact(EXCLUSIVE_TRY_LOCK, data, &reply);
184 return reply.readInt32();
185 }
186 virtual status_t exclusiveLock()
187 {
188 Parcel data, reply;
189 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
190 remote()->transact(EXCLUSIVE_LOCK, data, &reply);
191 return reply.readInt32();
192 }
193
194 virtual status_t exclusiveUnlock()
195 {
196 Parcel data, reply;
197 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
198 remote()->transact(EXCLUSIVE_UNLOCK, data, &reply);
199 return reply.readInt32();
200 }
201
202 virtual bool hasExclusiveLock()
203 {
204 Parcel data, reply;
205 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
206 remote()->transact(HAS_EXCLUSIVE_LOCK, data, &reply);
207 return !!reply.readInt32();
208 }
209
210 virtual int submitRequest(camera_metadata_t* metadata, bool streaming)
211 {
212
213 Parcel data, reply;
214 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
215
Igor Murashkin985fd302013-02-20 18:24:43 -0800216 // arg0+arg1
217 writeMetadata(data, metadata);
Igor Murashkin634a5152013-02-20 17:15:11 -0800218
219 // arg2 = streaming (bool)
220 data.writeInt32(streaming);
221
222 remote()->transact(SUBMIT_REQUEST, data, &reply);
223 return reply.readInt32();
224 }
225
226 virtual status_t cancelRequest(int requestId)
227 {
228 Parcel data, reply;
229 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
230 data.writeInt32(requestId);
231
232 remote()->transact(CANCEL_REQUEST, data, &reply);
233 return reply.readInt32();
234 }
235
Igor Murashkinfa4cf9d2013-03-04 16:14:23 -0800236 virtual status_t deleteStream(int streamId)
Igor Murashkin634a5152013-02-20 17:15:11 -0800237 {
238 Parcel data, reply;
239 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
240 data.writeInt32(streamId);
241
Igor Murashkinfa4cf9d2013-03-04 16:14:23 -0800242 remote()->transact(DELETE_STREAM, data, &reply);
Igor Murashkin634a5152013-02-20 17:15:11 -0800243 return reply.readInt32();
244 }
245
Igor Murashkin985fd302013-02-20 18:24:43 -0800246 virtual status_t createStream(int width, int height, int format,
Igor Murashkin76f8b432013-02-20 19:15:15 -0800247 const sp<IGraphicBufferProducer>& bufferProducer,
Igor Murashkin985fd302013-02-20 18:24:43 -0800248 /*out*/
249 int* streamId)
250 {
251 Parcel data, reply;
252 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
253 data.writeInt32(width);
254 data.writeInt32(height);
255 data.writeInt32(format);
256
Igor Murashkin76f8b432013-02-20 19:15:15 -0800257 sp<IBinder> b(bufferProducer->asBinder());
258 data.writeStrongBinder(b);
259
Igor Murashkin985fd302013-02-20 18:24:43 -0800260 remote()->transact(CREATE_STREAM, data, &reply);
261
262 int sId = reply.readInt32();
263 if (streamId) {
264 *streamId = sId;
265 }
266 return reply.readInt32();
267 }
268
269 // Create a request object from a template.
270 virtual status_t createDefaultRequest(int templateId,
271 /*out*/
272 camera_metadata** request)
273 {
274 Parcel data, reply;
275 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
276 data.writeInt32(templateId);
277 remote()->transact(CREATE_DEFAULT_REQUEST, data, &reply);
278 readMetadata(reply, /*out*/request);
279 return reply.readInt32();
280 }
281
282
Igor Murashkin7b33a742013-02-21 13:49:26 -0800283 virtual status_t getCameraInfo(int cameraId, camera_metadata** info)
284 {
285 Parcel data, reply;
286 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
287 data.writeInt32(cameraId);
288 remote()->transact(GET_CAMERA_INFO, data, &reply);
289 readMetadata(reply, /*out*/info);
290 return reply.readInt32();
291 }
292
293
Igor Murashkin985fd302013-02-20 18:24:43 -0800294private:
295
296
Igor Murashkin634a5152013-02-20 17:15:11 -0800297};
298
299IMPLEMENT_META_INTERFACE(ProCameraUser, "android.hardware.IProCameraUser");
300
301// ----------------------------------------------------------------------
302
303status_t BnProCameraUser::onTransact(
304 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
305{
306 switch(code) {
307 case DISCONNECT: {
308 ALOGV("DISCONNECT");
309 CHECK_INTERFACE(IProCameraUser, data, reply);
310 disconnect();
Igor Murashkinbef3f232013-05-30 17:47:38 -0700311 reply->writeNoException();
Igor Murashkin634a5152013-02-20 17:15:11 -0800312 return NO_ERROR;
313 } break;
314 case CONNECT: {
315 CHECK_INTERFACE(IProCameraUser, data, reply);
316 sp<IProCameraCallbacks> cameraClient =
317 interface_cast<IProCameraCallbacks>(data.readStrongBinder());
318 reply->writeInt32(connect(cameraClient));
319 return NO_ERROR;
320 } break;
321
322 /* Shared ProCameraUser */
323 case EXCLUSIVE_TRY_LOCK: {
324 CHECK_INTERFACE(IProCameraUser, data, reply);
325 reply->writeInt32(exclusiveTryLock());
326 return NO_ERROR;
327 } break;
328 case EXCLUSIVE_LOCK: {
329 CHECK_INTERFACE(IProCameraUser, data, reply);
330 reply->writeInt32(exclusiveLock());
331 return NO_ERROR;
332 } break;
333 case EXCLUSIVE_UNLOCK: {
334 CHECK_INTERFACE(IProCameraUser, data, reply);
335 reply->writeInt32(exclusiveUnlock());
336 return NO_ERROR;
337 } break;
338 case HAS_EXCLUSIVE_LOCK: {
339 CHECK_INTERFACE(IProCameraUser, data, reply);
340 reply->writeInt32(hasExclusiveLock());
341 return NO_ERROR;
342 } break;
343 case SUBMIT_REQUEST: {
344 CHECK_INTERFACE(IProCameraUser, data, reply);
345 camera_metadata_t* metadata;
Igor Murashkin985fd302013-02-20 18:24:43 -0800346 readMetadata(data, /*out*/&metadata);
Igor Murashkin634a5152013-02-20 17:15:11 -0800347
348 // arg2 = streaming (bool)
349 bool streaming = data.readInt32();
350
351 // return code: requestId (int32)
352 reply->writeInt32(submitRequest(metadata, streaming));
353
354 return NO_ERROR;
355 } break;
356 case CANCEL_REQUEST: {
357 CHECK_INTERFACE(IProCameraUser, data, reply);
358 int requestId = data.readInt32();
359 reply->writeInt32(cancelRequest(requestId));
360 return NO_ERROR;
361 } break;
Igor Murashkinfa4cf9d2013-03-04 16:14:23 -0800362 case DELETE_STREAM: {
Igor Murashkin634a5152013-02-20 17:15:11 -0800363 CHECK_INTERFACE(IProCameraUser, data, reply);
364 int streamId = data.readInt32();
Igor Murashkinfa4cf9d2013-03-04 16:14:23 -0800365 reply->writeInt32(deleteStream(streamId));
Igor Murashkin634a5152013-02-20 17:15:11 -0800366 return NO_ERROR;
367 } break;
Igor Murashkin985fd302013-02-20 18:24:43 -0800368 case CREATE_STREAM: {
369 CHECK_INTERFACE(IProCameraUser, data, reply);
370 int width, height, format;
371
372 width = data.readInt32();
373 height = data.readInt32();
374 format = data.readInt32();
375
Igor Murashkin76f8b432013-02-20 19:15:15 -0800376 sp<IGraphicBufferProducer> bp =
377 interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
Igor Murashkin985fd302013-02-20 18:24:43 -0800378
379 int streamId = -1;
380 status_t ret;
Igor Murashkin76f8b432013-02-20 19:15:15 -0800381 ret = createStream(width, height, format, bp, &streamId);
Igor Murashkin985fd302013-02-20 18:24:43 -0800382
383 reply->writeInt32(streamId);
384 reply->writeInt32(ret);
385
386 return NO_ERROR;
387 } break;
388
389 case CREATE_DEFAULT_REQUEST: {
390 CHECK_INTERFACE(IProCameraUser, data, reply);
391
392 int templateId = data.readInt32();
393
394 camera_metadata_t* request = NULL;
395 status_t ret;
396 ret = createDefaultRequest(templateId, &request);
397
398 writeMetadata(*reply, request);
399 reply->writeInt32(ret);
400
Igor Murashkin7b33a742013-02-21 13:49:26 -0800401 free_camera_metadata(request);
402
403 return NO_ERROR;
404 } break;
405 case GET_CAMERA_INFO: {
406 CHECK_INTERFACE(IProCameraUser, data, reply);
407
408 int cameraId = data.readInt32();
409
410 camera_metadata_t* info = NULL;
411 status_t ret;
412 ret = getCameraInfo(cameraId, &info);
413
414 writeMetadata(*reply, info);
415 reply->writeInt32(ret);
416
417 free_camera_metadata(info);
418
Igor Murashkin985fd302013-02-20 18:24:43 -0800419 return NO_ERROR;
420 } break;
Igor Murashkin634a5152013-02-20 17:15:11 -0800421 default:
422 return BBinder::onTransact(code, data, reply, flags);
423 }
424}
425
426// ----------------------------------------------------------------------------
427
428}; // namespace android