当前位置: 首页 > news >正文

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)中&#xff0c;看一下它的代码&#xff1a; /*** 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

学习笔记。 开启靶机。 进入靶场&#xff1a; 我们跟进 tips瞅瞅&#xff1a; 额&#xff0c;纯小白&#xff0c;能想到的就是先F12看看&#xff0c;在CTRLu、以及抓包。 得&#xff0c;不会了&#xff0c;看wp呗&#xff0c;不会死磕没脑子0,0&#xff1f; 参考&#xff1a;…...

JS使用MutationObserver接口来监听DOM的更新

在JavaScript中&#xff0c;可以使用MutationObserver接口来监听DOM的更新。以下是一个使用MutationObserver的示例代码&#xff0c;它监听一个DOM节点的变化&#xff0c;并在变化发生时输出信息 // 选择目标节点 const targetNode document.getElementById(some-id);// 创建…...

图解C#高级教程(三):泛型

本讲用许多代码示例介绍了 C# 语言当中的泛型&#xff0c;主要包括泛型类、接口、结构、委托和方法。 文章目录 1. 为什么需要泛型&#xff1f;2. 泛型类的定义2.1 泛型类的定义2.2 使用泛型类创建变量和实例 3. 使用泛型类实现一个简单的栈3.1 类型参数的约束3.2 Where 子句3…...

240930_CycleGAN循环生成对抗网络

240930_CycleGAN循环生成对抗网络 CycleGAN&#xff0c;也算是笔者记录GAN生成对抗网络的第四篇&#xff0c;前三篇可以跳转 240925-GAN生成对抗网络-CSDN博客 240929-DCGAN生成漫画头像-CSDN博客 240929-CGAN条件生成对抗网络-CSDN博客 在第三篇中&#xff0c;我们采用了p…...

ide 使用技巧与插件推荐

ide 使用技巧与插件推荐 一、IDE 使用技巧 1. 快捷键 掌握常用快捷键&#xff1a; Windows: 使用 Ctrl、Alt 和 Shift 的组合。 Mac: 使用 Cmd、Option 和 Shift。 常用快捷键示例&#xff1a; VS Code: Ctrl P: 快速打开文件。 Ctrl Shift P: 打开命令面板。 Ctrl /…...

【node】 cnpm|npm查看、修改镜像地址操作 换源操作

【node】 cnpm|npm查看、修改镜像地址操作 换源操作 安装完node后 npm 1.查看当前npm信息 npm -v2.查看当前的镜像源 npm config get registry3.如果需要淘宝镜像源&#xff0c;修改当前的镜像源为淘宝镜像源 registry https://registry.npm.taobao.org弃用 npm config se…...

大数据-152 Apache Druid 集群模式 配置启动【下篇】 超详细!

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&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类&#xff0c;并加载自定义fxml 前提步骤1. 普通类继承Application2. 实现main方法3. 写一个controller4. 写一个fxml文件5. 写start方法加载fxml6. 具体代码7. 运行即可 前提 使用自带javafx的jdk&#xff0c;这里使用的是jdk1.834&#xff…...

数据结构之——单循环链表和双向循环链表

一、单循环链表的奥秘 单循环链表是一种特殊的链表结构&#xff0c;它在数据结构领域中具有重要的地位。其独特的循环特性使得它在某些特定的应用场景中表现出强大的优势。 &#xff08;一&#xff09;结构与初始化 单循环链表的结构由节点组成&#xff0c;每个节点包含数据域…...

Git Stash: 管理临时更改的利器

Git 是一个非常强大的版本控制系统&#xff0c;它不仅帮助我们管理代码的版本&#xff0c;还提供了许多实用的功能来优化我们的工作流程。今天&#xff0c;我们要介绍的是 Git 中的一个非常实用的功能——git stash。 什么是 Git Stash&#xff1f; 在开发过程中&#xff0c;…...

ELK--收集日志demo

ELK--收集日志demo 安装ELK日志收集配置启动容器springboot配置测试 之前项目多实例部署的时候&#xff0c;由于请求被负载到任意节点&#xff0c;所以查看日志是开多个终端窗口。后来做了简单处理&#xff0c;将同一项目的多实例日志存入同一个文件&#xff0c;由于存在文件锁…...

Redis的主要特点及运用场景

Redis的主要特点及运用场景 Redis&#xff08;Remote Dictionary Server&#xff09;是一个开源的高性能键值对&#xff08;key-value&#xff09;数据库。它支持多种类型的数据结构&#xff0c;如字符串&#xff08;strings&#xff09;、散列&#xff08;hashes&…...

