Thursday, January 3, 2013

Android Settings Reset Using ADB

I'm going to try updating my blog with all the random hacks I seem to end up doing.

I run CM10.1 nightly (Android 4.2.1) on my Galaxy SII and decided to mess with some of the developer options. After enabling "Simulate secondary displays" my phone locked up. So I reboot and it locks up again during boot... sigh...

Now there are lots of ways to recover from this in a brute force manner (reinstall the ROM, do a factory reset, etc), but I decided to try reverting the specific option using ADB.

First I installed the Android SDK to get access to ADB, then rebooted my phone into CWM recovery (hold volume-up, home and power). After CWM recovery booted I mounted the "/system" and "/data" filesystems from the menu. After this I tried running ADB on my PC, which gave:

C:\adt-bundle-windows-x86_64\sdk\platform-tools>adb shell
error: device not found

Crap! It can't find my phone. A few minutes of sanity checking revealed that I didn't have the proper Samsung USB Drivers installed (SAMSUNG_USB_Driver_for_Mobile_Phones.exe). After installing them I could finally get access to the ADB shell of my phone:

C:\adt-bundle-windows-x86_64\sdk\platform-tools>adb shell
shell@android:/ $

Now to figure out what I need to change, and how to change it. Luckily Android and Cyanogenmod are both open source, and a quick search of the code for "Simulate secondary displays" located this:
<string name="overlay_display_devices_title">Simulate secondary displays</string>
private static final String OVERLAY_DISPLAY_DEVICES_KEY = "overlay_display_devices";
String value = Settings.Global.getString(getActivity().getContentResolver(), Settings.Global.OVERLAY_DISPLAY_DEVICES);

So the "overlay_display_devices" global setting is the culprit! After a bit of searching I found that android simply stores all settings in the "" sqlite database. So resetting it should be pretty trivial. First I confirmed that I can actually see the value, and that it makes sense..

C:\adt-bundle-windows-x86_64\sdk\platform-tools>adb shell
shell@android:/ $ sqlite3 /data/data/
SQLite version 3.7.11 2012-03-20 11:35:50
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> select * from global where name="overlay_display_devices";

Okay, that looks sane! So hopefully just deleting that row and rebooting should work..

sqlite> delete from global where name="overlay_display_devices";
sqlite> select * from global where name="overlay_display_devices";

And... The setting is gone! And my phone boots into android again! Success!