Looper.quit() is asynchronous. The looper may still has some preview callbacks in the queue after quit is called. The preview callback still uses the camera object (setHasPreviewCallback). After camera is released, RuntimeException will be thrown from the method. So we need to join the looper thread here. This change also fixes a potential race condition. bug:2521202 Change-Id: If69bbb3125d1d30192563559579b87c20fa5aac8