From b6aef253f4c0d05496a4c93ae538bb94ba525648 Mon Sep 17 00:00:00 2001
From: Chih-Chung Chang <chihchung@google.com>
Date: Thu, 1 Jul 2010 21:06:45 +0800
Subject: Flush binder buffer after setting raw heap to avoid leaking a
 reference.

The problem was:

1. In handleShutter(), thread A in CameraService calls
   registerBuffers(IMemoryHeap) and it's received by thread B
   in system_server. [transaction 1]
2. While thread A is waiting for the reply, thread B calls
   back to thread A to get the id of the heap
   (IMemoryHeap.getHeapID). [transaction 2]
3. Thread A replies transaction 2 and is preemptied in kernel.
   Thread B gets the reply and finishes registerBuffers and send
   reply for transaction 1.
4. When thread A runs again, it gets the reply for transaction 1
   and returns to handleShutter().
5. At this point the transaction buffer for transaction 2 (which
   holds a reference to IMemoryHeap) is not freed because the
   BC_FREE_BUFFER command is kept in thread A's local command
   queue and not sent to the kernel.
6. Normally when thread A makes next transaction, the
   BC_FREE_BUFFER command will be sent together (piggyback) with
   the commands for that transaction. But in this case thread A
   is a callback thread from camera driver, so it does not make
   any binder calls afterwards, and the IMemoryHeap is never freed
   (until the next time handleShutter is called).

Change-Id: I435a258187509bdbbaf353339eb9ea577610cbd2
---
 camera/libcameraservice/CameraService.cpp | 1 +
 1 file changed, 1 insertion(+)

(limited to 'camera')

diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index 00bd54e..2690182 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -935,6 +935,7 @@ void CameraService::Client::handleShutter(
             mHardware->getRawHeap());
 
         mSurface->registerBuffers(buffers);
+        IPCThreadState::self()->flushCommands();
     }
 }
 
-- 
cgit v1.1