Android 系统开发笔记
一 系统编译
一. 全量编译
- source build/envsetup.sh // 设置环境变量
- lunch sdk_phone_x86_64(根据需要选择) // 选择编译类型
- m 或者make // 开始编译,系统资源够用的话可以加 -jN参数,例如make -j8 或者m -j8之类的,数字越大越快,相应的资源占用也越多,如果出现闪退,系统卡死失败则相应的减少-j的大小
二. 仅编译framework
修改完framework后可以不需要编译所有
回到aosp根目录下
make framework
make systemimage
三. 导入aosp源码到Android studio
-
source build/envsetup.sh
-
lunch sdk_phone_x86_64(根据需要选择)
-
make idegen -jN
-
sudo development/tools/idegen/idegen.sh
jiangc@jiangc:~/develop/aosp$ sudo development/tools/idegen/idegen.sh Error: A JNI error has occurred, please check your installation and try again Exception in thread "main" java.lang.UnsupportedClassVersionError: Main has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to 52.0 at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:756) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at java.net.URLClassLoader.defineClass(URLClassLoader.java:473) at java.net.URLClassLoader.access$100(URLClassLoader.java:74) at java.net.URLClassLoader$1.run(URLClassLoader.java:369) at java.net.URLClassLoader$1.run(URLClassLoader.java:363) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:362) at java.lang.ClassLoader.loadClass(ClassLoader.java:418) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352) at java.lang.ClassLoader.loadClass(ClassLoader.java:351) at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:601) // 有可能会碰到这个问题,这个问题的原因是:你编译idegen.jar的时候用的java版本是55(这里应该是jdk11),然后你执行脚本的时候用的java版本是52(这里应该是jdk 1.8) 我们执行命令看看java版本和javac的版本 jiangc@jiangc:~/develop/aosp$ java -version openjdk version "11.0.13" 2021-10-19 OpenJDK Runtime Environment Android_PDK (build 11.0.13+0-8163922) OpenJDK 64-Bit Server VM Android_PDK (build 11.0.13+0-8163922, mixed mode) jiangc@jiangc:~/develop/aosp$ javac -version javac 11.0.13 两个版本一致,而且是11好像又没有问题 使用which 命令查看一下当前命令在哪里 jiangc@jiangc:~/develop/aosp$ which java /home/jiangc/develop/aosp/prebuilts/jdk/jdk11/linux-x86/bin/java jiangc@jiangc:~/develop/aosp$ which javac /home/jiangc/develop/aosp/prebuilts/jdk/jdk11/linux-x86/bin/javac 这两个都是源码里面的,是我们执行source build/envsetup.sh时临时设置到环境变量中的 再看看我们执行出错的命令: sudo development/tools/idegen/idegen.sh 可以看到,执行命令的时候加了sudo 可以简单理解使用了特殊权限执行,看一下sudo环境下的java路径及版本 jiangc@jiangc:~/develop/aosp$ sudo java -version openjdk version "1.8.0_352" OpenJDK Runtime Environment (build 1.8.0_352-8u352-ga-1~22.04-b08) OpenJDK 64-Bit Server VM (build 25.352-b08, mixed mode) 可以看到版本是1.8,和报错匹配,也就是说我们加上sudo的时候用的java不是临时环境变量的java而是系统的全局环境变量 所以,两个方法:第一个是把系统的版本切换成和source中的一样,第二个就是 使用 . development/tools/idegen/idegen.sh 会报权限问题,但是不影响使用。
-
然后用Android studio打开android.ipr就可以了
-
可以通过修改 android.iml 文件去除不想加载的文件,降低对系统的压力,全部文件Android studio也不一定能加载成功
-
也可以使用aidegen的方法(推荐)
# 根据模块名 aidegen Settings -i s # 不知道模块名的情况可以使用路径 aidegen frameworks/base/packages/BackupEncryption -i s # TODO: 上面的用法需要在环境变量里面配置studio的路径,如果没有配置,可以使用 -p参数指定 # 如下:我想看整个framework aidegen frameworks -i s -p /home/xxx/androidStudio/bin/
二. 内置应用
一. 背景
系统定制的时候,经常会碰到客户或者自己公司想要集成某一个app,但又不想以源码的方式集成,原因有很多,比如第三方的应用,一般是不会有源码的,还有就是集成apk可以减少系统的编译时间,把app和系统编译分离,提高效率的目的。为什么要成为系统应用,因为系统应用权限高,不能被卸载。
二. 集成app的分类
- 单纯的app(不带so库的apk)
- 带so库的app
- 源码集成(这个一般不是我们的首选,可以参考源码中的,这里不记录)
三. 单纯的app的集成方式
3.1 步骤
- 在package/apps/目录下创建相应的文件夹如:myapp
- 在build/make/target/product/core.mk文件中加入该module的名字
- 再进行整体的make
3.2 单纯的app集成(不带so)
3.2.1 在package/apps/目录下创建文件夹(一般为app的名字)
3.2.2 编写Android.mk
LOCAL_PATH:=$(call my-dir) # 固定开头
include $(CLEAR_VARS) # 固定开头:清楚变量
LOCAL_MODULE := MyApp # 模块名
LOCAL_MODULE_TAGS := optional # 编译选项, 根据选项自己调整,后面再详细记录
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk #文件名
LOCAL_MODULE_CLASS := APPS # 模块类型,后面详细记录分类
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX) # 文件后缀名,后面详细记录
LOCAL_CERTIFICATE := PRESIGNED # 签名相关,后面详细记录
include $(BUILD_PREBUILT) # 编译类型,后面详细记录
3.2.1 LOCAL_MODULE_TAGS
- user: 指该模块只在user版本下才编译
- eng: 指该模块只在eng版本下才编译
- tests: 指该模块只在tests版本下才编译
- optional: 指该模块在所有版本下都编译
3.2.2 不同版本的区别
变体 | 说明 |
---|---|
eng | 这是默认变种。 安装带有 eng 或 debug 标记的模块。 除了带有标记的模块之外,还会根据产品定义文件安装相应模块。 ro.secure=0 ro.debuggable=1 ro.kernel.android.checkjni=1 adb 默认处于启用状态。 |
user | 打算作为最终发布版本的变体。安装带有 user 标记的模块。除了带有标记的模块之外,还会根据产品定义文件安装相应模块。ro.secure=1``ro.debuggable=0``adb 默认处于停用状态。 |
userdebug | 与 user 相同,但以下几点除外:还会安装带有 debug 标记的模块。ro.debuggable=1``adb 默认处于启用状态。 |
3.2.3 LOCAL_MODULE_CLASS
用于指定模块的类型
属性 | 值 |
---|---|
APPS | 编译apk文件 |
JAVA_LIBRAYIES | jar包 |
SHARED_LIBRAYIES | 动态库文件 |
EXECUTABLES | 可执行文件 |
3.2.4 LOCAL_MODULE_SUFFIX
目标文件的后缀
属性 | 值 |
---|---|
COMMON_PACKAGE_SUFFIX | .zip |
COMMON_JAVA_PACKAGE_SUFFIX | .jar |
COMMON_ANDROID_PACKAGE_SUFFIX | .apk |
3.2.5 LOCAL_CERTIFICATE
系统签名
属性 | 值 |
---|---|
testkey | 普通APK,默认情况下使用,如果Android.mk没有指定 |
media | 该APK是media/download系统中的一环 |
platform | 和系统一个签名,需要结合android:sharedUserId="android.uid.system"才有用 |
shared | 该APK需要和home/contacts进程共享数据 |
PRESIGNED | 使用apk本身的签名时使用这个属性 |
3.2.6 BUILD_PREBUILT
编译类型
属性 | 值 |
---|---|
BUILD_PREBUILT | 该模块已经预先编译 |
BUILD_SHARED_LIBRARY | 编译为动态库 |
BUILD_STATIC_LIBRARY | 编译为动态库 |
BUILD_EXECUTABLE | 编译为Native C可执行程序 |
3.2.3 在build/make/target/product/core.mk文件中加入该module的名字
3.3 带SO的app集成
- 提取apk中的so文件,进行单独的内置,参考前面,就多了一句话
LOCAL_PATH:=$(call my-dir) # 固定开头
include $(CLEAR_VARS) # 固定开头
LOCAL_MODULE := MyApp # 模块名
LOCAL_MODULE_TAGS := optional # 编译选项
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk #文件名
LOCAL_MODULE_CLASS := APPS # 模块类型
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX) # 文件后缀名
LOCAL_PREBUILT_JNI_LIBS := lib/x86_64/libnative-lib.so
LOCAL_CERTIFICATE := PRESIGNED # 签名相关
include $(BUILD_PREBUILT) # 编译类型
- 然后直接整体make完事
小知识
1. 打印当前栈顶的activity
adb shell
dumpsys activity activities
2. 根据包名找到apk
dumpsys pacakage 包名
四. Android.bp简单使用
在android 7.0发布之前,Android 仅使用GNU Make 描述和执行build规则。Make构建系统得到了广泛的支持和使用,但在Android层面变得缓慢、容易出错、无法扩展且难以测试。Soong构建系统正好提供了Android build所需要的灵活性。
因此,平台开发者应尽快的从Make切换到Soong。
以上摘抄自官方文档: https://source.android.google.cn/docs/setup/build?hl=zh-cn
4.1 什么是Soong
soong构建系统是在Android 7.0中引入的,旨在取代Make。它利用Kati GNU Make科隆工具和Ninia构建系统组件来加速Android的构建。
4.2 Make和Soong比较
以下是Make配置与Soong在Soong配置文件中完成相同操作的比较
Make 实例
LOCAL_PATH :=(call my-dir))
include $(CLEAR_VARS) # 模块的名字
LOCAL_MODULE := libxmlrpc++
LOCAL_MODULE_HOST_OS := linux # C++ rtti机制开启
LOCAL_RTTI_FLAG := -frtti # 编译选项
LOCAL_CPPFLAGS := -Wall -Werror -fexceptions # 源文件列表
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/src
LOCAL_SRC_FILES := $(call \
all-cpp-files-under, src)
# 编译动态库
include $(BUILD_SHARED_LIBRARY)
Soong实例
cc_library_shared{ # 动态库
name: "libxmlrpc++", # 模块名字
rtti: true # C++ rtti机制开启
cppflags:[ # 编译选项
"-Wall",
"-Werror",
"-fexceptions",
],
export_include_dirs: ["src"], # 包含的目录
srcs:["src/**/*.cpp"], # 包含的源文件
target:{
darwin:{
enabled:false
},
},
}
4.3 Android.bp 文件格式
根据设计,Android.bp文件很简单。它们不包含任何条件语句,也不包含控制流语句;所有复杂的问题都由go编写的构建逻辑处理。Android.bp文件的语法和语义都尽可能的与Bazel BUILD文件类似。
4.4 模块
Android.bp 文件中的模块以模块类型开头,后跟一组 name: “value”,格式的属性:
cc_binary{
name: "gzip",
srcs: ["src/test/minigzip.c"],
shared_libs: ["libz"],
stl: "none",
}
模块类型: