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