4/02/2014

Quick & easy way to mount Google Glass onto eyeglasses

I recently got my Google Glass. I was very excited about the product and the future of head mount displays in general but a very practical problem arose as soon as I tried to setup the device: I wear prescription lenses and without them I cannot see anything on the Glass display.

After giving up the sophisticated idea of 3D printing some custom mounting parts, I had a hack solution: twist ties! (https://www.google.com/search?q=twist+ties the malleable metal wires that often appear around your new gadgets' charger/USB/headset cables)

I happen to have kept, or rather that I haven't thrown them out yet, some twist ties from my Kinect package: they are long and they have good-looking insulator skin. I imagine that the availability of such material should not be a problem for people owning electronic gadgets. I immediately anchored Glass onto my prescription frame with two of them. They worked terrifically since the first setup.

my eyeglasses with Google Glass mounted
To keep enough space between the lens and Glass, a little touch sensitive space (anterior to the anterior twist tie) is sacrificed. But I had no trouble using the touch pad between the ties.

details of the anterior twist tie

details of the posterior twist tie

I secured the first tie on the front piece instead of the tempo. This prevents my eyeglass from folding but that was okay for me.
I think this works nicely on my eyeglasses because the side is rectangular providing enough support. The malleability of the twist ties offer a lot of room for adjustment and experimentation. The other important thing is that this method does not damage Glass.

If you decide to try this, remember to twist the ties at the end to provide enough tension. And the usual disclaimer applies, this solution works for me and I believe that it works in general but I don't know if it will work in your case and I cannot be responsible for its consequences. So proceed with caution and common sense.

Update: you will need to detach Glass from its original frame first by unscrewing the Torx screw near the camera button (the screw stays in the socket afterwards as seen in the images).

10/17/2013

Fixing Galaxy Nexus's IMEI Number

I have been using Galaxy Nexus for quite some time and it worked fine as an everyday+development phone until its IMEI number got blocked on T-Mobile recently. If your IMEI number is 004999010640000 (you can see your IMEI number by dialing *#06#), then this post might help you restore your connectivity. It did for me: I got my GN off eBay long ago. It was a DoCoMo phone from Japan and it was unlocked with the F*ckDoCoMo app by the seller.

For the confused audience

You used Galaxy Nexus on T-Mobile (or other networks) and someday you found it suddenly stop to register onto the cellular network. After rounds of unhelpful customer service calls, you were told that your IMEI number (004999010640000) is blocked on the T-Mobile network (and possibly other networks too). Furthermore, the customer representative could do absolutely nothing about it (aside from filing an effectless unblock request). If you have a blocked IMEI other than the stated one, this post will not help: it does NOT teach you how to change to an arbitrary IMEI. Legality aside, software-based IMEI change on Galaxy Nexus seems to remain an unsolved problem (unlike some other phones). 

Solution

The gist of my approach is to restore the original, unique IMEI number (it is on the sticker on the back of your phone under the battery) from your phone's /factory/.nv_data.bak file. And if you do your backups right, you shouldn't lose any of your data. The usual disclaimer for hacking guides applies: It worked for me and I believe it works in principle, but I cannot guarantee that it will work for you and I cannot be responsible for any damage. 

The basic ideas/facts behind the solution are:
  1. /factory/.nv_data.bak (and maybe /factory/nv_data.bin too?) stores the system backup of your IMEI (and other information). Note since this file is hidden (its filename starts with a dot), you can only list this file by "$ ls -a"
  2. similarly /data/radio/nv_data.bin stores your current IMEI (and other information)
  3. both files store the IMEI in some non-obvious way. This prevents easy IMEI modification with a Hex editor. This is why we cannot just make up a new IMEI number for your GN, unlike some other phones which lacks such protective mechanisms.
  4. the android system uses salted md5 checksums stored in /factory/.nv_data.bak.md5 and /data/radio/nv_data.bin.md5 to detect tempering of the aforementioned files. We don't know how to generate these salted checksums but a glitch/oversight in ICS (Ice Cream Sandwich, Android 4.0.x) can effectively generate them for us: it logs an offending checksum along with its correct counterpart.
  5. if both nv_data files fail the checksum test, the android system will create a "default" /data/radio/nv_data.bin containing the infamous generic IMEI (along with the unlock status). In fact, F*ckDoCoMo app achieved unlocking GN via this side-effect of tempering nv_data and leaving the checksums out-of-sync. The nice thing is that the app does edit your /factory/.nv_data.bak in a sensible way so your phone will remain unlocked with this nv_data file.

If your /factory/.nv_data.bak has not been overwritten inadvertently -- that is a big "if" which can only be tested by experimentation --, then we should be able to recover your original IMEI by acquiring the correct checksum for /factory/.nv_data.bak

Instructions

(I assume that you are familiar with adb, fastboot, and other basic tools or can easily acquire such knowledge via the Web. Upon requests, I will edit this post to expand/clarify on any unclear steps. The XDA threads mentioned at the end are also helpful.)

0. backup your entire phone to /sdcard with the ClockworkMod recovery (CWMR) boot image's backup utility. In additon, as there is risk that you will lose your unique IMEI forever, you should carefully backup the entire /factory and /data/radio directories onto your laptop/desktop/cloud/etc. You can do that by $ adb pull.

1. install a rooted ICS-based ROM (root is probably not necessary since you can get that in CWMR, but it will make life easier), e.g. cm-9.0.0-maguro-stable from cyanogenmod. The glitch we rely on is fixed in later versions. (I tried JellyBean 4.2 and it was no good.)

2. (You will need root to do this and the following steps.) Take note of the content in /data/radio/log/nv.log
$ cat /data/radio/log/nv.log 
It should look something like this:
Thu Jun 28 19:54:08 2012: /data/radio/nv_data.bin does not exist.
Thu Jun 28 19:54:08 2012: MD5 fail. orignal md5 '672f544c3d4c3c4f5bc699966bac6210' computed md5 '3b93401f8fb129a51aba4e70a8b47fbb' (rild)
Thu Jun 28 19:54:08 2012: MD5 fail. orignal md5 '92d39f2375e581f8bd8095486c8758b1' computed md5 'a4bc620886c51f712caa377adf90cf24' (rild)
Thu Jun 28 19:54:09 2012: default NV restored.
Find the original md5 that is the same as /factory/.nv_data.bak.md5 (in my case, it is 92d39f2375e581f8bd8095486c8758b1) and then you should copy the computed md5 in the same line (so in my case, it is a4bc620886c51f712caa377adf90cf24). The computed md5 is the salted md5 checksum we want. FYI- The other set of md5's corresponds to /factory/nv_data.bin. You don't really need to worry about them unless .nv_data.bak is corrupted and nv_data.bin is not. Then you might want to try the process with /factory/nv_data.bin.

3. Remount /factory as read/write and then replace .nv_data.bak.md5 with the correct salted md5 checksum from last step.
$ mount -oremount,rw /factory
$ echo salted-md5-checksum > /factory/.nv_data.bak.md5

4. $ rm /data/radio/nv_data.bin*

5. $ reboot. Now /data/radio/nv.log should contain no new complaints about failed checksums and the IMEI should be restored to some non-generic number! (If you don't care about restoring your data or the ROM/Android version you were using, you are done now.)

6. restore your backup from /sdcard using CWMR. Note that /data/radio (but not /factory) is replaced by your restored backup, so your IMEI is the generic one again! 

7. Since we have the correct salted md5 checksum in /factory/.nv_data.bak.md5 to go with /factory/.nv_data.bak, you only need to remove /data/radio/nv_data.bin* and then reboot to let the system automatically restore from /factory/.nv_data.bak. Finally, after rebooting, you should see the same non-generic IMEI as what you saw in step 5, while having your phone restored!

If this works and you want to thank me, buy me a cup of coffee and/or follow me on twitter: @falcondai :)


Additional Resource

You can check whether your IMEI is blocked on T-Mobile: http://www.t-mobile.com/VERIFYIMEI.ASPX (004999010640000 is confirmed to be blocked. Such a generic IMEI should never get blocked... maybe someone reported their phone with that IMEI as stolen to T-Mobile?) This IMEI number seems to be a default for many Samsung phones.

According to some people on Reddit, this generic IMEI number was blocked on T-Mobile as early as 2013/2: http://www.reddit.com/r/Android/comments/17yizs/anyone_else_running_a_custom_rom_and_have_your/ But mine somehow managed to survive till recently, about one month ago, i.e. 2013/9. I called T-Mobile to add the generic IMEI number to my account explicitly after the first time it showed symptoms (likely back in February) and that solved the problem for me until it happened again.

My method is inspired mainly by these two threads on XDA:
http://forum.xda-developers.com/showthread.php?t=1606982 (very insightful post that spotted the glitch)

Most, if not all, software-based IMEI modification discussions/methods do not generalize and almost certainly won't help in the case of Galaxy Nexus due to obfuscation in nv_data. (If you find anything applicable, feel free to share them in comments.)

6/20/2013

666 and How Twitter Samples Tweets in Streaming API

After having played around with Twitter data for a while, I had a question: how Twitter samples the supposedly random tweets to send out through its sample streaming API?

I vaguely remember that it used to say "1% random sample" somewhere on the official documentation but I can no longer find that statement. So I decided to investigate the question by experiments. The result turns out to be far more fascinating than I expected (such as the appearance of 666).

This task would be trivial if I had firehose access but I do not. I initially thought of crawling tweets with ID's near the ones received in the stream sample and then do the counting. But I quickly found out how terribly inefficient that was: the tweet ids seem often to be very sparse. Then, thanks to Twitter's commitment to open source, I found their tweet ID generator on Github, wittily named snowflake (after a snowflake's large number of possible configurations, I suppose). In order to create a distributed solution to global unique ID generation, the essential idea of snowflake is to use timestamp and unique worker ID together to ensure uniqueness in an independent manner.

The first thing I noticed in snowflake is that whereas the 'created_at' property of the returned JSON tweet objects provides timing information at per-second resolution, one can recover per-millisecond timing information from snowflake! With this more precise timing information, some intriguing pattern emerges from the tweets in sample stream: within each second, all received tweets fall within a 10-millisecond-wide window. So we get 10/1000 = 1% of the millisecond timestamps which translates to roughly 1% of all tweets (assuming good randomness in tweet creation time) confirming the claim in my memory. But the surprise does not stop there, that sampling window is the same for every second! It is fixed exactly between the 657th and the 666th millisecond. So there is the 666 in the title. I wonder what is the story behind choosing 666 and this particular scheme of "random" sampling.

To make the post more complete, I should add that: 1. snowflake is used not only for tweet ID's but also direct message ID's. 2. before snowflake was activated sometime on 11/4/2010, Twitter used incremental ID's (the earliest existing tweet being 20).

To start playing with snow, you can use my little python module to create and melt a snowflake ID. (Indeed, you might soon find that not every tweet is delivered even in that 10 milliseconds window.)

If you find this interesting, leave a comment. We can also talk on twitter: @falcondai