文章目录
前言
阅读此文的前提是 你已经学会了docker编译源码,有基本Android开发能力,最好是有一台ubuntu的电脑。这会让你的学习事半功倍,虽然八仙过海各显神通,但是作为过来人的经验告诉,ubuntu+docker才是学习fw的最佳路线。
对于没有基础的朋友,建议先从如下两篇入手
Framework入门のPiex 6P源码(下载/编译/刷机)
Docker - Android源码编译与烧写
开始
废话不多说,先上大家最喜欢的环节,不闹眼子!截图以证清白~
源码一览,导入源码后 注意项目路径 /home/maqi/work/packages/apps/Camera2

framework+sdk 资源引用,避免大部分报错,


签名工具
bash
#查看签名
maqi@9a170cee6e8a:~/work$ cd build/target/product/security/
maqi@9a170cee6e8a:~/work/build/target/product/security$ ls -l
total 52
-rw-r--r-- 1 maqi maqi 260 Sep 1 14:17 Android.mk
-rw-r--r-- 1 maqi maqi 3123 Sep 1 14:17 README
-rw-r--r-- 1 maqi maqi 1216 Sep 1 14:17 media.pk8
-rw-r--r-- 1 maqi maqi 1675 Sep 1 14:17 media.x509.pem
-rw-r--r-- 1 maqi maqi 1216 Sep 1 14:17 platform.pk8
-rw-r--r-- 1 maqi maqi 1675 Sep 1 14:17 platform.x509.pem
-rw-r--r-- 1 maqi maqi 1218 Sep 1 14:17 shared.pk8
-rw-r--r-- 1 maqi maqi 1675 Sep 1 14:17 shared.x509.pem
-rw-r--r-- 1 maqi maqi 1217 Sep 1 14:17 testkey.pk8
-rw-r--r-- 1 maqi maqi 1675 Sep 1 14:17 testkey.x509.pem
-rw-r--r-- 1 maqi maqi 1219 Sep 1 14:17 verity.pk8
-rw-r--r-- 1 maqi maqi 1444 Sep 1 14:17 verity.x509.pem
-rw-r--r-- 1 maqi maqi 524 Sep 1 14:17 verity_key
maqi@maqi-Vostro-5590:~/work/build/target/product/security$ openssl x509 -in testkey.x509.pem -fingerprint -sha1 -noout
SHA1 Fingerprint=61:ED:37:7E:85:D3:86:A8:DF:EE:6B:86:4B:D8:5B:0B:FA:A5:AF:81
maqi@9a170cee6e8a:~/work/build/target/product/security$ which java
/usr/bin/java
#签名工具
maqi@9a170cee6e8a:~/work/out$ pwd
/home/maqi/work/out
maqi@9a170cee6e8a:~/work/out$ find -name Camera2.apk
./target/product/angler/system/app/Camera2/Camera2.apk
maqi@9a170cee6e8a:~/work/out$ find -name "signapk.jar"
./host/linux-x86/framework/signapk.jar
# 报错 使用 wget https://raw.githubusercontent.com/pallxk/signapk/master/signapk.jar
java -jar ~/work/out/host/linux-x86/framework/signapk.jar \
~/work/build/target/product/security/platform.pk8 \
~/work/build/target/product/security/platform.x509.pem \
~/work/out/target/product/angler/system/app/Camera2/Camera2.apk \
Camear2_sign.apk
#java环境
maqi@maqi-Vostro-5590:~$ find -name java
./.jdks/corretto-1.8.0_462/jre/bin/java
maqi@maqi-Vostro-5590:~$ export JAVA_HOME=./.jdks/corretto-1.8.0_462
maqi@maqi-Vostro-5590:~$ export PATH=$JAVA_HOME/bin:$PATH
maqi@maqi-Vostro-5590:~$ java -version
openjdk version "1.8.0_462"
OpenJDK Runtime Environment Corretto-8.462.08.1 (build 1.8.0_462-b08)
OpenJDK 64-Bit Server VM Corretto-8.462.08.1 (build 25.462-b08, mixed mode)
#查找签名查看工具
maqi@maqi-Vostro-5590:~$ find -name "apksigner.jar"
./Android/Sdk/build-tools/36.0.0/lib/apksigner.jar
./Android/Sdk/build-tools/33.0.1/lib/apksigner.jar
./Android/Sdk/build-tools/36.1.0-rc1/lib/apksigner.jar
maqi@maqi-Vostro-5590:~$ java -jar /home/maqi/Android/Sdk/build-tools/36.0.0/lib/apksigner.jar verify --verbose --print-certs /home/maqi/work/out/target/product/angler/system/app/Camera2/Camera2.apk
Verifies
Verified using v1 scheme (JAR signing): true
Verified using v2 scheme (APK Signature Scheme v2): true
Verified using v3 scheme (APK Signature Scheme v3): false
Verified using v3.1 scheme (APK Signature Scheme v3.1): false
Verified using v4 scheme (APK Signature Scheme v4): false
Verified for SourceStamp: false
Number of signers: 1
Signer #1 certificate DN: EMAILADDRESS=android@android.com, CN=Android, OU=Android, O=Android, L=Mountain View, ST=California, C=US
Signer #1 certificate SHA-256 digest: a40da80a59d170caa950cf15c18c454d47a39b26989d8b640ecd745ba71bf5dc
Signer #1 certificate SHA-1 digest: 61ed377e85d386a8dfee6b864bd85b0bfaa5af81
Signer #1 certificate MD5 digest: e89b158e4bcf988ebd09eb83f5378e87
Signer #1 key algorithm: RSA
Signer #1 key size (bits): 2048
Signer #1 public key SHA-256 digest: ef57b690165cb561b5026922c00d2d6574e8b184fa7d161e076f06e06e6d35db
Signer #1 public key SHA-1 digest: 0c2440c055c753a8f0493b4e602d3ea0096b1023
Signer #1 public key MD5 digest: 452f8cfe026b30a8a3e99a6074e5f285
验证一致性
以下是千问的回答
是的,可以确定 Camera2.apk 使用的是 testkey.x509.pem 这个证书进行签名的。
我们可以通过对比两个信息来确认这一点:
1. SHA-1 指纹比对
你使用以下命令查看了 testkey.x509.pem 的 SHA-1 指纹:
bash
openssl x509 -in testkey.x509.pem -fingerprint -sha1 -noout
输出为:
SHA1 Fingerprint=61:ED:37:7E:85:D3:86:A8:DF:EE:6B:86:4B:D8:5B:0B:FA:A5:AF:81
注意:这里显示的是大写、带冒号分隔的 SHA-1 指纹。
而 apksigner verify 输出中,Signer #1 certificate SHA-1 digest 是:
61ed377e85d386a8dfee6b864bd85b0bfaa5af81
虽然格式不同(小写、无冒号),但内容完全一致:
61:ED:37:7E:85:D3:86:A8:DF:EE:6B:86:4B:D8:5B:0B:FA:A5:AF:8161ed377e85d386a8dfee6b864bd85b0bfaa5af81
将两者都转为统一格式(如全小写无冒号)后完全相同。
✅ 结论:SHA-1 证书指纹完全匹配
这说明 Camera2.apk 的签名证书与 testkey.x509.pem 是同一个证书。
2. 额外佐证:证书主体(DN)
apksigner 显示的证书信息中,证书的 DN(Distinguished Name)是:
EMAILADDRESS=android@android.com, CN=Android, OU=Android, O=Android, L=Mountain View, ST=California, C=US
这个 DN 是 AOSP(Android Open Source Project)默认测试密钥(testkey)的典型特征。也就是说,testkey.x509.pem 很大概率就是 AOSP 构建系统中的那个默认 testkey。
✅ 最终结论:
是的,
Camera2.apk使用的就是testkey.x509.pem对应的私钥进行签名的。
因为:
- 签名证书的 SHA-1 指纹完全一致
- 证书的 DN 符合 AOSP testkey 特征
- 签名验证成功,且只有一个签名者
补充说明:
- 在 Android 系统中,应用能否升级、与其他应用交互、访问系统权限,都依赖于签名证书的一致性。
- 使用
testkey签名的应用不能 在正式发布系统中获得系统级权限(除非系统镜像本身也是用testkey签名的,如用户调试版本)。 - 在生产环境中,应使用自定义的、安全保管的密钥,而不是 AOSP 默认的
testkey。
如需进一步确认,你也可以用 OpenSSL 查看 testkey.x509.pem 的完整 DN 信息:
bash
openssl x509 -in testkey.x509.pem -subject -noout
输出应该与 apksigner 显示的 DN 一致。
build_gradle
编译jni
m libjpeg -j8
m Camera2 -j8

