MIB Lotus worknote

来源:互联网 发布:四维彩超的数据看性别 编辑:程序博客网 时间:2024/05/29 13:20

Test CDF: http://repository.scsstage.sonyericsson.net/TestCDA/Internal/Dev_i/ST25i/20111107082543_Test.zip
http://www.gnu.org/software/gdb/
https://wiki.sonyericsson.net/androiki/GDB_debugging

http://flashtools.sonyericsson.net/viewtopic.php?t=711 //FG2 Install
http://flashtools.sonyericsson.net/viewtopic.php?t=1442 //FG3 Install


每天代码更新编译连接 
http://androidswrepo-cnbj.sonyericsson.net/pool/semc/b/build-metadata/
http://androidswrepo.sonyericsson.net/pool/semc/b/build-metadata/
http://android-ci-platform.sonyericsson.net/view/CM/job/daily_build_ginger-ste-dev/379/artifact/result-dir/
http://cgit.sonyericsson.net/cgit.cgi
http://opengrok.sonyericsson.net/ 查看代码的历史和改动的DMS等
http://rassist.sonyericsson.net/relcheck/v4/relcheck.pl  //如何获取两个版本之间的差异,这个比较好用
https://wiki.sonyericsson.net/androiki/CM_information_of_eDream_6_Series //查看代码的repo 路径
http://focalpoint.sonyericsson.net/fp/servlet/Login?file=/login/loginOk.jsp //可以查看FPxxxx的具体信息,该网站列出了所有的Feature 开发等详细情况
https://wiki.sonyericsson.net/androiki/CM_information_of_eDream_6_Series  //可以查看所有代码分支的下载路径
https://wiki.sonyericsson.net/mib/Debuggy

repo init -u git://review.sonyericsson.net/platform/manifest.git -b ginger-ste
repo init -u git://review.sonyericsson.net/platform/manifest.git -b edream6.0-fuji-r2-release //下载Aoba代码,6.0.C.1.XX
repo init -u git://review.sonyericsson.net/platform/manifest.git -b ics-riogrande //下载ics 代码,具体参考https://wiki.sonyericsson.net/androiki/Rio_Grande_1.1
repo init -u git://review.sonyericsson.net/platform/vendor/semc/ramdump-manifest -b <branch> //下载对应branch的ramdump代码

FG3中设置window->preferences->flash gordon 3->flash->debian-sacco->default build action-> build immediately(这样image文件可以保存到本地,default 是add build item)

一、PDP backlight cannot work
1. ADB Command: /sys/class/leds/lcd-backlight/brightness ,实际路径/sys/devices/i2c-0/2-0040/leds/lcd-backlight
    echo 0 > brightness \n
    echo 100 >brightness
    cat brightness
2. Check system/core/rootdir/init.rc 关于lcd-backlight的权限是否设置正确
3. Check LCD_BACKLIGHT driver: /kernel/drivers/leds/leds-as3677.c (wrong: ./drivers/leds/leds-lm3530.c, 和./arch/arm/mach-ux500/leds-lotus.c)
4. Check PDP schematic(Circuit_Diagram_1243-3693_4_2.pdf),LCD backlight 的供电 BMU_DCDC_OUT,发现 Keypad_backlight和LCD backlight共用 一路电源,而实际Lotus的硬件设计是没有Keypad_backlight的,估计会彼此有影响。导致LCD backlight的控制不正常。
5. Check /kernel/arch/arm/configs/semc_lotus_defconfig, 定义了 CONFIG_LEDS_AS3677
6. Check /kernel/drivers/leds/leds-as3677.c, LCD backlight电源供电芯片 的驱动
7. Check Lightsensor 初始的设置, ./device/semc/riogrande_pdp/files/hw_config.sh, hw_config.sh 设置了部分硬件设备的初始状态。 hw_config.sh会在projectname.mk中拷贝到system/etc,然后在init进程中分析执行init.semc.rc,从而完成硬件的初始化
8. Check Lightseneor 是否调整为自动背光,用ADB 查看/sys/devices/i2c-0/0-0040/leds/lcd-backlight/als/enable (mogami平台), /sys/devices/platform/nmk-i2c.2/i2c-2/2-0040/(Rio Grande平台)
[
开机阶段 外围硬件参数设置: 只是针对mogami平台
    1). mogami.mk 中如下设置把 文件拷贝到system
        PRODUCT_COPY_FILES += \
            device/semc/$(TARGET_PRODUCT)/files/hw_config.sh:system/etc/hw_config.sh \
            device/semc/$(TARGET_PRODUCT)/files/pre_hw_config.sh:system/etc/pre_hw_config.sh

    2). init.mogami.rc中 启动设置/dev/block/vold/179:33 /mnt/usbdisk vfat rw,
        service hw_config /system/bin/sh /system/etc/hw_config.sh
            user root
            oneshot
]
9. ADB /dev/block, /proc/partitions, /proc/mounts, df 可查看分块信息
10. 用 adb root 首先获取adb root权限(root权限重新启动 adb的守护进程),然后就可以adb remount, 从而可以自由操作系统文件了。
11. Android 不同partition 之间不能 移动文件,会出现Cross-device link错误, 比较好的方法是通过 /sdcard 来中转移动。
12.每天代码更新编译连接
http://android-ci-platform.sonyericsson.net/view/CM/job/daily_build_ginger-ste-dev/379/artifact/result-dir/
13.更新s1boot 和重新创建 ta, 重新flash,手机可以启动了,但system crash.
14.修改AS3677 chip(LCD backlight的供电),设置固定的curr1或curr6回路。
15.修改 待机时间 frameworks/base/services/java/com/android/server/PowerManagerService.java
    private static final int DEFAULT_SCREEN_OFF_TIMEOUT = 15000;
然后查找DEFAULT_SCREEN_OFF_TIMEOUT ,系统读取该值得地方,直接赋值即可; 实际上所有setting的default value都保存在frameworks/base/packages/SettingsProvider/res/values/defaults.xml
另外还可以直接修改其数据库文件,如下
    adb shell
    cd /data/data/com.android.providers.settings/databases
    sqlite3 settings.db
    select * from system where name = 'screen_off_timeout';//; 很重要,必须有
    update system set value='-1' where name='screen_off_timeout';
或者     sqlite3 /data/data/com.android.providers.settings/databases/settings.db  "UPDATE system SET value='-1' WHERE name = 'screen_off_timeout'";
    sqlite3 /data/data/com.android.providers.settings/databases/settings.db  "SELECT * FROM system  WHERE name = 'screen_off_timeout'";
    对其数据库操作的代码位于/frameworks/base/packages/settingprovider/src/com/android/providers/settings/databasehelper.java;
17. [JAVA APP层] 位于/packages/apps/Settings/src/com/android/settings, 其中BrightnessPreference.java 有函数setBrightness(int brightness)-->power.setBacklightBrightness(brightness);
18. [JAVA Framework层 ManagerService]frameworks/base/services/java/com/android/server/PowerManagerService.java,中有函数setBacklightBrightness-->mLcdLight.setBrightness(brightness); mLcdLight会在init()函数中赋值mLcdLight = lights.getLight(LightsService.LIGHT_ID_BACKLIGHT);
19. [JAVA Framework层Service] framework/base/services/java/com/android/server/lightsservice.java 中( LightsService.Light).setBrightness-->setLightLocked-->setLight_native
20. [JAVA Framework层Native] frameworks/base/services/jni/com_android_server_lightsservice.cpp 中有init_native--> hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (hw_module_t const**)&module)-->load(id, path, module);其中path指向lights.st-ericsson.so;和setLight_native
21. [HAL 层]/vendor/semc/hardware/lights/lights_core.c; 中函数leds_core_init-->get_link_table
22. [HAL 层]/vendor/semc/hardware/lights/hw/as3677.c中有as3677_set函数-->set_simple-->write_int
23. [HAL 层]/vendor/semc/hardware/lights/utils.c中有函数write_int-->write_str-->write_to_path-->write
24. [HAL 层]/vendor/semc/hardware/lights/illumination_service.c; 会被编译成BUILD_EXECUTABLE,可执行程序会最终放在 手机/system/bin/illumination_service; 利用init.st-ericsson.rc 中service illumination /system/bin/illumination_service 启动,其中的main函数会一直读取文件 #define soc_path "/data/lightservice.soc"的内容,通过该读写文件进行数据传递
25. [HAL 层]/vendor/semc/hardware/lights/lights_module.c; 中函数open_lights会设置好set_light(该函数会向文件/data/lightservice.soc 写入内容)
26. [HAL 层]在vendor/semc/hardware/lights/Android.mk中,有Build HW lib module部分,把lights_module.c编译成LOCAL_MODULE := $(SEMC_CFG_LIGHTS_MODULE_NAME),其中SEMC_CFG_LIGHTS_MODULE_NAME在device/semc/lotus/lotus_cfg.mk中定义为SEMC_CFG_LIGHTS_MODULE_NAME := lights.st-ericsson,所以最后Build 的HW lib module 位于手机/system/lib/hw/lights.st-ericsson.so;
27. [HAL 层]HAL 是如何被调用的 hardware/libhardware/include/hardware/hardware.h [中注释 Every hardware module must have a data structure named HAL_MODULE_INFO_SYM and the fields of this data structure must begin with hw_module_t],还定义了#define HAL_MODULE_INFO_SYM HMI
28. [HAL 层]hardware/libhardware/hardware.c中有函数hw_get_module(const char *id, const struct hw_module_t **module),负责得到对应的硬件模块,其中 id 是关键,通过id 会找到对应的hw module, 例如 backlight 的id 是#define LIGHTS_HARDWARE_MODULE_ID "lights" 在/hardware/libhardware/include/hardware/lights.h被定义,hw_get_module函数会在com_android_server_lightservice.cpp中调用
29. [HAL 层]/device/semc/lotus/lights/leds.c 中as3677_led as3677_lcd,并且定义了关联到"/sys/bus/i2c/drivers/as3677/2-0040" ,还关联了as3677_set函数, 这些都靠get_link_table 初始化

30. [HAL 层]static struct sw_led lcd_backlight_led@vendor/semc/hardware/lights/leds_android.c 和static const struct led_link link_table[]@vendor/semc/hardware/device/huashan/lights/leds两者如何关联?
 struct sw_led lcd_backlight_led:表示的是抽象的LED
 struct led_link link_table: 表示具体的driver node
 android_leds_init@vendor/semc/hardware/lights/leds_android.c 把两者关联起来了

31. [Kernel 层]关于backlight的kernel driver在 kernel/drivers/leds/leds-as3677.c --> as3677_set_led_brightness 和led-class.c-->led_class_attrs[]

32. User Space如何调用到kernel Space, 比如操作 /sys/class/leds/lcd-backlight/brightness,用户空间可以直接写入该文件值,然后产生系统调用的软中断(0x80)exception: ret_fast_syscall(asm)->sys_write->vfs_write->sysfs_write_file->dev_attr_store->led_brightness_store->as3677_set_led_brightness

二、SP ADB 不能工作/devices/sdi3/mmc_host/mmc3/mmc3
1.*#*#service#*#*(*#*#7378423#*#*), adb wait-for-device logcat
2.在FG3上读一下miscTA,GDFS-TA-->Partition(Misc TA)-->Unit(2301); 看看2301的值是多少,应该后4Byte 都是0
12. USB 不能识别成ADB,查看lsusb,识别成了Bus 002 Device 068: ID 0fce:d14c Sony Ericsson Mobile Communications AB; 再分析kernel/arch/arm/mach-ux500/board-rio-grande.c,中static int __init startup_reason_setup(char *startup),有如下代码,所以识别成了GG 设备,注销如下代码即可
    #ifdef CONFIG_USB_ANDROID_GG
            if (startup_reason & STARTUP_REASON_INDUS_LOG)
                init_usb_gg();
    #endif
