2013年7月8日 星期一 晴

日本人事情很多,过个Android CDD还要求那么多,我不得不帮他们改了很多。周日在家里看了半小时代码,没有设备和Log,想了半天unique deviceid,今天终于搞定了。

在CTS Report中,有一项是deviceid,Google要求这一项是一个独一无二的值,我看了Google给客户的文档(客户是OHA的成员),如果非手机设备,这个数值应该是独一无二的harewareid,我看了一下代码,这应该是ro.serialno。

如果是上层代码,APK可以调用ANDROID_ID,这应该是一个独一无二的值,基于ro.serialno的,ro.serialno一定要设置。 String androidId = Settings.System.getString(getContentResolver(), Settings.Secure.ANDROID_ID);

现在的问题是:方案商提供的ro.serialno是空的,我怎么去写一个呢? 写一个很简单,在/system/core/init/init.c或者/build/tools/buildinfo.sh那里写死就好了。

客户提出了新的要求:必须是unique deviceid。 我尝试了下面的方法:

  1. 在/system/core/init/init.c里,用srand(),rand()试图产生随机数,把随机数填入ro.serialno中。 结果:每次生成的随机数都是一样的。 结论:srand的种子都是一样的,就算是用时间作为种子,开机时间都是一样的,而随机数的本质是从一个超长的队列里取出来的而已,并不是真正的随机数。此方法行不通。

  2. 尝试在Java层面修改,比如在Framework收到bootupcomplte的地方,尝试写ro.serialno。 结果:ro.serialno,看不到了。写ro.serialno紧跟着的log也没能打出来。 结论:ro.serialno只能在第一次bootup的时候写,ro值只能写一次,后面再写也不会生效了。在init.c里,我记得好像是先去处理init.rc再去处理property的,可能那时候没处理,就没有加入property的初始化,所以缺失了。后面我再了解一下,能不能补加入到property里。

  3. 对比代码,我看高通和MTK都是在/system/core/init/init.c里写的ro.serialno。MTK是读/sys/下面的一个值,这个值应该是读芯片ID(高位和低位)转化而来的,所以独一无二。高通的是原版的android代码,应该也是从底层传来的,具体我就没仔细看了。

  4. 从这家芯片提供商找一个独一无二的ID出来,比如CPU ID、GPU ID。结果,他们一如既往地没有回应。我看了一下代码,果然没有,他们的CPU serialno也是用随机数算法算出来的。cat /proc/cpuinfo一看,CPU serialno果然也是完全相同的数字。 让他们评估开发,他们评估说要一周。我等不及了,只能自己干了。

  5. 审查/system/core/init/init.c,可以看到原生Androidro.serialno是通过/proc/cmdline传过来的。

思路那就是倒推过来: (1)连接adb,cat /proc/cmdline,看打印出什么字符串。

(2)拷贝打印的部分字符串,grep -rn “***” .,搜索uboot的源码,找到定义的bootargs。下面是我从我本地虚拟机取到的一段。 console=ttyS0,115200 pmem=0xb1800000 root=/dev/mmcblk1p2 rw rootwait mem=792M init=/init video=nusmartfb:1280x720@60 wifiethaddr=

(3)在bootargs里添加serialno的字段,测试发现有效,接下来就在这里传一个独一无二的值过来就可以了。

(4)哪里去获取这个独一无二的值?产线上刚好有写SN号和MAC地址,我找到一个地方,写代码读取到了SN号的内容,问题解决。这句话说起来轻描淡写,但还是求了芯片厂商要要来的读哪里的地址以及SN号的数据结构的。

  1. 生产时要保证下面流程: 贴片 –》 烧录 –》 写SN号 –》 第一次开机 也就是说,必须在第一次开机之前写SN号。