BoardConfig.mk(device文件夹里):该文件用来配置硬件主板,它其中定义的都是设备底层的硬件特性。例如:该设备的主板相关信息,Wifi 相关信息,还有 bootloader,内核,radioimage 等信息。对于该文件的示例,请参看 Android 源码树已经有的文件。
vendorsetup.sh:该文件中作用是通过 add_lunch_combo 函数在 lunch 函数中添加一个菜单选项。该函数的参数是产品名称加上编译类型,中间以“-”连接,例如:add_lunch_combo full_lt26-userdebug。/build/envsetup.sh 会扫描所有 device 和 vender 二 级目 录下的名称 为"vendorsetup.sh"文件,并根据其中的内容来确定 lunch 函数的 菜单选项。
使用“include FILENAMES...”,make程序处理时,如果“FILENAMES”列表中的任何一个文件不能正常读取而且不存在一个创建此文件的规则时make程序将会提示错误并退出。
使用“-include FILENAMES...”的情况是,当所包含的文件不存在或者不存在一个规则去创建它,make程序会继续执行,只有真正由于不能正确完成终极目标的重建时(某些必需的目标无法在当前已读取的makefile文件内容中找到正确的重建规则),才会提示致命错误并退出。
Make[flag][macro_definition][targets]
Makefile文件中:
.PHONY: cts //target:cts 一个target会定义一些规则
$ . build/envsetup.sh //配置选项,并编译android源码
$ make cts //android源码编译好后,在编译cts
查看源码版本
buildcoreversion_defaults.mk //搜索该文件中的 PLATFORM_VERSION值
m:编译所有的模块
mm:编译当前目录下的模块,当前目录下要有Android.mk文件
mmm [dir]:编译指定路径下的模块,指定路径下要有Android.mk文件
Makesnod:修改了out/target中的内容,在源码根目录使用后,可以生成新的img
单独编译模块:
1> source build/envsetup.sh:加载命令
2> lunch:选择平台编译选项(选择自己产品自定义的编译选项)
3> make:执行编译
Make clean/make distclean
0)Kernel编译使用JLB带的编译器, Android自成Boot.img, recovery.img需要zImage. 所以上面Clone下来的代码需要放在同一目录下
1)uboot
#> cd UBOOT_DIR
#> vi Makefile //修改CROSS COMPILE路径, 默认为/usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-, 相符可跳过
#> make tg4_dvt_config
#> make -j4
2)Kernel
#> cd KERNEL_DIR
#> ./build_kernel.sh tg4_dvt wqxga
3)Android
#> cd ANDROIR_DIR
#> ./build.sh tg4_dvt
编译sc1 kernel:
1.make sc1_dvt1_defconfig
2.make
make snod //把system文件夹打包为system.img
注:通过mmm packages/providers/ContactsProvider/ 编译后的apk在 out/target/product/generic/system/app
make 2&>txt
将make的信息输出到txt中,如果make > txt则无法输入
Linux Shell 环境中支持输入输出重定向,用符号"<"和">"来表示。0、1和2分别表示标准输入、标准输出和标准错误信息输出,可以用来指定需要重定向的标准输入或输出
make &>test
表示标准和错误全部输出
Eclipse :add to build path
Java Build Path是我们编译时所需要的包,在我们import某个包的时候,如果没有Java Build Path导入包的话,类里面就会有红叉,不能够识别这个类,复制到libs下是运行时所需要的包。如果用Add Buid Path导入包,但是没有放在libs下程序也会报ClassNotFindException
Makefile
include $(BUILD_EXECUTABLE)表示要编译成一个可执行文件(其实就是加载了$(BUILD_SYSTEM)/executable.mk),如果想编译成动态库则可用BUILD_SHARED_LIBRARY,这些可以在$(YOUR_ANDROID)/build/core/config.mk查到。
LOCAL_PRIVILEGED_MODULE := true,以声明app需要放在/system/priv-app下
LOCAL_MODULE:打出的库名 or 指定为用于注册库的 .xml 文件
LOCAL_AAPT_FLAGS: 引用其他模块的资源,将几个模块打成一个app
LOCAL_PACKAGE_NAME:package的名字,这个名字在脚本中将标识这个app或package
LOCAL_JAVA_LIBRARIES:当前模块依赖的 Java 共享库。
LOCAL_STATIC_JAVA_LIBRARIES:当前模块依赖的 Java 静态库。
LOCAL_STATIC_LIBRARIES: 表示该模块需要使用哪些静态库,以便在编译时进行链接。
LOCAL_SHARED_LIBRARIES: 表示模块在运行时要依赖的共享库(动态库),在链接时就需要,以便在生成文件时嵌入其相应的信息。
A. 静态库的名字一般是libxxx.a;利用静态函数库编译成的文件比较大,因为整个函数库的所有数据都被整合进目标代码中Android。创建命令:ar –cr。Makefile使用“include $(BUILD_STATIC_JAVA_LIBRARY)”指定创建为静态库
B.动态库又称共享库,这类库的名字一般是libxxx.so;相对于静态函数库,动态函数库在编译的时候并没有被编译进目标代码中,你的程序执行到相关函数时才调用函数库里的相应函数。创建命令:gcc –share。Makefile使用“include $(BUILD_JAVA_LIBRARY)”指定编译为动态库。
C. 注册第三方jar包。include $(BUILD_JAVA_LIBRARY) + include $(BUILD_PREBUILT)指定配置库的xml(LOCAL_MODULE := com.qrd.plugin.feature_query.xml)
.jar 文件:/system/framework/ (framework中模块的jar包打到这,第三方jar要xml中配置到这)
.xml 文件:/system/etc/permissions/
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES/LOCAL_PREBUILT_JAVA_LIBRARIES:利用外部jar包需要prebuilt
Avl7580 aricentimsclientsdk: LOCAL_MODULE_SUFFIX := .jar LOCAL_MODULE_CLASS := JAVA_LIBRARIES LOCAL_MODULE := aricentimsclientsdk LOCAL_SRC_FILES := aricentimsclientsdk.jar #TARGET_OUT_JAVA_STATIC_LIBRARIES := out/target/common/obj/JAVA_LIBRARIES/aricentimsclientsdk_intermediates #LOCAL_PROGUARD_FLAG_FILES := proguard.flags include $(BUILD_PREBUILT) |
$(call inherit-product-if-exists, device/.../xxx.mk)#指把xxx.mk(xxx.mk要存在)中的变量添加进来
修改google开放出来的类再进行编译,可能出现下面报错:
You have tried to change the API from what has been previously approved.
因为对javadoc的生成会产生影响。处理方法:
1, 添加 /**{@hide}*/ 修饰. 可以直接对整个类进行修饰。
2, 就是想要生成的javadoc里出现这个方法或变量,输入: make update-api,即编译时,输入make update-api PRODUCT-***-eng,但是输入 make PRODUCT-***-eng update-api 这样是有问题的,因为后面的update-api会被忽略掉,这样系统就会自动的把我们新增的API 写入 frameworks/base/api/current.xml 文件中。或者手动更新更新 frameworks/base/api/current.txt 文件。(或者需要先手动修改current.txt再make update-api)
3, Android.mk LOCAL_SDK_VERSION := current 加了这个就不能调用了,没加可以调用
类或API是否开放,是通过doc的注释{@hide}来控制的。非开放类,即是在android应用程序中无法直接访问的类。
LOCAL_AIDL_INCLUDES: 在aidl接口的函数中使用自己定义的类做参数,只需将该类实现Parcelable接口,并且将该类存放的路径加入到LOCAL_AIDL_INCLUDES中,同时在该类的同一目录下创建aidl文件,就可以编译了。
手动选屏
amoled屏: make avl8890_eng_defconfig make menuconfig platform selection -》 samsung Exynos -》hardware platform selection -》component selection 选 Support Video LCD S6E8FA0, unselect(*去掉) Support Video LCD Truely NT35596 tp选 Support Touch Screen ATMELMXTS, unselect(*去掉)Support Touch Screen SYNAPTICSRMI4 保存退出 make
SystemProperties
前缀必须用systemcoreinitproperty_service.c中定义的前缀 ,进行系统属性设置的程序也必须有system或root权限
如果我们要添加一个property:例如:silvan_liu
路径:system/core/rootdir/int.rc
在on post-fs-data 目录下
setprop persist.sys.silvan_liu 1//persist.sys 前缀名; 1为初始值
前缀必须用systemcoreinitproperty_service.c中定义的前缀这和int.rc的语法有关。
如果属性名称以“ro.”开头,那么这个属性被视为只读属性。一旦设置,属性值不能改变。
如果属性名称以“persist.”开头,当设置这个属性时,其值也将写入/data/property。
c++中对应JAVA的两个函数就是property_set, property_get, JAVA是通过JNI调用这两个函数实现属性的设置和读取。
在adb shell可以通过以下的命名读取和修改:
#getprop persist.sys.language
#setprop persist.sys.language zh
在sc1项目中,自定义的属性文件:
android4.2.2_JLB_SC1devicesc1_dvt1 system.prop
android4.3_JLB_SC1devicesscrsc1_dvt1 system.prop
我们可以在下面文件中定义属性:
devicesscrsc1_dvt1system.prop
例如:
ro.wifi.support.cmcc=true
这样,就可以在代码中通过“SystemProperties.get(“ro.wifi.support.cmcc”)”方法获取定义好的属性了。import android.os.SystemProperties;
最终,这些配置项会编译到image的/system/build.prop中。
系统的设置存于/data/data/PACKAGE_NAME/shared_prefs中(SharedPreferences)。
Android.mk属性定义
1, devicesc1_dvt1BoardConfig.mk
HAVE_WLAN_CMCC_FEATURE := true
2,wpa_supplicant_8wpa_supplicantAndroid.mk
ifeq ($(HAVE_WLAN_CMCC_FEATURE),true) //可以识别别的mk定义的属性
L_CFLAGS += -DWLAN_CMCC_FEATURE
Endif
编译时引入其他包:
- LOCAL_STATIC_JAVA_LIBRARIES : //系统内部编出来的包
- //直接引入的外部包,需要prebuilt
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := simplexml:libs/simple-xml-2.3.4.jar
LOCAL_STATIC_JAVA_LIBRARIES :=
simplexml
Sqlite使用
继承SQLiteOpenHelper,在OnCreate中建表,在onUpgrade中升级表。通过该类的getWritableDatabase和getReadableDatabase()可以获得 SQLiteDatabase的对象,从而增删改查表。
系统update原理
基于 android 系统的设备一般将存储区间逻辑上分为:引导区、内核区、 ramdisk 区间、 recovery 区、系统区、 cache 区间和数据区。
其中 reocvery 区间为系统修复时候使用,其他区间功能如下:引导区为处理器上电固定的加载点,其存储位置依据处理器不同而变化,对于支持从 nand 加载引导固件的处理器,可以将引导区域直接放置到nandflash 中,一般占据从 nand 的 block0 开始的一些区域。否则必放置到处理器支持的加载点如 norflash 等。
Boot 代码负责操作系统的加载和升级,由于 boot 才能从一些基本的数据源如串口、 usb 获取升级数据,作为处理器上电即加载和运行的这一区域一旦损坏则系统升级只能凭借处理器内建原生的引导能力,这个过程大都需要专用工具或软件才能完成。
内核区即 linux 内核保存位置,其和引导区在最终系统中对一般用户都设计为不能进行升级以维护基本系统的安全性。
Ramdisk 和 recovery 区间同标准 linux 中的 initrd ,引导程序根据启动参数决定加载正常的 ramdisk 还是 recovery 作为 initrd 传递给内核,其中 recovery 区间为修复系统使用,由于其为修复 / 升级系统的核心组件,一般也都设计为对用户不可改变。
系统区为正常的 android 应用保存位置,一般设计为对普通用户属只读系统以保护主要系统的安全性,数据区为用户设置信息、优化后的 DEX 和系统数据库保存位置,清空该区域会清除用户的所有数据以及优化过的 DEX 文件,导致下一次启动过程很长(需要重新创建 data 目录中的缺省信息)。
Cache 区间为升级过程使用的临时存储区。
升级过程主要流程描述如下:
1 boot 发现用户按住升级按键,将 recovery.img 作为 ramdisk 读取到内存。
2 内核根据 ramdisk 中的 init.rc 执行 recovery 脚本。 Recovery 脚本在 sdcard 中找到升级文件后调用 recovery 程序依次做以下操作:
A 检查升级文件的数字签名是否可靠。检查签名使用的本地密钥为 /res/keys
B 如果签名合法则执行提取压缩包中 META-INF/com/google/android/update-binary 文件重命名到 /tmp/update_binary 并执行该文件。
C update_binary 解析压缩文件中的 META-INF/com/google/android/updater-script 文件并执行。其升级进度通过管道回传给 recovery 程序。升级 / 更新可以直接覆盖目标文件,也可采用二进制补丁形式以减少升级文件的容量,采用的工具为 bsdiff 和 imgdiff 。对于补丁包升级形式,升级数据源可靠性鉴别的依据为 sha1 校验和数据长度比对。具体要求为: 1 升 级包提供的目标文件的 sha1 值和目标文件计算值符合,即目标正确。 2 进行补丁后的文件 sha1 值和长度符合升级包提供的补丁后的目标文件的长度和 sha1 数值,保证结果正确。两项有一项不符合则升级过程停止。为保证第二项操作不损毁最终目标,打补丁的文件会先临时存储到 cache 中,等到结果比对正确才进行实际写入 / 替换目标文件操作。所以此过程要求 cache 目录必须有足够空间能够保存临时文件。
资源替换:DEVICE_PACKAGE_OVERLAYS
DEVICE_PACKAGE_OVERLAYS可以设定路径,起到的作用就是替换掉原来的目录中的资源,比如图片等等,惟一的要求就是必须建立和原来图片位置相同的路径
有两种不同的overaly目录定义,来影响最终的效果:
PRODUCT_PACKAGE_OVERLAYS: used by a particular product
DEVICE_PACKAGE_OVERLAYS: used several products that share a common device model
如果包含同一资源,那么 PRODUCT_PACKAGE_OVERLAYS 将覆盖 DEVICE_PACKAGE_OVERLAYS
中的
例:devicesamsungavl7580device.mk
DEVICE_PACKAGE_OVERLAYS :=
device/samsung/avl7580/overlay
init.rc
init.c 、init.rc init.xx.rc 等最终会编译到ramdisk.img(根文件系统)中,和kernel一起打包成boot.img。android启动后每次都会从boot.img中解压出init.c等文件到内存
在init.rc中启动的服务,都是以一个进程的形式运行,属于android的本地服务。通过在终端输入PS命令可以查看在运行的相应进程,他们的ppid都为1,代表init进程。 init进程也是android系统启动的第一个应用进程
SELinux
首先在boardconfig.mk里定义SELinux的poliocy文件:
BOARD_SEPOLICY_DIRS +=
vendor/samsung_slsi/telephony/common/config/sepolicy
然后在pliocy文件中写权限:
allow system_server radio_service:service_manager add;