用lsusb正确识别成了:Bus 002 Device 073: ID 0fce:9146 Sony Ericsson Mobile Communications AB

三、拨打电话进入界面失败(后来进入界面后找不到网)
1. vendor/semc/packages/apps/phone/src, 平台默认的java应用代码在该目录下
2. vendor/semc/packages/resources/uxp/res/drawable,平台默认的资源在该目录下
3. 更换打电话的apk(用Google自带的Phone.apk): 首先 改名/system/app/SemcPhone.apk 为SemcPhone.bak;在adb remount, adb push Phone.apk 到/system/app/目录下
4. 拨打电话不通, 重新flash SIM Lock和IMEI(HW Config),在FG3 Flasheable items 中选择即可,注意一定要输入可用的IMEI
5. 用AT Command 不能打电话是由于,AT CMD 拨打电话的流程还是调用了ic_launcher_settings.png  上层的Phone application,用phone application 有问题,所以也不能打电话
6. Phone.apk 是Google generic的电话应用,用的资源是hdpi. 进入/packages/app/Phone/, a.source ./build/envsetup.sh; b. mmm; 即可,输出的目录out/target/product/lotus/system/app
    $. build/envsetup.sh #初始化
    $mmm packages/providers/ContactsProvider/
    ##用mm/mmm来编译生成的.apk并不会打包到system.img中,需要我们手动通过make snod把system文件夹打包为system.img
    ##可以使用make snod将模块打包到system.img中,也可以使用 adb install *.apk安装
    注:通过mmm packages/providers/ContactsProvider/ 编译后的apk在 out/target/product/generic/system/app
    这时候通过 adb install out/target/product/generic/system/app/xxx.apk 安装你刚修改过的apk就可以在模拟器上看到你修改的效果了。
7. 在源代码中Check /device/semc/kumquat/system.prop,其中应该如下 rild.libargs=-c UNIX -n 2 -p /dev/socket/at_core -s /dev/socket/at_core -i rmnet0;
8. 进入ADB, getprop rild.libargs; 如果与上面不一样则setprop rild.libargs "-c UNIX -n 2 -p /dev/socket/at_core -s /dev/socket/at_core -i rmnet0"; 另 getprop 将会得到所有的属性值

四、手机LCD不亮
1. adb wait-for-devices logcat
2. 硬件FPC断裂

五、获取不同版本的代码
1.smb://cnbjmsw03/productsw/mib/android/manifest, 得到相应版本的manifest_xxx.xml 或者http://androidswrepo-cnbj.sonyericsson.net/pool/semc/b/build-metadata/ 从这获取,https://wiki.sonyericsson.net/androiki/Builds/Feeds/6.0.B.0.x
2.新建一个代码目录,如: Code, 然后repo init -u git://review.sonyericsson.net/platform/manifest.git -b ginger-ste
3.检测.repo 目录,用对应版本的manifest_xxx.xml 替换原来的manifest.xml
4.repo sync -j5

1. repo init -u git://review.sonyericsson.net/platform/manifest.git -b "branch" (for instance: edream3.0-release-caf"
2. repository getpackage build-metadata "label" (for instance: 3.0.A.2.77)
3. dpkg -x build-metadata_"label"_all.deb .
4. cp manifest_static.xml .repo/manifests/default.xml
5 repo sync -j8


六、合并代码到285版本
/Lotus$ cp Code/kernel/arch/arm/configs/semc_lotus_defconfig Code_285/kernel/arch/arm/configs/
/Lotus$ cp Code/kernel/arch/arm/mach-ux500/leds-lotus.c Code_285/kernel/arch/arm/mach-ux500/
/Lotus$ cp Code/kernel/drivers/leds/leds-as3677.c Code_285/kernel/drivers/leds/
/Lotus$ cp Code/kernel/drivers/video/mcde/display-panel_dsi.c Code_285/kernel/drivers/video/mcde/
/Lotus$ cp Code/device/semc/lotus/files/init.lotus.rc Code_285/device/semc/lotus/files/
/Lotus$ cp Code/device/semc/lotus/lotus_cfg.mk Code_285/device/semc/lotus/
/Lotus$ cp Code/device/semc/lotus/lights/leds.c Code_285/device/semc/lotus/lights/
/Lotus$ cp Code/kernel/drivers/video/mcde/display-r61529_dsi_seiko_rj248.c Code_285/kernel/drivers/video/mcde/

七、设置界面不能运行settings.apk(进一步分析 九)
1. 相应的资源文件不存在 Caused by: android.content.res.Resources$NotFoundException: File res/drawable/semc_list_selector_background.xml from drawable resource ID #0x2020084
检查 vendor/semc/packages/resources/uxp/res/drawable/semc_list_selector_background.xml 文件,发现有以下资源不存在
android:drawable="@drawable/semc_list_selector_background_disabled"
2. 检查 vendor/semc/packages/resources/uxp/res 对应的资源文件
3. Check devices/semc/lotus/lotus.mk 文件有 PRODUCT_LOCALES += mdpi, 所以需要检查drawable-mdpi目录下的资源文件
4. 把drawable-hdpi中相应的资源文件 拷贝到 drawable-mdpi
5. 重新生成system.sin

八、手机不识别SIM卡
1. Modem代码修改出问题,用kumquat 版本在285-325之间的任一 modem.sin,重新flash, 解决识别sim卡的问题
2. 等待Modem代码升级,fix 不能识别sim 卡的问题

九、分析Setting APP不能运行的原因
1. adb shell,进入手机 /system/app/找到 Settings.apk,该应用是Android 的Setting Application.
2. adb pull ,Settings.apk, 用AXMLPrinter2.jar, decode 其中的AndroidManifest.xml,找到packet path: com.android.settings; 从而找到源代码位置:packages/apps/Settings/src/com/android/settings, 代码放在src,部分资源放在res
3. 分析 Settings.java, Settings.xml
4. 学习PreferenceActivity
5. 从vendor/semc/packages/resources/uxp/res/drawable 目录下删除 semc_list_selector_background.xml
6. 编译出错 vendor/semc/packages/resources/uxp/res/values/semc_styles.xml,修改 <item name="android:listSelector">@drawable/semc_list_selector_background</item> --->为 <item name="android:listSelector">@null</item>
7. Semc公司自己的资源文件会生成 /out/target/product/lotus/system/framework/SemcGenericUxpRes.apk
8. 对于以前Setting.apk 出错的手机,还可以直接替换 /system/framework/SemcGenericUxpRes.apk 即可,这样替换掉了其中的资源调用错误。

十、重力传感器方向不对

十一、SemcPhone.apk
0. 运行exception:
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.android.phone/com.android.phone.SemcInCallScreen}: android.view.InflateException: Binary XML file line #28:
    Caused by: android.view.InflateException: Binary XML file line #28: Error inflating class com.android.phone.SemcContactPicView
    Caused by: java.lang.reflect.InvocationTargetException
    Caused by: android.content.res.Resources$NotFoundException: Resource ID #0x7f090007
1. 代码路径vendor/semc/packages/apps/phone(查找SemcPhone#LOCAL_CFLAGS += -DDEBUG -UNDEBUG -ULOG_NDEBUG而得到)
2. /out/target/common/obj/APPS/SemcPhone_intermediates/src/com/android/phone/R.java; or /out/target/common/R/com/android/phone/R.java; or /out/target/common/obj/APPS/Phone_intermediates/src/com/android/phone/R.java(查找0x7f090007而得到)
3. vendor/semc/packages/apps/phone/res/values-hdpi/semc_dimens.xml中有 <integer name="incall_screen_contact_picture_width_large_size">400</integer>, 而vendor/semc/packages/apps/phone/res/values-mdpi/dimens.xml 则没有,用values-hdpi/semc_dimens.xml 替换 values-mdpi/dimens.xml, 编译不通过!!!  只添加部分<!-- Contact picture -->保持和hdpi一致, 还是运行出错; 把大部分添加到values-mdpi/dimens.xml
4. 查到incall_screen_contact_picture_width_large_size 在 /vendor/semc/packages/apps/phone/src/com/android/phone/SemcContactPicView.java调用函数setDensityScale(..)
5. 把vendor/semc/packages/apps/phone/res/drawable-hdpi中独有的资源 添加到 vendor/semc/packages/apps/phone/res/drawable-mdpi
6. ......

十二、Camera.apk 不能运行 没有SD卡可用
1. packages/apps/camera/src/com/android/camera/Camera.java, noStorageText = getString(R.string.no_storage);显示没有卡的提示
2. device/semc/lotus/files/init.lotus.rc; /out/target/product/lotus/root/init.st-ericsson.rc; ./out/target/product/lotus/system/etc/vold.fstab; /frameworks/base/core/java/android/os/Environment.java
3. 修改camera 默认存储路径为 外置SD Card,目前为内置的Nandflash模拟的SD card. 通过文件管理器可以看到,sdcard对应的是内部nandflash, ext_card对应的才是外置 SD 卡。
4. 修改手机/system/etc/vold.fstab 或者 代码中device/semc/lotus/files/vold.fstab (./out/target/product/lotus/system/etc/vold.fstab),中的内容为如下:
    dev_mount ext_card /mnt/ext_card 14 /devices/sdi4/mmc_host/mmc1/mmc1
    dev_mount sdcard /mnt/sdcard auto /devices/sdi3/mmc_host/mmc3/mmc3
    dev_mount usbdisk /mnt/usbdisk auto /socket vold stream 0660 root mountdevices/platform/musb_hdrc.0
   /devices/sdi4/mmc_host/mmc1/mmc1 位于手机目录sys下    
5. 修改手机中的init.rc 中       export EXTERNAL_STORAGE /mnt/sdcard 为 export EXTERNAL_STORAGE /mnt/ext_card, 但是init.rc 不能直接修改完后替换,只能通过 ramdisk.img 来操作;发现一个能直接替换的方法如下,可以在adb shell模式下运行:mount -o rw -o remount /dev/block/actb / (后面那个表示根目录),然后手机的根目录就变成了可读写的了,原来只是可读的。
    
6. emulator的ramdisk.img 位于android-sdk-linux-x86/platforms/android-2.3.3/images/ramdisk.img,可通过如下方式修改:
    将ramdisk.img复制一份到任何其他目录下,将其名称改为ramdisk.img.gz,并使用命令;
    gunzip ramdisk.img.gz
    然后新建一个文件夹,叫ramdisk吧,进入该目录,输入命令
    cpio -i -F ../ramdisk.img
    这下,你就能看见并操作ramdisk里面的内容了。
    修改ramdisk 文件夹中内容
    制作ramdisk.img,init.rc修改之后,可以使用下列命令重新打包成镜像
    cpio -i -t -F ../ramdisk.img > list
    cpio -o -H newc -O lk.img < list
    当前目录下生成的lk.img就是我们的新镜像了。
7. 针对手机,重新编译生成ramdisk.img,它存在于那个sin中?在kernel.sin中, 修改system/core/rootdir/init.rc [export EXTERNAL_STORAGE /mnt/sdcard ----> export EXTERNAL_STORAGE /mnt/ext_card]然后重新编译连接生成kernel.sin ,则拍照时会先拍到外部的sdcard上。


十三、工厂如何检测手机是否正常启动
1. 用FG3 读取misc TA(地址 2227), flash软件后值为0xAA, 第一次启动后如果出错则会写成0x55,如果没有问题则是0x50

十四、对于Window PC不能识别成modem设备

十五、如何手动mount sdcard和检测到sd card
1. mount -t vfat /dev/block/mmcblk0p1 /mnt/sdcard; 不好用!
2. [Framework 层]主要分析 system/vold/main.cpp, DirectVolume.cpp, Volume.cpp[void Volume::setState(int state); int Volume::mountVol()]
3. [Framework 层]system/vold/main.cpp->main函数-->初始化VolumeManager,NetlinkManager,CommandListener;
4. [Framework 层]system/vold/commandlistener.cpp-->FrameworkListener("vold") 和registerCmd(new VolumeCmd())[VolumeCmd 的过滤关键字为volume];
5. [Framework 层]system/core/libsysutils/src/frameworklistener.cpp; FrameworkListener->dispatchCommand
6. [Framework 层]system/core/libsysutils/src/socketlistener.cpp; startListener-->android_get_control_socket(mSocketName)其中mSocketName="vold",该socket已经通过init.rc 中的socket vold stream 0660 root mount 开始就创建了,绑定后就开始listen(mSock, 4)
7. [Framework 层]system/vold/netlinkmanager.cpp;在NetlinkManager::start() 中会新创建一个socket; 最后设置了 mHandler = new NetlinkHandler(mSock);
8. [Framework 层]system/vold/netlinkhandler.cpp;中onEvent函数会处理收到的消息;而NetlinkHandler继承于NetlinkListener又继承于SocketListener(socket, false),由false可知该socket不是监听socket;在SocketListener::startListener()中会增加 mClients->push_back(new SocketClient(mSock));
9. [Framework 层]system/vold/directvolume.cpp;中handleBlockEvent-->mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeDiskInserted,msg,false);会发送VolumeDiskInserted给CommandListener[mVm],然后逐个对其mClients中的SocketClient发送消息;
10. [Framework 层]谁触发的 DirectVolume::handleBlockEvent? 由NetlinkHandler::onEvent;--> vm->handleBlockEvent(evt);-->VolumeManager::handleBlockEvent;-->mVolumes中逐个volume->handleBlockEvent;
11. [Framework 层]而VolumeManager中的mVolumes 中元素,是在main.cpp中process_config函数分析手机上的文件/etc/vold.fstab而得到的;
12. [Framework 层]又是谁触发NetlinkHandler::onEvent的? 又回到了NetlinkManager::start() 创建了nladdr.nl_pid = getpid();的socket。也就是必须有其他socket主动连接到该 NetlinkManager的socket(NetlinkManager::mSock);然后由SocketListener::runListener()--> NetlinkListener::onDataAvailable(c)-->NetlinkHandler::onEvent;
13. [Framework 层]现在必须查明 谁给NetlinkManager::mSock请求连接并发送消息subsys=“block”???????应该是kernel发出的,./drivers/base/core.c-->device_add-->kobject_uevent(&dev->kobj, KOBJ_ADD);
14. [Framework 层]在SocketListener::runListener()中如果是可以监听的socket[mListen=true],会增加 mClients->push_back(new SocketClient(c)); 如果需要收到VolumeDiskInserted的消息,你就首先需要申请和SocketListener[名称为vold]连接。比如某些应用需要获取该消息

