Android应用管理一 -- APK包的安装、卸载和优化(PackageManagerService)

Android应用管理主要由PackageManagerService完成,包括安装、卸载、优化和查询APK包。系统启动时,PackageManagerService扫描APK和Jar文件,将信息存入内存,并进行必要的优化。它提供查询、安装和卸载服务,管理system和普通应用。系统应用不能直接删除,但可以通过安装高版本覆盖。PackageManagerService涉及包的解析、权限管理、数据存储等多个方面,安装流程包括文件解析、签名验证、数据目录创建等步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Android的应用管理主要是通过PackageManagerService来完成的。PackageManagerService服务负责各种APK包的安装、卸载、优化和查询。

PackageManagerService在启动时会扫描所有的APK文件和Jar包,然后把他们的信息读取出来,保存在内存中,这样系统在运行时就能迅速找到各种应用和组件的信息。扫描过程中如果遇到没有优化的文件,还要执行转换工作,将app文件从dex格式转换为oat格式(Android5.0之前是转换为odex格式)。

启动后,PackageManagerService将提供安装包的信息查询服务以及应用的安装和卸载服务。Android5.x,/data/app目录或者/system/app目录下存放的是以应用名称命名的目录,在这个目录下存放的是apk文件和一个lib目录,lib目录存放的是应用的so文件。

Android中的应用可以简单的分为两大类:系统应用和普通应用。

系统应用是指位于/system/app或者/system/priv-app目录下的应用。priv-app目录中存放的是一些系统底层应用,如setting,systemui等。/system/app存放的则是系统级的应用,如Phone、Contacts等。在PackageManagerService中,所有的system应用包括这两个目录下的应用,而所谓的private应用特指priv-app目录下的应用。

普通应用:用户安装的应用,位于目录/data/app下。普通应用还可以安装在SD卡上,系统应用不可以。

通常情况下,系统应用是不能删除的,但是可以升级。升级的方法是安装一个包名相同,但是具有更高版本号的应用在/data/app目录下。对于系统中的这种升级情况,Android会在/data/system/packages.xml文件中用标签<update-package>记录被覆盖的系统应用的信息。如果在升级过程中,如果出现与原始包名不同的应用,最后会改成原始包名,Android会在packages.xml文件中用标签<rename-package>记录这种改名的情况。

系统目录/data/dalvik-cache下保存的是大部分的apk文件和jar包的odex版本。odex是一种优化过的格式,执行速度比apk文件的dex格式更快。

每个应用都有保存数据的目录,位于/data/data/<包名>/目录下。其中数据目录下常见的两个子目录:shared_prefs目录中保存的是应用的设置文件,database保存的是应用的数据库文件。

一、了解PackageManagerService

在应用中如果使用PackageManagerService服务,通常调用的是Context的getPackageManager()方法,这个方法返回的是PackageManager对象,注意Context是一个抽象类,ContextImpl类继承了Context,方法如下:

    @Override
    public PackageManager getPackageManager() {
        if (mPackageManager != null) {
            return mPackageManager;
        }

        IPackageManager pm = ActivityThread.getPackageManager();
        if (pm != null) {
            // Doesn't matter if we make more than one instance.
            return (mPackageManager = new ApplicationPackageManager(this, pm));
        }

        return null;
    }

从getPackageManager()方法的代码中可以看到它返回的PackageManager对象实际上是一个ApplicationPackageManager对象,这个对象创建时使用了IPackageManager对象作为参数。IPackageManager对象是一个PackageManagerService的引用对象。因此,ApplicationPackageManager对象就是PackageManagerService的代理对象。ApplicationPackageManager类继承自PackageManager类。PackageManager类中定义了应用可以操作PackageManagerService的接口。ActivityThread类的getPackageManager()方法代码如下:

    public static IPackageManager getPackageManager() {
        if (sPackageManager != null) {
            //Slog.v("PackageManager", "returning cur default = " + sPackageManager);
            return sPackageManager;
        }
        IBinder b = ServiceManager.getService("package");
        //Slog.v("PackageManager", "default service binder = " + b);
        sPackageManager = IPackageManager.Stub.asInterface(b);
        //Slog.v("PackageManager", "default service = " + sPackageManager);
        return sPackageManager;
    }

