Android 安装应用-提交阶段之后剩下的操作
它的实现代码在executePostCommitSteps(commitRequest)中,看一下它的代码:
/*** On successful install, executes remaining steps after commit completes and the package lock* is released. These are typically more expensive or require calls to installd, which often* locks on {@link #mLock}.*/private void executePostCommitSteps(CommitRequest commitRequest) {final ArraySet<IncrementalStorage> incrementalStorages = new ArraySet<>();for (ReconciledPackage reconciledPkg : commitRequest.reconciledPackages.values()) {final boolean instantApp = ((reconciledPkg.scanResult.request.scanFlags& PackageManagerService.SCAN_AS_INSTANT_APP) != 0);final AndroidPackage pkg = reconciledPkg.pkgSetting.pkg;final String packageName = pkg.getPackageName();final String codePath = pkg.getPath();final boolean onIncremental = mIncrementalManager != null&& isIncrementalPath(codePath);if (onIncremental) {IncrementalStorage storage = mIncrementalManager.openStorage(codePath);if (storage == null) {throw new IllegalArgumentException("Install: null storage for incremental package " + packageName);}incrementalStorages.add(storage);}prepareAppDataAfterInstallLIF(pkg);if (reconciledPkg.prepareResult.clearCodeCache) {clearAppDataLIF(pkg, UserHandle.USER_ALL, FLAG_STORAGE_DE | FLAG_STORAGE_CE| FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);}if (reconciledPkg.prepareResult.replace) {mDexManager.notifyPackageUpdated(pkg.getPackageName(),pkg.getBaseApkPath(), pkg.getSplitCodePaths());}// Prepare the application profiles for the new code paths.// This needs to be done before invoking dexopt so that any install-time profile// can be used for optimizations.mArtManagerService.prepareAppProfiles(pkg,resolveUserIds(reconciledPkg.installArgs.user.getIdentifier()),/* updateReferenceProfileContent= */ true);// Compute the compilation reason from the installation scenario.final int compilationReason = mDexManager.getCompilationReasonForInstallScenario(reconciledPkg.installArgs.mInstallScenario);// Construct the DexoptOptions early to see if we should skip running dexopt.//// Do not run PackageDexOptimizer through the local performDexOpt// method because `pkg` may not be in `mPackages` yet.//// Also, don't fail application installs if the dexopt step fails.final boolean isBackupOrRestore =reconciledPkg.installArgs.installReason == INSTALL_REASON_DEVICE_RESTORE|| reconciledPkg.installArgs.installReason == INSTALL_REASON_DEVICE_SETUP;final int dexoptFlags = DexoptOptions.DEXOPT_BOOT_COMPLETE| DexoptOptions.DEXOPT_INSTALL_WITH_DEX_METADATA_FILE| (isBackupOrRestore ? DexoptOptions.DEXOPT_FOR_RESTORE : 0);DexoptOptions dexoptOptions =new DexoptOptions(packageName, compilationReason, dexoptFlags);// Check whether we need to dexopt the app.//// NOTE: it is IMPORTANT to call dexopt:// - after doRename which will sync the package data from AndroidPackage and// its corresponding ApplicationInfo.// - after installNewPackageLIF or replacePackageLIF which will update result with the// uid of the application (pkg.applicationInfo.uid).// This update happens in place!//// We only need to dexopt if the package meets ALL of the following conditions:// 1) it is not an instant app or if it is then dexopt is enabled via gservices.// 2) it is not debuggable.// 3) it is not on Incremental File System.//// Note that we do not dexopt instant apps by default. dexopt can take some time to// complete, so we skip this step during installation. Instead, we'll take extra time// the first time the instant app starts. It's preferred to do it this way to provide// continuous progress to the useur instead of mysteriously blocking somewhere in the// middle of running an instant app. The default behaviour can be overridden// via gservices.//// Furthermore, dexopt may be skipped, depending on the install scenario and current// state of the device.//// TODO(b/174695087): instantApp and onIncremental should be removed and their install// path moved to SCENARIO_FAST.final boolean performDexopt =(!instantApp || Global.getInt(mContext.getContentResolver(),Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0)&& !pkg.isDebuggable()&& (!onIncremental)&& dexoptOptions.isCompilationEnabled();if (performDexopt) {// Compile the layout resources.if (SystemProperties.getBoolean(PRECOMPILE_LAYOUTS, false)) {Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "compileLayouts");mViewCompiler.compileLayouts(pkg);Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);}Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");ScanResult result = reconciledPkg.scanResult;// This mirrors logic from commitReconciledScanResultLocked, where the library files// needed for dexopt are assigned.// TODO: Fix this to have 1 mutable PackageSetting for scan/install. If the previous// setting needs to be passed to have a comparison, hide it behind an immutable// interface. There's no good reason to have 3 different ways to access the real// PackageSetting object, only one of which is actually correct.PackageSetting realPkgSetting = result.existingSettingCopied? result.request.pkgSetting : result.pkgSetting;if (realPkgSetting == null) {realPkgSetting = reconciledPkg.pkgSetting;}// Unfortunately, the updated system app flag is only tracked on this PackageSettingboolean isUpdatedSystemApp = reconciledPkg.pkgSetting.getPkgState().isUpdatedSystemApp();realPkgSetting.getPkgState().setUpdatedSystemApp(isUpdatedSystemApp);mPackageDexOptimizer.performDexOpt(pkg, realPkgSetting,null /* instructionSets */,getOrCreateCompilerPackageStats(pkg),mDexManager.getPackageUseInfoOrDefault(packageName),dexoptOptions);Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);}// Notify BackgroundDexOptService that the package has been changed.// If this is an update of a package which used to fail to compile,// BackgroundDexOptService will remove it from its denylist.// TODO: Layering violationBackgroundDexOptService.notifyPackageChanged(packageName);notifyPackageChangeObserversOnUpdate(reconciledPkg);}waitForNativeBinariesExtraction(incrementalStorages);}
首先对ReconciledPackage对象循环,得到AndroidPackage对象pkg,包名、文件路径。
接着调用prepareAppDataAfterInstallLIF(pkg),它主要用来创建应用需要使用的文件或文件夹。应用需要使用的文件或文件夹和参数uuid(存储位置相关)、userId和包名相关。如果uuid为null,userId为0,则文件夹为"/data/data/“(版本遗留) + 包名 或 “/data/user/0/” + 包名,及其目录下面的"cache"和"code_cache"目录;”/data/user_de/0/" + 包名,及其目录下面的"cache"和"code_cache"目录,如果"dalvik.vm.usejitprofiles"属性值为true的情况下(和JIT编译有关),还会创建 “/data/misc/profiles/cur/0” + 包名 目录 和 “/data/misc/profiles/ref/” + 包名 目录。
如果reconciledPkg.prepareResult.clearCodeCache为true,代表需要清除代码缓存,所以调用带有Installer.FLAG_CLEAR_CODE_CACHE_ONLY标识的clearAppDataLIF()方法。带这个标识的方法,就是清除这个应用数据文件夹下面的"code_cache"目录及其中文件。
reconciledPkg.prepareResult.replace为true,代表是替换升级。mDexManager.notifyPackageUpdated()通知mDexManager应用包发生了更新,它会更新其中应用的安装位置,去除使用该应用的其他APP。
mArtManagerService.prepareAppProfiles()是和使用profile优化应用有关,它的参数updateReferenceProfileContent为true,代表它需要将dex元数据文件(“.dm"结尾文件)更新到它自己引用的profile内容中,这块需要使用Profman程序。主APK文件相关的profile文件名为"primary.prof”。
接着往下就是和执行Dex优化相关的,就是将相关的Dex指令转化成对应的机器指令。
在属性变量PRECOMPILE_LAYOUTS值为true,调用mViewCompiler.compileLayouts(pkg)。它是用来将布局资源文件转化成dex文件。生成的dex文件为 包的数据目录 + “/code_cache/compiled_view.dex”。包的数据目录和uuid、userId、ce标识相关,如果uuid为null,userId为0,ce标识存在,则生成的文件位置为"/data/user/0/" + packageName + “/code_cache/compiled_view.dex”。它是对应用的一种优化。
可以看到执行dexopt需要满足几个条件:不是instantApp,除非设置了Global.INSTANT_APP_DEXOPT_ENABLED对应的值不为0;包不是debuggable;不是在增量文件系统上。
接着,BackgroundDexOptService.notifyPackageChanged(packageName) 是从BackgroundDexOptService中将应用包从之前编译失败的名单中去除。
notifyPackageChangeObserversOnUpdate(reconciledPkg) 是通知注册在PackageManagerService对象成员mPackageChangeObservers集合中的每一个元素,调用它的onPackageChanged(event)方法。
最后waitForNativeBinariesExtraction(incrementalStorages) 是处理增量更新的。
总结
该阶段主要就是创建应用需要使用的目录,在更新应用安装情况下,会将代码缓存目录"code_cache"目录及其中文件清除。如果有dex元数据文件(.dm文件)会将它更新到应用的profile中去,如果满足dex优化条件,会执行Dexopt。
相关文章:
Android 安装应用-提交阶段之后剩下的操作
它的实现代码在executePostCommitSteps(commitRequest)中,看一下它的代码: /*** On successful install, executes remaining steps after commit completes and the package lock* is released. These are typically more expensive or require calls t…...
buuctf [ACTF2020 新生赛]Include
学习笔记。 开启靶机。 进入靶场: 我们跟进 tips瞅瞅: 额,纯小白,能想到的就是先F12看看,在CTRLu、以及抓包。 得,不会了,看wp呗,不会死磕没脑子0,0? 参考:…...
JS使用MutationObserver接口来监听DOM的更新
在JavaScript中,可以使用MutationObserver接口来监听DOM的更新。以下是一个使用MutationObserver的示例代码,它监听一个DOM节点的变化,并在变化发生时输出信息 // 选择目标节点 const targetNode document.getElementById(some-id);// 创建…...
图解C#高级教程(三):泛型
本讲用许多代码示例介绍了 C# 语言当中的泛型,主要包括泛型类、接口、结构、委托和方法。 文章目录 1. 为什么需要泛型?2. 泛型类的定义2.1 泛型类的定义2.2 使用泛型类创建变量和实例 3. 使用泛型类实现一个简单的栈3.1 类型参数的约束3.2 Where 子句3…...
240930_CycleGAN循环生成对抗网络
240930_CycleGAN循环生成对抗网络 CycleGAN,也算是笔者记录GAN生成对抗网络的第四篇,前三篇可以跳转 240925-GAN生成对抗网络-CSDN博客 240929-DCGAN生成漫画头像-CSDN博客 240929-CGAN条件生成对抗网络-CSDN博客 在第三篇中,我们采用了p…...
ide 使用技巧与插件推荐
ide 使用技巧与插件推荐 一、IDE 使用技巧 1. 快捷键 掌握常用快捷键: Windows: 使用 Ctrl、Alt 和 Shift 的组合。 Mac: 使用 Cmd、Option 和 Shift。 常用快捷键示例: VS Code: Ctrl P: 快速打开文件。 Ctrl Shift P: 打开命令面板。 Ctrl /…...
【node】 cnpm|npm查看、修改镜像地址操作 换源操作
【node】 cnpm|npm查看、修改镜像地址操作 换源操作 安装完node后 npm 1.查看当前npm信息 npm -v2.查看当前的镜像源 npm config get registry3.如果需要淘宝镜像源,修改当前的镜像源为淘宝镜像源 registry https://registry.npm.taobao.org弃用 npm config se…...
大数据-152 Apache Druid 集群模式 配置启动【下篇】 超详细!
点一下关注吧!!!非常感谢!!持续更新!!! 目前已经更新到了: Hadoop(已更完)HDFS(已更完)MapReduce(已更完&am…...
IDE 使用技巧与插件推荐全面指南
目录 目录 常用IDE概述 Visual Studio Visual Studio Code IntelliJ IDEA PyCharm Eclipse IDE 使用技巧 通用技巧 Visual Studio 专属技巧 Visual Studio Code 专属技巧 IntelliJ IDEA 专属技巧 插件推荐 Visual Studio 插件 Visual Studio Code 插件 IntelliJ…...
java-快速将普通main类变为javafx类,并加载自定义fxml
java-快速将普通main类变为javafx类,并加载自定义fxml 前提步骤1. 普通类继承Application2. 实现main方法3. 写一个controller4. 写一个fxml文件5. 写start方法加载fxml6. 具体代码7. 运行即可 前提 使用自带javafx的jdk,这里使用的是jdk1.834ÿ…...
数据结构之——单循环链表和双向循环链表
一、单循环链表的奥秘 单循环链表是一种特殊的链表结构,它在数据结构领域中具有重要的地位。其独特的循环特性使得它在某些特定的应用场景中表现出强大的优势。 (一)结构与初始化 单循环链表的结构由节点组成,每个节点包含数据域…...
Git Stash: 管理临时更改的利器
Git 是一个非常强大的版本控制系统,它不仅帮助我们管理代码的版本,还提供了许多实用的功能来优化我们的工作流程。今天,我们要介绍的是 Git 中的一个非常实用的功能——git stash。 什么是 Git Stash? 在开发过程中,…...
ELK--收集日志demo
ELK--收集日志demo 安装ELK日志收集配置启动容器springboot配置测试 之前项目多实例部署的时候,由于请求被负载到任意节点,所以查看日志是开多个终端窗口。后来做了简单处理,将同一项目的多实例日志存入同一个文件,由于存在文件锁…...
Redis的主要特点及运用场景
Redis的主要特点及运用场景 Redis(Remote Dictionary Server)是一个开源的高性能键值对(key-value)数据库。它支持多种类型的数据结构,如字符串(strings)、散列(hashes&…...
与我免费ai书童拆解《坚持》创作历程
插科打诨的海侃胡闹,调侃舒展《坚持》诗创的灵魂盛宴之旅。 (笔记模板由python脚本于2024年09月30日 19:11:42创建,本篇笔记适合喜欢python和诗歌的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网:https://www.python.org/ Free&#x…...
昇思MindSpore进阶教程--下沉模式
大家好,我是刘明,明志科技创始人,华为昇思MindSpore布道师。 技术上主攻前端开发、鸿蒙开发和AI算法研究。 努力为大家带来持续的技术分享,如果你也喜欢我的文章,就点个关注吧 正文开始 昇腾芯片集成了AICORE和AICPU等…...
Hive SQL业务场景:连续5天涨幅超过5%股票
一、需求描述 现有一张股票价格表 dwd_stock_trade_dtl 有3个字段分别是: 股票代码(stock_code), 日期(trade_date), 收盘价格(closing_price) 。 请找出满足连续5天以上(含)每天上涨超过5%的股票,并给出连续满足…...
Java 如何从图片上提取文字
生活中我们可能会遇到想从图片上直接复制上边的文字,该如何获取呢,接下来看看如何使用Java程序实现从图片中读取文字。 实现过程 1、引入Tess4J 依赖 <!--Tess4J 依赖--> <dependency><groupId>net.sourceforge.tess4j</groupId…...
C#进阶-读写Excel常用框架及其使用方式
目录 一、MiniExcel开源框架(推荐) 1、写/导出 方式一 方式二 多表创建 更改配置 特性使用 CSV尾行新增行 CSV、XLSX互转 2、读/导入 简单示例 二、NPOI开源框架 一、MiniExcel开源框架(推荐) 添加NuGet包MiniExcel…...
Python爬虫lxml模块安装导入和xpath基本语法
lxml模块是Python的一个解析库,主要用于解析HTML和XML文件。 一、安装导入 使用包管理器安装,在cmd下或编辑器下的控制台,运行: pip install lxml 导入: from lxml import etree 二、xpath基础知识 XPath&#…...
嵌入式软件架构设计:硬件抽象层实践
嵌入式软件架构设计:建立硬件抽象层的工程实践 1. 嵌入式软件架构概述 1.1 架构设计的必要性 在嵌入式系统开发中,软件架构设计直接影响产品的可维护性、可扩展性和可移植性。良好的架构设计能够: 减少不必要的返工 建立宏观层面的开发规…...
从IMU初始化到点云去畸变:深入Fast-LIO2的传感器融合核心流程
从IMU初始化到点云去畸变:Fast-LIO2传感器融合全流程解析 在自动驾驶和机器人定位领域,激光雷达与IMU的紧耦合系统正成为高精度状态估计的主流方案。Fast-LIO2作为这一技术路线的代表,其核心创新在于将IMU的动力学特性与激光点云几何特征深度…...
光纤布拉格光栅(FBG)笔记【2】:传感机制与布拉格波长调谐分析
1. 光纤布拉格光栅的传感机制揭秘 第一次接触光纤布拉格光栅(FBG)传感时,我完全被它"以光测万物"的能力震撼了。这根比头发还细的光纤,竟然能精准感知温度、应变等物理量的变化。经过多次实验验证,我发现它的核心秘密就藏在布拉格波…...
5分钟搞定局域网IP扫描:OpUtils保姆级配置教程(附常见问题排查)
5分钟搞定局域网IP扫描:OpUtils保姆级配置教程(附常见问题排查) 办公室里突然断网了?打印机死活连不上?新同事的电脑无法接入内网?作为中小企业IT运维人员,这些场景你一定不陌生。别急着打电话求…...
AI智能应用开发(Java)从起点到终点-面向对象
自定义对象Java中自定义对象的必要性就像我们之前用的Scanner 和Random 都是java里面已经写好的对象,直接拿来用就好了,不用再自己写一大串代码来实现键盘录入和随机数的需求,但是有些需求是java中没有定义和写好的,,但…...
告别树莓派溢价!Radxa ROCK 5A 8GB版开箱实测,652元真香体验与避坑指南
652元平替树莓派4B?Radxa ROCK 5A深度体验与实战避坑手册 当树莓派4B的价格突破900元大关时,许多开发者开始寻找更具性价比的替代方案。Radxa ROCK 5A的出现恰逢其时——这款搭载RK3588S芯片的单板计算机不仅性能翻倍,价格却仅为652元&#…...
目标检测新手必看:如何用Python手写IOU计算函数(附完整代码)
目标检测实战:从零编写Python版IOU计算函数 刚接触目标检测时,最让人困惑的莫过于那些神秘的评估指标。其中IOU(交并比)就像一把尺子,能量化算法预测框与真实框的贴合程度。但纸上得来终觉浅,今天我们就用P…...
别再死记硬背Sarsa公式了!用Python手搓一个‘胆小’的迷宫探索AI(附完整代码)
用Python打造胆小如鼠的迷宫AI:Sarsa算法实战图解 当你在迷宫中小心翼翼地贴着墙走,生怕掉进陷阱时——恭喜,你已经理解了Sarsa算法的核心思想。今天我们不谈枯燥的数学公式,而是用Python构建一个会"瑟瑟发抖"的迷宫探索…...
RT-Thread Nano 3.0.3移植STM32F103后,第一个实战:用FinSH组件实现串口命令行调试
RT-Thread Nano 3.0.3移植STM32F103实战:FinSH组件实现串口命令行调试 当你成功将RT-Thread Nano移植到STM32F103开发板后,第一个令人兴奋的里程碑就是让系统真正"活"起来——而FinSH组件正是实现这一目标的完美起点。这个内置的命令行交互工具…...
计算机毕业设计springboot校园文化社区视频网站 基于SpringBoot的校园文化交流短视频平台 SpringBoot框架下的高校文化分享与视频互动系统
计算机毕业设计springboot校园文化社区视频网站94nso9 (配套有源码 程序 mysql数据库 论文)本套源码可以先看具体功能演示视频领取,文末有联xi 可分享在"互联网校园"理念全面渗透的今天,视频已成为大学生记录生活、传播…...