1. [Kernel 层]主要分析 kernel/drivers/mmc/core/bus.c, mmc的driver注册到/sys/bus/mmc/devices下mmc3:aaaa, 实际对应的路径又为/sys/devices/sdi3/mmc_host/mmc3/mmc3:aaaa,这正好与前面dev_mount xxxx 中的设备点一致
2. [Kernel 层]kernel/drivers/mmc/core/bus.c [int mmc_add_card(struct mmc_card *card)];
   kernel/drivers/mmc/core/sd.c [mmc_attach_sd]
   kernel/drivers/mmc/core/core.c [mmc_rescan_try_freq <---mmc_rescan]    
   kernel/drivers/mmc/core/host.c [mmc_alloc_host: INIT_DELAYED_WORK(&host->detect, mmc_rescan);]
   EXPORT_SYMBOL(mmc_alloc_host) : 内核"导出"的符号表,这个表在insmod 时候会用到,可通过cat /proc/kallsyms查看
   kernel/drivers/mmc/core/core.c [mmc_detect_change]
   kernel/drivers/mmc/core/sd.c    [mmc_sd_detect]
   kernel/drivers/mmc/host/mmci.c  [mmci_cd_irq]  根据查kernel/arch/arm/configs/semc_lotus_defconfig中关于mmc 的config 和Makefile选择
   kernel/drivers/mmc/host/mmci.c  [mmci_probe]  注册中断监听函数mmci_cd_irq,还有mmc = mmc_alloc_host(sizeof(struct mmci_host), &dev->dev);初始化mmc_host;
   kernel/drivers/mmc/core/core.c  [mmc_detect_change]-->mmc_schedule_delayed_work(&host->detect, delay); ????
   host->detect = mmc_rescan;在kernel/drivers/mmc/core/host.c中mmc_alloc_host函数有INIT_DELAYED_WORK(&host->detect, mmc_rescan);其中mmc_rescan在kernel/drivers/mmc/core/core.c中
   似乎不太重要mmc_rescan-->host->bus_ops->detect(host)[该函数在/kernel/driver/mmc/core/mmc.c中赋值为mmc_detect]-->mmc_claim_host(host);-->__mmc_claim_host-->add_wait_queue(&host->wq, &wait);
3. [Kernel 层]kernel的sd卡插入和拔出的detect event 如何传递到 user space的vold->NetlinkManager::mSock的?????
4. [Kernel 层]kernel/lib/kobject_uevent.c中uevent_net_init函数会创建netlink_kernel_create(net, NETLINK_KOBJECT_UEVENT,...), 而kobject_uevent_env->netlink_broadcast_filtered-->do_one_broadcast[单一广播]会发送uevent到user space
5. [Kernel 层]/drivers/base/core.c;中device_add函数有kobject_uevent(&dev->kobj, KOBJ_ADD) 该处是所找的向user space发送消息
6. [Kernel 层]kernel/lib/kobject_uevent.c中kobject_uevent->kobject_uevent_env(kobj, action, NULL);
7. [Kernel 层]/drivers/mmc/core/bus.c有mmc_add_card->device_add函数
8. [Kernel 层]/drivers/mmc/core/sd.c有mmc_attach_sd函数->mmc_add_card(host->card);
9. [Kernel 层]/drivers/mmc/core/core.c有mmc_rescan_try_freq函数->mmc_attach_sd; 注意其attch顺序为sdio,sd,mmc; 而mmc_rescan会调用mmc_rescan_try_freq


