1 /*
2 **
3 ** Copyright (C) 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 "ProCamera"
20 #include <utils/Log.h>
21 #include <utils/threads.h>
22 #include <utils/Mutex.h>
23
24 #include <binder/IPCThreadState.h>
25 #include <binder/IServiceManager.h>
26 #include <binder/IMemory.h>
27
28 #include <camera/ProCamera.h>
29 #include <camera/ICameraService.h>
30 #include <camera/IProCameraUser.h>
31 #include <camera/IProCameraCallbacks.h>
32
33 #include <gui/IGraphicBufferProducer.h>
34
35 #include <system/camera_metadata.h>
36
37 namespace android {
38
connect(int cameraId)39 sp<ProCamera> ProCamera::connect(int cameraId)
40 {
41 return CameraBaseT::connect(cameraId, String16(),
42 ICameraService::USE_CALLING_UID);
43 }
44
ProCamera(int cameraId)45 ProCamera::ProCamera(int cameraId)
46 : CameraBase(cameraId)
47 {
48 }
49
~ProCamera()50 ProCamera::~ProCamera()
51 {
52
53 }
54
55 /* IProCameraUser's implementation */
56
57 // callback from camera service
notifyCallback(int32_t msgType,int32_t ext1,int32_t ext2)58 void ProCamera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2)
59 {
60 return CameraBaseT::notifyCallback(msgType, ext1, ext2);
61 }
62
onLockStatusChanged(IProCameraCallbacks::LockStatus newLockStatus)63 void ProCamera::onLockStatusChanged(
64 IProCameraCallbacks::LockStatus newLockStatus)
65 {
66 ALOGV("%s: newLockStatus = %d", __FUNCTION__, newLockStatus);
67
68 sp<ProCameraListener> listener;
69 {
70 Mutex::Autolock _l(mLock);
71 listener = mListener;
72 }
73 if (listener != NULL) {
74 switch (newLockStatus) {
75 case IProCameraCallbacks::LOCK_ACQUIRED:
76 listener->onLockAcquired();
77 break;
78 case IProCameraCallbacks::LOCK_RELEASED:
79 listener->onLockReleased();
80 break;
81 case IProCameraCallbacks::LOCK_STOLEN:
82 listener->onLockStolen();
83 break;
84 default:
85 ALOGE("%s: Unknown lock status: %d",
86 __FUNCTION__, newLockStatus);
87 }
88 }
89 }
90
onResultReceived(int32_t frameId,camera_metadata * result)91 void ProCamera::onResultReceived(int32_t frameId, camera_metadata* result) {
92 ALOGV("%s: frameId = %d, result = %p", __FUNCTION__, frameId, result);
93
94 sp<ProCameraListener> listener;
95 {
96 Mutex::Autolock _l(mLock);
97 listener = mListener;
98 }
99
100 CameraMetadata tmp(result);
101
102 // Unblock waitForFrame(id) callers
103 {
104 Mutex::Autolock al(mWaitMutex);
105 mMetadataReady = true;
106 mLatestMetadata = tmp; // make copy
107 mWaitCondition.broadcast();
108 }
109
110 result = tmp.release();
111
112 if (listener != NULL) {
113 listener->onResultReceived(frameId, result);
114 } else {
115 free_camera_metadata(result);
116 }
117
118 }
119
exclusiveTryLock()120 status_t ProCamera::exclusiveTryLock()
121 {
122 sp <IProCameraUser> c = mCamera;
123 if (c == 0) return NO_INIT;
124
125 return c->exclusiveTryLock();
126 }
exclusiveLock()127 status_t ProCamera::exclusiveLock()
128 {
129 sp <IProCameraUser> c = mCamera;
130 if (c == 0) return NO_INIT;
131
132 return c->exclusiveLock();
133 }
exclusiveUnlock()134 status_t ProCamera::exclusiveUnlock()
135 {
136 sp <IProCameraUser> c = mCamera;
137 if (c == 0) return NO_INIT;
138
139 return c->exclusiveUnlock();
140 }
hasExclusiveLock()141 bool ProCamera::hasExclusiveLock()
142 {
143 sp <IProCameraUser> c = mCamera;
144 if (c == 0) return NO_INIT;
145
146 return c->hasExclusiveLock();
147 }
148
149 // Note that the callee gets a copy of the metadata.
submitRequest(const struct camera_metadata * metadata,bool streaming)150 int ProCamera::submitRequest(const struct camera_metadata* metadata,
151 bool streaming)
152 {
153 sp <IProCameraUser> c = mCamera;
154 if (c == 0) return NO_INIT;
155
156 return c->submitRequest(const_cast<struct camera_metadata*>(metadata),
157 streaming);
158 }
159
cancelRequest(int requestId)160 status_t ProCamera::cancelRequest(int requestId)
161 {
162 sp <IProCameraUser> c = mCamera;
163 if (c == 0) return NO_INIT;
164
165 return c->cancelRequest(requestId);
166 }
167
deleteStream(int streamId)168 status_t ProCamera::deleteStream(int streamId)
169 {
170 sp <IProCameraUser> c = mCamera;
171 if (c == 0) return NO_INIT;
172
173 status_t s = c->deleteStream(streamId);
174
175 mStreams.removeItem(streamId);
176
177 return s;
178 }
179
createStream(int width,int height,int format,const sp<Surface> & surface,int * streamId)180 status_t ProCamera::createStream(int width, int height, int format,
181 const sp<Surface>& surface,
182 /*out*/
183 int* streamId)
184 {
185 *streamId = -1;
186
187 ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
188 format);
189
190 if (surface == 0) {
191 return BAD_VALUE;
192 }
193
194 return createStream(width, height, format,
195 surface->getIGraphicBufferProducer(),
196 streamId);
197 }
198
createStream(int width,int height,int format,const sp<IGraphicBufferProducer> & bufferProducer,int * streamId)199 status_t ProCamera::createStream(int width, int height, int format,
200 const sp<IGraphicBufferProducer>& bufferProducer,
201 /*out*/
202 int* streamId) {
203 *streamId = -1;
204
205 ALOGV("%s: createStreamT %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
206 format);
207
208 if (bufferProducer == 0) {
209 return BAD_VALUE;
210 }
211
212 sp <IProCameraUser> c = mCamera;
213 status_t stat = c->createStream(width, height, format, bufferProducer,
214 streamId);
215
216 if (stat == OK) {
217 StreamInfo s(*streamId);
218
219 mStreams.add(*streamId, s);
220 }
221
222 return stat;
223 }
224
createStreamCpu(int width,int height,int format,int heapCount,sp<CpuConsumer> * cpuConsumer,int * streamId)225 status_t ProCamera::createStreamCpu(int width, int height, int format,
226 int heapCount,
227 /*out*/
228 sp<CpuConsumer>* cpuConsumer,
229 int* streamId) {
230 return createStreamCpu(width, height, format, heapCount,
231 /*synchronousMode*/true,
232 cpuConsumer, streamId);
233 }
234
createStreamCpu(int width,int height,int format,int heapCount,bool synchronousMode,sp<CpuConsumer> * cpuConsumer,int * streamId)235 status_t ProCamera::createStreamCpu(int width, int height, int format,
236 int heapCount,
237 bool synchronousMode,
238 /*out*/
239 sp<CpuConsumer>* cpuConsumer,
240 int* streamId)
241 {
242 ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
243 format);
244
245 *cpuConsumer = NULL;
246
247 sp <IProCameraUser> c = mCamera;
248 if (c == 0) return NO_INIT;
249
250 sp<CpuConsumer> cc = new CpuConsumer(heapCount, synchronousMode);
251 cc->setName(String8("ProCamera::mCpuConsumer"));
252
253 sp<Surface> stc = new Surface(
254 cc->getProducerInterface());
255
256 status_t s = createStream(width, height, format,
257 stc->getIGraphicBufferProducer(),
258 streamId);
259
260 if (s != OK) {
261 ALOGE("%s: Failure to create stream %dx%d (fmt=0x%x)", __FUNCTION__,
262 width, height, format);
263 return s;
264 }
265
266 sp<ProFrameListener> frameAvailableListener =
267 new ProFrameListener(this, *streamId);
268
269 getStreamInfo(*streamId).cpuStream = true;
270 getStreamInfo(*streamId).cpuConsumer = cc;
271 getStreamInfo(*streamId).synchronousMode = synchronousMode;
272 getStreamInfo(*streamId).stc = stc;
273 // for lifetime management
274 getStreamInfo(*streamId).frameAvailableListener = frameAvailableListener;
275
276 cc->setFrameAvailableListener(frameAvailableListener);
277
278 *cpuConsumer = cc;
279
280 return s;
281 }
282
getCameraInfo(int cameraId)283 camera_metadata* ProCamera::getCameraInfo(int cameraId) {
284 ALOGV("%s: cameraId = %d", __FUNCTION__, cameraId);
285
286 sp <IProCameraUser> c = mCamera;
287 if (c == 0) return NULL;
288
289 camera_metadata* ptr = NULL;
290 status_t status = c->getCameraInfo(cameraId, &ptr);
291
292 if (status != OK) {
293 ALOGE("%s: Failed to get camera info, error = %d", __FUNCTION__, status);
294 }
295
296 return ptr;
297 }
298
createDefaultRequest(int templateId,camera_metadata ** request) const299 status_t ProCamera::createDefaultRequest(int templateId,
300 camera_metadata** request) const {
301 ALOGV("%s: templateId = %d", __FUNCTION__, templateId);
302
303 sp <IProCameraUser> c = mCamera;
304 if (c == 0) return NO_INIT;
305
306 return c->createDefaultRequest(templateId, request);
307 }
308
onFrameAvailable(int streamId)309 void ProCamera::onFrameAvailable(int streamId) {
310 ALOGV("%s: streamId = %d", __FUNCTION__, streamId);
311
312 sp<ProCameraListener> listener = mListener;
313 StreamInfo& stream = getStreamInfo(streamId);
314
315 if (listener.get() != NULL) {
316 listener->onFrameAvailable(streamId, stream.cpuConsumer);
317 }
318
319 // Unblock waitForFrame(id) callers
320 {
321 Mutex::Autolock al(mWaitMutex);
322 getStreamInfo(streamId).frameReady++;
323 mWaitCondition.broadcast();
324 }
325 }
326
waitForFrameBuffer(int streamId)327 int ProCamera::waitForFrameBuffer(int streamId) {
328 status_t stat = BAD_VALUE;
329 Mutex::Autolock al(mWaitMutex);
330
331 StreamInfo& si = getStreamInfo(streamId);
332
333 if (si.frameReady > 0) {
334 int numFrames = si.frameReady;
335 si.frameReady = 0;
336 return numFrames;
337 } else {
338 while (true) {
339 stat = mWaitCondition.waitRelative(mWaitMutex,
340 mWaitTimeout);
341 if (stat != OK) {
342 ALOGE("%s: Error while waiting for frame buffer: %d",
343 __FUNCTION__, stat);
344 return stat;
345 }
346
347 if (si.frameReady > 0) {
348 int numFrames = si.frameReady;
349 si.frameReady = 0;
350 return numFrames;
351 }
352 // else it was some other stream that got unblocked
353 }
354 }
355
356 return stat;
357 }
358
dropFrameBuffer(int streamId,int count)359 int ProCamera::dropFrameBuffer(int streamId, int count) {
360 StreamInfo& si = getStreamInfo(streamId);
361
362 if (!si.cpuStream) {
363 return BAD_VALUE;
364 } else if (count < 0) {
365 return BAD_VALUE;
366 }
367
368 if (!si.synchronousMode) {
369 ALOGW("%s: No need to drop frames on asynchronous streams,"
370 " as asynchronous mode only keeps 1 latest frame around.",
371 __FUNCTION__);
372 return BAD_VALUE;
373 }
374
375 int numDropped = 0;
376 for (int i = 0; i < count; ++i) {
377 CpuConsumer::LockedBuffer buffer;
378 if (si.cpuConsumer->lockNextBuffer(&buffer) != OK) {
379 break;
380 }
381
382 si.cpuConsumer->unlockBuffer(buffer);
383 numDropped++;
384 }
385
386 return numDropped;
387 }
388
waitForFrameMetadata()389 status_t ProCamera::waitForFrameMetadata() {
390 status_t stat = BAD_VALUE;
391 Mutex::Autolock al(mWaitMutex);
392
393 if (mMetadataReady) {
394 return OK;
395 } else {
396 while (true) {
397 stat = mWaitCondition.waitRelative(mWaitMutex,
398 mWaitTimeout);
399
400 if (stat != OK) {
401 ALOGE("%s: Error while waiting for metadata: %d",
402 __FUNCTION__, stat);
403 return stat;
404 }
405
406 if (mMetadataReady) {
407 mMetadataReady = false;
408 return OK;
409 }
410 // else it was some other stream or metadata
411 }
412 }
413
414 return stat;
415 }
416
consumeFrameMetadata()417 CameraMetadata ProCamera::consumeFrameMetadata() {
418 Mutex::Autolock al(mWaitMutex);
419
420 // Destructive: Subsequent calls return empty metadatas
421 CameraMetadata tmp = mLatestMetadata;
422 mLatestMetadata.clear();
423
424 return tmp;
425 }
426
getStreamInfo(int streamId)427 ProCamera::StreamInfo& ProCamera::getStreamInfo(int streamId) {
428 return mStreams.editValueFor(streamId);
429 }
430
431 }; // namespace android
432