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