十六、文件访问操作,如何从application->framework->kernel
1. libcore/luni/src/main目录
2. libcore/luni/src/main/java/java/io/File.java; createNewFile[java]-->createNewFileImpl[native]
3. libcore/luni/src/main/native/java_io_File.cpp;  File_createNewFileImpl; 用jniRegisterNativeMethods 注册Jni函数,建立java函数和C函数之间的对应关系
4. libcore 最后生成了啥?放在那儿了? system/framework/core.jar ,编译选项 BUILD_JAVA_LIBRARY->生成jar文件;BUILD_SHARED_LIBRARY->生成lib$(LOCAL_MODULE).so的文件;BUILD_STATIC_LIBRARY->生成名为lib$(LOCAL_MODULE).a的文件
5. Java代码: File myFile = new File(path); myFile.createNewFile();并不会马上在指定路径上创建文件,如果不做FileOutputStream的申明操作,则该文件不会有。改为分析libcore/luni/src/main/java/java/io/FileOutputStream.java ,write 函数
6. libcore/luni/src/main/java/org/apache/harmony/uni/platform/OSFileSystem.java, 中 public native long write(int fd, byte[] bytes, int offset, int length) throws IOException;
7. libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSFileSystem.cpp, 中 OSFileSystem_writeDirect
8. 最后调用标准的C函数 write
9. ;/development/ndk/platforms/android-3/include/stdio.h,中函数 fwrite
10. 分析不下去了? :(

11. 如何获取外部存储状态, android.os.Environment.getExternalStorageState()
12. /frameworks/base/core/java/android/os/Environment.java; 中getExternalStorageDirectory函数 调用getExternalStorageDirectory-->getDirectory-->System.getenv(variableName);
13. ./libcore/luni/src/main/java/java/lang/System.java;中函数 getenv-->getEnvByName; private static native String getEnvByName(String name);
14. libcore/luni/src/main/registerListenernative/java_lang_System.cpp; NATIVE_METHOD(System, getEnvByName, "(Ljava/lang/String;)Ljava/lang/String;"), 中函数 System_getEnvByName
15. init.rc中有export EXTERNAL_STORAGE /mnt/sdcard, 设置到system environment, 这些参数则可以用函数System_getEnvByName读出



十七、修改重力传感器的方向
1. /device/semc/lotus/files/sensor.conf
2. frameworks/base/core/java/android/hardware/SensorManager.java; 中函数registerListener, 创建ListenerDelegate中函数handleMessage 其中会触发interface SensorEventListener中的接口函数onSensorChanged
3. SensorThread,SensorThreadRunnable; enableSensorLocked-->sensors_enable_sensor
4. kernel driver 位于kernel/drivers/input/misc/lsm303dlhc_acc.c

十七(+)、如何修改kernel log 的输出等级
1.如何修改kernel log 的输出等级,以方便调试输出, 查看 kernel/include/linux/kernel.h 中有console_loglevel等定义
2. system/core/include/cutils/log.h, 中有定义LOG_NDEBUG, 可通过修改它,改变输出log级别(除了kernel log); kenrel/printk.c 中有函数 vprintk(是printk的最终执行函数)和 vprintk--> release_console_sem--> call_console_drivers-->_call_console_drivers
3. cat /proc/sys/kernel/printk 显示了当前kernel log 的设置情况,[应控制台日志级别、默认的消息日志级别、最低的控制台日志级别、默认的控制台日志级别],所有小于应控制台日志级别 的log,都可以输出,所以可以把其改大,输出更多log
4. 在 include/linux/device.h 中 dev_dbg,目前定义了 CONFIG_DYNAMIC_DEBUG=y,所以dev_printk 没有输出, 另外CONFIG_DEBUG_INFO 也定义了
5. early_parm, 在文件 init/main.c中有函数loglevel-->get_option[读的那里的参数?],并且有early_param("loglevel", loglevel); early_parm 是在 setup_arch--> parse_command中处理的, 只有在bootloader设置传递该参数, 或者在内核CONFIG_DEFAULT_COMMANDLINE中声明了, 内核在处理参数的时候才会执行相对应的函数。
6. 文件 kernel/arch/arm/kernel/setup.c中 函数setup_arch-->parse_early_param;会分析early_parm的设置
7. 实际上是在 文件kernel/include/linux/kernel.h 中函数 console_verbose 最后设置了console_loglevel的值为15
8. parse_cmdline会分析执行early_parm的内容
10. printk输出的时间信息[  304.531250]为[秒.毫秒微妙],其中时间输出的控制在CONFIG_PRINTK_TIME=y


9#. 在 /system/core/include/cutils/log.h 中定义 NDEBUG 即可输出LOGV 的信息,或者 在模块中的Android.mk添加LOCAL_CFLAGS += -DDEBUG -UNDEBUG -ULOG_NDEBUG



十八、 JNI 的原始代码位于 dalvik 目录下
 
十九、如何编译连接 .c 的可执行文件
1. 在./development目录下创建一目录 如:hello
2. 进入hello目录,在其下编写自己的.c文件,如: hello.c
    #include <stdio.h>
    int main()
    {
        printf("hello world\n");
        exit(0);
        //return 0;                       
    }
3. 在hello目录中,编写Android.mk, 内容如下:
    LOCAL_PATH:= $(call my-dir)
    include $(CLEAR_VARS)
    LOCAL_MODULE := helloworld
    LOCAL_SRC_FILES := hello.c
    LOCAL_MODULE_TAGS := optional
    include $(BUILD_EXECUTABLE)
4. 回到Android源代码顶层目录,进行编译,make helloworld
5. 生成的可执行文件位于:out/target/product/lotus/system/bin/ 目录下
6. adb push 到手机 /data 目录下,然后进入adb shell,到data目录下,执行./helloworld 皆可

手动编译连接
7、编译成目标文件:
   #$(yourAndroid)/prebuilt/linux-x86/toolchain/[arm-eabi-4.2.1]/bin/arm-eabi-gcc -I bionic/libc/arch-arm/include/ -I bionic/libc/include -I bionic/libc/kernel/common -I bionic/libc/kernel/arch-arm -g -c helloworld.c  -o hello.o
8、生成可执行代码:
   #$(yourAndroid)/prebuilt/linux-x86/toolchain/[arm-eabi-4.2.1]/bin/arm-eabi-gcc -nostdlib -Bdynamic -Wl,-T,build/core/armelf.x -Wl,-dynamic-linker,/system/bin/linker -Wl,--gc-sections -Wl,-z,nocopyreloc -o helloworld -Lout/target/product/[generic]/obj/lib -Wl,-rpath-link=out/target/product/[generic]/obj/lib -lc hello.o -entry=main
    其中[ ]中部分根据实际情况修改

二十、Dalvik虚拟机和Java 库
1. dalvik 目录下包含了目标机和主机的内容;dalvik/vm 目录下是虚拟机的实现,由本地代码实现,包含部分的汇编代码,编译结果为共享库libdvm.co;
2. libcore 目录包含对基础java实现支持的代码目录,包含C和JAVA代码,编译结果为java的包core.jar;
3. nativehelper 库是一个工具库,用于注册java本地调用的函数,其他代码需要使用jni从本地层次向java层次提供功能的时候,需要用到这个库;代码位于dalvik/libnativehelper, 连接静态库libjavacore.a,生成动态库libnativehelper.so
4. Android的java 库主要为 android包和子包,核心包为frameworks/base/core/java;
5. Android中java类的api描述文件在 frameworks/base/api/current.xml
6. 主要的jni代码位于 frameworks/base/core/jni, 最后编译生成libandroid_runtime.so,放在 system/lib; 另外如媒体部分jni在 frameworks/base/media/jni,最后生成libmedia_jni.so
7. 所有在android中实现的jni库,都需要连接动态库libnativehelper.so,可查看 development/samples/simplejni 代码.


二十一、debugd


二十二、busybox
如何安装,从 http://www.busybox.net/downloads/binaries下载busybox-armv6l,然后把busybox ,push到 /system/xbin, #chmod 755 busybox, #busybox --install
com.sonyericsson.androidapp.footballdownloads-1.apk
org.microemu.android.se.appello.lp.WisepilotSE-1.apk
com.sony.snei.mu.phone-1.apk
com.sonyericsson.androidapp.smart-1.apk
de.arvatomobile.sonyericsson.playnow.android-1.apk
com.wsandroid.suite-1.apk
com.sonyericsson.xhs-1.apk
com.sonyericsson.androidapp.everchwallpaper-1.apk
com.chartcross.gpstest-1.apk
com.testapp-1.apk
com.sonyericsson.android.LogAlong-1.apk
com.metago.astro-1.apk

二十三、video 不能录像
1.  kernel/drivers/misc/dispdev/dispdev.c 中函数init_dispdev
2. packages/apps/camera/src/com/android/camera/camera.java; 应用层代码 (startPreview)
3. frameworks/base/core/java/android/hardware/Camera.java; Java native 接口代码(native interface startPreview); open(int cameraID) ->Camera 构造函数会调用native_setup
4. frameworks/base/core/jni/android_hardware_Camera.cpp(最后生成libandroid_runtime.so); JNI 关联代码,startPreview-->android_hardware_Camera_startPreview; 另外函数 android_hardware_Camera_native_setup-->Camera::connect(cameraId);
5. frameworks/base/libs/camera/Camera.cpp(最后生成libui.so),中函数Camera::connect(int cameraId)-->getCameraService
6. frameworks/base/services/camera/libcameraservice/CameraService.cpp(最后生成libcameraservice.so) 用于实现一个Camera的服务,HAL_openCameraHardware 调用得到一个CameraHardwareInterface类型的指针,所有对camera的操作最终是对该指针操作。
7. HAL层:[vendor/semc/hardware/libcamera/SemcCameraHardware.cpp中,函数HAL_openCameraHardware,HAL_gCameraIndexParamConv定义了两个camera, 还有startPreview函数-->startPreviewInternal--> mpCald->pICamera->StartPreview; 注意 startCamera 将初始化mpCald];
   实际用的是vendor/semc/hardware/libcamera/riogrande/stecameracore.cpp
8. libcamera.so


8. 另外,所有SEMC独有的hardware, HAL 层代码都在vendor/semc/hardware/下
9. vender/semc/hardware/libcamera/riogrande/stecamera.cpp中有 startpreview函数
10. st-mmio.c, kanna, KMO05BN0
11. 驱动的代码位于vendor/st-ericsson/multimedia/imaging/isp8500_firmware_IMX072

二十四、分析android如何编译的
1. 主要位于build目录下,lunch shell命令在envsetup.sh中定义了
2. lunch会设置product. 选择某个编号后 TARGET_PRODUCT和TARGET_BUILD_VARIANT 会被赋值
3. lunch-->printconfig-->get_build_var-->会运行build/core/config.mk-->include $(BUILD_SYSTEM)/envsetup.mk-->输出配置结果
4. envsetup.sh-->lunch-->build/core/config.mk-->buildspec.mk和envsetup.mk,BoardConfig.mk
5. 编译顺序:config.mk,envsetup.mk,product_config.mk(会对TARGET_DEVICE赋值),device/semc/lotus/BoardConfig.mk->device/semc/riogrande/BoardConfig.mk(中定义了与平台相关的编译参数)和device/semc/lotus/lotus_cfg.mk
6. 每个package/apps的模块下都与Android.mk,里面会定义当前模块的tag, 其中LOCAL_MODULE_TAGS 会决定是否本模块会编译进系统,
7. 在main.mk中,subdir_makefiles 变量会包含所有子目录下的Android.mk, ALL_DEFAULT_INSTALLED_MODULES包含所有需要编译的模块路径,build/core/Makefile 会对ALL_DEFAULT_INSTALLED_MODULES赋更多的值
8. SEMC sin文件如何生成? vendor/semc/build/sin 目录下有sin文件生成的代码


二十五、LCD驱动
1. kernel config文件中 MCDE DSI displays 定义CONFIG_MCDE_DISPLAY_XXXX_XXXX(CONFIG_MCDE_DISPLAY_R61529_DSI_SEIKO_RJ248)
2. 驱动文件 /kernel/drivers/video/mcde/display-r61529_dsi_seiko_rj248.c

二十六、如何加载动态库so
1. bionic\linker\dlfcn.c -->dlopen,dlsym

二十七、USB mass storage驱动分析
1. USB驱动代码在/drivers/usb/gadget下,有文件:android.c,其他驱动文件f_adb.c,f_mass_storage.c;其中android.c 依赖于f_adb.c 和 f_mass_storage.c(这两个文件之间无依赖关系)。
2. usb_mass_storage重新mount一个分区;
    a. adb shell 进入/sys/devices/platform/usb_mass_storage/lun0
    b. echo "" > file  //unmount card
    c. echo /dev/block/vold/179:14 > file //mount internal mass storage
    d. echo "" > file  //unmount card
    e. echo /dev/block/vold/179:32 > file //mount external mass storage
3. 如何check 设备号
    a. cat /proc/partitions
    b. cat /proc/mounts
    c. ls -l /dev/block
4. f_mass_storage.c中 android_register_function(&mass_storage_function);注册该驱动为USB驱动,其中有如下设置其属性
    static DEVICE_ATTR(ro, 0644, fsg_show_ro, fsg_store_ro);
    static DEVICE_ATTR(file, 0644, fsg_show_file, fsg_store_file);
   fsg_show_ro, fsg_store_ro, 和 fsg_show_file, fsg_store_file 位于 storage_common.c文件中

5. 函数 fsg_store_file 中会把以前的partition给fsg_lun_close,然后 fsg_lun_open 一个新的partition,这就可以解释为什么不能同时mount两个partition暴露给PC, 如何挂载多个mass storage设备?

6. kernel\arch\arm\mach-ux500\board-rio-grande.c中有static struct usb_mass_storage_platform_data mass_storage_pdata定义,修改nluns = 2,测试

7. 进入手机会发现/sys/devices/platform/usb_mass_storage 目录下多一个lun?, 在两个不同的lun0/1下,可以手动挂载两个卡
    a. 进入lun0
    b. echo /dev/block/vold/179:14 > file
    c. 进入lun1
    d. echo /dev/block/vold/179:32 > file
  (顺便提及下多出的lun2 是给cdrom用的,因为在f_mass_storage.c中fsg_probe 有nluns = fsg_cfg.nluns + fsg_cfg.cdrom_nluns;而cdrom_nluns=1

8. system\vold\volumemanager.cpp中函数sharevolume和unsinit.rcharevolume中会往/sys/devices/platform/usb_mass_storage/lun0 写入/dev/block/vold/179:xx; 可在这修改添加挂载多一个sd卡设备

9. system\vold\main.cpp中process_config函数会分析/system/etc/vold.fstab,然后addVolume 到volumemanager.cpp中的变量mVolumes中

10. system\vold\commandlistener.cpp中int CommandListener::VolumeCmd::runCommand(SocketClient*cli,int argc, char **argv)函数接收sd卡的挂载命令

11. frameworks\base\services\java\com\android\server\mountservice.java,中函数setEachUsbMassStorageEnabled(String path, boolean enable) <--setUsbMassStorageEnabled

12. /dev/block/vold/179:14设备可以同时挂载为mtp 和 sd 卡



二十八、socket 机制(即demoen 服务进程的机制)
1. init.rc 中有
    service vold /system/bin/vold
    console
    socket vold stream 0660 root mount
    ioprio be 2
2. system\core\init\init.c 中init_parse_config_file("/init.rc");会解析;   init_parse_config_file-->parse_config-->lookup_keyword(得到的类型有K_service和K_socket)-->parse_new_section-->parse_service-->添加到service_list;
3. init.c中main函数中queue_builtin_action(keychord_init_action, "keychord_init");-->keychord_init_action-->keychord_init-->service_for_each
4. init.c中main函数中queue_builtin_action(..)-->action_add_queue_tail会把keychord_init_action生成一个action添加到action_list中同时还会添加到action_queue中(用于队列执行)
5. init.c中main函数中execute_one_command-->action_remove_queue_head,会执行所有的service 一遍并同时把执行过的item 移出action_queue
6. init.c中main函数中 restart_processes();会判断分析当前service_list的所有service状态,如果不是SVC_ONESHOT并且为 SVC_RESTARTING则重新启动该service
7. execute_one_command和restart_processes最终都会执行到init.c中service_start函数,如果有K_socket属性就会执行create_socket(...)和 publish_socket(...)
8. 手机中 dev/socket/vold
9. Android创建的socket没有端口(port)和地址(IP addr)? 用如下函数创建和绑定,其中bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen)中的struct sockaddr有两种赋值方式
    mSock = socket(PF_NETLINK,SOCK_DGRAM,NETLINK_KOBJECT_UEVENT);
    bind(mSock, (struct sockaddr *) &nladdr, sizeof(nladdr));
    struct sockaddr_nl
    {
     sa_family_t nl_family;
     unsigned short nl_pad;
     __u32 nl_pid; //process id
     __u32 nl_groups;
    };
    
    fd = socket(PF_UNIX, type, 0);
    bind(fd, (struct sockaddr *) &addr, sizeof (addr));
    struct sockaddr_un {
     sa_family_t sun_family;
     char sun_path[UNIX_PATH_MAX];//文件路径  e.g /dev/socket/vold;根据#define ANDROID_SOCKET_DIR "/dev/socket";
    };
    以上都是为了进程间通信,两者有啥区别?
二十九、Main UI
1. system/app/launcher2.apk默认的google home ui
2. 其中packages/apps/Launcher2/Android.mk中有 LOCAL_OVERRIDES_PACKAGES := Home ,所以可以用 system/app/Home.apk 替换google 默认的Home UI

三十、去掉factory中强制reboot 整个系统
1. device/semc/riogrande/files/init.riogrande.rc;  /system/bin/modem-supervisor -f [去掉-r即可]
#STE: Modem-supervisor
service modem-supervisor /system/bin/modem-supervisor -r -f /dev/dbx500_mloader_fw -i /sys/devices/platform/ab8500-i2c.0/chip_id -c monitor -t 0
    user root

三十一、工厂如何判断第一次flash后开机成功
1. 用FG3读取 miscTA,GDFS-TA-->Partition(Misc TA)-->Unit(2227);
2. 具体值的含义如下
    0xAA: Means final flash has been performed. Set by loader at production.
    0xAB: First startup after final flash šC early boot completed. This is written by TA-task in AMSS.
    0x50: First startup after final flash šC Android boot completed. This is written by "startupflag" which is run by :init on property ev.bootcomplete=1.
    0x55: Error state, e.g. first startup failed after 0xAB before 0x50.
    Once 0x50 or 0x55 is reached, the value is never changed by SW.
3. 因为STE modem有问题,需要flash image后,重新reset整个手机(update firmware和set parameter),所以实际上第一次开机是不成功的,0x2227的值就是0x55了
4. 如何full build 参考https://wiki.sonyericsson.net/androiki/Full_Build_and_Run; 其中最后一步不同在于用make -j4 all-deb 代替make sin;另外The all-deb target will produce all debian packages needed to compose a software in your out/target/product/product/obj/deb folder.
5. make -j9 PRODUCT-semcsdk-semcsdk
6. semc-multi-build
7. semcpkgtoimg pp-[lotus]-dev-dev variant-eng result-flashable -snap [6.0.B.1.208] -src [out/target/product/lotus/obj/deb];其中[]中的内容需要根据实际情况修改

三十二、log 机制
1. dmesg 读取kernel 的log, system/core/toolbox/dmesg.c 文件中dmesg_main函数-->klogctl, 可以看到只支持dmesg -c,并且用dmesg显示kernel log不能连续显示(可从代码中看出来),用cat proc/kmsg 则可以连续显示kernel log.
2. klogctl函数的定义在那? bionic/libc/arch-arm/syscalls/klogctl.s, 从user space读取kernel space的log,需要进一步分析如何实现的????? klogctl是实现kernel log能输出到user space(logcat, dmesg)的关键。
3. logcat 能输出kernel log的机制, vendor/semc/system/utility/klogrouter/src/klogrouter.c 中有函数main-->klog_to_logcat-->klogctl
4. 在手机的init.st-ericsson.rc中有
    on property:persist.kernel.log=logcat
        stop klogrouterd
        start klogrouterd
    on property:persist.kernel.log=uart
        stop klogrouterd
        exec /system/bin/klogrouter uart
    on property:persist.kernel.log=default
       stop klogrouterd
       exec /system/bin/klogrouter default
    service klogrouterd /system/bin/klogrouter logcat  
    最开始执行的是带参数 logcat, 其中的stop/start/exec 你也可以单独在adb shell中执行
    可以在adb shell中用setprop persist.kernel.log xxxx 做控制log的操作,实际上是控制klogrouter.c-->main-->会写/proc/console_control
    setprop persist.kernel.log uart (enables UART logging)
    setprop persist.kernel.log default (disables UART logging)
    setprop persist.kernel.log logcat (redirects kernel logs to logcat)
5. kernel/arch/arm/kernel/console_control.c 会创建/proc/console_control, 函数console_control_write会设置console_drivers控制台con->flag是否CON_ENABLED,也就是是否可输出log
6. kernel/kernel/printk.c, 控制台信息输出路径release_console_sem-->call_console_drivers-->_call_console_drivers-->_call_console_drivers-->__call_console_drivers-->con->write(con, &LOG_BUF(start), end - start);
7. ????很重要semc_lotus_defconfig中有CONFIG_CMDLINE= ...rootwait console=ttyAMA2,115200n8 mem=96M@0 ...,才能有uart串口输出,如果还没有uart输出,则需要执行
    adb shell chmod 6755 /system/bin/klogger
    adb shell setprop persist.kernel.log uart
    adb shell klogger &
UART串口注册的设备位于 sys/devices/uart2/tty/ttyAMA2,[console=ttyAMA2,115200n8]表示可以用ttyAMA2这个控制台,并且设置的参数为115200n8,这样就可以与实际的uart串口相关联, 但是实际这个uart串口设备在那注册的呢???? 在kernel/drivers/serial/serial_core.c中有函数uart_register_driver-->tty_register_driver
8. 注册的设备为sys/devices/platform/ram_console,注册名称为ram_console,是啥????? 串口输出的uart设备是ttyAMA2, 这儿有三个uart设备
    ttyAMA0: 位于sys/devices/uart0/tty/ttyAMA0, 但是没有enable
    ttyAMA1: 位于sys/devices/uart1/tty/ttyAMA1, 但是没有enable
    ttyAMA2: 位于sys/devices/uart2/tty/ttyAMA2; 这才是手机串口输出log的uart接口
9. 函数setup_arch-->继续调用文件(kernel/init/main.c中)函数parse_early_param-->parse_early_options-->(kernel/hernel/params.c)parse_args-->parse_one-->do_early_param 但是没有执行,因为没有用early_param添加到__setup_start到__setup_end段中, ealy_param和__setup两宏都会把函数对应关系添加到init.setup段中,但是用ealy_param添加时early=1,表示需要提前执行
10. /kernel/kernel/printk.c中有__setup("console=", console_setup);且console_setup 的参数是“ttyAMA2,115200n8“,该函数会初始化 uart串口输出的console;
11. /kernel/init/main.c中函数main->parse_args("Booting kernel",...)-->unknown_bootoption-->obsolete_checksetup,需要特别注意的是在函数unknown_bootoption中会对参数param做“=”的处理,最终param会变成"XXX=";这就与/kerne/kernel/printk.c中的__setup("console=", console_setup);对应上了,也就是console=ttyAMA2,115200n8,表示需要在init.setup段中,查找param为"console="对应的函数,恰好就是console_setup(“ttyAMA2,115200n8“),-->__add_preferred_console-->会往全局变量console_cmdline[MAX_CMDLINECONSOLES]添加值,
12. 以后继续分析/kernel/kernel/printk.c中console_setup-->__add_preferred_console 中会赋值selected_console=i,对全局变量static struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];中对应的结构赋值;另外函数register_console(struct console *newcon)会注册该串口设备,实际上也就是与console_cmdline相关联起来。
13. 串口设备的驱动在那(才会调用register_console注册sys/devices/uart2/tty/ttyAMA2)???目前发现是在kernel/drivers/serial/serial_core.c中有函数uart_register_driver-->tty_register_driver;
14. Uart串口设备属于Serial drivers,硬件驱动位于kernel/drivers/serial/amba-pl011.c, 函数pl011_init-->uart_register_driver(&amba_reg);和amba_driver_register(&pl011_driver);
15. 然后会调用register_console(谁调用的????)kernel/drivers/serial/amba-pl011.c,函数amba_driver_register-->pl011_probe-->uart_add_one_port-->uart_configure_port-->register_console; 其中 uart_add_one_port(&amba_reg, &uap->port);中的amba_reg.cons = &amba_console; amba_reg.cons.setup = pl011_console_setup, 注意在register_console(struct console *newcon)中newcon->index=-1 or 2,但是amba-pl011.c中的pl011_console_setup 里amba_ports并没有对应的数据,所以pl011_console_setup在前两次会失败,第三次会成功(因为pl011_probe 会执行3次???,其中会对amba_ports添加三次值,所以newcon->index=2,就有对应的amba_ports[2]数据)
16. 最初由kernel/drivers/serial/amba-pl011.c中变量amba_console.index = -1;-->可以推出 ttyAMA第一次调用 register_console(struct console *newcon)中newcon->index=-1; 在register_console函数中,amba_console.index 会被赋值为2,这是根据console_cmdline给于的,因为console_cmdline[]中有一个的name也是ttyAMA. 这样两者就关联起来了;
17. 根据以上分析,尝试把CONFIG_CMDLINE= ...console=ttyAMA0[或3],115200n8 ... 会有啥结果呢????没有串口log输出;原因待查????
18. 手机上注册的sys/devices/uart0[1,2]/tty/ttyAMA0[1,2]/dev,其主设备号都是204,子设备号为64[65,66].
19. 在手机上能查看,cat proc/tty/drivers-->ttyAMA /dev/ttyAMA   204 64-77 serial
20. sys/bus/amba/drivers/uart-pl011,实际的driver 注册在这里 kernel/drivers/serial/amba-pl011.c-->amba_driver_register(&pl011_driver);
21. 实际上串口log输出的uart driver 一定会注册,在semc_lotus_defconfig中有CONFIG_CMDLINE= ...console=ttyAMA2,115200n8 ...,只是设置了该uart port的相关参数,同时把console_cmdline console_cmdline[MAX_CMDLINECONSOLES]其中一个值与实际的uart driver相关联起来。


