blob: c9d98aaa7a2477244bc063adeb8e101a90ce2ef2 [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,
43 REQUEST_STREAM,
44 CANCEL_STREAM,
Igor Murashkin985fd302013-02-20 18:24:43 -080045 CREATE_STREAM,
46 CREATE_DEFAULT_REQUEST,
Igor Murashkin7b33a742013-02-21 13:49:26 -080047 GET_CAMERA_INFO,
Igor Murashkin634a5152013-02-20 17:15:11 -080048};
49
Igor Murashkin985fd302013-02-20 18:24:43 -080050/**
51 * Caller becomes the owner of the new metadata
52 * 'const Parcel' doesnt prevent us from calling the read functions.
53 * which is interesting since it changes the internal state
54 */
55void readMetadata(const Parcel& data, camera_metadata_t** out) {
56 camera_metadata_t* metadata;
57
58 // arg0 = metadataSize (int32)
59 size_t metadataSize = static_cast<size_t>(data.readInt32());
60
61 if (metadataSize == 0) {
62 if (out) {
63 *out = NULL;
64 }
65 return;
66 }
67
68 // NOTE: this doesn't make sense to me. shouldnt the blob
69 // know how big it is? why do we have to specify the size
70 // to Parcel::readBlob ?
71
72 ReadableBlob blob;
73 // arg1 = metadata (blob)
74 {
75 data.readBlob(metadataSize, &blob);
76 const camera_metadata_t* tmp =
77 reinterpret_cast<const camera_metadata_t*>(blob.data());
78 size_t entry_capacity = get_camera_metadata_entry_capacity(tmp);
79 size_t data_capacity = get_camera_metadata_data_capacity(tmp);
80
81 metadata = allocate_camera_metadata(entry_capacity, data_capacity);
82 copy_camera_metadata(metadata, metadataSize, tmp);
83 }
84 blob.release();
85
86 if (out) {
87 *out = metadata;
88 } else {
89 free_camera_metadata(metadata);
90 }
91}
92
93/**
94 * Caller retains ownership of metadata
95 * - Write 2 (int32 + blob) args in the current position
96 */
97void writeMetadata(Parcel& data, camera_metadata_t* metadata) {
98 // arg0 = metadataSize (int32)
99 size_t metadataSize;
100
101 if (metadata == NULL) {
102 data.writeInt32(0);
103 return;
104 }
105
106 metadataSize = get_camera_metadata_compact_size(metadata);
107 data.writeInt32(static_cast<int32_t>(metadataSize));
108
109 // arg1 = metadata (blob)
110 WritableBlob blob;
111 {
112 data.writeBlob(metadataSize, &blob);
113 copy_camera_metadata(blob.data(), metadataSize, metadata);
114 }
115 blob.release();
116}
117
Igor Murashkin634a5152013-02-20 17:15:11 -0800118class BpProCameraUser: public BpInterface<IProCameraUser>
119{
120public:
121 BpProCameraUser(const sp<IBinder>& impl)
122 : BpInterface<IProCameraUser>(impl)
123 {
124 }
125
126 // disconnect from camera service
127 void disconnect()
128 {
129 ALOGV("disconnect");
130 Parcel data, reply;
131 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
132 remote()->transact(DISCONNECT, data, &reply);
133 }
134
135 virtual status_t connect(const sp<IProCameraCallbacks>& cameraClient)
136 {
137 Parcel data, reply;
138 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
139 data.writeStrongBinder(cameraClient->asBinder());
140 remote()->transact(CONNECT, data, &reply);
141 return reply.readInt32();
142 }
143
144 /* Shared ProCameraUser */
145
146 virtual status_t exclusiveTryLock()
147 {
148 Parcel data, reply;
149 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
150 remote()->transact(EXCLUSIVE_TRY_LOCK, data, &reply);
151 return reply.readInt32();
152 }
153 virtual status_t exclusiveLock()
154 {
155 Parcel data, reply;
156 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
157 remote()->transact(EXCLUSIVE_LOCK, data, &reply);
158 return reply.readInt32();
159 }
160
161 virtual status_t exclusiveUnlock()
162 {
163 Parcel data, reply;
164 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
165 remote()->transact(EXCLUSIVE_UNLOCK, data, &reply);
166 return reply.readInt32();
167 }
168
169 virtual bool hasExclusiveLock()
170 {
171 Parcel data, reply;
172 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
173 remote()->transact(HAS_EXCLUSIVE_LOCK, data, &reply);
174 return !!reply.readInt32();
175 }
176
177 virtual int submitRequest(camera_metadata_t* metadata, bool streaming)
178 {
179
180 Parcel data, reply;
181 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
182
Igor Murashkin985fd302013-02-20 18:24:43 -0800183 // arg0+arg1
184 writeMetadata(data, metadata);
Igor Murashkin634a5152013-02-20 17:15:11 -0800185
186 // arg2 = streaming (bool)
187 data.writeInt32(streaming);
188
189 remote()->transact(SUBMIT_REQUEST, data, &reply);
190 return reply.readInt32();
191 }
192
193 virtual status_t cancelRequest(int requestId)
194 {
195 Parcel data, reply;
196 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
197 data.writeInt32(requestId);
198
199 remote()->transact(CANCEL_REQUEST, data, &reply);
200 return reply.readInt32();
201 }
202
203 virtual status_t requestStream(int streamId)
204 {
205 Parcel data, reply;
206 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
207 data.writeInt32(streamId);
208
209 remote()->transact(REQUEST_STREAM, data, &reply);
210 return reply.readInt32();
211 }
212 virtual status_t cancelStream(int streamId)
213 {
214 Parcel data, reply;
215 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
216 data.writeInt32(streamId);
217
218 remote()->transact(CANCEL_STREAM, data, &reply);
219 return reply.readInt32();
220 }
221
Igor Murashkin985fd302013-02-20 18:24:43 -0800222 virtual status_t createStream(int width, int height, int format,
Igor Murashkin76f8b432013-02-20 19:15:15 -0800223 const sp<IGraphicBufferProducer>& bufferProducer,
Igor Murashkin985fd302013-02-20 18:24:43 -0800224 /*out*/
225 int* streamId)
226 {
227 Parcel data, reply;
228 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
229 data.writeInt32(width);
230 data.writeInt32(height);
231 data.writeInt32(format);
232
Igor Murashkin76f8b432013-02-20 19:15:15 -0800233 sp<IBinder> b(bufferProducer->asBinder());
234 data.writeStrongBinder(b);
235
Igor Murashkin985fd302013-02-20 18:24:43 -0800236 remote()->transact(CREATE_STREAM, data, &reply);
237
238 int sId = reply.readInt32();
239 if (streamId) {
240 *streamId = sId;
241 }
242 return reply.readInt32();
243 }
244
245 // Create a request object from a template.
246 virtual status_t createDefaultRequest(int templateId,
247 /*out*/
248 camera_metadata** request)
249 {
250 Parcel data, reply;
251 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
252 data.writeInt32(templateId);
253 remote()->transact(CREATE_DEFAULT_REQUEST, data, &reply);
254 readMetadata(reply, /*out*/request);
255 return reply.readInt32();
256 }
257
258
Igor Murashkin7b33a742013-02-21 13:49:26 -0800259 virtual status_t getCameraInfo(int cameraId, camera_metadata** info)
260 {
261 Parcel data, reply;
262 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
263 data.writeInt32(cameraId);
264 remote()->transact(GET_CAMERA_INFO, data, &reply);
265 readMetadata(reply, /*out*/info);
266 return reply.readInt32();
267 }
268
269
Igor Murashkin985fd302013-02-20 18:24:43 -0800270private:
271
272
Igor Murashkin634a5152013-02-20 17:15:11 -0800273};
274
275IMPLEMENT_META_INTERFACE(ProCameraUser, "android.hardware.IProCameraUser");
276
277// ----------------------------------------------------------------------
278
279status_t BnProCameraUser::onTransact(
280 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
281{
282 switch(code) {
283 case DISCONNECT: {
284 ALOGV("DISCONNECT");
285 CHECK_INTERFACE(IProCameraUser, data, reply);
286 disconnect();
287 return NO_ERROR;
288 } break;
289 case CONNECT: {
290 CHECK_INTERFACE(IProCameraUser, data, reply);
291 sp<IProCameraCallbacks> cameraClient =
292 interface_cast<IProCameraCallbacks>(data.readStrongBinder());
293 reply->writeInt32(connect(cameraClient));
294 return NO_ERROR;
295 } break;
296
297 /* Shared ProCameraUser */
298 case EXCLUSIVE_TRY_LOCK: {
299 CHECK_INTERFACE(IProCameraUser, data, reply);
300 reply->writeInt32(exclusiveTryLock());
301 return NO_ERROR;
302 } break;
303 case EXCLUSIVE_LOCK: {
304 CHECK_INTERFACE(IProCameraUser, data, reply);
305 reply->writeInt32(exclusiveLock());
306 return NO_ERROR;
307 } break;
308 case EXCLUSIVE_UNLOCK: {
309 CHECK_INTERFACE(IProCameraUser, data, reply);
310 reply->writeInt32(exclusiveUnlock());
311 return NO_ERROR;
312 } break;
313 case HAS_EXCLUSIVE_LOCK: {
314 CHECK_INTERFACE(IProCameraUser, data, reply);
315 reply->writeInt32(hasExclusiveLock());
316 return NO_ERROR;
317 } break;
318 case SUBMIT_REQUEST: {
319 CHECK_INTERFACE(IProCameraUser, data, reply);
320 camera_metadata_t* metadata;
Igor Murashkin985fd302013-02-20 18:24:43 -0800321 readMetadata(data, /*out*/&metadata);
Igor Murashkin634a5152013-02-20 17:15:11 -0800322
323 // arg2 = streaming (bool)
324 bool streaming = data.readInt32();
325
326 // return code: requestId (int32)
327 reply->writeInt32(submitRequest(metadata, streaming));
328
329 return NO_ERROR;
330 } break;
331 case CANCEL_REQUEST: {
332 CHECK_INTERFACE(IProCameraUser, data, reply);
333 int requestId = data.readInt32();
334 reply->writeInt32(cancelRequest(requestId));
335 return NO_ERROR;
336 } break;
337 case REQUEST_STREAM: {
338 CHECK_INTERFACE(IProCameraUser, data, reply);
339 int streamId = data.readInt32();
340 reply->writeInt32(requestStream(streamId));
341 return NO_ERROR;
342 } break;
343 case CANCEL_STREAM: {
344 CHECK_INTERFACE(IProCameraUser, data, reply);
345 int streamId = data.readInt32();
346 reply->writeInt32(cancelStream(streamId));
347 return NO_ERROR;
348 } break;
Igor Murashkin985fd302013-02-20 18:24:43 -0800349 case CREATE_STREAM: {
350 CHECK_INTERFACE(IProCameraUser, data, reply);
351 int width, height, format;
352
353 width = data.readInt32();
354 height = data.readInt32();
355 format = data.readInt32();
356
Igor Murashkin76f8b432013-02-20 19:15:15 -0800357 sp<IGraphicBufferProducer> bp =
358 interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
Igor Murashkin985fd302013-02-20 18:24:43 -0800359
360 int streamId = -1;
361 status_t ret;
Igor Murashkin76f8b432013-02-20 19:15:15 -0800362 ret = createStream(width, height, format, bp, &streamId);
Igor Murashkin985fd302013-02-20 18:24:43 -0800363
364 reply->writeInt32(streamId);
365 reply->writeInt32(ret);
366
367 return NO_ERROR;
368 } break;
369
370 case CREATE_DEFAULT_REQUEST: {
371 CHECK_INTERFACE(IProCameraUser, data, reply);
372
373 int templateId = data.readInt32();
374
375 camera_metadata_t* request = NULL;
376 status_t ret;
377 ret = createDefaultRequest(templateId, &request);
378
379 writeMetadata(*reply, request);
380 reply->writeInt32(ret);
381
Igor Murashkin7b33a742013-02-21 13:49:26 -0800382 free_camera_metadata(request);
383
384 return NO_ERROR;
385 } break;
386 case GET_CAMERA_INFO: {
387 CHECK_INTERFACE(IProCameraUser, data, reply);
388
389 int cameraId = data.readInt32();
390
391 camera_metadata_t* info = NULL;
392 status_t ret;
393 ret = getCameraInfo(cameraId, &info);
394
395 writeMetadata(*reply, info);
396 reply->writeInt32(ret);
397
398 free_camera_metadata(info);
399
Igor Murashkin985fd302013-02-20 18:24:43 -0800400 return NO_ERROR;
401 } break;
Igor Murashkin634a5152013-02-20 17:15:11 -0800402 default:
403 return BBinder::onTransact(code, data, reply, flags);
404 }
405}
406
407// ----------------------------------------------------------------------------
408
409}; // namespace android