标签 aosp 下的文章

转自: http://bbs.100ask.net/article/35#:~:text=%E7%94%B1%E4%BA%8Elinux%E7%9A%84IIC%E5%9C%B0%E5%9D%80%E5%9C%A8%E4%BD%8E7%E4%BD%8D%EF%BC%8C%E5%9B%A0%E6%AD%A4gt911%E7%9A%84%E5%AE%9E%E9%99%85%E5%9C%B0%E5%9D%80%E6%98%AF0xBA%3E1%3D0x5d%2C%E8%BF%99%E5%B0%B1%E6%98%AF%E4%B8%BA%E4%BB%80%E4%B9%88%E6%88%91%E4%BB%AC%E5%9C%A8%E8%AE%BE%E5%A4%87%E6%A0%91%E4%B8%AD%E5%B0%86GT911%E7%9A%84%E5%9C%B0%E5%9D%80%E9%85%8D%E7%BD%AE%E4%B8%BA0x5d,gt911%E9%9C%80%E8%A6%81%E9%85%8D%E7%BD%AE%E7%9A%84%E5%AF%84%E5%AD%98%E5%99%A8%20gt911%E9%9C%80%E8%A6%81%E9%85%8D%E7%BD%AE186%E4%B8%AA%E5%AF%84%E5%AD%98%E5%99%A8%EF%BC%8C%E5%88%86%E5%88%AB%E4%B8%BA0x8047-0x8100

源码在最下面

问题一:资源获取Gt911数据手册