三十三、如何在window上安装adb驱动
1. 得到kumquart 的adb 驱动
2. 直接安装不成功,检查驱动win32目录下的 sa0102adb.inf配置文件
3. 在linux上用lsusb 查看lotus手机的product ID:  (b173)
    Bus 002 Device 051: ID 0fce:b173 Sony Ericsson Mobile Communications AB
    Bus 002: 表示第二个usb主控制器
    Device 051:  表示系统给usb鼠标分配的设备号(devnum),同时也可以看到该鼠标是插入到了第二个usb主控制器006 usb_device.devnum (/sys/devices/pci0000:00/0000:00:1d.1/usb2/2-2/devnum)
    ID 0fce:b173:表示usb设备的ID(这个ID由芯片制造商设置,可以唯一表示该设备),0fce->usb_device_descriptor.idVendor;b173->usb_device_descriptor.idProduct( /sys/devices/pci0000:00/0000:00:1d.1/usb2/2-2/idVendor)

4. lsusb -s 002:051 -v 查看adb 功能的接口号
      Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass       255 Vendor Specific Class  //255表示的是adb driver 接口
      bInterfaceSubClass     66
      bInterfaceProtocol      1
      iInterface              0
5. 在[SEMC.NTx86] 增加如下内容 PID_XXXX(prodruct id)  &MI_XX(interfacenumber)
    %CompositeAdbInterface%     = USB_Install, USB\VID_0FCE&PID_b173&MI_02

三十四、在手机上如何输入log到sd卡
1. 查看手机中init.rc 其中有
    service console /system/bin/sh
    console
    disabled
    user shell //用户为shell,需要修改为root,这样就有了root权限
    group log
