blob: 5784c4b12b9a5eb7b593b06f92a166987a0ced1d [file] [log] [blame]
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001/*
2**
3** Copyright 2008, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18
19#define LOG_TAG "CameraService"
20#include <utils/Log.h>
21
22#include <utils/IServiceManager.h>
23#include <utils/IPCThreadState.h>
24#include <utils/String16.h>
25#include <utils/Errors.h>
26#include <utils/MemoryBase.h>
27#include <utils/MemoryHeapBase.h>
28#include <ui/ICameraService.h>
29
30#include "CameraService.h"
31
32namespace android {
33
34extern "C" {
35#include <stdio.h>
36#include <sys/types.h>
37#include <sys/stat.h>
38#include <fcntl.h>
39#include <pthread.h>
40}
41
42// When you enable this, as well as DEBUG_REFS=1 and
43// DEBUG_REFS_ENABLED_BY_DEFAULT=0 in libutils/RefBase.cpp, this will track all
44// references to the CameraService::Client in order to catch the case where the
45// client is being destroyed while a callback from the CameraHardwareInterface
46// is outstanding. This is a serious bug because if we make another call into
47// CameraHardwreInterface that itself triggers a callback, we will deadlock.
48
49#define DEBUG_CLIENT_REFERENCES 0
50
51#define PICTURE_TIMEOUT seconds(5)
52
53#define DEBUG_DUMP_PREVIEW_FRAME_TO_FILE 0 /* n-th frame to write */
54#define DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE 0
55#define DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE 0
56
57#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
58static int debug_frame_cnt;
59#endif
60
61// ----------------------------------------------------------------------------
62
63void CameraService::instantiate() {
64 defaultServiceManager()->addService(
65 String16("media.camera"), new CameraService());
66}
67
68// ----------------------------------------------------------------------------
69
70CameraService::CameraService() :
71 BnCameraService()
72{
73 LOGI("CameraService started: pid=%d", getpid());
74}
75
76CameraService::~CameraService()
77{
78 if (mClient != 0) {
79 LOGE("mClient was still connected in destructor!");
80 }
81}
82
83sp<ICamera> CameraService::connect(const sp<ICameraClient>& cameraClient)
84{
85 LOGD("Connect E from ICameraClient %p", cameraClient->asBinder().get());
86
87 Mutex::Autolock lock(mLock);
88 if (mClient != 0) {
89 sp<Client> currentClient = mClient.promote();
90 if (currentClient != 0) {
91 sp<ICameraClient> currentCameraClient(currentClient->getCameraClient());
92 if (cameraClient->asBinder() == currentCameraClient->asBinder()) {
93 // this is the same client reconnecting...
94 LOGD("Connect X same client is reconnecting...");
95 return currentClient;
96 } else {
97 // it's another client... boot the previous one...
98 LOGD("new client connecting, booting the old one...");
99 mClient.clear();
100 }
101 } else {
102 // can't promote, the previous client has died...
103 LOGD("new client connecting, old reference was dangling...");
104 mClient.clear();
105 }
106 }
107
108 // create a new Client object
109 sp<Client> client = new Client(this, cameraClient);
110 mClient = client;
111#if DEBUG_CLIENT_REFERENCES
112 // Enable tracking for this object, and track increments and decrements of
113 // the refcount.
114 client->trackMe(true, true);
115#endif
116 LOGD("Connect X");
117 return client;
118}
119
120void CameraService::removeClient(const sp<ICameraClient>& cameraClient)
121{
122 // declar this outside the lock to make absolutely sure the
123 // destructor won't be called with the lock held.
124 sp<Client> client;
125
126 Mutex::Autolock lock(mLock);
127
128 if (mClient == 0) {
129 // This happens when we have already disconnected.
130 LOGV("mClient is null.");
131 return;
132 }
133
134 // Promote mClient. It should never fail because we're called from
135 // a binder call, so someone has to have a strong reference.
136 client = mClient.promote();
137 if (client == 0) {
138 LOGW("can't get a strong reference on mClient!");
139 mClient.clear();
140 return;
141 }
142
143 if (cameraClient->asBinder() != client->getCameraClient()->asBinder()) {
144 // ugh! that's not our client!!
145 LOGW("removeClient() called, but mClient doesn't match!");
146 } else {
147 // okay, good, forget about mClient
148 mClient.clear();
149 }
150}
151
152CameraService::Client::Client(const sp<CameraService>& cameraService,
153 const sp<ICameraClient>& cameraClient) :
154 mCameraService(cameraService), mCameraClient(cameraClient), mHardware(0)
155{
156 LOGD("Client E constructor");
157 mHardware = openCameraHardware();
158 mHasFrameCallback = false;
159 LOGD("Client X constructor");
160}
161
162#if HAVE_ANDROID_OS
163static void *unregister_surface(void *arg)
164{
165 ISurface *surface = (ISurface *)arg;
166 surface->unregisterBuffers();
167 IPCThreadState::self()->flushCommands();
168 return NULL;
169}
170#endif
171
172CameraService::Client::~Client()
173{
174 // spin down hardware
175 LOGD("Client E destructor");
176 if (mSurface != 0) {
177#if HAVE_ANDROID_OS
178 pthread_t thr;
179 // We unregister the buffers in a different thread because binder does
180 // not let us make sychronous transactions in a binder destructor (that
181 // is, upon our reaching a refcount of zero.)
182 pthread_create(&thr, NULL,
183 unregister_surface,
184 mSurface.get());
185 pthread_join(thr, NULL);
186#else
187 mSurface->unregisterBuffers();
188#endif
189 }
190
191 disconnect();
192 LOGD("Client X destructor");
193}
194
195void CameraService::Client::disconnect()
196{
197 LOGD("Client E disconnect");
198 Mutex::Autolock lock(mLock);
199 mCameraService->removeClient(mCameraClient);
200 if (mHardware != 0) {
201 // Before destroying mHardware, we must make sure it's in the
202 // idle state.
203 mHardware->stopPreview();
204 // Cancel all picture callbacks.
205 mHardware->cancelPicture(true, true, true);
206 // Release the hardware resources.
207 mHardware->release();
208 }
209 mHardware.clear();
210 LOGD("Client X disconnect");
211}
212
213// pass the buffered ISurface to the camera service
214status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface)
215{
216 LOGD("setPreviewDisplay(%p)", surface.get());
217 Mutex::Autolock lock(mLock);
218 Mutex::Autolock surfaceLock(mSurfaceLock);
219 // asBinder() is safe on NULL (returns NULL)
220 if (surface->asBinder() != mSurface->asBinder()) {
221 if (mSurface != 0) {
222 LOGD("clearing old preview surface %p", mSurface.get());
223 mSurface->unregisterBuffers();
224 }
225 mSurface = surface;
226 }
227 return NO_ERROR;
228}
229
230// tell the service whether to callback with each preview frame
231void CameraService::Client::setHasFrameCallback(bool installed)
232{
233 Mutex::Autolock lock(mLock);
234 mHasFrameCallback = installed;
235 // If installed is false, mPreviewBuffer will be released in stopPreview().
236}
237
238// start preview mode, must call setPreviewDisplay first
239status_t CameraService::Client::startPreview()
240{
241 LOGD("startPreview()");
242
243 /* we cannot call into mHardware with mLock held because
244 * mHardware has callbacks onto us which acquire this lock
245 */
246
247 Mutex::Autolock lock(mLock);
248
249 if (mHardware == 0) {
250 LOGE("mHardware is NULL, returning.");
251 return INVALID_OPERATION;
252 }
253
254 if (mSurface == 0) {
255 LOGE("setPreviewDisplay must be called before startPreview!");
256 return INVALID_OPERATION;
257 }
258
259 // XXX: This needs to be improved. remove all hardcoded stuff
260
261 int w, h;
262 CameraParameters params(mHardware->getParameters());
263 params.getPreviewSize(&w, &h);
264
265 mSurface->unregisterBuffers();
266
267#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
268 debug_frame_cnt = 0;
269#endif
270
271 status_t ret = mHardware->startPreview(previewCallback,
272 mCameraService.get());
273 if (ret == NO_ERROR) {
274 mSurface->registerBuffers(w,h,w,h,
275 PIXEL_FORMAT_YCbCr_420_SP,
276 mHardware->getPreviewHeap());
277 }
278 else LOGE("mHardware->startPreview() failed with status %d\n",
279 ret);
280
281 return ret;
282}
283
284// stop preview mode
285void CameraService::Client::stopPreview()
286{
287 LOGD("stopPreview()");
288
289 Mutex::Autolock lock(mLock);
290
291 if (mHardware == 0) {
292 LOGE("mHardware is NULL, returning.");
293 return;
294 }
295
296 mHardware->stopPreview();
297 LOGD("stopPreview(), hardware stopped OK");
298
299 if (mSurface != 0) {
300 mSurface->unregisterBuffers();
301 }
302 mPreviewBuffer.clear();
303}
304
305// Safely retrieves a strong pointer to the client during a hardware callback.
306sp<CameraService::Client> CameraService::Client::getClientFromCookie(void* user)
307{
308 sp<Client> client = 0;
309 CameraService *service = static_cast<CameraService*>(user);
310 if (service != NULL) {
311 Mutex::Autolock ourLock(service->mLock);
312 if (service->mClient != 0) {
313 client = service->mClient.promote();
314 if (client == 0) {
315 LOGE("getClientFromCookie: client appears to have died");
316 service->mClient.clear();
317 }
318 } else {
319 LOGE("getClientFromCookie: got callback but client was NULL");
320 }
321 }
322 return client;
323}
324
325
326#if DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE || \
327 DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE || \
328 DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
329static void dump_to_file(const char *fname,
330 uint8_t *buf, uint32_t size)
331{
332 int nw, cnt = 0;
333 uint32_t written = 0;
334
335 LOGD("opening file [%s]\n", fname);
336 int fd = open(fname, O_RDWR | O_CREAT);
337 if (fd < 0) {
338 LOGE("failed to create file [%s]: %s", fname, strerror(errno));
339 return;
340 }
341
342 LOGD("writing %d bytes to file [%s]\n", size, fname);
343 while (written < size) {
344 nw = ::write(fd,
345 buf + written,
346 size - written);
347 if (nw < 0) {
348 LOGE("failed to write to file [%s]: %s",
349 fname, strerror(errno));
350 break;
351 }
352 written += nw;
353 cnt++;
354 }
355 LOGD("done writing %d bytes to file [%s] in %d passes\n",
356 size, fname, cnt);
357 ::close(fd);
358}
359#endif
360
361// preview callback - frame buffer update
362void CameraService::Client::previewCallback(const sp<IMemory>& mem, void* user)
363{
364 sp<Client> client = getClientFromCookie(user);
365 if (client == 0) {
366 return;
367 }
368
369#if DEBUG_HEAP_LEAKS && 0 // debugging
370 if (gWeakHeap == NULL) {
371 ssize_t offset;
372 size_t size;
373 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
374 if (gWeakHeap != heap) {
375 LOGD("SETTING PREVIEW HEAP");
376 heap->trackMe(true, true);
377 gWeakHeap = heap;
378 }
379 }
380#endif
381
382#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
383 {
384 if (debug_frame_cnt++ == DEBUG_DUMP_PREVIEW_FRAME_TO_FILE) {
385 ssize_t offset;
386 size_t size;
387 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
388 dump_to_file("/data/preview.yuv",
389 (uint8_t *)heap->base() + offset, size);
390 }
391 }
392#endif
393
394 // The strong pointer guarantees the client will exist, but no lock is held.
395 client->postFrame(mem);
396
397#if DEBUG_CLIENT_REFERENCES
398 //**** if the client's refcount is 1, then we are about to destroy it here,
399 // which is bad--print all refcounts.
400 if (client->getStrongCount() == 1) {
401 LOGE("++++++++++++++++ (PREVIEW) THIS WILL CAUSE A LOCKUP!");
402 client->printRefs();
403 }
404#endif
405}
406
407// take a picture - image is returned in callback
408status_t CameraService::Client::autoFocus()
409{
410 LOGV("autoFocus");
411
412 Mutex::Autolock lock(mLock);
413
414 if (mHardware == 0) {
415 LOGE("mHardware is NULL, returning.");
416 return INVALID_OPERATION;
417 }
418
419 return mHardware->autoFocus(autoFocusCallback,
420 mCameraService.get());
421}
422
423// take a picture - image is returned in callback
424status_t CameraService::Client::takePicture()
425{
426 LOGD("takePicture");
427
428 Mutex::Autolock lock(mLock);
429
430 if (mHardware == 0) {
431 LOGE("mHardware is NULL, returning.");
432 return INVALID_OPERATION;
433 }
434
435 if (mSurface != NULL)
436 mSurface->unregisterBuffers();
437
438 return mHardware->takePicture(shutterCallback,
439 yuvPictureCallback,
440 jpegPictureCallback,
441 mCameraService.get());
442}
443
444// picture callback - snapshot taken
445void CameraService::Client::shutterCallback(void *user)
446{
447 sp<Client> client = getClientFromCookie(user);
448 if (client == 0) {
449 return;
450 }
451
452 client->postShutter();
453}
454
455// picture callback - raw image ready
456void CameraService::Client::yuvPictureCallback(const sp<IMemory>& mem,
457 void *user)
458{
459 sp<Client> client = getClientFromCookie(user);
460 if (client == 0) {
461 return;
462 }
463 if (mem == NULL) {
464 client->postRaw(NULL);
465 client->postError(UNKNOWN_ERROR);
466 return;
467 }
468
469 ssize_t offset;
470 size_t size;
471 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
472#if DEBUG_HEAP_LEAKS && 0 // debugging
473 gWeakHeap = heap; // debugging
474#endif
475
476 //LOGV("yuvPictureCallback(%d, %d, %p)", offset, size, user);
477#if DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE // for testing pursposes only
478 dump_to_file("/data/photo.yuv",
479 (uint8_t *)heap->base() + offset, size);
480#endif
481
482 // Put the YUV version of the snapshot in the preview display.
483 int w, h;
484 CameraParameters params(client->mHardware->getParameters());
485 params.getPictureSize(&w, &h);
486
487// Mutex::Autolock clientLock(client->mLock);
488 if (client->mSurface != 0) {
489 client->mSurface->unregisterBuffers();
490 client->mSurface->registerBuffers(w,h,w,h,
491 PIXEL_FORMAT_YCbCr_420_SP, heap);
492 client->mSurface->postBuffer(offset);
493 }
494
495 client->postRaw(mem);
496
497#if DEBUG_CLIENT_REFERENCES
498 //**** if the client's refcount is 1, then we are about to destroy it here,
499 // which is bad--print all refcounts.
500 if (client->getStrongCount() == 1) {
501 LOGE("++++++++++++++++ (RAW) THIS WILL CAUSE A LOCKUP!");
502 client->printRefs();
503 }
504#endif
505}
506
507// picture callback - jpeg ready
508void CameraService::Client::jpegPictureCallback(const sp<IMemory>& mem, void *user)
509{
510 sp<Client> client = getClientFromCookie(user);
511 if (client == 0) {
512 return;
513 }
514 if (mem == NULL) {
515 client->postJpeg(NULL);
516 client->postError(UNKNOWN_ERROR);
517 return;
518 }
519
520 /** We absolutely CANNOT call into user code with a lock held **/
521
522#if DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE // for testing pursposes only
523 {
524 ssize_t offset;
525 size_t size;
526 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
527 dump_to_file("/data/photo.jpg",
528 (uint8_t *)heap->base() + offset, size);
529 }
530#endif
531
532 client->postJpeg(mem);
533
534#if DEBUG_CLIENT_REFERENCES
535 //**** if the client's refcount is 1, then we are about to destroy it here,
536 // which is bad--print all refcounts.
537 if (client->getStrongCount() == 1) {
538 LOGE("++++++++++++++++ (JPEG) THIS WILL CAUSE A LOCKUP!");
539 client->printRefs();
540 }
541#endif
542}
543
544void CameraService::Client::autoFocusCallback(bool focused, void *user)
545{
546 LOGV("autoFocusCallback");
547
548 sp<Client> client = getClientFromCookie(user);
549 if (client == 0) {
550 return;
551 }
552
553 client->postAutoFocus(focused);
554
555#if DEBUG_CLIENT_REFERENCES
556 if (client->getStrongCount() == 1) {
557 LOGE("++++++++++++++++ (AUTOFOCUS) THIS WILL CAUSE A LOCKUP!");
558 client->printRefs();
559 }
560#endif
561}
562
563// set preview/capture parameters - key/value pairs
564status_t CameraService::Client::setParameters(const String8& params)
565{
566 LOGD("setParameters(%s)", params.string());
567
568 Mutex::Autolock lock(mLock);
569
570 if (mHardware == 0) {
571 LOGE("mHardware is NULL, returning.");
572 return INVALID_OPERATION;
573 }
574
575 CameraParameters p(params);
576 mHardware->setParameters(p);
577 return NO_ERROR;
578}
579
580// get preview/capture parameters - key/value pairs
581String8 CameraService::Client::getParameters() const
582{
583 LOGD("getParameters");
584
585 Mutex::Autolock lock(mLock);
586
587 if (mHardware == 0) {
588 LOGE("mHardware is NULL, returning.");
589 return String8();
590 }
591
592 return mHardware->getParameters().flatten();
593}
594
595void CameraService::Client::postAutoFocus(bool focused)
596{
597 LOGV("postAutoFocus");
598 mCameraClient->autoFocusCallback(focused);
599}
600
601void CameraService::Client::postShutter()
602{
603 mCameraClient->shutterCallback();
604}
605
606void CameraService::Client::postRaw(const sp<IMemory>& mem)
607{
608 LOGD("postRaw");
609 mCameraClient->rawCallback(mem);
610}
611
612void CameraService::Client::postJpeg(const sp<IMemory>& mem)
613{
614 LOGD("postJpeg");
615 mCameraClient->jpegCallback(mem);
616}
617
618void CameraService::Client::postFrame(const sp<IMemory>& mem)
619{
620 ssize_t offset;
621 size_t size;
622 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
623
624 sp<MemoryBase> frame;
625
626 {
627 Mutex::Autolock surfaceLock(mSurfaceLock);
628 if (mSurface != NULL)
629 mSurface->postBuffer(offset);
630 }
631
632 // It is necessary to copy out of pmem before sending this to the callback.
633 // For efficiency, reuse the same MemoryHeapBase provided it's big enough.
634 // Don't allocate the memory or perform the copy if there's no callback.
635 if (mHasFrameCallback) {
636 if (mPreviewBuffer == 0) {
637 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
638 } else if (size > mPreviewBuffer->virtualSize()) {
639 mPreviewBuffer.clear();
640 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
641 }
642 memcpy(mPreviewBuffer->base(), (uint8_t *)heap->base() + offset, size);
643 frame = new MemoryBase(mPreviewBuffer, 0, size);
644 }
645
646 // Do not hold the client lock while calling back.
647 if (frame != 0) {
648 mCameraClient->frameCallback(frame);
649 }
650}
651
652void CameraService::Client::postError(status_t error) {
653 mCameraClient->errorCallback(error);
654}
655
656status_t CameraService::dump(int fd, const Vector<String16>& args)
657{
658 const size_t SIZE = 256;
659 char buffer[SIZE];
660 String8 result;
661 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
662 snprintf(buffer, SIZE, "Permission Denial: "
663 "can't dump CameraService from pid=%d, uid=%d\n",
664 IPCThreadState::self()->getCallingPid(),
665 IPCThreadState::self()->getCallingUid());
666 result.append(buffer);
667 write(fd, result.string(), result.size());
668 } else {
669 AutoMutex lock(&mLock);
670 if (mClient != 0) {
671 sp<Client> currentClient = mClient.promote();
672 currentClient->mHardware->dump(fd, args);
673 } else {
674 result.append("No camera client yet.\n");
675 write(fd, result.string(), result.size());
676 }
677 }
678 return NO_ERROR;
679}
680
681
682#if DEBUG_HEAP_LEAKS
683
684#define CHECK_INTERFACE(interface, data, reply) \
685 do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
686 LOGW("Call incorrectly routed to " #interface); \
687 return PERMISSION_DENIED; \
688 } } while (0)
689
690status_t CameraService::onTransact(
691 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
692{
693 // permission checks...
694 switch (code) {
695 case BnCameraService::CONNECT:
696 IPCThreadState* ipc = IPCThreadState::self();
697 const int pid = ipc->getCallingPid();
698 const int self_pid = getpid();
699 if (pid != self_pid) {
700 // we're called from a different process, do the real check
701 if (!checkCallingPermission(
702 String16("android.permission.CAMERA")))
703 {
704 const int uid = ipc->getCallingUid();
705 LOGE("Permission Denial: "
706 "can't use the camera pid=%d, uid=%d", pid, uid);
707 return PERMISSION_DENIED;
708 }
709 }
710 break;
711 }
712
713 status_t err = BnCameraService::onTransact(code, data, reply, flags);
714
715 LOGD("+++ onTransact err %d code %d", err, code);
716
717 if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
718 // the 'service' command interrogates this binder for its name, and then supplies it
719 // even for the debugging commands. that means we need to check for it here, using
720 // ISurfaceComposer (since we delegated the INTERFACE_TRANSACTION handling to
721 // BnSurfaceComposer before falling through to this code).
722
723 LOGD("+++ onTransact code %d", code);
724
725 CHECK_INTERFACE(ICameraService, data, reply);
726
727 switch(code) {
728 case 1000:
729 {
730 if (gWeakHeap != 0) {
731 sp<IMemoryHeap> h = gWeakHeap.promote();
732 IMemoryHeap *p = gWeakHeap.unsafe_get();
733 LOGD("CHECKING WEAK REFERENCE %p (%p)", h.get(), p);
734 if (h != 0)
735 h->printRefs();
736 bool attempt_to_delete = data.readInt32() == 1;
737 if (attempt_to_delete) {
738 // NOT SAFE!
739 LOGD("DELETING WEAK REFERENCE %p (%p)", h.get(), p);
740 if (p) delete p;
741 }
742 return NO_ERROR;
743 }
744 }
745 break;
746 default:
747 break;
748 }
749 }
750 return err;
751}
752
753#endif // DEBUG_HEAP_LEAKS
754
755}; // namespace android
756
757