blob: d8dc2a5c3010c496e5fe6e397ca18d4ba70bf28d [file] [log] [blame]
Mathias Agopian3cf61352010-02-09 17:46:37 -08001/*
2**
3** Copyright (C) 2008, The Android Open Source Project
Mathias Agopian3cf61352010-02-09 17:46:37 -08004**
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 "Camera"
20#include <utils/Log.h>
21#include <utils/threads.h>
Eino-Ville Talvala48af7e82013-02-19 10:40:14 -080022#include <utils/String16.h>
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +080023#include <binder/IPCThreadState.h>
Mathias Agopian3cf61352010-02-09 17:46:37 -080024#include <binder/IServiceManager.h>
25#include <binder/IMemory.h>
26
27#include <camera/Camera.h>
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +080028#include <camera/ICameraRecordingProxyListener.h>
Mathias Agopian3cf61352010-02-09 17:46:37 -080029#include <camera/ICameraService.h>
30
Andy McFadden484566c2012-12-18 09:46:54 -080031#include <gui/IGraphicBufferProducer.h>
Mathias Agopiandf712ea2012-02-25 18:48:35 -080032#include <gui/Surface.h>
Mathias Agopian3cf61352010-02-09 17:46:37 -080033
34namespace android {
35
36// client singleton for camera service binder interface
37Mutex Camera::mLock;
38sp<ICameraService> Camera::mCameraService;
39sp<Camera::DeathNotifier> Camera::mDeathNotifier;
40
41// establish binder interface to camera service
42const sp<ICameraService>& Camera::getCameraService()
43{
44 Mutex::Autolock _l(mLock);
45 if (mCameraService.get() == 0) {
46 sp<IServiceManager> sm = defaultServiceManager();
47 sp<IBinder> binder;
48 do {
49 binder = sm->getService(String16("media.camera"));
50 if (binder != 0)
51 break;
Steve Block5ff1dd52012-01-05 23:22:43 +000052 ALOGW("CameraService not published, waiting...");
Mathias Agopian3cf61352010-02-09 17:46:37 -080053 usleep(500000); // 0.5 s
54 } while(true);
55 if (mDeathNotifier == NULL) {
56 mDeathNotifier = new DeathNotifier();
57 }
58 binder->linkToDeath(mDeathNotifier);
59 mCameraService = interface_cast<ICameraService>(binder);
60 }
Steve Block29357bc2012-01-06 19:20:56 +000061 ALOGE_IF(mCameraService==0, "no CameraService!?");
Mathias Agopian3cf61352010-02-09 17:46:37 -080062 return mCameraService;
63}
64
65// ---------------------------------------------------------------------------
66
67Camera::Camera()
68{
69 init();
70}
71
72// construct a camera client from an existing camera remote
73sp<Camera> Camera::create(const sp<ICamera>& camera)
74{
Steve Block3856b092011-10-20 11:56:00 +010075 ALOGV("create");
Mathias Agopian3cf61352010-02-09 17:46:37 -080076 if (camera == 0) {
Steve Block29357bc2012-01-06 19:20:56 +000077 ALOGE("camera remote is a NULL pointer");
Mathias Agopian3cf61352010-02-09 17:46:37 -080078 return 0;
79 }
80
81 sp<Camera> c = new Camera();
82 if (camera->connect(c) == NO_ERROR) {
83 c->mStatus = NO_ERROR;
84 c->mCamera = camera;
85 camera->asBinder()->linkToDeath(c);
Wu-cheng Li627baac2011-01-04 20:00:55 +080086 return c;
Mathias Agopian3cf61352010-02-09 17:46:37 -080087 }
Wu-cheng Li627baac2011-01-04 20:00:55 +080088 return 0;
Mathias Agopian3cf61352010-02-09 17:46:37 -080089}
90
91void Camera::init()
92{
93 mStatus = UNKNOWN_ERROR;
94}
95
96Camera::~Camera()
97{
Chih-Chung Changd06618e2010-05-13 15:14:24 +080098 // We don't need to call disconnect() here because if the CameraService
99 // thinks we are the owner of the hardware, it will hold a (strong)
100 // reference to us, and we can't possibly be here. We also don't want to
101 // call disconnect() here if we are in the same process as mediaserver,
102 // because we may be invoked by CameraService::Client::connect() and will
103 // deadlock if we call any method of ICamera here.
Mathias Agopian3cf61352010-02-09 17:46:37 -0800104}
105
Chih-Chung Chang35a055b2010-05-06 16:36:58 +0800106int32_t Camera::getNumberOfCameras()
107{
108 const sp<ICameraService>& cs = getCameraService();
109 if (cs == 0) return 0;
110 return cs->getNumberOfCameras();
111}
112
Chih-Chung Changddbdb352010-06-10 13:32:16 +0800113status_t Camera::getCameraInfo(int cameraId,
114 struct CameraInfo* cameraInfo) {
115 const sp<ICameraService>& cs = getCameraService();
116 if (cs == 0) return UNKNOWN_ERROR;
117 return cs->getCameraInfo(cameraId, cameraInfo);
118}
119
Eino-Ville Talvala48af7e82013-02-19 10:40:14 -0800120sp<Camera> Camera::connect(int cameraId, const String16& clientPackageName,
121 int clientUid)
Mathias Agopian3cf61352010-02-09 17:46:37 -0800122{
Steve Block3856b092011-10-20 11:56:00 +0100123 ALOGV("connect");
Mathias Agopian3cf61352010-02-09 17:46:37 -0800124 sp<Camera> c = new Camera();
Igor Murashkinbfb5d5e2013-02-20 17:15:11 -0800125 sp<ICameraClient> cl = c;
Mathias Agopian3cf61352010-02-09 17:46:37 -0800126 const sp<ICameraService>& cs = getCameraService();
127 if (cs != 0) {
Eino-Ville Talvala48af7e82013-02-19 10:40:14 -0800128 c->mCamera = cs->connect(cl, cameraId, clientPackageName, clientUid);
Mathias Agopian3cf61352010-02-09 17:46:37 -0800129 }
130 if (c->mCamera != 0) {
131 c->mCamera->asBinder()->linkToDeath(c);
132 c->mStatus = NO_ERROR;
133 } else {
134 c.clear();
135 }
136 return c;
137}
138
139void Camera::disconnect()
140{
Steve Block3856b092011-10-20 11:56:00 +0100141 ALOGV("disconnect");
Mathias Agopian3cf61352010-02-09 17:46:37 -0800142 if (mCamera != 0) {
143 mCamera->disconnect();
Chih-Chung Changf8ed70a2010-03-24 16:38:02 -0700144 mCamera->asBinder()->unlinkToDeath(this);
Mathias Agopian3cf61352010-02-09 17:46:37 -0800145 mCamera = 0;
146 }
147}
148
149status_t Camera::reconnect()
150{
Steve Block3856b092011-10-20 11:56:00 +0100151 ALOGV("reconnect");
Mathias Agopian3cf61352010-02-09 17:46:37 -0800152 sp <ICamera> c = mCamera;
153 if (c == 0) return NO_INIT;
154 return c->connect(this);
155}
156
157sp<ICamera> Camera::remote()
158{
159 return mCamera;
160}
161
162status_t Camera::lock()
163{
164 sp <ICamera> c = mCamera;
165 if (c == 0) return NO_INIT;
166 return c->lock();
167}
168
169status_t Camera::unlock()
170{
171 sp <ICamera> c = mCamera;
172 if (c == 0) return NO_INIT;
173 return c->unlock();
174}
175
Jamie Gennis4b791682010-08-10 16:37:53 -0700176// pass the buffered Surface to the camera service
Mathias Agopian3cf61352010-02-09 17:46:37 -0800177status_t Camera::setPreviewDisplay(const sp<Surface>& surface)
178{
Steve Block3856b092011-10-20 11:56:00 +0100179 ALOGV("setPreviewDisplay(%p)", surface.get());
Mathias Agopian3cf61352010-02-09 17:46:37 -0800180 sp <ICamera> c = mCamera;
181 if (c == 0) return NO_INIT;
182 if (surface != 0) {
Jamie Gennis4b791682010-08-10 16:37:53 -0700183 return c->setPreviewDisplay(surface);
Mathias Agopian3cf61352010-02-09 17:46:37 -0800184 } else {
Steve Blockb8a80522011-12-20 16:23:08 +0000185 ALOGD("app passed NULL surface");
Mathias Agopian3cf61352010-02-09 17:46:37 -0800186 return c->setPreviewDisplay(0);
187 }
188}
189
Andy McFadden484566c2012-12-18 09:46:54 -0800190// pass the buffered IGraphicBufferProducer to the camera service
191status_t Camera::setPreviewTexture(const sp<IGraphicBufferProducer>& bufferProducer)
Jamie Gennisbfa33aa2010-12-20 11:51:31 -0800192{
Andy McFadden484566c2012-12-18 09:46:54 -0800193 ALOGV("setPreviewTexture(%p)", bufferProducer.get());
Jamie Gennisbfa33aa2010-12-20 11:51:31 -0800194 sp <ICamera> c = mCamera;
195 if (c == 0) return NO_INIT;
Andy McFadden484566c2012-12-18 09:46:54 -0800196 if (bufferProducer != 0) {
197 return c->setPreviewTexture(bufferProducer);
Jamie Gennisbfa33aa2010-12-20 11:51:31 -0800198 } else {
Steve Blockb8a80522011-12-20 16:23:08 +0000199 ALOGD("app passed NULL surface");
Jamie Gennisbfa33aa2010-12-20 11:51:31 -0800200 return c->setPreviewTexture(0);
201 }
202}
203
Mathias Agopian3cf61352010-02-09 17:46:37 -0800204// start preview mode
205status_t Camera::startPreview()
206{
Steve Block3856b092011-10-20 11:56:00 +0100207 ALOGV("startPreview");
Mathias Agopian3cf61352010-02-09 17:46:37 -0800208 sp <ICamera> c = mCamera;
209 if (c == 0) return NO_INIT;
210 return c->startPreview();
211}
212
James Donge2ad6732010-10-18 20:42:51 -0700213status_t Camera::storeMetaDataInBuffers(bool enabled)
214{
Steve Block3856b092011-10-20 11:56:00 +0100215 ALOGV("storeMetaDataInBuffers: %s",
James Donge2ad6732010-10-18 20:42:51 -0700216 enabled? "true": "false");
217 sp <ICamera> c = mCamera;
218 if (c == 0) return NO_INIT;
219 return c->storeMetaDataInBuffers(enabled);
220}
221
Mathias Agopian3cf61352010-02-09 17:46:37 -0800222// start recording mode, must call setPreviewDisplay first
223status_t Camera::startRecording()
224{
Steve Block3856b092011-10-20 11:56:00 +0100225 ALOGV("startRecording");
Mathias Agopian3cf61352010-02-09 17:46:37 -0800226 sp <ICamera> c = mCamera;
227 if (c == 0) return NO_INIT;
228 return c->startRecording();
229}
230
231// stop preview mode
232void Camera::stopPreview()
233{
Steve Block3856b092011-10-20 11:56:00 +0100234 ALOGV("stopPreview");
Mathias Agopian3cf61352010-02-09 17:46:37 -0800235 sp <ICamera> c = mCamera;
236 if (c == 0) return;
237 c->stopPreview();
238}
239
240// stop recording mode
241void Camera::stopRecording()
242{
Steve Block3856b092011-10-20 11:56:00 +0100243 ALOGV("stopRecording");
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800244 {
245 Mutex::Autolock _l(mLock);
246 mRecordingProxyListener.clear();
247 }
Mathias Agopian3cf61352010-02-09 17:46:37 -0800248 sp <ICamera> c = mCamera;
249 if (c == 0) return;
250 c->stopRecording();
251}
252
253// release a recording frame
254void Camera::releaseRecordingFrame(const sp<IMemory>& mem)
255{
Steve Block3856b092011-10-20 11:56:00 +0100256 ALOGV("releaseRecordingFrame");
Mathias Agopian3cf61352010-02-09 17:46:37 -0800257 sp <ICamera> c = mCamera;
258 if (c == 0) return;
259 c->releaseRecordingFrame(mem);
260}
261
262// get preview state
263bool Camera::previewEnabled()
264{
Steve Block3856b092011-10-20 11:56:00 +0100265 ALOGV("previewEnabled");
Mathias Agopian3cf61352010-02-09 17:46:37 -0800266 sp <ICamera> c = mCamera;
267 if (c == 0) return false;
268 return c->previewEnabled();
269}
270
271// get recording state
272bool Camera::recordingEnabled()
273{
Steve Block3856b092011-10-20 11:56:00 +0100274 ALOGV("recordingEnabled");
Mathias Agopian3cf61352010-02-09 17:46:37 -0800275 sp <ICamera> c = mCamera;
276 if (c == 0) return false;
277 return c->recordingEnabled();
278}
279
280status_t Camera::autoFocus()
281{
Steve Block3856b092011-10-20 11:56:00 +0100282 ALOGV("autoFocus");
Mathias Agopian3cf61352010-02-09 17:46:37 -0800283 sp <ICamera> c = mCamera;
284 if (c == 0) return NO_INIT;
285 return c->autoFocus();
286}
287
288status_t Camera::cancelAutoFocus()
289{
Steve Block3856b092011-10-20 11:56:00 +0100290 ALOGV("cancelAutoFocus");
Mathias Agopian3cf61352010-02-09 17:46:37 -0800291 sp <ICamera> c = mCamera;
292 if (c == 0) return NO_INIT;
293 return c->cancelAutoFocus();
294}
295
296// take a picture
James Donge468ac52011-02-17 16:38:06 -0800297status_t Camera::takePicture(int msgType)
Mathias Agopian3cf61352010-02-09 17:46:37 -0800298{
Steve Block3856b092011-10-20 11:56:00 +0100299 ALOGV("takePicture: 0x%x", msgType);
Mathias Agopian3cf61352010-02-09 17:46:37 -0800300 sp <ICamera> c = mCamera;
301 if (c == 0) return NO_INIT;
James Donge468ac52011-02-17 16:38:06 -0800302 return c->takePicture(msgType);
Mathias Agopian3cf61352010-02-09 17:46:37 -0800303}
304
305// set preview/capture parameters - key/value pairs
306status_t Camera::setParameters(const String8& params)
307{
Steve Block3856b092011-10-20 11:56:00 +0100308 ALOGV("setParameters");
Mathias Agopian3cf61352010-02-09 17:46:37 -0800309 sp <ICamera> c = mCamera;
310 if (c == 0) return NO_INIT;
311 return c->setParameters(params);
312}
313
314// get preview/capture parameters - key/value pairs
315String8 Camera::getParameters() const
316{
Steve Block3856b092011-10-20 11:56:00 +0100317 ALOGV("getParameters");
Mathias Agopian3cf61352010-02-09 17:46:37 -0800318 String8 params;
319 sp <ICamera> c = mCamera;
320 if (c != 0) params = mCamera->getParameters();
321 return params;
322}
323
324// send command to camera driver
325status_t Camera::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2)
326{
Steve Block3856b092011-10-20 11:56:00 +0100327 ALOGV("sendCommand");
Mathias Agopian3cf61352010-02-09 17:46:37 -0800328 sp <ICamera> c = mCamera;
329 if (c == 0) return NO_INIT;
330 return c->sendCommand(cmd, arg1, arg2);
331}
332
333void Camera::setListener(const sp<CameraListener>& listener)
334{
335 Mutex::Autolock _l(mLock);
336 mListener = listener;
337}
338
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800339void Camera::setRecordingProxyListener(const sp<ICameraRecordingProxyListener>& listener)
340{
341 Mutex::Autolock _l(mLock);
342 mRecordingProxyListener = listener;
343}
344
Mathias Agopian3cf61352010-02-09 17:46:37 -0800345void Camera::setPreviewCallbackFlags(int flag)
346{
Steve Block3856b092011-10-20 11:56:00 +0100347 ALOGV("setPreviewCallbackFlags");
Mathias Agopian3cf61352010-02-09 17:46:37 -0800348 sp <ICamera> c = mCamera;
349 if (c == 0) return;
350 mCamera->setPreviewCallbackFlag(flag);
351}
352
353// callback from camera service
354void Camera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2)
355{
356 sp<CameraListener> listener;
357 {
358 Mutex::Autolock _l(mLock);
359 listener = mListener;
360 }
361 if (listener != NULL) {
362 listener->notify(msgType, ext1, ext2);
363 }
364}
365
366// callback from camera service when frame or image is ready
Wu-cheng Li57c86182011-07-30 05:00:37 +0800367void Camera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr,
368 camera_frame_metadata_t *metadata)
Mathias Agopian3cf61352010-02-09 17:46:37 -0800369{
370 sp<CameraListener> listener;
371 {
372 Mutex::Autolock _l(mLock);
373 listener = mListener;
374 }
375 if (listener != NULL) {
Wu-cheng Li57c86182011-07-30 05:00:37 +0800376 listener->postData(msgType, dataPtr, metadata);
Mathias Agopian3cf61352010-02-09 17:46:37 -0800377 }
378}
379
380// callback from camera service when timestamped frame is ready
381void Camera::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr)
382{
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800383 // If recording proxy listener is registered, forward the frame and return.
384 // The other listener (mListener) is ignored because the receiver needs to
385 // call releaseRecordingFrame.
386 sp<ICameraRecordingProxyListener> proxylistener;
387 {
388 Mutex::Autolock _l(mLock);
389 proxylistener = mRecordingProxyListener;
390 }
391 if (proxylistener != NULL) {
392 proxylistener->dataCallbackTimestamp(timestamp, msgType, dataPtr);
393 return;
394 }
395
Mathias Agopian3cf61352010-02-09 17:46:37 -0800396 sp<CameraListener> listener;
397 {
398 Mutex::Autolock _l(mLock);
399 listener = mListener;
400 }
401 if (listener != NULL) {
402 listener->postDataTimestamp(timestamp, msgType, dataPtr);
James Dongc42478e2010-11-15 10:38:37 -0800403 } else {
Steve Block5ff1dd52012-01-05 23:22:43 +0000404 ALOGW("No listener was set. Drop a recording frame.");
James Dongc42478e2010-11-15 10:38:37 -0800405 releaseRecordingFrame(dataPtr);
Mathias Agopian3cf61352010-02-09 17:46:37 -0800406 }
407}
408
409void Camera::binderDied(const wp<IBinder>& who) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000410 ALOGW("ICamera died");
Mathias Agopian3cf61352010-02-09 17:46:37 -0800411 notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_SERVER_DIED, 0);
412}
413
414void Camera::DeathNotifier::binderDied(const wp<IBinder>& who) {
Steve Block3856b092011-10-20 11:56:00 +0100415 ALOGV("binderDied");
Mathias Agopian3cf61352010-02-09 17:46:37 -0800416 Mutex::Autolock _l(Camera::mLock);
417 Camera::mCameraService.clear();
Steve Block5ff1dd52012-01-05 23:22:43 +0000418 ALOGW("Camera server died!");
Mathias Agopian3cf61352010-02-09 17:46:37 -0800419}
420
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800421sp<ICameraRecordingProxy> Camera::getRecordingProxy() {
Steve Block3856b092011-10-20 11:56:00 +0100422 ALOGV("getProxy");
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800423 return new RecordingProxy(this);
424}
425
426status_t Camera::RecordingProxy::startRecording(const sp<ICameraRecordingProxyListener>& listener)
427{
Steve Block3856b092011-10-20 11:56:00 +0100428 ALOGV("RecordingProxy::startRecording");
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800429 mCamera->setRecordingProxyListener(listener);
430 mCamera->reconnect();
431 return mCamera->startRecording();
432}
433
434void Camera::RecordingProxy::stopRecording()
435{
Steve Block3856b092011-10-20 11:56:00 +0100436 ALOGV("RecordingProxy::stopRecording");
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800437 mCamera->stopRecording();
438}
439
440void Camera::RecordingProxy::releaseRecordingFrame(const sp<IMemory>& mem)
441{
Steve Block3856b092011-10-20 11:56:00 +0100442 ALOGV("RecordingProxy::releaseRecordingFrame");
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800443 mCamera->releaseRecordingFrame(mem);
444}
445
446Camera::RecordingProxy::RecordingProxy(const sp<Camera>& camera)
447{
448 mCamera = camera;
449}
450
Mathias Agopian3cf61352010-02-09 17:46:37 -0800451}; // namespace android