blob: 851b2132f648b66eb13a4f184eda1938050f5df4 [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
The Android Open Source Project0c2bcbc2009-03-19 23:08:54 -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
The Android Open Source Project0c2bcbc2009-03-19 23:08:54 -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
The Android Open Source Project0c2bcbc2009-03-19 23:08:54 -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
The Android Open Source Project0c2bcbc2009-03-19 23:08:54 -0700286 mMediaPlayerBeep.clear();
287 mMediaPlayerClick.clear();
288
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800289 // make sure we tear down the hardware
290 mClientPid = IPCThreadState::self()->getCallingPid();
291 disconnect();
292 LOGD("Client X destructor");
293}
294
295void CameraService::Client::disconnect()
296{
297 LOGD("Client (%p) E disconnect from (%d)",
298 getCameraClient()->asBinder().get(),
299 IPCThreadState::self()->getCallingPid());
300 Mutex::Autolock lock(mLock);
301 if (mClientPid <= 0) {
302 LOGV("camera is unlocked, don't tear down hardware");
303 return;
304 }
305 if (checkPid() != NO_ERROR) {
306 LOGV("Different client - don't disconnect");
307 return;
308 }
309
310 mCameraService->removeClient(mCameraClient);
311 if (mHardware != 0) {
312 LOGV("hardware teardown");
313 // Before destroying mHardware, we must make sure it's in the
314 // idle state.
315 mHardware->stopPreview();
316 // Cancel all picture callbacks.
317 mHardware->cancelPicture(true, true, true);
318 // Release the hardware resources.
319 mHardware->release();
320 }
321 mHardware.clear();
322 LOGD("Client X disconnect");
323}
324
325// pass the buffered ISurface to the camera service
326status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface)
327{
328 LOGD("setPreviewDisplay(%p)", surface.get());
329 Mutex::Autolock lock(mLock);
330 status_t result = checkPid();
331 if (result != NO_ERROR) return result;
332 Mutex::Autolock surfaceLock(mSurfaceLock);
333 // asBinder() is safe on NULL (returns NULL)
334 if (surface->asBinder() != mSurface->asBinder()) {
335 if (mSurface != 0 && !mUseOverlay) {
336 LOGD("clearing old preview surface %p", mSurface.get());
337 mSurface->unregisterBuffers();
338 }
339 mSurface = surface;
340 }
341 return NO_ERROR;
342}
343
344// set the preview callback flag to affect how the received frames from
345// preview are handled.
346void CameraService::Client::setPreviewCallbackFlag(int callback_flag)
347{
348 LOGV("setPreviewCallbackFlag");
349 Mutex::Autolock lock(mLock);
350 if (checkPid() != NO_ERROR) return;
351 mPreviewCallbackFlag = callback_flag;
352}
353
354// start preview mode, must call setPreviewDisplay first
355status_t CameraService::Client::startCameraMode(camera_mode mode)
356{
357 LOGD("startCameraMode(%d)", mode);
358
359 /* we cannot call into mHardware with mLock held because
360 * mHardware has callbacks onto us which acquire this lock
361 */
362
363 Mutex::Autolock lock(mLock);
364 status_t result = checkPid();
365 if (result != NO_ERROR) return result;
366
367 if (mHardware == 0) {
368 LOGE("mHardware is NULL, returning.");
369 return INVALID_OPERATION;
370 }
371
372 if (mSurface == 0) {
373 LOGE("setPreviewDisplay must be called before startCameraMode!");
374 return INVALID_OPERATION;
375 }
376
377 switch(mode) {
378 case CAMERA_RECORDING_MODE:
379 return startRecordingMode();
380
381 default: // CAMERA_PREVIEW_MODE
382 return startPreviewMode();
383 }
384}
385
386status_t CameraService::Client::startRecordingMode()
387{
388 LOGV("startRecordingMode");
389
390 status_t ret = UNKNOWN_ERROR;
391
392 // if preview has not been started, start preview first
393 if (!mHardware->previewEnabled()) {
394 ret = startPreviewMode();
395 if (ret != NO_ERROR) {
396 return ret;
397 }
398 }
399
400 // if recording has been enabled, nothing needs to be done
401 if (mHardware->recordingEnabled()) {
402 return NO_ERROR;
403 }
404
405 // start recording mode
406 ret = mHardware->startRecording(recordingCallback,
407 mCameraService.get());
408 if (ret != NO_ERROR) {
409 LOGE("mHardware->startRecording() failed with status %d", ret);
410 }
411 return ret;
412}
413
414status_t CameraService::Client::startPreviewMode()
415{
416 LOGV("startPreviewMode");
417
418 // if preview has been enabled, nothing needs to be done
419 if (mHardware->previewEnabled()) {
420 return NO_ERROR;
421 }
422
423 // start preview mode
424#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
425 debug_frame_cnt = 0;
426#endif
427 status_t ret = UNKNOWN_ERROR;
428 int w, h;
429 CameraParameters params(mHardware->getParameters());
430 params.getPreviewSize(&w, &h);
431
432 if (mUseOverlay) {
433 const char *format = params.getPreviewFormat();
434 int fmt;
435 LOGD("Use Overlays");
436 if (!strcmp(format, "yuv422i"))
437 fmt = OVERLAY_FORMAT_YCbCr_422_I;
438 else if (!strcmp(format, "rgb565"))
439 fmt = OVERLAY_FORMAT_RGB_565;
440 else {
441 LOGE("Invalid preview format for overlays");
442 return -EINVAL;
443 }
444 sp<OverlayRef> ref = mSurface->createOverlay(w, h, fmt);
445 ret = mHardware->setOverlay(new Overlay(ref));
446 if (ret != NO_ERROR) {
447 LOGE("mHardware->setOverlay() failed with status %d\n", ret);
448 return ret;
449 }
450 ret = mHardware->startPreview(NULL, mCameraService.get());
451 if (ret != NO_ERROR)
452 LOGE("mHardware->startPreview() failed with status %d\n", ret);
453
454 } else {
455 ret = mHardware->startPreview(previewCallback,
456 mCameraService.get());
457 if (ret == NO_ERROR) {
458
459 mSurface->unregisterBuffers();
460
461 uint32_t transform = 0;
462 if (params.getOrientation() ==
463 CameraParameters::CAMERA_ORIENTATION_PORTRAIT) {
464 LOGV("portrait mode");
465 transform = ISurface::BufferHeap::ROT_90;
466 }
467 ISurface::BufferHeap buffers(w, h, w, h,
468 PIXEL_FORMAT_YCbCr_420_SP,
469 transform,
470 0,
471 mHardware->getPreviewHeap());
472
473 mSurface->registerBuffers(buffers);
474 } else {
475 LOGE("mHardware->startPreview() failed with status %d", ret);
476 }
477 }
478 return ret;
479}
480
481status_t CameraService::Client::startPreview()
482{
483 return startCameraMode(CAMERA_PREVIEW_MODE);
484}
485
486status_t CameraService::Client::startRecording()
487{
The Android Open Source Project0c2bcbc2009-03-19 23:08:54 -0700488 if (mMediaPlayerBeep.get() != NULL) {
489 mMediaPlayerBeep->start();
490 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800491 return startCameraMode(CAMERA_RECORDING_MODE);
492}
493
494// stop preview mode
495void CameraService::Client::stopPreview()
496{
497 LOGD("stopPreview()");
498
499 Mutex::Autolock lock(mLock);
500 if (checkPid() != NO_ERROR) return;
501
502 if (mHardware == 0) {
503 LOGE("mHardware is NULL, returning.");
504 return;
505 }
506
507 mHardware->stopPreview();
508 LOGD("stopPreview(), hardware stopped OK");
509
510 if (mSurface != 0 && !mUseOverlay) {
511 mSurface->unregisterBuffers();
512 }
513 mPreviewBuffer.clear();
514}
515
516// stop recording mode
517void CameraService::Client::stopRecording()
518{
519 LOGV("stopRecording()");
520
521 Mutex::Autolock lock(mLock);
522 if (checkPid() != NO_ERROR) return;
523
524 if (mHardware == 0) {
525 LOGE("mHardware is NULL, returning.");
526 return;
527 }
528
The Android Open Source Project0c2bcbc2009-03-19 23:08:54 -0700529 if (mMediaPlayerBeep.get() != NULL) {
530 mMediaPlayerBeep->start();
531 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800532 mHardware->stopRecording();
533 LOGV("stopRecording(), hardware stopped OK");
534 mPreviewBuffer.clear();
535}
536
537// release a recording frame
538void CameraService::Client::releaseRecordingFrame(const sp<IMemory>& mem)
539{
540 LOGV("releaseRecordingFrame()");
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
550 mHardware->releaseRecordingFrame(mem);
551}
552
553bool CameraService::Client::previewEnabled()
554{
555 Mutex::Autolock lock(mLock);
556 if (mHardware == 0) return false;
557 return mHardware->previewEnabled();
558}
559
560bool CameraService::Client::recordingEnabled()
561{
562 Mutex::Autolock lock(mLock);
563 if (mHardware == 0) return false;
564 return mHardware->recordingEnabled();
565}
566
567// Safely retrieves a strong pointer to the client during a hardware callback.
568sp<CameraService::Client> CameraService::Client::getClientFromCookie(void* user)
569{
570 sp<Client> client = 0;
571 CameraService *service = static_cast<CameraService*>(user);
572 if (service != NULL) {
573 Mutex::Autolock ourLock(service->mLock);
574 if (service->mClient != 0) {
575 client = service->mClient.promote();
576 if (client == 0) {
577 LOGE("getClientFromCookie: client appears to have died");
578 service->mClient.clear();
579 }
580 } else {
581 LOGE("getClientFromCookie: got callback but client was NULL");
582 }
583 }
584 return client;
585}
586
587
588#if DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE || \
589 DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE || \
590 DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
591static void dump_to_file(const char *fname,
592 uint8_t *buf, uint32_t size)
593{
594 int nw, cnt = 0;
595 uint32_t written = 0;
596
597 LOGD("opening file [%s]\n", fname);
598 int fd = open(fname, O_RDWR | O_CREAT);
599 if (fd < 0) {
600 LOGE("failed to create file [%s]: %s", fname, strerror(errno));
601 return;
602 }
603
604 LOGD("writing %d bytes to file [%s]\n", size, fname);
605 while (written < size) {
606 nw = ::write(fd,
607 buf + written,
608 size - written);
609 if (nw < 0) {
610 LOGE("failed to write to file [%s]: %s",
611 fname, strerror(errno));
612 break;
613 }
614 written += nw;
615 cnt++;
616 }
617 LOGD("done writing %d bytes to file [%s] in %d passes\n",
618 size, fname, cnt);
619 ::close(fd);
620}
621#endif
622
623// preview callback - frame buffer update
624void CameraService::Client::previewCallback(const sp<IMemory>& mem, void* user)
625{
626 LOGV("previewCallback()");
627 sp<Client> client = getClientFromCookie(user);
628 if (client == 0) {
629 return;
630 }
631
632#if DEBUG_HEAP_LEAKS && 0 // debugging
633 if (gWeakHeap == NULL) {
634 ssize_t offset;
635 size_t size;
636 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
637 if (gWeakHeap != heap) {
638 LOGD("SETTING PREVIEW HEAP");
639 heap->trackMe(true, true);
640 gWeakHeap = heap;
641 }
642 }
643#endif
644
645#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
646 {
647 if (debug_frame_cnt++ == DEBUG_DUMP_PREVIEW_FRAME_TO_FILE) {
648 ssize_t offset;
649 size_t size;
650 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
651 dump_to_file("/data/preview.yuv",
652 (uint8_t *)heap->base() + offset, size);
653 }
654 }
655#endif
656
657 // The strong pointer guarantees the client will exist, but no lock is held.
658 client->postPreviewFrame(mem);
659
660#if DEBUG_CLIENT_REFERENCES
661 //**** if the client's refcount is 1, then we are about to destroy it here,
662 // which is bad--print all refcounts.
663 if (client->getStrongCount() == 1) {
664 LOGE("++++++++++++++++ (PREVIEW) THIS WILL CAUSE A LOCKUP!");
665 client->printRefs();
666 }
667#endif
668}
669
670// recording callback
671void CameraService::Client::recordingCallback(const sp<IMemory>& mem, void* user)
672{
673 LOGV("recordingCallback");
674 sp<Client> client = getClientFromCookie(user);
675 if (client == 0) {
676 return;
677 }
678 // The strong pointer guarantees the client will exist, but no lock is held.
679 client->postRecordingFrame(mem);
680}
681
682// take a picture - image is returned in callback
683status_t CameraService::Client::autoFocus()
684{
685 LOGV("autoFocus");
686
687 Mutex::Autolock lock(mLock);
688 status_t result = checkPid();
689 if (result != NO_ERROR) return result;
690
691 if (mHardware == 0) {
692 LOGE("mHardware is NULL, returning.");
693 return INVALID_OPERATION;
694 }
695
696 return mHardware->autoFocus(autoFocusCallback,
697 mCameraService.get());
698}
699
700// take a picture - image is returned in callback
701status_t CameraService::Client::takePicture()
702{
703 LOGD("takePicture");
704
705 Mutex::Autolock lock(mLock);
706 status_t result = checkPid();
707 if (result != NO_ERROR) return result;
708
709 if (mHardware == 0) {
710 LOGE("mHardware is NULL, returning.");
711 return INVALID_OPERATION;
712 }
713
The Android Open Source Project0c2bcbc2009-03-19 23:08:54 -0700714 if (mMediaPlayerClick.get() != NULL) {
715 mMediaPlayerClick->start();
716 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800717 return mHardware->takePicture(shutterCallback,
718 yuvPictureCallback,
719 jpegPictureCallback,
720 mCameraService.get());
721}
722
723// picture callback - snapshot taken
724void CameraService::Client::shutterCallback(void *user)
725{
726 sp<Client> client = getClientFromCookie(user);
727 if (client == 0) {
728 return;
729 }
730
731 // Screen goes black after the buffer is unregistered.
732 if (client->mSurface != 0 && !client->mUseOverlay) {
733 client->mSurface->unregisterBuffers();
734 }
735
736 client->postShutter();
737
738 // It takes some time before yuvPicture callback to be called.
739 // Register the buffer for raw image here to reduce latency.
740 if (client->mSurface != 0 && !client->mUseOverlay) {
741 int w, h;
742 CameraParameters params(client->mHardware->getParameters());
743 params.getPictureSize(&w, &h);
744 uint32_t transform = 0;
745 if (params.getOrientation() == CameraParameters::CAMERA_ORIENTATION_PORTRAIT) {
746 LOGV("portrait mode");
747 transform = ISurface::BufferHeap::ROT_90;
748 }
749 ISurface::BufferHeap buffers(w, h, w, h,
750 PIXEL_FORMAT_YCbCr_420_SP, transform, 0, client->mHardware->getRawHeap());
751
752 client->mSurface->registerBuffers(buffers);
753 }
754}
755
756// picture callback - raw image ready
757void CameraService::Client::yuvPictureCallback(const sp<IMemory>& mem,
758 void *user)
759{
760 sp<Client> client = getClientFromCookie(user);
761 if (client == 0) {
762 return;
763 }
764 if (mem == NULL) {
765 client->postRaw(NULL);
766 client->postError(UNKNOWN_ERROR);
767 return;
768 }
769
770 ssize_t offset;
771 size_t size;
772 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
773#if DEBUG_HEAP_LEAKS && 0 // debugging
774 gWeakHeap = heap; // debugging
775#endif
776
777 //LOGV("yuvPictureCallback(%d, %d, %p)", offset, size, user);
778#if DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE // for testing pursposes only
779 dump_to_file("/data/photo.yuv",
780 (uint8_t *)heap->base() + offset, size);
781#endif
782
783 // Put the YUV version of the snapshot in the preview display.
784 if (client->mSurface != 0 && !client->mUseOverlay) {
785 client->mSurface->postBuffer(offset);
786 }
787
788 client->postRaw(mem);
789
790#if DEBUG_CLIENT_REFERENCES
791 //**** if the client's refcount is 1, then we are about to destroy it here,
792 // which is bad--print all refcounts.
793 if (client->getStrongCount() == 1) {
794 LOGE("++++++++++++++++ (RAW) THIS WILL CAUSE A LOCKUP!");
795 client->printRefs();
796 }
797#endif
798}
799
800// picture callback - jpeg ready
801void CameraService::Client::jpegPictureCallback(const sp<IMemory>& mem, void *user)
802{
803 sp<Client> client = getClientFromCookie(user);
804 if (client == 0) {
805 return;
806 }
807 if (mem == NULL) {
808 client->postJpeg(NULL);
809 client->postError(UNKNOWN_ERROR);
810 return;
811 }
812
813 /** We absolutely CANNOT call into user code with a lock held **/
814
815#if DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE // for testing pursposes only
816 {
817 ssize_t offset;
818 size_t size;
819 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
820 dump_to_file("/data/photo.jpg",
821 (uint8_t *)heap->base() + offset, size);
822 }
823#endif
824
825 client->postJpeg(mem);
826
827#if DEBUG_CLIENT_REFERENCES
828 //**** if the client's refcount is 1, then we are about to destroy it here,
829 // which is bad--print all refcounts.
830 if (client->getStrongCount() == 1) {
831 LOGE("++++++++++++++++ (JPEG) THIS WILL CAUSE A LOCKUP!");
832 client->printRefs();
833 }
834#endif
835}
836
837void CameraService::Client::autoFocusCallback(bool focused, void *user)
838{
839 LOGV("autoFocusCallback");
840
841 sp<Client> client = getClientFromCookie(user);
842 if (client == 0) {
843 return;
844 }
845
846 client->postAutoFocus(focused);
847
848#if DEBUG_CLIENT_REFERENCES
849 if (client->getStrongCount() == 1) {
850 LOGE("++++++++++++++++ (AUTOFOCUS) THIS WILL CAUSE A LOCKUP!");
851 client->printRefs();
852 }
853#endif
854}
855
856// set preview/capture parameters - key/value pairs
857status_t CameraService::Client::setParameters(const String8& params)
858{
859 LOGD("setParameters(%s)", params.string());
860
861 Mutex::Autolock lock(mLock);
862 status_t result = checkPid();
863 if (result != NO_ERROR) return result;
864
865 if (mHardware == 0) {
866 LOGE("mHardware is NULL, returning.");
867 return INVALID_OPERATION;
868 }
869
870 CameraParameters p(params);
871 mHardware->setParameters(p);
872 return NO_ERROR;
873}
874
875// get preview/capture parameters - key/value pairs
876String8 CameraService::Client::getParameters() const
877{
878 LOGD("getParameters");
879
880 Mutex::Autolock lock(mLock);
881
882 if (mHardware == 0) {
883 LOGE("mHardware is NULL, returning.");
884 return String8();
885 }
886
887 return mHardware->getParameters().flatten();
888}
889
890void CameraService::Client::postAutoFocus(bool focused)
891{
892 LOGV("postAutoFocus");
893 mCameraClient->autoFocusCallback(focused);
894}
895
896void CameraService::Client::postShutter()
897{
898 mCameraClient->shutterCallback();
899}
900
901void CameraService::Client::postRaw(const sp<IMemory>& mem)
902{
903 LOGD("postRaw");
904 mCameraClient->rawCallback(mem);
905}
906
907void CameraService::Client::postJpeg(const sp<IMemory>& mem)
908{
909 LOGD("postJpeg");
910 mCameraClient->jpegCallback(mem);
911}
912
913void CameraService::Client::copyFrameAndPostCopiedFrame(sp<IMemoryHeap> heap, size_t offset, size_t size)
914{
915 LOGV("copyFrameAndPostCopiedFrame");
916 // It is necessary to copy out of pmem before sending this to
917 // the callback. For efficiency, reuse the same MemoryHeapBase
918 // provided it's big enough. Don't allocate the memory or
919 // perform the copy if there's no callback.
920 if (mPreviewBuffer == 0) {
921 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
922 } else if (size > mPreviewBuffer->virtualSize()) {
923 mPreviewBuffer.clear();
924 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
925 if (mPreviewBuffer == 0) {
926 LOGE("failed to allocate space for preview buffer");
927 return;
928 }
929 }
930 memcpy(mPreviewBuffer->base(),
931 (uint8_t *)heap->base() + offset, size);
932
933 sp<MemoryBase> frame = new MemoryBase(mPreviewBuffer, 0, size);
934 if (frame == 0) {
935 LOGE("failed to allocate space for frame callback");
936 return;
937 }
938 mCameraClient->previewCallback(frame);
939}
940
941void CameraService::Client::postRecordingFrame(const sp<IMemory>& frame)
942{
943 LOGV("postRecordingFrame");
944 if (frame == 0) {
945 LOGW("frame is a null pointer");
946 return;
947 }
948 mCameraClient->recordingCallback(frame);
949}
950
951void CameraService::Client::postPreviewFrame(const sp<IMemory>& mem)
952{
953 LOGV("postPreviewFrame");
954 if (mem == 0) {
955 LOGW("mem is a null pointer");
956 return;
957 }
958
959 ssize_t offset;
960 size_t size;
961 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
962 {
963 Mutex::Autolock surfaceLock(mSurfaceLock);
964 if (mSurface != NULL) {
965 mSurface->postBuffer(offset);
966 }
967 }
968
969 // Is the callback enabled or not?
970 if (!(mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
971 // If the enable bit is off, the copy-out and one-shot bits are ignored
972 LOGV("frame callback is diabled");
973 return;
974 }
975
976 // Is the received frame copied out or not?
977 if (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
978 LOGV("frame is copied out");
979 copyFrameAndPostCopiedFrame(heap, offset, size);
980 } else {
981 LOGV("frame is directly sent out without copying");
982 mCameraClient->previewCallback(mem);
983 }
984
985 // Is this is one-shot only?
986 if (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) {
987 LOGV("One-shot only, thus clear the bits and disable frame callback");
988 mPreviewCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
989 FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
990 FRAME_CALLBACK_FLAG_ENABLE_MASK);
991 }
992}
993
994void CameraService::Client::postError(status_t error)
995{
996 mCameraClient->errorCallback(error);
997}
998
999status_t CameraService::dump(int fd, const Vector<String16>& args)
1000{
1001 const size_t SIZE = 256;
1002 char buffer[SIZE];
1003 String8 result;
1004 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
1005 snprintf(buffer, SIZE, "Permission Denial: "
1006 "can't dump CameraService from pid=%d, uid=%d\n",
1007 IPCThreadState::self()->getCallingPid(),
1008 IPCThreadState::self()->getCallingUid());
1009 result.append(buffer);
1010 write(fd, result.string(), result.size());
1011 } else {
1012 AutoMutex lock(&mLock);
1013 if (mClient != 0) {
1014 sp<Client> currentClient = mClient.promote();
1015 sprintf(buffer, "Client (%p) PID: %d\n",
1016 currentClient->getCameraClient()->asBinder().get(),
1017 currentClient->mClientPid);
1018 result.append(buffer);
1019 write(fd, result.string(), result.size());
1020 currentClient->mHardware->dump(fd, args);
1021 } else {
1022 result.append("No camera client yet.\n");
1023 write(fd, result.string(), result.size());
1024 }
1025 }
1026 return NO_ERROR;
1027}
1028
1029
1030#if DEBUG_HEAP_LEAKS
1031
1032#define CHECK_INTERFACE(interface, data, reply) \
1033 do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
1034 LOGW("Call incorrectly routed to " #interface); \
1035 return PERMISSION_DENIED; \
1036 } } while (0)
1037
1038status_t CameraService::onTransact(
1039 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1040{
1041 // permission checks...
1042 switch (code) {
1043 case BnCameraService::CONNECT:
1044 IPCThreadState* ipc = IPCThreadState::self();
1045 const int pid = ipc->getCallingPid();
1046 const int self_pid = getpid();
1047 if (pid != self_pid) {
1048 // we're called from a different process, do the real check
1049 if (!checkCallingPermission(
1050 String16("android.permission.CAMERA")))
1051 {
1052 const int uid = ipc->getCallingUid();
1053 LOGE("Permission Denial: "
1054 "can't use the camera pid=%d, uid=%d", pid, uid);
1055 return PERMISSION_DENIED;
1056 }
1057 }
1058 break;
1059 }
1060
1061 status_t err = BnCameraService::onTransact(code, data, reply, flags);
1062
1063 LOGD("+++ onTransact err %d code %d", err, code);
1064
1065 if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
1066 // the 'service' command interrogates this binder for its name, and then supplies it
1067 // even for the debugging commands. that means we need to check for it here, using
1068 // ISurfaceComposer (since we delegated the INTERFACE_TRANSACTION handling to
1069 // BnSurfaceComposer before falling through to this code).
1070
1071 LOGD("+++ onTransact code %d", code);
1072
1073 CHECK_INTERFACE(ICameraService, data, reply);
1074
1075 switch(code) {
1076 case 1000:
1077 {
1078 if (gWeakHeap != 0) {
1079 sp<IMemoryHeap> h = gWeakHeap.promote();
1080 IMemoryHeap *p = gWeakHeap.unsafe_get();
1081 LOGD("CHECKING WEAK REFERENCE %p (%p)", h.get(), p);
1082 if (h != 0)
1083 h->printRefs();
1084 bool attempt_to_delete = data.readInt32() == 1;
1085 if (attempt_to_delete) {
1086 // NOT SAFE!
1087 LOGD("DELETING WEAK REFERENCE %p (%p)", h.get(), p);
1088 if (p) delete p;
1089 }
1090 return NO_ERROR;
1091 }
1092 }
1093 break;
1094 default:
1095 break;
1096 }
1097 }
1098 return err;
1099}
1100
1101#endif // DEBUG_HEAP_LEAKS
1102
1103}; // namespace android