blob: 6a6a811fa790e88793a48434917d15ac338bf5a1 [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) {
495 mMediaPlayerBeep->start();
496 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800497 return startCameraMode(CAMERA_RECORDING_MODE);
498}
499
500// stop preview mode
501void CameraService::Client::stopPreview()
502{
503 LOGD("stopPreview()");
504
505 Mutex::Autolock lock(mLock);
506 if (checkPid() != NO_ERROR) return;
507
508 if (mHardware == 0) {
509 LOGE("mHardware is NULL, returning.");
510 return;
511 }
512
513 mHardware->stopPreview();
514 LOGD("stopPreview(), hardware stopped OK");
515
516 if (mSurface != 0 && !mUseOverlay) {
517 mSurface->unregisterBuffers();
518 }
519 mPreviewBuffer.clear();
520}
521
522// stop recording mode
523void CameraService::Client::stopRecording()
524{
525 LOGV("stopRecording()");
526
527 Mutex::Autolock lock(mLock);
528 if (checkPid() != NO_ERROR) return;
529
530 if (mHardware == 0) {
531 LOGE("mHardware is NULL, returning.");
532 return;
533 }
534
Jason Sams78b877e2009-03-24 20:21:36 -0700535 if (mMediaPlayerBeep.get() != NULL) {
536 mMediaPlayerBeep->start();
537 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800538 mHardware->stopRecording();
539 LOGV("stopRecording(), hardware stopped OK");
540 mPreviewBuffer.clear();
541}
542
543// release a recording frame
544void CameraService::Client::releaseRecordingFrame(const sp<IMemory>& mem)
545{
546 LOGV("releaseRecordingFrame()");
547
548 Mutex::Autolock lock(mLock);
549 if (checkPid() != NO_ERROR) return;
550
551 if (mHardware == 0) {
552 LOGE("mHardware is NULL, returning.");
553 return;
554 }
555
556 mHardware->releaseRecordingFrame(mem);
557}
558
559bool CameraService::Client::previewEnabled()
560{
561 Mutex::Autolock lock(mLock);
562 if (mHardware == 0) return false;
563 return mHardware->previewEnabled();
564}
565
566bool CameraService::Client::recordingEnabled()
567{
568 Mutex::Autolock lock(mLock);
569 if (mHardware == 0) return false;
570 return mHardware->recordingEnabled();
571}
572
573// Safely retrieves a strong pointer to the client during a hardware callback.
574sp<CameraService::Client> CameraService::Client::getClientFromCookie(void* user)
575{
576 sp<Client> client = 0;
577 CameraService *service = static_cast<CameraService*>(user);
578 if (service != NULL) {
579 Mutex::Autolock ourLock(service->mLock);
580 if (service->mClient != 0) {
581 client = service->mClient.promote();
582 if (client == 0) {
583 LOGE("getClientFromCookie: client appears to have died");
584 service->mClient.clear();
585 }
586 } else {
587 LOGE("getClientFromCookie: got callback but client was NULL");
588 }
589 }
590 return client;
591}
592
593
594#if DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE || \
595 DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE || \
596 DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
597static void dump_to_file(const char *fname,
598 uint8_t *buf, uint32_t size)
599{
600 int nw, cnt = 0;
601 uint32_t written = 0;
602
603 LOGD("opening file [%s]\n", fname);
604 int fd = open(fname, O_RDWR | O_CREAT);
605 if (fd < 0) {
606 LOGE("failed to create file [%s]: %s", fname, strerror(errno));
607 return;
608 }
609
610 LOGD("writing %d bytes to file [%s]\n", size, fname);
611 while (written < size) {
612 nw = ::write(fd,
613 buf + written,
614 size - written);
615 if (nw < 0) {
616 LOGE("failed to write to file [%s]: %s",
617 fname, strerror(errno));
618 break;
619 }
620 written += nw;
621 cnt++;
622 }
623 LOGD("done writing %d bytes to file [%s] in %d passes\n",
624 size, fname, cnt);
625 ::close(fd);
626}
627#endif
628
629// preview callback - frame buffer update
630void CameraService::Client::previewCallback(const sp<IMemory>& mem, void* user)
631{
632 LOGV("previewCallback()");
633 sp<Client> client = getClientFromCookie(user);
634 if (client == 0) {
635 return;
636 }
637
638#if DEBUG_HEAP_LEAKS && 0 // debugging
639 if (gWeakHeap == NULL) {
640 ssize_t offset;
641 size_t size;
642 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
643 if (gWeakHeap != heap) {
644 LOGD("SETTING PREVIEW HEAP");
645 heap->trackMe(true, true);
646 gWeakHeap = heap;
647 }
648 }
649#endif
650
651#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
652 {
653 if (debug_frame_cnt++ == DEBUG_DUMP_PREVIEW_FRAME_TO_FILE) {
654 ssize_t offset;
655 size_t size;
656 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
657 dump_to_file("/data/preview.yuv",
658 (uint8_t *)heap->base() + offset, size);
659 }
660 }
661#endif
662
663 // The strong pointer guarantees the client will exist, but no lock is held.
664 client->postPreviewFrame(mem);
665
666#if DEBUG_CLIENT_REFERENCES
667 //**** if the client's refcount is 1, then we are about to destroy it here,
668 // which is bad--print all refcounts.
669 if (client->getStrongCount() == 1) {
670 LOGE("++++++++++++++++ (PREVIEW) THIS WILL CAUSE A LOCKUP!");
671 client->printRefs();
672 }
673#endif
674}
675
676// recording callback
677void CameraService::Client::recordingCallback(const sp<IMemory>& mem, void* user)
678{
679 LOGV("recordingCallback");
680 sp<Client> client = getClientFromCookie(user);
681 if (client == 0) {
682 return;
683 }
684 // The strong pointer guarantees the client will exist, but no lock is held.
685 client->postRecordingFrame(mem);
686}
687
688// take a picture - image is returned in callback
689status_t CameraService::Client::autoFocus()
690{
691 LOGV("autoFocus");
692
693 Mutex::Autolock lock(mLock);
694 status_t result = checkPid();
695 if (result != NO_ERROR) return result;
696
697 if (mHardware == 0) {
698 LOGE("mHardware is NULL, returning.");
699 return INVALID_OPERATION;
700 }
701
702 return mHardware->autoFocus(autoFocusCallback,
703 mCameraService.get());
704}
705
706// take a picture - image is returned in callback
707status_t CameraService::Client::takePicture()
708{
709 LOGD("takePicture");
710
711 Mutex::Autolock lock(mLock);
712 status_t result = checkPid();
713 if (result != NO_ERROR) return result;
714
715 if (mHardware == 0) {
716 LOGE("mHardware is NULL, returning.");
717 return INVALID_OPERATION;
718 }
719
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800720 return mHardware->takePicture(shutterCallback,
721 yuvPictureCallback,
722 jpegPictureCallback,
723 mCameraService.get());
724}
725
726// picture callback - snapshot taken
727void CameraService::Client::shutterCallback(void *user)
728{
729 sp<Client> client = getClientFromCookie(user);
730 if (client == 0) {
731 return;
732 }
733
Wu-cheng Liaab44b82009-03-24 20:39:09 -0700734 // Play shutter sound.
735 if (client->mMediaPlayerClick.get() != NULL) {
736 client->mMediaPlayerClick->start();
737 }
738
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800739 // Screen goes black after the buffer is unregistered.
740 if (client->mSurface != 0 && !client->mUseOverlay) {
741 client->mSurface->unregisterBuffers();
742 }
743
744 client->postShutter();
745
746 // It takes some time before yuvPicture callback to be called.
747 // Register the buffer for raw image here to reduce latency.
748 if (client->mSurface != 0 && !client->mUseOverlay) {
749 int w, h;
750 CameraParameters params(client->mHardware->getParameters());
751 params.getPictureSize(&w, &h);
752 uint32_t transform = 0;
753 if (params.getOrientation() == CameraParameters::CAMERA_ORIENTATION_PORTRAIT) {
754 LOGV("portrait mode");
755 transform = ISurface::BufferHeap::ROT_90;
756 }
757 ISurface::BufferHeap buffers(w, h, w, h,
758 PIXEL_FORMAT_YCbCr_420_SP, transform, 0, client->mHardware->getRawHeap());
759
760 client->mSurface->registerBuffers(buffers);
761 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800762}
763
764// picture callback - raw image ready
765void CameraService::Client::yuvPictureCallback(const sp<IMemory>& mem,
766 void *user)
767{
768 sp<Client> client = getClientFromCookie(user);
769 if (client == 0) {
770 return;
771 }
772 if (mem == NULL) {
773 client->postRaw(NULL);
774 client->postError(UNKNOWN_ERROR);
775 return;
776 }
777
778 ssize_t offset;
779 size_t size;
780 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
781#if DEBUG_HEAP_LEAKS && 0 // debugging
782 gWeakHeap = heap; // debugging
783#endif
784
785 //LOGV("yuvPictureCallback(%d, %d, %p)", offset, size, user);
786#if DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE // for testing pursposes only
787 dump_to_file("/data/photo.yuv",
788 (uint8_t *)heap->base() + offset, size);
789#endif
790
791 // Put the YUV version of the snapshot in the preview display.
792 if (client->mSurface != 0 && !client->mUseOverlay) {
793 client->mSurface->postBuffer(offset);
794 }
795
796 client->postRaw(mem);
797
798#if DEBUG_CLIENT_REFERENCES
799 //**** if the client's refcount is 1, then we are about to destroy it here,
800 // which is bad--print all refcounts.
801 if (client->getStrongCount() == 1) {
802 LOGE("++++++++++++++++ (RAW) THIS WILL CAUSE A LOCKUP!");
803 client->printRefs();
804 }
805#endif
806}
807
808// picture callback - jpeg ready
809void CameraService::Client::jpegPictureCallback(const sp<IMemory>& mem, void *user)
810{
811 sp<Client> client = getClientFromCookie(user);
812 if (client == 0) {
813 return;
814 }
815 if (mem == NULL) {
816 client->postJpeg(NULL);
817 client->postError(UNKNOWN_ERROR);
818 return;
819 }
820
821 /** We absolutely CANNOT call into user code with a lock held **/
822
823#if DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE // for testing pursposes only
824 {
825 ssize_t offset;
826 size_t size;
827 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
828 dump_to_file("/data/photo.jpg",
829 (uint8_t *)heap->base() + offset, size);
830 }
831#endif
832
833 client->postJpeg(mem);
834
835#if DEBUG_CLIENT_REFERENCES
836 //**** if the client's refcount is 1, then we are about to destroy it here,
837 // which is bad--print all refcounts.
838 if (client->getStrongCount() == 1) {
839 LOGE("++++++++++++++++ (JPEG) THIS WILL CAUSE A LOCKUP!");
840 client->printRefs();
841 }
842#endif
843}
844
845void CameraService::Client::autoFocusCallback(bool focused, void *user)
846{
847 LOGV("autoFocusCallback");
848
849 sp<Client> client = getClientFromCookie(user);
850 if (client == 0) {
851 return;
852 }
853
854 client->postAutoFocus(focused);
855
856#if DEBUG_CLIENT_REFERENCES
857 if (client->getStrongCount() == 1) {
858 LOGE("++++++++++++++++ (AUTOFOCUS) THIS WILL CAUSE A LOCKUP!");
859 client->printRefs();
860 }
861#endif
862}
863
864// set preview/capture parameters - key/value pairs
865status_t CameraService::Client::setParameters(const String8& params)
866{
867 LOGD("setParameters(%s)", params.string());
868
869 Mutex::Autolock lock(mLock);
870 status_t result = checkPid();
871 if (result != NO_ERROR) return result;
872
873 if (mHardware == 0) {
874 LOGE("mHardware is NULL, returning.");
875 return INVALID_OPERATION;
876 }
877
878 CameraParameters p(params);
879 mHardware->setParameters(p);
880 return NO_ERROR;
881}
882
883// get preview/capture parameters - key/value pairs
884String8 CameraService::Client::getParameters() const
885{
886 LOGD("getParameters");
887
888 Mutex::Autolock lock(mLock);
889
890 if (mHardware == 0) {
891 LOGE("mHardware is NULL, returning.");
892 return String8();
893 }
894
895 return mHardware->getParameters().flatten();
896}
897
898void CameraService::Client::postAutoFocus(bool focused)
899{
900 LOGV("postAutoFocus");
901 mCameraClient->autoFocusCallback(focused);
902}
903
904void CameraService::Client::postShutter()
905{
906 mCameraClient->shutterCallback();
907}
908
909void CameraService::Client::postRaw(const sp<IMemory>& mem)
910{
911 LOGD("postRaw");
912 mCameraClient->rawCallback(mem);
913}
914
915void CameraService::Client::postJpeg(const sp<IMemory>& mem)
916{
917 LOGD("postJpeg");
918 mCameraClient->jpegCallback(mem);
919}
920
921void CameraService::Client::copyFrameAndPostCopiedFrame(sp<IMemoryHeap> heap, size_t offset, size_t size)
922{
923 LOGV("copyFrameAndPostCopiedFrame");
924 // It is necessary to copy out of pmem before sending this to
925 // the callback. For efficiency, reuse the same MemoryHeapBase
926 // provided it's big enough. Don't allocate the memory or
927 // perform the copy if there's no callback.
928 if (mPreviewBuffer == 0) {
929 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
930 } else if (size > mPreviewBuffer->virtualSize()) {
931 mPreviewBuffer.clear();
932 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
933 if (mPreviewBuffer == 0) {
934 LOGE("failed to allocate space for preview buffer");
935 return;
936 }
937 }
938 memcpy(mPreviewBuffer->base(),
939 (uint8_t *)heap->base() + offset, size);
940
941 sp<MemoryBase> frame = new MemoryBase(mPreviewBuffer, 0, size);
942 if (frame == 0) {
943 LOGE("failed to allocate space for frame callback");
944 return;
945 }
946 mCameraClient->previewCallback(frame);
947}
948
949void CameraService::Client::postRecordingFrame(const sp<IMemory>& frame)
950{
951 LOGV("postRecordingFrame");
952 if (frame == 0) {
953 LOGW("frame is a null pointer");
954 return;
955 }
956 mCameraClient->recordingCallback(frame);
957}
958
959void CameraService::Client::postPreviewFrame(const sp<IMemory>& mem)
960{
961 LOGV("postPreviewFrame");
962 if (mem == 0) {
963 LOGW("mem is a null pointer");
964 return;
965 }
966
967 ssize_t offset;
968 size_t size;
969 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
970 {
971 Mutex::Autolock surfaceLock(mSurfaceLock);
972 if (mSurface != NULL) {
973 mSurface->postBuffer(offset);
974 }
975 }
976
977 // Is the callback enabled or not?
978 if (!(mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
979 // If the enable bit is off, the copy-out and one-shot bits are ignored
980 LOGV("frame callback is diabled");
981 return;
982 }
983
984 // Is the received frame copied out or not?
985 if (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
986 LOGV("frame is copied out");
987 copyFrameAndPostCopiedFrame(heap, offset, size);
988 } else {
989 LOGV("frame is directly sent out without copying");
990 mCameraClient->previewCallback(mem);
991 }
992
993 // Is this is one-shot only?
994 if (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) {
995 LOGV("One-shot only, thus clear the bits and disable frame callback");
996 mPreviewCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
997 FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
998 FRAME_CALLBACK_FLAG_ENABLE_MASK);
999 }
1000}
1001
1002void CameraService::Client::postError(status_t error)
1003{
1004 mCameraClient->errorCallback(error);
1005}
1006
1007status_t CameraService::dump(int fd, const Vector<String16>& args)
1008{
1009 const size_t SIZE = 256;
1010 char buffer[SIZE];
1011 String8 result;
1012 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
1013 snprintf(buffer, SIZE, "Permission Denial: "
1014 "can't dump CameraService from pid=%d, uid=%d\n",
1015 IPCThreadState::self()->getCallingPid(),
1016 IPCThreadState::self()->getCallingUid());
1017 result.append(buffer);
1018 write(fd, result.string(), result.size());
1019 } else {
1020 AutoMutex lock(&mLock);
1021 if (mClient != 0) {
1022 sp<Client> currentClient = mClient.promote();
1023 sprintf(buffer, "Client (%p) PID: %d\n",
1024 currentClient->getCameraClient()->asBinder().get(),
1025 currentClient->mClientPid);
1026 result.append(buffer);
1027 write(fd, result.string(), result.size());
1028 currentClient->mHardware->dump(fd, args);
1029 } else {
1030 result.append("No camera client yet.\n");
1031 write(fd, result.string(), result.size());
1032 }
1033 }
1034 return NO_ERROR;
1035}
1036
1037
1038#if DEBUG_HEAP_LEAKS
1039
1040#define CHECK_INTERFACE(interface, data, reply) \
1041 do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
1042 LOGW("Call incorrectly routed to " #interface); \
1043 return PERMISSION_DENIED; \
1044 } } while (0)
1045
1046status_t CameraService::onTransact(
1047 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1048{
1049 // permission checks...
1050 switch (code) {
1051 case BnCameraService::CONNECT:
1052 IPCThreadState* ipc = IPCThreadState::self();
1053 const int pid = ipc->getCallingPid();
1054 const int self_pid = getpid();
1055 if (pid != self_pid) {
1056 // we're called from a different process, do the real check
1057 if (!checkCallingPermission(
1058 String16("android.permission.CAMERA")))
1059 {
1060 const int uid = ipc->getCallingUid();
1061 LOGE("Permission Denial: "
1062 "can't use the camera pid=%d, uid=%d", pid, uid);
1063 return PERMISSION_DENIED;
1064 }
1065 }
1066 break;
1067 }
1068
1069 status_t err = BnCameraService::onTransact(code, data, reply, flags);
1070
1071 LOGD("+++ onTransact err %d code %d", err, code);
1072
1073 if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
1074 // the 'service' command interrogates this binder for its name, and then supplies it
1075 // even for the debugging commands. that means we need to check for it here, using
1076 // ISurfaceComposer (since we delegated the INTERFACE_TRANSACTION handling to
1077 // BnSurfaceComposer before falling through to this code).
1078
1079 LOGD("+++ onTransact code %d", code);
1080
1081 CHECK_INTERFACE(ICameraService, data, reply);
1082
1083 switch(code) {
1084 case 1000:
1085 {
1086 if (gWeakHeap != 0) {
1087 sp<IMemoryHeap> h = gWeakHeap.promote();
1088 IMemoryHeap *p = gWeakHeap.unsafe_get();
1089 LOGD("CHECKING WEAK REFERENCE %p (%p)", h.get(), p);
1090 if (h != 0)
1091 h->printRefs();
1092 bool attempt_to_delete = data.readInt32() == 1;
1093 if (attempt_to_delete) {
1094 // NOT SAFE!
1095 LOGD("DELETING WEAK REFERENCE %p (%p)", h.get(), p);
1096 if (p) delete p;
1097 }
1098 return NO_ERROR;
1099 }
1100 }
1101 break;
1102 default:
1103 break;
1104 }
1105 }
1106 return err;
1107}
1108
1109#endif // DEBUG_HEAP_LEAKS
1110
1111}; // namespace android