PackageManagerService的两个重要成员变量mInstallerService和mInstller与应用安装有密切关系。mInstallerService是类PackageInstallerService的实例对象,一个应用的安装过程比较长,Android5.0中新增加了PackageInstallerService来管理应用的安装过程。另一个成员变量mInstaller是类Installer的实例对象,它也有一个名为mInstaller的成员变量,其类型是InstallerConnection,而InstallerConnection中存在着和Deamon进程Installd通信的Socket命令通道。实际上系统中进行apk文件格式转换、建立数据目录等工作最后都是由installd进程来完成的。这些对象之间的关系如下图所示。

1、理解packages.xml和Settings类

这里先看一下Settings这个类,这个类用来保存和PackageManagerService相关的一些设置,它所保存的内容在解析应用时会用到。那么Settings中保存的值是从哪里来的?作用又是什么呢?我们先看一下Settings的构造方法,代码如下:

    Settings(Context context) {
        this(context, Environment.getDataDirectory());//获取用户数据目录:/data
    }

    Settings(Context context, File dataDir) {
        mSystemDir = new File(dataDir, "system");
        mSystemDir.mkdirs();//在data目录下创建system目录:/data/system
        FileUtils.setPermissions(mSystemDir.toString(),
                FileUtils.S_IRWXU|FileUtils.S_IRWXG
                |FileUtils.S_IROTH|FileUtils.S_IXOTH,
                -1, -1);//设置目录的属性为0775
        mSettingsFilename = new File(mSystemDir, "packages.xml");//data/system/packages.xml
        mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");
        mPackageListFilename = new File(mSystemDir, "packages.list");
        FileUtils.setPermissions(mPackageListFilename, 0640, SYSTEM_UID, PACKAGE_INFO_GID);

        // Deprecated: Needed for migration
        mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
        mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
    }

如下是Android N 的构造方法:

    Settings(File dataDir, Object lock) {
        mLock = lock;

        mRuntimePermissionsPersistence = new RuntimePermissionPersistence(mLock);

        mSystemDir = new File(dataDir, "system");
        mSystemDir.mkdirs();
        FileUtils.setPermissions(mSystemDir.toString(),
                FileUtils.S_IRWXU|FileUtils.S_IRWXG
                |FileUtils.S_IROTH|FileUtils.S_IXOTH,
                -1, -1);
        mSettingsFilename = new File(mSystemDir, "packages.xml");
        mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");
        mPackageListFilename = new File(mSystemDir, "packages.list");
        FileUtils.setPermissions(mPackageListFilename, 0640, SYSTEM_UID, PACKAGE_INFO_GID);

        final File kernelDir = new File("/config/sdcardfs");
        mKernelMappingFilename = kernelDir.exists() ? kernelDir : null;

        // Deprecated: Needed for migration
        mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
        mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
    }
Settings的构造方法会创建data目录下的system目录,这个目录用来保存很多系统文件。主要的工作是创建了5个位于目录/data/system下的File对象,分别是:

  • packages.xml:记录系统中所有安装的应用信息,包括基本信息、签名和权限。
  • packages-backup.xml:packages.xml文件的备份。
  • packages.list:保存普通应用的数据目录和uid等信息。
  • packages-stopped.xml:记录系统中被强制停止运行的应用信息。系统在强制停止某个应用时,会将应用的信息记录到该文件中。
  • packages-stopped-backup.xml:pacakges-stopped.xml文件的备份。
这5个文件中packages-backup.xml和packages-stopped-backup.xml是备份文件。当Android对文件packages.xml和packages-stopped.xml写之前,会先把他们备份,如果写文件成功了,再把备份文件删除。如果写的时候出问题了,重启后再需要读取这两个文件时,如果发现备份文件存在,会使用备份文件的内容,因为原文件可能损坏了。

