OUYA: Auto-update early firmwares

My community OUYA server is working well, but every now and then a user on the OUYA chat server describes that he cannot get the OUYA working. Nearly every time a manual firmware update is necessary.

I investigated the issue; the earliest 1.2 firmware OUYA-1.2.667 can be setup without problems on my server. Then I went back to the first firmware that can be installed on a normal OUYA, OUYA-1.0.138 - and it failed. It turns out that it has a build property ro.update_url that points to http://ouya-updates.s3.amazonaws.com/updates-ouya_1_1.json, and that URL returns a link to domain cds.t2z5c2q6.hwcdn.net that does not exist anymore.

The solution was to modify my DNS server to respond to ouya-updates.s3.amazonaws.com, and my web server to deliver a modified updates-ouya_1_1.json file that links to the (still) working devs-ouya-tv-prod.s3.amazonaws.com domain. Automatic updates for firmwares 1.0.138, .158 and .193 work now flawlessly: At first they update to 1.2.1084, and then to the latest 1.2.1427.


Controller setup (firmware 1.0.138) Wifi setup (firmware 1.0.138) Downloading system update (firmware 1.0.138) Download finished (firmware 1.0.138) Preparing update (firmware 1.0.158) Your OUYA is upgrading (firmware 1.2.1084) Update available (main screen, firmware 1.2.1084) Discover unavailable because of system update (firmware 1.2.1084)


Technical notes I took while working on the problem in the four evenings:

Downgrade warning

When downgrading to an earlier firmware like v1.0.138 with OuyaCWMrecovery6.0.3.2.img, it asks you a question before rebooting:

ROM may flash stock recovery on boot. Fix?

You have to select "No" here; otherwise automatic firmware updates will not work. (The firmware update screen will show "OUYA" and a red exclamation mark)

Stock recovery menu

The OUYA stock recovery and firmware update mode only shows the "OUYA" logo and nothing else.

To see the menu, press "Home" (Pos1) on the attached keyboard.

Crash when trying to update

I modified the update-ouya_1_1.json file and then the OUYA framework crashed:

Unfortunately, OUYA Launcher has stopped.

adb logcat showed:

W/dalvikvm(  595): threadid=15: thread exiting with uncaught exception (group=0x40f44300)
E/AndroidRuntime(  595): FATAL EXCEPTION: AsyncTask #1
E/AndroidRuntime(  595): java.lang.RuntimeException: An error occured while executing doInBackground()
E/AndroidRuntime(  595): 	at android.os.AsyncTask$3.done(AsyncTask.java:299)
E/AndroidRuntime(  595): 	at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
E/AndroidRuntime(  595): 	at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
E/AndroidRuntime(  595): 	at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
E/AndroidRuntime(  595): 	at java.util.concurrent.FutureTask.run(FutureTask.java:137)
E/AndroidRuntime(  595): 	at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
E/AndroidRuntime(  595): 	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
E/AndroidRuntime(  595): 	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
E/AndroidRuntime(  595): 	at java.lang.Thread.run(Thread.java:856)
E/AndroidRuntime(  595): Caused by: java.lang.StringIndexOutOfBoundsException: length=4; regionStart=0; regionLength=-1
E/AndroidRuntime(  595): 	at java.lang.String.startEndAndLength(String.java:593)
E/AndroidRuntime(  595): 	at java.lang.String.substring(String.java:1474)
E/AndroidRuntime(  595): 	at tv.ouya.console.util.SystemUpdateUtils$VersionDetails.<init>(SystemUpdateUtils.java:385)
E/AndroidRuntime(  595): 	at tv.ouya.console.util.SystemUpdateUtils.isNewerFirmware(SystemUpdateUtils.java:368)
E/AndroidRuntime(  595): 	at tv.ouya.console.util.SystemUpdateUtils.checkForWaitingUpdates(SystemUpdateUtils.java:297)
E/AndroidRuntime(  595): 	at tv.ouya.console.launcher.settings.UpdateActivity$UpdateChecker.doInBackground(UpdateActivity.java:295)
E/AndroidRuntime(  595): 	at tv.ouya.console.launcher.settings.UpdateActivity$UpdateChecker.doInBackground(UpdateActivity.java:275)
E/AndroidRuntime(  595): 	at android.os.AsyncTask$2.call(AsyncTask.java:287)
E/AndroidRuntime(  595): 	at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
E/AndroidRuntime(  595): 	... 5 more
W/ActivityManager(  306):   Force finishing activity tv.ouya.console/.launcher.settings.UpdateActivity
V/DropBoxReceiver(  641): Starting service for tag: system_app_crash, time: 1621361557289
D/CrashReportService(  641): Writing crash report to: /data/user/0/tv.ouya/cache/.reports/1621361557289
D/OUYAOverlayMenu(  595): onResume called!
I/ActivityManager(  306): START {cmp=tv.ouya.console/.launcher.settings.UpdateActivity u=0} from pid 595

I had to de-odex and de-compile the source code to find the problem: updates-ouya_1_1.json had the wrong filename. The code searches for a dash "-" to extract the version from the filename, and it crashed because I had one too much :(

-      "filename": "OUYA-1.2.1084-r1.zip",
+      "filename": "RC-OUYA-1.0.158-r1_ota.zip",

Afterwards it still crashed because the json file gets cached. I had to manually delete the cached file via adb shell and reboot:

V/OuyaResponseCache( 1424): Cache dir: /data/user/0/tv.ouya.console/cache
D/OuyaResponseCache( 1274): Found file for: http://ouya-updates.s3.amazonaws.com/updates-ouya_1_1.json md5: 88f3212e1533496a9c6696ec49899be6

Written by Christian Weiske.

Comments? Please send an e-mail.