您的位置:首页 > 健康 > 养生 > 网络运维工程师简历怎么写_软件开发流程图教程_实时热点新闻_做市场推广应该掌握什么技巧

网络运维工程师简历怎么写_软件开发流程图教程_实时热点新闻_做市场推广应该掌握什么技巧

2024/12/22 23:34:02 来源:https://blog.csdn.net/weixin_44780781/article/details/144330561  浏览:    关键词:网络运维工程师简历怎么写_软件开发流程图教程_实时热点新闻_做市场推广应该掌握什么技巧
网络运维工程师简历怎么写_软件开发流程图教程_实时热点新闻_做市场推广应该掌握什么技巧

文章目录

  • 前言
  • 1. PMS 的初始化
    • 1.1 SystemServer 启动 PMS
    • 1.2 PMS 的入口方法 main
    • 1.3 PMS 构造函数
    • 1.4 扫描 APK 文件
    • 1.5 权限初始化
    • 1.6 提供对外服务
  • 2. APK 安装机制
    • 2.1. 安装请求的触发
    • 2.2 APK 文件解析与验证
    • 2.3 签名校验
    • 2.4 权限管理
      • 2.4.1 权限声明
      • 2.4.2 权限校验与分配
    • 2.5 持久化存储
    • 2.6 广播通知
  • 3. APK 解析流程
    • 3.1 APK 文件读取
    • 3.2 APK 校验
      • 3.2.1 签名校验
      • 3.2.2 APK 格式校验
      • 3.2.3 权限检查
      • 3.2.4 其他格式校验
    • 3.3 安装信息持久化
  • 4. Intent 和组件管理
    • 4.1 Intent 的作用
    • 4.2 组件的管理
      • 源码解析
          • resolveIntent() 方法
          • queryIntentActivities() 方法
  • 5. 卸载流程
    • 5.1 卸载请求的触发
    • 5.2 PackageManagerService 接收到卸载请求
  • 5.3 停用应用
    • 5.4 删除应用数据
    • 5.5 更新系统数据库
    • 5.6 广播通知
    • 5.7 删除 APK 文件
    • 5.8 更新 UI
  • 6. 持久化机制
    • 6.1 持久化数据存储位置
    • 6.2 数据存储格式
    • 6.3 持久化流程
      • 6.3.1 应用安装时持久化
      • 6.3.2 应用卸载时持久化
      • 6.3.3 应用更新时持久化
    • 主要类
  • 总结


前言

在 Android 系统中,PackageManagerService(简称 PMS)是负责管理应用程序的核心服务。无论是应用安装、卸载,还是权限分配,PMS 都扮演着至关重要的角色。
本篇文章将带你深入探讨 PMS 的幕后机制,特别是 APK 安装与解析的详细流程。


1. PMS 的初始化

步骤完成任务影响范围
启动 PMS 服务注册 PMS 到 ServiceManager,成为系统管理的核心服务。提供应用管理能力,供系统其他组件调用。
初始化组件构建数据结构、组件解析器,启动后台线程。提供运行时支持,准备后续任务。
加载持久化数据恢复设备重启前的已安装应用信息。确保已安装应用在系统重启后仍被识别和管理。
扫描并解析 APK扫描系统和用户目录,解析 APK 元数据,并注册到内存。让系统能够识别和管理设备上的所有 APK。
初始化权限系统加载默认权限配置文件,为系统应用分配权限。保障系统安全,防止权限滥用。
提供对外接口通过 API 提供安装、卸载、查询等功能,供系统和开发者调用。提供应用安装和运行管理能力。

1.1 SystemServer 启动 PMS

源码路径:
frameworks/base/services/java/com/android/server/SystemServer.java

PMS 是 Android 启动服务的关键部分,在 startOtherServices() 方法中初始化:

private void startOtherServices() {PackageManagerService pms = PackageManagerService.main(mSystemContext);ServiceManager.addService("package", pms);
}
  • 主要工作:
    1、调用 PackageManagerService.main() 方法,启动 PMS。
    2、注册 PMS 服务到 ServiceManager,供系统其他服务访问。

1.2 PMS 的入口方法 main

代码路径: frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public static PackageManagerService main(Context context) {Installer installer = new Installer();return new PackageManagerService(context, installer, ...);
}
  • 主要工作:
    创建 Installer 实例,用于管理 APK 文件的安装和删除。
    构造 PackageManagerService 对象。