packages.xml是PackageManagerService启动时需要用的文件,先看下文件的内容:

    <package name="com.dianping.v1"
           codePath="/system/presetapp/BY_3RD_Dianping.apk"
           nativeLibraryPath="/data/app-lib/BY_3RD_Dianping" 
           primaryCpuAbi="armeabi-v7a" 
           flags="1621572" ft="14de3458a58" it="14de3458a58" ut="14de3458a58" 
           version="711" userId="10091">
        <sigs count="1">
            <cert index="5" key="3082025f308201c8a00......" />
        </sigs>
        <perms>
            <item name="android.permission.WRITE_SETTINGS" />
            <item name="android.permission.READ_SMS" />
            <item name="android.permission.ACCESS_FINE_LOCATION" />
            ......
        </perms>
        <proper-signing-keyset identifier="9" />
        <signing-keyset identifier="9" />
    </package>
上面是文件的一个片段,通过标签<package>记录了一个应用的基本信息,签名和申明的权限。

标签<package>中的属性name表示应用的包名,codePath表示apk文件的位置,nativeLibraryPath表示应用的native库的存储路径;flags表示应用的属性,如FLAG_SYSTEM等;it表示应用安装的时间;ut表示应用最后一次修改的时间;version表示应用的版本号;userId表示应用所属的用户ID。

便签<sigs>表示应用的签名,属性count表示标签中包含有多少个证书。cert表示具体的证书的值。

标签<perms>表示应用声明使用的权限,每个子标签<item>代表一项权限。

<package>标签解析后将保存在PackageSetting对象中。系统中实际运行的应用信息会通过标签<package>记录,被升级包覆盖的系统应用不通过<package>标签记录,而是通过<update-packages>标签记录。这两个标签的记录基本一致。这两个标签的应用信息都将保存在PackageSetting对象中。类PackageSetting的继承关系如图。

PackageSetting类继承了PackageSettingBase类,PackageSettingBase类又继承了GrantedPermissions类,应用的基本信息保存在PackageSettingBase类的成员变量中,申明的权限保存在GrantedPremissions类,签名则保持在SharedUserSetting类的成员变量signatures中。

类SharedUserSetting用来描述具有相同sharedUserId的应用信息,它的成员变量packages保存了所有具有相同sharedUserId的应用信息的引用。这些应用的签名是相同的,所以只需在成员变量signatures中保存一份。通过这个对象,Android运行时很容易检索到和某个应用拥有相同sharedUserId的其他应用。

标签<package>所标识的应用的PackageSetting对象都保存在Settings的成员变量mPackages中,标签<update-packages>所标识的系统应用的PackageSetting对象都保存在Settings的成员变量mDisabledSysPackages中,定义如下:

private final ArrayMap<String, PackageSetting> mPackages = new ArrayMap<String, PackageSetting>();
private final ArrayMap<String, PackageSetting> mDisabledSysPackages = new ArrayMap<String, PackageSetting>();

