blob: 800ffa48a1949aded8d4e50ff21ef2d160cb2ec4 [file] [log] [blame]
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001/*
2**
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -08003** Copyright (C) 2008, The Android Open Source Project
4** Copyright (C) 2008 HTC Inc.
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07005**
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
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -080019//#define LOG_NDEBUG 0
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070020#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 if (mClient != 0) {
90 sp<Client> currentClient = mClient.promote();
91 if (currentClient != 0) {
92 sp<ICameraClient> currentCameraClient(currentClient->getCameraClient());
93 if (cameraClient->asBinder() == currentCameraClient->asBinder()) {
94 // this is the same client reconnecting...
95 LOGD("Connect X same client is reconnecting...");
96 return currentClient;
97 } else {
98 // it's another client... boot the previous one...
99 LOGD("new client connecting, booting the old one...");
100 mClient.clear();
101 }
102 } else {
103 // can't promote, the previous client has died...
104 LOGD("new client connecting, old reference was dangling...");
105 mClient.clear();
106 }
107 }
108
109 // create a new Client object
110 sp<Client> client = new Client(this, cameraClient);
111 mClient = client;
112#if DEBUG_CLIENT_REFERENCES
113 // Enable tracking for this object, and track increments and decrements of
114 // the refcount.
115 client->trackMe(true, true);
116#endif
117 LOGD("Connect X");
118 return client;
119}
120
121void CameraService::removeClient(const sp<ICameraClient>& cameraClient)
122{
123 // declar this outside the lock to make absolutely sure the
124 // destructor won't be called with the lock held.
125 sp<Client> client;
126
127 Mutex::Autolock lock(mLock);
128
129 if (mClient == 0) {
130 // This happens when we have already disconnected.
131 LOGV("mClient is null.");
132 return;
133 }
134
135 // Promote mClient. It should never fail because we're called from
136 // a binder call, so someone has to have a strong reference.
137 client = mClient.promote();
138 if (client == 0) {
139 LOGW("can't get a strong reference on mClient!");
140 mClient.clear();
141 return;
142 }
143
144 if (cameraClient->asBinder() != client->getCameraClient()->asBinder()) {
145 // ugh! that's not our client!!
146 LOGW("removeClient() called, but mClient doesn't match!");
147 } else {
148 // okay, good, forget about mClient
149 mClient.clear();
150 }
151}
152
153CameraService::Client::Client(const sp<CameraService>& cameraService,
154 const sp<ICameraClient>& cameraClient) :
155 mCameraService(cameraService), mCameraClient(cameraClient), mHardware(0)
156{
157 LOGD("Client E constructor");
158 mHardware = openCameraHardware();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800159
160 // Callback is disabled by default
161 mFrameCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700162 LOGD("Client X constructor");
163}
164
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800165status_t CameraService::Client::connect(const sp<ICameraClient>& client)
166{
167 // remvoe old client
168 LOGD("connect (new client)");
169 Mutex::Autolock _l(mLock);
170 mCameraClient = client;
171 mFrameCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
172 return NO_ERROR;
173}
174
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700175#if HAVE_ANDROID_OS
176static void *unregister_surface(void *arg)
177{
178 ISurface *surface = (ISurface *)arg;
179 surface->unregisterBuffers();
180 IPCThreadState::self()->flushCommands();
181 return NULL;
182}
183#endif
184
185CameraService::Client::~Client()
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800186{
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700187 // spin down hardware
188 LOGD("Client E destructor");
189 if (mSurface != 0) {
190#if HAVE_ANDROID_OS
191 pthread_t thr;
192 // We unregister the buffers in a different thread because binder does
193 // not let us make sychronous transactions in a binder destructor (that
194 // is, upon our reaching a refcount of zero.)
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800195 pthread_create(&thr, NULL,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700196 unregister_surface,
197 mSurface.get());
198 pthread_join(thr, NULL);
199#else
200 mSurface->unregisterBuffers();
201#endif
202 }
203
204 disconnect();
205 LOGD("Client X destructor");
206}
207
208void CameraService::Client::disconnect()
209{
210 LOGD("Client E disconnect");
211 Mutex::Autolock lock(mLock);
212 mCameraService->removeClient(mCameraClient);
213 if (mHardware != 0) {
214 // Before destroying mHardware, we must make sure it's in the
215 // idle state.
216 mHardware->stopPreview();
217 // Cancel all picture callbacks.
218 mHardware->cancelPicture(true, true, true);
219 // Release the hardware resources.
220 mHardware->release();
221 }
222 mHardware.clear();
223 LOGD("Client X disconnect");
224}
225
226// pass the buffered ISurface to the camera service
227status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface)
228{
229 LOGD("setPreviewDisplay(%p)", surface.get());
230 Mutex::Autolock lock(mLock);
231 Mutex::Autolock surfaceLock(mSurfaceLock);
232 // asBinder() is safe on NULL (returns NULL)
233 if (surface->asBinder() != mSurface->asBinder()) {
234 if (mSurface != 0) {
235 LOGD("clearing old preview surface %p", mSurface.get());
236 mSurface->unregisterBuffers();
237 }
238 mSurface = surface;
239 }
240 return NO_ERROR;
241}
242
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800243// set the frame callback flag to affect how the received frames from
244// preview are handled.
245void CameraService::Client::setFrameCallbackFlag(int frame_callback_flag)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700246{
247 Mutex::Autolock lock(mLock);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800248 mFrameCallbackFlag = frame_callback_flag;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700249}
250
251// start preview mode, must call setPreviewDisplay first
252status_t CameraService::Client::startPreview()
253{
254 LOGD("startPreview()");
255
256 /* we cannot call into mHardware with mLock held because
257 * mHardware has callbacks onto us which acquire this lock
258 */
259
260 Mutex::Autolock lock(mLock);
261
262 if (mHardware == 0) {
263 LOGE("mHardware is NULL, returning.");
264 return INVALID_OPERATION;
265 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800266
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700267 if (mSurface == 0) {
268 LOGE("setPreviewDisplay must be called before startPreview!");
269 return INVALID_OPERATION;
270 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800271
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700272 // XXX: This needs to be improved. remove all hardcoded stuff
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800273
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700274 int w, h;
275 CameraParameters params(mHardware->getParameters());
276 params.getPreviewSize(&w, &h);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800277
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700278 mSurface->unregisterBuffers();
279
280#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
281 debug_frame_cnt = 0;
282#endif
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800283
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700284 status_t ret = mHardware->startPreview(previewCallback,
285 mCameraService.get());
286 if (ret == NO_ERROR) {
287 mSurface->registerBuffers(w,h,w,h,
288 PIXEL_FORMAT_YCbCr_420_SP,
289 mHardware->getPreviewHeap());
290 }
291 else LOGE("mHardware->startPreview() failed with status %d\n",
292 ret);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800293
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700294 return ret;
295}
296
297// stop preview mode
298void CameraService::Client::stopPreview()
299{
300 LOGD("stopPreview()");
301
302 Mutex::Autolock lock(mLock);
303
304 if (mHardware == 0) {
305 LOGE("mHardware is NULL, returning.");
306 return;
307 }
308
309 mHardware->stopPreview();
310 LOGD("stopPreview(), hardware stopped OK");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800311
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700312 if (mSurface != 0) {
313 mSurface->unregisterBuffers();
314 }
315 mPreviewBuffer.clear();
316}
317
318// Safely retrieves a strong pointer to the client during a hardware callback.
319sp<CameraService::Client> CameraService::Client::getClientFromCookie(void* user)
320{
321 sp<Client> client = 0;
322 CameraService *service = static_cast<CameraService*>(user);
323 if (service != NULL) {
324 Mutex::Autolock ourLock(service->mLock);
325 if (service->mClient != 0) {
326 client = service->mClient.promote();
327 if (client == 0) {
328 LOGE("getClientFromCookie: client appears to have died");
329 service->mClient.clear();
330 }
331 } else {
332 LOGE("getClientFromCookie: got callback but client was NULL");
333 }
334 }
335 return client;
336}
337
338
339#if DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE || \
340 DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE || \
341 DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
342static void dump_to_file(const char *fname,
343 uint8_t *buf, uint32_t size)
344{
345 int nw, cnt = 0;
346 uint32_t written = 0;
347
348 LOGD("opening file [%s]\n", fname);
349 int fd = open(fname, O_RDWR | O_CREAT);
350 if (fd < 0) {
351 LOGE("failed to create file [%s]: %s", fname, strerror(errno));
352 return;
353 }
354
355 LOGD("writing %d bytes to file [%s]\n", size, fname);
356 while (written < size) {
357 nw = ::write(fd,
358 buf + written,
359 size - written);
360 if (nw < 0) {
361 LOGE("failed to write to file [%s]: %s",
362 fname, strerror(errno));
363 break;
364 }
365 written += nw;
366 cnt++;
367 }
368 LOGD("done writing %d bytes to file [%s] in %d passes\n",
369 size, fname, cnt);
370 ::close(fd);
371}
372#endif
373
374// preview callback - frame buffer update
375void CameraService::Client::previewCallback(const sp<IMemory>& mem, void* user)
376{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800377 LOGV("previewCallback()");
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700378 sp<Client> client = getClientFromCookie(user);
379 if (client == 0) {
380 return;
381 }
382
383#if DEBUG_HEAP_LEAKS && 0 // debugging
384 if (gWeakHeap == NULL) {
385 ssize_t offset;
386 size_t size;
387 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
388 if (gWeakHeap != heap) {
389 LOGD("SETTING PREVIEW HEAP");
390 heap->trackMe(true, true);
391 gWeakHeap = heap;
392 }
393 }
394#endif
395
396#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
397 {
398 if (debug_frame_cnt++ == DEBUG_DUMP_PREVIEW_FRAME_TO_FILE) {
399 ssize_t offset;
400 size_t size;
401 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
402 dump_to_file("/data/preview.yuv",
403 (uint8_t *)heap->base() + offset, size);
404 }
405 }
406#endif
407
408 // The strong pointer guarantees the client will exist, but no lock is held.
409 client->postFrame(mem);
410
411#if DEBUG_CLIENT_REFERENCES
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800412 //**** if the client's refcount is 1, then we are about to destroy it here,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700413 // which is bad--print all refcounts.
414 if (client->getStrongCount() == 1) {
415 LOGE("++++++++++++++++ (PREVIEW) THIS WILL CAUSE A LOCKUP!");
416 client->printRefs();
417 }
418#endif
419}
420
421// take a picture - image is returned in callback
422status_t CameraService::Client::autoFocus()
423{
424 LOGV("autoFocus");
425
426 Mutex::Autolock lock(mLock);
427
428 if (mHardware == 0) {
429 LOGE("mHardware is NULL, returning.");
430 return INVALID_OPERATION;
431 }
432
433 return mHardware->autoFocus(autoFocusCallback,
434 mCameraService.get());
435}
436
437// take a picture - image is returned in callback
438status_t CameraService::Client::takePicture()
439{
440 LOGD("takePicture");
441
442 Mutex::Autolock lock(mLock);
443
444 if (mHardware == 0) {
445 LOGE("mHardware is NULL, returning.");
446 return INVALID_OPERATION;
447 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800448
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700449 if (mSurface != NULL)
450 mSurface->unregisterBuffers();
451
452 return mHardware->takePicture(shutterCallback,
453 yuvPictureCallback,
454 jpegPictureCallback,
455 mCameraService.get());
456}
457
458// picture callback - snapshot taken
459void CameraService::Client::shutterCallback(void *user)
460{
461 sp<Client> client = getClientFromCookie(user);
462 if (client == 0) {
463 return;
464 }
465
466 client->postShutter();
467}
468
469// picture callback - raw image ready
470void CameraService::Client::yuvPictureCallback(const sp<IMemory>& mem,
471 void *user)
472{
473 sp<Client> client = getClientFromCookie(user);
474 if (client == 0) {
475 return;
476 }
477 if (mem == NULL) {
478 client->postRaw(NULL);
479 client->postError(UNKNOWN_ERROR);
480 return;
481 }
482
483 ssize_t offset;
484 size_t size;
485 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
486#if DEBUG_HEAP_LEAKS && 0 // debugging
487 gWeakHeap = heap; // debugging
488#endif
489
490 //LOGV("yuvPictureCallback(%d, %d, %p)", offset, size, user);
491#if DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE // for testing pursposes only
492 dump_to_file("/data/photo.yuv",
493 (uint8_t *)heap->base() + offset, size);
494#endif
495
496 // Put the YUV version of the snapshot in the preview display.
497 int w, h;
498 CameraParameters params(client->mHardware->getParameters());
499 params.getPictureSize(&w, &h);
500
501// Mutex::Autolock clientLock(client->mLock);
502 if (client->mSurface != 0) {
503 client->mSurface->unregisterBuffers();
504 client->mSurface->registerBuffers(w,h,w,h,
505 PIXEL_FORMAT_YCbCr_420_SP, heap);
506 client->mSurface->postBuffer(offset);
507 }
508
509 client->postRaw(mem);
510
511#if DEBUG_CLIENT_REFERENCES
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800512 //**** if the client's refcount is 1, then we are about to destroy it here,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700513 // which is bad--print all refcounts.
514 if (client->getStrongCount() == 1) {
515 LOGE("++++++++++++++++ (RAW) THIS WILL CAUSE A LOCKUP!");
516 client->printRefs();
517 }
518#endif
519}
520
521// picture callback - jpeg ready
522void CameraService::Client::jpegPictureCallback(const sp<IMemory>& mem, void *user)
523{
524 sp<Client> client = getClientFromCookie(user);
525 if (client == 0) {
526 return;
527 }
528 if (mem == NULL) {
529 client->postJpeg(NULL);
530 client->postError(UNKNOWN_ERROR);
531 return;
532 }
533
534 /** We absolutely CANNOT call into user code with a lock held **/
535
536#if DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE // for testing pursposes only
537 {
538 ssize_t offset;
539 size_t size;
540 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
541 dump_to_file("/data/photo.jpg",
542 (uint8_t *)heap->base() + offset, size);
543 }
544#endif
545
546 client->postJpeg(mem);
547
548#if DEBUG_CLIENT_REFERENCES
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800549 //**** if the client's refcount is 1, then we are about to destroy it here,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700550 // which is bad--print all refcounts.
551 if (client->getStrongCount() == 1) {
552 LOGE("++++++++++++++++ (JPEG) THIS WILL CAUSE A LOCKUP!");
553 client->printRefs();
554 }
555#endif
556}
557
558void CameraService::Client::autoFocusCallback(bool focused, void *user)
559{
560 LOGV("autoFocusCallback");
561
562 sp<Client> client = getClientFromCookie(user);
563 if (client == 0) {
564 return;
565 }
566
567 client->postAutoFocus(focused);
568
569#if DEBUG_CLIENT_REFERENCES
570 if (client->getStrongCount() == 1) {
571 LOGE("++++++++++++++++ (AUTOFOCUS) THIS WILL CAUSE A LOCKUP!");
572 client->printRefs();
573 }
574#endif
575}
576
577// set preview/capture parameters - key/value pairs
578status_t CameraService::Client::setParameters(const String8& params)
579{
580 LOGD("setParameters(%s)", params.string());
581
582 Mutex::Autolock lock(mLock);
583
584 if (mHardware == 0) {
585 LOGE("mHardware is NULL, returning.");
586 return INVALID_OPERATION;
587 }
588
589 CameraParameters p(params);
590 mHardware->setParameters(p);
591 return NO_ERROR;
592}
593
594// get preview/capture parameters - key/value pairs
595String8 CameraService::Client::getParameters() const
596{
597 LOGD("getParameters");
598
599 Mutex::Autolock lock(mLock);
600
601 if (mHardware == 0) {
602 LOGE("mHardware is NULL, returning.");
603 return String8();
604 }
605
606 return mHardware->getParameters().flatten();
607}
608
609void CameraService::Client::postAutoFocus(bool focused)
610{
611 LOGV("postAutoFocus");
612 mCameraClient->autoFocusCallback(focused);
613}
614
615void CameraService::Client::postShutter()
616{
617 mCameraClient->shutterCallback();
618}
619
620void CameraService::Client::postRaw(const sp<IMemory>& mem)
621{
622 LOGD("postRaw");
623 mCameraClient->rawCallback(mem);
624}
625
626void CameraService::Client::postJpeg(const sp<IMemory>& mem)
627{
628 LOGD("postJpeg");
629 mCameraClient->jpegCallback(mem);
630}
631
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800632void CameraService::Client::copyFrameAndPostCopiedFrame(sp<IMemoryHeap> heap, size_t offset, size_t size)
633{
634 LOGV("copyFrameAndPostCopiedFrame");
635 // It is necessary to copy out of pmem before sending this to
636 // the callback. For efficiency, reuse the same MemoryHeapBase
637 // provided it's big enough. Don't allocate the memory or
638 // perform the copy if there's no callback.
639 if (mPreviewBuffer == 0) {
640 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
641 } else if (size > mPreviewBuffer->virtualSize()) {
642 mPreviewBuffer.clear();
643 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
644 if (mPreviewBuffer == 0) {
645 LOGE("failed to allocate space for preview buffer");
646 return;
647 }
648 }
649 memcpy(mPreviewBuffer->base(),
650 (uint8_t *)heap->base() + offset, size);
651
652 sp<MemoryBase> frame = new MemoryBase(mPreviewBuffer, 0, size);
653 if (frame == 0) {
654 LOGE("failed to allocate space for frame callback");
655 return;
656 }
657 mCameraClient->frameCallback(frame);
658}
659
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700660void CameraService::Client::postFrame(const sp<IMemory>& mem)
661{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800662 LOGV("postFrame");
663 if (mem == 0) {
664 LOGW("mem is a null pointer");
665 return;
666 }
667
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700668 ssize_t offset;
669 size_t size;
670 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700671 {
672 Mutex::Autolock surfaceLock(mSurfaceLock);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800673 if (mSurface != NULL) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700674 mSurface->postBuffer(offset);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700675 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700676 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800677
678 // Is the callback enabled or not?
679 if (!(mFrameCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
680 // If the enable bit is off, the copy-out and one-shot bits are ignored
681 LOGV("frame callback is diabled");
682 return;
683 }
684
685 // Is the received frame copied out or not?
686 if (mFrameCallbackFlag & FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
687 LOGV("frame is copied out");
688 copyFrameAndPostCopiedFrame(heap, offset, size);
689 } else {
690 LOGV("frame is directly sent out without copying");
691 mCameraClient->frameCallback(mem);
692 }
693
694 // Is this is one-shot only?
695 if (mFrameCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) {
696 LOGV("One-shot only, thus clear the bits and disable frame callback");
697 mFrameCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
698 FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
699 FRAME_CALLBACK_FLAG_ENABLE_MASK);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700700 }
701}
702
703void CameraService::Client::postError(status_t error) {
704 mCameraClient->errorCallback(error);
705}
706
707status_t CameraService::dump(int fd, const Vector<String16>& args)
708{
709 const size_t SIZE = 256;
710 char buffer[SIZE];
711 String8 result;
712 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
713 snprintf(buffer, SIZE, "Permission Denial: "
714 "can't dump CameraService from pid=%d, uid=%d\n",
715 IPCThreadState::self()->getCallingPid(),
716 IPCThreadState::self()->getCallingUid());
717 result.append(buffer);
718 write(fd, result.string(), result.size());
719 } else {
720 AutoMutex lock(&mLock);
721 if (mClient != 0) {
722 sp<Client> currentClient = mClient.promote();
723 currentClient->mHardware->dump(fd, args);
724 } else {
725 result.append("No camera client yet.\n");
726 write(fd, result.string(), result.size());
727 }
728 }
729 return NO_ERROR;
730}
731
732
733#if DEBUG_HEAP_LEAKS
734
735#define CHECK_INTERFACE(interface, data, reply) \
736 do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
737 LOGW("Call incorrectly routed to " #interface); \
738 return PERMISSION_DENIED; \
739 } } while (0)
740
741status_t CameraService::onTransact(
742 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
743{
744 // permission checks...
745 switch (code) {
746 case BnCameraService::CONNECT:
747 IPCThreadState* ipc = IPCThreadState::self();
748 const int pid = ipc->getCallingPid();
749 const int self_pid = getpid();
750 if (pid != self_pid) {
751 // we're called from a different process, do the real check
752 if (!checkCallingPermission(
753 String16("android.permission.CAMERA")))
754 {
755 const int uid = ipc->getCallingUid();
756 LOGE("Permission Denial: "
757 "can't use the camera pid=%d, uid=%d", pid, uid);
758 return PERMISSION_DENIED;
759 }
760 }
761 break;
762 }
763
764 status_t err = BnCameraService::onTransact(code, data, reply, flags);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800765
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700766 LOGD("+++ onTransact err %d code %d", err, code);
767
768 if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
769 // the 'service' command interrogates this binder for its name, and then supplies it
770 // even for the debugging commands. that means we need to check for it here, using
771 // ISurfaceComposer (since we delegated the INTERFACE_TRANSACTION handling to
772 // BnSurfaceComposer before falling through to this code).
773
774 LOGD("+++ onTransact code %d", code);
775
776 CHECK_INTERFACE(ICameraService, data, reply);
777
778 switch(code) {
779 case 1000:
780 {
781 if (gWeakHeap != 0) {
782 sp<IMemoryHeap> h = gWeakHeap.promote();
783 IMemoryHeap *p = gWeakHeap.unsafe_get();
784 LOGD("CHECKING WEAK REFERENCE %p (%p)", h.get(), p);
785 if (h != 0)
786 h->printRefs();
787 bool attempt_to_delete = data.readInt32() == 1;
788 if (attempt_to_delete) {
789 // NOT SAFE!
790 LOGD("DELETING WEAK REFERENCE %p (%p)", h.get(), p);
791 if (p) delete p;
792 }
793 return NO_ERROR;
794 }
795 }
796 break;
797 default:
798 break;
799 }
800 }
801 return err;
802}
803
804#endif // DEBUG_HEAP_LEAKS
805
806}; // namespace android
807
808