blob: e5d42203f5142a1718ec365479cab7c6453bce8a [file] [log] [blame]
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001/*
2**
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08003** Copyright (C) 2008, The Android Open Source Project
4** Copyright (C) 2008 HTC Inc.
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07005**
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
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -080019//#define LOG_NDEBUG 0
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070020#define LOG_TAG "CameraService"
21#include <utils/Log.h>
22
23#include <utils/IServiceManager.h>
24#include <utils/IPCThreadState.h>
25#include <utils/String16.h>
26#include <utils/Errors.h>
27#include <utils/MemoryBase.h>
28#include <utils/MemoryHeapBase.h>
29#include <ui/ICameraService.h>
30
31#include "CameraService.h"
32
33namespace android {
34
35extern "C" {
36#include <stdio.h>
37#include <sys/types.h>
38#include <sys/stat.h>
39#include <fcntl.h>
40#include <pthread.h>
41}
42
43// When you enable this, as well as DEBUG_REFS=1 and
44// DEBUG_REFS_ENABLED_BY_DEFAULT=0 in libutils/RefBase.cpp, this will track all
45// references to the CameraService::Client in order to catch the case where the
46// client is being destroyed while a callback from the CameraHardwareInterface
47// is outstanding. This is a serious bug because if we make another call into
48// CameraHardwreInterface that itself triggers a callback, we will deadlock.
49
50#define DEBUG_CLIENT_REFERENCES 0
51
52#define PICTURE_TIMEOUT seconds(5)
53
54#define DEBUG_DUMP_PREVIEW_FRAME_TO_FILE 0 /* n-th frame to write */
55#define DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE 0
56#define DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE 0
57
58#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
59static int debug_frame_cnt;
60#endif
61
62// ----------------------------------------------------------------------------
63
64void CameraService::instantiate() {
65 defaultServiceManager()->addService(
66 String16("media.camera"), new CameraService());
67}
68
69// ----------------------------------------------------------------------------
70
71CameraService::CameraService() :
72 BnCameraService()
73{
74 LOGI("CameraService started: pid=%d", getpid());
75}
76
77CameraService::~CameraService()
78{
79 if (mClient != 0) {
80 LOGE("mClient was still connected in destructor!");
81 }
82}
83
84sp<ICamera> CameraService::connect(const sp<ICameraClient>& cameraClient)
85{
86 LOGD("Connect E from ICameraClient %p", cameraClient->asBinder().get());
87
88 Mutex::Autolock lock(mLock);
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -080089 sp<Client> client;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070090 if (mClient != 0) {
91 sp<Client> currentClient = mClient.promote();
92 if (currentClient != 0) {
93 sp<ICameraClient> currentCameraClient(currentClient->getCameraClient());
94 if (cameraClient->asBinder() == currentCameraClient->asBinder()) {
95 // this is the same client reconnecting...
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -080096 LOGD("Connect X same client (%p) is reconnecting...", cameraClient->asBinder().get());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070097 return currentClient;
98 } else {
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -080099 // it's another client... reject it
100 LOGD("new client (%p) attempting to connect - rejected", cameraClient->asBinder().get());
101 return client;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700102 }
103 } else {
104 // can't promote, the previous client has died...
105 LOGD("new client connecting, old reference was dangling...");
106 mClient.clear();
107 }
108 }
109
110 // create a new Client object
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800111 client = new Client(this, cameraClient, IPCThreadState::self()->getCallingPid());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700112 mClient = client;
113#if DEBUG_CLIENT_REFERENCES
114 // Enable tracking for this object, and track increments and decrements of
115 // the refcount.
116 client->trackMe(true, true);
117#endif
118 LOGD("Connect X");
119 return client;
120}
121
122void CameraService::removeClient(const sp<ICameraClient>& cameraClient)
123{
124 // declar this outside the lock to make absolutely sure the
125 // destructor won't be called with the lock held.
126 sp<Client> client;
127
128 Mutex::Autolock lock(mLock);
129
130 if (mClient == 0) {
131 // This happens when we have already disconnected.
132 LOGV("mClient is null.");
133 return;
134 }
135
136 // Promote mClient. It should never fail because we're called from
137 // a binder call, so someone has to have a strong reference.
138 client = mClient.promote();
139 if (client == 0) {
140 LOGW("can't get a strong reference on mClient!");
141 mClient.clear();
142 return;
143 }
144
145 if (cameraClient->asBinder() != client->getCameraClient()->asBinder()) {
146 // ugh! that's not our client!!
147 LOGW("removeClient() called, but mClient doesn't match!");
148 } else {
149 // okay, good, forget about mClient
150 mClient.clear();
151 }
152}
153
154CameraService::Client::Client(const sp<CameraService>& cameraService,
The Android Open Source Project43aa2b12009-03-03 14:04:24 -0800155 const sp<ICameraClient>& cameraClient, pid_t clientPid)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700156{
157 LOGD("Client E constructor");
The Android Open Source Project27629322009-01-09 17:51:23 -0800158 mCameraService = cameraService;
159 mCameraClient = cameraClient;
160 mClientPid = clientPid;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700161 mHardware = openCameraHardware();
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800162 mUseOverlay = mHardware->useOverlay();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800163
164 // Callback is disabled by default
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800165 mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700166 LOGD("Client X constructor");
167}
168
The Android Open Source Project27629322009-01-09 17:51:23 -0800169status_t CameraService::Client::checkPid()
170{
The Android Open Source Project5f78a482009-01-20 14:03:58 -0800171 if (mClientPid == IPCThreadState::self()->getCallingPid()) return NO_ERROR;
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800172 LOGW("Attempt to use locked camera (%p) from different process", getCameraClient()->asBinder().get());
The Android Open Source Project5f78a482009-01-20 14:03:58 -0800173 return -EBUSY;
The Android Open Source Project27629322009-01-09 17:51:23 -0800174}
175
176status_t CameraService::Client::lock()
177{
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800178 Mutex::Autolock _l(mLock);
The Android Open Source Project5f78a482009-01-20 14:03:58 -0800179 // lock camera to this client if the the camera is unlocked
180 if (mClientPid == 0) {
181 mClientPid = IPCThreadState::self()->getCallingPid();
182 return NO_ERROR;
183 }
184 // returns NO_ERROR if the client already owns the camera, -EBUSY otherwise
185 return checkPid();
The Android Open Source Project27629322009-01-09 17:51:23 -0800186}
187
188status_t CameraService::Client::unlock()
189{
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800190 Mutex::Autolock _l(mLock);
The Android Open Source Project27629322009-01-09 17:51:23 -0800191 // allow anyone to use camera
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800192 LOGV("unlock (%p)", getCameraClient()->asBinder().get());
The Android Open Source Project27629322009-01-09 17:51:23 -0800193 status_t result = checkPid();
194 if (result == NO_ERROR) mClientPid = 0;
195 return result;
196}
197
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800198status_t CameraService::Client::connect(const sp<ICameraClient>& client)
199{
The Android Open Source Project5f78a482009-01-20 14:03:58 -0800200 // connect a new process to the camera
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800201 LOGV("connect (%p)", client->asBinder().get());
The Android Open Source Project5f78a482009-01-20 14:03:58 -0800202
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800203 // I hate this hack, but things get really ugly when the media recorder
204 // service is handing back the camera to the app. The ICameraClient
205 // destructor will be called during the same IPC, making it look like
206 // the remote client is trying to disconnect. This hack temporarily
207 // sets the mClientPid to an invalid pid to prevent the hardware from
208 // being torn down.
The Android Open Source Project5f78a482009-01-20 14:03:58 -0800209 {
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800210
211 // hold a reference to the old client or we will deadlock if the client is
212 // in the same process and we hold the lock when we remove the reference
213 sp<ICameraClient> oldClient;
214 {
215 Mutex::Autolock _l(mLock);
216 if (mClientPid != 0) {
217 LOGW("Tried to connect to locked camera");
218 return -EBUSY;
219 }
220 oldClient = mCameraClient;
221
222 // did the client actually change?
223 if (client->asBinder() == mCameraClient->asBinder()) return NO_ERROR;
224
225 mCameraClient = client;
226 mClientPid = -1;
227 mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
228 LOGV("connect new process (%d) to existing camera client", mClientPid);
The Android Open Source Project5f78a482009-01-20 14:03:58 -0800229 }
The Android Open Source Project5f78a482009-01-20 14:03:58 -0800230
The Android Open Source Project5f78a482009-01-20 14:03:58 -0800231 }
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800232 // the old client destructor is called when oldClient goes out of scope
233 // now we set the new PID to lock the interface again
234 mClientPid = IPCThreadState::self()->getCallingPid();
The Android Open Source Project5f78a482009-01-20 14:03:58 -0800235
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800236 return NO_ERROR;
237}
238
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700239#if HAVE_ANDROID_OS
240static void *unregister_surface(void *arg)
241{
242 ISurface *surface = (ISurface *)arg;
243 surface->unregisterBuffers();
244 IPCThreadState::self()->flushCommands();
245 return NULL;
246}
247#endif
248
249CameraService::Client::~Client()
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800250{
The Android Open Source Project5f78a482009-01-20 14:03:58 -0800251 // tear down client
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800252 LOGD("Client (%p) E destructor", getCameraClient()->asBinder().get());
253 if (mSurface != 0 && !mUseOverlay) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700254#if HAVE_ANDROID_OS
255 pthread_t thr;
256 // We unregister the buffers in a different thread because binder does
257 // not let us make sychronous transactions in a binder destructor (that
258 // is, upon our reaching a refcount of zero.)
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800259 pthread_create(&thr, NULL,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700260 unregister_surface,
261 mSurface.get());
262 pthread_join(thr, NULL);
263#else
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800264 mSurface->unregisterBuffers();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700265#endif
266 }
267
The Android Open Source Project5f78a482009-01-20 14:03:58 -0800268 // make sure we tear down the hardware
269 mClientPid = IPCThreadState::self()->getCallingPid();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700270 disconnect();
271 LOGD("Client X destructor");
272}
273
274void CameraService::Client::disconnect()
275{
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800276 LOGD("Client (%p) E disconnect from (%d)",
277 getCameraClient()->asBinder().get(),
278 IPCThreadState::self()->getCallingPid());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700279 Mutex::Autolock lock(mLock);
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800280 if (mClientPid <= 0) {
The Android Open Source Project5f78a482009-01-20 14:03:58 -0800281 LOGV("camera is unlocked, don't tear down hardware");
282 return;
283 }
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800284 if (checkPid() != NO_ERROR) {
285 LOGV("Different client - don't disconnect");
286 return;
287 }
The Android Open Source Project5f78a482009-01-20 14:03:58 -0800288
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700289 mCameraService->removeClient(mCameraClient);
290 if (mHardware != 0) {
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800291 LOGV("hardware teardown");
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700292 // Before destroying mHardware, we must make sure it's in the
293 // idle state.
294 mHardware->stopPreview();
295 // Cancel all picture callbacks.
296 mHardware->cancelPicture(true, true, true);
297 // Release the hardware resources.
298 mHardware->release();
299 }
300 mHardware.clear();
301 LOGD("Client X disconnect");
302}
303
304// pass the buffered ISurface to the camera service
305status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface)
306{
307 LOGD("setPreviewDisplay(%p)", surface.get());
308 Mutex::Autolock lock(mLock);
The Android Open Source Project27629322009-01-09 17:51:23 -0800309 status_t result = checkPid();
310 if (result != NO_ERROR) return result;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700311 Mutex::Autolock surfaceLock(mSurfaceLock);
312 // asBinder() is safe on NULL (returns NULL)
313 if (surface->asBinder() != mSurface->asBinder()) {
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800314 if (mSurface != 0 && !mUseOverlay) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700315 LOGD("clearing old preview surface %p", mSurface.get());
316 mSurface->unregisterBuffers();
317 }
318 mSurface = surface;
319 }
320 return NO_ERROR;
321}
322
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800323// set the preview callback flag to affect how the received frames from
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800324// preview are handled.
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800325void CameraService::Client::setPreviewCallbackFlag(int callback_flag)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700326{
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800327 LOGV("setPreviewCallbackFlag");
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700328 Mutex::Autolock lock(mLock);
The Android Open Source Project27629322009-01-09 17:51:23 -0800329 if (checkPid() != NO_ERROR) return;
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800330 mPreviewCallbackFlag = callback_flag;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700331}
332
333// start preview mode, must call setPreviewDisplay first
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800334status_t CameraService::Client::startCameraMode(camera_mode mode)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700335{
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800336 LOGD("startCameraMode(%d)", mode);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700337
338 /* we cannot call into mHardware with mLock held because
339 * mHardware has callbacks onto us which acquire this lock
340 */
341
342 Mutex::Autolock lock(mLock);
The Android Open Source Project27629322009-01-09 17:51:23 -0800343 status_t result = checkPid();
344 if (result != NO_ERROR) return result;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700345
346 if (mHardware == 0) {
347 LOGE("mHardware is NULL, returning.");
348 return INVALID_OPERATION;
349 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800350
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700351 if (mSurface == 0) {
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800352 LOGE("setPreviewDisplay must be called before startCameraMode!");
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700353 return INVALID_OPERATION;
354 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800355
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800356 switch(mode) {
357 case CAMERA_RECORDING_MODE:
358 return startRecordingMode();
The Android Open Source Project27629322009-01-09 17:51:23 -0800359
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800360 default: // CAMERA_PREVIEW_MODE
361 return startPreviewMode();
362 }
363}
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800364
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800365status_t CameraService::Client::startRecordingMode()
366{
367 LOGV("startRecordingMode");
368
369 status_t ret = UNKNOWN_ERROR;
370
371 // if preview has not been started, start preview first
372 if (!mHardware->previewEnabled()) {
373 ret = startPreviewMode();
374 if (ret != NO_ERROR) {
375 return ret;
376 }
377 }
378
379 // if recording has been enabled, nothing needs to be done
380 if (mHardware->recordingEnabled()) {
381 return NO_ERROR;
382 }
383
384 // start recording mode
385 ret = mHardware->startRecording(recordingCallback,
386 mCameraService.get());
387 if (ret != NO_ERROR) {
388 LOGE("mHardware->startRecording() failed with status %d", ret);
389 }
390 return ret;
391}
392
393status_t CameraService::Client::startPreviewMode()
394{
395 LOGV("startPreviewMode");
396
397 // if preview has been enabled, nothing needs to be done
398 if (mHardware->previewEnabled()) {
399 return NO_ERROR;
400 }
401
402 // start preview mode
403#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
404 debug_frame_cnt = 0;
405#endif
406 status_t ret = UNKNOWN_ERROR;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700407 int w, h;
408 CameraParameters params(mHardware->getParameters());
409 params.getPreviewSize(&w, &h);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800410
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800411 if (mUseOverlay) {
412 const char *format = params.getPreviewFormat();
413 int fmt;
414 LOGD("Use Overlays");
415 if (!strcmp(format, "yuv422i"))
416 fmt = OVERLAY_FORMAT_YCbCr_422_I;
417 else if (!strcmp(format, "rgb565"))
418 fmt = OVERLAY_FORMAT_RGB_565;
419 else {
420 LOGE("Invalid preview format for overlays");
421 return -EINVAL;
422 }
423 sp<OverlayRef> ref = mSurface->createOverlay(w, h, fmt);
424 ret = mHardware->setOverlay(new Overlay(ref));
425 if (ret != NO_ERROR) {
426 LOGE("mHardware->setOverlay() failed with status %d\n", ret);
427 return ret;
428 }
429 ret = mHardware->startPreview(NULL, mCameraService.get());
430 if (ret != NO_ERROR)
431 LOGE("mHardware->startPreview() failed with status %d\n", ret);
The Android Open Source Project43aa2b12009-03-03 14:04:24 -0800432
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800433 } else {
434 ret = mHardware->startPreview(previewCallback,
435 mCameraService.get());
436 if (ret == NO_ERROR) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800437
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800438 mSurface->unregisterBuffers();
439
440 uint32_t transform = 0;
441 if (params.getOrientation() ==
442 CameraParameters::CAMERA_ORIENTATION_PORTRAIT) {
443 LOGV("portrait mode");
444 transform = ISurface::BufferHeap::ROT_90;
445 }
446 ISurface::BufferHeap buffers(w, h, w, h,
447 PIXEL_FORMAT_YCbCr_420_SP,
448 transform,
449 0,
450 mHardware->getPreviewHeap());
451
452 mSurface->registerBuffers(buffers);
453 } else {
454 LOGE("mHardware->startPreview() failed with status %d", ret);
455 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700456 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700457 return ret;
458}
459
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800460status_t CameraService::Client::startPreview()
461{
462 return startCameraMode(CAMERA_PREVIEW_MODE);
463}
464
465status_t CameraService::Client::startRecording()
466{
467 return startCameraMode(CAMERA_RECORDING_MODE);
468}
469
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700470// stop preview mode
471void CameraService::Client::stopPreview()
472{
473 LOGD("stopPreview()");
474
475 Mutex::Autolock lock(mLock);
The Android Open Source Project27629322009-01-09 17:51:23 -0800476 if (checkPid() != NO_ERROR) return;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700477
478 if (mHardware == 0) {
479 LOGE("mHardware is NULL, returning.");
480 return;
481 }
482
483 mHardware->stopPreview();
484 LOGD("stopPreview(), hardware stopped OK");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800485
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800486 if (mSurface != 0 && !mUseOverlay) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700487 mSurface->unregisterBuffers();
488 }
489 mPreviewBuffer.clear();
490}
491
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800492// stop recording mode
493void CameraService::Client::stopRecording()
494{
495 LOGV("stopRecording()");
496
497 Mutex::Autolock lock(mLock);
498 if (checkPid() != NO_ERROR) return;
499
500 if (mHardware == 0) {
501 LOGE("mHardware is NULL, returning.");
502 return;
503 }
504
505 mHardware->stopRecording();
506 LOGV("stopRecording(), hardware stopped OK");
507 mPreviewBuffer.clear();
508}
509
510// release a recording frame
511void CameraService::Client::releaseRecordingFrame(const sp<IMemory>& mem)
512{
513 LOGV("releaseRecordingFrame()");
514
515 Mutex::Autolock lock(mLock);
516 if (checkPid() != NO_ERROR) return;
517
518 if (mHardware == 0) {
519 LOGE("mHardware is NULL, returning.");
520 return;
521 }
522
523 mHardware->releaseRecordingFrame(mem);
524}
525
The Android Open Source Project27629322009-01-09 17:51:23 -0800526bool CameraService::Client::previewEnabled()
527{
528 Mutex::Autolock lock(mLock);
529 if (mHardware == 0) return false;
530 return mHardware->previewEnabled();
531}
532
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800533bool CameraService::Client::recordingEnabled()
534{
535 Mutex::Autolock lock(mLock);
536 if (mHardware == 0) return false;
537 return mHardware->recordingEnabled();
538}
539
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700540// Safely retrieves a strong pointer to the client during a hardware callback.
541sp<CameraService::Client> CameraService::Client::getClientFromCookie(void* user)
542{
543 sp<Client> client = 0;
544 CameraService *service = static_cast<CameraService*>(user);
545 if (service != NULL) {
546 Mutex::Autolock ourLock(service->mLock);
547 if (service->mClient != 0) {
548 client = service->mClient.promote();
549 if (client == 0) {
550 LOGE("getClientFromCookie: client appears to have died");
551 service->mClient.clear();
552 }
553 } else {
554 LOGE("getClientFromCookie: got callback but client was NULL");
555 }
556 }
557 return client;
558}
559
560
561#if DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE || \
562 DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE || \
563 DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
564static void dump_to_file(const char *fname,
565 uint8_t *buf, uint32_t size)
566{
567 int nw, cnt = 0;
568 uint32_t written = 0;
569
570 LOGD("opening file [%s]\n", fname);
571 int fd = open(fname, O_RDWR | O_CREAT);
572 if (fd < 0) {
573 LOGE("failed to create file [%s]: %s", fname, strerror(errno));
574 return;
575 }
576
577 LOGD("writing %d bytes to file [%s]\n", size, fname);
578 while (written < size) {
579 nw = ::write(fd,
580 buf + written,
581 size - written);
582 if (nw < 0) {
583 LOGE("failed to write to file [%s]: %s",
584 fname, strerror(errno));
585 break;
586 }
587 written += nw;
588 cnt++;
589 }
590 LOGD("done writing %d bytes to file [%s] in %d passes\n",
591 size, fname, cnt);
592 ::close(fd);
593}
594#endif
595
596// preview callback - frame buffer update
597void CameraService::Client::previewCallback(const sp<IMemory>& mem, void* user)
598{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800599 LOGV("previewCallback()");
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700600 sp<Client> client = getClientFromCookie(user);
601 if (client == 0) {
602 return;
603 }
604
605#if DEBUG_HEAP_LEAKS && 0 // debugging
606 if (gWeakHeap == NULL) {
607 ssize_t offset;
608 size_t size;
609 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
610 if (gWeakHeap != heap) {
611 LOGD("SETTING PREVIEW HEAP");
612 heap->trackMe(true, true);
613 gWeakHeap = heap;
614 }
615 }
616#endif
617
618#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
619 {
620 if (debug_frame_cnt++ == DEBUG_DUMP_PREVIEW_FRAME_TO_FILE) {
621 ssize_t offset;
622 size_t size;
623 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
624 dump_to_file("/data/preview.yuv",
625 (uint8_t *)heap->base() + offset, size);
626 }
627 }
628#endif
629
630 // The strong pointer guarantees the client will exist, but no lock is held.
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800631 client->postPreviewFrame(mem);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700632
633#if DEBUG_CLIENT_REFERENCES
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800634 //**** if the client's refcount is 1, then we are about to destroy it here,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700635 // which is bad--print all refcounts.
636 if (client->getStrongCount() == 1) {
637 LOGE("++++++++++++++++ (PREVIEW) THIS WILL CAUSE A LOCKUP!");
638 client->printRefs();
639 }
640#endif
641}
642
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800643// recording callback
644void CameraService::Client::recordingCallback(const sp<IMemory>& mem, void* user)
645{
646 LOGV("recordingCallback");
647 sp<Client> client = getClientFromCookie(user);
648 if (client == 0) {
649 return;
650 }
651 // The strong pointer guarantees the client will exist, but no lock is held.
652 client->postRecordingFrame(mem);
653}
654
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700655// take a picture - image is returned in callback
656status_t CameraService::Client::autoFocus()
657{
658 LOGV("autoFocus");
659
660 Mutex::Autolock lock(mLock);
The Android Open Source Project27629322009-01-09 17:51:23 -0800661 status_t result = checkPid();
662 if (result != NO_ERROR) return result;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700663
664 if (mHardware == 0) {
665 LOGE("mHardware is NULL, returning.");
666 return INVALID_OPERATION;
667 }
668
669 return mHardware->autoFocus(autoFocusCallback,
670 mCameraService.get());
671}
672
673// take a picture - image is returned in callback
674status_t CameraService::Client::takePicture()
675{
676 LOGD("takePicture");
677
678 Mutex::Autolock lock(mLock);
The Android Open Source Project27629322009-01-09 17:51:23 -0800679 status_t result = checkPid();
680 if (result != NO_ERROR) return result;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700681
682 if (mHardware == 0) {
683 LOGE("mHardware is NULL, returning.");
684 return INVALID_OPERATION;
685 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800686
The Android Open Source Project43aa2b12009-03-03 14:04:24 -0800687 if (mSurface != NULL && !mUseOverlay)
688 mSurface->unregisterBuffers();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700689
The Android Open Source Project43aa2b12009-03-03 14:04:24 -0800690 return mHardware->takePicture(shutterCallback,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700691 yuvPictureCallback,
692 jpegPictureCallback,
693 mCameraService.get());
694}
695
696// picture callback - snapshot taken
697void CameraService::Client::shutterCallback(void *user)
698{
699 sp<Client> client = getClientFromCookie(user);
700 if (client == 0) {
701 return;
702 }
703
704 client->postShutter();
705}
706
707// picture callback - raw image ready
708void CameraService::Client::yuvPictureCallback(const sp<IMemory>& mem,
709 void *user)
710{
711 sp<Client> client = getClientFromCookie(user);
712 if (client == 0) {
713 return;
714 }
715 if (mem == NULL) {
716 client->postRaw(NULL);
717 client->postError(UNKNOWN_ERROR);
718 return;
719 }
720
721 ssize_t offset;
722 size_t size;
723 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
724#if DEBUG_HEAP_LEAKS && 0 // debugging
725 gWeakHeap = heap; // debugging
726#endif
727
728 //LOGV("yuvPictureCallback(%d, %d, %p)", offset, size, user);
729#if DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE // for testing pursposes only
730 dump_to_file("/data/photo.yuv",
731 (uint8_t *)heap->base() + offset, size);
732#endif
733
734 // Put the YUV version of the snapshot in the preview display.
The Android Open Source Project43aa2b12009-03-03 14:04:24 -0800735 int w, h;
736 CameraParameters params(client->mHardware->getParameters());
737 params.getPictureSize(&w, &h);
738
739// Mutex::Autolock clientLock(client->mLock);
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800740 if (client->mSurface != 0 && !client->mUseOverlay) {
The Android Open Source Project43aa2b12009-03-03 14:04:24 -0800741 client->mSurface->unregisterBuffers();
742
743 uint32_t transform = 0;
744 if (params.getOrientation() == CameraParameters::CAMERA_ORIENTATION_PORTRAIT) {
745 LOGV("portrait mode");
746 transform = ISurface::BufferHeap::ROT_90;
747 }
748 ISurface::BufferHeap buffers(w, h, w, h,
749 PIXEL_FORMAT_YCbCr_420_SP, transform, 0, heap);
750
751 client->mSurface->registerBuffers(buffers);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700752 client->mSurface->postBuffer(offset);
753 }
754
755 client->postRaw(mem);
756
757#if DEBUG_CLIENT_REFERENCES
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800758 //**** if the client's refcount is 1, then we are about to destroy it here,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700759 // which is bad--print all refcounts.
760 if (client->getStrongCount() == 1) {
761 LOGE("++++++++++++++++ (RAW) THIS WILL CAUSE A LOCKUP!");
762 client->printRefs();
763 }
764#endif
765}
766
767// picture callback - jpeg ready
768void CameraService::Client::jpegPictureCallback(const sp<IMemory>& mem, void *user)
769{
770 sp<Client> client = getClientFromCookie(user);
771 if (client == 0) {
772 return;
773 }
774 if (mem == NULL) {
775 client->postJpeg(NULL);
776 client->postError(UNKNOWN_ERROR);
777 return;
778 }
779
780 /** We absolutely CANNOT call into user code with a lock held **/
781
782#if DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE // for testing pursposes only
783 {
784 ssize_t offset;
785 size_t size;
786 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
787 dump_to_file("/data/photo.jpg",
788 (uint8_t *)heap->base() + offset, size);
789 }
790#endif
791
792 client->postJpeg(mem);
793
794#if DEBUG_CLIENT_REFERENCES
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800795 //**** if the client's refcount is 1, then we are about to destroy it here,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700796 // which is bad--print all refcounts.
797 if (client->getStrongCount() == 1) {
798 LOGE("++++++++++++++++ (JPEG) THIS WILL CAUSE A LOCKUP!");
799 client->printRefs();
800 }
801#endif
802}
803
804void CameraService::Client::autoFocusCallback(bool focused, void *user)
805{
806 LOGV("autoFocusCallback");
807
808 sp<Client> client = getClientFromCookie(user);
809 if (client == 0) {
810 return;
811 }
812
813 client->postAutoFocus(focused);
814
815#if DEBUG_CLIENT_REFERENCES
816 if (client->getStrongCount() == 1) {
817 LOGE("++++++++++++++++ (AUTOFOCUS) THIS WILL CAUSE A LOCKUP!");
818 client->printRefs();
819 }
820#endif
821}
822
823// set preview/capture parameters - key/value pairs
824status_t CameraService::Client::setParameters(const String8& params)
825{
826 LOGD("setParameters(%s)", params.string());
827
828 Mutex::Autolock lock(mLock);
The Android Open Source Project27629322009-01-09 17:51:23 -0800829 status_t result = checkPid();
830 if (result != NO_ERROR) return result;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700831
832 if (mHardware == 0) {
833 LOGE("mHardware is NULL, returning.");
834 return INVALID_OPERATION;
835 }
836
837 CameraParameters p(params);
838 mHardware->setParameters(p);
839 return NO_ERROR;
840}
841
842// get preview/capture parameters - key/value pairs
843String8 CameraService::Client::getParameters() const
844{
845 LOGD("getParameters");
846
847 Mutex::Autolock lock(mLock);
848
849 if (mHardware == 0) {
850 LOGE("mHardware is NULL, returning.");
851 return String8();
852 }
853
854 return mHardware->getParameters().flatten();
855}
856
857void CameraService::Client::postAutoFocus(bool focused)
858{
859 LOGV("postAutoFocus");
860 mCameraClient->autoFocusCallback(focused);
861}
862
863void CameraService::Client::postShutter()
864{
865 mCameraClient->shutterCallback();
866}
867
868void CameraService::Client::postRaw(const sp<IMemory>& mem)
869{
870 LOGD("postRaw");
871 mCameraClient->rawCallback(mem);
872}
873
874void CameraService::Client::postJpeg(const sp<IMemory>& mem)
875{
876 LOGD("postJpeg");
877 mCameraClient->jpegCallback(mem);
878}
879
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800880void CameraService::Client::copyFrameAndPostCopiedFrame(sp<IMemoryHeap> heap, size_t offset, size_t size)
881{
882 LOGV("copyFrameAndPostCopiedFrame");
883 // It is necessary to copy out of pmem before sending this to
884 // the callback. For efficiency, reuse the same MemoryHeapBase
885 // provided it's big enough. Don't allocate the memory or
886 // perform the copy if there's no callback.
887 if (mPreviewBuffer == 0) {
888 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
889 } else if (size > mPreviewBuffer->virtualSize()) {
890 mPreviewBuffer.clear();
891 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
892 if (mPreviewBuffer == 0) {
893 LOGE("failed to allocate space for preview buffer");
894 return;
895 }
896 }
897 memcpy(mPreviewBuffer->base(),
898 (uint8_t *)heap->base() + offset, size);
899
900 sp<MemoryBase> frame = new MemoryBase(mPreviewBuffer, 0, size);
901 if (frame == 0) {
902 LOGE("failed to allocate space for frame callback");
903 return;
904 }
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800905 mCameraClient->previewCallback(frame);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800906}
907
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800908void CameraService::Client::postRecordingFrame(const sp<IMemory>& frame)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700909{
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800910 LOGV("postRecordingFrame");
911 if (frame == 0) {
912 LOGW("frame is a null pointer");
913 return;
914 }
915 mCameraClient->recordingCallback(frame);
916}
917
918void CameraService::Client::postPreviewFrame(const sp<IMemory>& mem)
919{
920 LOGV("postPreviewFrame");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800921 if (mem == 0) {
922 LOGW("mem is a null pointer");
923 return;
924 }
925
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700926 ssize_t offset;
927 size_t size;
928 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700929 {
930 Mutex::Autolock surfaceLock(mSurfaceLock);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800931 if (mSurface != NULL) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700932 mSurface->postBuffer(offset);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700933 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700934 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800935
936 // Is the callback enabled or not?
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800937 if (!(mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800938 // If the enable bit is off, the copy-out and one-shot bits are ignored
939 LOGV("frame callback is diabled");
940 return;
941 }
942
943 // Is the received frame copied out or not?
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800944 if (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800945 LOGV("frame is copied out");
946 copyFrameAndPostCopiedFrame(heap, offset, size);
947 } else {
948 LOGV("frame is directly sent out without copying");
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800949 mCameraClient->previewCallback(mem);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800950 }
951
952 // Is this is one-shot only?
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800953 if (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800954 LOGV("One-shot only, thus clear the bits and disable frame callback");
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800955 mPreviewCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800956 FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
957 FRAME_CALLBACK_FLAG_ENABLE_MASK);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700958 }
959}
960
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800961void CameraService::Client::postError(status_t error)
962{
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700963 mCameraClient->errorCallback(error);
964}
965
966status_t CameraService::dump(int fd, const Vector<String16>& args)
967{
968 const size_t SIZE = 256;
969 char buffer[SIZE];
970 String8 result;
971 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
972 snprintf(buffer, SIZE, "Permission Denial: "
973 "can't dump CameraService from pid=%d, uid=%d\n",
974 IPCThreadState::self()->getCallingPid(),
975 IPCThreadState::self()->getCallingUid());
976 result.append(buffer);
977 write(fd, result.string(), result.size());
978 } else {
979 AutoMutex lock(&mLock);
980 if (mClient != 0) {
981 sp<Client> currentClient = mClient.promote();
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -0800982 sprintf(buffer, "Client (%p) PID: %d",
983 currentClient->getCameraClient()->asBinder().get(),
984 currentClient->mClientPid);
985 result.append(buffer);
986 write(fd, result.string(), result.size());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700987 currentClient->mHardware->dump(fd, args);
988 } else {
989 result.append("No camera client yet.\n");
990 write(fd, result.string(), result.size());
991 }
992 }
993 return NO_ERROR;
994}
995
996
997#if DEBUG_HEAP_LEAKS
998
999#define CHECK_INTERFACE(interface, data, reply) \
1000 do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
1001 LOGW("Call incorrectly routed to " #interface); \
1002 return PERMISSION_DENIED; \
1003 } } while (0)
1004
1005status_t CameraService::onTransact(
1006 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1007{
1008 // permission checks...
1009 switch (code) {
1010 case BnCameraService::CONNECT:
1011 IPCThreadState* ipc = IPCThreadState::self();
1012 const int pid = ipc->getCallingPid();
1013 const int self_pid = getpid();
1014 if (pid != self_pid) {
1015 // we're called from a different process, do the real check
1016 if (!checkCallingPermission(
1017 String16("android.permission.CAMERA")))
1018 {
1019 const int uid = ipc->getCallingUid();
1020 LOGE("Permission Denial: "
1021 "can't use the camera pid=%d, uid=%d", pid, uid);
1022 return PERMISSION_DENIED;
1023 }
1024 }
1025 break;
1026 }
1027
1028 status_t err = BnCameraService::onTransact(code, data, reply, flags);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08001029
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001030 LOGD("+++ onTransact err %d code %d", err, code);
1031
1032 if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
1033 // the 'service' command interrogates this binder for its name, and then supplies it
1034 // even for the debugging commands. that means we need to check for it here, using
1035 // ISurfaceComposer (since we delegated the INTERFACE_TRANSACTION handling to
1036 // BnSurfaceComposer before falling through to this code).
1037
1038 LOGD("+++ onTransact code %d", code);
1039
1040 CHECK_INTERFACE(ICameraService, data, reply);
1041
1042 switch(code) {
1043 case 1000:
1044 {
1045 if (gWeakHeap != 0) {
1046 sp<IMemoryHeap> h = gWeakHeap.promote();
1047 IMemoryHeap *p = gWeakHeap.unsafe_get();
1048 LOGD("CHECKING WEAK REFERENCE %p (%p)", h.get(), p);
1049 if (h != 0)
1050 h->printRefs();
1051 bool attempt_to_delete = data.readInt32() == 1;
1052 if (attempt_to_delete) {
1053 // NOT SAFE!
1054 LOGD("DELETING WEAK REFERENCE %p (%p)", h.get(), p);
1055 if (p) delete p;
1056 }
1057 return NO_ERROR;
1058 }
1059 }
1060 break;
1061 default:
1062 break;
1063 }
1064 }
1065 return err;
1066}
1067
1068#endif // DEBUG_HEAP_LEAKS
1069
1070}; // namespace android