package.xml文件中除了标签<package>、<updated-package>,还有两个标签<cleaning-package>和<renamed-package>。Settings中解析这些标签的代码如下:

                if (tagName.equals("package")) {
                    readPackageLPw(parser);
                } else if (tagName.equals("permissions")) {
                    readPermissionsLPw(mPermissions, parser);
                } else if (tagName.equals("updated-package")) {
                    readDisabledSysPackageLPw(parser);
                } else if (tagName.equals("cleaning-package")) {
                    ......
                        addPackageToCleanLPw(new PackageCleanItem(userId, name, andCode));
                    }
                } else if (tagName.equals("renamed-package")) {
                   ......
                        mRenamedPackages.put(nname, oname);
标签<cleaning-package>用来记录哪些已经删除,但是数据目录还暂时保留的应用的信息。扫描后生成的对象是PackageCleanItem,放入mSettings的mPackagesToBeCleaned数组中管理。

    // Packages that have been uninstalled and still need their external
    // storage data deleted.
    final ArrayList<PackageCleanItem> mPackagesToBeCleaned = new ArrayList<PackageCleanItem>();
标签<renamed-package>记录了系统中改名应用的新旧包名,它记录的信息都保存到mSettings的mRenamedPackaged对象中,定义如下:

final ArrayMap<String, String> mRenamedPackages = new ArrayMap<String, String>();
2、服务的初始化过程

PackageManagerService也是在SystemServer中开始初始化的,代码如下:

mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
......
try {
            mPackageManagerService.performBootDexOpt();
        } catch (Throwable e) {
            reportWtf("performing boot dexopt", e);
        }
......
try {
            mPackageManagerService.systemReady();
        } catch (Throwable e) {
            reportWtf("making Package Manager Service ready", e);
        }
SystemServer对PMS的初始化主要是通过上面代码完成的。首先看下PMS对象的创建,main()函数的代码如下:

    public static final PackageManagerService main(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) {
        PackageManagerService m = new PackageManagerService(context, installer,
                factoryTest, onlyCore);
        ServiceManager.addService("package", m);
        return m;
    }
main函数比较简单,只是创建PMS对象并在ServiceManager中注册。

PMS的构造方法主要完成两件事,第一是把系统中的apk文件和jar包从dex格式转换成ART的oat格式;第二是扫描系统中所有安装的应用,把他们的信息提取出来。

    public PackageManagerService(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) {
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
                SystemClock.uptimeMillis());

        if (mSdkVersion <= 0) {//检查SDK版本
            Slog.w(TAG, "**** ro.build.version.sdk not set!");
        }

        Object bridgeObject;

        try {

            /*
             * load and create the security bridge:com.android.services.SecurityBridge.core.PackageManagerSB
             */
            bridgeObject = getClass().getClassLoader().loadClass(SECURITY_BRIDGE_NAME).newInstance();
            mSecurityBridge = (PackageManagerMonitor)bridgeObject;

        } catch (Exception e){
            Slog.w(TAG, "No security bridge jar found, using default");
            mSecurityBridge = new PackageManagerMonitor();
        }

        mContext = context;
        mFactoryTest = factoryTest;//设置运行模式。工厂模式是一种测试模式
        mOnlyCore = onlyCore;//onlyCore为true表示只处理系统的应用,通常为false
        mLazyDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
        mMetrics = new DisplayMetrics();//DisplayMetrics对象存储屏幕的显示信息
        mSettings = new Settings(context);//新创建一个settings对象
        mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
                ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,
                ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.log", LOG_UID,
                ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID,
                ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID,
                ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID,
                ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
        //上面添加SharedUserSetting对象到mSettings中,sharedUserId属性相同的包可以运行在同一个进程中,或者相互读取资源。这里添加了6中系统的uid:system、phone、log、nfc、Bluetooth、shell。
        // TODO: add a property to control this?
        long dexOptLRUThresholdInMinutes;
        if (mLazyDexOpt) {
            dexOptLRUThresholdInMinutes = 30; // only last 30 minutes of apps for eng builds.
        } else {
            dexOptLRUThresholdInMinutes = 7 * 24 * 60; // apps used in the 7 days for users.
        }
        mDexOptLRUThresholdInMills = dexOptLRUThresholdInMinutes * 60 * 1000;

        String separateProcesses = SystemProperties.get("debug.separate_processes");
        if (separateProcesses != null && separateProcesses.length() > 0) {
            if ("*".equals(separateProcesses)) {
                mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
                mSeparateProcesses = null;
                Slog.w(TAG, "Running with debug.separate_processes: * (ALL)");
            } else {
                mDefParseFlags = 0;
                mSeparateProcesses = separateProcesses.split(",");
                Slog.w(TAG, "Running with debug.separate_processes: "
                        + separateProcesses);
            }
        } else {
            mDefParseFlags = 0;
            mSeparateProcesses = null;
        }

        mInstaller = installer;//应用安装器

        getDefaultDisplayMetrics(context, mMetrics);//设置DisplayMetrics对象
        //读取系统配置来初始化mGlobalGids、mSystemPermissions、mAvailableFeatures
        SystemConfig sy
<think>我们正在分析Android 13中的PackageManagerService(PMS)应用安装卸载流程。根据引用,我们知道PMS负责管理信息,但实际安装卸载操作通过installd服务完成。我们将结合引用内容Android 13源码进行分析。 ### 应用安装流程(Android 13) 1. **入口点与权限校验** 安装请求通常通过`PackageManagerService.installPackage()`方法开始。首先会检查调用者是否具有`INSTALL_PACKAGES`权限[^1][^2]。 2. **APK文件处理** - 复制APK文件到目标目录(如`/data/app/<名>-<随机后缀>`)。 - 通过`Installer`服务(与`installd`守护进程通信)创建应用数据目录:`/data/data/<名>`[^1][^3]。 3. **解析AndroidManifest.xml** 使用`PackageParser`解析APK的清单文件,生成`Package`对象,含四大组件、权限等信息[^2]。 4. **更新PMS内部状态** - 将解析后的信息添加到PMS的`mPackages`映射中。 - 更新`packages.xml``packages.list`文件(通过`mSettings.writeLPr()`)[^2]。 5. **Dex优化与资源准备** - 调用`performDexOpt()`进行Dex文件优化(生成ODE或VDEX文件)。 -应用分配UID并授予声明的权限[^1][^3]。 6. **广播通知** 发送`ACTION_PACKAGE_ADDED`广播,通知系统应用安装完成[^3]。 ### 二、应用卸载流程(Android 13) 1. **入口点与权限校验** 卸载请求通过`PackageManagerService.deletePackageVersioned()`触发,校验`DELETE_PACKAGES`权限[^3]。 2. **资源清理** - 删除APK文件(`/data/app/<名>-<随机后缀>`)。 - 通过`Installer.destroyAppData()`删除数据目录(`/data/data/<名>``/data/user/<userId>/<名>`)[^1][^3]。 -应用安装在外部存储,同时删除外部数据。 3. **状态更新** - 从PMS的`mPackages`中移除信息。 - 调用`mSettings.removePackageLPw()`更新`packages.xml`[^3]。 - 回收UID并撤销权限。 4. **多用户与依赖处理** - **多用户**:遍历所有用户删除应用数据(`/data/user/<userId>/<名>`)。 - **共享库依赖**:检查是否有其他应用依赖当前的共享库,若有则强制停止依赖应用[^3]。 5. **系统应用特殊处理** - 卸载系统应用更新时,回退到初始版本(`/system`分区中的APK)。 - 发送`ACTION_PACKAGE_REMOVED`广播[^3]。 ### 三、关键源码位置(Android 13) 1. **安装核心逻辑** - `PackageManagerService.installPackage()`(入口) - `PackageManagerService.installPackageAsUser()`(多用户支持) - `PackageManagerService.processInstallRequestAsync()`(异步处理安装请求) - `PackageParser.parsePackage()`(解析APK- `Installer.createAppData()`(创建数据目录)[^1] 2. **卸载核心逻辑** - `PackageManagerService.deletePackageVersioned()`(入口) - `PackageManagerService.deletePackageX()`(卸载执行) - `Installer.destroyAppData()`(删除数据目录) - `Settings.removePackageLPw()`(更新设置)[^3] 3. **跨进程通信** PMS通过Binder与`installd`交互,文件操作由`InstallerConnection`实现[^1]。 --- ### 四、流程示意图 #### 安装流程 ```mermaid sequenceDiagram participant Client participant PMS as PackageManagerService participant installd Client->>PMS: installPackage() PMS->>PMS: 校验权限 PMS->>PMS: 复制APK到/data/app PMS->>installd: createAppData() installd->>PMS: 创建目录结果 PMS->>PMS: 解析APK(PackageParser) PMS->>PMS: 更新mPackagespackages.xml PMS->>PMS: 执行Dex优化 PMS->>installd: dexopt() PMS->>PMS: 发送安装完成广播 ``` #### 卸载流程 ```mermaid sequenceDiagram participant Client participant PMS as PackageManagerService participant installd Client->>PMS: deletePackageVersioned() PMS->>PMS: 校验权限 PMS->>installd: destroyAppData() installd->>PMS: 删除数据目录结果 PMS->>PMS: 删除APK文件 PMS->>PMS: 从mPackages移除 PMS->>PMS: 更新packages.xml PMS->>PMS: 发送卸载广播 ``` --- §§ 相关问题 §§ 1. Android 13中PMS如何处理安装过程中的签名冲突? 2. 多用户场景下应用安装的资源隔离机制是如何实现的? 3. 系统应用与普通应用卸载流程中有哪些关键差异? 4. 如何通过PMS实现静默安装(无需用户交互)? [^1]: `frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java` [^2]: `frameworks/base/core/java/android/content/pm/PackageParser.java` [^3]: `frameworks/base/services/core/java/com/android/server/pm/Installer.java`</think>### Android 13 PackageManagerService 应用安装卸载流程分析 #### 应用安装流程(Android 13) ```mermaid graph TD A[安装请求] --> B[权限校验] B --> C[APK文件处理] C --> D[解析与注册] D --> E[资源优化] E --> F[广播通知] ``` 1. **入口与权限校验** - 入口方法:`PackageManagerService.installPackage()` - 校验`INSTALL_PACKAGES`权限签名合法性 - 新增白名单校验机制(通过`IPackageManager.aidl`接口实现)[^2] 2. **APK文件处理** - 复制APK到目标目录:`/data/app/<名>-<随机后缀>` - 通过`Installer`服务调用`installd`守护进程创建数据目录: ```java mInstaller.createAppData(..., packageName, ...); // 创建/data/data/<名> ``` 3. **解析与注册** - 使用`PackageParser`解析`AndroidManifest.xml`生成`Package`对象 - 更新PMS核心数据结构: ```java mPackages.put(packageName, pkg); // 添加到内存映射 mSettings.writeLPr(); // 写入packages.xml ``` - 注册四大组件到`ActivityTaskManagerService`[^2] 4. **资源优化与权限分配** - 执行Dex优化(生成VDEX/ODEX文件) - 分配UID并授予声明权限 - 更新`packages.list`文件(记录与UID映射) 5. **广播通知** - 发送`Intent.ACTION_PACKAGE_ADDED`系统广播 - 触发`PackageInstaller`回调通知安装结果 --- #### 二、应用卸载流程(Android 13) ```mermaid graph TD G[卸载请求] --> H[权限校验] H --> I[资源清理] I --> J[状态更新] J --> K[多用户处理] K --> L[广播通知] ``` 1. **入口与校验** - 主入口:`PackageManagerService.deletePackageVersioned()` - 校验`DELETE_PACKAGES`权限调用者身份 - 检查是否为受保护应用(如系统核心组件) 2. **资源清理** - 删除APK文件:`/data/app/<名>-<随机后缀>` - 通过`Installer`服务删除数据目录: ```java mInstaller.destroyAppData(packageName, userId, flags); // 删除/data/data/<名> ``` - 清理外部存储:`/sdcard/Android/data/<名>` 3. **状态更新** - 从PMS内存结构中移除信息: ```java mPackages.remove(packageName); mSettings.removePackageLPw(packageName); // 更新packages.xml ``` - 回收UID并撤销权限[^3] 4. **多用户与依赖处理** - 遍历所有用户删除数据:`/data/user/<userId>/<名>` - 处理共享库依赖: ```java if (isLibraryDependent(pkg)) { forceStopDependentApps(pkg); // 强制停止依赖应用 } ``` 5. **系统应用特殊处理** - 卸载系统应用更新时回退到初始版本(`/system/app`) - 发送`Intent.ACTION_PACKAGE_REMOVED`广播 - 更新`staged-installer`状态(OTA相关) --- #### 三、关键改进(Android 13) 1. **增量安装优化** - 支持`APEX``APKS`格式的分块安装 - 新增`IncrementalManager`处理增量文件系统 2. **权限模型升级** - 细粒度权限控制(每次授权需用户确认) - 后台安装限制加强(需`REQUEST_INSTALL_PACKAGES`权限) 3. **存储优化** - 采用`F2FS`文件系统提升IO性能 - 数据目录重构(如`/data/app/vmdl<sessionId>.tmp`临时目录) 4. **安全增强** - 强制签名方案v3/v4验证 - 安装前扫描`ANDROID_manifest.xml`防漏洞攻击 --- #### 四、核心源码位置 1. **安装流程** - 入口:`PackageManagerService.installPackage()` - APK处理:`PackageInstallerService.createSession()` - 解析:`PackageParser2.parsePackage()` - 资源优化:`DexManager.performDexOpt()` 2. **卸载流程** - 入口:`PackageManagerService.deletePackageVersioned()` - 资源清理:`DeletePackageHelper.deletePackageX()` - 状态更新:`Settings.removePackageLPw()` 3. **跨进程通信** - `InstallerConnection.execute()`(与`installd`通信) - `PackageManagerService.BinderService`(Binder接口实现) ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值