blob: cd7bf5c6a10f0e67c263d6fe205b605401f4765c [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,
222 const sp<Surface>& surface,
223 /*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
232 Surface::writeToParcel(surface, &data);
233 remote()->transact(CREATE_STREAM, data, &reply);
234
235 int sId = reply.readInt32();
236 if (streamId) {
237 *streamId = sId;
238 }
239 return reply.readInt32();
240 }
241
242 // Create a request object from a template.
243 virtual status_t createDefaultRequest(int templateId,
244 /*out*/
245 camera_metadata** request)
246 {
247 Parcel data, reply;
248 data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
249 data.writeInt32(templateId);
250 remote()->transact(CREATE_DEFAULT_REQUEST, data, &reply);
251 readMetadata(reply, /*out*/request);
252 return reply.readInt32();
253 }
254
255
256private:
257
258
Igor Murashkin634a5152013-02-20 17:15:11 -0800259};
260
261IMPLEMENT_META_INTERFACE(ProCameraUser, "android.hardware.IProCameraUser");
262
263// ----------------------------------------------------------------------
264
265status_t BnProCameraUser::onTransact(
266 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
267{
268 switch(code) {
269 case DISCONNECT: {
270 ALOGV("DISCONNECT");
271 CHECK_INTERFACE(IProCameraUser, data, reply);
272 disconnect();
273 return NO_ERROR;
274 } break;
275 case CONNECT: {
276 CHECK_INTERFACE(IProCameraUser, data, reply);
277 sp<IProCameraCallbacks> cameraClient =
278 interface_cast<IProCameraCallbacks>(data.readStrongBinder());
279 reply->writeInt32(connect(cameraClient));
280 return NO_ERROR;
281 } break;
282
283 /* Shared ProCameraUser */
284 case EXCLUSIVE_TRY_LOCK: {
285 CHECK_INTERFACE(IProCameraUser, data, reply);
286 reply->writeInt32(exclusiveTryLock());
287 return NO_ERROR;
288 } break;
289 case EXCLUSIVE_LOCK: {
290 CHECK_INTERFACE(IProCameraUser, data, reply);
291 reply->writeInt32(exclusiveLock());
292 return NO_ERROR;
293 } break;
294 case EXCLUSIVE_UNLOCK: {
295 CHECK_INTERFACE(IProCameraUser, data, reply);
296 reply->writeInt32(exclusiveUnlock());
297 return NO_ERROR;
298 } break;
299 case HAS_EXCLUSIVE_LOCK: {
300 CHECK_INTERFACE(IProCameraUser, data, reply);
301 reply->writeInt32(hasExclusiveLock());
302 return NO_ERROR;
303 } break;
304 case SUBMIT_REQUEST: {
305 CHECK_INTERFACE(IProCameraUser, data, reply);
306 camera_metadata_t* metadata;
Igor Murashkin985fd302013-02-20 18:24:43 -0800307 readMetadata(data, /*out*/&metadata);
Igor Murashkin634a5152013-02-20 17:15:11 -0800308
309 // arg2 = streaming (bool)
310 bool streaming = data.readInt32();
311
312 // return code: requestId (int32)
313 reply->writeInt32(submitRequest(metadata, streaming));
314
315 return NO_ERROR;
316 } break;
317 case CANCEL_REQUEST: {
318 CHECK_INTERFACE(IProCameraUser, data, reply);
319 int requestId = data.readInt32();
320 reply->writeInt32(cancelRequest(requestId));
321 return NO_ERROR;
322 } break;
323 case REQUEST_STREAM: {
324 CHECK_INTERFACE(IProCameraUser, data, reply);
325 int streamId = data.readInt32();
326 reply->writeInt32(requestStream(streamId));
327 return NO_ERROR;
328 } break;
329 case CANCEL_STREAM: {
330 CHECK_INTERFACE(IProCameraUser, data, reply);
331 int streamId = data.readInt32();
332 reply->writeInt32(cancelStream(streamId));
333 return NO_ERROR;
334 } break;
Igor Murashkin985fd302013-02-20 18:24:43 -0800335 case CREATE_STREAM: {
336 CHECK_INTERFACE(IProCameraUser, data, reply);
337 int width, height, format;
338
339 width = data.readInt32();
340 height = data.readInt32();
341 format = data.readInt32();
342
343 sp<Surface> surface = Surface::readFromParcel(data);
344
345 int streamId = -1;
346 status_t ret;
347 ret = createStream(width, height, format, surface, &streamId);
348
349 reply->writeInt32(streamId);
350 reply->writeInt32(ret);
351
352 return NO_ERROR;
353 } break;
354
355 case CREATE_DEFAULT_REQUEST: {
356 CHECK_INTERFACE(IProCameraUser, data, reply);
357
358 int templateId = data.readInt32();
359
360 camera_metadata_t* request = NULL;
361 status_t ret;
362 ret = createDefaultRequest(templateId, &request);
363
364 writeMetadata(*reply, request);
365 reply->writeInt32(ret);
366
367 return NO_ERROR;
368 } break;
Igor Murashkin634a5152013-02-20 17:15:11 -0800369 default:
370 return BBinder::onTransact(code, data, reply, flags);
371 }
372}
373
374// ----------------------------------------------------------------------------
375
376}; // namespace android