2. adb pull init.rc,修改后 adb push init.rc, 但不成功,文件系统只读
3. 查看手机init.rc 的属性-rwxr-x---;
4. 修改其可写属性 用 chmod 777 init.rc ,但是失败提示:Unable to chmod init.rc: Read-only file system
5. 查看 cat proc/mounts 有rootfs / rootfs ro,relatime 0 0 表示根目录只读
6. 在adb shell模式下运行:mount -o rw -o remount /dev/block/actb / (后面那个表示根目录),查看cat proc/mounts有rootfs / rootfs rw,relatime 0 0
变成了可读写的模式
7. 这时就可以把修改完的init.rc, adb push 到手机中了, 但是手机一重启,init.rc 又还原了!!!没有用阿
8. 在手机的超级终端中执行 mount -o rw -o remount rootfs /
9. 以上都没有用,最后发现一招 在shell下执行 logcat -f /sdcard/logcat.log &  !!!!!!!!

三十五、    system call 的分析
0. sysfs_write_file@kernel/fs/sysfs/file.c
1. vfs_write@kernel/fs/read_write.c
2. sys_write@kernel/fs/read_write.c有SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf,    size_t, count)定义, SYSCALL_DEFINEx的定义在 kernel/include/linux/syscalls.h, 经过转换就变成了sys_write(...)
3. ret_fast_syscall(asm)@kernel/arch/arm/kernel/entry-common.S中(entry_armv.s)
4. 所有的system call函数都是以 sys_???开头的
5. kernel/arch/arm/include/asm/unistd.h 中定义了system call number, 系统调用的调用号规则,
    #define __NR_write    (__NR_SYSCALL_BASE+  4)
