blob: e60cfe5ea321e326446c691dc9e9a21358bc3b57 [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 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
53 */
54void readMetadata(const Parcel& data, camera_metadata_t** out) {
55 camera_metadata_t* metadata;
56
57 // arg0 = metadataSize (int32)
58 size_t metadataSize = static_cast<size_t>(data.readInt32());
59
60 if (metadataSize == 0) {
61 if (out) {
62 *out = NULL;
63 }
64 return;
65 }
66
67 // NOTE: this doesn't make sense to me. shouldnt the blob
68 // know how big it is? why do we have to specify the size
69 // to Parcel::readBlob ?
70
71 ReadableBlob blob;
72 // arg1 = metadata (blob)
73 {
74 data.readBlob(metadataSize, &blob);
75 const camera_metadata_t* tmp =
76 reinterpret_cast<const camera_metadata_t*>(blob.data());
77 size_t entry_capacity = get_camera_metadata_entry_capacity(tmp);
78 size_t data_capacity = get_camera_metadata_data_capacity(tmp);
79
80 metadata = allocate_camera_metadata(entry_capacity, data_capacity);
81 copy_camera_metadata(metadata, metadataSize, tmp);
82 }
83 blob.release();
84
85 if (out) {
86 *out = metadata;
87 } else {
88 free_camera_metadata(metadata);
89 }
90}
91
92/**
93 * Caller retains ownership of metadata
94 * - Write 2 (int32 + blob) args in the current position
95 */
96void writeMetadata(Parcel& data, camera_metadata_t* metadata) {
97 // arg0 = metadataSize (int32)
98 size_t metadataSize;
99
100 if (metadata == NULL) {
101 data.writeInt32(0);
102 return;
103 }
104
105 metadataSize = get_camera_metadata_compact_size(metadata);
106 data.writeInt32(static_cast<int32_t>(metadataSize));
107
108 // arg1 = metadata (blob)
109 WritableBlob blob;
110 {
111 data.writeBlob(metadataSize, &blob);
112 copy_camera_metadata(blob.data(), metadataSize, metadata);
113 }
114 blob.release();
115}
116
Igor Murashkin634a5152013-02-20 17:15:11 -0800117class BpProCameraUser: public BpInterface<IProCameraUser>
118{
119public:
120 BpProCameraUser(const sp<IBinder>& impl)
121 : BpInterface<IProCameraUser>(impl)
122 {
123 }
124
125 // disconnect from camera service
126 void disconnect()
127 {
128 ALOGV("disconnect");
129 Parcel data, reply;
130 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
131 remote()->transact(DISCONNECT, data, &reply);
132 }
133
134 virtual status_t connect(const sp<IProCameraCallbacks>& cameraClient)
135 {
136 Parcel data, reply;
137 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
138 data.writeStrongBinder(cameraClient->asBinder());
139 remote()->transact(CONNECT, data, &reply);
140 return reply.readInt32();
141 }
142
143 /* Shared ProCameraUser */
144
145 virtual status_t exclusiveTryLock()
146 {
147 Parcel data, reply;
148 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
149 remote()->transact(EXCLUSIVE_TRY_LOCK, data, &reply);
150 return reply.readInt32();
151 }
152 virtual status_t exclusiveLock()
153 {
154 Parcel data, reply;
155 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
156 remote()->transact(EXCLUSIVE_LOCK, data, &reply);
157 return reply.readInt32();
158 }
159
160 virtual status_t exclusiveUnlock()
161 {
162 Parcel data, reply;
163 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
164 remote()->transact(EXCLUSIVE_UNLOCK, data, &reply);
165 return reply.readInt32();
166 }
167
168 virtual bool hasExclusiveLock()
169 {
170 Parcel data, reply;
171 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
172 remote()->transact(HAS_EXCLUSIVE_LOCK, data, &reply);
173 return !!reply.readInt32();
174 }
175
176 virtual int submitRequest(camera_metadata_t* metadata, bool streaming)
177 {
178
179 Parcel data, reply;
180 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
181
Igor Murashkin985fd302013-02-20 18:24:43 -0800182 // arg0+arg1
183 writeMetadata(data, metadata);
Igor Murashkin634a5152013-02-20 17:15:11 -0800184
185 // arg2 = streaming (bool)
186 data.writeInt32(streaming);
187
188 remote()->transact(SUBMIT_REQUEST, data, &reply);
189 return reply.readInt32();
190 }
191
192 virtual status_t cancelRequest(int requestId)
193 {
194 Parcel data, reply;
195 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
196 data.writeInt32(requestId);
197
198 remote()->transact(CANCEL_REQUEST, data, &reply);
199 return reply.readInt32();
200 }
201
202 virtual status_t requestStream(int streamId)
203 {
204 Parcel data, reply;
205 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
206 data.writeInt32(streamId);
207
208 remote()->transact(REQUEST_STREAM, data, &reply);
209 return reply.readInt32();
210 }
211 virtual status_t cancelStream(int streamId)
212 {
213 Parcel data, reply;
214 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
215 data.writeInt32(streamId);
216
217 remote()->transact(CANCEL_STREAM, data, &reply);
218 return reply.readInt32();
219 }
220
Igor Murashkin985fd302013-02-20 18:24:43 -0800221 virtual status_t createStream(int width, int height, int format,
Igor Murashkin76f8b432013-02-20 19:15:15 -0800222 const sp<IGraphicBufferProducer>& bufferProducer,
Igor Murashkin985fd302013-02-20 18:24:43 -0800223 /*out*/
224 int* streamId)
225 {
226 Parcel data, reply;
227 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
228 data.writeInt32(width);
229 data.writeInt32(height);
230 data.writeInt32(format);
231
Igor Murashkin76f8b432013-02-20 19:15:15 -0800232 sp<IBinder> b(bufferProducer->asBinder());
233 data.writeStrongBinder(b);
234
Igor Murashkin985fd302013-02-20 18:24:43 -0800235 remote()->transact(CREATE_STREAM, data, &reply);
236
237 int sId = reply.readInt32();
238 if (streamId) {
239 *streamId = sId;
240 }
241 return reply.readInt32();
242 }
243
244 // Create a request object from a template.
245 virtual status_t createDefaultRequest(int templateId,
246 /*out*/
247 camera_metadata** request)
248 {
249 Parcel data, reply;
250 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
251 data.writeInt32(templateId);
252 remote()->transact(CREATE_DEFAULT_REQUEST, data, &reply);
253 readMetadata(reply, /*out*/request);
254 return reply.readInt32();
255 }
256
257
258private:
259
260
Igor Murashkin634a5152013-02-20 17:15:11 -0800261};
262
263IMPLEMENT_META_INTERFACE(ProCameraUser, "android.hardware.IProCameraUser");
264
265// ----------------------------------------------------------------------
266
267status_t BnProCameraUser::onTransact(
268 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
269{
270 switch(code) {
271 case DISCONNECT: {
272 ALOGV("DISCONNECT");
273 CHECK_INTERFACE(IProCameraUser, data, reply);
274 disconnect();
275 return NO_ERROR;
276 } break;
277 case CONNECT: {
278 CHECK_INTERFACE(IProCameraUser, data, reply);
279 sp<IProCameraCallbacks> cameraClient =
280 interface_cast<IProCameraCallbacks>(data.readStrongBinder());
281 reply->writeInt32(connect(cameraClient));
282 return NO_ERROR;
283 } break;
284
285 /* Shared ProCameraUser */
286 case EXCLUSIVE_TRY_LOCK: {
287 CHECK_INTERFACE(IProCameraUser, data, reply);
288 reply->writeInt32(exclusiveTryLock());
289 return NO_ERROR;
290 } break;
291 case EXCLUSIVE_LOCK: {
292 CHECK_INTERFACE(IProCameraUser, data, reply);
293 reply->writeInt32(exclusiveLock());
294 return NO_ERROR;
295 } break;
296 case EXCLUSIVE_UNLOCK: {
297 CHECK_INTERFACE(IProCameraUser, data, reply);
298 reply->writeInt32(exclusiveUnlock());
299 return NO_ERROR;
300 } break;
301 case HAS_EXCLUSIVE_LOCK: {
302 CHECK_INTERFACE(IProCameraUser, data, reply);
303 reply->writeInt32(hasExclusiveLock());
304 return NO_ERROR;
305 } break;
306 case SUBMIT_REQUEST: {
307 CHECK_INTERFACE(IProCameraUser, data, reply);
308 camera_metadata_t* metadata;
Igor Murashkin985fd302013-02-20 18:24:43 -0800309 readMetadata(data, /*out*/&metadata);
Igor Murashkin634a5152013-02-20 17:15:11 -0800310
311 // arg2 = streaming (bool)
312 bool streaming = data.readInt32();
313
314 // return code: requestId (int32)
315 reply->writeInt32(submitRequest(metadata, streaming));
316
317 return NO_ERROR;
318 } break;
319 case CANCEL_REQUEST: {
320 CHECK_INTERFACE(IProCameraUser, data, reply);
321 int requestId = data.readInt32();
322 reply->writeInt32(cancelRequest(requestId));
323 return NO_ERROR;
324 } break;
325 case REQUEST_STREAM: {
326 CHECK_INTERFACE(IProCameraUser, data, reply);
327 int streamId = data.readInt32();
328 reply->writeInt32(requestStream(streamId));
329 return NO_ERROR;
330 } break;
331 case CANCEL_STREAM: {
332 CHECK_INTERFACE(IProCameraUser, data, reply);
333 int streamId = data.readInt32();
334 reply->writeInt32(cancelStream(streamId));
335 return NO_ERROR;
336 } break;
Igor Murashkin985fd302013-02-20 18:24:43 -0800337 case CREATE_STREAM: {
338 CHECK_INTERFACE(IProCameraUser, data, reply);
339 int width, height, format;
340
341 width = data.readInt32();
342 height = data.readInt32();
343 format = data.readInt32();
344
Igor Murashkin76f8b432013-02-20 19:15:15 -0800345 sp<IGraphicBufferProducer> bp =
346 interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
Igor Murashkin985fd302013-02-20 18:24:43 -0800347
348 int streamId = -1;
349 status_t ret;
Igor Murashkin76f8b432013-02-20 19:15:15 -0800350 ret = createStream(width, height, format, bp, &streamId);
Igor Murashkin985fd302013-02-20 18:24:43 -0800351
352 reply->writeInt32(streamId);
353 reply->writeInt32(ret);
354
355 return NO_ERROR;
356 } break;
357
358 case CREATE_DEFAULT_REQUEST: {
359 CHECK_INTERFACE(IProCameraUser, data, reply);
360
361 int templateId = data.readInt32();
362
363 camera_metadata_t* request = NULL;
364 status_t ret;
365 ret = createDefaultRequest(templateId, &request);
366
367 writeMetadata(*reply, request);
368 reply->writeInt32(ret);
369
370 return NO_ERROR;
371 } break;
Igor Murashkin634a5152013-02-20 17:15:11 -0800372 default:
373 return BBinder::onTransact(code, data, reply, flags);
374 }
375}
376
377// ----------------------------------------------------------------------------
378
379}; // namespace android