blob: c5c95b05e7df6bb42de2bb2bf08da58e1f24d62d [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
Jason Samsb18b6912009-03-24 20:21:36 -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
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 Samsb18b6912009-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 Project9066cfe2009-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 Samsb18b6912009-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 Project9066cfe2009-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 Sams403914a2009-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 Samsb18b6912009-03-24 20:21:36 -0700294
The Android Open Source Project9066cfe2009-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 Samsb18b6912009-03-24 20:21:36 -0700494 if (mMediaPlayerBeep.get() != NULL) {
495 mMediaPlayerBeep->start();
496 }
The Android Open Source Project9066cfe2009-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 Samsb18b6912009-03-24 20:21:36 -0700535 if (mMediaPlayerBeep.get() != NULL) {
536 mMediaPlayerBeep->start();
537 }
The Android Open Source Project9066cfe2009-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 Project9066cfe2009-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
734 // Screen goes black after the buffer is unregistered.
735 if (client->mSurface != 0 && !client->mUseOverlay) {
736 client->mSurface->unregisterBuffers();
737 }
738
739 client->postShutter();
740
741 // It takes some time before yuvPicture callback to be called.
742 // Register the buffer for raw image here to reduce latency.
743 if (client->mSurface != 0 && !client->mUseOverlay) {
744 int w, h;
745 CameraParameters params(client->mHardware->getParameters());
746 params.getPictureSize(&w, &h);
747 uint32_t transform = 0;
748 if (params.getOrientation() == CameraParameters::CAMERA_ORIENTATION_PORTRAIT) {
749 LOGV("portrait mode");
750 transform = ISurface::BufferHeap::ROT_90;
751 }
752 ISurface::BufferHeap buffers(w, h, w, h,
753 PIXEL_FORMAT_YCbCr_420_SP, transform, 0, client->mHardware->getRawHeap());
754
755 client->mSurface->registerBuffers(buffers);
756 }
Jason Sams403914a2009-03-24 20:36:57 -0700757
758 if (client->mMediaPlayerClick.get() != NULL) {
759 client->mMediaPlayerClick->start();
760 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800761}
762
763// picture callback - raw image ready
764void CameraService::Client::yuvPictureCallback(const sp<IMemory>& mem,
765 void *user)
766{
767 sp<Client> client = getClientFromCookie(user);
768 if (client == 0) {
769 return;
770 }
771 if (mem == NULL) {
772 client->postRaw(NULL);
773 client->postError(UNKNOWN_ERROR);
774 return;
775 }
776
777 ssize_t offset;
778 size_t size;
779 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
780#if DEBUG_HEAP_LEAKS && 0 // debugging
781 gWeakHeap = heap; // debugging
782#endif
783
784 //LOGV("yuvPictureCallback(%d, %d, %p)", offset, size, user);
785#if DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE // for testing pursposes only
786 dump_to_file("/data/photo.yuv",
787 (uint8_t *)heap->base() + offset, size);
788#endif
789
790 // Put the YUV version of the snapshot in the preview display.
791 if (client->mSurface != 0 && !client->mUseOverlay) {
792 client->mSurface->postBuffer(offset);
793 }
794
795 client->postRaw(mem);
796
797#if DEBUG_CLIENT_REFERENCES
798 //**** if the client's refcount is 1, then we are about to destroy it here,
799 // which is bad--print all refcounts.
800 if (client->getStrongCount() == 1) {
801 LOGE("++++++++++++++++ (RAW) THIS WILL CAUSE A LOCKUP!");
802 client->printRefs();
803 }
804#endif
805}
806
807// picture callback - jpeg ready
808void CameraService::Client::jpegPictureCallback(const sp<IMemory>& mem, void *user)
809{
810 sp<Client> client = getClientFromCookie(user);
811 if (client == 0) {
812 return;
813 }
814 if (mem == NULL) {
815 client->postJpeg(NULL);
816 client->postError(UNKNOWN_ERROR);
817 return;
818 }
819
820 /** We absolutely CANNOT call into user code with a lock held **/
821
822#if DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE // for testing pursposes only
823 {
824 ssize_t offset;
825 size_t size;
826 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
827 dump_to_file("/data/photo.jpg",
828 (uint8_t *)heap->base() + offset, size);
829 }
830#endif
831
832 client->postJpeg(mem);
833
834#if DEBUG_CLIENT_REFERENCES
835 //**** if the client's refcount is 1, then we are about to destroy it here,
836 // which is bad--print all refcounts.
837 if (client->getStrongCount() == 1) {
838 LOGE("++++++++++++++++ (JPEG) THIS WILL CAUSE A LOCKUP!");
839 client->printRefs();
840 }
841#endif
842}
843
844void CameraService::Client::autoFocusCallback(bool focused, void *user)
845{
846 LOGV("autoFocusCallback");
847
848 sp<Client> client = getClientFromCookie(user);
849 if (client == 0) {
850 return;
851 }
852
853 client->postAutoFocus(focused);
854
855#if DEBUG_CLIENT_REFERENCES
856 if (client->getStrongCount() == 1) {
857 LOGE("++++++++++++++++ (AUTOFOCUS) THIS WILL CAUSE A LOCKUP!");
858 client->printRefs();
859 }
860#endif
861}
862
863// set preview/capture parameters - key/value pairs
864status_t CameraService::Client::setParameters(const String8& params)
865{
866 LOGD("setParameters(%s)", params.string());
867
868 Mutex::Autolock lock(mLock);
869 status_t result = checkPid();
870 if (result != NO_ERROR) return result;
871
872 if (mHardware == 0) {
873 LOGE("mHardware is NULL, returning.");
874 return INVALID_OPERATION;
875 }
876
877 CameraParameters p(params);
878 mHardware->setParameters(p);
879 return NO_ERROR;
880}
881
882// get preview/capture parameters - key/value pairs
883String8 CameraService::Client::getParameters() const
884{
885 LOGD("getParameters");
886
887 Mutex::Autolock lock(mLock);
888
889 if (mHardware == 0) {
890 LOGE("mHardware is NULL, returning.");
891 return String8();
892 }
893
894 return mHardware->getParameters().flatten();
895}
896
897void CameraService::Client::postAutoFocus(bool focused)
898{
899 LOGV("postAutoFocus");
900 mCameraClient->autoFocusCallback(focused);
901}
902
903void CameraService::Client::postShutter()
904{
905 mCameraClient->shutterCallback();
906}
907
908void CameraService::Client::postRaw(const sp<IMemory>& mem)
909{
910 LOGD("postRaw");
911 mCameraClient->rawCallback(mem);
912}
913
914void CameraService::Client::postJpeg(const sp<IMemory>& mem)
915{
916 LOGD("postJpeg");
917 mCameraClient->jpegCallback(mem);
918}
919
920void CameraService::Client::copyFrameAndPostCopiedFrame(sp<IMemoryHeap> heap, size_t offset, size_t size)
921{
922 LOGV("copyFrameAndPostCopiedFrame");
923 // It is necessary to copy out of pmem before sending this to
924 // the callback. For efficiency, reuse the same MemoryHeapBase
925 // provided it's big enough. Don't allocate the memory or
926 // perform the copy if there's no callback.
927 if (mPreviewBuffer == 0) {
928 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
929 } else if (size > mPreviewBuffer->virtualSize()) {
930 mPreviewBuffer.clear();
931 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
932 if (mPreviewBuffer == 0) {
933 LOGE("failed to allocate space for preview buffer");
934 return;
935 }
936 }
937 memcpy(mPreviewBuffer->base(),
938 (uint8_t *)heap->base() + offset, size);
939
940 sp<MemoryBase> frame = new MemoryBase(mPreviewBuffer, 0, size);
941 if (frame == 0) {
942 LOGE("failed to allocate space for frame callback");
943 return;
944 }
945 mCameraClient->previewCallback(frame);
946}
947
948void CameraService::Client::postRecordingFrame(const sp<IMemory>& frame)
949{
950 LOGV("postRecordingFrame");
951 if (frame == 0) {
952 LOGW("frame is a null pointer");
953 return;
954 }
955 mCameraClient->recordingCallback(frame);
956}
957
958void CameraService::Client::postPreviewFrame(const sp<IMemory>& mem)
959{
960 LOGV("postPreviewFrame");
961 if (mem == 0) {
962 LOGW("mem is a null pointer");
963 return;
964 }
965
966 ssize_t offset;
967 size_t size;
968 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
969 {
970 Mutex::Autolock surfaceLock(mSurfaceLock);
971 if (mSurface != NULL) {
972 mSurface->postBuffer(offset);
973 }
974 }
975
976 // Is the callback enabled or not?
977 if (!(mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
978 // If the enable bit is off, the copy-out and one-shot bits are ignored
979 LOGV("frame callback is diabled");
980 return;
981 }
982
983 // Is the received frame copied out or not?
984 if (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
985 LOGV("frame is copied out");
986 copyFrameAndPostCopiedFrame(heap, offset, size);
987 } else {
988 LOGV("frame is directly sent out without copying");
989 mCameraClient->previewCallback(mem);
990 }
991
992 // Is this is one-shot only?
993 if (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) {
994 LOGV("One-shot only, thus clear the bits and disable frame callback");
995 mPreviewCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
996 FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
997 FRAME_CALLBACK_FLAG_ENABLE_MASK);
998 }
999}
1000
1001void CameraService::Client::postError(status_t error)
1002{
1003 mCameraClient->errorCallback(error);
1004}
1005
1006status_t CameraService::dump(int fd, const Vector<String16>& args)
1007{
1008 const size_t SIZE = 256;
1009 char buffer[SIZE];
1010 String8 result;
1011 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
1012 snprintf(buffer, SIZE, "Permission Denial: "
1013 "can't dump CameraService from pid=%d, uid=%d\n",
1014 IPCThreadState::self()->getCallingPid(),
1015 IPCThreadState::self()->getCallingUid());
1016 result.append(buffer);
1017 write(fd, result.string(), result.size());
1018 } else {
1019 AutoMutex lock(&mLock);
1020 if (mClient != 0) {
1021 sp<Client> currentClient = mClient.promote();
1022 sprintf(buffer, "Client (%p) PID: %d\n",
1023 currentClient->getCameraClient()->asBinder().get(),
1024 currentClient->mClientPid);
1025 result.append(buffer);
1026 write(fd, result.string(), result.size());
1027 currentClient->mHardware->dump(fd, args);
1028 } else {
1029 result.append("No camera client yet.\n");
1030 write(fd, result.string(), result.size());
1031 }
1032 }
1033 return NO_ERROR;
1034}
1035
1036
1037#if DEBUG_HEAP_LEAKS
1038
1039#define CHECK_INTERFACE(interface, data, reply) \
1040 do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
1041 LOGW("Call incorrectly routed to " #interface); \
1042 return PERMISSION_DENIED; \
1043 } } while (0)
1044
1045status_t CameraService::onTransact(
1046 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1047{
1048 // permission checks...
1049 switch (code) {
1050 case BnCameraService::CONNECT:
1051 IPCThreadState* ipc = IPCThreadState::self();
1052 const int pid = ipc->getCallingPid();
1053 const int self_pid = getpid();
1054 if (pid != self_pid) {
1055 // we're called from a different process, do the real check
1056 if (!checkCallingPermission(
1057 String16("android.permission.CAMERA")))
1058 {
1059 const int uid = ipc->getCallingUid();
1060 LOGE("Permission Denial: "
1061 "can't use the camera pid=%d, uid=%d", pid, uid);
1062 return PERMISSION_DENIED;
1063 }
1064 }
1065 break;
1066 }
1067
1068 status_t err = BnCameraService::onTransact(code, data, reply, flags);
1069
1070 LOGD("+++ onTransact err %d code %d", err, code);
1071
1072 if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
1073 // the 'service' command interrogates this binder for its name, and then supplies it
1074 // even for the debugging commands. that means we need to check for it here, using
1075 // ISurfaceComposer (since we delegated the INTERFACE_TRANSACTION handling to
1076 // BnSurfaceComposer before falling through to this code).
1077
1078 LOGD("+++ onTransact code %d", code);
1079
1080 CHECK_INTERFACE(ICameraService, data, reply);
1081
1082 switch(code) {
1083 case 1000:
1084 {
1085 if (gWeakHeap != 0) {
1086 sp<IMemoryHeap> h = gWeakHeap.promote();
1087 IMemoryHeap *p = gWeakHeap.unsafe_get();
1088 LOGD("CHECKING WEAK REFERENCE %p (%p)", h.get(), p);
1089 if (h != 0)
1090 h->printRefs();
1091 bool attempt_to_delete = data.readInt32() == 1;
1092 if (attempt_to_delete) {
1093 // NOT SAFE!
1094 LOGD("DELETING WEAK REFERENCE %p (%p)", h.get(), p);
1095 if (p) delete p;
1096 }
1097 return NO_ERROR;
1098 }
1099 }
1100 break;
1101 default:
1102 break;
1103 }
1104 }
1105 return err;
1106}
1107
1108#endif // DEBUG_HEAP_LEAKS
1109
1110}; // namespace android