在韦老师给的资料里,路径为\06_Datasheet\Extend_modules\7寸LCD模块\电容触控芯片GT911 Datasheet_121120(海威思.pdf

问题二:需要准备哪些知识

  1. 能够修改设备树
  2. 能够编写字符设备驱动
  3. 能够在linux下编写中断程序
  4. 能够在linux下编写IIC收发程序
  5. 了解input子系统
  6. 移植tslib(用于校准,测试触摸屏)

- 阅读剩余部分 -

android 生成的 kernel config 在 out/target/product/msm8937_32/obj/KERNEL_OBJ/.config 。要想找出到底哪个 config 决定了最后的 config,我们可以选择 CONFIG_TOUCHSCREEN_FT5X06=y 这一项进行测试。

直接在 kernel 目录下面搜索所有的 CONFIG_TOUCHSCREEN_FT5X06=y, 然后修改CONFIG_TOUCHSCREEN_FT5X06=n,再使用 make kernel,然后查看最终的输出 config,查看变化。

最终确定是 msm-4.9/arch/arm/configs/msm8937_defconfig 决定了 out/target/product/msm8937_32/obj/KERNEL_OBJ/.config

参考: https://blog.csdn.net/u013377887/article/details/81328491

当系统中缺少某个特定版本的 libc 的时候,可以在编译的时候,添加 -nostdlib 选项,并在后面附上指定的库即可。类似于

arm-linux-gcc -fPIC -shared hardcontrol.c -o libhardcontrol.so -I /usr/lib/jvm/java-1.7.0-openjdk-amd64/include/ -nostdlib /work/android-5.0.2/prebuilts/ndk/9/platform/android-19/arch-arm/usr/lib/libc.so

当c文件编译的时候,找不到 log 方面的头文件和库的时候,可以手动添加,类似下面这样

arm-linux-gcc -fPIC -shared hardcontrol.c -o libhardcontrol.so -I /usr/lib/jvm/java-1.7.0-openjdk-amd64/include/ -nostdlib /work/android-5.0.2/prebuilts/ndk/9/platform/android-19/arch-arm/usr/lib/libc.so -I /work/android-5.0.2/prebuilts/ndk/9/platform/android-19/arch-arm/usr/include /work/android-5.0.2/prebuilts/ndk/9/platform/android-19/arch-arm/usr/lib/liblog.so

硬件服务中,xxx_service.cpp, hal_xxx.c 的关系

com_android_server_LedService.cpp 这样的文件是 jni 源码,主要做的是向系统注册的事情。hal_led.c 这样的是实际的对硬件进行操作的源码,比如说 read, write, ioctrl 等等。 之所以分开来主要考虑两个原因。

  • com_android_server_LedService.cpp 这样的文件如果有变更,那么需要系统重新编译。hal_led.c这样的正常时编译为 so 库,所以可以不用系统重新编译。
  • 有些厂商为了保密的需要,不提供 hal_led.c 这样的源码,只是提供一个 so 的库文件。
  • onload.cpp 调用 com_android_server_LedService.cpp 中实现的函数
  • SystemServer.java 需要 new LedService 然后再 addService
  • LedService.java 里面调用 native 方法
  • ILedService.java 给 app 来使用。

ILedService.java

  1. 仿照其他的 aidl 文件,比如说 vibr 的 aidl 文件,复制为ILedService.aidl,然后修改一下接口。
  2. 查看 vibr aidl 文件所在的目录,放到类似的目录
  3. 从当前目录开始查看有没有 Android.mk,如果没有,就向上一层继续查找,知道找到为止。
  4. Android.mk 中仿照 vibr aidl,把ILedService.aidl加入进去。
  5. 使用 mmm . 进行编译。
  6. 到 out 目录下找找有没有 ILedService.java 生成
  7. 可以估计 app 中对 led 的用法是
    ILedService iLedService;
    iLedService = ILedService.stub.asInterface(ServiceManager.getService("led"));
    iLedService.ledCtrl(0, 1);

参考 VibratorService.java 来写 LedService.java.

  1. LedService 继承了 ILedService.Stub, 到 ILedService.javaStub 申明实现的接口 android.os.ILedService , android.os.ILedService 这个里面自动生成的需要实现的只有 ledCtrl 这个函数。
  2. LedService.java 中实现 ledCtrl,这个函数中直接调用 native 方法即可。别忘了申明 native 方法
  3. LedService.java 中的构造函数中也需要调用 open 的 native 方法。别忘了申明 native 方法
  4. SystemServer.java 中,找到 vibr 使用 ServiceManager.addService 的地方,仿照写个 led 的添加服务的调用。

com_android_server_LedService.cpp

参考 com_android_server_VibratorService.cpp 来写。

Onload.cpp

找到 register_android_server_VibratorService(env) 这个注册的地方,复制一份,改为 register_android_server_LedService(env). 别忘了添加这个函数相应的申明。

保存 mmm 编译时的指令

mmm frameworks/base show commands >log.txt 2>&1

在 app 中直接 import android.os.ILedService 会找不到

  1. 可以参考: https://stackoverflow.com/questions/7888191/how-do-i-build-the-android-sdk-with-hidden-and-internal-apis-available ,把 out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar 这个复制出来,并改个名字。
  2. 可以参考 https://stackoverflow.com/questions/16608135/android-studio-add-jar-as-library 中的在 android studio 中添加 jar 文件。

led_hal.c

参考 hardware/libhardware/modules/vibrator/vibrator.chardware.h 来写 led_hal.c

编译

上面这些修改好了之后,可以使用命令进行编译。

mmm frameworks/base/services
mmm hardware/libhardware/modules/led
make snod

logcat

logcat 在命令行中可以使用类似 logcat LedHal:I *:S 这样的方法来进行过滤。

转自: http://gityuan.com/2016/03/19/android-build/

工欲善其事,必先利其器,对于想要深入学习Android源码,必须先掌握Android编译命令.

一、引言

关于Android Build系统,这个话题很早就打算整理下,迟迟没有下笔,决定跟大家分享下。先看下面几条指令,相信编译过Android源码的人都再熟悉不过的。

source setenv.sh
lunch
make -j12

记得最初刚接触Android时,同事告诉我用上面的指令就可以编译Android源码,指令虽短但过几天就记不全或者忘记顺序,每次编译时还需要看看自己的云笔记,冰冷的指令总是难以让我记忆。后来我决定认真研究下这个指令的含义。知其然还需知其所以然,这样能更深层次的理解并记忆,才能与自身的知识体系建立强连接,或许还有意外收获,果然如此,接下来跟大家分享一下在研究上述几条指令含义的过程中,深入了解到的Android Build(编译)系统。

二、编译命令

准备好编译环境后,编译Android源码的第一步是 source build/envsetup.sh,其中source命令就是用于运行shell脚本命令,功能等价于”.”,因此该命令也等价于. build/envsetup.sh。在文件envsetup.sh声明了当前会话终端可用的命令,这里需要注意的是当前会话终端,也就意味着每次新打开一个终端都必须再一次执行这些指令。起初并不理解为什么新开的终端不能直接执行make指令,到这里总算明白了。

接下来,解释一下本文开头的引用的命令:

source setenv.sh  //初始化编译环境,包括后面的lunch和make指令
lunch  //指定此次编译的目标设备以及编译类型
make  -j12 //开始编译,默认为编译整个系统,其中-j12代表的是编译的job数量为12。

所有的编译命令都在envsetup.sh文件能找到相对应的function,比如上述的命令lunch,make,在文件一定能找到

function lunch(){
    ...
}

function make(){
    ...
}

source envsetup.sh,需要cd到setenv.sh文件所在路径执行,路径可能在build/envsetup.sh,或者integrate/envsetup.sh,再或者不排除有些厂商会封装自己的.sh脚本,但核心思路是一致的。

具体实现这里就不展开说明,下面精炼地总结了一下各个指令用法和功效。

2.1 代码编译

编译指令 解释
m 在源码树的根目录执行编译
mm 编译当前路径下所有模块,但不包含依赖
mmm [module_path] 编译指定路径下所有模块,但不包含依赖
mma 编译当前路径下所有模块,且包含依赖
mmma [module_path] 编译指定路径下所有模块,且包含依赖
make [module_name] 无参数,则表示编译整个Android代码

下面列举部分模块的编译指令:

模块 make命令 mmm命令
init make init mmm system/core/init
zygote make app_process mmm frameworks/base/cmds/app_process
system_server make services mmm frameworks/base/services
java framework make framework mmm frameworks/base
framework资源 make framework-res mmm frameworks/base/core/res
jni framework make libandroid_runtime mmm frameworks/base/core/jni
binder make libbinder mmm frameworks/native/libs/binder

上述mmm命令同样适用于mm/mma/mmma,编译系统采用的是增量编译,只会编译发生变化的目标文件。当需要重新编译所有的相关模块,则需要编译命令后增加参数-B,比如make -B [module_name],或者 mm -B [module_path]

Tips:

  • 对于m、mm、mmm、mma、mmma这些命令的实现都是通过make方式来完成的。
  • mmm/mm编译的效率很高,而make/mma/mmma编译较缓慢;
  • make/mma/mmma编译时会把所有的依赖模块一同编译,但mmm/mm不会;
  • 建议:首次编译时采用make/mma/mmma编译;当依赖模块已经编译过的情况,则使用mmm/mm编译。

2.2 代码搜索

搜索指令 解释
cgrep 所有C/C++文件执行搜索操作
jgrep 所有Java文件执行搜索操作
ggrep 所有Gradle文件执行搜索操作
mangrep [keyword] 所有AndroidManifest.xml文件执行搜索操作
mgrep [keyword] 所有Android.mk文件执行搜索操作
sepgrep [keyword] 所有sepolicy文件执行搜索操作
resgrep [keyword] 所有本地res/*.xml文件执行搜索操作
sgrep [keyword] 所有资源文件执行搜索操作

上述指令用法最终实现方式都是基于grep指令,各个指令用法格式:

xgrep [keyword]  //x代表的是上表的搜索指令

例如,搜索所有AndroidManifest.xml文件中的launcher关键字所在文件的具体位置,指令

mangrep launcher

再如,搜索所有Java代码中包含zygote所在文件

jgrep zygote

又如,搜索所有system_app的selinux权限信息

sepgrep system_app

Tips: Android源码非常庞大,直接采用grep来搜索代码,不仅方法笨拙、浪费时间,而且搜索出很多无意义的混淆结果。根据具体需求,来选择合适的代码搜索指令,能节省代码搜索时间,提高搜索结果的精准度,方便定位目标代码。

2.3 导航指令

导航指令 解释
croot 切换至Android根目录
cproj 切换至工程的根目录
godir [filename] 跳转到包含某个文件的目录

Tips: 当每次修改完某个文件后需要编译时,执行cproj后会跳转到当前模块的根目录,也就是Android.mk文件所在目录,然后再执行mm指令,即可编译目标模块;当进入源码层级很深后,需要返回到根目录,使用croot一条指令完成;另外cd - 指令可用于快速切换至上次目录。

2.4 信息查询

查询指令 解释
hmm 查询所有的指令help信息
findmakefile 查询当前目录所在工程的Android.mk文件路径
print_lunch_menu 查询lunch可选的product
printconfig 查询各项编译变量值
gettop 查询Android源码的根目录
gettargetarch 获取TARGET_ARCH值

2.5 其他指令

上述只是列举比较常用的指令,还有其他指令,而且不同的build编译系统,支持的指令可能会存在一些差异,当忘记这些编译指令,可以通过执行hmm,查询指令的帮助信息。

最后再列举两个比较常用的指令:

  • make clean:执行清理操作,等价于 rm -rf out/
  • make update-api:更新API,在framework API改动后需执行该指令,Api记录在目录frameworks/base/api

三、编译系统

Android 编译系统是Android源码的一部分,用于编译Android系统,Android SDK以及相关文档。该编译系统是由Make文件、Shell以及Python脚本共同组成,其中最为重要的便是Make文件。关于编译系统可参考 理解 Android Build 系统。 www.ibm.com/developerworks/cn/opensource/os-cn-android-build/

3.1 Makefile分类

整个Build系统的Make文件分为三大类:

  • 系统核心的Make文件:定义了Build系统的框架,文件全部位于路径/build/core,其他Make文件都是基于该框架编写的;
  • 针对产品的Make文件:定义了具体某个型号手机的Make文件,文件路径位于/device,该目录下往往又以公司名和产品名划分两个子级目录,比如/device/qcom/msm8916
  • 针对模块的Make文件:整个系统分为各个独立的模块,每个模块都一个专门的Make文件,名称统一为”Android.mk”,该文件定义了当前模块的编译方式。Build系统会扫描整个源码树中名为”Android.mk”的问题,并执行相应模块的编译工作。

3.2 编译产物

经过make编译后的产物,都位于/out目录,该目录下主要关注下面几个目录:

  • /out/host:Android开发工具的产物,包含SDK各种工具,比如adb,dex2oat,aapt等。
  • /out/target/common:通用的一些编译产物,包含Java应用代码和Java库;
  • /out/target/product/[product_name]:针对特定设备的编译产物以及平台相关C/C++代码和二进制文件;

在/out/target/product/[product_name]目录下,有几个重量级的镜像文件:

  • system.img:挂载为根分区,主要包含Android OS的系统文件;
  • ramdisk.img:主要包含init.rc文件和配置文件等;
  • userdata.img:被挂载在/data,主要包含用户以及应用程序相关的数据;

当然还有boot.img,reocovery.img等镜像文件,这里就不介绍了。

3.3 Android.mk解析

在源码树中每一个模块的所有文件通常都相应有一个自己的文件夹,在该模块的根目录下有一个名称为“Android.mk” 的文件。编译系统正是以模块为单位进行编译,每个模块都有唯一的模块名,一个模块可以有依赖多个其他模块,模块间的依赖关系就是通过模块名来引用的。也就是说当模块需要依赖一个jar包或者apk时,必须先将jar包或apk定义为一个模块,然后再依赖相应的模块。

对于Android.mk文件,通常都是以下面两行

LOCAL_PATH := $(call my-dir)  //设置当编译路径为当前文件夹所在路径
include $(CLEAR_VARS)  //清空编译环境的变量(由其他模块设置过的变量)

为方便模块编译,编译系统设置了很多的编译环境变量,如下:

  • LOCAL_SRC_FILES:当前模块包含的所有源码文件;
  • LOCAL_MODULE:当前模块的名称(具有唯一性);
  • LOCAL_PACKAGE_NAME:当前APK应用的名称(具有唯一性);
  • LOCAL_C_INCLUDES:C/C++所需的头文件路径;
  • LOCAL_STATIC_LIBRARIES:当前模块在静态链接时需要的库名;
  • LOCAL_SHARED_LIBRARIES:当前模块在运行时依赖的动态库名;
  • LOCAL_STATIC_JAVA_LIBRARIES:当前模块依赖的Java静态库;
  • LOCAL_JAVA_LIBRARIES:当前模块依赖的Java共享库;
  • LOCAL_CERTIFICATE:签署当前应用的证书名称,比如platform。
  • LOCAL_MODULE_TAGS:当前模块所包含的标签,可以包含多标签,可能值为debgu,eng,user,development或optional(默认值)

针对这些环境变量,编译系统还定义了一些便捷函数,如下:

  • $(call my-dir):获取当前文件夹路径;
  • $(call all-java-files-under, ):获取指定目录下的所有Java文件;
  • $(call all-c-files-under, ):获取指定目录下的所有C文件;
  • $(call all-Iaidl-files-under, ) :获取指定目录下的所有AIDL文件;
  • $(call all-makefiles-under, ):获取指定目录下的所有Make文件;

示例:

  LOCAL_PATH := $(call my-dir)
  include $(CLEAR_VARS)

  # 获取所有子目录中的Java文件
  LOCAL_SRC_FILES := $(call all-subdir-java-files)

  # 当前模块依赖的动态Java库名称
  LOCAL_JAVA_LIBRARIES := com.gityuan.lib

  # 当前模块的名称
  LOCAL_MODULE := demo

  # 将当前模块编译成一个静态的Java库
  include $(BUILD_STATIC_JAVA_LIBRARY)

转自: https://segmentfault.com/a/1190000021742841

基于 Android 9.0。
许多命令时间一长就记不清了,记录一下。

Android 环境引入的命令

在shell中执行"source build/envsetup.sh"后,Android将增加一些命令到当前环境中。

  • lunch:选择编译的产品类型,并存储在当前环境中。
        lunch <product_name>-<build_variant>
  • tapas:与 'lunch' 类似,可以指定编译的应用。
        tapas [<App1> <App2> ...] [arm|x86|mips|arm64|x86_64|mips64] [eng|userdebug|user]
  • printconfig:打印当前配置。
  • croot:切换到顶层目录
  • m:从顶层目录开始编译。
  • mm:编译当前目录中的所有模块,但不包含依赖的模块。

  • mmm:编译指定目录的所有模块,但不包含依赖的模块。可以使用下述方式限制编译的模块。
        mmm dir/:target1,target2.
  • mma:编译当前目录中的所有模块,包含依赖的模块。
  • mmma:编译指定目录的所有模块,包含依赖的模块
  • provision:对设备进行固件升级,选项将被传递到 fastboot 中。
  • cgrep:在当前目录的所有 C/C++ 文件中查找。
  • ggrep:在当前目录的所有 Gradle 文件中查找。
  • jgrep:在当前目录的所有 Java 文件中查找。
  • resgrep:在当前目录的所有 res/*.xml 文件中查找。
  • mangrep:在当前目录的所有 AndroidManifest.xml 文件中查找。
  • mgrep:在当前目录的所有 Makefiles 文件中查找。
  • sepgrep:在当前目录的所有 sepolicy 文件中查找。
  • sgrep:在当前目录的所有文件中查找。
  • godir:切换到包含指定文件的目录。

make相关命令

make 或 m 后面可以跟随不同的参数来指定编译目标。

  • droid:默认的 make 编译目标。
  • all:编译所有内容,包括不含droid标记的内容。编译服务器会运行此命令,以确保项目中包含Android.mk文件的所有元素都会编译。
  • checkbuild:编译所有的模块。
  • showcommands:显示编译步骤中实际的编译指令。
  • PRODUCT-xxx-yyy:编译指定的产品。
  • dump-products:显示产品的编译信息。

  • LOCAL_MODULE:编译指定的模块。例如,
        make runtime
  • nothing:不编译任何事情,只是解析和验证编译框架。
  • java:编译项目中的所有java代码。
  • native:编译项目中的所有native代码。
  • host:编译host端代码。
  • target:编译target端代码。
  • (java|native)-(host|target):按组合编译限定代码。
  • (host|target)-(java|native):按组合编译限定代码。
  • snod:快速重新编译system镜像。
  • vnod:快速重新编译vendor镜像。
  • pnod:快速重新编译product镜像。
  • update-api:更新SDK API。
  • otapackage:生成OTA升级包。
  • updatepackage:生成zip升级包。
  • docs:编译文档。
  • ndk-docs:生成ndk文档。
  • sdk:编译生成SDK。
  • ndk:编译生成NDK。
  • ramdisk:编译生成ramdisk。
  • systemtarball:生成system的tar包。
  • boottarball:生成boot的tar包。
  • userdatatarball:生成data的tar包。
  • systemimage:生成system.img镜像。
  • bootimage:生成boot.img镜像。
  • vbmetaimage:生成vbmeta.img镜像。
  • userdateimage:生成userdata.img镜像。
  • cacheimage:生成cache.img镜像。
  • bptimage:生成partition-table.img镜像。
  • vendorimage:生成vendor.img镜像。
  • productimage:生成product.img镜像。
  • apps_only:编译不包含 user,userdebug,eng 标签的应用程序。
  • dist:拷贝输出到dist目录。
  • dist_files:仅仅拷贝库文件到dist目录。
  • libandroid_runtime:编译JNI相关内容。
  • framework:编译java framework相关内容。
  • services:编译系统服务相关内容。
  • cts:编译CTS测试套件。
  • vts:编译VTS测试套件。

make clean 相关命令

  • clean:清除当前配置编译的所有文件,等同于rm -rf out//。
  • **clean-$(LOCAL_MODULE):清理指定模块的编译结果。
  • clean-$(LOCAL_PACKAGE_NAME):清理指定包的编译结果。
  • clobber:清除所有输出,等同于rm -rf out/。
  • dataclean:删除当前配置上data目录的所有文件。
  • clean-sdk:清理SDK编译输出。
  • installclean:清除与编译类型相关的文件。在切换编译目标是使用该命令可以加快编译。

new product

new directory

device/[company]/[device] [device] is your PCBA name. product is your software.

mkdir -p device/qiushao/pure

lunch
--> COMMON_LUNCH_CHOICES := pure-eng(AndroidProducts.mk)
--> PRODUCT_MAKEFILES := $(LOCAL_DIR)/pure.mk(AndroidProducts.mk)
--> PRODUCT_DEVICE := pure(pure.mk)
--> device/[company]/pure/BoardConfig.mk
==> out directory: PRODUCT_NAME := pure(pure.mk)

vim AndroidProducts.mk

PRODUCT_MAKEFILES := \
    $(LOCAL_DIR)/pure.mk

COMMON_LUNCH_CHOICES := \
    pure-eng
vim pure.mk

$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_x86_64.mk)

PRODUCT_NAME   := pure
PRODUCT_DEVICE := pure
vim BoardConfig.mk

include $(SRC_TARGET_DIR)/board/generic_x86_64/BoardConfig.mk
tree 

.
└── pure
    ├── AndroidProducts.mk
    ├── BoardConfig.mk
    └── pure.mk