Monday, 1 October 2012

An Android design flaw and how ADB saved the day

    My little cousins (5 years and 8 years old) love to play games on my Nexus One - Angry Birds is their latest favorite. However, they have their mid-term examinations going on, and as per their mother's request, I attempted to restrict their game time. Unfortunately, even the little 5 year old is tech savvy enough to unlock the simple slide-to-unlock screen. So, I had to resort to the pattern unlock, which is where the problems started.

    Usually, they bring the mobile to me to unlock, I unlock it if it's their break time from studying, and all goes well. Today, however, the little one today decided it was time to become a rebel and try to break the security. She kept on trying different patterns, even persisting through the 'Wait 30 seconds' message, while I was busy elsewhere. Finally, my Android had had enough, and said 'Too many pattern attempts', and asked for my Google login and password.

    Now again, I should have been able to give my username and password, set a new pattern and go on my way. However, there were two things combined to make things not so easy: my mobile had both GPRS data and WiFi turned off, and I had enable two-factor auth for my account. Because of the latter, my actual Gmail password did not work in the unlock page, and because of the former, even disabling two-factor auth in my Google account from my laptop made no change. I also tried a few other "solutions" given online such as:
  • trying the password 'null' (without quotes)
  • calling the mobile from some other number, accessing the notifications area from the incoming call screen, hoping you have some message or mail notifications, finding a clever way to go to the Settings screen from there (this one failed right at the beginning - the notifications area couldn't be opened from the incoming (or ongoing) call screen)
  • pressing the menu key repeatedly while the OS is booting up
    None of these were of any help, and I had at this stage started cursing Android for this poor design and even started thinking maybe an iPhone wasn't such a bad idea after all (blasphemy!).

    Finally, my incessant searching led to a forum post that linked to this post which started me on the right path. However, the stuff about factory reset at the end of it was pretty discouraging, and the method mentioned seemed pretty ugly too. I kept searching further, which led me to this page. Combining the info on these two posts, I was able to get my phone unlocked and breathe a sigh of accomplishment! These were my steps:
  1. I wasn't sure I had USB debugging enabled, but anyway tried connecting the mobile to my laptop. 
  2. I then went to the tools folder under my android-sdk-windows (I already had the Android SDK installed) directory in the Windows command line
  3. I tried the 'adb devices' command. Thankfully, it listed one device as currently attached. That meant USB debugging was enabled and adb could talk to my device
  4. Next, I opened the adb shell with 'adb -d shell', and the # prompt popped up
  5. Then, I opened the settings.db in sqlite as 'sqlite3 data/data/com.android.providers.settings/databases/settings.db'
  6. By this time, I'd come to know that the mobile_data setting that controls whether the device connects to GPRS data services used to be in the 'system' database table in old Android versions, but has moved to the 'secure' table now. I didn't know which table had it in my phone, so I first tried 'select value from system where name="mobile_data";'. This printed out my input itself, which I guessed to mean no such row in the table (bad design in SQLite here?)
  7. Now, I tried 'select value from secure where name="mobile_data";'. This time, it printed out 0, which meant mobile_data was in this table and was set to 0, thus disabling GPRS access. 
  8. I set the above value to 1 with 'update secure set value=1 where name="mobile_data";'
  9. I then finished it off with '.exit', then 'exit', then 'adb reboot'.
    When the device rebooted now, it had a GPRS data connection on and working. Phew. Now I tried my original Google password (since I had disabled 2-factor auth temporarily), the device checked it with the Google servers and deigned to allow me in. Yay!

    So, despite my complaints about Android and the iPhone fantasies, it's Android's hackability and openness that allowed me to find a solution much less onerous than a hard reset of the device. That, however, in no way excuses Android's poor design in this area; off the top of my head, one solution would be to special case the Internet access from this lock screen and enable data and WiFi when the username-password check fails once - there are probably much better solutions the fellas at Google could come up with, if only they paid a little attention to this. Also, there doesn't seem to be any option to increase the number of pattern attempts before Android pops this annoying page up - with there being 389112 distinct patterns, I'd gladly allow 100 attempts before assuming someone's trying to hack my mobile.

    My moral from this story has been to save the application-specific password of my mobile somewhere safe, and to always have USB debugging enabled in the mobile. What's yours?