blob: 203b45ebe0bc8e82d70f9256db0d7b6557db6026 [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 "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
The Android Open Source Projectc2ad2412009-03-19 23:08:54 -070031#include <media/mediaplayer.h>
32#include <media/AudioSystem.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033#include "CameraService.h"
34
Eric Laurenteeea9222009-03-26 01:57:59 -070035#include <cutils/properties.h>
36
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037namespace android {
38
39extern "C" {
40#include <stdio.h>
41#include <sys/types.h>
42#include <sys/stat.h>
43#include <fcntl.h>
44#include <pthread.h>
45}
46
47// When you enable this, as well as DEBUG_REFS=1 and
48// DEBUG_REFS_ENABLED_BY_DEFAULT=0 in libutils/RefBase.cpp, this will track all
49// references to the CameraService::Client in order to catch the case where the
50// client is being destroyed while a callback from the CameraHardwareInterface
51// is outstanding. This is a serious bug because if we make another call into
52// CameraHardwreInterface that itself triggers a callback, we will deadlock.
53
54#define DEBUG_CLIENT_REFERENCES 0
55
56#define PICTURE_TIMEOUT seconds(5)
57
58#define DEBUG_DUMP_PREVIEW_FRAME_TO_FILE 0 /* n-th frame to write */
59#define DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE 0
60#define DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE 0
61
62#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
63static int debug_frame_cnt;
64#endif
65
66// ----------------------------------------------------------------------------
67
68void CameraService::instantiate() {
69 defaultServiceManager()->addService(
70 String16("media.camera"), new CameraService());
71}
72
73// ----------------------------------------------------------------------------
74
75CameraService::CameraService() :
76 BnCameraService()
77{
78 LOGI("CameraService started: pid=%d", getpid());
79}
80
81CameraService::~CameraService()
82{
83 if (mClient != 0) {
84 LOGE("mClient was still connected in destructor!");
85 }
86}
87
88sp<ICamera> CameraService::connect(const sp<ICameraClient>& cameraClient)
89{
90 LOGD("Connect E from ICameraClient %p", cameraClient->asBinder().get());
91
92 Mutex::Autolock lock(mLock);
93 sp<Client> client;
94 if (mClient != 0) {
95 sp<Client> currentClient = mClient.promote();
96 if (currentClient != 0) {
97 sp<ICameraClient> currentCameraClient(currentClient->getCameraClient());
98 if (cameraClient->asBinder() == currentCameraClient->asBinder()) {
99 // this is the same client reconnecting...
100 LOGD("Connect X same client (%p) is reconnecting...", cameraClient->asBinder().get());
101 return currentClient;
102 } else {
103 // it's another client... reject it
104 LOGD("new client (%p) attempting to connect - rejected", cameraClient->asBinder().get());
105 return client;
106 }
107 } else {
108 // can't promote, the previous client has died...
109 LOGD("new client connecting, old reference was dangling...");
110 mClient.clear();
111 }
112 }
113
114 // create a new Client object
115 client = new Client(this, cameraClient, IPCThreadState::self()->getCallingPid());
116 mClient = client;
117#if DEBUG_CLIENT_REFERENCES
118 // Enable tracking for this object, and track increments and decrements of
119 // the refcount.
120 client->trackMe(true, true);
121#endif
122 LOGD("Connect X");
123 return client;
124}
125
126void CameraService::removeClient(const sp<ICameraClient>& cameraClient)
127{
128 // declar this outside the lock to make absolutely sure the
129 // destructor won't be called with the lock held.
130 sp<Client> client;
131
132 Mutex::Autolock lock(mLock);
133
134 if (mClient == 0) {
135 // This happens when we have already disconnected.
136 LOGV("mClient is null.");
137 return;
138 }
139
140 // Promote mClient. It should never fail because we're called from
141 // a binder call, so someone has to have a strong reference.
142 client = mClient.promote();
143 if (client == 0) {
144 LOGW("can't get a strong reference on mClient!");
145 mClient.clear();
146 return;
147 }
148
149 if (cameraClient->asBinder() != client->getCameraClient()->asBinder()) {
150 // ugh! that's not our client!!
151 LOGW("removeClient() called, but mClient doesn't match!");
152 } else {
153 // okay, good, forget about mClient
154 mClient.clear();
155 }
156}
157
The Android Open Source Projectc2ad2412009-03-19 23:08:54 -0700158static sp<MediaPlayer> newMediaPlayer(const char *file)
159{
160 sp<MediaPlayer> mp = new MediaPlayer();
161 if (mp->setDataSource(file) == NO_ERROR) {
Eric Laurenteeea9222009-03-26 01:57:59 -0700162 char value[PROPERTY_VALUE_MAX];
163 property_get("ro.camera.sound.forced", value, "0");
164 if (atoi(value)) {
165 mp->setAudioStreamType(AudioSystem::ENFORCED_AUDIBLE);
166 } else {
167 mp->setAudioStreamType(AudioSystem::SYSTEM);
168 }
The Android Open Source Projectc2ad2412009-03-19 23:08:54 -0700169 mp->prepare();
170 } else {
171 mp.clear();
172 LOGE("Failed to load CameraService sounds.");
173 }
174 return mp;
175}
176
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800177CameraService::Client::Client(const sp<CameraService>& cameraService,
178 const sp<ICameraClient>& cameraClient, pid_t clientPid)
179{
180 LOGD("Client E constructor");
181 mCameraService = cameraService;
182 mCameraClient = cameraClient;
183 mClientPid = clientPid;
184 mHardware = openCameraHardware();
185 mUseOverlay = mHardware->useOverlay();
186
The Android Open Source Projectc2ad2412009-03-19 23:08:54 -0700187 mMediaPlayerClick = newMediaPlayer("/system/media/audio/ui/camera_click.ogg");
188 mMediaPlayerBeep = newMediaPlayer("/system/media/audio/ui/VideoRecord.ogg");
189
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800190 // Callback is disabled by default
191 mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
192 LOGD("Client X constructor");
193}
194
195status_t CameraService::Client::checkPid()
196{
197 if (mClientPid == IPCThreadState::self()->getCallingPid()) return NO_ERROR;
198 LOGW("Attempt to use locked camera (%p) from different process", getCameraClient()->asBinder().get());
199 return -EBUSY;
200}
201
202status_t CameraService::Client::lock()
203{
204 Mutex::Autolock _l(mLock);
205 // lock camera to this client if the the camera is unlocked
206 if (mClientPid == 0) {
207 mClientPid = IPCThreadState::self()->getCallingPid();
208 return NO_ERROR;
209 }
210 // returns NO_ERROR if the client already owns the camera, -EBUSY otherwise
211 return checkPid();
212}
213
214status_t CameraService::Client::unlock()
215{
216 Mutex::Autolock _l(mLock);
217 // allow anyone to use camera
218 LOGV("unlock (%p)", getCameraClient()->asBinder().get());
219 status_t result = checkPid();
220 if (result == NO_ERROR) mClientPid = 0;
221 return result;
222}
223
224status_t CameraService::Client::connect(const sp<ICameraClient>& client)
225{
226 // connect a new process to the camera
227 LOGV("connect (%p)", client->asBinder().get());
228
229 // I hate this hack, but things get really ugly when the media recorder
230 // service is handing back the camera to the app. The ICameraClient
231 // destructor will be called during the same IPC, making it look like
232 // the remote client is trying to disconnect. This hack temporarily
233 // sets the mClientPid to an invalid pid to prevent the hardware from
234 // being torn down.
235 {
236
237 // hold a reference to the old client or we will deadlock if the client is
238 // in the same process and we hold the lock when we remove the reference
239 sp<ICameraClient> oldClient;
240 {
241 Mutex::Autolock _l(mLock);
242 if (mClientPid != 0) {
243 LOGW("Tried to connect to locked camera");
244 return -EBUSY;
245 }
246 oldClient = mCameraClient;
247
248 // did the client actually change?
249 if (client->asBinder() == mCameraClient->asBinder()) return NO_ERROR;
250
251 mCameraClient = client;
252 mClientPid = -1;
253 mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
254 LOGV("connect new process (%d) to existing camera client", mClientPid);
255 }
256
257 }
258 // the old client destructor is called when oldClient goes out of scope
259 // now we set the new PID to lock the interface again
260 mClientPid = IPCThreadState::self()->getCallingPid();
261
262 return NO_ERROR;
263}
264
265#if HAVE_ANDROID_OS
266static void *unregister_surface(void *arg)
267{
268 ISurface *surface = (ISurface *)arg;
269 surface->unregisterBuffers();
270 IPCThreadState::self()->flushCommands();
271 return NULL;
272}
273#endif
274
275CameraService::Client::~Client()
276{
277 // tear down client
278 LOGD("Client (%p) E destructor", getCameraClient()->asBinder().get());
279 if (mSurface != 0 && !mUseOverlay) {
280#if HAVE_ANDROID_OS
281 pthread_t thr;
282 // We unregister the buffers in a different thread because binder does
283 // not let us make sychronous transactions in a binder destructor (that
284 // is, upon our reaching a refcount of zero.)
285 pthread_create(&thr, NULL,
286 unregister_surface,
287 mSurface.get());
288 pthread_join(thr, NULL);
289#else
290 mSurface->unregisterBuffers();
291#endif
292 }
293
Jason Sams7f1f3bb2009-03-24 17:58:31 -0700294 if (mMediaPlayerBeep.get() != NULL) {
295 mMediaPlayerBeep->disconnect();
296 mMediaPlayerBeep.clear();
297 }
298 if (mMediaPlayerClick.get() != NULL) {
299 mMediaPlayerClick->disconnect();
300 mMediaPlayerClick.clear();
301 }
The Android Open Source Projectc2ad2412009-03-19 23:08:54 -0700302
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800303 // make sure we tear down the hardware
304 mClientPid = IPCThreadState::self()->getCallingPid();
305 disconnect();
306 LOGD("Client X destructor");
307}
308
309void CameraService::Client::disconnect()
310{
311 LOGD("Client (%p) E disconnect from (%d)",
312 getCameraClient()->asBinder().get(),
313 IPCThreadState::self()->getCallingPid());
314 Mutex::Autolock lock(mLock);
315 if (mClientPid <= 0) {
316 LOGV("camera is unlocked, don't tear down hardware");
317 return;
318 }
319 if (checkPid() != NO_ERROR) {
320 LOGV("Different client - don't disconnect");
321 return;
322 }
323
324 mCameraService->removeClient(mCameraClient);
325 if (mHardware != 0) {
326 LOGV("hardware teardown");
327 // Before destroying mHardware, we must make sure it's in the
328 // idle state.
329 mHardware->stopPreview();
330 // Cancel all picture callbacks.
331 mHardware->cancelPicture(true, true, true);
332 // Release the hardware resources.
333 mHardware->release();
334 }
335 mHardware.clear();
336 LOGD("Client X disconnect");
337}
338
339// pass the buffered ISurface to the camera service
340status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface)
341{
342 LOGD("setPreviewDisplay(%p)", surface.get());
343 Mutex::Autolock lock(mLock);
344 status_t result = checkPid();
345 if (result != NO_ERROR) return result;
346 Mutex::Autolock surfaceLock(mSurfaceLock);
347 // asBinder() is safe on NULL (returns NULL)
348 if (surface->asBinder() != mSurface->asBinder()) {
349 if (mSurface != 0 && !mUseOverlay) {
350 LOGD("clearing old preview surface %p", mSurface.get());
351 mSurface->unregisterBuffers();
352 }
353 mSurface = surface;
354 }
355 return NO_ERROR;
356}
357
358// set the preview callback flag to affect how the received frames from
359// preview are handled.
360void CameraService::Client::setPreviewCallbackFlag(int callback_flag)
361{
362 LOGV("setPreviewCallbackFlag");
363 Mutex::Autolock lock(mLock);
364 if (checkPid() != NO_ERROR) return;
365 mPreviewCallbackFlag = callback_flag;
366}
367
368// start preview mode, must call setPreviewDisplay first
369status_t CameraService::Client::startCameraMode(camera_mode mode)
370{
371 LOGD("startCameraMode(%d)", mode);
372
373 /* we cannot call into mHardware with mLock held because
374 * mHardware has callbacks onto us which acquire this lock
375 */
376
377 Mutex::Autolock lock(mLock);
378 status_t result = checkPid();
379 if (result != NO_ERROR) return result;
380
381 if (mHardware == 0) {
382 LOGE("mHardware is NULL, returning.");
383 return INVALID_OPERATION;
384 }
385
386 if (mSurface == 0) {
387 LOGE("setPreviewDisplay must be called before startCameraMode!");
388 return INVALID_OPERATION;
389 }
390
391 switch(mode) {
392 case CAMERA_RECORDING_MODE:
393 return startRecordingMode();
394
395 default: // CAMERA_PREVIEW_MODE
396 return startPreviewMode();
397 }
398}
399
400status_t CameraService::Client::startRecordingMode()
401{
402 LOGV("startRecordingMode");
403
404 status_t ret = UNKNOWN_ERROR;
405
406 // if preview has not been started, start preview first
407 if (!mHardware->previewEnabled()) {
408 ret = startPreviewMode();
409 if (ret != NO_ERROR) {
410 return ret;
411 }
412 }
413
414 // if recording has been enabled, nothing needs to be done
415 if (mHardware->recordingEnabled()) {
416 return NO_ERROR;
417 }
418
419 // start recording mode
420 ret = mHardware->startRecording(recordingCallback,
421 mCameraService.get());
422 if (ret != NO_ERROR) {
423 LOGE("mHardware->startRecording() failed with status %d", ret);
424 }
425 return ret;
426}
427
428status_t CameraService::Client::startPreviewMode()
429{
430 LOGV("startPreviewMode");
431
432 // if preview has been enabled, nothing needs to be done
433 if (mHardware->previewEnabled()) {
434 return NO_ERROR;
435 }
436
437 // start preview mode
438#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
439 debug_frame_cnt = 0;
440#endif
441 status_t ret = UNKNOWN_ERROR;
442 int w, h;
443 CameraParameters params(mHardware->getParameters());
444 params.getPreviewSize(&w, &h);
445
446 if (mUseOverlay) {
447 const char *format = params.getPreviewFormat();
448 int fmt;
449 LOGD("Use Overlays");
450 if (!strcmp(format, "yuv422i"))
451 fmt = OVERLAY_FORMAT_YCbCr_422_I;
452 else if (!strcmp(format, "rgb565"))
453 fmt = OVERLAY_FORMAT_RGB_565;
454 else {
455 LOGE("Invalid preview format for overlays");
456 return -EINVAL;
457 }
458 sp<OverlayRef> ref = mSurface->createOverlay(w, h, fmt);
459 ret = mHardware->setOverlay(new Overlay(ref));
460 if (ret != NO_ERROR) {
461 LOGE("mHardware->setOverlay() failed with status %d\n", ret);
462 return ret;
463 }
464 ret = mHardware->startPreview(NULL, mCameraService.get());
465 if (ret != NO_ERROR)
466 LOGE("mHardware->startPreview() failed with status %d\n", ret);
467
468 } else {
469 ret = mHardware->startPreview(previewCallback,
470 mCameraService.get());
471 if (ret == NO_ERROR) {
472
473 mSurface->unregisterBuffers();
474
475 uint32_t transform = 0;
476 if (params.getOrientation() ==
477 CameraParameters::CAMERA_ORIENTATION_PORTRAIT) {
478 LOGV("portrait mode");
479 transform = ISurface::BufferHeap::ROT_90;
480 }
481 ISurface::BufferHeap buffers(w, h, w, h,
482 PIXEL_FORMAT_YCbCr_420_SP,
483 transform,
484 0,
485 mHardware->getPreviewHeap());
486
487 mSurface->registerBuffers(buffers);
488 } else {
489 LOGE("mHardware->startPreview() failed with status %d", ret);
490 }
491 }
492 return ret;
493}
494
495status_t CameraService::Client::startPreview()
496{
497 return startCameraMode(CAMERA_PREVIEW_MODE);
498}
499
500status_t CameraService::Client::startRecording()
501{
The Android Open Source Projectc2ad2412009-03-19 23:08:54 -0700502 if (mMediaPlayerBeep.get() != NULL) {
Andreas Huber48733752009-03-24 18:14:23 -0700503 mMediaPlayerBeep->seekTo(0);
The Android Open Source Projectc2ad2412009-03-19 23:08:54 -0700504 mMediaPlayerBeep->start();
505 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800506 return startCameraMode(CAMERA_RECORDING_MODE);
507}
508
509// stop preview mode
510void CameraService::Client::stopPreview()
511{
512 LOGD("stopPreview()");
513
514 Mutex::Autolock lock(mLock);
515 if (checkPid() != NO_ERROR) return;
516
517 if (mHardware == 0) {
518 LOGE("mHardware is NULL, returning.");
519 return;
520 }
521
522 mHardware->stopPreview();
523 LOGD("stopPreview(), hardware stopped OK");
524
525 if (mSurface != 0 && !mUseOverlay) {
526 mSurface->unregisterBuffers();
527 }
528 mPreviewBuffer.clear();
529}
530
531// stop recording mode
532void CameraService::Client::stopRecording()
533{
534 LOGV("stopRecording()");
535
536 Mutex::Autolock lock(mLock);
537 if (checkPid() != NO_ERROR) return;
538
539 if (mHardware == 0) {
540 LOGE("mHardware is NULL, returning.");
541 return;
542 }
543
The Android Open Source Projectc2ad2412009-03-19 23:08:54 -0700544 if (mMediaPlayerBeep.get() != NULL) {
Andreas Huber48733752009-03-24 18:14:23 -0700545 mMediaPlayerBeep->seekTo(0);
The Android Open Source Projectc2ad2412009-03-19 23:08:54 -0700546 mMediaPlayerBeep->start();
547 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800548 mHardware->stopRecording();
549 LOGV("stopRecording(), hardware stopped OK");
550 mPreviewBuffer.clear();
551}
552
553// release a recording frame
554void CameraService::Client::releaseRecordingFrame(const sp<IMemory>& mem)
555{
556 LOGV("releaseRecordingFrame()");
557
558 Mutex::Autolock lock(mLock);
559 if (checkPid() != NO_ERROR) return;
560
561 if (mHardware == 0) {
562 LOGE("mHardware is NULL, returning.");
563 return;
564 }
565
566 mHardware->releaseRecordingFrame(mem);
567}
568
569bool CameraService::Client::previewEnabled()
570{
571 Mutex::Autolock lock(mLock);
572 if (mHardware == 0) return false;
573 return mHardware->previewEnabled();
574}
575
576bool CameraService::Client::recordingEnabled()
577{
578 Mutex::Autolock lock(mLock);
579 if (mHardware == 0) return false;
580 return mHardware->recordingEnabled();
581}
582
583// Safely retrieves a strong pointer to the client during a hardware callback.
584sp<CameraService::Client> CameraService::Client::getClientFromCookie(void* user)
585{
586 sp<Client> client = 0;
587 CameraService *service = static_cast<CameraService*>(user);
588 if (service != NULL) {
589 Mutex::Autolock ourLock(service->mLock);
590 if (service->mClient != 0) {
591 client = service->mClient.promote();
592 if (client == 0) {
593 LOGE("getClientFromCookie: client appears to have died");
594 service->mClient.clear();
595 }
596 } else {
597 LOGE("getClientFromCookie: got callback but client was NULL");
598 }
599 }
600 return client;
601}
602
603
604#if DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE || \
605 DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE || \
606 DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
607static void dump_to_file(const char *fname,
608 uint8_t *buf, uint32_t size)
609{
610 int nw, cnt = 0;
611 uint32_t written = 0;
612
613 LOGD("opening file [%s]\n", fname);
614 int fd = open(fname, O_RDWR | O_CREAT);
615 if (fd < 0) {
616 LOGE("failed to create file [%s]: %s", fname, strerror(errno));
617 return;
618 }
619
620 LOGD("writing %d bytes to file [%s]\n", size, fname);
621 while (written < size) {
622 nw = ::write(fd,
623 buf + written,
624 size - written);
625 if (nw < 0) {
626 LOGE("failed to write to file [%s]: %s",
627 fname, strerror(errno));
628 break;
629 }
630 written += nw;
631 cnt++;
632 }
633 LOGD("done writing %d bytes to file [%s] in %d passes\n",
634 size, fname, cnt);
635 ::close(fd);
636}
637#endif
638
639// preview callback - frame buffer update
640void CameraService::Client::previewCallback(const sp<IMemory>& mem, void* user)
641{
642 LOGV("previewCallback()");
643 sp<Client> client = getClientFromCookie(user);
644 if (client == 0) {
645 return;
646 }
647
648#if DEBUG_HEAP_LEAKS && 0 // debugging
649 if (gWeakHeap == NULL) {
650 ssize_t offset;
651 size_t size;
652 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
653 if (gWeakHeap != heap) {
654 LOGD("SETTING PREVIEW HEAP");
655 heap->trackMe(true, true);
656 gWeakHeap = heap;
657 }
658 }
659#endif
660
661#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
662 {
663 if (debug_frame_cnt++ == DEBUG_DUMP_PREVIEW_FRAME_TO_FILE) {
664 ssize_t offset;
665 size_t size;
666 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
667 dump_to_file("/data/preview.yuv",
668 (uint8_t *)heap->base() + offset, size);
669 }
670 }
671#endif
672
673 // The strong pointer guarantees the client will exist, but no lock is held.
674 client->postPreviewFrame(mem);
675
676#if DEBUG_CLIENT_REFERENCES
677 //**** if the client's refcount is 1, then we are about to destroy it here,
678 // which is bad--print all refcounts.
679 if (client->getStrongCount() == 1) {
680 LOGE("++++++++++++++++ (PREVIEW) THIS WILL CAUSE A LOCKUP!");
681 client->printRefs();
682 }
683#endif
684}
685
686// recording callback
687void CameraService::Client::recordingCallback(const sp<IMemory>& mem, void* user)
688{
689 LOGV("recordingCallback");
690 sp<Client> client = getClientFromCookie(user);
691 if (client == 0) {
692 return;
693 }
694 // The strong pointer guarantees the client will exist, but no lock is held.
695 client->postRecordingFrame(mem);
696}
697
698// take a picture - image is returned in callback
699status_t CameraService::Client::autoFocus()
700{
701 LOGV("autoFocus");
702
703 Mutex::Autolock lock(mLock);
704 status_t result = checkPid();
705 if (result != NO_ERROR) return result;
706
707 if (mHardware == 0) {
708 LOGE("mHardware is NULL, returning.");
709 return INVALID_OPERATION;
710 }
711
712 return mHardware->autoFocus(autoFocusCallback,
713 mCameraService.get());
714}
715
716// take a picture - image is returned in callback
717status_t CameraService::Client::takePicture()
718{
719 LOGD("takePicture");
720
721 Mutex::Autolock lock(mLock);
722 status_t result = checkPid();
723 if (result != NO_ERROR) return result;
724
725 if (mHardware == 0) {
726 LOGE("mHardware is NULL, returning.");
727 return INVALID_OPERATION;
728 }
729
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800730 return mHardware->takePicture(shutterCallback,
731 yuvPictureCallback,
732 jpegPictureCallback,
733 mCameraService.get());
734}
735
736// picture callback - snapshot taken
737void CameraService::Client::shutterCallback(void *user)
738{
739 sp<Client> client = getClientFromCookie(user);
740 if (client == 0) {
741 return;
742 }
743
Wu-cheng Lia34bb202009-03-24 18:01:34 -0700744 // Play shutter sound.
745 if (client->mMediaPlayerClick.get() != NULL) {
Andreas Huber48733752009-03-24 18:14:23 -0700746 client->mMediaPlayerClick->seekTo(0);
Wu-cheng Lia34bb202009-03-24 18:01:34 -0700747 client->mMediaPlayerClick->start();
748 }
749
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800750 // Screen goes black after the buffer is unregistered.
751 if (client->mSurface != 0 && !client->mUseOverlay) {
752 client->mSurface->unregisterBuffers();
753 }
754
755 client->postShutter();
756
757 // It takes some time before yuvPicture callback to be called.
758 // Register the buffer for raw image here to reduce latency.
759 if (client->mSurface != 0 && !client->mUseOverlay) {
760 int w, h;
761 CameraParameters params(client->mHardware->getParameters());
762 params.getPictureSize(&w, &h);
763 uint32_t transform = 0;
764 if (params.getOrientation() == CameraParameters::CAMERA_ORIENTATION_PORTRAIT) {
765 LOGV("portrait mode");
766 transform = ISurface::BufferHeap::ROT_90;
767 }
768 ISurface::BufferHeap buffers(w, h, w, h,
769 PIXEL_FORMAT_YCbCr_420_SP, transform, 0, client->mHardware->getRawHeap());
770
771 client->mSurface->registerBuffers(buffers);
772 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800773}
774
775// picture callback - raw image ready
776void CameraService::Client::yuvPictureCallback(const sp<IMemory>& mem,
777 void *user)
778{
779 sp<Client> client = getClientFromCookie(user);
780 if (client == 0) {
781 return;
782 }
783 if (mem == NULL) {
784 client->postRaw(NULL);
785 client->postError(UNKNOWN_ERROR);
786 return;
787 }
788
789 ssize_t offset;
790 size_t size;
791 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
792#if DEBUG_HEAP_LEAKS && 0 // debugging
793 gWeakHeap = heap; // debugging
794#endif
795
796 //LOGV("yuvPictureCallback(%d, %d, %p)", offset, size, user);
797#if DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE // for testing pursposes only
798 dump_to_file("/data/photo.yuv",
799 (uint8_t *)heap->base() + offset, size);
800#endif
801
802 // Put the YUV version of the snapshot in the preview display.
803 if (client->mSurface != 0 && !client->mUseOverlay) {
804 client->mSurface->postBuffer(offset);
805 }
806
807 client->postRaw(mem);
808
809#if DEBUG_CLIENT_REFERENCES
810 //**** if the client's refcount is 1, then we are about to destroy it here,
811 // which is bad--print all refcounts.
812 if (client->getStrongCount() == 1) {
813 LOGE("++++++++++++++++ (RAW) THIS WILL CAUSE A LOCKUP!");
814 client->printRefs();
815 }
816#endif
817}
818
819// picture callback - jpeg ready
820void CameraService::Client::jpegPictureCallback(const sp<IMemory>& mem, void *user)
821{
822 sp<Client> client = getClientFromCookie(user);
823 if (client == 0) {
824 return;
825 }
826 if (mem == NULL) {
827 client->postJpeg(NULL);
828 client->postError(UNKNOWN_ERROR);
829 return;
830 }
831
832 /** We absolutely CANNOT call into user code with a lock held **/
833
834#if DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE // for testing pursposes only
835 {
836 ssize_t offset;
837 size_t size;
838 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
839 dump_to_file("/data/photo.jpg",
840 (uint8_t *)heap->base() + offset, size);
841 }
842#endif
843
844 client->postJpeg(mem);
845
846#if DEBUG_CLIENT_REFERENCES
847 //**** if the client's refcount is 1, then we are about to destroy it here,
848 // which is bad--print all refcounts.
849 if (client->getStrongCount() == 1) {
850 LOGE("++++++++++++++++ (JPEG) THIS WILL CAUSE A LOCKUP!");
851 client->printRefs();
852 }
853#endif
854}
855
856void CameraService::Client::autoFocusCallback(bool focused, void *user)
857{
858 LOGV("autoFocusCallback");
859
860 sp<Client> client = getClientFromCookie(user);
861 if (client == 0) {
862 return;
863 }
864
865 client->postAutoFocus(focused);
866
867#if DEBUG_CLIENT_REFERENCES
868 if (client->getStrongCount() == 1) {
869 LOGE("++++++++++++++++ (AUTOFOCUS) THIS WILL CAUSE A LOCKUP!");
870 client->printRefs();
871 }
872#endif
873}
874
875// set preview/capture parameters - key/value pairs
876status_t CameraService::Client::setParameters(const String8& params)
877{
878 LOGD("setParameters(%s)", params.string());
879
880 Mutex::Autolock lock(mLock);
881 status_t result = checkPid();
882 if (result != NO_ERROR) return result;
883
884 if (mHardware == 0) {
885 LOGE("mHardware is NULL, returning.");
886 return INVALID_OPERATION;
887 }
888
889 CameraParameters p(params);
890 mHardware->setParameters(p);
891 return NO_ERROR;
892}
893
894// get preview/capture parameters - key/value pairs
895String8 CameraService::Client::getParameters() const
896{
897 LOGD("getParameters");
898
899 Mutex::Autolock lock(mLock);
900
901 if (mHardware == 0) {
902 LOGE("mHardware is NULL, returning.");
903 return String8();
904 }
905
906 return mHardware->getParameters().flatten();
907}
908
909void CameraService::Client::postAutoFocus(bool focused)
910{
911 LOGV("postAutoFocus");
912 mCameraClient->autoFocusCallback(focused);
913}
914
915void CameraService::Client::postShutter()
916{
917 mCameraClient->shutterCallback();
918}
919
920void CameraService::Client::postRaw(const sp<IMemory>& mem)
921{
922 LOGD("postRaw");
923 mCameraClient->rawCallback(mem);
924}
925
926void CameraService::Client::postJpeg(const sp<IMemory>& mem)
927{
928 LOGD("postJpeg");
929 mCameraClient->jpegCallback(mem);
930}
931
932void CameraService::Client::copyFrameAndPostCopiedFrame(sp<IMemoryHeap> heap, size_t offset, size_t size)
933{
934 LOGV("copyFrameAndPostCopiedFrame");
935 // It is necessary to copy out of pmem before sending this to
936 // the callback. For efficiency, reuse the same MemoryHeapBase
937 // provided it's big enough. Don't allocate the memory or
938 // perform the copy if there's no callback.
939 if (mPreviewBuffer == 0) {
940 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
941 } else if (size > mPreviewBuffer->virtualSize()) {
942 mPreviewBuffer.clear();
943 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
944 if (mPreviewBuffer == 0) {
945 LOGE("failed to allocate space for preview buffer");
946 return;
947 }
948 }
949 memcpy(mPreviewBuffer->base(),
950 (uint8_t *)heap->base() + offset, size);
951
952 sp<MemoryBase> frame = new MemoryBase(mPreviewBuffer, 0, size);
953 if (frame == 0) {
954 LOGE("failed to allocate space for frame callback");
955 return;
956 }
957 mCameraClient->previewCallback(frame);
958}
959
960void CameraService::Client::postRecordingFrame(const sp<IMemory>& frame)
961{
962 LOGV("postRecordingFrame");
963 if (frame == 0) {
964 LOGW("frame is a null pointer");
965 return;
966 }
967 mCameraClient->recordingCallback(frame);
968}
969
970void CameraService::Client::postPreviewFrame(const sp<IMemory>& mem)
971{
972 LOGV("postPreviewFrame");
973 if (mem == 0) {
974 LOGW("mem is a null pointer");
975 return;
976 }
977
978 ssize_t offset;
979 size_t size;
980 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
981 {
982 Mutex::Autolock surfaceLock(mSurfaceLock);
983 if (mSurface != NULL) {
984 mSurface->postBuffer(offset);
985 }
986 }
987
988 // Is the callback enabled or not?
989 if (!(mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
990 // If the enable bit is off, the copy-out and one-shot bits are ignored
991 LOGV("frame callback is diabled");
992 return;
993 }
994
995 // Is the received frame copied out or not?
996 if (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
997 LOGV("frame is copied out");
998 copyFrameAndPostCopiedFrame(heap, offset, size);
999 } else {
1000 LOGV("frame is directly sent out without copying");
1001 mCameraClient->previewCallback(mem);
1002 }
1003
1004 // Is this is one-shot only?
1005 if (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) {
1006 LOGV("One-shot only, thus clear the bits and disable frame callback");
1007 mPreviewCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
1008 FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
1009 FRAME_CALLBACK_FLAG_ENABLE_MASK);
1010 }
1011}
1012
1013void CameraService::Client::postError(status_t error)
1014{
1015 mCameraClient->errorCallback(error);
1016}
1017
1018status_t CameraService::dump(int fd, const Vector<String16>& args)
1019{
1020 const size_t SIZE = 256;
1021 char buffer[SIZE];
1022 String8 result;
1023 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
1024 snprintf(buffer, SIZE, "Permission Denial: "
1025 "can't dump CameraService from pid=%d, uid=%d\n",
1026 IPCThreadState::self()->getCallingPid(),
1027 IPCThreadState::self()->getCallingUid());
1028 result.append(buffer);
1029 write(fd, result.string(), result.size());
1030 } else {
1031 AutoMutex lock(&mLock);
1032 if (mClient != 0) {
1033 sp<Client> currentClient = mClient.promote();
1034 sprintf(buffer, "Client (%p) PID: %d\n",
1035 currentClient->getCameraClient()->asBinder().get(),
1036 currentClient->mClientPid);
1037 result.append(buffer);
1038 write(fd, result.string(), result.size());
1039 currentClient->mHardware->dump(fd, args);
1040 } else {
1041 result.append("No camera client yet.\n");
1042 write(fd, result.string(), result.size());
1043 }
1044 }
1045 return NO_ERROR;
1046}
1047
1048
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001049
1050#define CHECK_INTERFACE(interface, data, reply) \
1051 do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
1052 LOGW("Call incorrectly routed to " #interface); \
1053 return PERMISSION_DENIED; \
1054 } } while (0)
1055
1056status_t CameraService::onTransact(
1057 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1058{
1059 // permission checks...
1060 switch (code) {
1061 case BnCameraService::CONNECT:
1062 IPCThreadState* ipc = IPCThreadState::self();
1063 const int pid = ipc->getCallingPid();
1064 const int self_pid = getpid();
1065 if (pid != self_pid) {
1066 // we're called from a different process, do the real check
1067 if (!checkCallingPermission(
1068 String16("android.permission.CAMERA")))
1069 {
1070 const int uid = ipc->getCallingUid();
1071 LOGE("Permission Denial: "
1072 "can't use the camera pid=%d, uid=%d", pid, uid);
1073 return PERMISSION_DENIED;
1074 }
1075 }
1076 break;
1077 }
1078
1079 status_t err = BnCameraService::onTransact(code, data, reply, flags);
1080
Dave Sparks7b7225c2009-05-21 09:18:18 -07001081#if DEBUG_HEAP_LEAKS
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001082 LOGD("+++ onTransact err %d code %d", err, code);
1083
1084 if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
1085 // the 'service' command interrogates this binder for its name, and then supplies it
1086 // even for the debugging commands. that means we need to check for it here, using
1087 // ISurfaceComposer (since we delegated the INTERFACE_TRANSACTION handling to
1088 // BnSurfaceComposer before falling through to this code).
1089
1090 LOGD("+++ onTransact code %d", code);
1091
1092 CHECK_INTERFACE(ICameraService, data, reply);
1093
1094 switch(code) {
1095 case 1000:
1096 {
1097 if (gWeakHeap != 0) {
1098 sp<IMemoryHeap> h = gWeakHeap.promote();
1099 IMemoryHeap *p = gWeakHeap.unsafe_get();
1100 LOGD("CHECKING WEAK REFERENCE %p (%p)", h.get(), p);
1101 if (h != 0)
1102 h->printRefs();
1103 bool attempt_to_delete = data.readInt32() == 1;
1104 if (attempt_to_delete) {
1105 // NOT SAFE!
1106 LOGD("DELETING WEAK REFERENCE %p (%p)", h.get(), p);
1107 if (p) delete p;
1108 }
1109 return NO_ERROR;
1110 }
1111 }
1112 break;
1113 default:
1114 break;
1115 }
1116 }
Dave Sparks7b7225c2009-05-21 09:18:18 -07001117#endif // DEBUG_HEAP_LEAKS
1118
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001119 return err;
1120}
1121
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001122
1123}; // namespace android