gradle依赖
glide 版本
bash
maqi@9a170cee6e8a:~/work$ find external/glide -name "Android.mk" -o -name "Android.bp" 2>/dev/null
external/glide/Android.mk
maqi@9a170cee6e8a:~/work$ cat external/glide/Android.mk
LOCAL_PATH := $(my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-java-files-under, library/src)
LOCAL_SRC_FILES += $(call all-java-files-under, third_party/disklrucache/src)
LOCAL_SRC_FILES += $(call all-java-files-under, third_party/gif_decoder/src)
LOCAL_SRC_FILES += $(call all-java-files-under, third_party/gif_encoder/src)
LOCAL_MANIFEST_FILE := library/src/main/AndroidManifest.xml
LOCAL_STATIC_JAVA_LIBRARIES := volley
LOCAL_STATIC_JAVA_LIBRARIES += android-support-v4
LOCAL_MODULE := glide
LOCAL_MODULE_TAGS := optional
LOCAL_SDK_VERSION := 19
include $(BUILD_STATIC_JAVA_LIBRARY)
include $(CLEAR_VARS)
implementation 'com.github.bumptech.glide:glide:4.16.0'
bash
#查找
find out/target/common/obj/JAVA_LIBRARIES -name "javalib.jar" | grep -i ext
out/target/common/obj/JAVA_LIBRARIES/ext_intermediates/classes.jar
#复制
maqi@maqi-Vostro-5590:~/work$ cp out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar packages/apps/Camera2/libs/framework.jar
maqi@maqi-Vostro-5590:~$ ls -l work/out/target/common/obj/JAVA_LIBRARIES/ |grep camera2
drwxr-xr-x 3 maqi maqi 4096 9月 17 23:29 android-ex-camera2-portability_intermediates
drwxr-xr-x 3 maqi maqi 4096 9月 17 23:29 android-ex-camera2-utils_intermediates
#监验
jar tf work/out/target/common/obj/JAVA_LIBRARIES/android-ex-camera2-portability_intermediates/classes.jar |grep CameraAgent
#复制
cp out/target/common/obj/JAVA_LIBRARIES/android-ex-camera2-portability_intermediates/classes.jar packages/apps/Camera2/libs/frameworks-ext.jar
# 手动添加 framework 和 frameworks-ext
implementation files('libs/framework.jar')
implementation files('libs/frameworks-ext.jar')
perfect 不报错了

