blob: 0037399752189971b973fbc53d2fb6a5c3baf30d [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2**
3** Copyright (C) 2008, The Android Open Source Project
4** Copyright (C) 2008 HTC Inc.
5**
6** Licensed under the Apache License, Version 2.0 (the "License");
7** you may not use this file except in compliance with the License.
8** You may obtain a copy of the License at
9**
10** http://www.apache.org/licenses/LICENSE-2.0
11**
12** Unless required by applicable law or agreed to in writing, software
13** distributed under the License is distributed on an "AS IS" BASIS,
14** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15** See the License for the specific language governing permissions and
16** limitations under the License.
17*/
18
19//#define LOG_NDEBUG 0
20#define LOG_TAG "Camera"
21#include <utils/Log.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022#include <utils/threads.h>
Mathias Agopian000479f2010-02-09 17:46:37 -080023
24#include <binder/IServiceManager.h>
Mathias Agopian07952722009-05-19 19:08:10 -070025#include <binder/IMemory.h>
Mathias Agopian000479f2010-02-09 17:46:37 -080026
27#include <camera/Camera.h>
28#include <camera/ICameraService.h>
29
30#include <surfaceflinger/Surface.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031
32namespace android {
33
34// client singleton for camera service binder interface
35Mutex Camera::mLock;
36sp<ICameraService> Camera::mCameraService;
37sp<Camera::DeathNotifier> Camera::mDeathNotifier;
38
39// establish binder interface to camera service
40const sp<ICameraService>& Camera::getCameraService()
41{
42 Mutex::Autolock _l(mLock);
43 if (mCameraService.get() == 0) {
44 sp<IServiceManager> sm = defaultServiceManager();
45 sp<IBinder> binder;
46 do {
47 binder = sm->getService(String16("media.camera"));
48 if (binder != 0)
49 break;
50 LOGW("CameraService not published, waiting...");
51 usleep(500000); // 0.5 s
52 } while(true);
53 if (mDeathNotifier == NULL) {
54 mDeathNotifier = new DeathNotifier();
55 }
56 binder->linkToDeath(mDeathNotifier);
57 mCameraService = interface_cast<ICameraService>(binder);
58 }
59 LOGE_IF(mCameraService==0, "no CameraService!?");
60 return mCameraService;
61}
62
63// ---------------------------------------------------------------------------
64
65Camera::Camera()
66{
67 init();
68}
69
James Dong325ac472009-04-27 12:01:59 -070070// construct a camera client from an existing camera remote
James Dong2adc2db2009-04-23 14:07:23 -070071sp<Camera> Camera::create(const sp<ICamera>& camera)
72{
James Dong325ac472009-04-27 12:01:59 -070073 LOGV("create");
74 if (camera == 0) {
75 LOGE("camera remote is a NULL pointer");
76 return 0;
77 }
78
James Dong2adc2db2009-04-23 14:07:23 -070079 sp<Camera> c = new Camera();
James Dong2adc2db2009-04-23 14:07:23 -070080 if (camera->connect(c) == NO_ERROR) {
81 c->mStatus = NO_ERROR;
82 c->mCamera = camera;
83 camera->asBinder()->linkToDeath(c);
84 }
85 return c;
86}
87
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088void Camera::init()
89{
90 mStatus = UNKNOWN_ERROR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091}
92
93Camera::~Camera()
94{
Chih-Chung Chang553447b2010-05-13 15:14:24 +080095 // We don't need to call disconnect() here because if the CameraService
96 // thinks we are the owner of the hardware, it will hold a (strong)
97 // reference to us, and we can't possibly be here. We also don't want to
98 // call disconnect() here if we are in the same process as mediaserver,
99 // because we may be invoked by CameraService::Client::connect() and will
100 // deadlock if we call any method of ICamera here.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101}
102
Chih-Chung Change25cc652010-05-06 16:36:58 +0800103int32_t Camera::getNumberOfCameras()
104{
105 const sp<ICameraService>& cs = getCameraService();
106 if (cs == 0) return 0;
107 return cs->getNumberOfCameras();
108}
109
Chih-Chung Changb8bb78f2010-06-10 13:32:16 +0800110status_t Camera::getCameraInfo(int cameraId,
111 struct CameraInfo* cameraInfo) {
112 const sp<ICameraService>& cs = getCameraService();
113 if (cs == 0) return UNKNOWN_ERROR;
114 return cs->getCameraInfo(cameraId, cameraInfo);
115}
116
Chih-Chung Change25cc652010-05-06 16:36:58 +0800117sp<Camera> Camera::connect(int cameraId)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118{
119 LOGV("connect");
120 sp<Camera> c = new Camera();
121 const sp<ICameraService>& cs = getCameraService();
122 if (cs != 0) {
Chih-Chung Change25cc652010-05-06 16:36:58 +0800123 c->mCamera = cs->connect(c, cameraId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800124 }
125 if (c->mCamera != 0) {
126 c->mCamera->asBinder()->linkToDeath(c);
127 c->mStatus = NO_ERROR;
128 } else {
129 c.clear();
130 }
131 return c;
132}
133
134void Camera::disconnect()
135{
136 LOGV("disconnect");
137 if (mCamera != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800138 mCamera->disconnect();
Chih-Chung Changcfea8fd2010-03-24 16:38:02 -0700139 mCamera->asBinder()->unlinkToDeath(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140 mCamera = 0;
141 }
142}
143
144status_t Camera::reconnect()
145{
146 LOGV("reconnect");
147 sp <ICamera> c = mCamera;
148 if (c == 0) return NO_INIT;
149 return c->connect(this);
150}
151
152sp<ICamera> Camera::remote()
153{
154 return mCamera;
155}
156
157status_t Camera::lock()
158{
159 sp <ICamera> c = mCamera;
160 if (c == 0) return NO_INIT;
161 return c->lock();
162}
163
164status_t Camera::unlock()
165{
166 sp <ICamera> c = mCamera;
167 if (c == 0) return NO_INIT;
168 return c->unlock();
169}
170
171// pass the buffered ISurface to the camera service
172status_t Camera::setPreviewDisplay(const sp<Surface>& surface)
173{
174 LOGV("setPreviewDisplay");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800175 sp <ICamera> c = mCamera;
176 if (c == 0) return NO_INIT;
Wu-cheng Lib8a10fe2009-06-23 23:37:36 +0800177 if (surface != 0) {
178 return c->setPreviewDisplay(surface->getISurface());
179 } else {
180 LOGD("app passed NULL surface");
181 return c->setPreviewDisplay(0);
182 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800183}
184
185status_t Camera::setPreviewDisplay(const sp<ISurface>& surface)
186{
187 LOGV("setPreviewDisplay");
188 if (surface == 0) {
Wu-cheng Lib8a10fe2009-06-23 23:37:36 +0800189 LOGD("app passed NULL surface");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800190 }
191 sp <ICamera> c = mCamera;
192 if (c == 0) return NO_INIT;
193 return c->setPreviewDisplay(surface);
194}
195
196
Wu-cheng Lib8a10fe2009-06-23 23:37:36 +0800197// start preview mode
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800198status_t Camera::startPreview()
199{
200 LOGV("startPreview");
201 sp <ICamera> c = mCamera;
202 if (c == 0) return NO_INIT;
203 return c->startPreview();
204}
205
206// start recording mode, must call setPreviewDisplay first
207status_t Camera::startRecording()
208{
209 LOGV("startRecording");
210 sp <ICamera> c = mCamera;
211 if (c == 0) return NO_INIT;
212 return c->startRecording();
213}
214
215// stop preview mode
216void Camera::stopPreview()
217{
218 LOGV("stopPreview");
219 sp <ICamera> c = mCamera;
220 if (c == 0) return;
221 c->stopPreview();
222}
223
224// stop recording mode
225void Camera::stopRecording()
226{
227 LOGV("stopRecording");
228 sp <ICamera> c = mCamera;
229 if (c == 0) return;
230 c->stopRecording();
231}
232
233// release a recording frame
234void Camera::releaseRecordingFrame(const sp<IMemory>& mem)
235{
236 LOGV("releaseRecordingFrame");
237 sp <ICamera> c = mCamera;
238 if (c == 0) return;
239 c->releaseRecordingFrame(mem);
240}
241
242// get preview state
243bool Camera::previewEnabled()
244{
245 LOGV("previewEnabled");
246 sp <ICamera> c = mCamera;
247 if (c == 0) return false;
248 return c->previewEnabled();
249}
250
251// get recording state
252bool Camera::recordingEnabled()
253{
254 LOGV("recordingEnabled");
255 sp <ICamera> c = mCamera;
256 if (c == 0) return false;
257 return c->recordingEnabled();
258}
259
260status_t Camera::autoFocus()
261{
262 LOGV("autoFocus");
263 sp <ICamera> c = mCamera;
264 if (c == 0) return NO_INIT;
265 return c->autoFocus();
266}
267
Chih-Chung Chang244f8c22009-09-15 14:51:56 +0800268status_t Camera::cancelAutoFocus()
269{
270 LOGV("cancelAutoFocus");
271 sp <ICamera> c = mCamera;
272 if (c == 0) return NO_INIT;
273 return c->cancelAutoFocus();
274}
275
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276// take a picture
277status_t Camera::takePicture()
278{
279 LOGV("takePicture");
280 sp <ICamera> c = mCamera;
281 if (c == 0) return NO_INIT;
282 return c->takePicture();
283}
284
285// set preview/capture parameters - key/value pairs
286status_t Camera::setParameters(const String8& params)
287{
288 LOGV("setParameters");
289 sp <ICamera> c = mCamera;
290 if (c == 0) return NO_INIT;
291 return c->setParameters(params);
292}
293
294// get preview/capture parameters - key/value pairs
295String8 Camera::getParameters() const
296{
297 LOGV("getParameters");
298 String8 params;
299 sp <ICamera> c = mCamera;
300 if (c != 0) params = mCamera->getParameters();
301 return params;
302}
303
Wu-cheng Li36f68b82009-09-28 16:14:58 -0700304// send command to camera driver
305status_t Camera::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2)
306{
Wu-cheng Lica9d9dc2010-02-10 13:01:48 +0800307 LOGV("sendCommand");
Wu-cheng Li36f68b82009-09-28 16:14:58 -0700308 sp <ICamera> c = mCamera;
309 if (c == 0) return NO_INIT;
310 return c->sendCommand(cmd, arg1, arg2);
311}
312
Dave Sparks5e271152009-06-23 17:30:11 -0700313void Camera::setListener(const sp<CameraListener>& listener)
314{
315 Mutex::Autolock _l(mLock);
316 mListener = listener;
317}
318
319void Camera::setPreviewCallbackFlags(int flag)
320{
321 LOGV("setPreviewCallbackFlags");
322 sp <ICamera> c = mCamera;
323 if (c == 0) return;
324 mCamera->setPreviewCallbackFlag(flag);
325}
326
Dave Sparks2a04aef2009-05-07 12:25:25 -0700327// callback from camera service
328void Camera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2)
329{
Dave Sparks5e271152009-06-23 17:30:11 -0700330 sp<CameraListener> listener;
331 {
332 Mutex::Autolock _l(mLock);
333 listener = mListener;
334 }
335 if (listener != NULL) {
336 listener->notify(msgType, ext1, ext2);
337 }
Dave Sparks2a04aef2009-05-07 12:25:25 -0700338}
339
Dave Sparksd6289b12009-05-07 19:27:32 -0700340// callback from camera service when frame or image is ready
341void Camera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr)
Dave Sparks2a04aef2009-05-07 12:25:25 -0700342{
Dave Sparks5e271152009-06-23 17:30:11 -0700343 sp<CameraListener> listener;
344 {
345 Mutex::Autolock _l(mLock);
346 listener = mListener;
347 }
348 if (listener != NULL) {
349 listener->postData(msgType, dataPtr);
350 }
Dave Sparks2a04aef2009-05-07 12:25:25 -0700351}
352
Dave Sparks59c1a932009-07-08 15:56:53 -0700353// callback from camera service when timestamped frame is ready
354void Camera::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr)
355{
356 sp<CameraListener> listener;
357 {
358 Mutex::Autolock _l(mLock);
359 listener = mListener;
360 }
361 if (listener != NULL) {
362 listener->postDataTimestamp(timestamp, msgType, dataPtr);
363 }
364}
365
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800366void Camera::binderDied(const wp<IBinder>& who) {
367 LOGW("ICamera died");
James Donga1b653d2009-07-02 10:04:20 -0700368 notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_SERVER_DIED, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800369}
370
371void Camera::DeathNotifier::binderDied(const wp<IBinder>& who) {
372 LOGV("binderDied");
373 Mutex::Autolock _l(Camera::mLock);
374 Camera::mCameraService.clear();
375 LOGW("Camera server died!");
376}
377
378}; // namespace android
379