1.3 PMS 构造函数

代码路径: frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public PackageManagerService(Context context, Installer installer, ...) {mContext = context;mInstaller = installer;// 初始化数据结构mPackages = new ArrayMap<>();mComponentResolver = new ComponentResolver();// 创建并启动后台线程mBackgroundThread = BackgroundThread.get();mHandler = new PackageHandler(mBackgroundThread.getLooper());// 初始化权限管理服务mPermissionManager = new PermissionManagerService(context, ...);// 恢复持久化存储的数据mSettings = new Settings(...);mSettings.readPackageRestrictionsLPr();// 启动扫描逻辑scanPackages();
}

初始化内容:

  • 核心数据结构:
    mPackages: 存储已安装包的信息。
    mComponentResolver: 解析组件(Activity、Service 等)依赖关系。
  • 后台线程:
    创建 BackgroundThread 处理异步任务,如 APK 扫描和安装。
  • 权限管理:
    初始化 PermissionManagerService 管理动态权限和默认权限。
  • 持久化存储:
    从 packages.xml 和 packages.list 加载已安装应用的状态。
  • 启动扫描:
    调用 scanPackages(),扫描系统目录和用户目录。

1.4 扫描 APK 文件

代码路径: frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

private void scanPackages() {scanDirLI(new File("/system/app"), ...); // 扫描系统目录scanDirLI(new File("/data/app"), ...);  // 扫描用户目录
}private void scanDirLI(File dir, ...) {File[] files = dir.listFiles();for (File file : files) {if (file.isFile() && file.getName().endsWith(".apk")) {try {// 解析 APKPackageParser.Package pkg = parsePackage(file);// 注册包信息scanPackageLI(pkg, ...);} catch (PackageParserException e) {Slog.e(TAG, "Failed to parse package: " + file, e);}}}
}

解析逻辑:

  • 调用 PackageParser 解析 APK 的 AndroidManifest.xml。
  • 验证签名、权限、依赖等信息。
  • 将解析后的包注册到内存数据结构。

1.5 权限初始化

代码路径: frameworks/base/services/core/java/com/android/server/pm/PermissionManagerService.java

public void initializeDefaultPermissions() {// 加载默认权限配置loadDefaultPermissions();for (String permission : defaultPermissions) {grantPermission(permission);}
}

主要工作:

  • 加载 /etc/permissions 目录下的权限定义文件。
  • 为系统应用自动授予默认权限。

1.6 提供对外服务

代码路径: frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

注册到 ServiceManager 后,PMS 提供以下对外服务:

1、获取已安装应用列表:

public List<PackageInfo> getInstalledPackages() {...}

2、安装应用:

public void installPackage(String packageName, ...) {...}

3、卸载应用:

public void deletePackage(String packageName, ...) {...}

2. APK 安装机制

2.1. 安装请求的触发

入口:

  1. 命令行触发:通过 ADB 命令安装 APK
  2. 系统触发:例如应用商店或系统应用发起安装请求。

核心代码路径:
PackageManagerService 类:
方法: installPackageAsUser()
路径: frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
功能:接收安装请求,校验请求来源并创建安装任务。

public void installPackageAsUser(String originPath, IPackageInstallObserver2 observer, int installFlags, int userId) {...// 校验权限,检查安装来源合法性// 创建安装任务,提交到后台处理
}

2.2 APK 文件解析与验证

在接收到安装请求后,PMS 通过 PackageParser 类解析 APK 文件,提取其元数据并进行签名校验。

PackageManagerService 调用 PackageParser 来解析 APK 文件,并将解析得到的包信息传递给后续处理模块。

关键类
PackageParser:
路径: frameworks/base/core/java/android/content/pm/PackageParser.java
方法: parsePackage()
功能: 解析 APK 文件中的 AndroidManifest.xml,提取包名、版本、权限等信息,并封装到 Package 对象中。

public static Package parsePackage(File apkFile, int flags) throws PackageParserException {...// 解析 APK 的 manifest 文件,获取包信息return new Package(pkgName);
}

2.3 签名校验

PackageManagerService 需要确保新安装的 APK 是合法的,尤其是对于系统应用或需要特定权限的应用,签名校验是一个关键步骤。PackageUtils 提供了签名校验的功能。

在解析 APK 后,PackageManagerService 会调用 PackageUtils.compareSignatures() 方法,校验安装包的签名

关键类:
PackageUtils:
源码路径
frameworks/base/core/java/android/content/pm/PackageUtils.java
入口:PackageUtils(compareSignatures() 方法)
作用:校验 APK 签名,确保其合法性。

public boolean compareSignatures(Signature[] newSig, Signature[] oldSig) {return SignatureUtils.areSignaturesMatching(newSig, oldSig); // 校验签名是否匹配
}

2.4 权限管理

2.4.1 权限声明

在 AndroidManifest.xml 文件中,应用声明所需的权限,例如 INTERNET、CAMERA 等。这些权限会在应用安装时进行解析。
示例:

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.CAMERA"/>

2.4.2 权限校验与分配

  • 在应用安装时,PackageManagerService 会调用 grantPermissions() 方法来根据 AndroidManifest.xml 中声明的权限,为应用授予相应的权限。
  • 对于 危险权限,Android 会在运行时请求用户授权(在应用首次访问权限时)。

关键类:
PackageManagerService:
源码路径
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
入口:PackageManagerService(grantPermissions() 方法)
作用:分配权限,确保安装的应用可以正常使用系统资源。

public void grantPermissions(Package pkg) {if (pkg != null) {for (Permission perm : pkg.permissions) {grantPermission(perm); // 授予应用声明的权限}}
}

2.5 持久化存储

在 APK 安装过程中,系统需要将应用的相关信息持久化存储,以确保在系统重启后仍然能访问到应用信息,并且保证应用的权限和其他元数据不会丢失。

  1. 安装包信息存储
    在应用安装时,PackageManagerService 会将应用的信息(如包名、版本、权限等)写入系统的持久化存储中。这个过程通常通过 writePackagesLocked() 方法完成。

  2. 系统数据更新
    系统维护一个应用数据库,存储有关已安装应用的所有信息(包括应用包名、路径、签名、权限等)。当应用安装或卸载时,PackageManagerService 会更新这些数据,确保系统的一致性。

关键类:
PackageManagerService:
源码路径
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
入口:PackageManagerService(writePackagesLocked() 方法)
作用:将已安装的包信息存储在系统持久化存储中,确保系统重启后信息不会丢失。

public void writePackagesLocked() {...writePackageListLPr(); // 将包信息写入存储
}

2.6 广播通知

在 APK 安装过程中,系统需要向其他组件(如 Launcher、系统 UI 等)广播应用安装成功的消息。这使得其他系统服务能够及时获知应用安装并进行相应操作,如更新图标或设置默认应用等。

关键类:
PackageManagerService:
源码路径
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
入口:PackageManagerService(sendPackageAddedBroadcast() 方法)
作用:安装完成后,发送广播通知系统其他组件应用安装成功。

public void sendPackageAddedBroadcast(String packageName, boolean replacing) {Intent intent = new Intent(Intent.ACTION_PACKAGE_ADDED);intent.setData(Uri.parse("package:" + packageName));sendBroadcast(intent); // 发送广播
}

3. APK 解析流程

3.1 APK 文件读取

APK 文件通常是一个 .apk 格式的压缩包,里面包含了应用的所有资源、代码(DEX 文件)、清单文件(AndroidManifest.xml)、签名信息等。

  • 读取文件:系统首先需要通过文件路径或 URI 来读取 APK 文件。
    在 PackageManagerService 中,安装包的处理通常是通过 installPackage 或 installPackageWithExistingManifest 方法进行的。PackageManagerService 是处理与安装相关的主要服务。

源码路径:frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public void installPackage(final Uri packageUri, final IPackageInstallObserver2 observer,final int flags, final int userId) {// 调用 PackageParser 解析 APKPackageParser.Package pkg = parsePackage(packageUri);
}

通过 PackageParser 类的 parsePackage 方法解析 APK。

3.2 APK 校验

  1. 签名校验:
    ApkFile.getSignatures() 提取签名。
    checkSignatures() 方法校验签名是否有效。

  2. 格式校验:
    通过 ApkFile.contains() 检查 APK 文件结构是否完整。
    使用 validateFileStructure() 校验 AndroidManifest.xml 和 classes.dex 文件是否存在。

  3. 权限校验:
    PackageManagerService.resolvePermissions() 方法检查 AndroidManifest.xml 中声明的权限是否合法。

3.2.1 签名校验

在 Android 中,每个 APK 都必须进行签名校验,确保 APK 文件没有被篡改。签名校验是通过 PackageParser 类和 PackageManagerService 服务来进行的。

源码路径:frameworks/base/core/java/android/content/pm/PackageParser.java

在 PackageParser 中,parsePackage() 方法会解析 APK 文件并校验签名。签名校验的主要工作是通过 ApkFile 类来获取 APK 的签名,然后通过 checkSignatures() 方法校验签名的有效性。

public static Package parsePackage(File packageFile, int flags) throws PackageParser.PackageParserException {// 创建 ApkFile 对象,用于解析 APKApkFile apkFile = new ApkFile(packageFile);// 获取签名Signatures signatures = apkFile.getSignatures();// 校验签名checkSignatures(signatures);
}

ApkFile.getSignatures() 会从 APK 中提取签名数据。接下来通过 checkSignatures() 来验证签名。

checkSignatures() 方法
在 checkSignatures() 方法中,系统会验证签名是否为空或者无效,如果签名校验失败,APK 的安装会被终止。

private static void checkSignatures(Signatures signatures) {if (signatures == null || signatures.length == 0) {throw new PackageParser.PackageParserException("Missing signatures for package");}// 更多签名验证逻辑,比如签名一致性检查// 如果签名不匹配或无效,将会抛出异常
}

逻辑

  • 如果签名为空,抛出 PackageParserException 异常。
  • 如果签名无效或与系统要求不匹配,APK 安装会失败。

3.2.2 APK 格式校验

APK 文件需要遵循特定的结构:包含 AndroidManifest.xml 文件,至少一个 classes.dex 文件等。PackageParser 会在解析 APK 时进行格式校验,确保 APK 的结构完整且符合要求。

文件结构校验

源码路径:frameworks/base/core/java/android/content/pm/PackageParser.java

validateFileStructure() 方法负责检查 APK 文件的结构是否完整,特别是是否包含 AndroidManifest.xml 和 classes.dex 等必要文件。

private static void validateFileStructure(ApkFile apkFile) throws PackageParser.PackageParserException {// 检查是否包含 AndroidManifest.xml 文件if (!apkFile.contains("AndroidManifest.xml")) {throw new PackageParser.PackageParserException("Missing AndroidManifest.xml in APK");}// 检查是否包含 classes.dex 文件if (!apkFile.contains("classes.dex")) {throw new PackageParser.PackageParserException("Missing classes.dex in APK");}
}

逻辑:

  • 使用 apkFile.contains() 方法检查 AndroidManifest.xml 和 classes.dex 文件是否存在。
  • 如果缺少其中任何一个文件,抛出 PackageParserException 异常,终止安装。

3.2.3 权限检查

确认应用声明的权限是否符合系统要求

源码路径:frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

在安装过程中,PackageManagerService 会调用 resolvePermissions() 方法来检查应用所声明的权限。

public void resolvePermissions(Package pkg) {// 解析权限for (String perm : pkg.requestedPermissions) {// 检查权限是否合法if (!isPermissionValid(perm)) {throw new PackageManagerException("Invalid permission: " + perm);}}
}

逻辑

  • 遍历 AndroidManifest.xml 中声明的权限。
  • 调用 isPermissionValid() 方法检查权限是否合法。
  • 如果权限无效,抛出异常,安装被中止。

3.2.4 其他格式校验

除了签名和权限校验外,还会进行以下校验:
Manifest 校验:系统会检查 AndroidManifest.xml 文件的内容是否符合系统要求,例如检查包名是否重复,组件是否声明完整等。

PackageParser 中的 parseManifest() 方法负责解析 AndroidManifest.xml 文件并进行格式校验。

private static void parseManifest(File packageFile, Package pkg) throws PackageParser.PackageParserException {// 解析 AndroidManifest.xmltry {// 解析逻辑} catch (Exception e) {throw new PackageParser.PackageParserException("Manifest parsing failed: " + e.getMessage());}
}

哈希校验:为了确保文件没有被篡改,系统会对 classes.dex、资源文件等进行哈希校验。
校验 classes.dex 文件是否存在并有效。classes.dex 文件是应用的核心字节码文件,必须存在并符合格式。

3.3 安装信息持久化

APK 解析完成后,PackageManagerService 会将解析得到的信息持久化到系统数据库中,例如应用的包名、版本、权限等。

源码路径:frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

在 PackageManagerService 中,installPackage() 方法会将解析后的应用信息持久化。

public int installPackage(Package pkg) {// 保存应用信息savePackageToDatabase(pkg);// 其他安装过程
}

逻辑:
将 Package 对象保存到数据库中,确保应用信息能够在后续访问中使用。

4. Intent 和组件管理

Intent 和组件管理是系统的重要组成部分,负责管理和调度应用程序的各个组件(如 Activity、Service、BroadcastReceiver 和 ContentProvider)。Intent 作为通信的媒介,允许不同的组件之间进行交互和数据传递。PackageManagerService(PMS)是管理和调度这些组件的核心服务,负责根据 Intent 定位和启动对应的组件。

4.1 Intent 的作用

Intent 是 Android 中用于描述一个应用组件执行某个动作的对象。它不仅用于启动活动(Activity),服务(Service)和广播(BroadcastReceiver),还用于传递数据和指示操作。可以通过 Intent 向系统请求某些操作,例如启动另一个应用的组件、发送广播等。
Intent 主要有以下几种类型

显式 Intent:明确指定目标组件(如包名和类名)。通常用于在同一应用内启动组件。

隐式 Intent:没有指定具体的目标组件,而是通过指定操作(如 ACTION_VIEW)让系统根据 Intent 的内容查找合适的组件来响应。

4.2 组件的管理

在 Android 中,每个应用包含若干个组件(如 Activity、Service、BroadcastReceiver 和 ContentProvider)。PMS 负责管理这些组件,并根据 Intent 选择合适的组件进行调度。

组件管理的核心操作包括
注册组件:当应用安装或更新时,PMS 会解析应用的 AndroidManifest.xml 文件,获取应用的组件信息,并将其注册到系统中。
查找组件:当收到一个 Intent 时,PMS 会根据该 Intent 的操作、数据、类别等信息,在所有已安装的应用中查找能够响应该 Intent 的组件。
启动组件:当 PMS 找到匹配的组件时,它会启动相应的 Activity、Service 或 BroadcastReceiver。

源码解析

PackageManagerService(PMS)是管理和调度组件的核心服务。当通过 Intent 启动一个组件时,系统会首先通过 PMS 查找符合条件的组件,并通过 ActivityManagerService 启动对应的组件。以下是相关的关键代码和流程。

resolveIntent() 方法

路径: frameworks/base/core/java/android/content/pm/ResolveInfo.java

PackageManagerService 中的 resolveIntent() 方法负责根据 Intent 查找符合条件的组件。
public ResolveInfo resolveIntent(Intent intent, String resolvedType, int flags) {// 查找能够处理 Intent 的所有组件List<ResolveInfo> queryIntentActivities = queryIntentActivities(intent, resolvedType, flags);for (ResolveInfo resolveInfo : queryIntentActivities) {if (resolveInfo.activityInfo.packageName.equals("com.example.target")) {return resolveInfo;}}return null;
}

作用:该方法根据传入的 Intent,在已安装的应用中查找能够处理该 Intent 的 Activity。在返回的 ResolveInfo 中包含了与 Intent 匹配的组件信息。

参数
intent:目标 Intent 对象。
resolvedType:意图的类型。
flags:标记,用于决定匹配策略。

queryIntentActivities() 方法

路径frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
queryIntentActivities() 方法用于查找系统中能够响应指定 Intent 的所有组件,返回一个 ResolveInfo 列表。它主要会遍历系统中已安装应用的组件列表,找到符合条件的组件。

public List<ResolveInfo> queryIntentActivities(Intent intent, String resolvedType, int flags) {List<ResolveInfo> result = new ArrayList<>();// 遍历所有已安装的应用,寻找匹配的组件for (ApplicationInfo appInfo : mAppDirs) {List<ResolveInfo> appResult = queryIntentActivitiesForPackage(intent, appInfo.packageName, resolvedType, flags);result.addAll(appResult);}return result;
}

作用:查找所有能够响应给定 Intent 的 Activity,返回一个包含 ResolveInfo 对象的列表。
流程
遍历系统中所有已安装的应用。
对每个应用执行匹配检查,查看是否有 Activity 能够处理传入的 Intent。

Intent 启动组件的流程

当 Intent 发起组件调用时,PMS 负责解析和匹配相关组件,然后通过 ActivityManagerService 来启动对应的组件。具体流程如下:
1、用户或系统发起 Intent:一个 Intent 请求组件(如启动一个 Activity)。
2、PMS 解析 Intent:PackageManagerService 会调用 resolveIntent() 或 queryIntentActivities() 等方法,解析 Intent 并查找合适的组件。
3、返回匹配的组件:如果找到匹配的组件,PMS 会返回该组件的详细信息(如 ResolveInfo)。
4、ActivityManagerService 启动组件:ActivityManagerService 会通过 startActivity() 或 startService() 启动对应的组件。

权限和安全性管理

在进行组件管理时,系统还会进行权限校验,确保只有具有相应权限的应用才能启动某些组件。PackageManagerService 会根据 Intent 中的请求权限以及目标组件的权限声明进行权限检查,确保安全性。

5. 卸载流程

5.1 卸载请求的触发

卸载请求通常是由用户通过系统设置或者其他应用程序发起的。调用的 API 是 PackageManager.deletePackage()。

路径
frameworks/base/core/java/android/content/pm/PackageManager.java。这个方法是对外提供的卸载接口。

public int deletePackage(String packageName, IPackageDeleteObserver observer, int flags) {// 调用 PackageManagerService 的删除方法mPackageManagerService.deletePackage(packageName, observer, flags);
}

作用:

  • deletePackage() 方法接收包名、卸载观察者和标志位。该方法会通过 PackageManagerService 调用实际的卸载逻辑。
  • 会根据 flags 参数确定是否保留应用的数据或是强制卸载

5.2 PackageManagerService 接收到卸载请求

卸载请求被 PackageManagerService(PMS)接收后,首先会进行一系列的初步验证和检查。PMS 是处理所有包管理事务的核心组件。

路径:frameworks/base/core/java/android/content/pm/PackageManager.java

public void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) {// 权限检查enforceSystemOrRoot();// 获取要卸载的 PackageSetting 对象PackageSetting ps = mSettings.getPackageSetting(packageName);// 如果没有找到对应包名,则返回错误if (ps == null) {throw new IllegalArgumentException("Package " + packageName + " not found");}// 删除包裹的 APK 文件deletePackageFile(packageName);// 清除与该应用相关的数据deleteDataDirsLIL(packageName);// 更新系统数据库状态,移除包记录removePackageData(ps);// 发送卸载完成的广播sendPackageRemovedBroadcast(packageName);
}

卸载过程中,系统会检查是否有权限执行该操作。

路径:frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

private void enforceSystemOrRoot() {if (Binder.getCallingUid() != Process.SYSTEM_UID && Binder.getCallingUid() != Process.ROOT_UID) {throw new SecurityException("Permission Denial: cannot delete package");}
}

作用:
如果请求不是来自系统 UID 或 ROOT UID,则抛出 SecurityException,拒绝卸载请求。

作用
1、调用 enforceSystemOrRoot() 来检查请求是否来自系统或有适当权限的进程。
2、通过 mSettings.getPackageSetting(packageName) 获取与包名相关的设置对象。
3、删除包裹的 APK 文件和与该应用相关的数据。

5.3 停用应用

在卸载之前,需要停止正在运行的应用进程和服务,防止应用在卸载过程中仍然活动。

路径:frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public void forceStopPackage(String packageName) {// 终止正在运行的进程和服务mActivityManager.forceStopPackage(packageName);
}

作用:
停止与卸载应用相关的进程和服务,确保不会在卸载过程中影响系统。

5.4 删除应用数据

卸载时需要删除应用的数据文件,包括缓存、数据库等。

路径:frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

private void deleteDataDirsLIL(String packageName) {// 删除应用的私有数据目录File dataDir = new File("/data/data/" + packageName);if (dataDir.exists()) {FileUtils.deleteContents(dataDir);}// 删除缓存目录File cacheDir = new File("/data/cache/" + packageName);if (cacheDir.exists()) {FileUtils.deleteContents(cacheDir);}
}

5.5 更新系统数据库

卸载过程中,系统数据库(如包管理数据库)需要移除该应用的相关信息。

路径:frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

private void removePackageData(PackageSetting packageSetting) {// 从数据库中删除该应用相关信息mSettings.removePackage(packageSetting);// 更新数据库以确保删除记录mSettings.writeLPr();
}

作用
删除与该应用相关的所有系统记录,包括应用的权限、签名、路径等信息。
使用 mSettings.writeLPr() 方法将更新后的数据库写入磁盘。

5.6 广播通知

卸载完成后,系统需要广播卸载信息,通知其他应用或系统组件。

路径:frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

private void sendPackageRemovedBroadcast(String packageName) {// 发送卸载广播Intent intent = new Intent(Intent.ACTION_PACKAGE_REMOVED, Uri.parse("package:" + packageName));intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);mContext.sendBroadcast(intent);
}

作用:
向系统广播卸载事件,通知其他系统组件(如 Launcher、应用管理等)更新其状态。

5.7 删除 APK 文件

卸载过程中,系统会删除与应用相关的 APK 文件。

路径:frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

private void deletePackageFile(String packageName) {// 删除 APK 文件File apkFile = new File("/data/app/" + packageName);if (apkFile.exists()) {apkFile.delete();}
}

作用:
删除存储在 /data/app/ 或 /system/app/ 下的 APK 文件,释放存储空间。

5.8 更新 UI

卸载后,系统 UI(如 Launcher)需要更新,移除已卸载应用的图标。

路径:frameworks/base/core/java/android/app/ActivityManager.java

public void removePackageFromLauncher(String packageName) {// 从 Launcher 中移除应用图标Intent intent = new Intent(Intent.ACTION_PACKAGE_REMOVED, Uri.parse("package:" + packageName));mContext.sendBroadcast(intent);
}

作用:
通知 Launcher 更新其 UI,删除已卸载应用的图标。

6. 持久化机制

为了保持应用程序数据的一致性和持久化,PMS 需要使用持久化机制来存储和管理已安装应用的相关信息

6.1 持久化数据存储位置

PMS 主要通过 PackageManagerService 内部的 Settings 对象来管理应用的持久化数据。Settings 类封装了应用安装和卸载所需的所有信息,并提供了将这些信息持久化到磁盘的能力。具体来说,持久化的应用信息存储在系统的数据库文件中,通常位于 /data/system/ 目录下。

6.2 数据存储格式

PMS 使用的是基于 XML 文件的数据存储格式,所有关于已安装应用的信息(如包名、路径、权限等)都被保存在一个 XML 文件中。这个 XML 文件被称为 packages.xml,它包含了所有已安装应用的元数据。

路径:/data/system/packages.xml
该文件存储着系统中所有安装应用的配置,包括每个应用的包名、路径、安装时间、签名、权限等。

6.3 持久化流程

6.3.1 应用安装时持久化

当新应用被安装时,PMS 会更新 packages.xml 文件,新增该应用的相关信息。安装时,PMS 会将应用的包名、路径、签名等信息存储在该文件中,确保这些信息可以在系统重启后依然存在。

路径:frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

private void addPackageSetting(PackageSetting ps) {// 将 PackageSetting 对象持久化到 Settings 数据中mSettings.addPackageSetting(ps);// 更新 packages.xml 文件mSettings.writeLPr();
}

作用:
addPackageSetting() 方法将新安装应用的 PackageSetting 对象添加到 Settings 数据中,并调用 mSettings.writeLPr() 更新 packages.xml 文件。

6.3.2 应用卸载时持久化

当应用被卸载时,PMS 会从 packages.xml 文件中删除该应用的记录,并更新文件。

路径:frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

private void removePackageData(PackageSetting ps) {// 从 settings 数据中移除应用的记录mSettings.removePackage(ps);// 更新 packages.xml 文件mSettings.writeLPr();
}

作用:
removePackageData() 方法会删除卸载应用的所有记录,并通过 mSettings.writeLPr() 更新 packages.xml 文件,确保卸载后的数据一致性。

6.3.3 应用更新时持久化

当应用更新时,PMS 会修改原有记录并更新 packages.xml 文件,以反映应用的新状态(如新版本号、安装路径等)。

路径:frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

private void updatePackageSetting(PackageSetting oldPs, PackageSetting newPs) {// 更新旧的 PackageSetting 记录为新的记录mSettings.replacePackageSetting(oldPs, newPs);// 更新 packages.xml 文件mSettings.writeLPr();
}

作用:
updatePackageSetting() 方法用于更新应用的持久化数据,确保新版本的应用信息被正确保存,并通过 mSettings.writeLPr() 更新 packages.xml 文件。

主要类


Settings 类的作用
Settings 类会将应用的配置信息存储为一系列 PackageSetting 对象。

路径:frameworks/base/services/core/java/com/android/server/pm/Settings.java

public class Settings {private final File mPackagesFile;private Map<String, PackageSetting> mPackages = new HashMap<>();public void readLPr() {// 读取 packages.xml 文件并解析成 Map 数据FileInputStream fis = null;try {fis = new FileInputStream(mPackagesFile);// 解析 XML 文件,将数据加载到 mPackages 中XmlUtils.readMapXml(fis, mPackages);} catch (IOException e) {Slog.e(TAG, "Error reading packages.xml", e);} finally {IoUtils.closeQuietly(fis);}}public void writeLPr() {// 将 mPackages 中的数据写入 packages.xml 文件FileOutputStream fos = null;try {fos = new FileOutputStream(mPackagesFile);// 将 Map 数据以 XML 格式写入文件XmlUtils.writeMapXml(fos, mPackages);} catch (IOException e) {Slog.e(TAG, "Error writing packages.xml", e);} finally {IoUtils.closeQuietly(fos);}}public void addPackageSetting(PackageSetting ps) {mPackages.put(ps.name, ps);}public void removePackage(PackageSetting ps) {mPackages.remove(ps.name);}
}

作用:
readLPr():从 packages.xml 文件读取数据并解析为 mPackages 映射。
writeLPr():将 mPackages 中的数据写入到 packages.xml 文件。
addPackageSetting():将一个 PackageSetting 对象添加到 mPackages 中,表示添加一个新的应用。
removePackage():从 mPackages 中删除一个 PackageSetting 对象,表示卸载一个应用。


PackageSetting 类的作用
PackageSetting 类表示一个应用程序的持久化数据。它包含了应用的各种元信息,如包名、签名、权限、安装路径、版本号等。

路径:frameworks/base/services/core/java/com/android/server/pm/PackageSetting.java

public class PackageSetting {public String name;public String codePath;public String resourcePath;public String dataDir;public int versionCode;public String[] signatures;public boolean isSystemApp;
}

作用
PackageSetting 用于存储每个应用的核心信息,包含应用的路径、签名、版本号、系统应用标识等。
它是 Settings 类和 PackageManagerService 中用于持久化存储和管理应用元数据的主要对象。

总结

这篇文章的内容概述了 Android 系统中包管理服务(PMS)的工作原理,涉及从应用安装到卸载以及相关的持久化机制。以下是各章节的总结:

1、PMS 的初始化:

  • 介绍了系统启动时,SystemServer 启动 PMS 的过程,并通过 main 方法初始化 PMS。
  • PMS 构造函数负责初始化必要的资源,并扫描 APK 文件以便安装。
  • 权限初始化过程和对外服务的提供是 PMS 的重要功能。

2、APK 安装机制:
描述了安装请求的触发、APK 文件的解析和验证过程,包括签名校验和权限管理。
权限声明与校验、持久化存储和广播通知等过程确保 APK 安全和正确安装。

3、APK 解析流程:
介绍了 APK 文件的读取、校验、权限检查等细节。
通过签名校验、格式校验等多项验证确保 APK 的有效性,并将安装信息持久化。

4、Intent 和组件管理:
讲解了 Intent 的作用以及如何通过 resolveIntent() 和 queryIntentActivities() 方法进行组件管理,确保应用间的通信和组件调用正确。

5、卸载流程:
描述了卸载请求的触发和处理过程,包括停用应用、删除数据、更新系统数据库、广播通知等步骤。
最终删除 APK 文件并更新 UI。

6、持久化机制:
讨论了持久化数据存储的位置、格式以及持久化流程。
重点描述了在应用安装、卸载和更新时的数据存储和管理方式。

总的来说,文章从 PMS 初始化到 APK 安装、解析、卸载及持久化机制,详细介绍了 Android 系统中包管理服务的运作流程。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com