android 14 apexd分析(2)apexd 启动

 


1. class main进程一起启动,  apexservice是他提供的binderservice,这也第二阶段的最主要的作用

/system/apex/apexd/apexd.rc?r=3c8e8603c640fc41e0406ddcf981381803447cfb#1
1 service apexd /system/bin/apexd
2     interface aidl apexservice     ----------> aidl service
3     class core
4     user root
5     group system
6     oneshot
7     disabled # does not start with the core class
8     reboot_on_failure reboot,apexd-failed
9     # CAP_CHOWN, CAP_DAC_OVERRIDE, CAP_DAC_READ_SEARCH required for apexdata snapshot & restore
10     # CAP_SYS_ADMIN is required to access device-mapper and to use mount syscall
11     capabilities CHOWN DAC_OVERRIDE DAC_READ_SEARCH FOWNER SYS_ADMIN


 
2. main()函数的的内容
 

/system/apex/apexd/apexd_main.cpp?r=3c8e8603c640fc41e0406ddcf981381803447cfb#106
106  int main(int /*argc*/, char** argv) {
.......
155    android::base::Result<android::apex::VoldCheckpointInterface>
156        vold_service_st = android::apex::VoldCheckpointInterface::Create();   ----> 获得Ivold binder service
157    android::apex::VoldCheckpointInterface* vold_service = nullptr;
158    if (!vold_service_st.ok()) {
159      LOG(ERROR) << "Could not retrieve vold service: "
160                 << vold_service_st.error();
161    } else {
162      vold_service = &*vold_service_st;
163    }
164    android::apex::Initialize(vold_service);                           ----> 获得使用Ivold的一些初始化操作
165  
166    if (booting) {         
167      if (auto res = android::apex::MigrateSessionsDirIfNeeded(); !res.ok()) {
168        LOG(ERROR) << "Failed to migrate sessions to /metadata partition : "
169                   << res.error();
170      }
171      android::apex::OnStart();                              ----> onstart 这其中就会 decompress compressedapex 和 ActivateApexPackages()
172    } else {
173      // TODO(b/172911822): Trying to use data apex related ApexFileRepository
174      //  apis without initializing it should throw error. Also, unit tests should
175      //  not pass without initialization.
176      // TODO(b/172911822): Consolidate this with Initialize() when
177      //  ApexFileRepository can act as cache and re-scanning is not expensive
178      android::apex::InitializeDataApex();
179    }
180    // start apexservice before ApexdLifecycle::WaitForBootStatus which waits for
181    // IApexService::markBootComplete().
182    android::apex::binder::CreateAndRegisterService();  ----> 把apexservice 添加到servicemanager中,这是个lazy service
183    android::apex::binder::StartThreadPool();
184  


题外话:
想要使用apexservice命令时,需要加上-w参数,因为他是个lazyservice,-w 是start and wait的意思,调用的是sm->waitforservice这个方法:
 

Example:
cmd -w apexservice getAllPackages
cmd -w apexservice deactivatePackage /system/apex/com.android.virt.apex
cmd -w apexservice activatePackage /system/apex/com.android.virt.apex

 

compressed apex解压如下:(实际上是对origin_apex又包了一层)
com.google.android.art_compressed$ ls
AndroidManifest.xml   apex_build_info.pb   apex_manifest.pb   apex_pubkey   META-INF   original_apex  original  stamp-cert-sha256

com.google.android.art_compressed/original_apex $ ls
AndroidManifest.xml  apex_build_info.pb  apex_manifest.pb  apex_payload.img  apex_pubkey  assets  META-INF  stamp-cert-sha256


3.ProcessCompressedApex() 把compressed apex搞到/data/apex/decompressed/下面
其中有一个验证比较有意思拉出来单聊,其他我也没兴趣,就没细看
 

2990  Result<void> ValidateDecompressedApex(const ApexFile& capex,
2991                                        const ApexFile& apex) {
2992    // Decompressed APEX must have same public key as CAPEX
2993    if (capex.GetBundledPublicKey() != apex.GetBundledPublicKey()) {=========> 1 压缩包的apexpubkey和original_apex的aepxpubkey是一样的
2994      return Error()
2995             << "Public key of compressed APEX is different than original "
2996             << "APEX for " << apex.GetPath();
2997    }
2998    // Decompressed APEX must have same version as CAPEX                        2 ======>压缩包的version和original_apex的version是一样的
2999    if (capex.GetManifest().version() != apex.GetManifest().version()) {
3000      return Error()
3001             << "Compressed APEX has different version than decompressed APEX "
3002             << apex.GetPath();
3003    }
3004    // Decompressed APEX must have same root digest as what is stored in CAPEX
3005    auto apex_verity = apex.VerifyApexVerity(apex.GetBundledPublicKey());      =======> 3 首先验证decompressed apex自己的avb特性
3006    if (!apex_verity.ok() ||
3007        capex.GetManifest().capexmetadata().originalapexdigest() !=
3008            apex_verity->root_digest) {
3009      return Error() << "Root digest of " << apex.GetPath()  =======> 4 再和compressed apex的manifest的root digest对比一下,见CompressedApexMetadata
3010                     << " does not match with"
3011                     << " expected root digest in " << capex.GetPath();
3012    }
3013    return {};
3014  }
秘钥的结果一模一样,就问你牛不牛逼
python3 avbtool.py info_image --image apex_payload.img
Footer version:           1.0
Image size:               831488 bytes
Original image size:      811008 bytes
VBMeta offset:            823296
VBMeta size:              2240 bytes
--
Minimum libavb version:   1.0
Header Block:             256 bytes
Authentication Block:     576 bytes
Auxiliary Block:          1408 bytes
Public key (sha1):        184474f2094c5dcbfc923af813bebddbf3f712e8
Algorithm:                SHA256_RSA4096
Rollback Index:           0
Flags:                    0
Rollback Index Location:  0
Release String:           'avbtool 1.2.0'
Descriptors:Hashtree descriptor: ------------------------------------- apex 用的是hashtreeVersion of dm-verity:  1Image Size:            811008 bytes                         -----> 198 blocksTree Offset:           811008Tree Size:             12288 bytes                          ------> 3 blocksData Block Size:       4096 bytesHash Block Size:       4096 bytesFEC num roots:         0FEC offset:            0FEC size:              0 bytesHash Algorithm:        sha256Partition Name:        Salt:                  b1c8aab92b646d2d85d0553fa1d3e0bea4c7289e2b740ae6079d40a490631bc0Root Digest:           25aaef0ecde6d8d66458d20f8ff4ef808c2630410443ffec18d82d8647aa332aFlags:                 0Prop: apex.key -> 'com_google_android_ipsec-image'      $ cat ./apex_pubkey |sha1sum
184474f2094c5dcbfc923af813bebddbf3f712e8hashtree的size的计算从layer 1开始,所以是3 blocks, 对于sha256算法,128个data block对应一个hashtree blocklayer 2                   root_hash_blk0/              \
layer 1         hash_blk_0              hash_blk_1/       \               /        \
layer 0    [blk_0] ....[blk_127]  [blk_128]....[blk_197]

 

 

 

 


4. ActivateApexPackages()  同上一章


5.PMS和apex的联系,用adb install apex
PMS在安装apex的时候,其实是通过apexservice 调用apexservice的

installAndActivatePackage()方法
/frameworks/base/services/core/java/com/android/server/pm/InstallingSession.java?r=3491936bce332909e2b20f7891ced303b9806925#495
495      private void processInstallRequests(boolean success, List<InstallRequest> installRequests) {
496          List<InstallRequest> apexInstallRequests = new ArrayList<>();
497          List<InstallRequest> apkInstallRequests = new ArrayList<>();
498          for (InstallRequest request : installRequests) {
499              if ((request.getInstallFlags() & PackageManager.INSTALL_APEX) != 0) {
500                  apexInstallRequests.add(request);
501              } else {
502                  apkInstallRequests.add(request);
503              }
504          }
505          // Note: supporting multi package install of both APEXes and APKs might requir some
506          // thinking to ensure atomicity of the install.
507          if (!apexInstallRequests.isEmpty() && !apkInstallRequests.isEmpty()) {
508              // This should've been caught at the validation step, but for some reason wasn't.
509              throw new IllegalStateException(
510                      "Attempted to do a multi package install of both APEXes and APKs");
511          }
512          if (!apexInstallRequests.isEmpty()) {
513              if (success) {
514                  // Since installApexPackages requires talking to external service (apexd), we
515                  // schedule to run it async. Once it finishes, it will resume the install.
516                  Thread t = new Thread(() -> installApexPackagesTraced(apexInstallRequests),  ====> 其实是调用的installAndActivatePackage()
517                          "installApexPackages");
518                  t.start();
519              } else {
520                  // Non-staged APEX installation failed somewhere before
521                  // processInstallRequestAsync. In that case just notify the observer about the
522                  // failure.
523                  InstallRequest request = apexInstallRequests.get(0);
524                  mPm.notifyInstallObserver(request);
525              }
526              return;
527          }
528   
529          processApkInstallRequests(success, installRequests);          ====> 普通apk的安装
530      }adb install apex命令和结果:
$ adb install com.android.ipsec@340818020.decompressed.apex
Performing Streamed Install
Success. Reboot device to apply staged session

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/795761.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

云数据库正进入2.0时代...

云数据库正进入2.0时代... 如何看待院士点赞国产数据库&#xff1f;这一行业还有哪些前景&#xff1f;中国在数据库领域正在赶超世界先进水平&#xff0c;您觉得数据库产业的突破到底意味着什么&#xff1f; 关于云原生数据库PolarDB&#xff0c;个人在实验场景或者是阿里云数据…

C++:连接MySQL数据库(一)

1、MySQL提供的连接相关API C和C都提供了访问MySQL的API接口&#xff0c;连接过程也较为简单主要是下面两个函数 mysql_init&#xff1a;初始化创建的MySQL结构体&#xff0c;如果传入空则自动分配一个。失败返回NULL&#xff0c;成功返回一个指针&#xff0c;它是线程不安全的…

【C++航海王:追寻罗杰的编程之路】C++的类型转换

目录 1 -> C语言中的类型转换 2 -> 为什么C需要四种类型转换 3 -> C强制类型转换 3.1 -> static_cast 3.2 -> reinterpret_cast 3.3 -> const_cast 3.4 -> dynamic_cast 4 -> RTTI 1 -> C语言中的类型转换 在C语言中&#xff0c;如果赋值运…

计算机中数的表示

0. 简介 介绍计算机中数的表示方法&#xff0c;主要内容来自 c s a p p csapp csapp。 1. 整数的表示 包括有符号整数与无符号整数的表示。 假设 w → [ w n − 1 w n − 2 . . . w 0 ] \overrightarrow w[w_{n-1}w_{n-2}...w_0] w [wn−1​wn−2​...w0​] 为一种整数。…

【Frida】【Android】09_爬虫之Socket

&#x1f6eb; 系列文章导航 【Frida】【Android】01_手把手教你环境搭建 https://blog.csdn.net/kinghzking/article/details/136986950【Frida】【Android】02_JAVA层HOOK https://blog.csdn.net/kinghzking/article/details/137008446【Frida】【Android】03_RPC https://bl…

2024 年广东省职业院校技能大赛(高职组)“云计算应用”赛项样题 3

#需要资源&#xff08;软件包及镜像&#xff09;或有问题的&#xff0c;可私聊博主&#xff01;&#xff01;&#xff01; #需要资源&#xff08;软件包及镜像&#xff09;或有问题的&#xff0c;可私聊博主&#xff01;&#xff01;&#xff01; #需要资源&#xff08;软件…

江协科技STM32:TIM输出比较

输出比较模块的主要功能&#xff1a;输出一定频率和占空比的PWM波形 CC是捕获比较的意思,R是Register&#xff0c;寄存器的意思&#xff0c;CCR捕获比较寄存器它是输入捕获和输出比较共用的 当使用输入捕获&#xff0c;它就是捕获寄存器 当使用输出比较&#xff0c;它就是比…

蓝桥杯每日一题:斐波那契(矩阵乘法)

在斐波那契数列中&#xff0c;Fib00,Fib11,FibnFibn−1Fibn−2(n>1) 给定整数 n&#xff0c;求 Fibnmod10000。 输入格式 输入包含不超过 100100 组测试用例。 每个测试用例占一行&#xff0c;包含一个整数 当输入用例 n−1时&#xff0c;表示输入终止&#xff0c;且该…

自由定义表单table组件(antdesign版)

对表单自由排序&#xff0c;决定哪些列显示隐藏&#xff0c;能保存设置过的操作 效果图 使用页&#xff0c;操作列dataIndex要设置为action&#xff0c;forKey必需是唯一的 用的vue2版的antdesign vue写的样式&#xff0c;想用其它的ui框架可以自行修改样式 <customTable …

Brain.js 的力量:构建多样化的人工智能应用程序

机器学习&#xff08;ML&#xff09;是人工智能 (AI) 的一种形式&#xff0c;旨在构建可以从处理的数据中学习或使用数据更好地执行的系统。人工智能是模仿人类智能的系统或机器的总称。 机器学习&#xff08;ML&#xff09;与复杂的数学纠缠在一起&#xff0c;让大多数初学者…

解决nginx代理后,前端拿不到后端自定义的header

先说结论&#xff0c;因为前端和nginx对接&#xff0c;所以需要在nginx添加如下配置向前端暴露header add_header Access-Control-Expose-Headers Authorization 排查过程 1.后端设置了Authorization 的响应头作为token的返回&#xff0c;前后端本地联调没有问题 response.s…

嵌入式驱动学习第六周——内核函数调用(堆栈打印)

前言 在内核中&#xff0c;函数调用堆栈非常重要&#xff0c;因为它可以帮助开发人员理解代码是如何执行的&#xff0c;从而进行调试、性能优化或问题排查。堆栈可以显示当前执行的函数以及导致该函数调用的先前函数&#xff0c;从而形成一个函数调用链。本篇博客就介绍堆栈打印…

软件无线电原理

常规软件无线电接收器&#xff1a; 首先&#xff0c;来自天线的射频信号被放大&#xff0c;通常射频部分利用一个调谐器将感兴趣的频段区域的信号进行放大。这个放大的射频信号被送入一个混频器。来自本振的信号也被送入混频器&#xff0c;其频率由无线电的调谐控制决定。混频器…

【LeetCode】--- 动态规划 集训(二)

目录 一、63. 不同路径 II1.1 题目解析1.2 状态转移方程1.3 解题代码 二、931. 下降路径最小和2.1 题目解析2.2 状态转移方程2.3 解题代码三、174. 地下城游戏3.1 题目解析3.2 状态转移方程3.3 解题代码 一、63. 不同路径 II 题目地址&#xff1a; 不同路径 II 一个机器人位于…

传输层 --- TCP (下篇)

目录 1. 超时重传 1.1. 数据段丢包 1.2. 接收方发送的ACK丢包 1.3. 超时重传的超时时间如何设置 2. 流量控制 3. 滑动窗口 3.1. 初步理解滑动窗口 3.2. 滑动窗口的完善理解 3.3. 关于快重传的补充 3.4. 快重传和超时重传的区别 4. 拥塞控制 4.1. 拥塞控制的宏观认识…

Java主流框架的历史演进与现代应用

Java作为一门广泛应用的编程语言&#xff0c;拥有丰富的框架生态系统&#xff0c;这些框架在Java应用程序的开发中发挥着重要作用。让我们深入探讨Java主流框架的历史演进&#xff0c;并对现代常用框架进行详细描述&#xff0c;包括Spring、Hibernate、Struts、Maven、MyBatis、…

「 典型安全漏洞系列 」11.身份验证漏洞详解

身份验证是验证用户或客户端身份的过程。网站可能会暴露给任何连接到互联网的人。这使得健壮的身份验证机制成为有效的网络安全不可或缺的一部分。 1. 什么是身份验证 身份验证即认证&#xff0c;是验证给定用户或客户端身份的过程。身份验证漏洞使攻击者能够访问敏感数据和功…

3.手写JavaScript前序中序后序递归遍历二叉树

一、核心思想 1.前序 本质是中左右&#xff0c;对每个结点执行中左右的操作&#xff0c;全部结点执行完毕后&#xff0c;返回结果 2.中序 本质是左中右&#xff0c;对每个结点执行左中右的操作&#xff0c;全部结点执行完毕后&#xff0c;返回结果 3.后序 本质是左右中&a…

Linux网络基础 (三) —— Socket

文章目录 Socket 编程基本概念Socket背景Socket 为了解决什么问题 socketsockaddr结构sockaddrsockaddr_insockaddr 和 sockaddr_in 的关系sockaddr_un 示例代码 &#x1f396; 博主的CSDN主页&#xff1a;Ryan.Alaskan Malamute &#x1f4dc; 博主的代码仓库主页 [ Gitee ]&…

【MySQL】数据操作语句(DML)

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前学习计网、mysql和算法 ✈️专栏&#xff1a;MySQL学习 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac…