分类目录归档:Android Rom

给 Android ROM(AOSP)集成 SuperSU 的方法

Published / by sickworm / 给 Android ROM(AOSP)集成 SuperSU 的方法有4条评论

本文实验配置:

ROM: AOSP Android-6.0.1_r77
设备:Nexus 5
SuperSU: SR5-SuperSU-v2.82-SR5-20171001224502.zip

SuperSU 官方下载链接:https://download.chainfire.eu/1220/SuperSU/

处理 SELinux

我们给 Android 编译 ROM 的时候,可以编译出带有 root 权限的版本。但是由于 Android 4.4 以上 SELinux 的存在,apk 还是无法获得 root 权限,这样很多 root app 都会提示无法获取 root,不能正常使用了。想要 apk 可获得 root 权限,有两种方法:

  1. 关闭 SELinux 监控
  2. 配置 SELinux 权限

由于方案 2 需要熟悉复杂的 selinux 权限模型,而且我在实验过程中按网上办法硬是配置不上 domain(提示我没有设置 domain。有可能是因为我没有清空输出物,但不确定),所以我最后使用了方案 1。办法是在 $YOUR_AOSP/device/$YOUR_RAND/$YOUR_DEVICE/BoardConfig.mk 中的 BOARD_KERNEL_CMDLINE := xxxx下方加上:

BOARD_KERNEL_CMDLINE += androidboot.selinux=permissive

这样就可以使 SELinux 不阻止你的操作了,permissive 只会打日志不会做实际动作,disabled 是完全关闭。注意加上这个后会通过不了 Google 的 CTS 测试,如果你是厂家的话需要注意这一点,个人开发者不需要关心。

当然,启动完成后进入 shell,以 root 权限执行 setenforce 0 也是可以达到关闭 SELinux 监控的效果。但每次重启都要设置一遍,比较麻烦。

好了,关闭 SELinux 了。但此时你用 apk 尝试获取 root 权限,发现还是不行。因为 AOSP 的 su 是只能 shell 或者 root 用的。解决办法是:

  1. 注释掉 system/extras/su/su.c 中 main 的一行 “not allow” 的代码,这行代码会判断 uid。注释后重新 make 一次 su 就能正常使用了
  2. 使用非 AOSP 的 su,SuperSU 提供的 su 需要配合 SuperSU 其他文件,不能直接用。

然后我发现改了 su 还是不行。。我猜测 framework 层可能还有权限处理机制,那我再给 rom 集成 SuperSU 授权管理,这样总可以了把。当然你也可以每次刷 rom 后重新刷一遍第三方 recovery,再刷一遍 SuperSU。这个集成我搞了 2 天才完成,网上资料不多,而且没一个能用。。

这里提一点,如果不搞好 SELinux,集成了 SuperSU 也是没法用的。如果你不想使用方案 2,我提供几篇文章以供参考:

Compile Android 5.1.1 ROM with ROOT by SuperSU

这篇没有配置 init.rc 里面的 service 的 SELinux domain。反正我不行。

init 启动 Native Service 时出现Service xxxx needs a SELinux domain defined; please fix 警告的说明
[Android][L][SELinux]Define a SELinux domain for Service

这 2 篇教你如何配置 SELinux domain。我配置完了还是说我没配置:“init 启动 Native Service 时出现Service xxxx needs a SELinux domain defined; please fix”。上面我也提到了,可能我没 clean/clobber 才失败的,如果你尝试成功了,不妨也告诉我。

实现 SELinux | AOSP

这是 AOSP 官方对 SELinux 的介绍,在这个问题里我没看到更多的信息。

集成 SuperSU

上面这篇文章Compile Android 5.1.1 ROM with ROOT by SuperSU 也提到了集成 SuperSU 的步骤。可惜日月变迁,现在 SuperSU 已经不是单一个 su 运作了。通过翻看 SuperSU 的指南 How-To SU,我得到几个信息:

  1. 最少需要这 4 个文件,就可以保证 SuperSU 正常运行:
    /system/xbin/su
    /system/xbin/daemonsu
    /system/xbin/supolicy
    /system/lib(64)/libsupol.so
    
  2. 需要在开机时执行 daemonsu --auto-daemon,启动守护进程。

  3. 执行 daemonsu --auto-daemon 时会调用 supolicy ,然后调用 libsupol.so。用于配置 SuperSU 的 SELinux 权限。

通过翻看 SuperSU 的刷 recovery 的包里的 update-binary.sh 我得到几个信息:

  1. daemonsu 和 su 是同一个文件

  2. 开机执行 daemonsu --auto-daemon 的方法有好几种,如果有 /system/int/init.d/ 这个文件夹(我没有)就放一个脚本进去,不然就是劫持 /system/bin/app_process(64),或是给 /system/放一个 install-recovery.sh。原文 Furthermore, daemonsu --auto-daemon needs to be launched somehow on boot. This is generally done via install-recovery.sh, 99SuperSUDaemon, or hijacking app_process([32|64]).

最后这条信息告诉我们 SuperSU 不需要关闭 SELinux 也可以使用,也告诉我们集成 SELinux 而不关闭 SELinux 的办法。方法 1 由于我手机没有,所以不用;2 劫持 app_process 那个是把 app_process 链接给了 su,具体我没看懂;3 install-recovery.sh 这个文件是刷 recovery 的时候会产生的,当系统启动的时候就会执行到它,刷完就会删掉这个文件。SuperSU 利用了这个特性,在 install-recovery.sh 里执行了daemonsu --auto-daemon,而且这个文件一直存在。因为执行 install-recovery.sh 对应的是 flash_recovery 的 SELinux domain,是已经配置好的。SuperSU 通过这三种方法来绕过 SELinux,然后再通过 sepolicy 来修改 SELinux 配置。

而我这边因为一直都是配置在 init.rc 里,且关闭了 SELinux,所以没有用到上面提到的方案。