编译
介于jni的集成有点复杂,此时还是只能用aosp的方式编译,但非完全不可能,目前代码编写布局引用均已完成链接,正常写代码不影响,make也是可以的
bash
maqi@9a170cee6e8a:~/work$ m Camera2 -j8
make: Entering directory '/home/maqi/work'
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=8.0.0
TARGET_PRODUCT=aosp_angler
TARGET_BUILD_VARIANT=userdebug
TARGET_BUILD_TYPE=release
TARGET_ARCH=arm64
TARGET_ARCH_VARIANT=armv8-a
TARGET_CPU_VARIANT=cortex-a53
TARGET_2ND_ARCH=arm
TARGET_2ND_ARCH_VARIANT=armv7-a-neon
TARGET_2ND_CPU_VARIANT=cortex-a53.a57
HOST_ARCH=x86_64
HOST_2ND_ARCH=x86
HOST_OS=linux
HOST_OS_EXTRA=Linux-5.15.0-139-generic-x86_64-with-Ubuntu-20.04-focal
HOST_CROSS_OS=windows
HOST_CROSS_ARCH=x86
HOST_CROSS_2ND_ARCH=x86_64
HOST_BUILD_TYPE=release
BUILD_ID=OPR5.170623.007
OUT_DIR=out
============================================
ninja: no work to do.
ninja: no work to do.
No need to regenerate ninja file
ninja: no work to do.
make: Leaving directory '/home/maqi/work'
#### make completed successfully (10 seconds) ####
修改项一览
bash
maqi@maqi-Vostro-5590:~/work/packages/apps/Camera2$ git status
On branch local_build
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: gradle.properties
new file: build.gradle
new file: gradle/wrapper/gradle-wrapper.jar
new file: gradle/wrapper/gradle-wrapper.properties
new file: local.properties
deleted: res/drawable-xxhdpi/ic_refocus_disabled.png
deleted: res/drawable-xxhdpi/ic_refocus_normal.png
示例一 格栅颜色修改


