blob: 4c4dec3f5924676c590b4fb016ca0b92c8b9de83 [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);
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
Igor Murashkin985fd302013-02-20 18:24:43 -0800215 // arg0+arg1
216 writeMetadata(data, metadata);
Igor Murashkin634a5152013-02-20 17:15:11 -0800217
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
Igor Murashkinfa4cf9d2013-03-04 16:14:23 -0800235 virtual status_t deleteStream(int streamId)
Igor Murashkin634a5152013-02-20 17:15:11 -0800236 {
237 Parcel data, reply;
238 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
239 data.writeInt32(streamId);
240
Igor Murashkinfa4cf9d2013-03-04 16:14:23 -0800241 remote()->transact(DELETE_STREAM, data, &reply);
Igor Murashkin634a5152013-02-20 17:15:11 -0800242 return reply.readInt32();
243 }
244
Igor Murashkin985fd302013-02-20 18:24:43 -0800245 virtual status_t createStream(int width, int height, int format,
Igor Murashkin76f8b432013-02-20 19:15:15 -0800246 const sp<IGraphicBufferProducer>& bufferProducer,
Igor Murashkin985fd302013-02-20 18:24:43 -0800247 /*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
Igor Murashkin76f8b432013-02-20 19:15:15 -0800256 sp<IBinder> b(bufferProducer->asBinder());
257 data.writeStrongBinder(b);
258
Igor Murashkin985fd302013-02-20 18:24:43 -0800259 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
Igor Murashkin7b33a742013-02-21 13:49:26 -0800282 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
Igor Murashkin985fd302013-02-20 18:24:43 -0800293private:
294
295
Igor Murashkin634a5152013-02-20 17:15:11 -0800296};
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;
Igor Murashkin985fd302013-02-20 18:24:43 -0800344 readMetadata(data, /*out*/&metadata);
Igor Murashkin634a5152013-02-20 17:15:11 -0800345
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;
Igor Murashkinfa4cf9d2013-03-04 16:14:23 -0800360 case DELETE_STREAM: {
Igor Murashkin634a5152013-02-20 17:15:11 -0800361 CHECK_INTERFACE(IProCameraUser, data, reply);
362 int streamId = data.readInt32();
Igor Murashkinfa4cf9d2013-03-04 16:14:23 -0800363 reply->writeInt32(deleteStream(streamId));
Igor Murashkin634a5152013-02-20 17:15:11 -0800364 return NO_ERROR;
365 } break;
Igor Murashkin985fd302013-02-20 18:24:43 -0800366 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
Igor Murashkin76f8b432013-02-20 19:15:15 -0800374 sp<IGraphicBufferProducer> bp =
375 interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
Igor Murashkin985fd302013-02-20 18:24:43 -0800376
377 int streamId = -1;
378 status_t ret;
Igor Murashkin76f8b432013-02-20 19:15:15 -0800379 ret = createStream(width, height, format, bp, &streamId);
Igor Murashkin985fd302013-02-20 18:24:43 -0800380
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
Igor Murashkin7b33a742013-02-21 13:49:26 -0800399 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
Igor Murashkin985fd302013-02-20 18:24:43 -0800417 return NO_ERROR;
418 } break;
Igor Murashkin634a5152013-02-20 17:15:11 -0800419 default:
420 return BBinder::onTransact(code, data, reply, flags);
421 }
422}
423
424// ----------------------------------------------------------------------------
425
426}; // namespace android