集成步骤(在 Compile Android 5.1.1 ROM with ROOT by SuperSU 基础上修改)

  1. 删除原 su。文件位置 system\extras\su,最简单的方法是把该目录下的 Android.mk 重命名或者删掉。

  2. 添加 SuperSU 相关文件。包括上面提到的 4个 Linux 文件,和一个 SuperSU.apk。Linux 文件我选择在 packages 下新建了一个 su,放入上面那4个文件,以及创建 Android.mk。我比较懒,就没有做架构选择,就只把自己的 Nexus 5 对应的 armv7 包里的文件拷过来了,suinit 和 sukernel 不需要,复制一份 su 改名为 daemonsu。Android.mk 内容如下:

    LOCAL_PATH := $(call my-dir)
    
    include $(CLEAR_VARS)
    
    LOCAL_MODULE_TAGS := optional
    LOCAL_MODULE := su
    LOCAL_SRC_FILES := $(LOCAL_MODULE)
    LOCAL_MODULE_CLASS := EXECUTABLES
    LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
    LOCAL_UNSTRIPPED_PATH := $(LOCAL_MODULE_PATH)
    include $(BUILD_PREBUILT)
    
    
    include $(CLEAR_VARS)
    
    LOCAL_MODULE_TAGS := optional
    LOCAL_MODULE := daemonsu
    LOCAL_SRC_FILES := $(LOCAL_MODULE)
    LOCAL_MODULE_CLASS := EXECUTABLES
    LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
    LOCAL_UNSTRIPPED_PATH := $(LOCAL_MODULE_PATH)
    include $(BUILD_PREBUILT)
    
    
    include $(CLEAR_VARS)
    
    LOCAL_MODULE_TAGS := optional
    LOCAL_MODULE := supolicy
    LOCAL_SRC_FILES := $(LOCAL_MODULE)
    LOCAL_MODULE_CLASS := EXECUTABLES
    LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
    LOCAL_UNSTRIPPED_PATH := $(LOCAL_MODULE_PATH)
    include $(BUILD_PREBUILT)
    
    
    include $(CLEAR_VARS)
    
    LOCAL_MODULE_TAGS := optional
    LOCAL_MODULE := libsupol.so
    LOCAL_MODULE_CLASS := SHARED_LIBRARIES
    LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
    LOCAL_SRC_FILES := $(LOCAL_MODULE)
    OVERRIDE_BUILD_MODULE_PATH := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)
    include $(BUILD_PREBUILT)
    

    apk 我放在了 packages/apps/SuperSU,同样的,放入 Superuser.apk(上面的官方刷机包里有),同时创建 Android.mk,内容如下:

    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    
    LOCAL_MODULE := SuperSU
    
    LOCAL_SRC_FILES := Superuser.apk
    LOCAL_MODULE_CLASS := APPS
    LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
    LOCAL_CERTIFICATE := PRESIGNED
    
    include $(BUILD_PREBUILT)
    
  3. 把第 2 步添加的 packages 添加到编译路径中。我只给 Nexus 5 设备添加了(这样不好,因为第一步把所有设备的 su 都删掉了)。修改 $YOUR_AOSP/device/$YOUR_RAND/$YOUR_DEVICE/device.mk,添加:
    PRODUCT_PACKAGES += \
         power.hammerhead
    
    +# SuperSU
    +#PRODUCT_PACKAGES += \
    +#    su \
    +#    daemonsu \
    +#    supolicy \
    +#    libsupol.so \
    +#    SuperSU
    
  4. 添加相关文件权限。修改 system/core/libcutils/fs_config.c,寻找 “system/xbin/su”,修改:
    -    { 04750, AID_ROOT,      AID_SHELL,     0, "system/xbin/su" },
    +    { 06755, AID_ROOT,      AID_ROOT,     0, "system/xbin/su" },
    +    { 07777, AID_ROOT,      AID_ROOT,     0, "system/xbin/daemonsu" },
    +    { 06755, AID_ROOT,      AID_ROOT,     0, "system/xbin/supolicy" },
    
  5. 在 system/core/rootdir/init.rc 中添加服务:
    service console /system/bin/sh
         class core
         console
         disabled
    -    user shell
    -    group shell log
    +    user root
    +    group root 
         seclabel u:r:shell:s0
    
    service installd /system/bin/installd
         class main
         socket installd stream 600 system system
    
    +# SuperSU
    +service daemonsu /system/xbin/daemonsu --auto-daemon &
    +    class main
    +    oneshot
    +
     service flash_recovery /system/bin/install-recovery.sh
         class main
         oneshot
    
  6. 编译,刷进去。自此 apk 可通过 SuperSU 获得 root 权限!

存在问题

由于对 AOSP 不熟悉,文件放置不太讲究,不能迎合多设备编译的需求。

还有一个小问题,就是点击 SuperSU 进入主界面时会提示有新 SU 可用,可是我已经下载最新版本了。我估计因为这是最小系统,SuperSU 发现有些文件缺失所以做出提示。

此时注意:不可以点击 INSTALL!因为点击 install SuperSU 会把 install-recovery.sh 加到文件系统里,而我本来又在 init.rc 里写过一次启动了,这会导致多次启动 daemonsu,结果是系统起不来(也可能是别的原因,但至少可以确定的是当我没有在 init.rc 配置启动 daemonsu,而是手动更新的时候,此时点击 INSTALL 系统是能正常启动的)。如果用到 SuperSU 提到的那三种办法,估计就不会多次启动了。因为平时也不需要打开 SuperSU,我就不深究下去了,毕竟编译花时间。

版权所有,转载请注明出处:
http://sickworm.com/?p=367

下载 Android source code(AOSP)遇到的一些问题及解决方法

Published / by sickworm / 下载 Android source code(AOSP)遇到的一些问题及解决方法有1条评论

最近在搞 apk 爆破工程,经常需要调试别人的 apk,每次手动修改 apk 的 debuggable 属性比较麻烦,而且要有时候还不成功。所以还是一劳永逸,下载 AOSP ,把 ro.debuggable 打开,编一个 Nexus 5 的镜像给我手机用。关于 apk 调试的参考链接:https://www.0xaa55.com/technews/201602/00000215.html

建议使用清华镜像,免翻墙。教程链接:https://mirrors.tuna.tsinghua.edu.cn/help/AOSP/

下面是我在 windows 下,使用cygwin 下载官方 AOSP 时遇到的问题及解决办法:(在 windows 下载主要是为了方便我做别的事情,AOSP 官网上说 repo 只支持 linux 和 mac OS,cygwin 理论上也是支持的,但要填一些坑)

1. repo init 失败,request time out / 404

原因是没有翻墙。我使用的是 Proxifier + shadowsocks ,可以全局翻墙。 或者用普通的 VPN 也可以。网上方法是修改 repo 内容,增加 ss 翻墙配置的;也有修改镜像 url,改成国内的。我在 mac 上试过,部分链接还是被墙,没有成功。

2. 使用 cygwin 的 python 无法运行,报错 no module named site / no module named sysconfig / no module named fcntl;或者是 repo init 时 Get 完第一个之后没有预兆直接退出