6. kernle/arch/arm/kernel/calls.S声明了系统调用函数 CALL(sys_write) 为于第4个
7. kernel/arch/arm/kernel/entry-common.S,中有sys_syscall的定义,还有vector_swi的定义,用于软中断的进入,也就是最终会执行例程vector_swi来完成对系统调用的处理。
8. kernel/arch/avr32/kernel/syscall_table.S,中有sys_call_table(系统调用系统call)的定义
9. kernel/arch/arm/kernel/entry-armv.S和entry-header.S,中有 ARM Linux的异常向量表
    __vectors_start:
     ARM(    swi    SYS_ERROR0    )
     THUMB(    svc    #0        )
     THUMB(    nop            )
        W(ldr)    pc, .LCvswi + stubs_offset//另外有定义.LCvswi: .word    vector_swi;所以最终执行到了vector_swi
        W(b)    vector_irq + stubs_offset//定义在vector_stub    irq, IRQ_MODE, 4; 是Interrupt dispatcher
    __vectors_end:    
10. 总而言之,system call是用户空间程序用系统软中断(0x80)模拟出现异常,然后进入内核空间的异常处理handler,-->vector_swi-->读取相关寄存器获取系统调用号(4)->参照sys_call_table对应到sys_XXX(sys_write)->进入vfs_write-->???
11. system all最多可传7个参数保存在(R0--R6),R7->syscall number, R8->syscall table pointer&linux syscall, R9->Current thread_info,这些在kernel/arch/arm/kernel/entry-header.S中有说明


三十六、minicom的使用,可参考https://wiki.sonyericsson.net/androiki/Urban
1. 安装minicom ,sudo apt-get install minicom
2. load the device drivers for urban manually:
    sudo modprobe ftdi_sio vendor=0x0403 product=0xfc8a (0xfc8a: ttyUSB0, 0xfc8b: ttyUSB1)
    //modprobe 我们常用的功能就是挂载模块,在挂载某个内核模块的同时,这个模块所依赖的模块也被同时挂载;
    //当然modprobe 也有列出内核所有模块,还有移除模块的功能;下在我们举个例子说一说咱们常用的功能和参数;
    #modprobe -r filename //删除mode
    #lsmod    //列出所有mod    ,还有modinfo
3. 设置串口设备名称 #minicom -D /dev/ttyUSB0,或者进入#minicom -s 进入 Serial port setup --> A 设置 Serial Device 为/dev/ttyUSB0
4. cat /dev/ttyUSB0 | tee log_file.txt 直接拷贝到文件 或者 在minicom的运行界面执行ctrl+A 然后l:保存文件;q:退出
5. The UART logging will stop after reboot of the phone. It can be started again by setting the property kernel.log in ADB.
    setprop persist.kernel.log uart (enables UART logging)
    setprop persist.kernel.log default (disables UART logging)
    setprop persist.kernel.log logcat (redirects kernel logs to logcat)

三十六、如何用minicom发送at command
1. adb root && adb shell setprop persist.usb.eng 1
2. sudo modprobe usbserial vendor=0x0fce product=0x5146
3. ls /dev/tty* //查看增加了那个tty设备,针对lotus是/dev/ttyACM0
3. minicom -D /dev/ttyACM0 # ACM0 may not be your case. If true, please try other devices like ttyXXXx.
4. You may try to run your AT command now.
5. #AT ;返回ok则表示At command channel ready

三十七. CONFIG_CMDLINE是如何被解释执行的?
1. CONFIG_CMDLINE 定义在**_defconfig中,进入手机后还可用cat proc/cmdline 看到
2. kernel/arch/arm/kernel/setup.c中有static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; 函数setup_arch-->继续调用文件(kernel/init/main.c中)函数parse_early_param-->parse_early_options-->(kernel/hernel/params.c)parse_args-->parse_one-->do_early_param
3. 对于do_early_param函数分析,是将param与__setup_start到__setup_end段中的参数比较,并执行相应的处理函数;文件kernel/include/asm-generic/vmlinux.lds.h中有INIT_SETUP的定义;kernel/inlcude/linux/init.h中有 __setup_param和__setup的定义,用于在init.setup段中定义一个param和对应的处理函数
4. 查找用 __setup 做的console 对应函数定义?????? 没有申明
5. early_param(...)设置的对应函数会在parse_early_param()->do_early_param执行,比__setup()申明的函数在parse_args(...)->unknown_bootoption执行,所以early_param比__setup设置的函数先执行,

三十八、camera 的时钟默认有输出,导致GPS测试有干扰
1. kernel/arch/arm/mach-ux500/clock-db8500.c,主要设置不同模块的时钟参数。其中函数clkout0_enable,clkout0_disable是主camera 的时钟设置函数,用的是GPIO227
2. kernel/arch/arm/mach-ux500/gpio-lotus.c 有mop500_pins_default 是设置gpio默认状态的, 为了设置camera 的时钟默认输出没有,需要修改如下
    static pin_cfg_t mop500_pins_default[] = {
        ...
        GPIO227_CLKOUT1,        -->GPIO227_GPIO |PIN_OUTPUT_LOW,
        GPIO228_CLKOUT2,        -->GPIO228_GPIO |PIN_OUTPUT_LOW,
        ...
    }
3. GPIO227_CLKOUT1和GPIO227_GPIO的含义是不一样的

三十九、Setting中的display界面没有“Mobile BRAVIA Engine”项目
1. /packages/apps/Settings/src/com/android/settings/DisplaySettings.java中有函数onCreate,其中有如下内容
        if (SystemProperties.getBoolean(SWIQI_SUPPORTED , false)) {
            mSwIqiEnabled = (CheckBoxPreference) findPreference(KEY_SWIQI_ENABLED);
            mSwIqiEnabled.setPersistent(false);
            mSwIqiEnabled.setChecked(SystemProperties.getInt(SWIQI_ENABLED , 0) != 0);
        } else {
            // if not supported swiqi then not display item of swiqi.
            getPreferenceScreen().removePreference(findPreference(KEY_SWIQI_ENABLED));
            mSwIqiEnabled = null;
        }
2. packages/apps/Settings/src/com/android/settings/DisplaySettings.java中有 private static final String SWIQI_SUPPORTED = "ro.service.swiqi.supported";
3. 进入adb 可以用setprop ro.service.swiqi.supported true, 来打开menu item(Mobile BRAVIA Engine)显示
4. 哪代码又是从来添加的呢? 在手机中/system/build.prop中有ro.service.swiqi.supported=true,实际上用getprop获取,setprop设置的属性值,保存在/default.prop,/system/build.prop
5. 谁添加到 /system/build.prop,其生成是由make系统解析build/core/Makefile完成的,Makefile中调用build/tools/buildinfo.sh执行脚本,并输出到build.prop(Buildinfo.sh很简单,只是echo一些属性), Makefile中直接把$(TARGET_DEVICE_DIR)/system.prop的内容追加到build.prop中,针对Lotus则是./device/semc/lotus/system.prop,另外还收集ADDITIONAL_BUILD_PROPERTIES中的属性,追加到build.prop中,ADDITIONAL_BUILD_PROPERTIES又会收集PRODUCT_PROPERTY_OVERRIDES中定义的属性。
6. 在 vendor/semc/framework/swiqi/lib-swiqi-core/Android.mk中有
    ifeq ($(TARGET_PRODUCT), kumquat)//但是没有lotus的设置,所以需要在这个文件中添加类似内容
    PARAM_FILE_PHOTO := $(wildcard $(LOCAL_PATH)/data/be_photo_hjortron)
    PARAM_FILE_MOVIE := $(wildcard $(LOCAL_PATH)/data/be_movie_hjortron)
    SWIQI_PROP_ENABLE := ON
    endif

    ifneq ($(SWIQI_PROP_ENABLE),)
        ADDITIONAL_BUILD_PROPERTIES += ro.service.swiqi.supported=true
    ifeq ($(SWIQI_PROP_ENABLE), ON)
        ADDITIONAL_BUILD_PROPERTIES += persist.service.swiqi.enable=1
    else
        ADDITIONAL_BUILD_PROPERTIES += persist.service.swiqi.enable=0
    endif
7. 如上,ro.service.swiqi.supported=true 是通过ADDITIONAL_BUILD_PROPERTIES添加到build.prop

四十、如何生成 Lotus GREAT_receiver&speaker_audio_database 为其测试
1. 需要 Lotus的GREAT文件,其中包含 product_lotus_structdata.csv和platform.sql
2. 然后替换vendor/st-ericsson/multimedia/audio/adm/db/ 目录下对应的文件即可

四十一、如何使用sqlite3
1. adb shell
2. 找到需要操作的数据库,一般在/data/data下,比如setting 对应的数据库为/data/data/com.android.providers.settings/databases/settings.db
3. 进入目录/data/data/com.android.providers.settings/databases/
4. 进入sqlite3, #sqlite3 settings.db
5. sqlite>.table //显示db中的所有table
6. sqlite>.schema [table name] //可以显示创建该table的sql statement,也就可以看到table里的fields了
   sqlite>.header on//可以显示字段名
7. 执行sql命令sqlite> XXXX; //注意一定要用;结尾
8. 比如    sqlite>.schema system  
    sqlite>select * from system where name = 'screen_off_timeout';//; 很重要,必须有
    sqlite>update system set value='-1' where name='screen_off_timeout'; //表示永不关掉LCD

四十二、ADB的机制和原理
1. 在init.rc 中有如下内容,
    # adbd is controlled by the persist.service.adb.enable system property
    service adbd /sbin/adbd
        disabled
    # adbd on at boot in emulator
    on property:ro.kernel.qemu=1
        start adbd
    on property:persist.service.adb.enable=1
        start adbd
    on property:persist.service.adb.enable=0
        stop adbd
   所以adb是否enable,是由系统属性 persist.service.adb.enable 来控制

四十三、android 的参数保存机制(adb enable)
1. 保存到数据库,利用sqlite3,例如 setting app 部分参数保存在/data/data/com.android.providers.settings/databases/settings.db中,源代码位于/frameworks/base/packages/settingprovider/src/com/android/providers/settings/databasehelper.java;
2. 利用ContentProvider和ContentResover.例如 /packages/apps/settings/com/android/settings/developmentsettings.java;中有Settings.Secure.putInt(getContentResolver(), Settings.Secure.ADB_ENABLED, 1);设置adb是否可用。 DevelopmentSettings继承PreferenceActivity继承ListActivity继承Activity继承ContextThemeWrapper继承ContextWrapper,对于数据的保存会用到frameworks/base/core/java/android/provider/settings.java中的Settings class;而Settings class提供的全是staic函数,数据会保存到NameValueCache同时还会保存到一个ContentProvider中(具体是访问数据库,还是shareperferences,还需要分析?????)现在不知道,是那个ContentProvider
    a.继续分析 frameworks/base/packages/SettingsProvider/AndroidManifest.xml,有 <provider android:name="SettingsProvider" android:authorities="settings" ....> (表示会在Activity中增加一个标志为"settings"的Contentprovider,这样用Activity中的getContentResolver()函数可以根据参数url中的authority找到对应的contentprovider )与frameworks/base/core/java/android/provider/settings.java中的   public static final String AUTHORITY = "settings"; 一致。
    b.frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/settingsprovider.java;根据分析该ContentProvider包含的是data/data/com.android.providers.settings/databases
    注:附加成果,setting app 的所有参数保存在手机上的data/data/com.android.providers.settings/databases/settings.db数据库中!!!
    c. 针对adb enable,该参数保存在data/data/com.android.providers.settings/databases/settings.db中的表secure有条记录adb_enabled;
3. 注意 利用ContentProvider和ContentResover 机制,只是提供了一种数据共享的方法,后台数据如何组织全靠代码如何写,可以是sqlite3数据库,xml文件,shareperferences.
4. SharePerferences保存的存储文件都存放在/data/data/<package name>/shares_prefs文件夹下的xml文件;
5. frameworks/base/services/java/com/android/server/SystemServer.java中有一个AdbSettingsObserver????当前面的adb_enabled变化时会执行
    private class AdbSettingsObserver extends ContentObserver {
        public AdbSettingsObserver() {
            super(null);
        }
        @Override
        public void onChange(boolean selfChange) {
            boolean enableAdb = (Settings.Secure.getInt(mContentResolver,
                Settings.Secure.ADB_ENABLED, 0) > 0);
            // setting this secure property will start or stop adbd
           SystemProperties.set("persist.service.adb.enable", enableAdb ? "1" : "0");
        }
    }
    而其后有
        // register observer to listen for settings changes
        mContentResolver.registerContentObserver(Settings.Secure.getUriFor(Settings.Secure.ADB_ENABLED),
                false, new AdbSettingsObserver());
    设置adb_enable和通知adb_enable变化的完整流程:
    a. 在packages/apps/settings/src/com/android/settings/developmentsettings.java,比如有Settings.Secure.putInt(getContentResolver(), Settings.Secure.ADB_ENABLED, 0);
    b. 继续调用了framework/base/core/java/android/provider/settings.java中,Secure.putInt-->Secure.putString-->Settings.putString-->resolver.int(uri,values);其中的resolver是Settingsprovider;则继续调用framework/base/packages/settingsprovider/src/com/android/providers/settings/settingsprovider中insert(...)函数-->sendNotify(url);
    c. 没有做更深入的分析,比如传递的参数Uri url,会有啥变化
6. 分析frameworks/base/core/java/android/content/contentresolver.java

四十四、Activity中的getContentResolver()函数详细分析, AndroidManifest.xml的分析执行

四十五、system manager分析
1. init.rc 中有
    service servicemanager /system/bin/servicemanager
    user system
    critical
    onrestart restart zygote
    onrestart restart media
    和
    service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    socket zygote stream 666
    onrestart write /proc/sysrq-trigger c
2. service zygote在frameworks/base/cmds/app_process/app_main.cpp--> main启动 --> runtime.start("com.android.internal.os.ZygoteInit",startSystemServer); 启动ZygoteInit进程,以后所有的java进程均须通过此进程fork而成。
3. frameworks/base/core/jni/AndroidRuntime.cpp中函数start(...)非常重要,virtual machine在这启动和android function在这注册;最后env->CallStaticVoidMethod(startClass, startMeth, strArray); //调用com.android.internal.os.ZygoteInit的main()方法  
4. frameworks/base/core/java/com/android/internal/os/ZygoteInit.java; 启动main函数中有,其中gc()也在这启动
            if (argv[1].equals("true")) { //只支持true参数  
                startSystemServer();       //此处启动systemserver  
            }
            if (ZYGOTE_FORK_MODE) { //进入死循环,zygote进程由此建立,并一直运行;利用Socket通讯,接收ActivityManangerService的请求,Fork应用程序
                runForkMode();
            } else {
                runSelectLoopMode();
            }
    在startSystemServer();中有
        pid = Zygote.forkSystemServer(                   //fork出进程  
                    parsedArgs.uid, parsedArgs.gid,  
                    parsedArgs.gids, debugFlags, null,  
                    parsedArgs.permittedCapabilities,  
                    parsedArgs.effectiveCapabilities);  
            if (pid == 0) {
                handleSystemServerProcess(parsedArgs);//parsedArgs的参数中包含有"com.android.server.SystemServer"
5. 进程fork出来后,关闭socket并初始化进程handleSystemServerProcess
    private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws ZygoteInit.MethodAndArgsCaller {

        closeServerSocket();

        /*
         * Pass the remaining arguments to SystemServer.
         * "--nice-name=system_server com.android.server.SystemServer"
         */
        RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
        /* should never reach here */
    }
     最后调用 所有java进程的共同入口zygoteInit()。
6. frameworks/base/core/java/com/android/internal/os/RuntimeInit.java中函数zygoteInit(String[] argv)
        public static final void zygoteInit(String[] argv)  
                throws ZygoteInit.MethodAndArgsCaller {  
    ...  
        commonInit();  //初始化时区,设置agent  
            zygoteInitNative();    //调用到com_android_internal_os_RuntimeInit_zygoteInit@AndroidRuntime.cpp -> gCurRuntime->onZygoteInit(),此处启动ThreadPool  
    ...  
            invokeStaticMain(startClass, startArgs); //调用com.android.server.SystemServer的main方法  
        }  
7. frameworks/base/core/jni/androidruntime.cpp中
    static JNINativeMethod gMethods[] = {"zygoteInitNative", "()V",(void*) com_android_internal_os_RuntimeInit_zygoteInit}
    static void com_android_internal_os_RuntimeInit_zygoteInit(JNIEnv* env, jobject clazz)
    {
        gCurRuntime->onZygoteInit();
    }
8. frameworks/base/cmds/app_process; 是class AppRuntime : public AndroidRuntime;所以onZygoteInit被重载
    virtual void onZygoteInit()  
    {  
        sp<ProcessState> proc = ProcessState::self();  
        if (proc->supportsProcesses()) {  
        LOGV("App process: starting thread pool.\n");  
        proc->startThreadPool(); //启动线程池处理Binder事件,需要进一步分析,有啥用处?
        }          
    }
9. 继续分析前面invokeStaticMain的运行路径,frameworks/base/services/java/com/android/server/SystemServer.java;
    public static void main(String[] args) {  
        // The system server has to run all of the time, so it needs to be  
        // as efficient as possible with its memory usage.  
        VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);  

        System.loadLibrary("android_servers"); //Load JNI library here that is used by SystemServer,位于手机中/system/lib
        init1(args);     //这里调用到com_android_server_SystemServer.cpp/android_server_SystemServer_init1
    }  
10. frameworks/base/services/jni/com_android_server_SystemServer.cpp中有
    static JNINativeMethod gMethods[] = {
        /* name, signature, funcPtr */
        { "init1", "([Ljava/lang/String;)V", (void*) android_server_SystemServer_init1 },
    };
    调用路径android_server_SystemServer_init1-->frameworks/base/cmds/system_server/library/system_init.cpp中函数system_init
    extern "C" status_t system_init()
    {
        ...
       // Start the sensor service
        SensorService::instantiate();//sensor service在这启动,意外收获
        if (!proc->supportsProcesses()) { //在phone上,这些service在mediaserver中创建。模拟器上,以下service在此进程创建  
        // Start the AudioFlinger  
        AudioFlinger::instantiate();  
        // Start the media playback service  
        MediaPlayerService::instantiate();  
        // Start the camera service  
        CameraService::instantiate();  
        // Start the audio policy service  
        AudioPolicyService::instantiate();  
        }  
        AndroidRuntime* runtime = AndroidRuntime::getRuntime();

        LOGI("System server: starting Android services.\n");
        runtime->callStatic("com/android/server/SystemServer", "init2");//调用init2@SystemServer.java,在这里创建工作线程以启动各java服务并进入循环处理各service请求
    }
11. 从上分析来看,frameworks/base/services/java/com/android/server/SystemServer.java, main函数中-->init1-->init2 如此关联起来的-->ServerThread-->run实现Java Service注册初始化及进入SystemServer事件处理循环;在run中通过addservice注册很多sevice,另外还有启动 ActivityManagerService.main(factoryTest);和((ActivityManagerService)ActivityManagerNative.getDefault()).systemReady(new Runnable()...)
12. frameworks/base/services/java/com/android/server/am/ActivityManagerService.java; 中main函数
    public static final Context main(int factoryTest) {
            AThread thr = new AThread();//作为ActivityManager的工作线程,在其中处理ActivityManager相关的消息
            thr.start();
        ...
        ActivityThread at = ActivityThread.systemMain();//加载system应用,并把此线程作为SystemServer进程的system线程
        ...
        m.startRunning(null, null, null, null); //初始化变量并设置system ready为true  
    }
13. systemReady@ActivityManagerService.java--> mMainStack.resumeTopActivityLocked(null);-->mService.startHomeActivityLocked();-->mMainStack.startActivityLocked ,由此启动了Home apk;
14. frameworks/base/core/java/android/app/activitythread.java; 中systemMain()、startRunning和systemReady函数

四十六、android binder机制

四十七、如何调试 linux kernel的crash
1. System.map是一个特定内核的内核符号表,它是你当前运行的内核的System.map的链接,该文件位于out/target/product/lotus[项目名称]/obj/kernel/System.map
2. 如果kernel出错,可以根据出错的地址,通过system.map找到对应的函数。
3. 如果kernel crash,就会有dump info,具体内容如下
    I/DEBUG   ( 1417): pid: 1434, tid: 1460  >>> system_server <<<   //说明那个process crash了
    I/DEBUG   ( 1417): signal 11 (SIGSEGV), fault addr 00000000     //crash的类别,如果不清楚,可用kill -l列出所有的signal类别
    r0 xxx r1 xxx .... 当前寄存器的值
    #00  pc 000009ba  /system/lib/hw/sensors.default.so    //当前出错的so或exe, 000009ba表示出错的地方,那又如何对应其中的具体函数?
    #01  pc 00003244  /system/lib/libandroid_servers.so     //android会dump出栈的内容。在unix/linux中,一般情况下栈会向低地址位置移动,android也不例外。在上面dump的信息中,越靠上(地址越小)表示这是栈顶位置,越往下表示栈底。
    stack:
    ...
    4a570b54  8150218c  /system/lib/hw/sensors.default.so //4a570b54表示栈空间的地址;8150218c栈单元中的内容;表示该内容对应的代码sensors.default.so。 需要注意的是,这里显示的地址为完整形式,即基地址+偏移量
4. 查看对应的pid maps信息,在手机上$cat /proc/1434/maps,可以查看到
    81500000-81502000 r-xp 00000000 00:0f 953        /system/lib/hw/sensors.default.so
    81502000-81503000 rwxp 00002000 00:0f 953        /system/lib/hw/sensors.default.so
    //这里上面一行(不可写)为sensors.default.so的文本段,下一行为数据段(可读写)。可以看到sensors.default.so被映射到了system_server进程的81500000~81503000地址空间中。将代码完整地址8150218c减去基地址81500000,可以得到libc.so中的偏移地址0000218c。另外注意到,8150218c映射到数据段,说明出问题时栈保存有 sensors.default.so中某一个函数中的局部变量。
5. 反汇编代码,有工具arm-eabi-objdump(位于prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin),执行如下命令:
    ./arm-eabi-objdump -t sensors.default.so |sort > sensors.default.dump
    或者 ./arm-eabi-objdump -dS sensors.default.so > sensors.default.dump //则可以查看其汇编代码了,用于进一步分析定位
    00000990 <sensors__get_sensors_list>:
    000009a8 <open_sensors_device>: //000009ba与其最为接近
    00000a8c <pick_sensor>:
6. 用命令nm -gCl sensors.default.so; 还可以列出所有在lib中用到的符号和地址,这样也可根据地址找到对应函数

四十八、T32/Lauterbach如何安装
1. https://wiki.sonyericsson.net/mib/Lauterbach_Installation#Install.2FUpdate_Lauterbach_Trace32_Scripts
2. 安装semc-trace32-sw_31731+git20110822.d77042cd_amd64.deb; 用#sudo dpkg -i xxx.deb或者通过ubuntu界面双击安装
3. #sudo apt-get install semc-trace32-scripts
4. #t32_start --install
5. #dpkg -l semc-trace32* ; 检测是否安装ok;CMM脚本文件位于/opt/t32
6. 把profile_riogrande 拷贝到~/t32/profiles,如何使用 https://wiki.sonyericsson.net/mib/Lauterbach_User_Guide
7. 进入代码目录,运行#t32_start profile_riogrande; 最好在code source 的根目录下运行,这样当前目录就是代码目录.
8. 进入T32 应用界面,配置好参数和路径后,运行load图标,如果JTag连接没有问题,则在下方会显示running 的绿色条
9. 单击set图标,进入Target Setup Dialog, 设置kernel load file(vmlinux):???/out/target/product/lotus/obj/kernel/vmlinux,vmlinux是没有(zImage是压缩过的内核)压缩过的内核,就是由piggy.o、head.o、misc.o、head-xxxx.o(和HW相关)组成的。 选上Use recursive source path, Debug linux on APP side, SMP debugging, Modem TAP is on;
10. 运行load,会出现"Lauterbach is waitting ..." 对话框,然后手机 power on.
11. 如果正常,出现提示“Target setup done, ready to debug...”, 然后单击 运行按钮
12. 设置断点view-->symbols-->Browse function (根据函数设置断点),在输入框直接输入 函数名称 即可
13. 单击 暂停 按钮,停止simlulator 运行,然后在代码中 单击右键 设置断点即可。
14. 进行单步调试时,逐个进入函数嵌套,可以单击 Source/List 图标,显示当前运行的源代码。,如果没有代码显示,单击 Mode 按钮,切换显示模式
15. 设置断点,需要

四十九、如何手动mount,umount sd card
1. 查看手机上 /dev/block/vold/*:* 下的块设备有那些,比如 外部sdcard 的设备路径为/dev/block/vold/179:33
2. 查看手机 /mnt下的目录,一般外部块设备都是挂载在该目录下,但是该目录下需要root权限才能创建目录,例如有/mnt/ext_card,/mnt/usbdisk
3. 用#mount 或 #cat /proc/mounts,查看已经mount的设备,比如有:/dev/block/vold/179:33 /mnt/ext_card vfat rw,....; 表示块设备外部sdcard挂载在/mnt/ext_card下
4. #umount /mnt/ext_card 则可以取消挂载在 该目录下的设备
5. #mount -t vfat /dev/block/vold/179:33 /mnt/usbdisk 则可以重新挂载 外部sdcard设备到/mnt/usbdisk 下

五十、如何获取两个版本之间的差异
1. http://rassist.sonyericsson.net/relcheck/v3/relcheck.pl
2. 在下拉菜单中选择两个不同的软件版本
3. 执行pretty short diff

五十一、Android linux kernel crash dump机制
1. CONFIG_CRASH_DUMP会定义是否crash dump,分析kernel/kernel/crash_dump.c,其中有一个重要变量unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX; //一个重要变量记录内核装载的位置,用以判断是正常启动还是kdump启动。
2. kernel/fs/proc/vmcore.c中
    vmcore_list:主要接收挂掉内核的内存片断,所有的vmcore组成一个链表,这个链表就是内存按照从小到大的顺序,其实之所以用此结构体组成链表来装载挂掉内核的内存是因为内核本身就是elf的,elf中就是将所有的内存看作一系列的节,所有的节组成了整个linux内核映射空间,linux的内核 vmlinuz就是映射在这个空间的,在模块初始化的时候会调用vmcore_init;
    vmcore_init: 其中 parse_crash_elf_headers()--->本质上内核文件是一个elf映像,这个函数要做的就是将内核映像(注意是已经crash的内核)的elf诸多内存节字段设置到内核专门为kdump准备的一个list中,即上述的链表vmcore_list。
    proc_vmcore = proc_create("vmcore", S_IRUSR, NULL, &proc_vmcore_operations)--->如果系统崩溃,那么在kdump的机制kexec中起来新的内核后,会将垮掉内核的内存映像放入到/proc/vmcore中,其实并不是把几百兆的数据存入了文件,procfs文件系统本身就不是用来在硬盘上存放数据的,它只是提供了一个存取接口,通过这个存取接口用户可以得到一些内核的信息
3. 如何触发crash dump?????? 可以手动
    # echo 'c' > /proc/sysrq-trigger;这造成kernel panic(CONFIG_PROC_FS必须=y),紧跟着系统重启kdump内核。当启动进程进入到启动kdump服务器时,vmcore将会被拷贝到你在/etc/kdump.conf文件中指定的位置。
4. 需要继续深入分析??????,kernel/driver/char/sysrq.c-->write_sysrq_trigger-->__handle_sysrq
5. kernel/driver/char/sysrq.c 变量sysrq_key_table 具体说明了写入/proc/sysrq-trigger的含义,比如# echo 'b' > /proc/sysrq-trigger,重启手机
6. 针对# echo 'c' > /proc/sysrq-trigger,对应的是sysrq_crash_op(sysrq_key_table中)-->sysrq_handle_crash
    static void sysrq_handle_crash(int key, struct tty_struct *tty)
    {
        char *killer = NULL;
        panic_on_oops = 1;    /* force panic */
        wmb();
        *killer = 1;
    }//具体如何触发到__die,还需要分析???????