与我免费ai书童拆解《坚持》创作历程

插科打诨的海侃胡闹&#xff0c;调侃舒展《坚持》诗创的灵魂盛宴之旅。 (笔记模板由python脚本于2024年09月30日 19:11:42创建&#xff0c;本篇笔记适合喜欢python和诗歌的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Free&#x…...

昇思MindSpore进阶教程--下沉模式

大家好&#xff0c;我是刘明&#xff0c;明志科技创始人&#xff0c;华为昇思MindSpore布道师。 技术上主攻前端开发、鸿蒙开发和AI算法研究。 努力为大家带来持续的技术分享&#xff0c;如果你也喜欢我的文章&#xff0c;就点个关注吧 正文开始 昇腾芯片集成了AICORE和AICPU等…...

Hive SQL业务场景:连续5天涨幅超过5%股票

一、需求描述 现有一张股票价格表 dwd_stock_trade_dtl 有3个字段分别是&#xff1a; 股票代码(stock_code), 日期(trade_date)&#xff0c; 收盘价格(closing_price) 。 请找出满足连续5天以上&#xff08;含&#xff09;每天上涨超过5%的股票&#xff0c;并给出连续满足…...

Java 如何从图片上提取文字

生活中我们可能会遇到想从图片上直接复制上边的文字&#xff0c;该如何获取呢&#xff0c;接下来看看如何使用Java程序实现从图片中读取文字。 实现过程 1、引入Tess4J 依赖 <!--Tess4J 依赖--> <dependency><groupId>net.sourceforge.tess4j</groupId…...

C#进阶-读写Excel常用框架及其使用方式

目录 一、MiniExcel开源框架&#xff08;推荐&#xff09; 1、写/导出 方式一 方式二 多表创建 更改配置 特性使用 CSV尾行新增行 CSV、XLSX互转 2、读/导入 简单示例 二、NPOI开源框架 一、MiniExcel开源框架&#xff08;推荐&#xff09; 添加NuGet包MiniExcel…...

Python爬虫lxml模块安装导入和xpath基本语法

lxml模块是Python的一个解析库&#xff0c;主要用于解析HTML和XML文件。 一、安装导入 使用包管理器安装&#xff0c;在cmd下或编辑器下的控制台&#xff0c;运行&#xff1a; pip install lxml 导入&#xff1a; from lxml import etree 二、xpath基础知识 XPath&#…...

网络编程(Modbus进阶)

思维导图 Modbus RTU&#xff08;先学一点理论&#xff09; 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议&#xff0c;由 Modicon 公司&#xff08;现施耐德电气&#xff09;于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案

JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停​​ 1. ​​安全点(Safepoint)阻塞​​ ​​现象​​:JVM暂停但无GC日志,日志显示No GCs detected。​​原因​​:JVM等待所有线程进入安全点(如…...

优选算法第十二讲:队列 + 宽搜 优先级队列

优选算法第十二讲&#xff1a;队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)

前言&#xff1a; 最近在做行为检测相关的模型&#xff0c;用的是时空图卷积网络&#xff08;STGCN&#xff09;&#xff0c;但原有kinetic-400数据集数据质量较低&#xff0c;需要进行细粒度的标注&#xff0c;同时粗略搜了下已有开源工具基本都集中于图像分割这块&#xff0c…...

Redis:现代应用开发的高效内存数据存储利器

一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发&#xff0c;其初衷是为了满足他自己的一个项目需求&#xff0c;即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源&#xff0c;Redis凭借其简单易用、…...

Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换

目录 关键点 技术实现1 技术实现2 摘要&#xff1a; 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式&#xff08;自动驾驶、人工驾驶、远程驾驶、主动安全&#xff09;&#xff0c;并通过实时消息推送更新车…...

系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文通过代码驱动的方式&#xff0c;系统讲解PyTorch核心概念和实战技巧&#xff0c;涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...

tauri项目,如何在rust端读取电脑环境变量

如果想在前端通过调用来获取环境变量的值&#xff0c;可以通过标准的依赖&#xff1a; std::env::var(name).ok() 想在前端通过调用来获取&#xff0c;可以写一个command函数&#xff1a; #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...

Ubuntu系统多网卡多相机IP设置方法

目录 1、硬件情况 2、如何设置网卡和相机IP 2.1 万兆网卡连接交换机&#xff0c;交换机再连相机 2.1.1 网卡设置 2.1.2 相机设置 2.3 万兆网卡直连相机 1、硬件情况 2个网卡n个相机 电脑系统信息&#xff0c;系统版本&#xff1a;Ubuntu22.04.5 LTS&#xff1b;内核版本…...