这个问题可能是好几个原因造成的。首先,cygwin 是会继承 windows 的环境变量 PATH,所以 cygwin 可能会直接用你 windows 下配置的 python。这会带来几个问题:

  1. 直接输入 python 的 play ground 不能正常显示了(没研究具体原因)

  2. repo init 时提示 Get xxx.bundle 后直接退出。我跟了一下 repo 的代码,是 repo 构造 git clone 命令不对,其路径是 Windows 的路径,而不是 cygwin 的路径。

  3. 运行 repo init 时提示 no module named fcntl。上 google 查了一下,有回答说 Windows 没有 fcntl 这个 python 库。这个回答让我放弃了直接用 windows shell 运行 repo 的想法。(最后发现是存在的,不然 cygwin 也没办法运行 fcntl,因为 cygwin 不是 linux 虚拟机,本质也是 windows 的东西。因为网上说 Windows 没有 fcntl 放弃 windows shell,而尝试 cygwin 运行 repo,也是一个挺蠢的想法)

所以需要切换到 cygwin 的 python 。安装方法可以直接运行 cygwin 的 setup,搜索 python 下载。或使用 apt-cyg (需另外安装,网上有教程)执行 “`apt-cyg install python““。安装完成后还需要把 cygwin 的 $PATH 变量修改一下,把 windows 下的 python 路径剔除掉(我这里是 /cygdriver/d/Python27),否则还是会优先使用 Windows 下的 python。修改方法直接在 .bashrc 或 .bash_profile 下改就可以了。切换过来后,后还可能出现问题:

  1. 运行 python 报错 no module named site / no module named sysconfig

原因是 python 包路径错了,你可以输入 “import sys(回车)print sys.path “看一下。我这里就是莫名其妙多了当前目录的路径前缀。

解决办法是为cygwin 设置正确的路径,并写入环境变量 PYTHONPATH 中。我写的是/lib/python27.zip:/lib/python2.7:/lib/python2.7/plat-cygwin:/lib/python2.7/lib-tk:/lib/python2.7/lib-old:/lib/python2.7/lib-dynload

下面是我在 mac 下编译遇到的问题及解决办法:

首先官网上的环境准备要先做好,参考下面链接的 Setting up a Mac OS build environment 章节。防止意外,里面提到的 gmake 降级我都做了。
https://source.android.com/source/initializing

1. build/core/combo/mac_version.mk: Can not find SDK 10.6 at XXX

写这篇文章时 SDK 已经去到 10.12 了,而打开build/core/combo/mac_version.mk 一看,上面写着 supported versions 只支持 10.6 10.7 10.8 10.9。我直接在 supported version 上加了 10.12。结果遇到第二个问题。

2. desperate method XXXX

具体方法名字我忘了,说是 10.12 这个方法已经废弃了。那没办法,搜了一下 SDK 可以从网上下载。下载链接https://github.com/phracker/MacOSX-SDKs/releases

参考文章,教你如何放置 SDK 到正确路径:
http://www.jianshu.com/p/1513fc9e1a74

我看既然是找不到 10.6了,那就直接下 10.6 吧!结果出了第三个问题。

3. no member named llrintl / no member named llroundl

编译器说只有 lrintl 没有 llrintl。我跑去 MacOS SDK 里面看,有 llrintl,但是被宏控制着,因为其不是 C90 标准,需要加 -srd=c99 才可以。但要我找到调用编译的位置实在太麻烦了。

继续 google,有人说 10.11 10.9 都成功了,那我下一个 10.9放进去吧。结果还是提示找不到 10.6。

说好的 supported versions 呢?!我生气的吧 supported versions 中的 10.6 10.7 10.8 都删掉了,10.6 的 SDK 目录也删了,只留了一个 10.9。成功!

4. 切换分支时遇到:error.GitError: manifests rev-list (‘^HEAD’, ‘XXXXX’, ‘–‘): fatal: bad revision ‘^HEAD’

原因可能有好几个,我用了网上的方法都没有凑效。这个错误在我这里是 .git 的 HEAD 值丢失了,至于为什么我也不知道。这条语句的意思是:

在 manifests 这个 git 项目中执行 git rev-list ^HEAD XXXXX — 这个命令时,报错 fatal: bad revision ‘^HEAD’,即错误的版本 HEAD,意思是 HEAD 对应的 git 版本不正确。其中 manifests 这个工程在 .repo/manifests 中。 HEAD 对应的 git 版本存储在 .repo/manifests/.git/HEAD 中,这个 HEAD 文件的值为 ref: refs/heads/default。然后发现并没有 .repo/manifests/.git/heads/default 这个文件。解决办法:在其他目录重新 repo init 一次,把这个文件拷过来即可。

奇怪的是,我之前按照 http://blog.leanote.com/post/gyhlqq@gmail.com/Android-repo-sync-issue-fatal-bad-revision-HEAD-%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88 将整个 repo init 相关的文件都覆盖过去了,这个文件应该也复制过去才对,结果没有。

嗯。。我傻逼了,cp 命令的 src 为目录时,不是拷贝目录,而是把目录下的所有文件拷贝过去。还是推荐上面链接的做法,因为不止这一处会出问题,直接整个覆盖是最吼的。

版权所有,转载请注明出处:

http://sickworm.com/?p=346

【MT8382/8121】为MTK的工厂测试添加测试项

Published / by sickworm / Leave a Comment

摘要:

本文介绍添加MTK工厂测试项的步骤及调试技巧。

纲要:

1. 描述添加MTK工厂测试项的步骤

2.调试小技巧

1. 描述添加MTK工厂测试项的步骤

以添加红外测试为例:

 

1. mediatek/factory/inc/common.h

enum枚举添加ITEM_IR_TEST到最下面的ITEM_MAX_IDS上面,即倒数第2个;

 

2. mediatek/factory/inc/uistrings_chn.h

添加 #define uistr_ir_test “红外”;

这个字符串用于匹配factory.ini配置文件的测试项,只有两者一致的时候才会添加。注意这个文件是gbk编码。

unistrings.h是选择了英文才会使用,我们现在都使用的是中文,所以会匹配uistring_chn.h

 

3. mediatek/factory/src/factory.c

ftm_test_items[]添加item(ITEM_IR_TEST, uistr_ir_test);(在手动测试和单项测试中显示,必添加)

ftm_auto_test_items[]添加item(ITEM_IR_TEST, uistr_ir_test);(在自动测试中显示,尚不清楚机制,可选)

这两个参数就是步骤1 2添加的项目,名字要一致。

这里一般都会使用宏来控制是否添加,除非是都测的项目,以免运行出错。

 

4. mediatek/factory/src/test/ftm_irtest.c

添加ftm_irtest.c文件。实现ir_test_init(),  ir_test_entry()两个函数。函数名没有要求。具体实现参考ftm_rftest.c。(rftest是通过代码判断是否测试通过的,如果需要手动确认是否通过,参考ftm_otg.c。主要区别在entry函数)

ir_test_init()中需要调用ftm_alloc,这个会注册一个ITEM_IR_TEST相关的结构体。然后调用ftm_register,把ir_test_entry和这个结构体绑定。

ir_test_init()在factory初始化过程中会调用。

ir_test_entry()在项目被点击的时候调用。需要实现一些UI相关的绑定,以及具体的验证方法。通常会启动一个线程如ir_update_thread来测试,entry通过全局变量ir_factory检测测试结果。

 

5. mediatek/factory/src/test/ftm_mods.c

添加extern int ir_test_init();

在ftm_init_funcs[]的倒数第二个(NULL上面)添加ir_test_init。这样在factory启动的时候就会自动调用ir_test_init,从而将ITEM_IR_TEST测试项与ir_test_entry绑定起来。

至此,所有添加项都关联起来了。

 

6.mediatek/factory/Android.mk

将ftm_ir_test.c加进TEST_SRC_FILES中。

同样用宏控制是否添加,这里用到CVTE_IRREMOTE_APP_SUPPORT的宏来控制。

 

7.factory.ini

添加MenuItem=红外;需要和uistr_ir_test 名字一致,否则无法匹配。

这个文件会先去/sdcard目录寻找,再去/etc目录寻找,我们调试的时候直接放进sdcard目录就可以了。

 

8.mediatek/custom/active_1051j/factory/factory.ini

把修改的ini文件放入custom目录下,使用mk文件将其拷贝至/etc目录下。

custom的factory目录会存在factory.ini和factory_chn.ini两个文件。如果是中文,则把factory_chn.ini拷进去,并重命名为factory.ini;英文则直接拷贝。也可以只留一个factory.ini文件,里面是中文。factory程序只会解析名为factory.ini的文件

 

调试小技巧:

1. 烧录eng版本软件,打开USB调试。

2. 重启进入MTK工厂测试。

3. 需要烧录新factory程序的时候,push进/system/bin并chmod 777 /system/bin/factory。

4. 执行ps factory查询当前正在运行的测试程序,kill掉。

5. 在shell中输入factory重新启动MTK工厂测试程序。

6. 再次需要烧录新的factory程序的时候,ctrl+C即可停掉当前的factory程序,然后重新执行步骤3,5。 无需重启。

 

版权所有,转载请注明出处:

http://sickworm.com/?p=30 

【Linux驱动学习】SD卡规范学习

Published / by sickworm / Leave a Comment

摘要:

学习SD卡的相关规范,包括定义,硬件特性,数据传输,命令系统等。不涉及代码。

文章针对Linux驱动开发而写,以助于理解SD卡驱动,不会涉及过多硬件内容。

纲要:

1. SD卡介绍

2. SD卡硬件规范

3. SD卡指令规范

4. SD卡寄存器

 

1. SD卡介绍

1.1 各类型储存卡/接口

首先了解一下我们在SD卡驱动学习中会碰到的主要几个储存卡名词:

SD:Security Digital Memory Card,新一代多媒体储存卡,高速,安全(但安全机制貌似很少用到)
MMC:Multimedia Card,SD卡的上一代多媒体储存卡,已基本被SD卡代替
eMMC:Embedded Multimedia Card,内嵌式存储器,一般焊在PCB上。内置主控制器,以实现统一MMC接口(在传统MMC接口上拓展,集成了整套理论),Nand Flash就是eMMC
SDIO:Secure Digital Input and Output Card,SD标准上定义了一种外设接口,有很多设备模块采用。如Wifi,GPS,Bluetooth

1.2 SD卡特性

以下是SD卡的部分特性。

  • 正向兼容MMC卡:能插SD卡的接口也可以插MMC卡
  • 最大10个堆叠的卡
  • SD模式和SPI模式
  • 可变时钟(0~25MHz),可变电压(2.0~3.6V)
  • 带电插拔保护
  • 安全系统,双方认证和“新的密码算法”技术

更多的特性请阅读SD卡官方规范。

2. SD卡硬件规范

2.1 SD卡物理接口

下图是SD卡和MMC卡的针脚:

SD,MMC卡针脚

可以看到,SD卡在MMC卡基础上增加了8、9两个针脚,这两个针脚将被用作数据传输,以支持SD传输模式。SD卡支持SD模式(4数据线)和SPI模式(2数据线),MMC卡只支持SPI模式。

SD卡针脚对应的功能:(SD模式)

SD卡针脚对应功能

 

SD模式:数据并行传输,2地,1电源,1时钟,1命令,4数据线(4出入)(SD模式的命令通过命令线传输)
SPI模式:数据串行传输,2地,1电源,1时钟,1片选,2数据线(1入1出)(SPI模式的命令通过数据线传输)

以下内容,如无分开说明,默认指SD模式。(本文不会涉及SPI模式学习)

2.2 SD卡与主机的连接

SD模式和SPI模式中与主机的连接拓扑图如下:

image

在SD模式中,数据线和命令线是分开连接到主机各GPIO口中的。在SPI模式中,片选线分别连接到主机各GPIO口,数据线在同一条总线上。

因为SPI模式的数据线在同一总线上,所以需要片选来选择不同的储存卡;SD模式分别连接到主机,不需要片选线。

3. SD卡命令规范

3.1 命令类型

SD卡有数十种指令,但无非都是一些获取信息,数据传输的功能,并不会很难理解。规范书上有详细的状态转换图,下面会有介绍。

下面是4种指令类型:

  • 广播指令,无应答(代号bc):发送完此类命令后,并不会有反馈,但操作已经生效。
  • 广播指令,有应答(代号bcr):发送完此类命令后,SD卡会给予反馈。可能是一些寄存器信息,可能是
  • 寻址(点对点)指令(代号ac):发送完此类命令后,只有指定地址的SD卡会给予反馈(地址通过命令请求SD卡发布,是唯一的)。此时DAT线上无数据传输。
  • 寻址(点对点)数据传输指令(adtc):发送完此类命令后,只有制定地址的SD卡会给予反馈。此时DAT线上有数据传输。

3.2命令表

官方文档将命令分成了好几种功能。下面将所有命令列出,仅作查阅了解用,不需要每个命令都记住:

基础命令:用于重置、切换SD卡状态,获取相关信息

SD卡命令表class0

读块命令:读单个、多个块数据,设置块长度

SD卡命令表class2

写块命令:写单个、多个块数据,设置块长度

SD卡命令表class4

擦除块命令:把对应的块数据擦除

SD卡命令表class5

写保护命令:设置、取消对应地址的数据的写保护,可以使其他程序无法写入指定的地址,达到保护目的。用的情况不太多。

SD卡命令表class6

锁卡命令:设置、取消锁卡。锁卡后需要密码才能访问SD卡。

SD卡命令表class7

应用特殊命令:CMD55,使用ACMD前必须先发送的命令;CMD56是标准的读、写命令,会读、写一个block的数据。

SD卡命令表class8_thumb[1]

SDIO命令:预留给SDIO设备使用(CMD5也是预留给SDIO设备),在SD卡官方文档中没有说明具体用途

SD卡命令表class9

SD卡专用命令:MMC卡无法使用这些命令,里面包括如设置数据总线位宽,获取SD卡信息(寄存器)。

SD卡命令表ACMD1

SD卡命令表ACMD2

3.2 命令/数据传输方式

命令的传输协议大致如下:

  • 0开头,1结尾
  • 大端传输:先MSB,最后LSB
  • CRC校验

下面这幅图是无响应和无数据两种命令的传输情况:

SD卡命令传输方式(无数据传输)

非常清晰易懂,就不赘述了。

下面这幅图是多块数据读的数据传输情况:

SD卡命令传输方式(有数据传输)

主机发送多块读命令时,首先sd卡会做出回应,同时准备数据。数据准备完成后开始发送,并在每个block传输完成后加入crc校验码。传输完一个block和crc后紧跟着下一个block的数据传输,直到传输完成,或主机发送了新的命令。

SD模式有4根数据线,一次可以传输半个字节,两次一个字节。他们的传输方式如下图:

SD卡命令传输方式

同样是先传MSB,再传LSB,一次传半个字节,这样做可以方便主机做位移组合成一个字节。如果每条线单独传一个字节,则需要移位8次才可以获得一个完整的byte。

3.3 状态转换

下图为SD卡状态转换图。重新上电时为Idle状态:

SD卡状态转换图1

SD卡状态转换图2

看起来这个状态图很复杂,其实我们要走的流程并不复杂。Linux驱动对SD卡做初始化会经过如下步骤:

CMD0上电重置到idle状态(防止一些机型关机不掉电,如某些FPGA平台)->ACMD41获取SD卡支持的电压信息(还需要通过主机控制器设置电压)->CMD2获取卡商信息->CMD3请求SD卡发布相对地址->CMD9获取CSD寄存器,即卡的电气特性数据(需要使用SD卡相对地址)->CMD7通过相对地址选择对应的SD卡,该卡进入数据传输Transfer State状态->各种CMD进行block读写

3.4 流程差异

不同种类的卡初始化过程是不一样的,通过流程差异我们可以判断不同类型的卡。

SDIO:CMD0之后执行CMD5,CMD5只有SDIO类型才会有响应。

MMC:ACMD 41换为CMD1,ACMD类命令只有SD或SDIO卡才有响应。所以要先检测是否是SDIO,再检测是否是SD,最后检测是否是MMC(core层代码中也是这个顺序),否则会出现误判。

 

4. SD卡寄存器

SD卡一共有6个寄存器,我们用的对多的是CID(卡商信息),RCA(相对地址)和OCR(电压信息):

SD卡寄存器

CID:卡信息:生产商,OEM,产品名,版本,出产日期,CRC校验(所有寄存器都有,下同),常用
RCA:卡地址:在初始化时发布,用于与host通信,0x0000表示与所有卡通信,常用
DSR:驱动相关,总线电流大小,上升沿时间,最大开启时间,最小开启时间
CSD:数据传输要求:包括读写时间,读写电压最大最低值,写保护,块读写错误
SCR:特性支持,如CMD支持,总线数量支持
OCR:支持的电压,常用
SSR:特有特性,卡类型(OTP,SD等),一次擦除块数量
CSR:R1返回指令的卡状态,此寄存器用与传输卡状态给host

命令系统中有对应的指令获取这6个寄存器。

 

版权所有,转载请注明出处:

http://sickworm.com/?p=28 

Ubuntu Touch环境搭建

Published / by sickworm / Leave a Comment

最近搞了一下Nexus 5的MultiRom Manger,体验了一把Ubuntu Touch和Android L,总体感觉还不错,不过Android L的NFC驱动还有问题,Ubuntu Touch优化还不足,画面有点卡,而且无法关背光。于是萌生了参与Ubuntu Touch驱动开发的念头,也算是把工作当成一种兴趣吧。

Ubuntu Touch for Nexus 5是非官方的,官方的只有Nexus 4,7,10。我们从MultiRom Manager可以直接下载到for Nexus 5的最新版本。

鉴于中文博客中并没有相关教程,只能参照 Ubuntu Touch 环境搭建的官方文档:

https://wiki.ubuntu.com/Touch/Building

 

以下记录我搭建Ubuntu Touch的过程(跟着上面的wiki走)。

Building Ubuntu Touch Android pieces from source

Whether you want to build Ubuntu Touch for the currently supported Nexus devices or want to port it to a new target, you need to set up your working environment to build Android from source. This setup is more or less the same whether you are building AOSP or a project based on it such as CyanogenMod, SEAndroid or Ubuntu Touch.

If you are new to building Android sources you may want to check out this document and others in the Getting Started section on the Google documentation site, as it covers the basics and terminology of AOSP building. While Ubuntu Touch uses some helper scripts as detailed below, if will nonetheless be helpful to understand what is going on under the hood especially if you want to work on this part of the project.

http://source.android.com/source/initializing.html

For Ubuntu Touch, you can find all the needed Android git repositories at https://code-review.phablet.ubuntu.com/#/admin/projects/. This is basically a mirror of AOSP 4.4.2_r1, but containing only the needed low level services used by Android (e.g. no Dalvik at all).

For any Android related project on our git server, you’ll find a branch named phablet-4.4.2_r1. This branch contains a static known git HEAD and the required changes needed for Ubuntu, including our custom Android manifest.

从源码编译Ubuntu Touch的Android部分

无论你想编译现在已经支持的Nexus设备,还是想为一个新设备移植Ubuntu Touch,你都需要的搭建编译环境来编译Android源码。该教程大致和你编译AOSP(Android Open Source Project)或者基于AOSP的项目是一样的,如CyanogenMod,SeAndroid或者Ubuntu Touch。

如果你是第一次编译Android源码,你可能需要下面这个文档,和Google文档网站Getting Started章节上的其他相关文档,文档讲解了AOSP编译的基础和一些术语。在下面的环节中Ubuntu Touch会使用一些辅助脚本。如果你打算在项目上做相关开发,通过浏览这些文档你会更明白接下来的每一步是在做什么。

http://source.android.com/source/initializing.html

你可以在https://code-review.phablet.ubuntu.com/#/admin/projects/找到所有搭建Ubuntu Touch需要的Android git repositories(repo是一个多git项目管理工具,这个东西在天朝不稳定的网络中显得非常难用)。这是一个基于AOSP 4.4.2_r1的镜像,但只包含了低层Android运行所需要的服务(例如没有Dalvik)。

在我们的git服务器上任意一个Android相关的项目,你都会找到一个叫phablet-4.4.2_r1的分支,这个分支包含了一个git HEAD和包括custom Android manifest(Ubuntu Touch的repo的Manifest,包含了所有Ubuntu Touch的基础git项目)等对于Ubuntu需要修改的代码。(这段不太明白想说什么)

该段只是介绍,没有需要执行的部分。

Set up your development environment

At this moment we’re using the Android code base provided by Android AOSP.

Everything we take from Android is just C/C++, so you’ll notice that your Android build environment will be way smaller than when comparing to the traditional Android builds.

For development you can run any 64-bit Desktop version of Ubuntu between 12.04 LTS and 13.04.

It’s not strictly necessary, but it’s helpful to install ccache. (http://source.android.com/source/initializing.html#ccache in the general Android Setup guide should help with this.)

Additional packages which are used to build the host tools:

  • $ sudo apt-get install git gnupg flex bison gperf build-essential   zip bzr curl libc6-dev libncurses5-dev:i386 x11proto-core-dev   libx11-dev:i386 libreadline6-dev:i386 libgl1-mesa-glx:i386   libgl1-mesa-dev g++-multilib mingw32 tofrodos   python-markdown libxml2-utils xsltproc zlib1g-dev:i386 schedtool

On Utopic (and maybe other) the 4.8 version of g++ is needed:

  • $ sudo apt-get install g++-4.8-multilib

Before 14.04 Trusty you’ll also need to set up the tools PPA.

Then you need to install phablet-tools:

  • $ sudo apt-get install phablet-tools

This will also install the repo tool, used to sync the Android repositories. Learn more about the repo tool. If you already have a repo tool in your $PATH from previous android development, be sure to remove it or make sure it’s after the system repo command in the path. To check that the right repo command is used, you can issue $ which repo. This should return /usr/bin/repo.

You can check out the source code using the repo and git tools already familiar to Android ROM developers, as described here

https://wiki.ubuntu.com/Touch/AndroidDevel

Alternately, all the Android code can be downloaded using the phablet-dev-bootstrap tool provided by the phablet-tools package installed in the previous step. This tool is a Python wrapper around repo and used to also check out bzr repositories before all code was managed by repo and git. For the purposes of getting the source code for development it is no longer needed.

To get the code setup run:

  • phablet-dev-bootstrap [target_directory]

If for some reason the sync ends midway, you can continue the sync with the -c switch, so the command would be:

  • phablet-dev-bootstrap -c [target_directory]

Alternatively, if you are just building an image for an already supported device, you can specify the -v switch:

  • phablet-dev-bootstrap -v [device codenames] [target_directory]

The phablet-dev-bootstrap command will automatically use the repo tool with the Ubuntu Touch Preview custom manifest to download all the git repositories and needed data. Be aware that this step takes a long time and requires at least 15GB (plus 2-3GB for the binary output).

搭建你的编译环境

我们将使用Android基础组件(基于Android AOSP)来编译。

我们只会用到Android中的C/C++代码,所以你会发现你的编译环境会比传统的Android编译环境要小。

你可以使用Ubuntu 12.04LTS到13.04的64位桌面版来开发Ubuntu Touch。(博主使用Mint 14.04,基于Ubuntu 14.04)

我们可以安装ccache(ccache会加快Android编译速度),但不是必需的。(http://source.android.com/source/initializing.html#ccache Android配置向导会指导你如何安装)

我们还需要这些安装包来编译主机上的编译工具:

$ sudo apt-get install git gnupg flex bison gperf build-essential  zip bzr curl libc6-dev libncurses5-dev:i386 x11proto-core-dev  libx11-dev:i386 libreadline6-dev:i386 libgl1-mesa-glx:i386  libgl1-mesa-dev g++-multilib mingw32 tofrodos  python-markdown libxml2-utils xsltproc zlib1g-dev:i386 schedtool

在Utopic(Ubuntu 14.10)(或者其他)中,还需要安装g—4.8

$ sudo apt-get install g++-4.8-multilib

在Ubuntu 14.04稳定前你还需要安装PPA工具(只需要把“Add PPAs (pre Trusty only)”那一步执行就ok了。)

然后安装phablet-tools:

$ sudo apt-get install phablet-tools

这会安装repo工具,repo用于同步Android的repositories。 点击了解repo工具。如果你已经有了repo工具且已经在之前的Android开发中把执行路径加入到$PATH中了,请把repo删除,或保证在$PATH中repo的路径在系统的repo command的路径(如/bin/repo)之后。你可以使用$ which repo验证repo路径是否正确。如果正确,会返回/usr/bin/repo。

(这段还没弄清楚什么意思,因为我还没编译过,应该保证是/usr/bin/repo就可以了。到时候回来补充)

然后使用repo和git(只需要安装git,不需要实际执行,repo会调用git工具),从以下网址获取Android源码。这一步对于Android Rom开发者应该很熟悉。

https://wiki.ubuntu.com/Touch/AndroidDevel

(此链接会另写一篇文章,下载源码的工作都在这个链接中)

使用之前步骤已经安装了的phablet-dev-bootstrap,就可以一个个项目地下载所有的Android代码(大概可有640多个)。这个工具使用Python将repo封装了起来。在所有的代码被repo和git管理之前,这个工具也可以用于下载bzr repositories(和repo相似的一个管理工具)的工程。不过只用于获取开发用的源码的话,已经不需要这个功能了。

接下来让代码跑起来:

phablet-dev-bootstrap [target_directory]

如果发生某些错误导致sync中途停止了,你可以使用-c参数继续同步:

phablet-dev-bootstrap -c [target_directory]

如果你只是编译一个已经被支持的设备的烧录文件,你可以使用-v参数:

phablet-dev-bootstrap -v [device codenames] [target_directory]

phablet-dev-bootstrap命令会使用repo工具自动下载manifest(项目列表)然后下载所有的git项目和需要的数据。注意这个步骤要很长的时间,而且需要至少15GB(加上2-3GB的二进制文件输出)的空间。

 

版权所有,转载请注明出处:

http://sickworm.com/?p=21

Settings点击Location(位置)后右上角的开关button不会消失

Published / by sickworm / Leave a Comment

MT8121/8382平台:

 

前几天又遇到一个源码的bug。在10寸平板上,进入设置界面,点击Location(位置)项,右上角Title处会显示一个开关button,用来开关定位服务。但点完Location项再点其他项的时候,button并不会消失。直到你点到Developer(开发者选项),再点击其他项那个button才会消失。Developer项本身右上角也有一个开关button。

于是很自然地想到,在切换设置项时,Location页面在退出时没有把button去掉。

结果一看果然是。

 

--- a/packages/apps/Settings/src/com/android/settings/location/LocationSettings.java +++ b/packages/apps/Settings/src/com/android/settings/location/LocationSettings.java @@ -100,6 +100,9 @@ public class LocationSettings extends LocationSettingsBase super.onPause(); mValidListener = false; mSwitch.setOnCheckedChangeListener(null); +        getActivity().getActionBar().setCustomView(null);

 

版权所有,转载请注明出处:

http://sickworm.com/?p=19

Launcher3自定义壁纸旋转后拉伸无法恢复

Published / by sickworm / Leave a Comment

MTK8382/8121平台。

 

描述:将自定义图片设置成壁纸后,横屏显示时,旋转为竖屏,图片由于分辨率过小,会拉伸;再旋转为横屏,拉伸不恢复。

这两天正在解这个问题,研究了很久,走了不少弯路,最后发现是Launcher读取SharePreferences时的一个bug。

 

bug是这样产生的:

Launcher3设置完自定义壁纸(系统自带壁纸不会记录)的时候,会在com.android.launcher3.WallpaperCropActivity.xml中记录被设置壁纸的分辨率,并提交分辨率给WallpaperManager(通过suggestWallpaperDimension())。具体函数是:WallpaperCropActivity.java中的updateWallpaperDimensions(),它被WallpaperCropActivity.java的setWallpaper()调用;

Launcher3每次旋转后会重新执行onCreate(),同时会提交当前壁纸的分辨率给WallpaperManager,提交分辨率的函数在Workspace.java中的setWallpaperDimension()中。问题在这里:setWallpaperDimension()无法获取之前updateWallpaperDimensions()修改的SharedPreferences,导致它提交的是默认的壁纸分辨率1920×1080,从而导致低分辨率的壁纸拉伸。

解决此问题的方法是:修改Workspace.java中的setWallpaperDimension()中的getSharedPreferences()的flag,把MODE_PRIVATE改为MODE_MULTI_PROCESS。修改后成功访问。

 

我的问题是:

根据Android Developer的解释:

MODE_PRIVATE:

File creation mode: the default mode, where the created file can only be accessed by the calling application (or all applications sharing the same user ID).

即MODEL_PRIVATE只能被同一个application或者同一个userID的application调用。按这个说法,这两个Activity应该是可以共同访问的。(Workspace.java使用的是Launcher.java的context,两个Activity pid不一样,uid一样)

同时我还看了MODE_MULTI_PROCESS的解释:

MODE_MULTI_PROCESS:

SharedPreference loading flag: when set, the file on disk will be checked for modification even if the shared preferences instance is already loaded in this process. This behavior is sometimes desired in cases where the application has multiple processes, all writing to the same SharedPreferences file. Generally there are better forms of communication between processes, though.

This was the legacy (but undocumented) behavior in and before Gingerbread (Android 2.3) and this flag is implied when targetting such releases. For applications targetting SDK versions greater than Android 2.3, this flag must be explicitly set if desired.

意思是这个flag用于给拥有多个进程的application共同访问同一个SharedPreferences使用的。按照这个说法,似乎又确实应该使用MODEL_MULTI_PROCESS。

 

于是我想找到getSharedPreference实现代码,看看它怎么处理这几个flag。可恶的是,从Activity父类一级一级往上找,都找不到实现的方法,直到找到这篇文章:

http://blog.csdn.net/qinjuning/article/details/7310620

才知道ContextImpl实现了Context的具体方法,进而找到了答案:

ContextImpl类中有getSharedPreferences的实现。里面说明了在MODE_MULTI_PROCESS标志中,getSharedPreferences会进行reload。换言之MODE_PRIVATE不会重新读取SharedPreferences。

这里终于搞懂他的意思:在之前的bug,并不是SharedPreferences获取失败,而是因为没有reload所以没有获取到新写入的分辨率信息。因为之前没有注意到这个问题,所以走了弯路。

不过还有问题:每次Launcher旋转的时候都会重新启动Activity调用onCreate,为什么我getSharePreferences还是旧的呢?继续观察android.app.ContextImpl的getSharedPreferences:

@Override public SharedPreferences getSharedPreferences(String name, int mode) { Log.w("Launcher", "contextImpl: " + this, new RuntimeException("getSp").fillInStackTrace()); SharedPreferencesImpl sp; synchronized (ContextImpl.class) { if (sSharedPrefs == null) { Log.e("Launcher", "all init"); sSharedPrefs = new ArrayMap<String, ArrayMap<String, SharedPreferencesImpl>>(); } final String packageName = getPackageName(); ArrayMap<String, SharedPreferencesImpl> packagePrefs = sSharedPrefs.get(packageName); if (packagePrefs == null) { Log.e("Launcher", "package init"); packagePrefs = new ArrayMap<String, SharedPreferencesImpl>(); sSharedPrefs.put(packageName, packagePrefs); } // At least one application in the world actually passes in a null // name. This happened to work because when we generated the file name // we would stringify it to "null.xml". Nice.
if (mPackageInfo.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.KITKAT) { if (name == null) { name = "null"; } } sp = packagePrefs.get(name); if (sp == null) { File prefsFile = getSharedPrefsFile(name); sp = new SharedPreferencesImpl(prefsFile, mode); packagePrefs.put(name, sp); Log.e("Launcher", "new sp"); return sp; } Log.e("Launcher", "old sp"); } if ((mode & Context.MODE_MULTI_PROCESS) != 0 || getApplicationInfo().targetSdkVersion < android.os.Build.VERSION_CODES.HONEYCOMB) { // If somebody else (some other process) changed the prefs // file behind our back, we reload it. This has been the // historical (if undocumented) behavior.
sp.startReloadIfChangedUnexpectedly(); Log.e("Launcher", "reload"); } return sp; }

里面Log.e(“Launcher”, …);是我自己加的调试信息。首先会判断sSharedPrefs是否有内容,然后从中获取对应package的prefsFile。如果sSharedPrefs找不到,才从xml文件中重新读取。最后加了一个判断,如果设置了MODE_MULTI_PROCESS变量,或者Android 2.2以下的系统,会默认从xml文件中重新reload,以保持最新的SharedPreferences数据。

注意这里的sSharedPrefs变量,它只在getSharedPreferences中有赋值,也就是说SharedPreferences的数据一直跟随着ContextImpl实例走,只从getSharedPreferences()方法中获取数据。也就是说,当旋转屏幕的时候,我们调用getSharedPreferences()获取的数据都是从这个sSharedPrefs变量中取出来的。实际从下面Log信息也可以看到,旋转并不会有”new sp”的Log打印,只有对Launcher3在设置中force stop和clear data的时候才会出现”new sp”。

旋转的Log提示:

09-11 08:47:19.599: E/Launcher(4628): launcher:com.android.launcher3.Launcher@42392ac8 09-11 08:47:19.599: E/Launcher(4628): mBase:android.app.ContextImpl@424c1898 09-11 08:47:19.608: E/Launcher(4628): old sp 09-11 08:47:19.727: E/Launcher(4628): old sp 09-11 08:47:19.731: E/Launcher(4628): reload 09-11 08:47:19.932: E/Launcher(4628): old sp

force stop的提示:

09-11 08:48:29.456: E/Launcher(5271): launcher:com.android.launcher3.Launcher@4238f220 09-11 08:48:29.456: E/Launcher(5271): mBase:android.app.ContextImpl@42391ab8 09-11 08:48:29.489: E/Launcher(5271): all init 09-11 08:48:29.489: E/Launcher(5271): package init 09-11 08:48:29.493: E/Launcher(5271): new sp 09-11 08:48:29.679: E/Launcher(5271): new sp 09-11 08:48:29.766: E/Launcher(5271): old sp 09-11 08:48:29.767: E/Launcher(5271): old sp 09-11 08:48:29.790: E/Launcher(5271): old sp

里面三个连着的old sp,只有第二个是读取分辨率的,其他两个分辨是LauncherAppState的SharedPreferences。因为此时Launcher3代码已经被我修改为MODE_MULTI_PROCESS,所以旋转会打出”reload”信息。

 

也就是说,旋转的时候sSharedPrefs的值是一直保存着的。可是通过Log打印信息,我们发现,每一次的getSharedPreferences()的contextImpl都是不一样的!

这里要注意的是,执行方法的context是Activity的父类ContextThemeWrapper的mBase私有成员执行的,获取mBase可以在getSharedPreferences()中打印this出来,也可以在Activity中进行反射,这里用的是反射方法:

try { Log.e("Launcher", "launcher:" + this); java.lang.reflect.Field f = Activity.class.getSuperclass().getDeclaredField("mBase"); f.setAccessible(true); Context s = (Context) f.get(this); Log.e("Launcher", "mBase:" + s); } catch(Exception e) { e.printStackTrace(); }

contextImpl不一样了,但是sSharedPrefs数据还保存着,且sSharedPrefs不能通过其他方法赋值,只能猜测在旋转的时候通过原型模式把原来的context传进去了。Launcher3的旋转处理,我只找到ACTION_CONFIGURATION_CHANGE这个广播,但是我把里面的代码注释了,依然可以正常工作。估计是更底层的代码控制的。

 

具体代码还没找到,因为还要搬砖。有空再研究吧!

版权所有,转载请注明出处:

http://sickworm.com/?p=17

Launcher3无图标问题

Published / by sickworm / Leave a Comment

 

MTK8382/8121平台。

 

机器(8寸,默认竖屏)第一次烧录完成后,以横放姿势启动,发现Launcher没有图标,而竖屏启动是没有这个问题的。在测试过程中发现,在设置中clear data后也会有这样的问题。因此可以初步判断是database初始化的问题,因为database存储着favorite icon和workspace的数据。

对比database,发现workspaces字段没有写入。查看输出的log,发现最大的不同在于,在step1的初始化过程中,出现了

setApplicationContext called twice!old=com.android.launcher3.LauncherApplication@41c76888 new=com.android.launcher3.LauncherApplication@41c76888

的warning。查找warning输出的位置,发现在onCreate中。也就是说在初始化过程中,Launcher3 onCreate了两次。

 

我们知道,为了重新布局,Launcher每次转屏都会重新onCreate的。而以横屏摆放启动,会导致在默认竖屏的状态下,很短时间内又进行了一次转屏。

看了一下AndroidManifest.xml,发现android:screenOrientation属性是nosensor,所以每次启动都是默认(竖屏)。改为sensor后,第一次初始化方向和实际方向一致,则不会出现执行两次onCreate()的情况。

 

在LauncherModel.java中,搜索“step 1”,可以找到初始化workspace的过程。而恰恰这个workspace初始化没有被synchronized保护起来。导致初始化database的过程中产生冲突,从而导致写入失败。

版权所有,转载请注明出处:

http://sickworm.com/?p=15

【MT8382/8121】使用绝对路径编译模块会导致recourse_overlay无法应用的问题

Published / by sickworm / Leave a Comment

 

之前为了方便mm模块编译,写了个脚本,实现了在任意模块其子目录下执行脚本即可编译的功能。

其实原理就是一层一层目录地往上寻找Android.mk文件,找到存放Android.mk目录后,就把该目录当作./mk mm 的目录参数。

(脚本现在还有点bug,等改好再放上来,以免误人子弟)

这里我犯了一个错误,我获取目录参数的使用的是pwd,也就是绝对路径。大家使用mm命令都是用相对路径,不会无聊打绝对路径上去的。这导致了一个问题,我编译出来的Launcher3.apk没有添加recourse_overlay中的壁纸,只有1.4M左右。由于mm.log中是没有相关信息的,导致发现的过程比较曲折。

后来发现overlay记录是在AppAssets_Overlay.log中,但是里面记录的东西都是重复的,没什么价值。

版权所有,转载请注明出处:

http://sickworm.com/?p=13

Android源码的BUG

Published / by sickworm / Leave a Comment

 

在Android系统移植过程中,遇到很多源码上的BUG。但是我们看到市面上都是没有这些问题的。难道这些BUG在每个开发商都要经历一次解BUG的过程吗?Android释放的源码是否是最新的?暂时没有想法。仅在此记录我遇到的Android源码上的BUG。

 

MTK8382/8121:

1、Launcher3无图标问题

 

2、Launcher3自定义壁纸旋转后拉伸无法恢复

 

3、Settings点击Location(位置)后右上角的开关button不会消失

 

 

版权所有,转载请注明出处:

http://sickworm.com/?p=11