Android 12 源码分析 —— 应用层 一(SystemUI准备篇)
Android 12 源码分析 —— 应用层一(SystemUI准备篇)
在接下来的时间中,将会使用Pixel 3(blueline)作为研究对象,选用AOSP的android-12.0.0_r34分支作源代码。
先从android的应用层进行探析,然后慢慢深入android的framework,接着进入android的hal层,最后以android的linux内核结束,期间可能会穿插一些其他文章如android的art虚拟机分析等。
本文是整个系列的第一篇,但是在此之前,请务必阅读以下的文章,他们将在以后的源码分析中时不时出场
- android 如何分析应用的内存(二)——xdd,gdb命令行(http://t.csdn.cn/RENbG)
- android 如何分析应用的内存(三)——LLDB命令行(http://t.csdn.cn/Vpw8e)
- android 如何分析应用的内存(四)——Visual studio code的LLDB(http://t.csdn.cn/8ZM8A)
- android 如何分析应用的内存(十四)——jdb命令行(http://t.csdn.cn/99r2G)
- android 如何分析应用的内存(十五)——Visual Studio Code 调试Android应用(http://t.csdn.cn/dWeF5)
上面列出的文章,是关于如何使用gdb,lldb,jdb进行android源码级别的调试。它在没有IDE的情况下非常有用。
本文作为应用层的开篇之作,选取SystemUI作为研究对象。
为什么选取SystemUI?
在Android的应用层有很多应用可以进行源码分析,如Launcher,Camera,Gallery,Bluetooth,SIM,telephony,Settings等等应用,综合考虑到SystemUI可能是定制比较多的一个模块,因此,对其进行仔细的分析。
本文的首要目标是——搭建分析SystemUI的环境——如何使用Android Studio进行AOSP的开发和调试
注意:在使用Android studio时,对pc的性能有一定的要求,如果pc性能确实不够,可以参考前面列出的5篇文章,使用VS code进行替代。在前面5篇文章中,未提及如何搭建java工程,只提及了如何调试。读者可参考其他关于:Extension Pack for Java插件的使用。搭配前面的5篇调试文章,也可以进行AOSP的开发。
如何使用Android Studio进行AOSP的开发和调试
要使用Android Studio进行SystemUI的编辑工作,需要进行如下的配置:
- 使用AOSP源码中aidegen工具,构建依赖模块
- 使用AOSP源码中的JDK
- 使用AOSP源码中的SDK
- 如何让AndroidManifest.xml和各种资源xml能相互引用
- 如何修改静态代码分析工具lint,以解决IDE中各种标红的错误(实际非错误)
- 如何使用Android studio单步调试SystemUI
接下来我们依次解决上面的步骤。
使用aidegen工具,构建依赖模块
在aosp源码中,加载完编译环境之后,即运行下面的命令之后:
. build/envsetup.sh
lunch
aidegen即可使用。
接下来使用aidegen工具,产生能在as中打开SystemUI的工程配置文件。如下:
aidegen SystemUI -i s -p /media/wanbiao/disk1t/root/IDE/android-studio/bin
# SystemUI:表示要生成工程文件的模块
# -i s:表示生成的工程文件对应的IDE为Android studio。
# j=IntelliJ s=Android Studio e=Eclipse c=CLion v=VS Code
# -p <路径>:表示对应的IDE的安装路径,在生成工程文件完成之后,会自动打开IDE
# 其他常见选项如下:
# -n:表示不用打开IDE
# -s:表示跳过编译各种依赖,如果以前运行过make等命令,可以添加-s
# -e:表示排除一些目录,这个非常有用,尤其是大型模块
# -d:源码引用的模块的深度
# -r:重置所有的aidegen保存的配置
# -v:显示debug级别的log
# -a:生成整个Android 源码树的工程文件
# -l:用指定的语言打开IDE,j=java,c=c/c++,r=Rust
# -h:打开帮助
成功运行之后,会得到如下的图片
在frameworks/base/package/SystemUI目录下,会出现一下几个文件:
- .idea文件夹,Android studio使用的工程文件夹,里面可以配置有多少个模块,从上图可以看到,有三个模块分别为:R,SystemUI,dependencies
- SystemUI.iml:配置SystemUI模块的配置文件
- dependencies.iml:配置dependencies模块的配置文件
接下来我们将要对上面的模块进行JDK和SDK的配置。这样as才能正确地在java类之间跳转。
使用AOSP源码中的JDK
可以使用which javac命令,查看具体的jdk路径如下:
然后打开Android studio,将这个jdk加入配置中,
- File->Project Structure
- 按照下图进行配置
如上图,我们选择了aosp目录中的jdk,并将这个jdk配置命名为:aosp-jdk11
接下来配置sdk
使用AOSP源码中的SDK
在android-12.0.0_r34分支中,默认并不会编译SDK,因此,运行下面的命令进行源码的编译。
. build/envsetup.sh
lunch
make sdk -j8
在Android的编译过程中,可能会报错,例如:module can not be located。又或者xxx文件不存在。
解决办法:只需要找到对应的报错文件,然后打开查看对应的module是否存在,如果不存在,就修改成正确的路径。当然也可简单粗暴的注释掉报错行,前提是:能够确定该行不会影响SDK的功能。
编译成功之后,将会在如下路径中出现:
./out/host/本机平台/sdk/aosp_blueline/android-sdk_eng.wanbiao_linux-x86
然后按照如下所示,添加SDK。
注意:在上图中,要保证SDK内部使用的JDK为我们前面配置的JDK即,aosp-jdk11.同时build target请确保为Android API 31.
将SDK和JDK与SystemUI项目相关联
上面两个步骤只是添加了对应的SDK配置和JDK配置,但是还未与SystemUI相关联起来,参照如下步骤,进行关联
接下来将项目下的各个模块,也配置好SDK,如下图
在点击完,apply之后,会出现一段时间的indexing…请等待片刻。
至此,as已经具备,编辑和跳转java代码的功能。在进行xml资源配置之前,我们需要先解决几个问题
如下:
- 如何正确跳转到源码中,而不是跳转到SDK中
- 源码中的重复文件该怎么操作
如何正确跳转到源码中
在上面的配置中,如果我们跳转源码,将会首先跳转到SDK中。为了能够成功跳转到我们的源码中而不是SDK中
可以有如下两种办法:
- 修改依赖的优先级
- 去掉sdk中的android.jar
两种办法都需要修改,project structure.我们用如下的图片来讲解两种办法
第一种办法:
第一种办法通常需要经常修改,因为as经常会将sdk移动到高优先级
第二种办法:
经过上面的配置,就可以正确的跳转到源码中的位置了
如何处理重复文件
我们处理重复文件,通过将其文件夹标记为exclude 目录即可,如下图
上图将Stub模块下的重复的SystemProperties.java排除在了source file之外。
注意:添加exclude 文件夹,除了上面的右键以外,还可通过对应的.iml文件添加如下的格式:
<content url="file://$MODULE_DIR$/../../../../system/tools/sysprop/stub"><sourceFolder url="file://$MODULE_DIR$/../../../../system/tools/sysprop/stub" isTestSource="false" /><excludeFolder url="file://$MODULE_DIR$/../../../../system/tools/sysprop/stub/android/os" />
</content>
再次注意:除了上面两种方法,还可以通过打开project structure进行修改,如下图
配置Android
上面的处理,只能进行java代码之间的跳转和配置,我们还需要进行AndroidManifest.xml和资源文件的处理。进行如下配置。
-
添加Android
-
选择清单文件和资源文件夹。其中清单文件和资源文件夹是必须
注意:在Android中,一次只能添加一个资源文件夹,如果有多个资源文件夹需要编辑,可以修改此处的配置。例如,我想在res-product中编辑资源的时候,IDE能给我正确的提示,那么可以将此处的Resource directory改为对应的文件夹。
至此,IDE中已经基本可以使用Android的资源了。但是在使用之前,依然还需要处理两个问题:
- 引用系统资源时,跳转到源码而不是sdk
- 处理IDE中报错,但是是正确的使用
如何调整到系统资源
在我的例子中,为了能够正确的关联到系统资源,我将编译出来的sdk中的资源文件夹,删掉,然后通过链接文件夹指向framworks/base/core/res/res目录。使用ln命令即可,不再赘述
处理xml中的非法使用
在AndroidManifest.xml中,如果使用了系统权限如:
<uses-permission android:name="android.permission.BIND_CONTROLS" />
再如,使用了不属于应用的useid
android:sharedUserId="android.uid.systemui"
这些会在IDE中,用红线标识其错误,
再如资源文件夹中使用
@*android:integer/config_mediumAnimTime
访问非public的资源,也会报错
这些都属于静态代码检查工具的功能,我们将对其进行一些修改。
针对上述错误,可做如下修改:
方法一:
- 打开AndroidManifest.xml文件之后,右键单击
- 选中Analyze->Configure Current File Analysis
- 最后选择Syntax
上面的步骤,是告诉IDE,对于当前这个文件,只做语法检查,不做其他检查
方法二:
上面仅仅是非常粗暴的关掉了提示。同样还可以通过File->Settings->Editor->Inspections 在打开的面板中,进行精细的条件。这个涉及到inspect功能的详细解读,不在此赘述。
方法三:
除了通过图形界面操作以外,还可以在当前目录下的lint.xml文件中进行配置。
lint.xml支持的选项,可以通过如下命令得到:
./prebuilts/devtools/tools/lint --list
至此,你可以畅快的在Android Studio中进行,java代码以及xml代码中的编辑工作了。
当然,你也可以对IDE编辑器上面的报错,视而不见,这对于我们的编辑工作并没有什么实质性影响。
在Android studio中调试
关于Android studio怎么调试Android 应用,此处不再介绍,请参考:
android 如何分析应用的内存(五)——Android studio的LLDB:http://t.csdn.cn/jSurw和android 如何分析应用的内存(十五)——Visual Studio Code 调试Android应用:http://t.csdn.cn/wHOgd
本文只介绍,如何能让SystemUI能够正确的调试起来。
事实上,在进行SystemUI的调试中,你将会发现local变量无法debug的场景。为了解决这个问题。需要处理如下几个步骤:
- 确定编译的时候,添加了javac -g选项
- 关掉AOSP中的优化配置
确定编译出来的class文件包含调试信息
在android 如何分析应用的内存(十四)——jdb命令行http://t.csdn.cn/GtbBH文章中,讲解了使用javap进行查看的命令。
接下来我们直接查看SystemUIApplication.class是否含有调试信息。
如果没有上面的输出,则尝试如下修改:
1. Android.mk中增加:LOCAL_JAVACFLAGS += -g
2. Android.bp中增加:javacflags:["-g"]
然后重新编译。并再次确定,如果依然没有调试信息。可以尝试切换成userdebug版本
关掉AOSP中的模块优化
在AOSP生成apk的环节中,有一个优化环节,这个优化环节包括资源的压缩,无用代码的剥离,混淆代码等。为了不破坏调试信息,我们需要关闭优化。如下:
1. Android.mk中添加:LOCAL_PROGUARD_ENABLED := false
2. Android.bp中添加:optimize:[enabled:false]
完成上述步骤之后,可关闭优化功能,且能够在单步调试中进行本地变量的查看
开始调试代码
为了能让SystemUI启动的时候就等待调试器的加入,我们运行下面的命令:
adb shell am set-debug-app -w com.android.systemui
上面代码的详细解释,可参考:android 如何分析应用的内存(十五)——Visual Studio Code 调试Android应用http://t.csdn.cn/JPBjC一文中的开始测试小节
调试结果
单步调试结果如下图
在上面的图中,可以一步一步单步下去,完成整个执行流程的熟悉。
本篇是我们分析SystemUI的基础环节,必不可少的环节,因为能够单步运行,减轻了许多分析源码的工作。说句人话就是少加班了。
至此,Android studio如何进行SystemUI的源码编辑和调试,介绍完毕。
从下一篇文章开始,我们将正式进入SystemUI的源码中,查看让人魂牵梦绕的SystemUI是怎样被写出来的。
另外,题外话,如果自己的PC性能还可以,可以使用一些AI工具,进行辅助编程,比如笔者正在使用tabnine插件,再比如使用variable extractor将对象翻译成json格式,然后使用工具,进行图形化查看,如前面文章中提及的Debug Visualizer工具
相关文章:

Android 12 源码分析 —— 应用层 一(SystemUI准备篇)
Android 12 源码分析 —— 应用层一(SystemUI准备篇) 在接下来的时间中,将会使用Pixel 3(blueline)作为研究对象,选用AOSP的android-12.0.0_r34分支作源代码。 先从android的应用层进行探析,然后慢慢深入android的fr…...
记录 MySQL 如何开启已有的定时任务
1.首先,确保你已经在MySQL的配置文件my.ini中启用了事件调度器。在[mysqld]部分添加event_schedulerON,然后保存文件并重启MySQL服务。这将启用MySQL的事件调度器功能。 但如果是线上业务不能停也可以在该数据库中输入 -- 开启事件计划程序 SET GLOBAL …...

三种生成树(STP,RSTP,MSTP)的基本配置(自我理解)
目录 一、为什么要使用生成树(STP): 二、由于设备冗余而导致的问题: 广播风暴: 三、802.1D生成树基本配置 四、802.1D生成树实验 实验拓扑: 实验配置: 配置完成后,在SW8上观察现象&…...

FRP内网穿透,配置本地电脑作为服务器
FRP内网穿透,配置本地电脑作为服务器 下载FRP服务端客户端 参考链接: https://www.it235.com/实用工具/内网穿透/pierce.html https://www.cnblogs.com/007sx/p/17469301.html 由于没有公网ip,所以尝试内网穿透将本地电脑作为服务器ÿ…...

Linux基础指令
本文已收录至《Linux知识与编程》专栏! 作者:ARMCSKGT 演示环境:CentOS 7 目录 前言 正文 查看当前用户whoami 查看当前目录路径pwd 清理屏幕clear 查看目录下文件指令ls 进入目录指令cd 以树状结构显示目录文件tree 创建普通文件指…...

基于GRU门控循环网络的时间序列预测matlab仿真,对比LSTM网络
目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 LSTM: GRU 2.算法运行软件版本 matlab2022a 3.部分核心程序 %构建GRU网络模型 layers [ ...sequenceInputLayer(N_feature)gruLayer(N_hidden)f…...

windows上ffmpeg如何录制双屏幕中的一个屏幕上的视频
首先,如何在window上安装ffmpeg自己查找scoop安装ffmpeg. 如题: 如果你有两个屏幕,如何让ffmpeg来录制其中的一个屏幕的视频呢。 很简单,首先你要查看另外一个屏幕的分辨率: 第一步:进入系统中 第二步&am…...

使用Python搭建服务器公网展示本地电脑文件
文章目录 1.前言2.本地http服务器搭建2.1.Python的安装和设置2.2.Python服务器设置和测试 3.cpolar的安装和注册3.1 Cpolar云端设置3.2 Cpolar本地设置 4.公网访问测试5.结语 1.前言 Python作为热度比较高的编程语言,其语法简单且语句清晰,而且python有…...

Java IO流(五)Netty实战[TCP|Http|心跳检测|Websocket]
Netty入门代码示例(基于TCP服务) Server端 package com.bierce.io.netty.simple; import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGro…...
C#基础进阶
C#基础进阶 泛型 http://www.runoob.com/csharp/csharp-generic.html 匿名函数 http://www.runoob.com/csharp/csharp-anonymous-methods.html 扩展方法 https://blog.csdn.net/u011127019/article/details/54728886 https://docs.microsoft.com/zh-cn/dotnet/csharp/pr…...

Java:ArrayList集合、LinkedList(链表)集合的底层原理及应用场景
ArrayList集合的底层原理及应用场景 LinkedList(链表)集合的底层原理及应用场景 单向链表 增加数据 删除数据 双向链表 LinkedList的应用场景之一:可以用来设计队列 入队 出队 LinkedList的应用场景之一:可以用来设计栈 压栈(push),addFirst…...

【Python】json文件的读取
文章目录 1. json简介2.json的使用规范3.json文件的书写4.json文件的读取 1. json简介 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,常用于将结构化数据进行传输和存储。它基于JavaScript语法,但可以被多种编程…...

专用杂凑函数的消息鉴别码算法学习记录
声明 本文是学习github5.com 网站的报告而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 范围 GB/T 15852的本部分规定了三种采用专用杂凑函数的消息鉴别码算法。这些消息鉴别码算法可用作数据完整性检验,检验数据是否被非授权地改变。同样…...

Golang使用消息队列(RabbitMQ)
最近在使用Golang做了一个网盘项目(类似百度网盘),这个网盘项目有一个功能描述如下:用户会删除一个文件到垃圾回收站,回收站的文件有一个时间期限,比如24h,24h后数据库中记录和oss中文件会被删除…...

Apache Spark远程代码执行漏洞(CVE-2023-32007)漏洞复现
漏洞描述 Apache Spark是美国阿帕奇(Apache)基金会的一款支持非循环数据流和内存计算的大规模数据处理引擎。 Apache Spark 3.4.0之前版本存在命令注入漏洞,该漏洞源于如果ACL启用后,HttpSecurityFilter中的代码路径可以允许通过…...

春秋云镜 :CVE-2020-21650(MyuCMS后台rce)
一、题目 靶标介绍: MyuCMS开源内容管理系统,采用ThinkPHP开发而成的社区商城聚合,插件,模板,轻便快捷容易扩展 其2.2版本中admin.php/config/add方法存在任意命令执行漏洞. 进入题目: exp: url/index.p…...
测试框架pytest教程(7)实现 xunit 风格的setup
pytest支持setup和teardown,对于使用unittest和nose框架的用户来说对这些很熟悉,但是在pytest可以使用功能更强大的fixture来实现固定装置。 模块级别 如果单个模块中有多个测试函数和测试类,您可以选择实现以下固定方法,这些方…...

用队列实现栈
目录 题目题目要求示例 解答方法一、实现思路时间复杂度和空间复杂度代码 方法二、实现思路时间复杂度和空间复杂度代码 方法三、实现思路时间复杂度和空间复杂度代码 总结 题目 用队列实现栈 题目要求 题目链接 示例 解答 方法一、 使用两个队列来实现栈。 实现思路 题…...

Anolis 8.6 下 Redis 7.2.0 集群搭建和配置
Redis 7.2.0 搭建和集群配置 一.Redis 下载与单机部署1.Redis 下载2.虚拟机配置3.Redis 单机源码安装和测试4.Java 单机连接测试1.Pom 依赖2.配置文件3.启动类4.配置类5.单元测试6.测试结果 二.Redis 集群部署1.主从1.从节点配置2.Java 测试 2.哨兵1.哨兵节点配置2.复制一个哨兵…...

综合能源系统(8)——综合能源系统支撑技术
综合能源系统关键技术与典型案例 何泽家,李德智主编 1、大数据技术 1.1、大数据技术概述 大数据是指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合,是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高…...

【项目实战】通过多模态+LangGraph实现PPT生成助手
PPT自动生成系统 基于LangGraph的PPT自动生成系统,可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析:自动解析Markdown文档结构PPT模板分析:分析PPT模板的布局和风格智能布局决策:匹配内容与合适的PPT布局自动…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...

AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...
十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建
【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...

MySQL的pymysql操作
本章是MySQL的最后一章,MySQL到此完结,下一站Hadoop!!! 这章很简单,完整代码在最后,详细讲解之前python课程里面也有,感兴趣的可以往前找一下 一、查询操作 我们需要打开pycharm …...
13.10 LangGraph多轮对话系统实战:Ollama私有部署+情感识别优化全解析
LangGraph多轮对话系统实战:Ollama私有部署+情感识别优化全解析 LanguageMentor 对话式训练系统架构与实现 关键词:多轮对话系统设计、场景化提示工程、情感识别优化、LangGraph 状态管理、Ollama 私有化部署 1. 对话训练系统技术架构 采用四层架构实现高扩展性的对话训练…...
手动给中文分词和 直接用神经网络RNN做有什么区别
手动分词和基于神经网络(如 RNN)的自动分词在原理、实现方式和效果上有显著差异,以下是核心对比: 1. 实现原理对比 对比维度手动分词(规则 / 词典驱动)神经网络 RNN 分词(数据驱动)…...
java+webstock
maven依赖 <dependency><groupId>org.java-websocket</groupId><artifactId>Java-WebSocket</artifactId><version>1.3.5</version></dependency><dependency><groupId>org.apache.tomcat.websocket</groupId&…...
Spring事务传播机制有哪些?
导语: Spring事务传播机制是后端面试中的必考知识点,特别容易出现在“项目细节挖掘”阶段。面试官通过它来判断你是否真正理解事务控制的本质与异常传播机制。本文将从实战与源码角度出发,全面剖析Spring事务传播机制,帮助你答得有…...

GC1808:高性能音频ADC的卓越之选
在音频处理领域,高质量的音频模数转换器(ADC)是实现精准音频数字化的关键。GC1808,一款96kHz、24bit立体声音频ADC,以其卓越的性能和高性价比脱颖而出,成为众多音频设备制造商的理想选择。 GC1808集成了64倍…...