示例二 分析下拍照流程

从capture开始

开始拍照

操作buffer onPictureTaken 把数据带回来

本地保存逻辑 此时java层拍照已经闭环
监听流

到jni层了
Called from Native code when an Event happens. This may be called from an arbitrary Binder thread, so access to the ImageReader must be synchronized appropriately.

C++层调研

后面有点复杂。。。 回头再看
示例三 分析下预览流程
找到requestCameraOpen

使用handler传递callback和自己的handler

到CameraManager

出现了ICameraService

获取到一个服务的句柄 下面有个dead监听

回到前面的connectDevice 获取到这个CameraService就开始aidl操作了 注意还有很多其他操作一起关注下

下一步坑定是到ICameraService这个服务啦 注意callback 逮到了服务层
这下面应该是binder通讯,将callback传递给了序列化,開啓流程结束了

案例4 预览流程
接下来坑定是预览流程了,我们最关心的是数据流怎么呈现在用户面前的。
还记得前面的mCameraDeviceStateCallback吧,当相机打开时 会有onOpened被调用,此时下方的另一个callback会被触发。这个回调其实就是在CameraActivity中被初始化的


这里的module是基于设计模式的多态设计的,因为相机有拍照 录像 对焦等多种状态,不必关心,我们看PhotoModule

预览流程正式开始

预览的状态码是102
注意这个CameraAgent 是有两个实现类的 看名字就知道 适配的camera 和camera2 ,没办法适应需求设计的就是这么复杂。


找到camer2imp的102,createRequest传入了一个callback
这只是开启预览

上面的101就是将纹理给到

后面太繁琐,我们从onDrawFrame反推流程 直接上相关关键字
bash
# 第一个关键字
MSG_CONFIGURE_OUTPUTS
# 这三个是流程产物
configureStreamsChecked
endConfigure
configureOutputs
# 主要看这个
new GLThreadManager
#一个流程控制 一个负责具体实施渲染
new RequestHandlerThread + new SurfaceTextureRenderer
#很明显将线程引擎开起来了
mRequestThread.start()
#最後關鍵字 渲染~
MSG_NEW_FRAME

终极案例 hal如何告知上层dodraw的
那一定是通过jni告知的,看下方的生产和消费者

那肯定是找生产者啊,C++部分暂时不看,直接找关键jni接口

下行找到了 ,找上行,既hal信号从哪来,从刚才的生产者应该是可以发现端倪的。
关键字
BufferQueueProducer::queueBuffer
后面再展开
标题你们来写
to be continue...