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