7. 系统会捕捉到exception->__dabt_svc(asm)-->do_dataabort->do_page_fault-->__do_kernel_fault, 以上会触发 kernel/arch/arm/kernel/traps.c -->die--> __die(...);    
    a. notify_die
    b. print_modules-->输出模块名称
    c. __show_regs-->输出当前所有寄存器的值
    d. dump_mem--> 输出当前thead的stack, 一段mem的值
    e. dump_backtrace-->unwind_backtrace-->unwind_frame和dump_backtrace_entry -->输出函数call stack信息
    f. dump_instr-->输出当前执行的code ???
8. 在手机上设置 /proc/sys/kernel/panic 为0,则如果系统出现panic,手机不会reboot
9. kernel/arch/arm/kernel/traps.c-->die(...),oops技术,需要好好学习
    oops_enter();
    oops_exit();//会输出 ”---[ end trace ????? ]---“的log
10. /kernel/kernel/kexec.c中 crash_kexec???? 会做啥工作
11. 因为panic_on_oops = 1, 所以运行die-->panic("Fatal exception")@kernel/kernel/panic.c-->dump_stack()-->dump_backtrace(NULL, NULL)//输出当前的call stack而不是出问题处的call stack;
12. panic("Fatal exception")-->会调用到kenel/kernel/notifier.c中atomic_notifier_call_chain->notifier_call_chain-->ret = nb->notifier_call(nb, val, v);-->crash_notes_save_this_cpu-->dump_regs和输出“@panic_name@”log
13. 紧接着kernel/kernel/panic.c中panic->emergency_restart(log: Rebooting in %d seconds) 开始重启(This will not be a clean reboot,会保留上次panic的context)
14. 系统开始重新启动,但是因为有crash flag,所以会启动ramdump的kernel
15. [Last word from S1 BOOT]“Jumping to kernel at address [0x13008000]”该内核地址是最小系统内核的地址,正常是在[0x00008000]
16. "Linux version 2.6.35.7+"系统最小内核的版本ramdump kernel,正常系统内核的版本 “Linux version 3.0.8+”
17. kernel/arch/arm/boot/compressed/head.s
18. kernel/arch/arm/boot/compressed/misc.c-->decompress_kernel
19. kernel/arch/arm/kernel/vmlinux.lds.s,中刚开始有函数    OUTPUT_ARCH(arm) 和ENTRY(stext)
20. kernel/arch/arm/kernel/head.S,中有ENTRY(stext)的定义-->ldr    r13, =__mmap_switched//执行到函数__mmap_switched
21. arch/arm/kernel/head-common.S,中有函数__mmap_switched-->b    start_kernel会执行到C代码的入口start_kernel

22. ramdumpV2可参考vendor/semc/system/ramdump,(https://wiki.sonyericsson.net/androiki/Ramdump)
23. ramdumpV2可以用repo init -u git://review.sonyericsson.net/platform/vendor/semc/ramdump-manifest -b <branch>, 但目前不知道如何make;
24. 针对ramdumpV3, 会逐个执行main@/ramdump/apps/rdinit/main.c, main@/ramdump/apps/rdapp/main.c

kernel-build-sin.sh

xx. kernel_restart@kernel/kernel/sys.c

五十二、torch fail
1. camera led flash 设备路径 /sys/devices/platform/nmk-i2c.2/i2c-2/2-0053
2. #echo 1 > torch_enable 可以打开led flash; #echo 0 > torch_enable 可以关闭led flash
3. Hallon(neo)手机的torch 路径为sys/devices/i2c-0/0-0053/torch_enable
4. 检查device/semc/lotus/files/[product]/flashled_param_config.cfg中关于torch的设置

五十三、ICS SW中SD Card不能被detect和mount
1. SD card不能被detect, 是没有设置detect gpio pin. 修改kernel/arch/arm/mach-ux500/board-rio-grande-sdi.c
    static struct mmci_platform_data mop500_sdi3_data = {
        .gpio_cd    = CARD_INS_DETECT_N, //实际上是GPIO84
    }
2. SD card不能被mount,是由于sdi3 mmc card块设备的配置有问题,也就是/devices/sdi3/mmc_host/mmc3/mmc3不能被正确mount. 修改文件kernel/arch/arm/mach-ux500/gpio-lotus.c中,需要有如下修改
static pin_cfg_t mop500_pins_default[] = {
    GPIO217_GPIO            |       PIN_OUTPUT_LOW,
}
/* sdi3 - SD/MMC card */
static UX500_PINS(mop500_pins_sdi3,
//      GPIO84_GPIO             |       PIN_INPUT_NOPULL,
//      GPIO85_GPIO             |       PIN_OUTPUT_LOW,
//      GPIO139_GPIO            |       PIN_OUTPUT_LOW,
        GPIO215_MC3_DAT2DIR     |       PIN_OUTPUT_HIGH,
        GPIO216_MC3_CMDDIR      |       PIN_OUTPUT_LOW,
//      GPIO217_GPIO            |       PIN_OUTPUT_LOW,
        GPIO218_MC3_DAT0DIR     |       PIN_OUTPUT_HIGH,
}


4.0.2.A.0.69

原创粉丝点击