blob: 33987c360723d0ded433bbe0d53b3f5937593e96 [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
The Android Open Source Project27629322009-01-09 17:51:23 -0800110 sp<Client> client = new Client(this, cameraClient, IPCThreadState::self()->getCallingPid());
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700111 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,
The Android Open Source Project27629322009-01-09 17:51:23 -0800154 const sp<ICameraClient>& cameraClient, pid_t clientPid)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700155{
156 LOGD("Client E constructor");
The Android Open Source Project27629322009-01-09 17:51:23 -0800157 mCameraService = cameraService;
158 mCameraClient = cameraClient;
159 mClientPid = clientPid;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700160 mHardware = openCameraHardware();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800161
162 // Callback is disabled by default
163 mFrameCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700164 LOGD("Client X constructor");
165}
166
The Android Open Source Project27629322009-01-09 17:51:23 -0800167status_t CameraService::Client::checkPid()
168{
169 // zero means the interface is not locked down
170 if (mClientPid == 0) return NO_ERROR;
171 return (int) mClientPid == IPCThreadState::self()->getCallingPid() ? NO_ERROR : -EBUSY;
172}
173
174status_t CameraService::Client::lock()
175{
176 // lock camera to this client
177 status_t result = checkPid();
178 if (result == NO_ERROR) mClientPid = IPCThreadState::self()->getCallingPid();
179 return result;
180}
181
182status_t CameraService::Client::unlock()
183{
184 // allow anyone to use camera
185 status_t result = checkPid();
186 if (result == NO_ERROR) mClientPid = 0;
187 return result;
188}
189
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800190status_t CameraService::Client::connect(const sp<ICameraClient>& client)
191{
The Android Open Source Project27629322009-01-09 17:51:23 -0800192 // remove old client
193 LOGV("connect new client to existing camera");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800194 Mutex::Autolock _l(mLock);
195 mCameraClient = client;
The Android Open Source Project27629322009-01-09 17:51:23 -0800196 mClientPid = IPCThreadState::self()->getCallingPid();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800197 mFrameCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
198 return NO_ERROR;
199}
200
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700201#if HAVE_ANDROID_OS
202static void *unregister_surface(void *arg)
203{
204 ISurface *surface = (ISurface *)arg;
205 surface->unregisterBuffers();
206 IPCThreadState::self()->flushCommands();
207 return NULL;
208}
209#endif
210
211CameraService::Client::~Client()
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800212{
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700213 // spin down hardware
214 LOGD("Client E destructor");
215 if (mSurface != 0) {
216#if HAVE_ANDROID_OS
217 pthread_t thr;
218 // We unregister the buffers in a different thread because binder does
219 // not let us make sychronous transactions in a binder destructor (that
220 // is, upon our reaching a refcount of zero.)
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800221 pthread_create(&thr, NULL,
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700222 unregister_surface,
223 mSurface.get());
224 pthread_join(thr, NULL);
225#else
226 mSurface->unregisterBuffers();
227#endif
228 }
229
230 disconnect();
231 LOGD("Client X destructor");
232}
233
234void CameraService::Client::disconnect()
235{
236 LOGD("Client E disconnect");
237 Mutex::Autolock lock(mLock);
The Android Open Source Project27629322009-01-09 17:51:23 -0800238 if (checkPid() != NO_ERROR) return;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700239 mCameraService->removeClient(mCameraClient);
240 if (mHardware != 0) {
241 // Before destroying mHardware, we must make sure it's in the
242 // idle state.
243 mHardware->stopPreview();
244 // Cancel all picture callbacks.
245 mHardware->cancelPicture(true, true, true);
246 // Release the hardware resources.
247 mHardware->release();
248 }
249 mHardware.clear();
250 LOGD("Client X disconnect");
251}
252
253// pass the buffered ISurface to the camera service
254status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface)
255{
256 LOGD("setPreviewDisplay(%p)", surface.get());
257 Mutex::Autolock lock(mLock);
The Android Open Source Project27629322009-01-09 17:51:23 -0800258 status_t result = checkPid();
259 if (result != NO_ERROR) return result;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700260 Mutex::Autolock surfaceLock(mSurfaceLock);
261 // asBinder() is safe on NULL (returns NULL)
262 if (surface->asBinder() != mSurface->asBinder()) {
263 if (mSurface != 0) {
264 LOGD("clearing old preview surface %p", mSurface.get());
265 mSurface->unregisterBuffers();
266 }
267 mSurface = surface;
268 }
269 return NO_ERROR;
270}
271
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800272// set the frame callback flag to affect how the received frames from
273// preview are handled.
274void CameraService::Client::setFrameCallbackFlag(int frame_callback_flag)
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700275{
276 Mutex::Autolock lock(mLock);
The Android Open Source Project27629322009-01-09 17:51:23 -0800277 if (checkPid() != NO_ERROR) return;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800278 mFrameCallbackFlag = frame_callback_flag;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700279}
280
281// start preview mode, must call setPreviewDisplay first
282status_t CameraService::Client::startPreview()
283{
284 LOGD("startPreview()");
285
286 /* we cannot call into mHardware with mLock held because
287 * mHardware has callbacks onto us which acquire this lock
288 */
289
290 Mutex::Autolock lock(mLock);
The Android Open Source Project27629322009-01-09 17:51:23 -0800291 status_t result = checkPid();
292 if (result != NO_ERROR) return result;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700293
294 if (mHardware == 0) {
295 LOGE("mHardware is NULL, returning.");
296 return INVALID_OPERATION;
297 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800298
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700299 if (mSurface == 0) {
300 LOGE("setPreviewDisplay must be called before startPreview!");
301 return INVALID_OPERATION;
302 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800303
The Android Open Source Project27629322009-01-09 17:51:23 -0800304 // do nothing if preview is already started
305 if (mHardware->previewEnabled()) return NO_ERROR;
306
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700307 // XXX: This needs to be improved. remove all hardcoded stuff
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800308
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700309 int w, h;
310 CameraParameters params(mHardware->getParameters());
311 params.getPreviewSize(&w, &h);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800312
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700313#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
314 debug_frame_cnt = 0;
315#endif
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800316
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700317 status_t ret = mHardware->startPreview(previewCallback,
318 mCameraService.get());
319 if (ret == NO_ERROR) {
The Android Open Source Project27629322009-01-09 17:51:23 -0800320 mSurface->unregisterBuffers();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700321 mSurface->registerBuffers(w,h,w,h,
322 PIXEL_FORMAT_YCbCr_420_SP,
323 mHardware->getPreviewHeap());
324 }
325 else LOGE("mHardware->startPreview() failed with status %d\n",
326 ret);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800327
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700328 return ret;
329}
330
331// stop preview mode
332void CameraService::Client::stopPreview()
333{
334 LOGD("stopPreview()");
335
336 Mutex::Autolock lock(mLock);
The Android Open Source Project27629322009-01-09 17:51:23 -0800337 if (checkPid() != NO_ERROR) return;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700338
339 if (mHardware == 0) {
340 LOGE("mHardware is NULL, returning.");
341 return;
342 }
343
344 mHardware->stopPreview();
345 LOGD("stopPreview(), hardware stopped OK");
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800346
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700347 if (mSurface != 0) {
348 mSurface->unregisterBuffers();
349 }
350 mPreviewBuffer.clear();
351}
352
The Android Open Source Project27629322009-01-09 17:51:23 -0800353bool CameraService::Client::previewEnabled()
354{
355 Mutex::Autolock lock(mLock);
356 if (mHardware == 0) return false;
357 return mHardware->previewEnabled();
358}
359
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700360// Safely retrieves a strong pointer to the client during a hardware callback.
361sp<CameraService::Client> CameraService::Client::getClientFromCookie(void* user)
362{
363 sp<Client> client = 0;
364 CameraService *service = static_cast<CameraService*>(user);
365 if (service != NULL) {
366 Mutex::Autolock ourLock(service->mLock);
367 if (service->mClient != 0) {
368 client = service->mClient.promote();
369 if (client == 0) {
370 LOGE("getClientFromCookie: client appears to have died");
371 service->mClient.clear();
372 }
373 } else {
374 LOGE("getClientFromCookie: got callback but client was NULL");
375 }
376 }
377 return client;
378}
379
380
381#if DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE || \
382 DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE || \
383 DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
384static void dump_to_file(const char *fname,
385 uint8_t *buf, uint32_t size)
386{
387 int nw, cnt = 0;
388 uint32_t written = 0;
389
390 LOGD("opening file [%s]\n", fname);
391 int fd = open(fname, O_RDWR | O_CREAT);
392 if (fd < 0) {
393 LOGE("failed to create file [%s]: %s", fname, strerror(errno));
394 return;
395 }
396
397 LOGD("writing %d bytes to file [%s]\n", size, fname);
398 while (written < size) {
399 nw = ::write(fd,
400 buf + written,
401 size - written);
402 if (nw < 0) {
403 LOGE("failed to write to file [%s]: %s",
404 fname, strerror(errno));
405 break;
406 }
407 written += nw;
408 cnt++;
409 }
410 LOGD("done writing %d bytes to file [%s] in %d passes\n",
411 size, fname, cnt);
412 ::close(fd);
413}
414#endif
415
416// preview callback - frame buffer update
417void CameraService::Client::previewCallback(const sp<IMemory>& mem, void* user)
418{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800419 LOGV("previewCallback()");
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700420 sp<Client> client = getClientFromCookie(user);
421 if (client == 0) {
422 return;
423 }
424
425#if DEBUG_HEAP_LEAKS && 0 // debugging
426 if (gWeakHeap == NULL) {
427 ssize_t offset;
428 size_t size;
429 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
430 if (gWeakHeap != heap) {
431 LOGD("SETTING PREVIEW HEAP");
432 heap->trackMe(true, true);
433 gWeakHeap = heap;
434 }
435 }
436#endif
437
438#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
439 {
440 if (debug_frame_cnt++ == DEBUG_DUMP_PREVIEW_FRAME_TO_FILE) {
441 ssize_t offset;
442 size_t size;
443 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
444 dump_to_file("/data/preview.yuv",
445 (uint8_t *)heap->base() + offset, size);
446 }
447 }
448#endif
449
450 // The strong pointer guarantees the client will exist, but no lock is held.
451 client->postFrame(mem);
452
453#if DEBUG_CLIENT_REFERENCES
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800454 //**** 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 -0700455 // which is bad--print all refcounts.
456 if (client->getStrongCount() == 1) {
457 LOGE("++++++++++++++++ (PREVIEW) THIS WILL CAUSE A LOCKUP!");
458 client->printRefs();
459 }
460#endif
461}
462
463// take a picture - image is returned in callback
464status_t CameraService::Client::autoFocus()
465{
466 LOGV("autoFocus");
467
468 Mutex::Autolock lock(mLock);
The Android Open Source Project27629322009-01-09 17:51:23 -0800469 status_t result = checkPid();
470 if (result != NO_ERROR) return result;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700471
472 if (mHardware == 0) {
473 LOGE("mHardware is NULL, returning.");
474 return INVALID_OPERATION;
475 }
476
477 return mHardware->autoFocus(autoFocusCallback,
478 mCameraService.get());
479}
480
481// take a picture - image is returned in callback
482status_t CameraService::Client::takePicture()
483{
484 LOGD("takePicture");
485
486 Mutex::Autolock lock(mLock);
The Android Open Source Project27629322009-01-09 17:51:23 -0800487 status_t result = checkPid();
488 if (result != NO_ERROR) return result;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700489
490 if (mHardware == 0) {
491 LOGE("mHardware is NULL, returning.");
492 return INVALID_OPERATION;
493 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800494
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700495 if (mSurface != NULL)
496 mSurface->unregisterBuffers();
497
498 return mHardware->takePicture(shutterCallback,
499 yuvPictureCallback,
500 jpegPictureCallback,
501 mCameraService.get());
502}
503
504// picture callback - snapshot taken
505void CameraService::Client::shutterCallback(void *user)
506{
507 sp<Client> client = getClientFromCookie(user);
508 if (client == 0) {
509 return;
510 }
511
512 client->postShutter();
513}
514
515// picture callback - raw image ready
516void CameraService::Client::yuvPictureCallback(const sp<IMemory>& mem,
517 void *user)
518{
519 sp<Client> client = getClientFromCookie(user);
520 if (client == 0) {
521 return;
522 }
523 if (mem == NULL) {
524 client->postRaw(NULL);
525 client->postError(UNKNOWN_ERROR);
526 return;
527 }
528
529 ssize_t offset;
530 size_t size;
531 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
532#if DEBUG_HEAP_LEAKS && 0 // debugging
533 gWeakHeap = heap; // debugging
534#endif
535
536 //LOGV("yuvPictureCallback(%d, %d, %p)", offset, size, user);
537#if DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE // for testing pursposes only
538 dump_to_file("/data/photo.yuv",
539 (uint8_t *)heap->base() + offset, size);
540#endif
541
542 // Put the YUV version of the snapshot in the preview display.
543 int w, h;
544 CameraParameters params(client->mHardware->getParameters());
545 params.getPictureSize(&w, &h);
546
547// Mutex::Autolock clientLock(client->mLock);
548 if (client->mSurface != 0) {
549 client->mSurface->unregisterBuffers();
550 client->mSurface->registerBuffers(w,h,w,h,
551 PIXEL_FORMAT_YCbCr_420_SP, heap);
552 client->mSurface->postBuffer(offset);
553 }
554
555 client->postRaw(mem);
556
557#if DEBUG_CLIENT_REFERENCES
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800558 //**** 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 -0700559 // which is bad--print all refcounts.
560 if (client->getStrongCount() == 1) {
561 LOGE("++++++++++++++++ (RAW) THIS WILL CAUSE A LOCKUP!");
562 client->printRefs();
563 }
564#endif
565}
566
567// picture callback - jpeg ready
568void CameraService::Client::jpegPictureCallback(const sp<IMemory>& mem, void *user)
569{
570 sp<Client> client = getClientFromCookie(user);
571 if (client == 0) {
572 return;
573 }
574 if (mem == NULL) {
575 client->postJpeg(NULL);
576 client->postError(UNKNOWN_ERROR);
577 return;
578 }
579
580 /** We absolutely CANNOT call into user code with a lock held **/
581
582#if DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE // for testing pursposes only
583 {
584 ssize_t offset;
585 size_t size;
586 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
587 dump_to_file("/data/photo.jpg",
588 (uint8_t *)heap->base() + offset, size);
589 }
590#endif
591
592 client->postJpeg(mem);
593
594#if DEBUG_CLIENT_REFERENCES
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800595 //**** 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 -0700596 // which is bad--print all refcounts.
597 if (client->getStrongCount() == 1) {
598 LOGE("++++++++++++++++ (JPEG) THIS WILL CAUSE A LOCKUP!");
599 client->printRefs();
600 }
601#endif
602}
603
604void CameraService::Client::autoFocusCallback(bool focused, void *user)
605{
606 LOGV("autoFocusCallback");
607
608 sp<Client> client = getClientFromCookie(user);
609 if (client == 0) {
610 return;
611 }
612
613 client->postAutoFocus(focused);
614
615#if DEBUG_CLIENT_REFERENCES
616 if (client->getStrongCount() == 1) {
617 LOGE("++++++++++++++++ (AUTOFOCUS) THIS WILL CAUSE A LOCKUP!");
618 client->printRefs();
619 }
620#endif
621}
622
623// set preview/capture parameters - key/value pairs
624status_t CameraService::Client::setParameters(const String8& params)
625{
626 LOGD("setParameters(%s)", params.string());
627
628 Mutex::Autolock lock(mLock);
The Android Open Source Project27629322009-01-09 17:51:23 -0800629 status_t result = checkPid();
630 if (result != NO_ERROR) return result;
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700631
632 if (mHardware == 0) {
633 LOGE("mHardware is NULL, returning.");
634 return INVALID_OPERATION;
635 }
636
637 CameraParameters p(params);
638 mHardware->setParameters(p);
639 return NO_ERROR;
640}
641
642// get preview/capture parameters - key/value pairs
643String8 CameraService::Client::getParameters() const
644{
645 LOGD("getParameters");
646
647 Mutex::Autolock lock(mLock);
648
649 if (mHardware == 0) {
650 LOGE("mHardware is NULL, returning.");
651 return String8();
652 }
653
654 return mHardware->getParameters().flatten();
655}
656
657void CameraService::Client::postAutoFocus(bool focused)
658{
659 LOGV("postAutoFocus");
660 mCameraClient->autoFocusCallback(focused);
661}
662
663void CameraService::Client::postShutter()
664{
665 mCameraClient->shutterCallback();
666}
667
668void CameraService::Client::postRaw(const sp<IMemory>& mem)
669{
670 LOGD("postRaw");
671 mCameraClient->rawCallback(mem);
672}
673
674void CameraService::Client::postJpeg(const sp<IMemory>& mem)
675{
676 LOGD("postJpeg");
677 mCameraClient->jpegCallback(mem);
678}
679
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800680void CameraService::Client::copyFrameAndPostCopiedFrame(sp<IMemoryHeap> heap, size_t offset, size_t size)
681{
682 LOGV("copyFrameAndPostCopiedFrame");
683 // It is necessary to copy out of pmem before sending this to
684 // the callback. For efficiency, reuse the same MemoryHeapBase
685 // provided it's big enough. Don't allocate the memory or
686 // perform the copy if there's no callback.
687 if (mPreviewBuffer == 0) {
688 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
689 } else if (size > mPreviewBuffer->virtualSize()) {
690 mPreviewBuffer.clear();
691 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
692 if (mPreviewBuffer == 0) {
693 LOGE("failed to allocate space for preview buffer");
694 return;
695 }
696 }
697 memcpy(mPreviewBuffer->base(),
698 (uint8_t *)heap->base() + offset, size);
699
700 sp<MemoryBase> frame = new MemoryBase(mPreviewBuffer, 0, size);
701 if (frame == 0) {
702 LOGE("failed to allocate space for frame callback");
703 return;
704 }
705 mCameraClient->frameCallback(frame);
706}
707
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700708void CameraService::Client::postFrame(const sp<IMemory>& mem)
709{
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800710 LOGV("postFrame");
711 if (mem == 0) {
712 LOGW("mem is a null pointer");
713 return;
714 }
715
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700716 ssize_t offset;
717 size_t size;
718 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700719 {
720 Mutex::Autolock surfaceLock(mSurfaceLock);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800721 if (mSurface != NULL) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700722 mSurface->postBuffer(offset);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700723 }
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700724 }
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800725
726 // Is the callback enabled or not?
727 if (!(mFrameCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
728 // If the enable bit is off, the copy-out and one-shot bits are ignored
729 LOGV("frame callback is diabled");
730 return;
731 }
732
733 // Is the received frame copied out or not?
734 if (mFrameCallbackFlag & FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
735 LOGV("frame is copied out");
736 copyFrameAndPostCopiedFrame(heap, offset, size);
737 } else {
738 LOGV("frame is directly sent out without copying");
739 mCameraClient->frameCallback(mem);
740 }
741
742 // Is this is one-shot only?
743 if (mFrameCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) {
744 LOGV("One-shot only, thus clear the bits and disable frame callback");
745 mFrameCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
746 FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
747 FRAME_CALLBACK_FLAG_ENABLE_MASK);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700748 }
749}
750
751void CameraService::Client::postError(status_t error) {
752 mCameraClient->errorCallback(error);
753}
754
755status_t CameraService::dump(int fd, const Vector<String16>& args)
756{
757 const size_t SIZE = 256;
758 char buffer[SIZE];
759 String8 result;
760 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
761 snprintf(buffer, SIZE, "Permission Denial: "
762 "can't dump CameraService from pid=%d, uid=%d\n",
763 IPCThreadState::self()->getCallingPid(),
764 IPCThreadState::self()->getCallingUid());
765 result.append(buffer);
766 write(fd, result.string(), result.size());
767 } else {
768 AutoMutex lock(&mLock);
769 if (mClient != 0) {
770 sp<Client> currentClient = mClient.promote();
771 currentClient->mHardware->dump(fd, args);
772 } else {
773 result.append("No camera client yet.\n");
774 write(fd, result.string(), result.size());
775 }
776 }
777 return NO_ERROR;
778}
779
780
781#if DEBUG_HEAP_LEAKS
782
783#define CHECK_INTERFACE(interface, data, reply) \
784 do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
785 LOGW("Call incorrectly routed to " #interface); \
786 return PERMISSION_DENIED; \
787 } } while (0)
788
789status_t CameraService::onTransact(
790 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
791{
792 // permission checks...
793 switch (code) {
794 case BnCameraService::CONNECT:
795 IPCThreadState* ipc = IPCThreadState::self();
796 const int pid = ipc->getCallingPid();
797 const int self_pid = getpid();
798 if (pid != self_pid) {
799 // we're called from a different process, do the real check
800 if (!checkCallingPermission(
801 String16("android.permission.CAMERA")))
802 {
803 const int uid = ipc->getCallingUid();
804 LOGE("Permission Denial: "
805 "can't use the camera pid=%d, uid=%d", pid, uid);
806 return PERMISSION_DENIED;
807 }
808 }
809 break;
810 }
811
812 status_t err = BnCameraService::onTransact(code, data, reply, flags);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800813
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700814 LOGD("+++ onTransact err %d code %d", err, code);
815
816 if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
817 // the 'service' command interrogates this binder for its name, and then supplies it
818 // even for the debugging commands. that means we need to check for it here, using
819 // ISurfaceComposer (since we delegated the INTERFACE_TRANSACTION handling to
820 // BnSurfaceComposer before falling through to this code).
821
822 LOGD("+++ onTransact code %d", code);
823
824 CHECK_INTERFACE(ICameraService, data, reply);
825
826 switch(code) {
827 case 1000:
828 {
829 if (gWeakHeap != 0) {
830 sp<IMemoryHeap> h = gWeakHeap.promote();
831 IMemoryHeap *p = gWeakHeap.unsafe_get();
832 LOGD("CHECKING WEAK REFERENCE %p (%p)", h.get(), p);
833 if (h != 0)
834 h->printRefs();
835 bool attempt_to_delete = data.readInt32() == 1;
836 if (attempt_to_delete) {
837 // NOT SAFE!
838 LOGD("DELETING WEAK REFERENCE %p (%p)", h.get(), p);
839 if (p) delete p;
840 }
841 return NO_ERROR;
842 }
843 }
844 break;
845 default:
846 break;
847 }
848 }
849 return err;
850}
851
852#endif // DEBUG_HEAP_LEAKS
853
854}; // namespace android
855
856