adb shell
# netstat -ap |grep 7777
tcp 0 0 0.0.0.0:7777 0.0.0.0:* LISTEN 2596/test_service
tcp 0 0 localhost:7777 localhost:45634 ESTABLISHED 2596/test_service
tcp6 0 0 localhost:45634 localhost:7777 ESTABLISHED 5336/com.android.test
socket的三次握手:
三次握手只是一个数据传输的过程,但是,我们传输前需要一些准备工作,比如将创建一个套接字,收集一些计算机的资源,将一些资源绑定套接字里面,以及接受和发送数据的函数等等,这些功能接口在一起构成了socket的编程
server服务端:
client客户端:
在C/C++写网络程序的时候,往往会遇到字节的网络顺序和主机顺序的问题。这是就可能用到htons()
, ntohl()
, ntohs()
,htons()
这4个函数。
网络字节顺序与本地字节顺序之间的转换函数:
之所以需要这些函数是因为计算机数据表示存在两种字节顺序:NBO与HBO
Android的签名机制是一种Android保证系统安全的方式。Android中的签名就是对我们的应用或者系统加上特定的一些信息,防止被恶意篡改,而加上的这些特定信息就是签名。
Android源码中的系统签名统一存放路径:build/target/product/security
.pem类型文件
:在android对apk签名的时候,.pem这种文件就是一个X.509的数字证书,里面有用户的公钥等信息,是用来解密的。文件格式里面不仅可以存储数字证书,还能存各种key,这个可以公开,主要用于验证某个App或者其它的是否由相应的私钥签名。.pk8类型文件
:以.pk8为扩展名的文件,应该和PKCS 8是对应的,用来保存private key,并且这个私钥需要保密保存,不能公开。Android系统签名路径下一共有5种key:
README中介绍了怎么通过内置工具生成和替换系统默认预置的各种key,以及各种key的简单使用实例
在Android 根目录下执行命令生成releasekey、platform、shared、media。以platform为例,其他key以相同方式生成
development/tools/make_key platform'/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com'
释义:
系统会提示让你输入生成该key所需要的密码,输入回车即可。如果设置key密码,则编译不通过。
生成的key存在于Android根目录下,把key移动到/build/target/product/security
下并替换之前的key,同时需要使用OpenSSL的工具来验证一下生成的key是否正常。以releaseKey为例,执行以下命令: openssl x509 -noout -subject -issuer -in releaseKey.x509.pem
输出:
subject= /C=CN/ST=NanJing/L=NanJing/O=13/OU=123/CN=123/emailAddress=test@123.com
issuer= /C=CN/ST=NanJing/L=NanJing/O=123/OU=13/CN=123/emailAddress=test@123.com
输出的内容与生成该key时输入的内容一致,则代表key验证成功
make generate_verity_key (mmm system/extras/verity/)
development/tools/make_key veritykey '/C=CN/ST=NanJing/L=NanJing /O=123/OU=13/CN=123/emailAddress=test@123.com'
out/host/linux-x86/bin/generate_verity_key -convert veritykey.x509.pem verity_key
签名的使用分为两种情况:
build/target/product/security/
目录下,覆盖之前所有的默认key。将veritykey.pk8,veritykey.x509.pem,verity_key.pub重命名:verity.pk8,verity.x509.pem,verity_key/build/core/config.mk
中定义的变量:DEFAULT_SYSTEM_DEV_CERTIFICATE := build/target/product/security/testkey
PS:PRODUCT_DEFAULT_DEV_CERTIFICATE
:mk文件中定义的LOCAL_CERTIFICATE
变量,如果mk文件中定义了LOCAL_CERTIFICATE
,编译则使用所定义的签名文件,如果没有定义LOCAL_CERTIFICATE 变量,则进入else流程
/build/core/Makefile
中定义变量:ifeq ($(DEFAULT_SYSTEM_DEV_CERTIFICATE),build/target/product/security/releasekey) BUILD_VERSION_TAGS += release-keys
PS:这段code主要是判断在config.mk中定义的DEFAULT_SYSTEM_DEV_CERTIFICATE
变量,并在编译的时候使用对应的build_key。在刷机后可以通过getprop build.tags
来查看
system/sepolicy/private/keys.conf system/sepolicy/prebuilts/api/{apilevel}/private/keys.conf
以testkey作为示例:
device/project/
路径下新建一个用于存放新建key文件的文件夹security。仅用于存在key文件。后续步骤中会对路径做条件判断。device/project/product.mk
中进行条件判断:获取TARGET_BUILD_VARIANT,如果TARGET_BUILD_VARIANT为userdebug/eng
,则使用build/make/target/product/security/testkey
;否则使用我们自定义的文件夹中的key通过以下命令验证打包编译好的系统使用的签名,这种方式只适用与不区分user和debug版本的第一种修改:
adb root;adb remount
adb shell
cd system
getprop | grep ro.build.tags
#可以看到一行 ro.build.tags=release-keys
如果要区分user和debug版本的key,则可以使用下面两个方法:
adb install -r test.apk
安装进行判断keytool -printcert -file \...\path\CERT.RSA
可以查看此apk的签名内容,如果签名内容与自己生成的key内容一致,则说明当前系统签名使用的是自己生成的key在三方App应用中,因为不用经过Android系统编译,所以如果没有签名文件的情况下用到特殊权限则无法安装使用。所以可以提供对应的.keystore文件供其使用
在自己生成的key所在的路径下:
.pem
文件:openssl pkcs8 -in platform.pk8 -inform DER -outform PEM -out platform.priv.pem -nocrypt
openssl pkcs12 -export -in platform.x509.pem -out platform.p12 -inkey platform.pem -password pass:pwd -name name
,其中name为alias name,pwd为alias pwdkeytool -importkeystore -deststorepass pwd-destkeystore ./platform.keystore -srckeystore ./platform.p12 -srcstoretype PKCS12 -srcstorepass pwd
上面三个步骤可以在该路径下生成一个platform.keystore
文件。该文件可用于apk签名使用。
bootchart是一个用于linux启动过程性能分析的开源工具软件,在系统启动过程中自动收集CPU占用率、磁盘吞吐率、进程等信息,并以图形方式显示分析结果,可用作指导优化系统启动过程。
bootchart让用户可以很直观的查看系统启动的过程和各个过程耗费的时间,以便让用户能够分析启动过程,从而进行优化以提高启动时间。它由bootchartd服务和bootchart-render两部分组成,后者主要负责生成启动流程的分析结果图。
Android系统源码中有bootchart的实现,路径在system/core/init/bootchart.cpp
中, bootchart通过内嵌在init进程中实现,在后台执行测量。不过bootchart的测量时段是 init进程启动之后,不包含uboot和kernel的启动时间
adb shell 'touch /data/bootchart/enabled'
/data/bootchart
目录,先行删除enabled, 再执行tar -zcf bootchart.tgz *
, 接着adb pull /data/bootchart/bootchart.tgz
到本地,拷贝到ubuntusudo apt-get install bootchart
和sudo apt-get install pybootchartgui
bootchart bootchart.tg
adb shell 'touch /data/bootchart/enabled'
adb reboot
调试设备后,ubuntu电脑连接调试设备,终端android根目录执行命令:android$ ./system/core/init/grab-bootchart.sh
android高版本上不支持简单的设置方式调整bootchart的结束时间,只能在init.rc中修改,bootchart的启动和结束方式如下:
# Start bootcharting as soon as possible after the data partition is
# mounted to collect more data.
mkdir /data/bootchart 0755 shell shell encryption=Require
bootchart start
...
on property:sys.boot_completed=1
bootchart stop
原生的逻辑中,在开机完成时,系统会设置sys.boot_completed=1
,此时bootchart停止抓取信息;
我们可以更改stop的条件,自定义一个属性来实现停止,自己实现可控停止方式如下,在开机后,手动去设置这个属性值=1:
整个图表以时间线为横轴,图标上方为CPU和磁盘的利用情况,下方是各进程的运行状态条,显示各个进程的开始时间与结束时间以及对CPU、I/O的利用情况,各个进程的运行时间以及CPU的使用情况,进而优化系统。
可以通过Laucher的启动完成时间判断开机完成完成时间,也就是开机动画结束的时间
#切横屏:
su
settings put system user_rotation 3
settings put system accelerometer_rotation 0
#切竖屏:
settings put system accelerometer_rotation 1/2/ 3 随便改
从Android6.0(API23)开始, Google为Android加入了两种省电特性,通过管理Android应用(以下简称应用)在非充电状态下的设备中的运行策略来达到延长用户的Android设备使用时间的目的。这两种特性存在一定的差别,Doze模式通过延缓应用在设备长时间待机状态下对于CPU和网络资源的使用来实现节能;而App Standby则是通过延缓最近未被使用的后台应用对于网络的请求来达到同样的目的。
Doze和App Standby在Android6.0及以上的Android设备中可以影响所有运行状态下的Android应用,无论这些应用的Target API是否是指定为API23。为了确保用户获得在不同Android版本下的应用体验一致性,开发者需要对应用在Doze及App Standby模式下做相应的适配。
短接后重新重启,然后执行fastboot flashing unlock
fastboot unlock flashing
make -n
例如:make android -n
adb shell
# 同时适用于linux系统
df -ah
#或者
df -h
adb shell cat proc/kmsg
git push origin HEAD:refs/drafts/master
git push origin HEAD:refs/for/master
或者使用git remote -v
查看远程仓库push地址,替代origin
~/.gitconfig
:[core]
editor=vim
这种情况下可以使用下面的方法解决冲突:
git am xxxx.patch
尝试直接打入补丁。patch可能会报错并中断(注意,虽然命令停止执行了,但依然处于git am命令的运行环境中,可以通过git status
命令查看到当前的状态)git apply --reject xxxx.patch
自动合入patch中不冲突的代码改动,同时保留冲突的部分。这些存在冲突的改动内容会被单独存储到目标源文件的相应目录下,以后缀为.rej
的文件进行保存。比如对./test/someDeviceDriver.c
文件中的某些行合入代码改动失败,则会将这些发生冲突的行数及内容都保存在./test/someDeviceDriver.c.rej
文件中。我们可以在执行git am
命令的目录下执行find -name *.rej
命令以查看所有存在冲突的源文件位置*.rej
文件内容逐个手动解决冲突,然后删除这些*.rej
文件。完成这一步骤的操作后,就可以继续执行git am
的过程了git status
查看当前改动过的以及新增的文件,确保没有多添加或少添加文件git add .
将所有改动都添加到暂存区(注意,关键字add后有一个小数点.作为参数,表示当前路径)git am --resolved
继续步骤1中被中断的patch合入操作。合入完成后,会有提示信息输出git log
确认合入状态控制台输出:
~$ sudo dpkg-reconfigure dash
debconf: DbDriver "config": /var/cache/debconf/config.dat is locked by another process: Resource temporarily unavailable
解决方式:
查询进程:
sudo lsof /var/cache/debconf/config.dat
杀进程:
sudo kill PID进程号
******************************************************
error: VNDK library: android.hardware.light@2.0's ABI has INCOMPATIBLE CHANGES Please check compatiblity report at : out/soong/.intermediates/hardware/interfaces/light/2.0/android.hardware.light@2.0/android_arm64_armv8-a_cortex-a53_vendor_shared/android.hardware.light@2.0.so.abidiff
******************************************************
---- Please update abi references by running platform/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l android.hardware.light@2.0 ----
//执行该脚本后报错:
Traceback (most recent call last):
File "development/vndk/tools/header-checker/utils/create_reference_dumps.py", line 224, in <module>
main()
File "development/vndk/tools/header-checker/utils/create_reference_dumps.py", line 210, in main
targets = [Target(True, product), Target(False, product)]
File "development/vndk/tools/header-checker/utils/create_reference_dumps.py", line 29, in __init__
self.arch = build_vars[1]
IndexError: list index out of range
解决方式:
(1)环境判断:
执行: ls -l /bin/sh,查看用的是什么来解释执行Python脚本
$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 4月 2 2019 /bin/sh -> dash
如果用dash来解释执行Python脚本,得切换成bash
执行: sudo dpkg-reconfigure dash 选择no
控制台输出:
Android$ development/vndk/tools/header-checker/utils/create_reference_dumps.py -l android.hardware.light@2.0
Removing reference dumps...
removing /home/workspace/Android/prebuilts/abi-dumps/vndk/28/32/arm_armv7-a-neon/source-based/android.hardware.light@2.0.so.lsdump.gz
removing /home/workspace/Android/prebuilts/abi-dumps/ndk/28/32/arm_armv7-a-neon/source-based/android.hardware.light@2.0.so.lsdump.gz
making libs for product: aosp_arm_ab
再次执行:
//即自己编译的product name(out/target/product/test_product)
Android$ development/vndk/tools/header-checker/utils/create_reference_dumps.py -l android.hardware.light@2.0 -product test_product
Removing reference dumps...
removing /home//workspace/Android/prebuilts/abi-dumps/vndk/28/64/arm_armv8-a/source-based/android.hardware.light@2.0.so.lsdump.gz
removing /home//workspace/Android/prebuilts/abi-dumps/ndk/28/64/arm_armv8-a/source-based/android.hardware.light@2.0.so.lsdump.gz
removing /home//workspace/Android/prebuilts/abi-dumps/vndk/28/64/arm64_armv8-a/source-based/android.hardware.light@2.0.so.lsdump.gz
removing /home//workspace/Android/prebuilts/abi-dumps/ndk/28/64/arm64_armv8-a/source-based/android.hardware.light@2.0.so.lsdump.gz
making libs for product: test_product
Creating dumps for target_arch: arm and variant armv8-a
Created abi dump at /home//workspace/Android/prebuilts/abi-dumps/vndk/28/64/arm_armv8-a/source-based/android.hardware.light@2.0.so.lsdump.gz
Creating dumps for target_arch: arm64 and variant armv8-a
Created abi dump at /home//workspace/Android/prebuilts/abi-dumps/vndk/28/64/arm64_armv8-a/source-based/android.hardware.light@2.0.so.lsdump.gz
msg: Processed 2 libraries in 2.2664194742838544 minutes
# 项目代码根目录
adb root;adb remount
adb sync
adb shell sync
adb reboot
adb sync [directory]
如果不指定目录,将同步更新/data/和/system/
PS:为了避免对硬盘的频繁读写,数据一般存放在缓冲区。什么情况下会把缓冲区的数据写入到磁盘中:
make selinux_policy
:这条命令可以编译所有selinux⽂件,50s左右即可完成⼀次makemake ⽂件名
:例如:make plat_file_contexts -j9;
make plat_sepolicy.cil -j9;
make vendor_sepolicy.cil -j9;
make vendor_property_contexts -j9;
如果使⽤make出来的selinux⽂件,建议adb sync
命令同步到device中
或以下命令:
adb push out/target/product/product/vendor/etc/selinux/* vendor/etc/selinux/*
adb push out/target/product/product/system/etc/selinux/* system/etc/selinux/*
/out/target/common/obj/JAVA_LIBRARIES/android.car_intermediates$ ll
total 1988
drwxr-xr-x 2 user domain users 4096 Nov 26 16:34 ./
drwxr-xr-x 161 user domain users 12288 Nov 23 10:13 ../
-rw-r--r-- 1 user domain users 578273 Nov 26 16:16 classes-header.jar
-rw-r--r-- 1 user domain users 782057 Nov 26 16:16 classes.jar ---------> 该文件作为app导入的jar包
-rw-r--r-- 1 user domain users 0 Nov 12 11:24 exported-sdk-libs
-rw-r--r-- 1 user domain users 648154 Nov 26 16:34 javalib.jar
-rw-r--r-- 1 user domain users 14 Nov 12 11:24 link_type
Upgrade OTA升级相关文档:
系列文章:
单篇文章:
独立文章:
升级包解压后在payload_properties.txt文件可以看到payload.bin和metadata的文件大小和hash值 该hash值是通过sha256sum计算后,再base64编码成字符串 参考:Android Update Engine分析(十) 生成 payload 和 metadata 的哈希
实际操作:
$ cat ../../../payload_properties.txt
#payload.bin升级包数据
FILE_HASH=Kw0egs8dY9Qm1sULkpkAPF+0PiKx14Uo0fHGZO3vNAk=
FILE_SIZE=2515281637
#压缩后的 manifest 数据
METADATA_HASH=z+5Qz8UIBrhCtMDgo+5IG4/rQqFUqmN/FMFyIWhaIEU=
METADATA_SIZE=179557
$ ls -l payload.bin
#文件大小对应
-rw-r--r-- 1 user domain users 2515281637 Jan 1 2009 payload.bin
$ sha256sum payload.bin | awk '{print $1}' | xxd -r -ps | base64
#计算后的文件hash值对应
Kw0egs8dY9Qm1sULkpkAPF+0PiKx14Uo0fHGZO3vNAk=
#计算后的metadata hash值对应
$ dd if=payload.bin bs=1 count=179557 2>/dev/null | sha256sum | awk '{print $1}' | xxd -r -ps | base64
z+5Qz8UIBrhCtMDgo+5IG4/rQqFUqmN/FMFyIWhaIEU=
输入以下命令:
sudo losetup -d /dev/loop0
sudo losetup -d /dev/loop1
sudo losetup -d /dev/loop2
sudo losetup -d /dev/loop3
adb shell am start com.android.car.systemupdater/.SystemUpdaterActivity
/out/target/product/product/system$ find . -iname "*systemui*"
./product/priv-app/CarSystemUI
./product/priv-app/CarSystemUI/CarSystemUI.apk
./product/etc/permissions/com.android.systemui.xml
adb root
adb pull /data/misc/update_engine_log
adb pull /data/misc/update_engine/
adb shell
/data/misc/update_engine/prefs # ls -thl
total 38K
-rw------- 1 root root 1 2021-01-01 00:11 total-bytes-downloaded
-rw------- 1 root root 17 2021-01-01 00:11 system-updated-marker
-rw------- 1 root root 1 2021-01-01 00:11 delta-update-failures
-rw------- 1 root root 36 2021-01-01 00:11 update-completed-on-boot-id
-rw------- 1 root root 4 2021-01-01 00:11 post-install-succeeded
-rw------- 1 root root 4 2021-01-01 00:09 verity-written
-rw------- 1 root root 1 2021-01-01 00:08 update-state-next-data-length
-rw------- 1 root root 9 2021-01-01 00:08 update-state-next-data-offset
-rw------- 1 root root 4 2021-01-01 00:08 update-state-next-operation
-rw------- 1 root root 112 2021-01-01 00:08 update-state-sha-256-context
-rw------- 1 root root 264 2021-01-01 00:08 update-state-signature-blob
-rw------- 1 root root 112 2021-01-01 00:08 update-state-signed-sha-256-context
-rw------- 1 root root 6 2021-01-01 00:02 manifest-metadata-size
-rw------- 1 root root 3 2021-01-01 00:02 manifest-signature-size
-rw------- 1 root root 4 2021-01-01 00:02 dynamic-partition-metadata-updated
-rw------- 1 root root 1 2021-01-01 00:02 resumed-update-failures
-rw------- 1 root root 88 2021-01-01 00:02 update-check-response-hash
-rw------- 1 root root 36 1970-01-01 08:00 boot-id
-rw------- 1 root root 24 1970-01-01 08:00 previous-version
:/data/misc/update_engine/prefs # cat boot-id
e2ecfeb4-d097-449c-8c7b-e8aee5067cc6
:/data/misc/update_engine/prefs # cat previous-version
eng.user.20211201.031118
:/data/misc/update_engine/prefs # cat update-check-response-hash
LBhFc9jN99sOu9/VKy7COfkBXtXzlDt5fHdx1kQyU3c=vsNI/ZuKzDY0uOuXZIOjr42UHrzJ86isJSEtAwlFf9k=
//android/system/update_engine/common/error_code.h
// Action exit codes.
enum class ErrorCode : int {
kSuccess = 0, //升级成功
kError = 1, //升级失败
kOmahaRequestError = 2, //请求action错误(action机制用于控制升级每个步骤)
kOmahaResponseHandlerError = 3, //返回handler action错误
kFilesystemCopierError = 4, //文件系统拷贝错误
kPostinstallRunnerError = 5, //预编译运行步骤错误(PostinstallRunner是一个升级步骤)
kPayloadMismatchedType = 6, //NOT NEED
kInstallDeviceOpenError = 7, //安装设备打开错误
kKernelDeviceOpenError = 8, //内核设备打开错误
kDownloadTransferError = 9, //下载传输错误
kPayloadHashMismatchError = 10, //升级包hash未匹配错误
kPayloadSizeMismatchError = 11, //升级包size未匹配错误
kDownloadPayloadVerificationError = 12, //下载过程升级包校验错误
kDownloadNewPartitionInfoError = 13, //下载过程新分区信息错误
kDownloadWriteError = 14, //下载过程数据写入错误
kNewRootfsVerificationError = 15, //升级分区hash校验失败
kNewKernelVerificationError = 16, //升级kernel校验失败
kSignedDeltaPayloadExpectedError = 17, //NOT NEED
kDownloadPayloadPubKeyVerificationError = 18, //下载过程升级包public key公钥校验错误
kPostinstallBootedFromFirmwareB = 19, //NOT NEED
kDownloadStateInitializationError = 20, //下载状态初始化错误
kDownloadInvalidMetadataMagicString = 21, //NOT NEED
kDownloadSignatureMissingInManifest = 22, //下载过程manifest缺少签名错误
kDownloadManifestParseError = 23, //下载过程manifest分析错误
kDownloadMetadataSignatureError = 24, //下载过程元数据签名错误
kDownloadMetadataSignatureVerificationError = 25, //下载过程元数据签名校验错误
kDownloadMetadataSignatureMismatch = 26, //下载过程元数据签名不匹配错误
kDownloadOperationHashVerificationError = 27, //下载过程操作hash校验错误
kDownloadOperationExecutionError = 28, //下载过程操作执行错误
kDownloadOperationHashMismatch = 29, //下载过程操作hash不匹配错误
kOmahaRequestEmptyResponseError = 30, //请求action无返回错误
kOmahaRequestXMLParseError = 31, //请求action分析xml错误
kDownloadInvalidMetadataSize = 32, //下载过程非法元数据大小
kDownloadInvalidMetadataSignature = 33, //下载过程非法元数据签名
kOmahaResponseInvalid = 34, //返回action非法错误
kOmahaUpdateIgnoredPerPolicy = 35, //NOT NEED(含义是接收已回滚版本,忽略此次升级)
kOmahaUpdateDeferredPerPolicy = 36, //NOT NEED(含义是因更新策略延迟,忽略此次升级)
kOmahaErrorInHTTPResponse = 37, //HTTP返回错误
kDownloadOperationHashMissingError = 38, //下载过程操作时缺失hash错误
kDownloadMetadataSignatureMissingError = 39, //下载过程元数据签名缺失错误
kOmahaUpdateDeferredForBackoff = 40, //NOT NEED(含义是忽略本次升级)
kPostinstallPowerwashError = 41, //NOT NEED(回滚报错,该版本已去除版本回滚限制)
kUpdateCanceledByChannelChange = 42, //通道变化升级取消
kPostinstallFirmwareRONotUpdatable = 43, //NOT NEED(需要升级固件firmware时才会取消,因为无法从FW B分区启动到FW A分区)
kUnsupportedMajorPayloadVersion = 44, //获取manifest偏移量错误
kUnsupportedMinorPayloadVersion = 45, //未manifest可支持更小版本错误
kOmahaRequestXMLHasEntityDecl = 46, //请求action xml hash非法错误
kFilesystemVerifierError = 47, //文件系统校验错误(FilesystemVerifier是一个升级步骤)
kUserCanceled = 48, //用户取消
kNonCriticalUpdateInOOBE = 49, //NOT NEED(Ignoring a non-critical Omaha update before OOBE completion.)
kOmahaUpdateIgnoredOverCellular = 50, //NOT NEED(未设置设备策略,因此用户首选项需要覆盖是否允许通过蜂窝网络进行更新)
kPayloadTimestampError = 51, //升级包时间戳错误 (payload.bin是OTA镜像打包文件)
kUpdatedButNotActive = 52, //升级分区非action状态错误
kNoUpdate = 53, //无升级(There are no updates. Aborting.)
kRollbackNotPossible = 54, //NOT NEED
kFirstActiveOmahaPingSentPersistenceError = 55, //NOT NEED(用于旧设备的Omaha校验)
kVerityCalculationError = 56, //校验计算错误(在FilesystemVerifier步骤中进行分区校验时)
Android系统源代码目录与系统目录 Android源码及系统目录结构分析 Ubuntu16.04编译Android源码系列
- art/ # Android runtime运行环境, java虚拟机art源码
- bionic/ # C库
- bootable/ # 启动引导和恢复系统相关代码(bootloader和recovery)
- bootloader
- dramk_2712/
- lk/ # liitle kernel,负责引导Linux的⼀个迷你⼩系统,启动顺序位于fastboot/uboot之后,Linux kernel之前,系统开机之后是进Android还是进recovery,即是这⾥负责
- lk_ext_mod/
- recovery # 负责升级、恢复出⼚等⼀些⽐较重要⼜不是很复杂的⼯作,一般属于升级update子模块
- bootstrap.bash
- build/ # 存放系统编译规则等基础开发包配置
- blueprint # .bp的全程,由Go语⾔编写,是⽣成、解析Android.bp的⼯具,是Soong的⼀部分。Soong则是专为Android编译⽽设计的⼯具,Blueprint只是解析⽂件的形式,⽽Soong则解释内容的含义
- kati # 基于Makefile来⽣成ninja.build的⼩项⽬。主要⽤于把Makefile转成成ninja file,⾃⾝没有编译能⼒,转换后使⽤Ninja编译
- make
- soong # Soong(go语言写的项目)构建系统是在Android 7中引⼊的,旨在取代Make。它利⽤Kati GNU Make克隆⼯具和Ninja构建系统组件来加速 Android 的构建;Soong在编译时使⽤,解析Android.bp,将之转化为Ninja⽂件
- compatibility/ # 兼容性计划文档目录,一些markdown文档
- cts/ # cts测试用例源码,但是一般cts跑测是从官网下载官方更新的cts测试包,如果跑测出现case faile,可以根据log在这边阅读源码分析
- dalvik/ # java dalvik虚拟机
- developers/ # demo源码和开发者参考文档
- demo
- samples
- development/ # 应用程序开发相关的实例/模板/工具
- apps # 开发者选项等app
- tools
- device/ # 芯片厂商定制代码,包含AOSP自带的多家芯片厂以及芯片平台的代码,android O引入treble后,该目录下大部分关于厂商定制的源码移到vendor目录下
- mediatek_projects # 此目录存放芯片平台平台下,几种不同的变种芯片项目编译定制化内容
- external/ # 开源第三方组件模块,存放着⼤量Google在创造、更新Android过程中,因实现某些功能⽽引⼊的开源第三⽅库,有些库是做了多系统适配(例如适配Android、Win、Linux),有些是only for Android
- aac/ # aac解码库,AAC是高级音频编码(Advanced Audio Coding)
- bsdiff/ # diff工具
- frameworks/ # framework层,应用程序框架层
- av
- camera # cameram模块
- cmds
- screenrecord/ # 录屏工具源码
- stagefright/ # 一个多媒体框架
- media # audio、media源码
- packages # 只有一个MediaComponents apk源码
- services # audioflinger、cameraservice、mediacodec等核心源码
- soundtrigger # audio模块的语音识别唤醒相关
- base
- api #Android对外暴露的API整体存放位置,make update-api命令更新的就是这里的文件
- cmds # 命令/工具源码路径,例如am、pm、screencap等
- bootanimation/ # 开机动画
- core # android java和JNI核心库源码,例如framework.jar,hwbinder.jar,libandroid_runtime等
- jni # libandroid_runtime
- data # Android系统中字体、效果音等资源文件存放目录
- graphics # graphic基础补充库,属于framework.jar
- libs # display模块的hwui库位于这个目录下,以及其他的几个模块
- media # media部分的java实现和jni实现源码,java部分属于framework.jar
- opengl # opengl java api,隶属于framework.jar
- packages # aosp core app源码路径,有DocumentsUI、Keyguard、MtpDocumentsProvider、SettingsProvide、SystemUI、Wallpaper等
- services # service.jar源码,systemServer中启动的多数java service服务代码所在地
- telecomm/ # tele模块,属于framework.jar
- telephony/
- wifi # wifi java api源码目录,属于framework.jar
- native
- cmds # bugreport、dumpsys等Android debug工具的c实现源码,以及serviceManager
- libs # binder的Android中间件层实现源码,及libgui、libui、libsensor等中间件库源码
- opengl # OpenGL的c/c++实现源码
- services # 一些Android核心C进程的C/C++源码,例如surfaceFlinger、inputflinger、sensorservice等
- gerrit_config.sh
- hardware/ # 硬件适配层hal层
- interfaces/ # Android aosp定义的hidl interface实现,hal service实现源码
- libhardware
- moudles
- audio
- camera
- input
- mediatek # 芯片平台 HAL实现代码,上层对接Google HIDL interface
- kernel/ # aosp的kernel适配目录
- kernel-4.9/ # kernel层源码,Android P之前使用,Q和R是4.14
- libcore/ # Java api核心库实现源码,dalvik、art部分java实现代码也在这里
- dalvik
- libnativehelper/ # native层helper,即JNJ相关cpp源码
- Makefile # 全局makefile
- packages/ # 大部分android apk源码
- apps
- Calendar #日历应用
- Camera2/ # 官方camera
- car
- Email/
- Gallery # 图库
- SoundRecorder # 录音机
- providers # 存放着一堆provider的源码,media模块使用的MediaProvider,ContactsProvider等
- services # java service源码位置
- car # carservice源码
- pdk/ # platform development kit,平台开发工具
- platform_testing/ # 平台一些测试相关的源码
- prebuilts/ # 预编译资源
- go # go语言环境,比如用于支持soong
- sdk/ # sdk工具源码
- system/ # 底层文件系统库、应用、组件,特殊功能模块
- bt # 蓝牙相关
- connectivity # wifi相关库
- core # Android C/C++部分核心组件源码,有相当一部分是common类的组件
- adb # adb进程源码
- fastboot # fastboot命令工具源码
- healthd # 电池服务守护进程源码
- init # init进程实现源码
- libcutils # 工具库源码,例如property_set
- ibion # ion内存管理工具类源码
- liblog # ALOGX等相关函数实现源码
- libusbhost # usbhost实现库
- logcat # logcat实现源码
- logd # 负责输出log的logd守护进程源码
- sdcard # 外置存储卡挂载时会使用到的工具类
- hwservicemanager # hwservicemanager的实现源码,负责管理hidl service的,类似serviceManager
- libhidl # hidl功能的c/c++层实现源码
- libhwbinder # hwbinder功能的实现源码
- sepolicy # aosp selinux配置文件所在目录
- vold # 用于磁盘管理的守护进程
- test/ # vts测试源码
- vts
- toolchain/ # Android工具链
- tools/ # android一些工具的源码,例如apk签名
- apksig
- vendor/ # 厂商定制模块(芯片厂商以及我司定制化功能的实现代码)
- mediatek #
- external/
- hardware/
- kernel_modules/
- packages/ # 芯片平台方案的私有app源码
- proprietary/
1.source执行device和vendor⽬录下⾯⼀堆vendorsetup.sh⽂件,该shell脚本实就是调⽤add_lunch_combo函数,注册了对应的product
PS:如果我们需要⾃定义新增⼀个product,那么第⼀步,我们应该:在vendor⽬录或device⽬录下(这⾥推荐在vendor⽬录下),新增⼀个vendorsetup.sh⽂件,并且调⽤add_lunch_combo函数将我们期望增加的product name传递进去。
2.在执⾏完source build/envsetup.sh
命令后,定义⼀堆shell到当前的⽤⼾环境中,此时可以输⼊hmm
命令看到这些扩展shell命令,或者执行m help
可以在build/envsetup.sh
文件头看到以下的注释:
命令 | 解释 |
---|---|
lunch | lunch -选择作为要构建的产品,作为要构建的变体,并将这些选择存储在环境中,以便后续调⽤“m”等读取 |
tapas | 交互⽅式:tapas [..] (arm/x86/mips/arm64/x86_64/mips64)(eng/userdebug/user) |
croot | 将⽬录更改到树的顶部或其⼦⽬录 |
m | 编译整个源码,可以不⽤切换到根⽬录 |
mm | 编译当前⽬录下的源码,不包含他们的依赖模块 |
mma | 编译当前⽬录下的源码,包含他们的依赖模块 |
mmm | 编译指定⽬录下的所有模块,不包含他们的依赖模块 例如:mmm dir/:target1,target2 |
mmma | 编译指定⽬录下的所模块,包含他们的依赖模块 |
provision | 具有所有必需分区的闪存设备。选项将传递给fastboot |
cgrep | 对系统本地所有的C/C++ ⽂件执⾏grep命令 |
ggrep | 对系统本地所有的Gradle⽂件执⾏grep命令 |
jgrep | 对系统本地所有的Java⽂件执⾏grep命令 |
resgrep | 对系统本地所有的res⽬录下的xml⽂件执⾏grep命令 |
mangrep | 对系统本地所有的AndroidManifest.xml⽂件执⾏grep命令 |
mgrep | 对系统本地所有的Makefiles⽂件执⾏grep命令 |
sepgrep | 对系统本地所有的sepolicy⽂件执⾏grep命令 |
sgrep | 对系统本地所有的source⽂件执⾏grep命令 |
godir | 根据godir后的参数⽂件名在整个⽬录下查找,并且切换⽬录 |
user/userdebug/eng
标签指的是Android.mk编译脚本⾥对应的属性LOCAL_MODULE_TAGS
,LOCAL_MODULE_TAGS的取值有user、debug、eng、tests、optional
五个。
optional的意思是该模块不主动参与编译,需要开发者⾃⾏在对应的mk⽂件中include这个模块,就是在device.mk中的PRODUCT_PACKAGES
变量中引⼊该模块
1. root权限关闭,默认情况下⽆法adb root,⽆法adb remount,发货版本均为user版;
2. 仅标签为user的模块会参与编译;
3. app及jar包,及java源码的代码混淆被开启(除⾮显式指定关闭的模块会关闭);
4. 不包含D级别log输出
1. root权限开启,可remount,开发常⽤版本;
2. 标签为user、userdebug的模块会参与编译
1. root权限开启;
2. 标签为user、userdebug、eng的模块参与编译
adb remount
将/system
部分置于可写入的模式,默认情况下/system
部分是只读模式的。这个命令只适用于已被root的设备。
在将文件push到/system
文件夹之前,必须先输入命令adb remount
。
adb remount
的作用相当于adb shell mount -o rw,remount,rw /system
adb remount
重新挂载system分区,实现对system分区重新挂载,重新挂载的时候将修改分区的属性,常见的修改参数为分区的读写。
使用该命令主要是因为android系统的system分区在启动之后是只读分区,但在开发过程中需要对system分区进行修改,则需重新挂载成读写模式
参考:内存泄漏问题初探 参考:性能问题分析方法(1) — RAM 参考:Android Display/Graphics调试技巧(六月份更新)
1.物理内存泄漏
一般物理内存泄漏会导致kernel oom-killer
杀进程内存
日志中会打印具体哪个进程invoked oom-killer
,以及申请内存的堆栈,可以据此分析。
2.native 进程内存泄漏
从event log
中可以看到进程的内存使用信息。
一般通过am_pss
中能看个各个进程内存使用情况,如果某个native进程的am_pss中uss过高,大概率是它引起内存泄漏
am_pss: Pid, UID, ProcessName, Pss, Uss
am_pss (Pid|1|5),(UID|1|5),(Process Name|3),(Pss|2|2),(Uss|2|2),(SwapPss|2|2),(Rss|2|2),(StatType|1|5),(ProcState|1|5),(TimeToCollect|2|2)
am_meminfo: Cached,Free,Zram,Kernel,Native
am_low_memory: NumProcesses
//内存含义
vss (virtual set size) 虚拟内存,从进程地址空间统计,包括未实际申请到物理内存的部分。
rss (resident set size) 实际物理内存+共享库。共享库如果映射多个进程,不均摊。
pss ( proportional set size) 物理内存+均摊的共享内存。
uss (unique set size) 独占物理内存,不包含共享库部分(进程所占用的私有内存(内存泄漏的最佳观察数据)不包含so库占用内存的)
//例如
Line 82266: 01-01 08:24:27.599 2697 2798 I am_pss : [3541,1000,vendor.projection.androidauto,51497984,47623168,0,133905408,0,5,7]
3.虚拟地址内存泄漏
vss oom
,多发生在32位应用。虚拟地址空间不足,无法申请到 vma,所以申请内存失败。 一般只有发生泄漏的应用会崩溃,物理内存情况可能使用并不多,虚拟内存可能接近 4G(32位)。 一般需要 smaps/maps 信息做进一步分析,确认哪种类型的 vma 占比较多,那么大概率是它泄漏(比如 libc, egl,ion,等等)
4.ion内存泄漏
ion是android中特有的内存分配器,一般在camera,图像中使用较多。
通过 ion 的 ioctl 接口,可以申请不同类型的内存,可以为指定进程预留,比如 物理地址空间连续(cma),为相机预留。
ion 申请的内存需要主动释放,不释放会存在泄漏。每一个 heap 中申请的都对应一个 ion_buffer,我们可以统计 ion buffer 中某个进程占比多少(高通支持)。
如果 ion 的总量特别大(比如 4/8G),那么大概率是 ion 泄漏。再通过每个进程的信息,确定到是哪个进程申请导致的泄漏。
adb shell procrank
adb shell dumpsys cpuinfo > cpuinfo.txt
adb shell dumpsys meminfo > meminfo.txt
top -d 3
结果显示:
Tasks: 227 total, 1 running, 226 sleeping, 0 stopped, 0 zombie
Mem: 2.8G total, 2.1G used, 733M free, 4.0M buffers
Swap: 1.4G total, 38M used, 1.3G free, 323M cached
400%cpu 42%user 0%nice 111%sys 233%idle 0%iow 8%irq 6%sirq 0%host
PID USER PR NI VIRT RES SHR S[%CPU] %MEM TIME+ ARGS
4279 shell 20 0 35M 9.0M 2.4M R 55.5 0.3 0:00.15 top -d 3
2316 system -3 -20 165M 16M 5.0M S 27.7 0.5 17:25.76 android.hardware.graphics.composer@2.3-service
2314 system -2 -8 340M 30M 15M S 25.0 1.0 16:40.84 surfaceflinger
1.ps -A|grep 进程名
2.查看进程优先级:
adb shell
# 如果该进程其值为0。0表示该进程是正在前台运行
cat proc/917/oom_adj
$ service list|grep Update
60 updatelock: [android.os.IUpdateLock]
61 system_update: [android.os.ISystemUpdateManager]
105 webviewupdate: [android.webkit.IWebViewUpdateService]
147 android.os.UpdateEngineService: []
在对应包的symbols下查找库文件,使用addr2line命令:
symbols/vendor$ addr2line -f -e bin/test_service 000000000000ac40
_ZN12UpdateSocket9handleMsgEPv
vendor/..../test.cpp:87
adb shell pm clear com.test.upgrade
dumpsys package com.test.upgrade |grep version
参考:Android.bp 添加宏开关 参考源码:
hardware/interfaces/configstore/1.1/default/surfaceflinger.mk
LOCAL_CFLAGS += -DXXX
:相当于在所有源文件中增加一个宏定义#define XXX
例如:
在Android.mk中增加:
ifeq ($(PRODUCT_MODEL),XXX_A)
LOCAL_CFLAGS += -DBUILD_MODEL
endif
即能在所编译的cpp文件中使用:
#ifdef BUILD_MODEL
....
#endif
make snod
make vendorimage
repo forall -c git checkout Branch
:切换分支
在Android.mk配置: LOCAL_DEX_PREOPT := false
8|console:/dev/block/by-name # e2fsck -d vendor_a
e2fsck 1.44.4 (18-Aug-2018)
vendor: clean, 748/32768 files, 120659/131072 blocks
console:/dev/block/by-name #
console:/dev/block/by-name # e2fsck -a vendor_a
vendor: clean, 748/32768 files, 120659/131072 blocks
console:/dev/block/by-name #
console:/dev/block/by-name # e2fsck -c vendor_a
e2fsck 1.44.4 (18-Aug-2018)
sh: badblocks: inaccessible or not found
vendor: Updating bad block inode.
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
vendor: ***** FILE SYSTEM WAS MODIFIED *****
vendor: 748/32768 files (0.9% non-contiguous), 120659/131072 blocks
android支持emmc坏块测试工具badblocks
代码路径:./external/e2fsprogs/misc/badblocks.c
默认不编译,需配置:PRODUCT_PACKAGES += badblocks
当然你也可以为了开始验证可以直接使用如下命令进行单独编译,前提是你之前已经全部编译通过了。
source ./build/envsetup.sh
lunch platform_name ###(platform_name对应的sdk)
mmm external/e2fsprogs/misc/
然后将其push到system/bin
目录下
使用方法:
1.对硬盘进行只读扫描,自动获取硬盘块数目并扫描全部块,将扫描日志输出到屏幕同时记录在sdbbadblocks.log文件中。
由于扫描速度比较低,一次不一定能扫完,可以分多次进行。
sudo badblocks -s -v -o sdbbadblocks.log /dev/sdb END START
badblocks -sv /dev/block/mmcblk0p10
2.如果找到了坏道,可以进行写入扫描进行修复。写入扫描遇到坏道的时候会自动重映射。写入扫描会覆盖原有数据,所以请先备份。写入扫描速度很低,所以应该只扫描只读扫描时候发现错误的部分。
sudo badblocks -w -s /dev/sdb END START
在 Android 系统中有一个Property Service服务,这个服务对外提供了两个接口:
特殊前缀属性含义:
/data/property
目录。其他前缀的属性被设置后,只是保存在内存中而已,并没有保存到磁盘,所有重启后就恢复默认值了init.rc
中定义。init一旦收到设置ctrl.start
属性的请求,属性服务将使用该属性值作为服务名找到该服务,启动该服务。这项服务的启动结果将会放入init.svc.<服务名>
属性中android通过SystemProperties的set和get方法来控制很多东西,一般上层添加一个控制开关可以使用这个方法,在系统里面存在很多个prop文件。它们分别是
system/build.prop
,system/etc/prop.default
,vendor/build.prop
,vendor/default.prop
。下面分别来说下这几个文件的构成。
xxx_app_anr这个⽂件,⼀般记录的进程堆栈信息较之traces⽂件少⼀些。
所以,如果有traces,那我们就基于该⽂件分析定位bug。
/data/anr/
⽬录下,默认情况下,每发⽣⼀次anr,都会⽣成traces.txt⽂件,但是后发⽣的会将之前的覆盖掉/data/system/dropbox/
⽬录下,按不同压缩包存放。由Dropbox生成出现ANR可以使⽤adb pull
命令将⻋机⾥以上两个⽬录提取出来
通过调整printk的打印级别:
通过使用dd命令dump出来实际的分区内容,可以用来同原始image比较
dd if=/dev/block/by-name/mmcblkp*** of=/sdacar/a.img bs=512
dump出来的是raw文件,如果像system/vendor等都是sparse文件,需要先使用simg2img
转换成raw文件(Android编译环境直接使用)
块大小bs=2x80x18b表示2 × 80 × 18 × 512 = 1474560字节,也就是一张1440 KiB软盘的确切大小
另一种方式: 在当前目录生成一个大小为1G的大文件,内容是0
dd if=/dev/zero of=/test count=2 bs=512M
dd if=/dev/zero of=/test count=1 bs=1G
注解:
PS:simg2img是一个能把Android sparse 镜像转为row 镜像的工具,进而可以挂载解压
console:/dev/block/by-name # dd if=vendor_b of=vendor_a
对比img文件类型:
//车机dd出来的img
Debug_OTA_0401_img$ file system_old.img
system_old.img: Linux rev 1.0 ext4 filesystem data, UUID=4729639d-b5f2-5cc1-a120-9ac5f788683c (extents) (large files) (huge files)
//系统编译的img
$ file system.img
system.img: Android sparse image, version: 1.0, Total of 1310720 4096-byte output blocks in 86 input chunks.
采用挂载分区的方式来打开system.img文件
Debug_OTA_0401_img$ file system_old.img
system_old.img: Linux rev 1.0 ext4 filesystem data, UUID=4729639d-b5f2-5cc1-a120-9ac5f788683c (needs journal recovery) (extents) (large files) (huge files)
Debug_OTA_0401_img$ mkdir 1
Debug_OTA_0401_img$ sudo mount system_old.img 1/ -o loop
android本身提供了源代码工具在两者之间转换,源代码位于:
system/core/libsparse/simg2img.c // 将sparse image转换为raw image;
system/core/libsparse/img2simg.c // 将raw image转换为sparse image;
如果完整的进行过一次Android的编译,默认会将simg2img当作主机工具编译出来,放在out/host/linux-x86/bin/simg2img
处
但默认是不会编译img2simg的,我们可以手工进行编译:
$ .build/envsetup.sh
$ lunch aosp_hammerhead-userdebug
$ make img2simg_host
这样就会编译出out/host/linux-x86/bin/img2simg
如果要将system.raw.img转换为system.simg,执行:img2simg system.raw.img system.simg
1.解压ota包获取到payload.bin 2.使用工具payload_dumper-win64
,将其放入payload_input(windows工具) 3.运行payload_dumper.exe 4.image生成在payload_output
1.进入adb shell 2.在/dev/block/by-name/
查看分区对应的/dev/block/mmcblk0p7
3.使用dd if=/dev/block/by-name/mmcblkp*** of=/sdacar/a.img bs=512
命令获取到
1.确认文件属性
//车机dd出来的img
Debug_OTA_0401_img$ file system_old.img
system_old.img: Linux rev 1.0 ext4 filesystem data, UUID=4729639d-b5f2-5cc1-a120-9ac5f788683c (extents) (large files) (huge files)
//系统编译的img
$ file system.img
system.img: Android sparse image, version: 1.0, Total of 1310720 4096-byte output blocks in 86 input chunks.
2.如果是sparse文件属性,则进行转化:(android编译环境)
simg2img get.img result.img
3.采用挂载分区的方式来打开img文件
Debug_OTA_0401_img$ file system_old.img
system_old.img: Linux rev 1.0 ext4 filesystem data, UUID=4729639d-b5f2-5cc1-a120-9ac5f788683c (needs journal recovery) (extents) (large files) (huge files)
Debug_OTA_0401_img$ mkdir 1
Debug_OTA_0401_img$ sudo mount system_old.img 1/ -o loop
1.编译
source build/envsetup.sh
make lpunpack
2.可以用 lpdump 查看镜像的一些信息,信息里就包括了分区名称
./lpdump super.img_raw(这里是用 simg2img 转换后的文件)
参考: Android Recovery OTA升级(一)—— make otapackage 参考:Android Update Engine分析(八)升级包制作脚本分析
make otapackage
是Android Build系统支持的命令,用来生成Recovery系统能够进行升级的zip包
或者使用target包制作:
# 制作全量升级包
$ ./build/tools/releasetools/ota_from_target_files \
dist-output/bcm7252ssffdr4-target_files-eng.ygu.zip \
full-ota.zip
# 制作增量升级包
$./build/tools/releasetools/ota_from_target_files \
-i dist-output/bcm7252ssffdr4-target_files-eng.ygu.zip \
dist-output-new/bcm7252ssffdr4-target_files-eng.ygu.zip \
incremental-ota.zip
make target-files-package
编译出来的默认路径在:
out/target/product/{机型名}/obj/PACKAGING/target_files_intermediates/***-target_files-eng.***.zip
在所选用的device中BoardConfig.mk文件,修改或者增加一行TARGET_SKIP_OTA_PACKAGE := true
即可在构建时不生成ota更新包
使用payload dumper工具对升级包patload.bin文件进行解析,可以生成对应升级的image镜像文件
settings put system pointer_location 1
settings put system pointer_location 0
sudo vim /etc/udev/rules.d/android.rules
SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", MODE="0666"
重新拔插一下手机即可
dumpsys package
dumpsys package com.***.***
adb shell pm path com.***.***
am start ***/***.actvity
dumpsys activity top|grep ACTIVITY
例如打开CarSettings应用:
/system/priv-app/CarSettings # dumpsys package|grep "car.settings"
d1e0997 com.android.car.settings/.common.CarSettingActivity (2 filters)
.....
/system/priv-app/CarSettings # dumpsys activity top|grep ACTIVITY
ACTIVITY com.android.car.settings/.common.CarSettingActivity 154d0d8 pid=6296
/system/priv-app/CarSettings # am start com.android.car.settings/.common.CarSettingActivity
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.android.car.settings/.common.CarSettingActivity }
Warning: Activity not started, intent has been delivered to currently running top-most instance.
adb shell dumpsys window | findstr mCurrentFocus
adb shell dumpsys window | grep mCurrentFocus
android的init rc目前不支持touch:
log中会报错:init: /init.rc: 83: invalid keyword ‘touch’
可以用copy和write命令创建文件:
.rc文件:
//服务定义:
service screencnap/system/bin/test_service
# class 包括core main late_start等,可以不设置。默认default
class main
# 用户属性,默认root,一般给root即可,权限最大
user root
# 所属组,默认root
group root
# disabled 即通过class不能启动,只能start screencap 这种name的方式启动
disabled
# 只运行一次
oneshot
//服务启动条件:
on property:sys.start_service=1
start test_service
//Android.mk
LOCAL_INIT_RC := test.rc
//因为该属性设成true表示vendor专属模块
//如果要移到vendor/bin,则注释掉proprietary : true
//Android.bp
init_rc: ["test.rc"],
添加目录:device/project.mk
# test service
PRODUCT_PACKAGES += \
test_service
添加目录:device/project/sepolicy/vendor/common/
修改device/project/sepolicy/vendor/common/file_contexts
# test service
/vendor/bin/test_service u:object_r:test_service_exec:s0
新增device/project/sepolicy/vendor/commo/test_service.te
Android启动过程深入解析 android10.0的init执行顺序 深入理解SELinux SEAndroid(第一部分) Android 8.1RK平台增加自定义脚本,修改文件权限
# ls -al
total 36
drwxrwxrwx 4 system system 4096 2021-12-12 08:00 .
drwxr-xr-x 25 root root 4096 2022-03-15 18:48 ..
drwx------ 2 root root 16384 1970-01-01 08:00 lost+found
drwx------ 3 system system 4096 2021-12-12 08:00 usb
r读 数字4,w写数字2,x执行数字1,3个一组
第一组是自己的权限,第二组是自己所在组的权限,第三组是所有人的权限
chmod 764 文件名
,表示7=4+2+1,6=4+2,4=4
sudo chmod -R 777 folderName
adb shell
/sdcard/Android/data # ls -lAZ
total 4
-rw-rw---- 1 root sdcard_rw u:object_r:sdcardfs:s0 0 2021-01-01 08:00 .nomedia
drwxrwx--x 3 system sdcard_rw u:object_r:sdcardfs:s0 4096 2021-01-01 08:00 com.android.media
cat log.txt | grep avc | audit2allow
方法一:(出现naverAllow错误)
type=1400 audit(0.0:124): avc: denied { write } for name="com.engineeringmode-Ok7vxJdZR3gumPFFem-2fg==" dev="mmcblk0p43" ino=8777 scontext=u:r:system_app:s0 tcontext=u:object_r:apk_data_file:s0 tclass=dir permissive=0
根据这个mmcblk0p43去在file_context添加:/dev/block/mmcblk0p43 u:object_r:mmcblk_device:s0
然后对mmcblk_device赋权限
方法二:
01-01 08:03:22.410000 217 217 W applypatch: type=1400 audit(0.0:16): avc: denied { read } for name="mmcblk0p15" dev="tmpfs" ino=3364 scontext=u:r:install_recovery:s0 tcontext=u:object_r:block_device:s0 tclass=blk_file permissive=0
意思是说明install_revovery没有block_device的权限
只要在install_recovery.te
中加入下面权限就可以了。
allow install_recovery recover_block_device:blk_file { open read write };
概念:平台签名:Android.mk中,定义
LOCAL_CERTIFICATE := platform
system权限:AndroidManifest.xml中声明
android:sharedUserId="android.uid.system"
,同时是平台签名
分类:
LOCAL_PRIVILEGED_MODULE := true
, 在priv-app目录下的app查看备注:ps只能查看正在运行的进程,如果需要查看指定的app,需要先运行该app
adb shell ps -Z -e
adb shell ps -Z -e |grep xxx 或者 adb shell ps -Z -e |findstr xxx
输出的结果第一列是SContext,第二列是UID,只要UID是system的基本都是system_app
Line 43826: 01-01 09:44:32.220 5076 5076 W engineeringmode: type=1400 audit(0.0:540): avc: denied { search } for name="/" dev="mmcblk0p41" ino=2 scontext=u:r:system_app:s0 tcontext=u:object_r:unlabeled:s0 tclass=dir permissive=0
Line 43826: 01-01 09:44:32.220 5076 5076 W engineeringmode: type=1400 audit(0.0:540): avc: denied { search } for name="/" dev="mmcblk0p41" ino=2 scontext=u:r:system_app:s0 tcontext=u:object_r:unlabeled:s0 tclass=dir permissive=0
假设mmcblk0p41节点映射的是system语音分区,该分区是unlabeled,即系统没有指定的目录。 但是在sepolicy已经对该目录打了标签,所以对该分区路径重新打签名
重新relable指定的文件(夹):
/dev/block/by-name $ ls -al
...
lrwxrwxrwx 1 root root 21 1970-01-01 08:00 system -> /dev/block/mmcblk0p41
# 修改device/project/init.project.rc
on fs
restorecon_recursive /system
编译权限生成在系统目录:/vendor/etc/selinux
restorecon -R /(对应权限目录)
修改代码android/system/core/init/selinux.cpp
:IsEnforcing() 添加:return false
参考Google官网解释(繁体)https://source.android.google.cn/docs/security/features/selinux/build
Android 12源码说明,BOARD_PLAT_PUBLIC_SEPOLICY_DIR和BOARD_PLAT_PRIVATE_SEPOLICY_DIR被启用,使用SYSTEM_EXT_*替代
//system/sepolicy/README
SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS += device/acme/roadrunner-sepolicy/systemext/public
SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS += device/acme/roadrunner-sepolicy/systemext/private
PRODUCT_PUBLIC_SEPOLICY_DIRS += device/acme/roadrunner-sepolicy/product/public
PRODUCT_PRIVATE_SEPOLICY_DIRS += device/acme/roadrunner-sepolicy/product/private
The old BOARD_PLAT_PUBLIC_SEPOLICY_DIR and BOARD_PLAT_PRIVATE_SEPOLICY_DIR
variables have been deprecated in favour of SYSTEM_EXT_*.
地点 | 包含 |
---|---|
system/sepolicy/public | 平台的 sepolicy API |
system/sepolicy/private | 平台实现细节(产商可以忽略) |
system/sepolicy/vendor | 供应商可以使用的策略和上下文文件(如果需要,供应商可以忽略) |
BOARD_SEPOLICY_DIRS | 供应商政策 |
BOARD_ODM_SEPOLICY_DIRS | (Android 9 及更高版本) odm sepolicy |
SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS (Android 11 及更高版本) | System_ext 的 sepolicy API |
SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS (Android 11 及更高版本) | System_ext 实现细节(产商可以忽略) |
PRODUCT_PUBLIC_SEPOLICY_DIRS | (Android 11 及更高版本) 产品的 sepolicy API |
PRODUCT_PRIVATE_SEPOLICY_DIRS | (Android 11 及更高版本) |
执行git config --global core.whitespace cr-at-eol
尝试下面操作:编译失败后 1) 切换到Android根目录,先source lunch,然后执行: make api-stubs-docs-update-current-api
2) 再整体编译下
win+x
键选择PowerShell(增强型命令提示符),或者win+r
输入PowerShell
进入终端get-filehash usb_ota_update.zip -algorithm md5
输出:
get-filehash usb_ota_update.zip -algorithm md5
Algorithm Hash Path
--------- ---- ----
MD5 5FD6FA7C9C9BCCE6A18102D8A1C4250D D:\...
或者使用certutil命令获取md5值:
certutil -hashfile usb_ota_update.zip MD5
结果:
MD5 的 usb_ota_update.zip 哈希:
5fd6fa7c9c9bcce6a18102d8a1c4250d
CertUtil: -hashfile 命令成功完成。
还可以使用:
对应Ubuntu上就是:
Tips:如果出现两个系统对比的文件校验码不同,是因为ftp上传得过程中采用了文本模式,会把文件中换行回车替换为换行。可以用二进制模式上传。(文件打开读取要用二进制方式,文件传输也要用二进制方式)
find ./ -type f -print0 | xargs -0 md5sum
rd/s/q D:\app
:强制删除文件文件夹和文件夹内所有文件del/f/s/q D:\app.txt
:强制删除文件,文件名必须加文件后缀名DEL /F /A /Q RD /S /Q
Linux Daemon(守护进程)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。它不需要用户输入就能运行而且提供某种服务,不是对整个系统就是对某个用户程序提供服务。 守护进程一般在系统启动时开始运行,除非强行终止,否则直到系统关机都保持运行。守护进程经常以超级用户(root)权限运行,因为它们要使用特殊的端口(1-1024)或访问某些特殊的资源。 一个守护进程的父进程是init进程,因为它真正的父进程在fork出子进程后就先于子进程exit退出了,所以它是一个由init继承的孤儿进程。守护进程是非交互式程序,没有控制终端,所以任何输出,无论是向标准输出设备stdout还是标准出错设备stderr的输出都需要特殊处理。 守护进程的名称通常以d结尾,比如sshd、xinetd、crond等
tree [-aACdDfFgilnNpqstux][-I <范本样式>][-P <范本样式>][目录...]
-a 显示所有文件和目录
-d 显示目录名称而非内容
-D 列出文件或目录的更改时间。
-f 在每个文件或目录之前,显示完整的相对路径名称
-L level 限制目录显示层级,例如 -L 1
-s 列出文件或目录大小
-t 用文件和目录的更改时间排序
sudo shutdown -r now
sudo mount -t ext4 /dev/xvdc /home/user/C
sudo apt-get autoclean
:将已经删除了的软件包的.deb安装文件从硬盘中删除掉sudo apt-get clean
:删除包缓存中的所有包,也会把你已安装的软件包的安装包也删除掉sudo apt-get autoremove
:删除为了满足其他软件包的依赖而安装的,但现在不再需要的软件包(或使用ubuntu-tweak工具清理)apt-get remove PackageName
: 删除已安装的软件包(保留配置文件)apt-get --purge remove PackageName
: 删除已安装包(不保留配置文件)chown system 文件名
chgrp system 文件名
单个文件可以直接使用linux的diff命令
ls -tl| head -n 10
同样适用于windows系统,速度快
# 例子:把/test文件夹打包后生成一个/home/test.tar.gz的文件
tar -zcvf /home/test.tar.gz /test
tar -zcvf 打包后生成的文件名全路径 要打包的目录
# 解压:
tar -xvf test.tar.gz
压缩当前的文件夹 zip -r ./test.zip ./* -r表示递归
zip [参数] [打包后的文件名] [打包的目录路径]
unzip test.zip
:如果要把文件解压到指定的目录下,需要用到-d参数,unzip -d /temp test.zip
文件编辑中常用快捷键:ctrl+X 离开nano软件,若有修改过的文件会提示是否保存;选择 :yes
又提示:file name to write :***.launch ,选择:Ctrl+T
在下一个界面用 “上下左右” 按键 选择要保存的文件名,然后直接点击 “Enter” 按键即可保存
source .bashrc
system$ du -sh
1.7G .
system$ du -sh -k
1746700 .
system$ du -sh -m
1706
1.查看新增的磁盘:sudo fdisk -l
.....
Disk /dev/xvdc: 500 GiB, 536870912000 bytes, 1048576000 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
2.创建分区
~$ sudo fdisk /dev/xvdc
Welcome to fdisk (util-linux 2.27.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0x990e1f81.
Command (m for help): n //输入n,创建新逻辑磁盘
Partition type
p primary (0 primary, 0 extended, 4 free)
e extended (container for logical partitions)
Select (default p): //回车
Using default response p.
Partition number (1-4, default 1): 1 //输入1
First sector (2048-1048575999, default 2048): //回车
Last sector, +sectors or +size{K,M,G,T,P} (2048-1048575999, default 1048575999): //回车
Created a new partition 1 of type 'Linux' and of size 500 GiB.
Command (m for help): ^C //ctrl+c
3.磁盘格式化:sudo mkfs -t ext4 /dev/xvdc
4.挂载
~$ mkdir workspace
~$ sudo mount -t ext4 /dev/xvdc /home//workspace
~$ df -h
Filesystem Size Used Avail Use% Mounted on
udev 7.9G 0 7.9G 0% /dev
tmpfs 1.6G 9.7M 1.6G 1% /run
/dev/xvda1 83G 5.1G 74G 7% /
tmpfs 7.9G 20M 7.9G 1% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 7.9G 0 7.9G 0% /sys/fs/cgroup
/dev/xvdb1 13M 5.8M 7.3M 45% /mnt/iddisk
tmpfs 1.6G 32K 1.6G 1% /run/user/108
127.0.0.1:/ 2.0G 1000M 1000M 50% /ctxmnt
tmpfs 1.6G 120K 1.6G 1% /run/user/16777216
/dev/xvdc 493G 70M 467G 1% /home//workspace
PS:重启虚拟机后,如果硬盘没有自动挂载,重新执行 挂载 这一步
5.更改用户组
~$ sudo chown -R : workspace/ //用户冒号后面一个空格然后按tab选择挂载的文件夹
~$ ll
...
drwxr-xr-x 3 domain users 4096 Aug 10 14:35 workspace/ //原来是root
6.自动挂载硬盘
~$ cat /etc/fstab
.....
# swap was on /dev/xvda5 during installation
UUID=8e68541c-22a5-4156-8bae-c4479adf10d4 none swap sw 0 0
/dev/xvdc /home/USER/workspace ext4 defaults 0 1 //新增行在最后
其实就是没有权限进行sudo,解决方法如下:
su root
/etc/sudoers
文件:vim /etc/sudoers
root ALL=(ALL) ALL
一行,在下面插入新的一行,内容是lizh ALL=(ALL) ALL
,然后保存并退出安装一个Debian软件包,如你手动下载的文件: dpkg -i <package.deb>
删除软件包 dpkg -r xxx.deb
连同配置文件一起删除 dpkg -r --purge xxx.deb
查看软件包信息 dpkg -info xxx.deb
查看文件拷贝详情 dpkg -L xxx.deb
查看系统中已安装软件包信息 dpkg -l
重新配置软件包 dpkg-reconfigure xxx
参考:代码规范参考
set cc=100
(gerrit上行限制字符数是100)
which +命令
获取该命令的指向路径ssize_t read(int fildes, void *buf, size_t nbyte);
返回值:
> 0: 实际读到的字节数
= 0: 读完数据(读文件, 管道, socket末尾-->对端关闭, 对端未关闭会一直等待)
-1: 异常:
errno == EINTR被信号中断, 重启或者退出
errno == EAGAIN或者EWOULDBLOCK以非阻塞方式读, 并且没有数据
其他值: 出现错误perror eixt
ssize_t write(int fildes, const void *buf, size_t nbyte);
返回值: 返回实际写出的字节数, 0表示什么也没有写
ubuntu初始环境只有root用户,为了安全,新建一般权限用户。
root@iZbp10p2g1civut:/# useradd test
root@iZbp10p2g1civut:/# passwd test
root@iZbp10p2g1civut:/# usermod -s /bin/bash test
root@iZbp10p2g1civut:/# usermod -d /home/csdn test
root@iZbp10p2g1civut:/# mkdir /home/test
root@iZbp10p2g1civut:/# chown -R test:test /home/test
此时创建用户已经成功,可以用test用户进行登录。但此时的test用户不能使用sudo命令,因为没有在/etc/sudoers
文件里给test用户添加权限。
此时切换到root用户下,在/etc/sudoers
文件中添加一行命令:test ALL=(ALL) ALL
注意:
test ALL=(ALL) ALL
:允许用户youuser执行sudo命令(需要输入密码)%test ALL=(ALL) ALL
:允许用户组youuser里面的用户执行sudo命令(需要输入密码)test ALL=(ALL) NOPASSWD: ALL
:允许用户youuser执行sudo命令,并且在执行的时候不输入密码%test ALL=(ALL) NOPASSWD: ALL
:允许用户组youuser里面的用户执行sudo命令,并且在执行的时候不输入密码root@compile03-Virtual-Machine:/etc# grep bash /etc/passwd
root:x:0:0:root:/root:/bin/bash
compile03:x:1000:1000:compile03,,,:/home/compile03:/bin/bash
uchej537:x:999:999::/home/uchej537:/bin/bash
usunw074:x:1001:1001::/home/compile03/workspace/usunw074:/bin/bash
root@compile03-Virtual-Machine:/etc#
sudo su
su 账户名
cp /etc/skel/.bashrc ~/
cp /etc/skel/.profile ~/
source ~/.profile
cat /proc/cpuinfo
然后查看一共有几核
⼀般⾄少留⼀个核给其他软件使⽤,剩余的拿来编Android。⽽不是上去直接-j16
,这样很⼤概率不会起到编译加速的作⽤,反⽽会减慢编译速度。
例如9核CPU,⼀般情况下make -j8
;挂机编译时候直接给满:make -j9`
sudo dmidecode|grep -P -A5 "Memory\s+Device"|grep Size|grep -v Range
[sudo] password for user:
Size: 16376 MB
# 或者使用
free -m
两者区别对照:
单例模式:一个类有且只有一个实例
其原型为:int snprintf(char *str, int n, char * format [, argument, ...]);
int fseek(FILE *stream, long offset, int fromwhere);
:函数设置文件指针stream的位置。
如果执行成功,stream将指向以fromwhere为基准,偏移offset(指针偏移量)个字节的位置,函数返回0。如果执行失败(比如offset取值大于等于210241024*1024,即long的正数范围2G),则不改变stream指向的位置,函数返回一个非0值。
fseek函数和lseek函数类似,但lseek返回的是一个off_t数值,而fseek返回的是一个整型。
具体说明:
int fseek( FILE *stream, long offset, int origin );
第一个参数stream为文件指针
第二个参数offset为偏移量,正数表示正向偏移,负数表示负向偏移
第三个参数origin设定从文件的哪里开始偏移,可能取值为:SEEK_CUR、 SEEK_END 或 SEEK_SET
SEEK_SET: 文件开头
SEEK_CUR: 当前位置
SEEK_END: 文件结尾
其中SEEK_SET,SEEK_CUR和SEEK_END依次为0,1和2.
简言之:
fseek(fp,100L,0);把stream指针移动到离文件开头100字节处;
fseek(fp,100L,1);把stream指针移动到离文件当前位置100字节处;
fseek(fp,-100L,2);把stream指针退回到离文件结尾100字节处。
long int ftell(FILE *stream)
:函数 ftell 用于得到文件位置指针当前位置相对于文件首的偏移字节数。在随机方式存取文件时,由于文件位置频繁的前后移动,程序不容易确定文件的当前位置。
ftell(fp);
:利用函数 ftell() 也能方便地知道一个文件的长。
如以下语句序列: fseek(fp, 0L,SEEK_END); len =ftell(fp);
首先将文件的当前位置移到文件的末尾,然后调用函数ftell()获得当前位置相对于文件首的位移,该位移值等于文件所含字节数。
feof是C语言标准库函数,其原型在stdio.h中,其功能是检测流上的文件结束符,如果文件结束,则返回非0值,否则返回0(即,文件结束:返回非0值;文件未结束:返回0值)
fgets函数功能为从指定的流中读取数据,每次读取一行。其原型为:char *fgets(char *str, int n, FILE *stream);
char *fgets(char *str, int n, FILE *stream);
从指定的流 stream 读取一行,并把它存储在str所指向的字符串内。当读取(n-1)个字符时,或者读取到换行符时,或者到达文件末尾时,它会停止,具体视情况而定
uint8_t char_2_hex(uint8_t *src)
{
uint8_t desc;
if((*src >= '0') && (*src <= '9'))
desc = *src - 0x30;
else if((*src >= 'a') && (*src <= 'f'))
desc = *src - 0x57;
else if((*src >= 'A') && (*src <= 'F'))
desc = *src - 0x37;
return desc;
}
其中char字符buf[1] - 0x30
:表示将16进制数转换成10进制数0x30在ascii里面是字符0
uint8_t hex_2_char(uint8_t *src)
{
uint8_t desc;
if((*src >= 0) && (*src <= 9))
desc = *src + 0x30;
else if((*src >= 0xA) && (*src <= 0xF))
desc = *src + 0x37;
return desc;
}
readdir()返回参数dir 目录流的下个目录进入点
d_type表示档案类型:
enum
{
DT_UNKNOWN = 0,
# define DT_UNKNOWN DT_UNKNOWN
DT_FIFO = 1,
# define DT_FIFO DT_FIFO
DT_CHR = 2,
# define DT_CHR DT_CHR
DT_DIR = 4,
# define DT_DIR DT_DIR
DT_BLK = 6,
# define DT_BLK DT_BLK
DT_REG = 8,
# define DT_REG DT_REG
DT_LNK = 10,
# define DT_LNK DT_LNK
DT_SOCK = 12,
# define DT_SOCK DT_SOCK
DT_WHT = 14
# define DT_WHT DT_WHT
};
这种方法不用考虑跨平台的问题,因为使用的是C++标准库中的函数实现的。
/*
* 文件名 : main.cpp
* 功能 : 将字符串转换为大写,使用transform函数
*/
#include <iostream>
#include <algorithm>
using namespace std;
int main(int argc, char **argv)
{
string strTest = "use test.";
transform(strTest.begin(), strTest.end(), strTest.begin(), toupper);
for (size_t i = 0; i < strTest.size(); i++) {
cout << strTest[i];
}
cout << endl;
return 0;
}
例如: 1.AndroidManifest.xml中添加:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:sharedUserId="android.uid.system"
package="com.example.debugapp">
....
2.build.gradle中添加签名文件
signingConfigs {
debug {
storeFile file("../signApk/platform.jks") //导入对应的keystore文件
storePassword 'android'
keyAlias 'androiddebugkey'
keyPassword 'android'
}
}
或者这样加:
release {
storeFile file("platform.jks")
storePassword 'android'
keyAlias 'platform'
keyPassword 'android'
v1SigningEnabled true
v2SigningEnabled true
}
debug {
storeFile file("platform.jks")
storePassword 'android'
keyAlias 'platform'
keyPassword 'android'
v1SigningEnabled true
v2SigningEnabled true
}
adb install -r -t -d Debug.apk
Performing Streamed Install
adb: failed to install Debug.apk: Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE: Package com.example.debugapp signatures do not match previously installed version; ignoring!]
/data/system/packages.xml
pull到本地根build.gradle文件中添加镜像仓库:
buildscript {
repositories {
maven { url 'https://jitpack.io' }
maven { url 'https://maven.aliyun.com/repository/public' }
maven { url 'https://maven.aliyun.com/repository/central' }
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'https://maven.aliyun.com/repository/public' }
maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
google()
jcenter()
}
dependencies {
.....
}
}
allprojects {
repositories {
maven { url 'https://jitpack.io' }
maven { url 'https://maven.aliyun.com/repository/public' }
maven { url 'https://maven.aliyun.com/repository/central' }
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'https://maven.aliyun.com/repository/public' }
maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
google()
jcenter()
}
在项目中的gradle.properties文件中添加语句:
android.overridePathCheck=true
网络问题,切换可用网络
工具推荐:
vscode插件:
安装koroFileHeader插件
设置选项搜索cursorMode修改如下:
// 函数注释
"fileheader.cursorMode": {
// 默认字段
"description":"",
"param":"",
"return":""
在file->preferences->settings
的settings.json中添加:"editor.rulers": [4, 100]
按:shift + tab
关闭方法:点击文件-首选项-设置,搜索editor.minimap.enabled
,默认值为打钩,只需要把钩去掉即可
workbench.editor.enablePreview
改为false
wrap tabs
ALT+Z
chromeium安装失败
在首选项-设置-扩展-markdown pdf的executablePath添加路径:C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe