• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 **
3 ** Copyright (C) 2008, The Android Open Source Project
4 ** Copyright (C) 2008 HTC Inc.
5 **
6 ** Licensed under the Apache License, Version 2.0 (the "License");
7 ** you may not use this file except in compliance with the License.
8 ** You may obtain a copy of the License at
9 **
10 **     http://www.apache.org/licenses/LICENSE-2.0
11 **
12 ** Unless required by applicable law or agreed to in writing, software
13 ** distributed under the License is distributed on an "AS IS" BASIS,
14 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 ** See the License for the specific language governing permissions and
16 ** limitations under the License.
17 */
18 
19 //#define LOG_NDEBUG 0
20 #define LOG_TAG "CameraService"
21 #include <utils/Log.h>
22 
23 #include <binder/IServiceManager.h>
24 #include <binder/IPCThreadState.h>
25 #include <utils/String16.h>
26 #include <utils/Errors.h>
27 #include <binder/MemoryBase.h>
28 #include <binder/MemoryHeapBase.h>
29 #include <ui/ICameraService.h>
30 
31 #include <media/mediaplayer.h>
32 #include <media/AudioSystem.h>
33 #include "CameraService.h"
34 
35 #include <cutils/atomic.h>
36 
37 namespace android {
38 
39 extern "C" {
40 #include <stdio.h>
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <fcntl.h>
44 #include <pthread.h>
45 #include <signal.h>
46 }
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 #define DEBUG_DUMP_POSTVIEW_SNAPSHOT_TO_FILE 0
63 
64 #if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
65 static int debug_frame_cnt;
66 #endif
67 
getCallingPid()68 static int getCallingPid() {
69     return IPCThreadState::self()->getCallingPid();
70 }
71 
72 // ----------------------------------------------------------------------------
73 
instantiate()74 void CameraService::instantiate() {
75     defaultServiceManager()->addService(
76             String16("media.camera"), new CameraService());
77 }
78 
79 // ----------------------------------------------------------------------------
80 
CameraService()81 CameraService::CameraService() :
82     BnCameraService()
83 {
84     LOGI("CameraService started: pid=%d", getpid());
85     mUsers = 0;
86 }
87 
~CameraService()88 CameraService::~CameraService()
89 {
90     if (mClient != 0) {
91         LOGE("mClient was still connected in destructor!");
92     }
93 }
94 
connect(const sp<ICameraClient> & cameraClient)95 sp<ICamera> CameraService::connect(const sp<ICameraClient>& cameraClient)
96 {
97     int callingPid = getCallingPid();
98     LOGD("CameraService::connect E (pid %d, client %p)", callingPid,
99             cameraClient->asBinder().get());
100 
101     Mutex::Autolock lock(mServiceLock);
102     sp<Client> client;
103     if (mClient != 0) {
104         sp<Client> currentClient = mClient.promote();
105         if (currentClient != 0) {
106             sp<ICameraClient> currentCameraClient(currentClient->getCameraClient());
107             if (cameraClient->asBinder() == currentCameraClient->asBinder()) {
108                 // This is the same client reconnecting...
109                 LOGD("CameraService::connect X (pid %d, same client %p) is reconnecting...",
110                     callingPid, cameraClient->asBinder().get());
111                 return currentClient;
112             } else {
113                 // It's another client... reject it
114                 LOGD("CameraService::connect X (pid %d, new client %p) rejected. "
115                     "(old pid %d, old client %p)",
116                     callingPid, cameraClient->asBinder().get(),
117                     currentClient->mClientPid, currentCameraClient->asBinder().get());
118                 if (kill(currentClient->mClientPid, 0) == -1 && errno == ESRCH) {
119                     LOGD("The old client is dead!");
120                 }
121                 return client;
122             }
123         } else {
124             // can't promote, the previous client has died...
125             LOGD("New client (pid %d) connecting, old reference was dangling...",
126                     callingPid);
127             mClient.clear();
128         }
129     }
130 
131     if (mUsers > 0) {
132         LOGD("Still have client, rejected");
133         return client;
134     }
135 
136     // create a new Client object
137     client = new Client(this, cameraClient, callingPid);
138     mClient = client;
139 #if DEBUG_CLIENT_REFERENCES
140     // Enable tracking for this object, and track increments and decrements of
141     // the refcount.
142     client->trackMe(true, true);
143 #endif
144     LOGD("CameraService::connect X");
145     return client;
146 }
147 
removeClient(const sp<ICameraClient> & cameraClient)148 void CameraService::removeClient(const sp<ICameraClient>& cameraClient)
149 {
150     int callingPid = getCallingPid();
151 
152     // Declare this outside the lock to make absolutely sure the
153     // destructor won't be called with the lock held.
154     sp<Client> client;
155 
156     Mutex::Autolock lock(mServiceLock);
157 
158     if (mClient == 0) {
159         // This happens when we have already disconnected.
160         LOGD("removeClient (pid %d): already disconnected", callingPid);
161         return;
162     }
163 
164     // Promote mClient. It can fail if we are called from this path:
165     // Client::~Client() -> disconnect() -> removeClient().
166     client = mClient.promote();
167     if (client == 0) {
168         LOGD("removeClient (pid %d): no more strong reference", callingPid);
169         mClient.clear();
170         return;
171     }
172 
173     if (cameraClient->asBinder() != client->getCameraClient()->asBinder()) {
174         // ugh! that's not our client!!
175         LOGW("removeClient (pid %d): mClient doesn't match!", callingPid);
176     } else {
177         // okay, good, forget about mClient
178         mClient.clear();
179     }
180 
181     LOGD("removeClient (pid %d) done", callingPid);
182 }
183 
184 // The reason we need this count is a new CameraService::connect() request may
185 // come in while the previous Client's destructor has not been run or is still
186 // running. If the last strong reference of the previous Client is gone but
187 // destructor has not been run, we should not allow the new Client to be created
188 // because we need to wait for the previous Client to tear down the hardware
189 // first.
incUsers()190 void CameraService::incUsers() {
191     android_atomic_inc(&mUsers);
192 }
193 
decUsers()194 void CameraService::decUsers() {
195     android_atomic_dec(&mUsers);
196 }
197 
newMediaPlayer(const char * file)198 static sp<MediaPlayer> newMediaPlayer(const char *file)
199 {
200     sp<MediaPlayer> mp = new MediaPlayer();
201     if (mp->setDataSource(file) == NO_ERROR) {
202         mp->setAudioStreamType(AudioSystem::ENFORCED_AUDIBLE);
203         mp->prepare();
204     } else {
205         mp.clear();
206         LOGE("Failed to load CameraService sounds.");
207     }
208     return mp;
209 }
210 
Client(const sp<CameraService> & cameraService,const sp<ICameraClient> & cameraClient,pid_t clientPid)211 CameraService::Client::Client(const sp<CameraService>& cameraService,
212         const sp<ICameraClient>& cameraClient, pid_t clientPid)
213 {
214     int callingPid = getCallingPid();
215     LOGD("Client::Client E (pid %d)", callingPid);
216     mCameraService = cameraService;
217     mCameraClient = cameraClient;
218     mClientPid = clientPid;
219     mHardware = openCameraHardware();
220     mUseOverlay = mHardware->useOverlay();
221 
222     mHardware->setCallbacks(notifyCallback,
223                             dataCallback,
224                             dataCallbackTimestamp,
225                             mCameraService.get());
226 
227     // Enable zoom, error, and focus messages by default
228     mHardware->enableMsgType(CAMERA_MSG_ERROR |
229                              CAMERA_MSG_ZOOM |
230                              CAMERA_MSG_FOCUS);
231 
232     mMediaPlayerClick = newMediaPlayer("/system/media/audio/ui/camera_click.ogg");
233     mMediaPlayerBeep = newMediaPlayer("/system/media/audio/ui/VideoRecord.ogg");
234     mOverlayW = 0;
235     mOverlayH = 0;
236 
237     // Callback is disabled by default
238     mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
239     cameraService->incUsers();
240     LOGD("Client::Client X (pid %d)", callingPid);
241 }
242 
checkPid()243 status_t CameraService::Client::checkPid()
244 {
245     int callingPid = getCallingPid();
246     if (mClientPid == callingPid) return NO_ERROR;
247     LOGW("Attempt to use locked camera (client %p) from different process "
248         " (old pid %d, new pid %d)",
249         getCameraClient()->asBinder().get(), mClientPid, callingPid);
250     return -EBUSY;
251 }
252 
lock()253 status_t CameraService::Client::lock()
254 {
255     int callingPid = getCallingPid();
256     LOGD("lock from pid %d (mClientPid %d)", callingPid, mClientPid);
257     Mutex::Autolock _l(mLock);
258     // lock camera to this client if the the camera is unlocked
259     if (mClientPid == 0) {
260         mClientPid = callingPid;
261         return NO_ERROR;
262     }
263     // returns NO_ERROR if the client already owns the camera, -EBUSY otherwise
264     return checkPid();
265 }
266 
unlock()267 status_t CameraService::Client::unlock()
268 {
269     int callingPid = getCallingPid();
270     LOGD("unlock from pid %d (mClientPid %d)", callingPid, mClientPid);
271     Mutex::Autolock _l(mLock);
272     // allow anyone to use camera
273     status_t result = checkPid();
274     if (result == NO_ERROR) {
275         mClientPid = 0;
276         LOGD("clear mCameraClient (pid %d)", callingPid);
277         // we need to remove the reference so that when app goes
278         // away, the reference count goes to 0.
279         mCameraClient.clear();
280     }
281     return result;
282 }
283 
connect(const sp<ICameraClient> & client)284 status_t CameraService::Client::connect(const sp<ICameraClient>& client)
285 {
286     int callingPid = getCallingPid();
287 
288     // connect a new process to the camera
289     LOGD("Client::connect E (pid %d, client %p)", callingPid, client->asBinder().get());
290 
291     // I hate this hack, but things get really ugly when the media recorder
292     // service is handing back the camera to the app. The ICameraClient
293     // destructor will be called during the same IPC, making it look like
294     // the remote client is trying to disconnect. This hack temporarily
295     // sets the mClientPid to an invalid pid to prevent the hardware from
296     // being torn down.
297     {
298 
299         // hold a reference to the old client or we will deadlock if the client is
300         // in the same process and we hold the lock when we remove the reference
301         sp<ICameraClient> oldClient;
302         {
303             Mutex::Autolock _l(mLock);
304             if (mClientPid != 0 && checkPid() != NO_ERROR) {
305                 LOGW("Tried to connect to locked camera (old pid %d, new pid %d)",
306                         mClientPid, callingPid);
307                 return -EBUSY;
308             }
309             oldClient = mCameraClient;
310 
311             // did the client actually change?
312             if ((mCameraClient != NULL) && (client->asBinder() == mCameraClient->asBinder())) {
313                 LOGD("Connect to the same client");
314                 return NO_ERROR;
315             }
316 
317             mCameraClient = client;
318             mClientPid = -1;
319             mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
320             LOGD("Connect to the new client (pid %d, client %p)",
321                 callingPid, mCameraClient->asBinder().get());
322         }
323 
324     }
325     // the old client destructor is called when oldClient goes out of scope
326     // now we set the new PID to lock the interface again
327     mClientPid = callingPid;
328 
329     return NO_ERROR;
330 }
331 
332 #if HAVE_ANDROID_OS
unregister_surface(void * arg)333 static void *unregister_surface(void *arg)
334 {
335     ISurface *surface = (ISurface *)arg;
336     surface->unregisterBuffers();
337     IPCThreadState::self()->flushCommands();
338     return NULL;
339 }
340 #endif
341 
~Client()342 CameraService::Client::~Client()
343 {
344     int callingPid = getCallingPid();
345 
346     // tear down client
347     LOGD("Client::~Client E (pid %d, client %p)",
348             callingPid, getCameraClient()->asBinder().get());
349     if (mSurface != 0 && !mUseOverlay) {
350 #if HAVE_ANDROID_OS
351         pthread_t thr;
352         // We unregister the buffers in a different thread because binder does
353         // not let us make sychronous transactions in a binder destructor (that
354         // is, upon our reaching a refcount of zero.)
355         pthread_create(&thr, NULL,
356                        unregister_surface,
357                        mSurface.get());
358         pthread_join(thr, NULL);
359 #else
360         mSurface->unregisterBuffers();
361 #endif
362     }
363 
364     if (mMediaPlayerBeep.get() != NULL) {
365         mMediaPlayerBeep->disconnect();
366         mMediaPlayerBeep.clear();
367     }
368     if (mMediaPlayerClick.get() != NULL) {
369         mMediaPlayerClick->disconnect();
370         mMediaPlayerClick.clear();
371     }
372 
373     // make sure we tear down the hardware
374     mClientPid = callingPid;
375     disconnect();
376     LOGD("Client::~Client X (pid %d)", mClientPid);
377 }
378 
disconnect()379 void CameraService::Client::disconnect()
380 {
381     int callingPid = getCallingPid();
382 
383     LOGD("Client::disconnect() E (pid %d client %p)",
384             callingPid, getCameraClient()->asBinder().get());
385 
386     Mutex::Autolock lock(mLock);
387     if (mClientPid <= 0) {
388         LOGD("camera is unlocked (mClientPid = %d), don't tear down hardware", mClientPid);
389         return;
390     }
391     if (checkPid() != NO_ERROR) {
392         LOGD("Different client - don't disconnect");
393         return;
394     }
395 
396     // Make sure disconnect() is done once and once only, whether it is called
397     // from the user directly, or called by the destructor.
398     if (mHardware == 0) return;
399 
400     LOGD("hardware teardown");
401     // Before destroying mHardware, we must make sure it's in the
402     // idle state.
403     mHardware->stopPreview();
404     // Cancel all picture callbacks.
405     mHardware->disableMsgType(CAMERA_MSG_SHUTTER |
406                               CAMERA_MSG_POSTVIEW_FRAME |
407                               CAMERA_MSG_RAW_IMAGE |
408                               CAMERA_MSG_COMPRESSED_IMAGE);
409     mHardware->cancelPicture();
410     // Turn off remaining messages.
411     mHardware->disableMsgType(CAMERA_MSG_ALL_MSGS);
412     // Release the hardware resources.
413     mHardware->release();
414     // Release the held overlay resources.
415     if (mUseOverlay)
416     {
417         mOverlayRef = 0;
418     }
419     mHardware.clear();
420 
421     mCameraService->removeClient(mCameraClient);
422     mCameraService->decUsers();
423 
424     LOGD("Client::disconnect() X (pid %d)", callingPid);
425 }
426 
427 // pass the buffered ISurface to the camera service
setPreviewDisplay(const sp<ISurface> & surface)428 status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface)
429 {
430     LOGD("setPreviewDisplay(%p) (pid %d)",
431          ((surface == NULL) ? NULL : surface.get()), getCallingPid());
432     Mutex::Autolock lock(mLock);
433     status_t result = checkPid();
434     if (result != NO_ERROR) return result;
435 
436     Mutex::Autolock surfaceLock(mSurfaceLock);
437     result = NO_ERROR;
438     // asBinder() is safe on NULL (returns NULL)
439     if (surface->asBinder() != mSurface->asBinder()) {
440         if (mSurface != 0) {
441             LOGD("clearing old preview surface %p", mSurface.get());
442             if ( !mUseOverlay)
443             {
444                 mSurface->unregisterBuffers();
445             }
446             else
447             {
448                 // Force the destruction of any previous overlay
449                 sp<Overlay> dummy;
450                 mHardware->setOverlay( dummy );
451             }
452         }
453         mSurface = surface;
454         mOverlayRef = 0;
455         // If preview has been already started, set overlay or register preview
456         // buffers now.
457         if (mHardware->previewEnabled()) {
458             if (mUseOverlay) {
459                 result = setOverlay();
460             } else if (mSurface != 0) {
461                 result = registerPreviewBuffers();
462             }
463         }
464     }
465     return result;
466 }
467 
468 // set the preview callback flag to affect how the received frames from
469 // preview are handled.
setPreviewCallbackFlag(int callback_flag)470 void CameraService::Client::setPreviewCallbackFlag(int callback_flag)
471 {
472     LOGV("setPreviewCallbackFlag (pid %d)", getCallingPid());
473     Mutex::Autolock lock(mLock);
474     if (checkPid() != NO_ERROR) return;
475     mPreviewCallbackFlag = callback_flag;
476 
477     if(mUseOverlay) {
478         if(mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK)
479             mHardware->enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
480         else
481             mHardware->disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
482     }
483 }
484 
485 // start preview mode
startCameraMode(camera_mode mode)486 status_t CameraService::Client::startCameraMode(camera_mode mode)
487 {
488     int callingPid = getCallingPid();
489 
490     LOGD("startCameraMode(%d) (pid %d)", mode, callingPid);
491 
492     /* we cannot call into mHardware with mLock held because
493      * mHardware has callbacks onto us which acquire this lock
494      */
495 
496     Mutex::Autolock lock(mLock);
497     status_t result = checkPid();
498     if (result != NO_ERROR) return result;
499 
500     if (mHardware == 0) {
501         LOGE("mHardware is NULL, returning.");
502         return INVALID_OPERATION;
503     }
504 
505     switch(mode) {
506     case CAMERA_RECORDING_MODE:
507         if (mSurface == 0) {
508             LOGE("setPreviewDisplay must be called before startRecordingMode.");
509             return INVALID_OPERATION;
510         }
511         return startRecordingMode();
512 
513     default: // CAMERA_PREVIEW_MODE
514         if (mSurface == 0) {
515             LOGD("mSurface is not set yet.");
516         }
517         return startPreviewMode();
518     }
519 }
520 
startRecordingMode()521 status_t CameraService::Client::startRecordingMode()
522 {
523     LOGD("startRecordingMode (pid %d)", getCallingPid());
524 
525     status_t ret = UNKNOWN_ERROR;
526 
527     // if preview has not been started, start preview first
528     if (!mHardware->previewEnabled()) {
529         ret = startPreviewMode();
530         if (ret != NO_ERROR) {
531             return ret;
532         }
533     }
534 
535     // if recording has been enabled, nothing needs to be done
536     if (mHardware->recordingEnabled()) {
537         return NO_ERROR;
538     }
539 
540     // start recording mode
541     ret = mHardware->startRecording();
542     if (ret != NO_ERROR) {
543         LOGE("mHardware->startRecording() failed with status %d", ret);
544     }
545     return ret;
546 }
547 
setOverlay()548 status_t CameraService::Client::setOverlay()
549 {
550     LOGD("setOverlay");
551     int w, h;
552     CameraParameters params(mHardware->getParameters());
553     params.getPreviewSize(&w, &h);
554 
555     if ( w != mOverlayW || h != mOverlayH )
556     {
557         // Force the destruction of any previous overlay
558         sp<Overlay> dummy;
559         mHardware->setOverlay( dummy );
560         mOverlayRef = 0;
561     }
562 
563     status_t ret = NO_ERROR;
564     if (mSurface != 0) {
565         if (mOverlayRef.get() == NULL) {
566 
567             // FIXME:
568             // Surfaceflinger may hold onto the previous overlay reference for some
569             // time after we try to destroy it. retry a few times. In the future, we
570             // should make the destroy call block, or possibly specify that we can
571             // wait in the createOverlay call if the previous overlay is in the
572             // process of being destroyed.
573             for (int retry = 0; retry < 50; ++retry) {
574                 mOverlayRef = mSurface->createOverlay(w, h, OVERLAY_FORMAT_DEFAULT);
575                 if (mOverlayRef != NULL) break;
576                 LOGD("Overlay create failed - retrying");
577                 usleep(20000);
578             }
579             if ( mOverlayRef.get() == NULL )
580             {
581                 LOGE("Overlay Creation Failed!");
582                 return -EINVAL;
583             }
584             ret = mHardware->setOverlay(new Overlay(mOverlayRef));
585         }
586     } else {
587         ret = mHardware->setOverlay(NULL);
588     }
589     if (ret != NO_ERROR) {
590         LOGE("mHardware->setOverlay() failed with status %d\n", ret);
591     }
592 
593     mOverlayW = w;
594     mOverlayH = h;
595 
596     return ret;
597 }
598 
registerPreviewBuffers()599 status_t CameraService::Client::registerPreviewBuffers()
600 {
601     int w, h;
602     CameraParameters params(mHardware->getParameters());
603     params.getPreviewSize(&w, &h);
604 
605     uint32_t transform = 0;
606     if (params.getOrientation() ==
607         CameraParameters::CAMERA_ORIENTATION_PORTRAIT) {
608       LOGV("portrait mode");
609       transform = ISurface::BufferHeap::ROT_90;
610     }
611     ISurface::BufferHeap buffers(w, h, w, h,
612                                  PIXEL_FORMAT_YCbCr_420_SP,
613                                  transform,
614                                  0,
615                                  mHardware->getPreviewHeap());
616 
617     status_t ret = mSurface->registerBuffers(buffers);
618     if (ret != NO_ERROR) {
619         LOGE("registerBuffers failed with status %d", ret);
620     }
621     return ret;
622 }
623 
startPreviewMode()624 status_t CameraService::Client::startPreviewMode()
625 {
626     LOGD("startPreviewMode (pid %d)", getCallingPid());
627 
628     // if preview has been enabled, nothing needs to be done
629     if (mHardware->previewEnabled()) {
630         return NO_ERROR;
631     }
632 
633     // start preview mode
634 #if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
635     debug_frame_cnt = 0;
636 #endif
637     status_t ret = NO_ERROR;
638 
639     if (mUseOverlay) {
640         // If preview display has been set, set overlay now.
641         if (mSurface != 0) {
642             ret = setOverlay();
643         }
644         if (ret != NO_ERROR) return ret;
645         ret = mHardware->startPreview();
646     } else {
647         mHardware->enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
648         ret = mHardware->startPreview();
649         if (ret != NO_ERROR) return ret;
650         // If preview display has been set, register preview buffers now.
651         if (mSurface != 0) {
652            // Unregister here because the surface registered with raw heap.
653            mSurface->unregisterBuffers();
654            ret = registerPreviewBuffers();
655         }
656     }
657     return ret;
658 }
659 
startPreview()660 status_t CameraService::Client::startPreview()
661 {
662     LOGD("startPreview (pid %d)", getCallingPid());
663 
664     return startCameraMode(CAMERA_PREVIEW_MODE);
665 }
666 
startRecording()667 status_t CameraService::Client::startRecording()
668 {
669     LOGD("startRecording (pid %d)", getCallingPid());
670 
671     if (mMediaPlayerBeep.get() != NULL) {
672         mMediaPlayerBeep->seekTo(0);
673         mMediaPlayerBeep->start();
674     }
675 
676     mHardware->enableMsgType(CAMERA_MSG_VIDEO_FRAME);
677 
678     return startCameraMode(CAMERA_RECORDING_MODE);
679 }
680 
681 // stop preview mode
stopPreview()682 void CameraService::Client::stopPreview()
683 {
684     LOGD("stopPreview (pid %d)", getCallingPid());
685 
686     // hold main lock during state transition
687     {
688         Mutex::Autolock lock(mLock);
689         if (checkPid() != NO_ERROR) return;
690 
691         if (mHardware == 0) {
692             LOGE("mHardware is NULL, returning.");
693             return;
694         }
695 
696         mHardware->stopPreview();
697         mHardware->disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
698         LOGD("stopPreview(), hardware stopped OK");
699 
700         if (mSurface != 0 && !mUseOverlay) {
701             mSurface->unregisterBuffers();
702         }
703     }
704 
705     // hold preview buffer lock
706     {
707         Mutex::Autolock lock(mPreviewLock);
708         mPreviewBuffer.clear();
709     }
710 }
711 
712 // stop recording mode
stopRecording()713 void CameraService::Client::stopRecording()
714 {
715     LOGD("stopRecording (pid %d)", getCallingPid());
716 
717     // hold main lock during state transition
718     {
719         Mutex::Autolock lock(mLock);
720         if (checkPid() != NO_ERROR) return;
721 
722         if (mHardware == 0) {
723             LOGE("mHardware is NULL, returning.");
724             return;
725         }
726 
727         if (mMediaPlayerBeep.get() != NULL) {
728             mMediaPlayerBeep->seekTo(0);
729             mMediaPlayerBeep->start();
730         }
731 
732         mHardware->stopRecording();
733         mHardware->disableMsgType(CAMERA_MSG_VIDEO_FRAME);
734         LOGD("stopRecording(), hardware stopped OK");
735     }
736 
737     // hold preview buffer lock
738     {
739         Mutex::Autolock lock(mPreviewLock);
740         mPreviewBuffer.clear();
741     }
742 }
743 
744 // release a recording frame
releaseRecordingFrame(const sp<IMemory> & mem)745 void CameraService::Client::releaseRecordingFrame(const sp<IMemory>& mem)
746 {
747     Mutex::Autolock lock(mLock);
748     if (checkPid() != NO_ERROR) return;
749 
750     if (mHardware == 0) {
751         LOGE("mHardware is NULL, returning.");
752         return;
753     }
754 
755     mHardware->releaseRecordingFrame(mem);
756 }
757 
previewEnabled()758 bool CameraService::Client::previewEnabled()
759 {
760     Mutex::Autolock lock(mLock);
761     if (mHardware == 0) return false;
762     return mHardware->previewEnabled();
763 }
764 
recordingEnabled()765 bool CameraService::Client::recordingEnabled()
766 {
767     Mutex::Autolock lock(mLock);
768     if (mHardware == 0) return false;
769     return mHardware->recordingEnabled();
770 }
771 
772 // Safely retrieves a strong pointer to the client during a hardware callback.
getClientFromCookie(void * user)773 sp<CameraService::Client> CameraService::Client::getClientFromCookie(void* user)
774 {
775     sp<Client> client = 0;
776     CameraService *service = static_cast<CameraService*>(user);
777     if (service != NULL) {
778         Mutex::Autolock ourLock(service->mServiceLock);
779         if (service->mClient != 0) {
780             client = service->mClient.promote();
781             if (client == 0) {
782                 LOGE("getClientFromCookie: client appears to have died");
783                 service->mClient.clear();
784             }
785         } else {
786             LOGE("getClientFromCookie: got callback but client was NULL");
787         }
788     }
789     return client;
790 }
791 
792 
793 #if DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE || \
794     DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE || \
795     DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
dump_to_file(const char * fname,uint8_t * buf,uint32_t size)796 static void dump_to_file(const char *fname,
797                          uint8_t *buf, uint32_t size)
798 {
799     int nw, cnt = 0;
800     uint32_t written = 0;
801 
802     LOGD("opening file [%s]\n", fname);
803     int fd = open(fname, O_RDWR | O_CREAT);
804     if (fd < 0) {
805         LOGE("failed to create file [%s]: %s", fname, strerror(errno));
806         return;
807     }
808 
809     LOGD("writing %d bytes to file [%s]\n", size, fname);
810     while (written < size) {
811         nw = ::write(fd,
812                      buf + written,
813                      size - written);
814         if (nw < 0) {
815             LOGE("failed to write to file [%s]: %s",
816                  fname, strerror(errno));
817             break;
818         }
819         written += nw;
820         cnt++;
821     }
822     LOGD("done writing %d bytes to file [%s] in %d passes\n",
823          size, fname, cnt);
824     ::close(fd);
825 }
826 #endif
827 
autoFocus()828 status_t CameraService::Client::autoFocus()
829 {
830     LOGD("autoFocus (pid %d)", getCallingPid());
831 
832     Mutex::Autolock lock(mLock);
833     status_t result = checkPid();
834     if (result != NO_ERROR) return result;
835 
836     if (mHardware == 0) {
837         LOGE("mHardware is NULL, returning.");
838         return INVALID_OPERATION;
839     }
840 
841     return mHardware->autoFocus();
842 }
843 
cancelAutoFocus()844 status_t CameraService::Client::cancelAutoFocus()
845 {
846     LOGD("cancelAutoFocus (pid %d)", getCallingPid());
847 
848     Mutex::Autolock lock(mLock);
849     status_t result = checkPid();
850     if (result != NO_ERROR) return result;
851 
852     if (mHardware == 0) {
853         LOGE("mHardware is NULL, returning.");
854         return INVALID_OPERATION;
855     }
856 
857     return mHardware->cancelAutoFocus();
858 }
859 
860 // take a picture - image is returned in callback
takePicture()861 status_t CameraService::Client::takePicture()
862 {
863     LOGD("takePicture (pid %d)", getCallingPid());
864 
865     Mutex::Autolock lock(mLock);
866     status_t result = checkPid();
867     if (result != NO_ERROR) return result;
868 
869     if (mHardware == 0) {
870         LOGE("mHardware is NULL, returning.");
871         return INVALID_OPERATION;
872     }
873 
874     mHardware->enableMsgType(CAMERA_MSG_SHUTTER |
875                              CAMERA_MSG_POSTVIEW_FRAME |
876                              CAMERA_MSG_RAW_IMAGE |
877                              CAMERA_MSG_COMPRESSED_IMAGE);
878 
879     return mHardware->takePicture();
880 }
881 
882 // snapshot taken
handleShutter(image_rect_type * size)883 void CameraService::Client::handleShutter(
884     image_rect_type *size // The width and height of yuv picture for
885                           // registerBuffer. If this is NULL, use the picture
886                           // size from parameters.
887 )
888 {
889     // Play shutter sound.
890     if (mMediaPlayerClick.get() != NULL) {
891         mMediaPlayerClick->seekTo(0);
892         mMediaPlayerClick->start();
893     }
894 
895     // Screen goes black after the buffer is unregistered.
896     if (mSurface != 0 && !mUseOverlay) {
897         mSurface->unregisterBuffers();
898     }
899 
900     sp<ICameraClient> c = mCameraClient;
901     if (c != NULL) {
902         c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
903     }
904     mHardware->disableMsgType(CAMERA_MSG_SHUTTER);
905 
906     // It takes some time before yuvPicture callback to be called.
907     // Register the buffer for raw image here to reduce latency.
908     if (mSurface != 0 && !mUseOverlay) {
909         int w, h;
910         CameraParameters params(mHardware->getParameters());
911         uint32_t transform = 0;
912         if (params.getOrientation() == CameraParameters::CAMERA_ORIENTATION_PORTRAIT) {
913             LOGV("portrait mode");
914             transform = ISurface::BufferHeap::ROT_90;
915         }
916 
917         if (size == NULL) {
918             params.getPictureSize(&w, &h);
919         } else {
920             w = size->width;
921             h = size->height;
922             w &= ~1;
923             h &= ~1;
924             LOGD("Snapshot image width=%d, height=%d", w, h);
925         }
926         ISurface::BufferHeap buffers(w, h, w, h,
927             PIXEL_FORMAT_YCbCr_420_SP, transform, 0, mHardware->getRawHeap());
928 
929         mSurface->registerBuffers(buffers);
930     }
931 }
932 
933 // preview callback - frame buffer update
handlePreviewData(const sp<IMemory> & mem)934 void CameraService::Client::handlePreviewData(const sp<IMemory>& mem)
935 {
936     ssize_t offset;
937     size_t size;
938     sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
939 
940 #if DEBUG_HEAP_LEAKS && 0 // debugging
941     if (gWeakHeap == NULL) {
942         if (gWeakHeap != heap) {
943             LOGD("SETTING PREVIEW HEAP");
944             heap->trackMe(true, true);
945             gWeakHeap = heap;
946         }
947     }
948 #endif
949 #if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
950     {
951         if (debug_frame_cnt++ == DEBUG_DUMP_PREVIEW_FRAME_TO_FILE) {
952             dump_to_file("/data/preview.yuv",
953                          (uint8_t *)heap->base() + offset, size);
954         }
955     }
956 #endif
957 
958     if (!mUseOverlay)
959     {
960         Mutex::Autolock surfaceLock(mSurfaceLock);
961         if (mSurface != NULL) {
962             mSurface->postBuffer(offset);
963         }
964     }
965 
966     // local copy of the callback flags
967     int flags = mPreviewCallbackFlag;
968 
969     // is callback enabled?
970     if (!(flags & FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
971         // If the enable bit is off, the copy-out and one-shot bits are ignored
972         LOGV("frame callback is diabled");
973         return;
974     }
975 
976     // hold a strong pointer to the client
977     sp<ICameraClient> c = mCameraClient;
978 
979     // clear callback flags if no client or one-shot mode
980     if ((c == NULL) || (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK)) {
981         LOGV("Disable preview callback");
982         mPreviewCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
983                                 FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
984                                 FRAME_CALLBACK_FLAG_ENABLE_MASK);
985         // TODO: Shouldn't we use this API for non-overlay hardware as well?
986         if (mUseOverlay)
987             mHardware->disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
988     }
989 
990     // Is the received frame copied out or not?
991     if (flags & FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
992         LOGV("frame is copied");
993         copyFrameAndPostCopiedFrame(c, heap, offset, size);
994     } else {
995         LOGV("frame is forwarded");
996         c->dataCallback(CAMERA_MSG_PREVIEW_FRAME, mem);
997     }
998 }
999 
1000 // picture callback - postview image ready
handlePostview(const sp<IMemory> & mem)1001 void CameraService::Client::handlePostview(const sp<IMemory>& mem)
1002 {
1003 #if DEBUG_DUMP_POSTVIEW_SNAPSHOT_TO_FILE // for testing pursposes only
1004     {
1005         ssize_t offset;
1006         size_t size;
1007         sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
1008         dump_to_file("/data/postview.yuv",
1009                      (uint8_t *)heap->base() + offset, size);
1010     }
1011 #endif
1012 
1013     sp<ICameraClient> c = mCameraClient;
1014     if (c != NULL) {
1015         c->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem);
1016     }
1017     mHardware->disableMsgType(CAMERA_MSG_POSTVIEW_FRAME);
1018 }
1019 
1020 // picture callback - raw image ready
handleRawPicture(const sp<IMemory> & mem)1021 void CameraService::Client::handleRawPicture(const sp<IMemory>& mem)
1022 {
1023     ssize_t offset;
1024     size_t size;
1025     sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
1026 #if DEBUG_HEAP_LEAKS && 0 // debugging
1027     gWeakHeap = heap; // debugging
1028 #endif
1029 
1030     //LOGV("handleRawPicture(%d, %d)", offset, size);
1031 #if DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE // for testing pursposes only
1032     dump_to_file("/data/photo.yuv",
1033                  (uint8_t *)heap->base() + offset, size);
1034 #endif
1035 
1036     // Put the YUV version of the snapshot in the preview display.
1037     if (mSurface != 0 && !mUseOverlay) {
1038         mSurface->postBuffer(offset);
1039     }
1040 
1041     sp<ICameraClient> c = mCameraClient;
1042     if (c != NULL) {
1043         c->dataCallback(CAMERA_MSG_RAW_IMAGE, mem);
1044     }
1045     mHardware->disableMsgType(CAMERA_MSG_RAW_IMAGE);
1046 }
1047 
1048 // picture callback - compressed picture ready
handleCompressedPicture(const sp<IMemory> & mem)1049 void CameraService::Client::handleCompressedPicture(const sp<IMemory>& mem)
1050 {
1051 #if DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE // for testing pursposes only
1052     {
1053         ssize_t offset;
1054         size_t size;
1055         sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
1056         dump_to_file("/data/photo.jpg",
1057                      (uint8_t *)heap->base() + offset, size);
1058     }
1059 #endif
1060 
1061     sp<ICameraClient> c = mCameraClient;
1062     if (c != NULL) {
1063         c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem);
1064     }
1065     mHardware->disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
1066 }
1067 
notifyCallback(int32_t msgType,int32_t ext1,int32_t ext2,void * user)1068 void CameraService::Client::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2, void* user)
1069 {
1070     LOGV("notifyCallback(%d)", msgType);
1071 
1072     sp<Client> client = getClientFromCookie(user);
1073     if (client == 0) {
1074         return;
1075     }
1076 
1077     switch (msgType) {
1078         case CAMERA_MSG_SHUTTER:
1079             // ext1 is the dimension of the yuv picture.
1080             client->handleShutter((image_rect_type *)ext1);
1081             break;
1082         default:
1083             sp<ICameraClient> c = client->mCameraClient;
1084             if (c != NULL) {
1085                 c->notifyCallback(msgType, ext1, ext2);
1086             }
1087             break;
1088     }
1089 
1090 #if DEBUG_CLIENT_REFERENCES
1091     if (client->getStrongCount() == 1) {
1092         LOGE("++++++++++++++++ (NOTIFY CALLBACK) THIS WILL CAUSE A LOCKUP!");
1093         client->printRefs();
1094     }
1095 #endif
1096 }
1097 
dataCallback(int32_t msgType,const sp<IMemory> & dataPtr,void * user)1098 void CameraService::Client::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, void* user)
1099 {
1100     LOGV("dataCallback(%d)", msgType);
1101 
1102     sp<Client> client = getClientFromCookie(user);
1103     if (client == 0) {
1104         return;
1105     }
1106 
1107     sp<ICameraClient> c = client->mCameraClient;
1108     if (dataPtr == NULL) {
1109         LOGE("Null data returned in data callback");
1110         if (c != NULL) {
1111             c->notifyCallback(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
1112             c->dataCallback(msgType, NULL);
1113         }
1114         return;
1115     }
1116 
1117     switch (msgType) {
1118         case CAMERA_MSG_PREVIEW_FRAME:
1119             client->handlePreviewData(dataPtr);
1120             break;
1121         case CAMERA_MSG_POSTVIEW_FRAME:
1122             client->handlePostview(dataPtr);
1123             break;
1124         case CAMERA_MSG_RAW_IMAGE:
1125             client->handleRawPicture(dataPtr);
1126             break;
1127         case CAMERA_MSG_COMPRESSED_IMAGE:
1128             client->handleCompressedPicture(dataPtr);
1129             break;
1130         default:
1131             if (c != NULL) {
1132                 c->dataCallback(msgType, dataPtr);
1133             }
1134             break;
1135     }
1136 
1137 #if DEBUG_CLIENT_REFERENCES
1138     if (client->getStrongCount() == 1) {
1139         LOGE("++++++++++++++++ (DATA CALLBACK) THIS WILL CAUSE A LOCKUP!");
1140         client->printRefs();
1141     }
1142 #endif
1143 }
1144 
dataCallbackTimestamp(nsecs_t timestamp,int32_t msgType,const sp<IMemory> & dataPtr,void * user)1145 void CameraService::Client::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
1146                                                   const sp<IMemory>& dataPtr, void* user)
1147 {
1148     LOGV("dataCallbackTimestamp(%d)", msgType);
1149 
1150     sp<Client> client = getClientFromCookie(user);
1151     if (client == 0) {
1152         return;
1153     }
1154     sp<ICameraClient> c = client->mCameraClient;
1155 
1156     if (dataPtr == NULL) {
1157         LOGE("Null data returned in data with timestamp callback");
1158         if (c != NULL) {
1159             c->notifyCallback(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
1160             c->dataCallbackTimestamp(0, msgType, NULL);
1161         }
1162         return;
1163     }
1164 
1165     if (c != NULL) {
1166         c->dataCallbackTimestamp(timestamp, msgType, dataPtr);
1167     }
1168 
1169 #if DEBUG_CLIENT_REFERENCES
1170     if (client->getStrongCount() == 1) {
1171         LOGE("++++++++++++++++ (DATA CALLBACK TIMESTAMP) THIS WILL CAUSE A LOCKUP!");
1172         client->printRefs();
1173     }
1174 #endif
1175 }
1176 
1177 // set preview/capture parameters - key/value pairs
setParameters(const String8 & params)1178 status_t CameraService::Client::setParameters(const String8& params)
1179 {
1180     LOGD("setParameters(%s)", params.string());
1181 
1182     Mutex::Autolock lock(mLock);
1183     status_t result = checkPid();
1184     if (result != NO_ERROR) return result;
1185 
1186     if (mHardware == 0) {
1187         LOGE("mHardware is NULL, returning.");
1188         return INVALID_OPERATION;
1189     }
1190 
1191     CameraParameters p(params);
1192     return mHardware->setParameters(p);
1193 }
1194 
1195 // get preview/capture parameters - key/value pairs
getParameters() const1196 String8 CameraService::Client::getParameters() const
1197 {
1198     Mutex::Autolock lock(mLock);
1199 
1200     if (mHardware == 0) {
1201         LOGE("mHardware is NULL, returning.");
1202         return String8();
1203     }
1204 
1205     String8 params(mHardware->getParameters().flatten());
1206     LOGD("getParameters(%s)", params.string());
1207     return params;
1208 }
1209 
sendCommand(int32_t cmd,int32_t arg1,int32_t arg2)1210 status_t CameraService::Client::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2)
1211 {
1212     LOGD("sendCommand (pid %d)", getCallingPid());
1213     Mutex::Autolock lock(mLock);
1214     status_t result = checkPid();
1215     if (result != NO_ERROR) return result;
1216 
1217     if (mHardware == 0) {
1218         LOGE("mHardware is NULL, returning.");
1219         return INVALID_OPERATION;
1220     }
1221 
1222     return mHardware->sendCommand(cmd, arg1, arg2);
1223 }
1224 
copyFrameAndPostCopiedFrame(const sp<ICameraClient> & client,const sp<IMemoryHeap> & heap,size_t offset,size_t size)1225 void CameraService::Client::copyFrameAndPostCopiedFrame(const sp<ICameraClient>& client,
1226         const sp<IMemoryHeap>& heap, size_t offset, size_t size)
1227 {
1228     LOGV("copyFrameAndPostCopiedFrame");
1229     // It is necessary to copy out of pmem before sending this to
1230     // the callback. For efficiency, reuse the same MemoryHeapBase
1231     // provided it's big enough. Don't allocate the memory or
1232     // perform the copy if there's no callback.
1233 
1234     // hold the preview lock while we grab a reference to the preview buffer
1235     sp<MemoryHeapBase> previewBuffer;
1236     {
1237         Mutex::Autolock lock(mPreviewLock);
1238         if (mPreviewBuffer == 0) {
1239             mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
1240         } else if (size > mPreviewBuffer->virtualSize()) {
1241             mPreviewBuffer.clear();
1242             mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
1243         }
1244         if (mPreviewBuffer == 0) {
1245             LOGE("failed to allocate space for preview buffer");
1246             return;
1247         }
1248         previewBuffer = mPreviewBuffer;
1249     }
1250     memcpy(previewBuffer->base(),
1251            (uint8_t *)heap->base() + offset, size);
1252 
1253     sp<MemoryBase> frame = new MemoryBase(previewBuffer, 0, size);
1254     if (frame == 0) {
1255         LOGE("failed to allocate space for frame callback");
1256         return;
1257     }
1258     client->dataCallback(CAMERA_MSG_PREVIEW_FRAME, frame);
1259 }
1260 
dump(int fd,const Vector<String16> & args)1261 status_t CameraService::dump(int fd, const Vector<String16>& args)
1262 {
1263     const size_t SIZE = 256;
1264     char buffer[SIZE];
1265     String8 result;
1266     if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
1267         snprintf(buffer, SIZE, "Permission Denial: "
1268                 "can't dump CameraService from pid=%d, uid=%d\n",
1269                 getCallingPid(),
1270                 IPCThreadState::self()->getCallingUid());
1271         result.append(buffer);
1272         write(fd, result.string(), result.size());
1273     } else {
1274         AutoMutex lock(&mServiceLock);
1275         if (mClient != 0) {
1276             sp<Client> currentClient = mClient.promote();
1277             sprintf(buffer, "Client (%p) PID: %d\n",
1278                     currentClient->getCameraClient()->asBinder().get(),
1279                     currentClient->mClientPid);
1280             result.append(buffer);
1281             write(fd, result.string(), result.size());
1282             currentClient->mHardware->dump(fd, args);
1283         } else {
1284             result.append("No camera client yet.\n");
1285             write(fd, result.string(), result.size());
1286         }
1287     }
1288     return NO_ERROR;
1289 }
1290 
1291 
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)1292 status_t CameraService::onTransact(
1293     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1294 {
1295     // permission checks...
1296     switch (code) {
1297         case BnCameraService::CONNECT:
1298             IPCThreadState* ipc = IPCThreadState::self();
1299             const int pid = ipc->getCallingPid();
1300             const int self_pid = getpid();
1301             if (pid != self_pid) {
1302                 // we're called from a different process, do the real check
1303                 if (!checkCallingPermission(
1304                         String16("android.permission.CAMERA")))
1305                 {
1306                     const int uid = ipc->getCallingUid();
1307                     LOGE("Permission Denial: "
1308                             "can't use the camera pid=%d, uid=%d", pid, uid);
1309                     return PERMISSION_DENIED;
1310                 }
1311             }
1312             break;
1313     }
1314 
1315     status_t err = BnCameraService::onTransact(code, data, reply, flags);
1316 
1317 #if DEBUG_HEAP_LEAKS
1318     LOGD("+++ onTransact err %d code %d", err, code);
1319 
1320     if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
1321         // the 'service' command interrogates this binder for its name, and then supplies it
1322         // even for the debugging commands.  that means we need to check for it here, using
1323         // ISurfaceComposer (since we delegated the INTERFACE_TRANSACTION handling to
1324         // BnSurfaceComposer before falling through to this code).
1325 
1326         LOGD("+++ onTransact code %d", code);
1327 
1328         CHECK_INTERFACE(ICameraService, data, reply);
1329 
1330         switch(code) {
1331         case 1000:
1332         {
1333             if (gWeakHeap != 0) {
1334                 sp<IMemoryHeap> h = gWeakHeap.promote();
1335                 IMemoryHeap *p = gWeakHeap.unsafe_get();
1336                 LOGD("CHECKING WEAK REFERENCE %p (%p)", h.get(), p);
1337                 if (h != 0)
1338                     h->printRefs();
1339                 bool attempt_to_delete = data.readInt32() == 1;
1340                 if (attempt_to_delete) {
1341                     // NOT SAFE!
1342                     LOGD("DELETING WEAK REFERENCE %p (%p)", h.get(), p);
1343                     if (p) delete p;
1344                 }
1345                 return NO_ERROR;
1346             }
1347         }
1348         break;
1349         default:
1350             break;
1351         }
1352     }
1353 #endif // DEBUG_HEAP_LEAKS
1354 
1355     return err;
1356 }
1357 
1358 }; // namespace android
1359