blob: 980ce78c22deea932561618d9e481af17d0f1f91 [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
Mathias Agopian07952722009-05-19 19:08:10 -070023#include <binder/IServiceManager.h>
24#include <binder/IPCThreadState.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025#include <utils/String16.h>
26#include <utils/Errors.h>
Mathias Agopian07952722009-05-19 19:08:10 -070027#include <binder/MemoryBase.h>
28#include <binder/MemoryHeapBase.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029#include <ui/ICameraService.h>
30
Jason Samsb18b6912009-03-24 20:21:36 -070031#include <media/mediaplayer.h>
32#include <media/AudioSystem.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033#include "CameraService.h"
34
Eric Laurenta7f1e5c2009-03-27 16:27:16 -070035#include <cutils/properties.h>
36
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037namespace android {
38
39extern "C" {
40#include <stdio.h>
41#include <sys/types.h>
42#include <sys/stat.h>
43#include <fcntl.h>
44#include <pthread.h>
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +080045#include <signal.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046}
47
48// When you enable this, as well as DEBUG_REFS=1 and
49// DEBUG_REFS_ENABLED_BY_DEFAULT=0 in libutils/RefBase.cpp, this will track all
50// references to the CameraService::Client in order to catch the case where the
51// client is being destroyed while a callback from the CameraHardwareInterface
52// is outstanding. This is a serious bug because if we make another call into
53// CameraHardwreInterface that itself triggers a callback, we will deadlock.
54
55#define DEBUG_CLIENT_REFERENCES 0
56
57#define PICTURE_TIMEOUT seconds(5)
58
59#define DEBUG_DUMP_PREVIEW_FRAME_TO_FILE 0 /* n-th frame to write */
60#define DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE 0
61#define DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE 0
62
63#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
64static int debug_frame_cnt;
65#endif
66
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +080067static int getCallingPid() {
68 return IPCThreadState::self()->getCallingPid();
69}
70
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071// ----------------------------------------------------------------------------
72
73void CameraService::instantiate() {
74 defaultServiceManager()->addService(
75 String16("media.camera"), new CameraService());
76}
77
78// ----------------------------------------------------------------------------
79
80CameraService::CameraService() :
81 BnCameraService()
82{
83 LOGI("CameraService started: pid=%d", getpid());
84}
85
86CameraService::~CameraService()
87{
88 if (mClient != 0) {
89 LOGE("mClient was still connected in destructor!");
90 }
91}
92
93sp<ICamera> CameraService::connect(const sp<ICameraClient>& cameraClient)
94{
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +080095 int callingPid = getCallingPid();
96 LOGD("CameraService::connect E (pid %d, client %p)", callingPid,
97 cameraClient->asBinder().get());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098
99 Mutex::Autolock lock(mLock);
100 sp<Client> client;
101 if (mClient != 0) {
102 sp<Client> currentClient = mClient.promote();
103 if (currentClient != 0) {
104 sp<ICameraClient> currentCameraClient(currentClient->getCameraClient());
105 if (cameraClient->asBinder() == currentCameraClient->asBinder()) {
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800106 // This is the same client reconnecting...
107 LOGD("CameraService::connect X (pid %d, same client %p) is reconnecting...",
108 callingPid, cameraClient->asBinder().get());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109 return currentClient;
110 } else {
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800111 // It's another client... reject it
112 LOGD("CameraService::connect X (pid %d, new client %p) rejected. "
113 "(old pid %d, old client %p)",
114 callingPid, cameraClient->asBinder().get(),
115 currentClient->mClientPid, currentCameraClient->asBinder().get());
116 if (kill(currentClient->mClientPid, 0) == ESRCH) {
117 LOGD("The old client is dead!");
118 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800119 return client;
120 }
121 } else {
122 // can't promote, the previous client has died...
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800123 LOGD("New client (pid %d) connecting, old reference was dangling...",
124 callingPid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800125 mClient.clear();
126 }
127 }
128
129 // create a new Client object
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800130 client = new Client(this, cameraClient, callingPid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800131 mClient = client;
132#if DEBUG_CLIENT_REFERENCES
133 // Enable tracking for this object, and track increments and decrements of
134 // the refcount.
135 client->trackMe(true, true);
136#endif
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800137 LOGD("CameraService::connect X");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800138 return client;
139}
140
141void CameraService::removeClient(const sp<ICameraClient>& cameraClient)
142{
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800143 int callingPid = getCallingPid();
144
145 // Declare this outside the lock to make absolutely sure the
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146 // destructor won't be called with the lock held.
147 sp<Client> client;
148
149 Mutex::Autolock lock(mLock);
150
151 if (mClient == 0) {
152 // This happens when we have already disconnected.
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800153 LOGD("removeClient (pid %d): already disconnected", callingPid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800154 return;
155 }
156
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800157 // Promote mClient. It can fail if we are called from this path:
158 // Client::~Client() -> disconnect() -> removeClient().
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800159 client = mClient.promote();
160 if (client == 0) {
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800161 LOGD("removeClient (pid %d): no more strong reference", callingPid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162 mClient.clear();
163 return;
164 }
165
166 if (cameraClient->asBinder() != client->getCameraClient()->asBinder()) {
167 // ugh! that's not our client!!
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800168 LOGW("removeClient (pid %d): mClient doesn't match!", callingPid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800169 } else {
170 // okay, good, forget about mClient
171 mClient.clear();
172 }
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800173
174 LOGD("removeClient (pid %d) done", callingPid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800175}
176
Jason Samsb18b6912009-03-24 20:21:36 -0700177static sp<MediaPlayer> newMediaPlayer(const char *file)
178{
179 sp<MediaPlayer> mp = new MediaPlayer();
180 if (mp->setDataSource(file) == NO_ERROR) {
Eric Laurenta7f1e5c2009-03-27 16:27:16 -0700181 char value[PROPERTY_VALUE_MAX];
182 property_get("ro.camera.sound.forced", value, "0");
183 if (atoi(value)) {
184 mp->setAudioStreamType(AudioSystem::ENFORCED_AUDIBLE);
185 } else {
186 mp->setAudioStreamType(AudioSystem::SYSTEM);
187 }
Jason Samsb18b6912009-03-24 20:21:36 -0700188 mp->prepare();
189 } else {
190 mp.clear();
191 LOGE("Failed to load CameraService sounds.");
192 }
193 return mp;
194}
195
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800196CameraService::Client::Client(const sp<CameraService>& cameraService,
197 const sp<ICameraClient>& cameraClient, pid_t clientPid)
198{
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800199 int callingPid = getCallingPid();
200 LOGD("Client::Client E (pid %d)", callingPid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800201 mCameraService = cameraService;
202 mCameraClient = cameraClient;
203 mClientPid = clientPid;
204 mHardware = openCameraHardware();
205 mUseOverlay = mHardware->useOverlay();
206
Jason Samsb18b6912009-03-24 20:21:36 -0700207 mMediaPlayerClick = newMediaPlayer("/system/media/audio/ui/camera_click.ogg");
208 mMediaPlayerBeep = newMediaPlayer("/system/media/audio/ui/VideoRecord.ogg");
209
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800210 // Callback is disabled by default
211 mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800212 LOGD("Client::Client X (pid %d)", callingPid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800213}
214
215status_t CameraService::Client::checkPid()
216{
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800217 int callingPid = getCallingPid();
218 if (mClientPid == callingPid) return NO_ERROR;
219 LOGW("Attempt to use locked camera (client %p) from different process "
220 " (old pid %d, new pid %d)",
221 getCameraClient()->asBinder().get(), mClientPid, callingPid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800222 return -EBUSY;
223}
224
225status_t CameraService::Client::lock()
226{
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800227 int callingPid = getCallingPid();
228 LOGD("lock from pid %d (mClientPid %d)", callingPid, mClientPid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229 Mutex::Autolock _l(mLock);
230 // lock camera to this client if the the camera is unlocked
231 if (mClientPid == 0) {
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800232 mClientPid = callingPid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800233 return NO_ERROR;
234 }
235 // returns NO_ERROR if the client already owns the camera, -EBUSY otherwise
236 return checkPid();
237}
238
239status_t CameraService::Client::unlock()
240{
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800241 int callingPid = getCallingPid();
242 LOGD("unlock from pid %d (mClientPid %d)", callingPid, mClientPid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800243 Mutex::Autolock _l(mLock);
244 // allow anyone to use camera
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800245 status_t result = checkPid();
James Donge251f322009-04-20 19:35:28 -0700246 if (result == NO_ERROR) {
247 mClientPid = 0;
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800248 LOGD("clear mCameraClient (pid %d)", callingPid);
James Donge251f322009-04-20 19:35:28 -0700249 // we need to remove the reference so that when app goes
250 // away, the reference count goes to 0.
251 mCameraClient.clear();
252 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800253 return result;
254}
255
256status_t CameraService::Client::connect(const sp<ICameraClient>& client)
257{
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800258 int callingPid = getCallingPid();
259
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260 // connect a new process to the camera
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800261 LOGD("Client::connect E (pid %d, client %p)", callingPid, client->asBinder().get());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800262
263 // I hate this hack, but things get really ugly when the media recorder
264 // service is handing back the camera to the app. The ICameraClient
265 // destructor will be called during the same IPC, making it look like
266 // the remote client is trying to disconnect. This hack temporarily
267 // sets the mClientPid to an invalid pid to prevent the hardware from
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800268 // being torn down.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800269 {
270
271 // hold a reference to the old client or we will deadlock if the client is
272 // in the same process and we hold the lock when we remove the reference
273 sp<ICameraClient> oldClient;
274 {
275 Mutex::Autolock _l(mLock);
Chih-Chung Changc8b24082009-06-09 13:56:44 +0800276 if (mClientPid != 0 && checkPid() != NO_ERROR) {
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800277 LOGW("Tried to connect to locked camera (old pid %d, new pid %d)",
278 mClientPid, callingPid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279 return -EBUSY;
280 }
281 oldClient = mCameraClient;
282
283 // did the client actually change?
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800284 if (client->asBinder() == mCameraClient->asBinder()) {
285 LOGD("Connect to the same client");
286 return NO_ERROR;
287 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288
289 mCameraClient = client;
290 mClientPid = -1;
291 mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800292 LOGD("Connect to the new client (pid %d, client %p)",
293 callingPid, mCameraClient->asBinder().get());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800294 }
295
296 }
297 // the old client destructor is called when oldClient goes out of scope
298 // now we set the new PID to lock the interface again
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800299 mClientPid = callingPid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800300
301 return NO_ERROR;
302}
303
304#if HAVE_ANDROID_OS
305static void *unregister_surface(void *arg)
306{
307 ISurface *surface = (ISurface *)arg;
308 surface->unregisterBuffers();
309 IPCThreadState::self()->flushCommands();
310 return NULL;
311}
312#endif
313
314CameraService::Client::~Client()
315{
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800316 int callingPid = getCallingPid();
317
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800318 // tear down client
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800319 LOGD("Client::~Client E (pid %d, client %p)",
320 callingPid, getCameraClient()->asBinder().get());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800321 if (mSurface != 0 && !mUseOverlay) {
322#if HAVE_ANDROID_OS
323 pthread_t thr;
324 // We unregister the buffers in a different thread because binder does
325 // not let us make sychronous transactions in a binder destructor (that
326 // is, upon our reaching a refcount of zero.)
327 pthread_create(&thr, NULL,
328 unregister_surface,
329 mSurface.get());
330 pthread_join(thr, NULL);
331#else
332 mSurface->unregisterBuffers();
333#endif
334 }
335
Jason Sams403914a2009-03-24 20:36:57 -0700336 if (mMediaPlayerBeep.get() != NULL) {
337 mMediaPlayerBeep->disconnect();
338 mMediaPlayerBeep.clear();
339 }
340 if (mMediaPlayerClick.get() != NULL) {
341 mMediaPlayerClick->disconnect();
342 mMediaPlayerClick.clear();
343 }
Jason Samsb18b6912009-03-24 20:21:36 -0700344
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800345 // make sure we tear down the hardware
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800346 mClientPid = callingPid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800347 disconnect();
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800348 LOGD("Client::~Client X (pid %d)", mClientPid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800349}
350
351void CameraService::Client::disconnect()
352{
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800353 int callingPid = getCallingPid();
354
355 LOGD("Client::disconnect() E (pid %d client %p)",
356 callingPid, getCameraClient()->asBinder().get());
357
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800358 Mutex::Autolock lock(mLock);
359 if (mClientPid <= 0) {
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800360 LOGD("camera is unlocked (mClientPid = %d), don't tear down hardware", mClientPid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800361 return;
362 }
363 if (checkPid() != NO_ERROR) {
Chih-Chung Chang4b4900b2009-06-16 17:15:04 +0800364 LOGD("Different client - don't disconnect");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800365 return;
366 }
367
368 mCameraService->removeClient(mCameraClient);
369 if (mHardware != 0) {
Chih-Chung Chang4b4900b2009-06-16 17:15:04 +0800370 LOGD("hardware teardown");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800371 // Before destroying mHardware, we must make sure it's in the
372 // idle state.
373 mHardware->stopPreview();
374 // Cancel all picture callbacks.
375 mHardware->cancelPicture(true, true, true);
376 // Release the hardware resources.
377 mHardware->release();
378 }
379 mHardware.clear();
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800380 LOGD("Client::disconnect() X (pid %d)", callingPid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800381}
382
383// pass the buffered ISurface to the camera service
384status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface)
385{
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800386 LOGD("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800387 Mutex::Autolock lock(mLock);
388 status_t result = checkPid();
389 if (result != NO_ERROR) return result;
390 Mutex::Autolock surfaceLock(mSurfaceLock);
391 // asBinder() is safe on NULL (returns NULL)
392 if (surface->asBinder() != mSurface->asBinder()) {
393 if (mSurface != 0 && !mUseOverlay) {
394 LOGD("clearing old preview surface %p", mSurface.get());
395 mSurface->unregisterBuffers();
396 }
397 mSurface = surface;
398 }
399 return NO_ERROR;
400}
401
402// set the preview callback flag to affect how the received frames from
403// preview are handled.
404void CameraService::Client::setPreviewCallbackFlag(int callback_flag)
405{
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800406 LOGV("setPreviewCallbackFlag (pid %d)", getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800407 Mutex::Autolock lock(mLock);
408 if (checkPid() != NO_ERROR) return;
409 mPreviewCallbackFlag = callback_flag;
410}
411
412// start preview mode, must call setPreviewDisplay first
413status_t CameraService::Client::startCameraMode(camera_mode mode)
414{
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800415 int callingPid = getCallingPid();
416
417 LOGD("startCameraMode(%d) (pid %d)", mode, callingPid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800418
419 /* we cannot call into mHardware with mLock held because
420 * mHardware has callbacks onto us which acquire this lock
421 */
422
423 Mutex::Autolock lock(mLock);
424 status_t result = checkPid();
425 if (result != NO_ERROR) return result;
426
427 if (mHardware == 0) {
428 LOGE("mHardware is NULL, returning.");
429 return INVALID_OPERATION;
430 }
431
432 if (mSurface == 0) {
433 LOGE("setPreviewDisplay must be called before startCameraMode!");
434 return INVALID_OPERATION;
435 }
436
437 switch(mode) {
438 case CAMERA_RECORDING_MODE:
439 return startRecordingMode();
440
441 default: // CAMERA_PREVIEW_MODE
442 return startPreviewMode();
443 }
444}
445
446status_t CameraService::Client::startRecordingMode()
447{
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800448 LOGD("startRecordingMode (pid %d)", getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800449
450 status_t ret = UNKNOWN_ERROR;
451
452 // if preview has not been started, start preview first
453 if (!mHardware->previewEnabled()) {
454 ret = startPreviewMode();
455 if (ret != NO_ERROR) {
456 return ret;
457 }
458 }
459
460 // if recording has been enabled, nothing needs to be done
461 if (mHardware->recordingEnabled()) {
462 return NO_ERROR;
463 }
464
465 // start recording mode
466 ret = mHardware->startRecording(recordingCallback,
467 mCameraService.get());
468 if (ret != NO_ERROR) {
469 LOGE("mHardware->startRecording() failed with status %d", ret);
470 }
471 return ret;
472}
473
474status_t CameraService::Client::startPreviewMode()
475{
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800476 LOGD("startPreviewMode (pid %d)", getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800477
478 // if preview has been enabled, nothing needs to be done
479 if (mHardware->previewEnabled()) {
480 return NO_ERROR;
481 }
482
483 // start preview mode
484#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
485 debug_frame_cnt = 0;
486#endif
487 status_t ret = UNKNOWN_ERROR;
488 int w, h;
489 CameraParameters params(mHardware->getParameters());
490 params.getPreviewSize(&w, &h);
491
492 if (mUseOverlay) {
493 const char *format = params.getPreviewFormat();
494 int fmt;
495 LOGD("Use Overlays");
496 if (!strcmp(format, "yuv422i"))
497 fmt = OVERLAY_FORMAT_YCbCr_422_I;
498 else if (!strcmp(format, "rgb565"))
499 fmt = OVERLAY_FORMAT_RGB_565;
500 else {
501 LOGE("Invalid preview format for overlays");
502 return -EINVAL;
503 }
504 sp<OverlayRef> ref = mSurface->createOverlay(w, h, fmt);
505 ret = mHardware->setOverlay(new Overlay(ref));
506 if (ret != NO_ERROR) {
507 LOGE("mHardware->setOverlay() failed with status %d\n", ret);
508 return ret;
509 }
510 ret = mHardware->startPreview(NULL, mCameraService.get());
511 if (ret != NO_ERROR)
512 LOGE("mHardware->startPreview() failed with status %d\n", ret);
513
514 } else {
515 ret = mHardware->startPreview(previewCallback,
516 mCameraService.get());
517 if (ret == NO_ERROR) {
518
519 mSurface->unregisterBuffers();
520
521 uint32_t transform = 0;
522 if (params.getOrientation() ==
523 CameraParameters::CAMERA_ORIENTATION_PORTRAIT) {
524 LOGV("portrait mode");
525 transform = ISurface::BufferHeap::ROT_90;
526 }
527 ISurface::BufferHeap buffers(w, h, w, h,
528 PIXEL_FORMAT_YCbCr_420_SP,
529 transform,
530 0,
531 mHardware->getPreviewHeap());
532
533 mSurface->registerBuffers(buffers);
534 } else {
535 LOGE("mHardware->startPreview() failed with status %d", ret);
536 }
537 }
538 return ret;
539}
540
541status_t CameraService::Client::startPreview()
542{
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800543 LOGD("startPreview (pid %d)", getCallingPid());
544
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800545 return startCameraMode(CAMERA_PREVIEW_MODE);
546}
547
548status_t CameraService::Client::startRecording()
549{
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800550 LOGD("startRecording (pid %d)", getCallingPid());
551
Jason Samsb18b6912009-03-24 20:21:36 -0700552 if (mMediaPlayerBeep.get() != NULL) {
Andreas Hubere25b51b2009-03-24 20:47:19 -0700553 mMediaPlayerBeep->seekTo(0);
Jason Samsb18b6912009-03-24 20:21:36 -0700554 mMediaPlayerBeep->start();
555 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800556 return startCameraMode(CAMERA_RECORDING_MODE);
557}
558
559// stop preview mode
560void CameraService::Client::stopPreview()
561{
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800562 LOGD("stopPreview (pid %d)", getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800563
564 Mutex::Autolock lock(mLock);
565 if (checkPid() != NO_ERROR) return;
566
567 if (mHardware == 0) {
568 LOGE("mHardware is NULL, returning.");
569 return;
570 }
571
572 mHardware->stopPreview();
573 LOGD("stopPreview(), hardware stopped OK");
574
575 if (mSurface != 0 && !mUseOverlay) {
576 mSurface->unregisterBuffers();
577 }
578 mPreviewBuffer.clear();
579}
580
581// stop recording mode
582void CameraService::Client::stopRecording()
583{
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800584 LOGD("stopRecording (pid %d)", getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800585
586 Mutex::Autolock lock(mLock);
587 if (checkPid() != NO_ERROR) return;
588
589 if (mHardware == 0) {
590 LOGE("mHardware is NULL, returning.");
591 return;
592 }
593
Jason Samsb18b6912009-03-24 20:21:36 -0700594 if (mMediaPlayerBeep.get() != NULL) {
Andreas Hubere25b51b2009-03-24 20:47:19 -0700595 mMediaPlayerBeep->seekTo(0);
Jason Samsb18b6912009-03-24 20:21:36 -0700596 mMediaPlayerBeep->start();
597 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800598 mHardware->stopRecording();
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800599 LOGD("stopRecording(), hardware stopped OK");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800600 mPreviewBuffer.clear();
601}
602
603// release a recording frame
604void CameraService::Client::releaseRecordingFrame(const sp<IMemory>& mem)
605{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800606 Mutex::Autolock lock(mLock);
607 if (checkPid() != NO_ERROR) return;
608
609 if (mHardware == 0) {
610 LOGE("mHardware is NULL, returning.");
611 return;
612 }
613
614 mHardware->releaseRecordingFrame(mem);
615}
616
617bool CameraService::Client::previewEnabled()
618{
619 Mutex::Autolock lock(mLock);
620 if (mHardware == 0) return false;
621 return mHardware->previewEnabled();
622}
623
624bool CameraService::Client::recordingEnabled()
625{
626 Mutex::Autolock lock(mLock);
627 if (mHardware == 0) return false;
628 return mHardware->recordingEnabled();
629}
630
631// Safely retrieves a strong pointer to the client during a hardware callback.
632sp<CameraService::Client> CameraService::Client::getClientFromCookie(void* user)
633{
634 sp<Client> client = 0;
635 CameraService *service = static_cast<CameraService*>(user);
636 if (service != NULL) {
637 Mutex::Autolock ourLock(service->mLock);
638 if (service->mClient != 0) {
639 client = service->mClient.promote();
640 if (client == 0) {
641 LOGE("getClientFromCookie: client appears to have died");
642 service->mClient.clear();
643 }
644 } else {
645 LOGE("getClientFromCookie: got callback but client was NULL");
646 }
647 }
648 return client;
649}
650
651
652#if DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE || \
653 DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE || \
654 DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
655static void dump_to_file(const char *fname,
656 uint8_t *buf, uint32_t size)
657{
658 int nw, cnt = 0;
659 uint32_t written = 0;
660
661 LOGD("opening file [%s]\n", fname);
662 int fd = open(fname, O_RDWR | O_CREAT);
663 if (fd < 0) {
664 LOGE("failed to create file [%s]: %s", fname, strerror(errno));
665 return;
666 }
667
668 LOGD("writing %d bytes to file [%s]\n", size, fname);
669 while (written < size) {
670 nw = ::write(fd,
671 buf + written,
672 size - written);
673 if (nw < 0) {
674 LOGE("failed to write to file [%s]: %s",
675 fname, strerror(errno));
676 break;
677 }
678 written += nw;
679 cnt++;
680 }
681 LOGD("done writing %d bytes to file [%s] in %d passes\n",
682 size, fname, cnt);
683 ::close(fd);
684}
685#endif
686
687// preview callback - frame buffer update
688void CameraService::Client::previewCallback(const sp<IMemory>& mem, void* user)
689{
690 LOGV("previewCallback()");
691 sp<Client> client = getClientFromCookie(user);
692 if (client == 0) {
693 return;
694 }
695
696#if DEBUG_HEAP_LEAKS && 0 // debugging
697 if (gWeakHeap == NULL) {
698 ssize_t offset;
699 size_t size;
700 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
701 if (gWeakHeap != heap) {
702 LOGD("SETTING PREVIEW HEAP");
703 heap->trackMe(true, true);
704 gWeakHeap = heap;
705 }
706 }
707#endif
708
709#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
710 {
711 if (debug_frame_cnt++ == DEBUG_DUMP_PREVIEW_FRAME_TO_FILE) {
712 ssize_t offset;
713 size_t size;
714 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
715 dump_to_file("/data/preview.yuv",
716 (uint8_t *)heap->base() + offset, size);
717 }
718 }
719#endif
720
721 // The strong pointer guarantees the client will exist, but no lock is held.
722 client->postPreviewFrame(mem);
723
724#if DEBUG_CLIENT_REFERENCES
725 //**** if the client's refcount is 1, then we are about to destroy it here,
726 // which is bad--print all refcounts.
727 if (client->getStrongCount() == 1) {
728 LOGE("++++++++++++++++ (PREVIEW) THIS WILL CAUSE A LOCKUP!");
729 client->printRefs();
730 }
731#endif
732}
733
734// recording callback
735void CameraService::Client::recordingCallback(const sp<IMemory>& mem, void* user)
736{
737 LOGV("recordingCallback");
738 sp<Client> client = getClientFromCookie(user);
739 if (client == 0) {
740 return;
741 }
742 // The strong pointer guarantees the client will exist, but no lock is held.
743 client->postRecordingFrame(mem);
744}
745
746// take a picture - image is returned in callback
747status_t CameraService::Client::autoFocus()
748{
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800749 LOGD("autoFocus (pid %d)", getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800750
751 Mutex::Autolock lock(mLock);
752 status_t result = checkPid();
753 if (result != NO_ERROR) return result;
754
755 if (mHardware == 0) {
756 LOGE("mHardware is NULL, returning.");
757 return INVALID_OPERATION;
758 }
759
760 return mHardware->autoFocus(autoFocusCallback,
761 mCameraService.get());
762}
763
764// take a picture - image is returned in callback
765status_t CameraService::Client::takePicture()
766{
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800767 LOGD("takePicture (pid %d)", getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800768
769 Mutex::Autolock lock(mLock);
770 status_t result = checkPid();
771 if (result != NO_ERROR) return result;
772
773 if (mHardware == 0) {
774 LOGE("mHardware is NULL, returning.");
775 return INVALID_OPERATION;
776 }
777
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800778 return mHardware->takePicture(shutterCallback,
779 yuvPictureCallback,
780 jpegPictureCallback,
781 mCameraService.get());
782}
783
784// picture callback - snapshot taken
785void CameraService::Client::shutterCallback(void *user)
786{
787 sp<Client> client = getClientFromCookie(user);
788 if (client == 0) {
789 return;
790 }
791
Wu-cheng Lia9f95fb2009-03-24 20:39:09 -0700792 // Play shutter sound.
793 if (client->mMediaPlayerClick.get() != NULL) {
Andreas Hubere25b51b2009-03-24 20:47:19 -0700794 client->mMediaPlayerClick->seekTo(0);
Wu-cheng Lia9f95fb2009-03-24 20:39:09 -0700795 client->mMediaPlayerClick->start();
796 }
797
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800798 // Screen goes black after the buffer is unregistered.
799 if (client->mSurface != 0 && !client->mUseOverlay) {
800 client->mSurface->unregisterBuffers();
801 }
802
803 client->postShutter();
804
805 // It takes some time before yuvPicture callback to be called.
806 // Register the buffer for raw image here to reduce latency.
807 if (client->mSurface != 0 && !client->mUseOverlay) {
808 int w, h;
809 CameraParameters params(client->mHardware->getParameters());
810 params.getPictureSize(&w, &h);
811 uint32_t transform = 0;
812 if (params.getOrientation() == CameraParameters::CAMERA_ORIENTATION_PORTRAIT) {
813 LOGV("portrait mode");
814 transform = ISurface::BufferHeap::ROT_90;
815 }
816 ISurface::BufferHeap buffers(w, h, w, h,
817 PIXEL_FORMAT_YCbCr_420_SP, transform, 0, client->mHardware->getRawHeap());
818
819 client->mSurface->registerBuffers(buffers);
820 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800821}
822
823// picture callback - raw image ready
824void CameraService::Client::yuvPictureCallback(const sp<IMemory>& mem,
825 void *user)
826{
827 sp<Client> client = getClientFromCookie(user);
828 if (client == 0) {
829 return;
830 }
831 if (mem == NULL) {
832 client->postRaw(NULL);
833 client->postError(UNKNOWN_ERROR);
834 return;
835 }
836
837 ssize_t offset;
838 size_t size;
839 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
840#if DEBUG_HEAP_LEAKS && 0 // debugging
841 gWeakHeap = heap; // debugging
842#endif
843
844 //LOGV("yuvPictureCallback(%d, %d, %p)", offset, size, user);
845#if DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE // for testing pursposes only
846 dump_to_file("/data/photo.yuv",
847 (uint8_t *)heap->base() + offset, size);
848#endif
849
850 // Put the YUV version of the snapshot in the preview display.
851 if (client->mSurface != 0 && !client->mUseOverlay) {
852 client->mSurface->postBuffer(offset);
853 }
854
855 client->postRaw(mem);
856
857#if DEBUG_CLIENT_REFERENCES
858 //**** if the client's refcount is 1, then we are about to destroy it here,
859 // which is bad--print all refcounts.
860 if (client->getStrongCount() == 1) {
861 LOGE("++++++++++++++++ (RAW) THIS WILL CAUSE A LOCKUP!");
862 client->printRefs();
863 }
864#endif
865}
866
867// picture callback - jpeg ready
868void CameraService::Client::jpegPictureCallback(const sp<IMemory>& mem, void *user)
869{
870 sp<Client> client = getClientFromCookie(user);
871 if (client == 0) {
872 return;
873 }
874 if (mem == NULL) {
875 client->postJpeg(NULL);
876 client->postError(UNKNOWN_ERROR);
877 return;
878 }
879
880 /** We absolutely CANNOT call into user code with a lock held **/
881
882#if DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE // for testing pursposes only
883 {
884 ssize_t offset;
885 size_t size;
886 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
887 dump_to_file("/data/photo.jpg",
888 (uint8_t *)heap->base() + offset, size);
889 }
890#endif
891
892 client->postJpeg(mem);
893
894#if DEBUG_CLIENT_REFERENCES
895 //**** if the client's refcount is 1, then we are about to destroy it here,
896 // which is bad--print all refcounts.
897 if (client->getStrongCount() == 1) {
898 LOGE("++++++++++++++++ (JPEG) THIS WILL CAUSE A LOCKUP!");
899 client->printRefs();
900 }
901#endif
902}
903
904void CameraService::Client::autoFocusCallback(bool focused, void *user)
905{
906 LOGV("autoFocusCallback");
907
908 sp<Client> client = getClientFromCookie(user);
909 if (client == 0) {
910 return;
911 }
912
913 client->postAutoFocus(focused);
914
915#if DEBUG_CLIENT_REFERENCES
916 if (client->getStrongCount() == 1) {
917 LOGE("++++++++++++++++ (AUTOFOCUS) THIS WILL CAUSE A LOCKUP!");
918 client->printRefs();
919 }
920#endif
921}
922
923// set preview/capture parameters - key/value pairs
924status_t CameraService::Client::setParameters(const String8& params)
925{
926 LOGD("setParameters(%s)", params.string());
927
928 Mutex::Autolock lock(mLock);
929 status_t result = checkPid();
930 if (result != NO_ERROR) return result;
931
932 if (mHardware == 0) {
933 LOGE("mHardware is NULL, returning.");
934 return INVALID_OPERATION;
935 }
936
937 CameraParameters p(params);
938 mHardware->setParameters(p);
939 return NO_ERROR;
940}
941
942// get preview/capture parameters - key/value pairs
943String8 CameraService::Client::getParameters() const
944{
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800945 Mutex::Autolock lock(mLock);
946
947 if (mHardware == 0) {
948 LOGE("mHardware is NULL, returning.");
949 return String8();
950 }
951
Wu-cheng Liab5b4242009-04-22 16:21:26 +0800952 String8 params(mHardware->getParameters().flatten());
953 LOGD("getParameters(%s)", params.string());
954 return params;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800955}
956
957void CameraService::Client::postAutoFocus(bool focused)
958{
959 LOGV("postAutoFocus");
Dave Sparksd6289b12009-05-07 19:27:32 -0700960 mCameraClient->notifyCallback(CAMERA_MSG_FOCUS, (int32_t)focused, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800961}
962
963void CameraService::Client::postShutter()
964{
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800965 LOGD("postShutter");
Dave Sparksd6289b12009-05-07 19:27:32 -0700966 mCameraClient->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800967}
968
969void CameraService::Client::postRaw(const sp<IMemory>& mem)
970{
971 LOGD("postRaw");
Dave Sparksd6289b12009-05-07 19:27:32 -0700972 mCameraClient->dataCallback(CAMERA_MSG_RAW_IMAGE, mem);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973}
974
975void CameraService::Client::postJpeg(const sp<IMemory>& mem)
976{
977 LOGD("postJpeg");
Dave Sparksd6289b12009-05-07 19:27:32 -0700978 mCameraClient->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800979}
980
981void CameraService::Client::copyFrameAndPostCopiedFrame(sp<IMemoryHeap> heap, size_t offset, size_t size)
982{
983 LOGV("copyFrameAndPostCopiedFrame");
984 // It is necessary to copy out of pmem before sending this to
985 // the callback. For efficiency, reuse the same MemoryHeapBase
986 // provided it's big enough. Don't allocate the memory or
987 // perform the copy if there's no callback.
988 if (mPreviewBuffer == 0) {
989 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
990 } else if (size > mPreviewBuffer->virtualSize()) {
991 mPreviewBuffer.clear();
992 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
993 if (mPreviewBuffer == 0) {
994 LOGE("failed to allocate space for preview buffer");
995 return;
996 }
997 }
998 memcpy(mPreviewBuffer->base(),
999 (uint8_t *)heap->base() + offset, size);
1000
1001 sp<MemoryBase> frame = new MemoryBase(mPreviewBuffer, 0, size);
1002 if (frame == 0) {
1003 LOGE("failed to allocate space for frame callback");
1004 return;
1005 }
Dave Sparksd6289b12009-05-07 19:27:32 -07001006 mCameraClient->dataCallback(CAMERA_MSG_PREVIEW_FRAME, frame);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001007}
1008
1009void CameraService::Client::postRecordingFrame(const sp<IMemory>& frame)
1010{
1011 LOGV("postRecordingFrame");
1012 if (frame == 0) {
1013 LOGW("frame is a null pointer");
1014 return;
1015 }
Dave Sparksd6289b12009-05-07 19:27:32 -07001016 mCameraClient->dataCallback(CAMERA_MSG_VIDEO_FRAME, frame);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001017}
1018
1019void CameraService::Client::postPreviewFrame(const sp<IMemory>& mem)
1020{
1021 LOGV("postPreviewFrame");
1022 if (mem == 0) {
1023 LOGW("mem is a null pointer");
1024 return;
1025 }
1026
1027 ssize_t offset;
1028 size_t size;
1029 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
1030 {
1031 Mutex::Autolock surfaceLock(mSurfaceLock);
1032 if (mSurface != NULL) {
1033 mSurface->postBuffer(offset);
1034 }
1035 }
1036
1037 // Is the callback enabled or not?
1038 if (!(mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
1039 // If the enable bit is off, the copy-out and one-shot bits are ignored
1040 LOGV("frame callback is diabled");
1041 return;
1042 }
1043
1044 // Is the received frame copied out or not?
1045 if (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
1046 LOGV("frame is copied out");
1047 copyFrameAndPostCopiedFrame(heap, offset, size);
1048 } else {
1049 LOGV("frame is directly sent out without copying");
Dave Sparksd6289b12009-05-07 19:27:32 -07001050 mCameraClient->dataCallback(CAMERA_MSG_PREVIEW_FRAME, mem);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001051 }
1052
1053 // Is this is one-shot only?
1054 if (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) {
1055 LOGV("One-shot only, thus clear the bits and disable frame callback");
1056 mPreviewCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
1057 FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
1058 FRAME_CALLBACK_FLAG_ENABLE_MASK);
1059 }
1060}
1061
1062void CameraService::Client::postError(status_t error)
1063{
Dave Sparksd6289b12009-05-07 19:27:32 -07001064 mCameraClient->notifyCallback(CAMERA_MSG_ERROR, error, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001065}
1066
1067status_t CameraService::dump(int fd, const Vector<String16>& args)
1068{
1069 const size_t SIZE = 256;
1070 char buffer[SIZE];
1071 String8 result;
1072 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
1073 snprintf(buffer, SIZE, "Permission Denial: "
1074 "can't dump CameraService from pid=%d, uid=%d\n",
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +08001075 getCallingPid(),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001076 IPCThreadState::self()->getCallingUid());
1077 result.append(buffer);
1078 write(fd, result.string(), result.size());
1079 } else {
1080 AutoMutex lock(&mLock);
1081 if (mClient != 0) {
1082 sp<Client> currentClient = mClient.promote();
1083 sprintf(buffer, "Client (%p) PID: %d\n",
1084 currentClient->getCameraClient()->asBinder().get(),
1085 currentClient->mClientPid);
1086 result.append(buffer);
1087 write(fd, result.string(), result.size());
1088 currentClient->mHardware->dump(fd, args);
1089 } else {
1090 result.append("No camera client yet.\n");
1091 write(fd, result.string(), result.size());
1092 }
1093 }
1094 return NO_ERROR;
1095}
1096
1097
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001098status_t CameraService::onTransact(
1099 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1100{
1101 // permission checks...
1102 switch (code) {
1103 case BnCameraService::CONNECT:
1104 IPCThreadState* ipc = IPCThreadState::self();
1105 const int pid = ipc->getCallingPid();
1106 const int self_pid = getpid();
1107 if (pid != self_pid) {
1108 // we're called from a different process, do the real check
1109 if (!checkCallingPermission(
1110 String16("android.permission.CAMERA")))
1111 {
1112 const int uid = ipc->getCallingUid();
1113 LOGE("Permission Denial: "
1114 "can't use the camera pid=%d, uid=%d", pid, uid);
1115 return PERMISSION_DENIED;
1116 }
1117 }
1118 break;
1119 }
1120
1121 status_t err = BnCameraService::onTransact(code, data, reply, flags);
1122
Dave Sparksb1f3b8f2009-05-20 20:02:59 -07001123#if DEBUG_HEAP_LEAKS
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001124 LOGD("+++ onTransact err %d code %d", err, code);
1125
1126 if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
1127 // the 'service' command interrogates this binder for its name, and then supplies it
1128 // even for the debugging commands. that means we need to check for it here, using
1129 // ISurfaceComposer (since we delegated the INTERFACE_TRANSACTION handling to
1130 // BnSurfaceComposer before falling through to this code).
1131
1132 LOGD("+++ onTransact code %d", code);
1133
1134 CHECK_INTERFACE(ICameraService, data, reply);
1135
1136 switch(code) {
1137 case 1000:
1138 {
1139 if (gWeakHeap != 0) {
1140 sp<IMemoryHeap> h = gWeakHeap.promote();
1141 IMemoryHeap *p = gWeakHeap.unsafe_get();
1142 LOGD("CHECKING WEAK REFERENCE %p (%p)", h.get(), p);
1143 if (h != 0)
1144 h->printRefs();
1145 bool attempt_to_delete = data.readInt32() == 1;
1146 if (attempt_to_delete) {
1147 // NOT SAFE!
1148 LOGD("DELETING WEAK REFERENCE %p (%p)", h.get(), p);
1149 if (p) delete p;
1150 }
1151 return NO_ERROR;
1152 }
1153 }
1154 break;
1155 default:
1156 break;
1157 }
1158 }
Dave Sparksb1f3b8f2009-05-20 20:02:59 -07001159#endif // DEBUG_HEAP_LEAKS
Dave Sparks7b7225c2009-05-21 09:18:18 -07001160
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001161 return err;
1162}
1163
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001164}; // namespace android