嵌入式系统文件系统比较
http://blog.sina.com.cn/s/blog_53ad41a50100eptc.html
LINUX系统性能调谐
http://www.host01.com/article/server/00070002/0621409052193755_2.htm
怎样限制或者修改/dev/shm的大小
http://www.linuxfly.cn/html/65/t-665.html
====================================================================
====================================================================
3. 制作交叉工具链
3.1 什么是工具链
3.2 获取交叉工具链的几种途径
3.3 android工具链与gnu工具链的比较
每一个软件,在编译的过程中,都要经过一系列的处理,才能从源代码变成可执行的目标代码。这一系列处理包括:预编译,高级语言编译,
汇编,连接及重定位。这一套流程里面用到的每个工具和相关的库组成的集合,就称为工具链(tool chain)。以GNU的开发工具GCC为例,
它就包括了预编译器cpp,c编译器gcc,汇编器as,和连接器ld等。在GNU自己对工具链定义中,还加进了一套额外的用于处理二进制包的
工具包binutils,整个工具链应该是GCC+binutils+Glibc, binutils其实与Glibc关系不是很大,它可以被独立安装的,所以GNU工具
链也可以狭义地被理解为GCC+Glibc。
要构建出一个交叉工具链,需要解决三个问题。一是这个工具链必须是可以运行在原工作站平台上的。二是我们需要更换一个与目标平台对应的
汇编器,使得工具链能产生对应的目标代码,三是要更换一套与目标平台对应的二进制库,使得工具链在连接时能找到正确的二进制库。
3.2 获取交叉工具链的几种途径
3.2.1 利用源代码制作交叉工具链
网上直接下载工具链或者从方案商处获取(如:marvell)
下载地址:
http://www.angstrom-distribution.org/unstable/
3.2.2 用脚本制作工具链
3.2.2.1 croostool-0.43
http://www.kegel.com/crosstool/crosstool-0.43.tar.gz
制作工具链的源码包搭配情况: http://www.kegel.com/crosstool/crosstool-0.43/buildlogs/
3.2.2.2 buildroot
http://buildroot.uclibc.org/downloads/snapshots/buildroot-snapshot.tar.bz2
若想详细地了解buildroot可参考该文档http://buildroot.uclibc.org/buildroot.html
3.2.3 利用OE制作工具链
http://www.scratchbox.org/wiki/OpenEmbedded
3.3 android工具链与gnu工具链的比较
Android所用的Toolchain(即交叉编译工具链)可从下面的网址下载:
http://android.kernel.org/pub/android-toolchain-20081019.tar.bz2。如果下载了完整的Android项目的源代码,则可以在
“/prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin”目录下找到交叉编译工具,比如Android所用的
arm-eabi-gcc-4.2.1。Android并没有采用glibc作为C库,而是采用了Google自己开发的Bionic Libc,它的官方Toolchain也是基于
Bionic Libc而并非glibc的。这使得使用或移植其他Toolchain来用于Android要比较麻烦:在Google公布用于Android的官方Toolchain之前,
多数的Android爱好者使用的Toolchain是在http://www.codesourcery.com/gnu_toolchains/arm/download.html 下载的一个通用的
Toolchain,它用来编译和移植Android 的Linux内核是可行的,因为内核并不需要C库,但是开发Android的应用程序时,直接采用或者移植其他
的Toolchain都比较麻烦,其他Toolchain编译的应用程序只能采用静态编译的方式才能运行于Android模拟器中,这显然是实际开发中所不能接
受的方式。目前尚没有看到说明成功移植其他交叉编译器来编译Android应用程序的资料。
与glibc相比,Bionic Libc有如下一些特点:
- 采用BSD License,而不是glibc的GPL License;
- 大小只有大约200k,比glibc差不多小一半,且比glibc更快;
- 实现了一个更小、更快的pthread;
- 提供了一些Android所需要的重要函数,如”getprop”, “LOGI”等;
- 不完全支持POSIX标准,比如C++ exceptions,wide chars等;
- 不提供libthread_db 和 libm的实现
另外,Android中所用的其他一些二进制工具也比较特殊:
- 加载动态库时使用的是/system/bin/linker而不是常用的/lib/ld.so;
- prelink工具不是常用的prelink而是apriori,其源代码位于” /build/tools/apriori”
- strip工具也没有采用常用的strip,即“/prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin”
目录下的arm-eabi-strip,而是位于/out/host/linux-x86/bin/的soslim工具。
参考文档:
CLFS2.0原理分析
http://www.linuxsir.org/bbs/showthread.php?t=267672
Cross-Compiled Linux From Scratch
http://cross-lfs.org/view/clfs-sysroot/arm/
全手工制作arm-linux交叉编译工具链《一》
http://blog.chinaunix.net/u2/62168/showart_1898748.html
自己制作arm-linux交叉编译环境(一)-scratch篇
http://blog.csdn.net/chenzhixin/archive/2007/01/12/1481442.aspx
如何建立交叉编译工具链
http://www.decell.org/article.asp?id=53
Android Toolchain与Bionic Libc
http://www.top-e.org/jiaoshi/html/?151.html
ndroid编译环境(2) - 手工编译C模块
=================================================
=================================================
4. 软件编译常识
4.1 链接器和加载器
4.2 android 的标准链接器和加载器
4.3 Makefile基本语法
何为链接器和加载器?
链接器为ld,加载为ld-linux.so.2,两个的区别很大,一个编译时用,一个运行时用,ld负责在编译的搜索路径里找到要求的库,并查看
是否有提供了需要的 符号(如函数等),如果有,记录相关信息到程序中,由ld-linux.so.2在执行时查找到该库,并根据相关信息进行需
要符号的重定位等工作.注意 这两者的搜索库的方式是不同的。
动态连接器通常是指的动态加载器(不要与 Binutils 里的标准连接器 ld 混淆了)。动态连接器由 Glibc 提供,用来
找到并加载一个程序运行时所需的共享库,在做好程序运行的准备之后,运行这个程序。动态连接器的名称通常是
ld-linux.so.2,标准连接器 ld 由 Binutils 这个包提供。
标准连接器
查看gcc使用的标准连接器
mhf@mhf-desktop:/usr/local/marvell-arm-linux-4.1.1/bin$ arm-linux-gcc -print-prog-name=ld
编译时库的搜索路径,以下几种方式让连接器去找需要的库
1. 编译的时候明确指定,如: gcc test.c ./say.so -o test中的 ./say.so
2. 编译 Binutils 的时候通过LIB_PATH 变量指定,
如:make -C ld LIB_PATH=/tools/lib
-C ld LIB_PATH=/tools/lib
这个选项重新编译 ld 子目录中的所有文件。在命令行中指定 Makefile 的 LIB_PATH 变量值,使它明确指向/tools/lib工具目录,
以覆盖默认值。这个变量的值指定了连接器的默认库搜索路径。
来源:Linux From Scratch - 版本 6.4第 5 章 构建临时系统 5.4. Binutils-2.18 - 第一遍
http://www.bitctp.org/lfsbook-6.4/chapter05/binutils-pass1.html
3. 在源码包configure的时候通过 --with-lib-path 指定,或者 --lib- path
例如:
binutils-2.18/configure --prefix=/tools --disable-nls --with-lib-path=/tools/lib
配置选项的含义:
--with-lib-path=/tools/lib
告诉配置脚本在为编译 Binutils 的过程中使用正确的库搜索路径,也就是将 /tools/lib 传递给连接器。这防止连接器搜索宿主系统中的库文件目录。
来源: Linux From Scratch - 版本 6.4 第 5 章 构建临时系统 lfs 5.13. Binutils-2.18 - 第二遍
http://www.bitctp.org/lfsbook-6.4/chapter05/binutils-pass2.html
4. 到 ld –verbose | grep SEARCH 列出的默认目录下去找
5. -L/usr/gpephone/lib 指定的目录找
经常以 LDFLAGS=" -L/usr/gpephone/lib -L/lib -L/usr/lib -L/usr/X11R7/lib" 的方式传入
参数 -rpath 与 -rpath-link
如果使用了'-rpath'选项, 那运行时搜索路径就只从'-rpath'选项中得到
'nodefaultlib'标志一个对象,使在搜索本对象所依赖的库时,忽略所有缺省库搜索路径.
LDFLAGS="-Wl,-rpath-link=/usr/gpephone/lib/:/usr/gphone/lib:/usr/local/lib -L/usr/gpephone/lib -L/usr/gphone/lib"
-rpath 与 -rpath-link 的特性:
1. 在编译的时候我们都可以使用这两个路径,
2. '-rpath'跟'-rpath_link'的不同之处在于,由'-rpath'指定的路径会被包含到可执行程序中,并在运行时使用,
而'-rpath-link'选项仅仅在链接时起作用。
-dumpspecs Display all of the built in spec strings
-dumpversion Display the version of the compiler
-dumpmachine Display the compiler's target processor
-print-search-dirs Display the directories in the compiler's search path
-print-prog-name= Display the full path to compiler component
-specs= Override built-in specs with the contents of
-Wa, Pass comma-separated on to the assembler
-Wp, Pass comma-separated on to the preprocessor
-Wl, Pass comma-separated on to the linker
从工具链内建的规范中查看动态加载器
gcc -dumpspecs | grep dynamic-linker //本机
查看编译起所指定的动态加载器
1. s3c2440 (arm9tdmi) 平台的工具链
/scratchbox/compilers/arm-9tdmi-softfloat-linux-gcc-3.4.4-glibc-2.3.5/bin/arm-softfloat-linux-gnu-gcc -dumpspecs | grep dynamic-linker
/scratchbox/compilers/arm-softfloat-linux-gcc-3.4.4-glibc-2.3.5/bin/arm-softfloat-linux-gnu-gcc -dumpspecs | grep dynamic-linker
2. marvell 的工具链
/scratchbox/compilers/marvell-arm-linux-4.1.1/bin/arm-linux-gcc -dumpspecs | grep dynamic-linker
3. scrathbox 中工具链 host-gcc
/scratchbox/compilers/host-gcc/bin/host-gcc -dumpspecs | grep dynamic-linker
如果我们在编译的时候给编译起 gcc 指定 -specs=/scratchbox/compilers/host-gcc/host-gcc.spec ,那么-specs指定
的规范将会覆盖工具链内建的规范。
cat /scratchbox/compilers/host-gcc/host-gcc.specs | grep ld 有如下内容:
-dynamic-linker /scratchbox/host_shared/lib/ld.so
/scratchbox/compilers/host-gcc/bin/gcc -specs=/scratchbox/compilers/host-gcc/host-gcc.specs
mhf@mhf-desktop:/usr/local/marvell-arm-linux-4.1.1/arm-iwmmxt-linux-gnueabi/bin$ ./gcc -dumpspecs|grep dynamic-linker
gcc -dumpspecs | sed 's@/lib/ld-linux.so.2@/tools&@g' | sudo tee `dirname $(gcc -print-libgcc-file-name)`/specs
cat `dirname $(gcc -print-libgcc-file-name)`/specs | grep tools
查看本机应用程序使用的动态加载器
readelf -l /usr/bin/make | grep interpreter
[Requesting program interpreter: /lib/ld-linux.so.2]
查看 scratchbox 中应用程序使用的动态加载器
readelf -l /scratchbox/tools/bin/make | grep interpreter
[Requesting program interpreter: /scratchbox/host_shared/lib/ld.so]
cd ~/svn/mohuifu.svn/trunk/mysource/compiler_test
/scratchbox/compilers/host-gcc/bin/gcc -specs=/scratchbox/compilers/host-gcc/host-gcc.specs -o ld.so.test1 ld.so.test.c
/scratchbox/compilers/host-gcc/bin/gcc -o ld.so.test2 ld.so.test.c
readelf -l ./ld.so.test1 | grep interpreter
readelf -l ./ld.so.test2 | grep interpreter
其他示例:
readelf -l /scratchbox/tools/bin/make | grep interpreter
readelf -l /usr/bin/make | grep interpreter
分别显示:
[Requesting program interpreter: /scratchbox/host_shared/lib/ld.so]
[Requesting program interpreter: /lib/ld-linux.so.2]
下面的方式也可以查看应用程序所使用的加载器
strings /scratchbox/tools/bin/make |grep lib
strings /usr/bin/make |grep lib
分别为:
/scratchbox/host_shared/lib/ld.so
/lib/ld-linux.so.2
查看应程序加载器库的搜索路径
显示 scratchbox 中加载器的库搜索路径
strings /scratchbox/host_shared/lib/ld.so |grep lib
display library search paths
/scratchbox/host_shared/lib/
/scratchbox/tools/lib/
显示本机中加载器的库搜索路径
strings /lib/ld-linux.so.2 |grep lib
display library search paths
/lib/
/usr/lib/
/lib/i486-linux-gnu/
/usr/lib/i486-linux-gnu/
ldd 验证应用程序所使用动态库
ldd /scratchbox/tools/bin/make
libc.so.6 => /scratchbox/host_shared/lib/libc.so.6 (0xb7ef9000)
/scratchbox/host_shared/lib/ld.so => /scratchbox/host_shared/lib/ld.so (0xb802f000)
ldd /usr/bin/make
librt.so.1 => /lib/tls/i686/cmov/librt.so.1 (0xb7fb9000)
libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb7e5b000)
libpthread.so.0 => /lib/tls/i686/cmov/libpthread.so.0 (0xb7e42000)
/lib/ld-linux.so.2 (0xb7fd5000)
参考文档:
交叉编译中libtool相关的问题
http://hi.baidu.com/lieyu063/blog/item/9c99a2dd23e41f365882dd39.html
静态库和共享库库的定位搜索路径
http://blog.csdn.net/lwhsyit/archive/2008/08/26/2830783.aspx
Linux动态连接原理
http://blog.chinaunix.net/u2/67984/showart_1359874.html
程序编译链接运行时对库关系的探讨(原创)
http://www.360doc.com/content/061107/09/13188_251964.html
http://lamp.linux.gov.cn/Linux/LFS-6.2/chapter05/toolchaintechnotes.html
[Linux命令] ld 中文使用手册完全版(译)
http://blog.csdn.net/rstevens/archive/2008/01/28/2070568.aspx
scratchbox 是mameo (nokia) 提供的一个集成开发环境,可以去官方网站:
http://www.scratchbox.org/
http://www.scratchbox.org/download/
4.2 android 的标准链接器和加载器
android的标准链接器 ./prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/arm-eabi-ld
android 中标准连接器搜索库的路径
./prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/arm-eabi-ld -verbose | grep SEARCH
SEARCH_DIR("/android/mathias/armdev/toolchain-eabi-4.2.1/arm-eabi/lib");
Android编译环境所用的交叉编译工具链是./prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/arm-eabi-gcc,
-I和-L参数指定了所用的C库头文件和动态库文件路径分别是bionic/libc /include 和out/target/product/generic/obj/lib,
其他还包括很多编译选项以及-D所定义的预编译宏。这里值得留意的是参数“-Wl,-dynamic-linker,/system/bin/linker”,它指定了
Android专用的动态链接器/system/bin/linker,而不是通常所用的ld.so。
上面的“make clean-$(LOCAL_MODULE)”是Android编译环境提供的make clean的方式。
android中应用程序使用的加载器
strings out/target/product/littleton/obj/EXECUTABLES/rild_intermediates/rild | grep link
/system/bin/linker
./prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/arm-eabi-gcc -dumpspecs|grep dynamic-linker
%{mbig-endian:-EB} %{mlittle-endian:-EL} %{static:-Bstatic} %{shared:-shared} %{symbolic:-Bsymbolic}
%{!static:%{shared: -Bsymbolic} %{!shared:%{rdynamic:-export-dynamic} %{!dynamic-linker:-dynamic-linker /system/bin/linker}}} -X
android中加载器搜索库的路径
strings /nfsroot/rootfs/system/bin/linker | grep lib
/system/lib
/lib
生成的可执行程序可用file和readelf命令来查看一下:
file out/target/product/littleton/obj/EXECUTABLES/rild_intermediates/rild
out/target/product/littleton/obj/EXECUTABLES/rild_intermediates/rild: ELF 32-bit LSB executable,
ARM, version 1 (SYSV), dynamically linked (uses shared libs), stripped
readelf -d out/target/product/littleton/obj/EXECUTABLES/rild_intermediates/rild |grep NEEDED
0x00000001 (NEEDED) Shared library: [liblog.so]
0x00000001 (NEEDED) Shared library: [libcutils.so]
0x00000001 (NEEDED) Shared library: [libril.so]
0x00000001 (NEEDED) Shared library: [libc.so]
0x00000001 (NEEDED) Shared library: [libstdc++.so]
0x00000001 (NEEDED) Shared library: [libm.so]
0x00000001 (NEEDED) Shared library: [libdl.so]
这是ARM格式的动态链接可执行文件,运行时需要libc.so和libm.so。“not stripped”表示它还没被STRIP。嵌入式系统中为节省空间通常
将编译完成的可执行文件或动态库进行STRIP,即去掉其中多余的符号表信息。在前面“make helloworld showcommands”命令的最后我们也
可以看到,Android编译环境中使用了out/host/linux-x86/bin/soslim工具进行STRIP。
4.3 Makefile基本语法
Makefile详解(超级好)
linux/Unix环境下的make和makefile详解
http://www.unlinux.com/doc/program/20051026/2365.html
跟我一起写 Makefile
http://dev.csdn.net/develop/article/20/20025.shtm
=================================================
=================================================
5. 设置模块流程分析
rild 流程分析
5.1 设置 pin 状态,pin认证
5.1.1 设置pin状态
5.1.2 修改sim卡pin
5.1.3 pin认证流程
5.2 网络设置
5.3 屏幕背光设置
5.4 获取,显示电池状态
================
EditPinPreference.java (packages\apps\settings\src\com\android\settings)
private OnPinEnteredListener mPinListener;
protected void onDialogClosed(boolean positiveResult)
mPinListener.onPinEntered(this, positiveResult);
执行 SimLockSettings.java (packages\apps\settings\src\com\android\settings)中函数:
public void onPinEntered(EditPinPreference preference, boolean positiveResult)
修改pin状态: tryChangeSimLockState();
修改pin: tryChangePin();
5.1.1 设置pin状态
private void tryChangeSimLockState()
Message callback = Message.obtain(mHandler, ENABLE_SIM_PIN_COMPLETE);
mPhone.getSimCard().setSimLockEnabled(mToState, mPin, callback);
进入sim lock 菜单会显示初始化pin状态,是通过下面语句得到:
mPinToggle.setChecked(mPhone.getSimCard().getSimLockEnabled());
mPhone.getSimCard().setSimLockEnabled(mToState, mPin, callback)调用的是文件:
GsmSimCard.java (frameworks\base\telephony\java\com\android\internal\telephony\gsm)中的函数:
public void setSimLockEnabled (boolean enabled,String password, Message onComplete) {
int serviceClassX;
serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE +
CommandsInterface.SERVICE_CLASS_DATA +
CommandsInterface.SERVICE_CLASS_FAX;
mDesiredPinLocked = enabled;
phone.mCM.setFacilityLock(CommandsInterface.CB_FACILITY_BA_SIM,
enabled, password, serviceClassX,
obtainMessage(EVENT_CHANGE_FACILITY_LOCK_DONE, onComplete));
phone.mCM.setFacilityLock 调用的是文件:
RIL.java (frameworks\base\telephony\java\com\android\internal\telephony\gsm)中的函数:
public void
setFacilityLock (String facility, boolean lockState, String password,
int serviceClass, Message response)
{
String lockString;
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_SET_FACILITY_LOCK, response);
if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
// count strings
rr.mp.writeInt(4);
rr.mp.writeString(facility);
lockString = (lockState)?"1":"0";
rr.mp.writeString(lockString);
rr.mp.writeString(password);
rr.mp.writeString(Integer.toString(serviceClass));
send(rr);
}
设置应用程序向 rild 发送 RIL_REQUEST_SET_FACILITY_LOCK 请求的 socket消息,
android的初始源代码中 RIL_REQUEST_SET_FACILITY_LOCK 请求,在参考实现 Reference-ril.c
(hardware\ril\reference-ril) 中没有实现。
我们需要做得工作是:
==========
5.1.2 修改sim卡pin
private void tryChangePin()
mPhone.getSimCard().changeSimLockPassword(mOldPin,mNewPin, callback);
mPhone.getSimCard 调用的是文件:
GsmSimCard.java (frameworks\base\telephony\java\com\android\internal\telephony\gsm)中的函数:
public void changeSimLockPassword(String oldPassword, String newPassword,
Message onComplete)
phone.mCM.changeSimPin(oldPassword, newPassword,
obtainMessage(EVENT_CHANGE_SIM_PASSWORD_DONE, onComplete));
phone.mCM.changeSimPin 调用的是文件:
RIL.java (frameworks\base\telephony\java\com\android\internal\telephony\gsm)中的函数:
public void
changeSimPin(String oldPin, String newPin, Message result)
{
RILRequest rr = RILRequest.obtain(RIL_REQUEST_CHANGE_SIM_PIN, result);
if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
rr.mp.writeInt(2);
rr.mp.writeString(oldPin);
rr.mp.writeString(newPin);
send(rr);
}
rild端处理流程:
5.1.3 pin认证流程
========
5.2 网络设置
=======
5.3 屏幕背光设置
packages/apps/Settings/src/com/android/settings/BrightnessPreference.java
背光设置滚动条和关闭按钮都会调用 setBrightness(mOldBrightness);
public void onProgressChanged(SeekBar seekBar, int progress,boolean fromTouch)
protected void onDialogClosed(boolean positiveResult)
private void setBrightness(int brightness) {
try {
IHardwareService hardware = IHardwareService.Stub.asInterface(
ServiceManager.getService("hardware"));
if (hardware != null) {
hardware.setBacklights(brightness);
}
} catch (RemoteException doe) {
}
}
调用硬件服务器 HardwareService 的 setBacklights 函数
HardwareService.java (frameworks\base\services\java\com\android\server):
public void setBacklights(int brightness)
{
. . .
// Don't let applications turn the screen all the way off
brightness = Math.max(brightness, Power.BRIGHTNESS_DIM);
setLightBrightness_UNCHECKED(LIGHT_ID_BACKLIGHT, brightness);
setLightBrightness_UNCHECKED(LIGHT_ID_KEYBOARD, brightness);
setLightBrightness_UNCHECKED(LIGHT_ID_BUTTONS, brightness);
. . .
}
void setLightOff_UNCHECKED(int light)
{
//本地调用 setLight_native
setLight_native(mNativePointer, light, 0, LIGHT_FLASH_NONE, 0, 0);
}
void setLightBrightness_UNCHECKED(int light, int brightness) {
int b = brightness & 0x000000ff;
b = 0xff000000 | (b = LIGHT_COUNT || devices->lights[light] == NULL) {
return ;
}
memset(&state, 0, sizeof(light_state_t));
state.color = colorARGB;
state.flashMode = flashMode;
state.flashOnMS = onMS;
state.flashOffMS = offMS;
devices->lights[light]->set_light(devices->lights[light], &state);
}
Lights.h (hardware\libhardware\include\hardware):#define LIGHTS_HARDWARE_MODULE_ID "lights"
com_android_server_HardwareService.cpp (frameworks\base\services\jni)
err = hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
static const char *variant_keys[] = {
"ro.hardware", /* This goes first so that it can pick up a different
file on the emulator. */
"ro.product.board",
"ro.board.platform",
"ro.arch"
};
int hw_get_module(const char *id, const struct hw_module_t **module)
status = load(id, prop, &hmi);
status = load(id, HAL_DEFAULT_VARIANT, &hmi);
static int load(const char *id, const char *variant,const struct hw_module_t **pHmi)
snprintf(path, sizeof(path), "%s/%s.%s.so", HAL_LIBRARY_PATH, id, variant);
#define HAL_DEFAULT_VARIANT "default"
#define HAL_LIBRARY_PATH "/system/lib/hw"
所以path等于:
/system/lib/hw/light.marvell.so
/system/lib/hw/light.default.so
我们编译的light模块放在 /system/lib/hw/light.default.so 所以初始化成功。
property_get(variant_keys, prop, NULL) 只有 ro.hardware 存在 [ro.hardware]: [marvell]
static int lights_device_open(const struct hw_module_t* module, const char* name,struct hw_device_t** device)
dev->set_light = set_light_backlight;
static struct hw_module_methods_t lights_module_methods = {
open: lights_device_open
};
hardware/libhardware/modules/lights/Android.mk
LOCAL_MODULE:= lights.default
err = module->methods->open(module, name, &device);
执行的是 : lights_device_open
const char * const brightness_file = "/sys/class/backlight/micco-bl/brightness";
static int set_light_backlight(struct light_device_t* dev,
struct light_state_t const* state)
{
. . .
color = state->color;
tmp = ((77*((color>>16)&0x00ff)) + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8;
brightness = tmp/16;
LOGD("---->calling %s(),line=%d state->color=%d,brightness=%d\n",__FUNCTION__,__LINE__,state->color,brightness);
len = sprintf(buf,"%d",brightness);
len = write(fd, buf, len);
. . .
}
上面的函数完成了与内核的交互
综上所述,程序调用流程如下,上层应用通过 /sys/class/leds/lcd-backlight/brightnes 于内核打交道
设置模块 -> 硬件服务器 -> 本地调用 ->功能库 -> 读写 /sys/class/leds/lcd-backlight/brightness 函数与内核交互
Init.rc (vendor\marvell\littleton): chown system system /sys/class/leds/keyboard-backlight/brightness
Init.rc (vendor\marvell\littleton): chown system system /sys/class/leds/lcd-backlight/brightness
Init.rc (vendor\marvell\littleton): chown system system /sys/class/leds/button-backlight/brightness
5.4 获取,显示电池状态
电池状态(正在充电(AC)):
Status.java
String statusString;
mBatteryStatus.setSummary(statusString);
public static final int BATTERY_STATUS_UNKNOWN = 1;
public static final int BATTERY_STATUS_CHARGING = 2;
public static final int BATTERY_STATUS_DISCHARGING = 3;
public static final int BATTERY_STATUS_NOT_CHARGING = 4;
public static final int BATTERY_STATUS_FULL = 5;
// values for "health" field in the ACTION_BATTERY_CHANGED Intent
public static final int BATTERY_HEALTH_UNKNOWN = 1;
public static final int BATTERY_HEALTH_GOOD = 2;
public static final int BATTERY_HEALTH_OVERHEAT = 3;
public static final int BATTERY_HEALTH_DEAD = 4;
public static final int BATTERY_HEALTH_OVER_VOLTAGE = 5;
public static final int BATTERY_HEALTH_UNSPECIFIED_FAILURE = 6;
public static final int BATTERY_PLUGGED_AC = 1; 电源充电
public static final int BATTERY_PLUGGED_USB = 2; USB充电
BatteryInfo.java (packages\apps\settings\src\com\android\settings)
电池级别(50%)
BatteryService.java (frameworks\base\services\java\com\android\server)
电池服务器:
构造函数:
public BatteryService(Context context)
mUEventObserver.startObserving("SUBSYSTEM=power_supply");
----------
UEventObserver.java (frameworks\base\core\java\android\os)
void startObserving(String match)
ensureThreadStarted();
sThread = new UEventThread();
sThread.start();
sThread.addObserver(match, this);
-----------
update()
native_update();
sendIntent();
private final void sendIntent()
Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
...
intent.putExtra("status", mBatteryStatus);
intent.putExtra("health", mBatteryHealth);
intent.putExtra("present", mBatteryPresent);
intent.putExtra("level", mBatteryLevel);
intent.putExtra("scale", BATTERY_SCALE);
intent.putExtra("icon-small", icon);
intent.putExtra("plugged", mPlugType);
intent.putExtra("voltage", mBatteryVoltage);
intent.putExtra("temperature", mBatteryTemperature);
intent.putExtra("technology", mBatteryTechnology);
ActivityManagerNative.broadcastStickyIntent(intent, null);