Native startPreview failed on Nexus S? Check your preview size

I got several error reports for Nerdstalgia from people using Nexus S. They were something akin to this:

04-05 12:22:50.371: DEBUG/SEC_Overlay(102): overlay_createOverlay:IN w=176 h=144 format=99
04-05 12:22:50.375: DEBUG/SEC_Overlay(102): src width, height are changed [w= 176, h= 144]->[w=176, h= 144]
04-05 12:22:50.375: INFO/SEC_Overlay(102): Opened video1/fd=253/obj=006e2468/shm=251/size=4096
04-05 12:22:50.375: DEBUG/SEC_Overlay(102): dst width, height have changed [w= 16, h= 1] -> [w=16, h= 16]
04-05 12:22:50.375: INFO/SEC_Overlay(102): Postponing Stream Enable/1/0
04-05 12:22:50.375: ERROR/v4l2_utils(75): Error = Invalid argument from stream on
04-05 12:22:50.375: ERROR/SEC_Overlay(75): Stream Enable Failed!/-1
04-05 12:22:50.375: ERROR/CameraHardwareSec(75): ERR(virtual android::status_t android::CameraHardwareSec::setOverlay(const android::sp<android::Overlay>&))::(mOverlay->setCrop(0, 0, 176, 144) fail
04-05 12:22:50.375: ERROR/CameraService(75): mHardware->setOverlay() failed with status -2147483648
04-05 12:22:50.378: DEBUG/AndroidRuntime(3875): Shutting down VM
04-05 12:22:50.378: WARN/dalvikvm(3875): threadid=1: thread exiting with uncaught exception (group=0x40015560)
04-05 12:22:50.378: ERROR/AndroidRuntime(3875): FATAL EXCEPTION: main
        java.lang.RuntimeException: startPreview failed
        at android.hardware.Camera.startPreview(Native Method)
        (and here starts my code)```


So it was failing well outside my <em>domains</em>--in a <strong>native</strong> method! There wasn't even a line number to have a look at. But was it because of something I did? I thought maybe it was because I wasn't synchronizing things properly--so I went to make sure everything was properly initialised, nothing was done before it was due... and still it crashed.

Then I paid even more close attention and I noticed that the difference between 'crash' and 'no crash' was that before it crashed it always output a <em>mHardware-&gt;setOverlay() failed with status -2147483648</em> message

So since I couldn't find any solution or pointer anywhere, I decided to have a look at the native code--that way, I could at least find out what was that <em>setOverlay() failed</em> message about.

It took me a bit to navigate the code, since there are lots of messages and calls going back and forward between Samsung's specific code and Android's core, and I'm not sure I have totally understood how it works, but it <em>seems</em> that the firmware for the Nexus S (alias <em>Samsung Crespo</em>) requires that
<ul>
<li>the preview surface width is a multiple of 8 (and at least 8), and</li>
<li>the preview surface height is at least 16</li>
</ul>

That is defined in the <a href="http://android.git.kernel.org/?p=device/samsung/crespo.git;a=blob;f=liboverlay/overlay.cpp;h=6220106fc8cbeb313c4aa5d5328b751abe6c9613;hb=HEAD#l984">check_fimc_dst_constraints</a> function in <a href="http://android.git.kernel.org/?p=device/samsung/crespo.git;a=blob;f=liboverlay/overlay.cpp;h=6220106fc8cbeb313c4aa5d5328b751abe6c9613;hb=HEAD">mydroid/device/samsung/crespo/liboverlay/overlay.cpp</a>

I changed the preview size to 8x16, and now the app doesn't crash on the Nexus S, although there's an unfortunate side effect: the preview is <em>more</em> visible than it was before --yes, it was visible. It was a 1x1 sized preview, and that's why it was failing on the Nexus S (and probably any other setup with that kind of surface size restriction). Now I need to find a way to hide it... oh wait, I found it! The answer, on the following post :P