Android源码分析-PackageManagerService(PMS)源码分析(二)- 利用PackageParser进行package的解析

本文介绍了Android系统中如何解析APK文件。重点分析了PackageParser类的功能及其实现过程,包括PackageParser实例的创建、parsePackage方法的具体实现以及关键组件如Activity、Service的解析流程。

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

一,PackageParser的作用:

PackageParser用于解析一个apk文件。

对于一个apk文件来说,系统是如何进行解析的?本节分析apk解析相关的代码。在上一节中,分析了PackageManagerService的初始化流程。其中,PMS的scanDirLI是关键方法,它用来扫描给定参数dir目录下的apk文件,并通过调用scanPackageLI来进行解析。
在scanPackageLI方法中,创建了解析器,正是通过这个解析器,实现了apk的解析。

二,PackageParser类的源码分析:

2.1 创建PackageParser实例:

在PMS的scanPackageLI方法中,初始化PackageParser,并且调用了它的parsePackage方法:

    private PackageParser.Package scanPackageLI(File scanFile,
            int parseFlags, int scanMode, long currentTime) {
        mLastScanError = PackageManager.INSTALL_SUCCEEDED;
        String scanPath = scanFile.getPath();
        parseFlags |= mDefParseFlags;
        PackageParser pp = new PackageParser(scanPath);

        //设置进程
        pp.setSeparateProcesses(mSeparateProcesses);
        //设置是否是核心app
        pp.setOnlyCoreApps(mOnlyCore);
        //简析
        final PackageParser.Package pkg = pp.parsePackage(scanFile,
                scanPath, mMetrics, parseFlags);

        ......

        //继续简析
        PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanMode
                | SCAN_UPDATE_SIGNATURE, currentTime);
    }

2.2 PackageParser的parsePackage方法:

parsePackage用于解析文件。根据解析的目标(用packageFile参数来判别)的不同,使用不同的解析方法。如果目标是文件夹,则解析这个文件夹下的所有apk文件;如果是文件,就解析单个文件。

parsePackage的代码如下:

public Package parsePackage(File sourceFile, String destCodePath,
            DisplayMetrics metrics, int flags) {
        mParseError = PackageManager.INSTALL_SUCCEEDED;

        //文件合法性检测
        mArchiveSourcePath = sourceFile.getPath();
        if (!sourceFile.isFile()) {
            Slog.w(TAG, "Skipping dir: " + mArchiveSourcePath);
            mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
            return null;
        }
        if (!isPackageFilename(sourceFile.getName())
                && (flags&PARSE_MUST_BE_APK) != 0) {
            if ((flags&PARSE_IS_SYSTEM) == 0) {
                // We expect to have non-.apk files in the system dir,
                // so don't warn about them.
                Slog.w(TAG, "Skipping non-package file: " + mArchiveSourcePath);
            }
            mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
            return null;
        }

        if (DEBUG_JAR)
            Slog.d(TAG, "Scanning package: " + mArchiveSourcePath);

        
        XmlResourceParser parser = null;
        AssetManager assmgr = null;
        Resources res = null;
        boolean assetError = true;
        try {

            assmgr = new AssetManager();
            int cookie = assmgr.addAssetPath(mArchiveSourcePath);
            if (cookie != 0) {
                res = new Resources(assmgr, metrics, null);
                assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                        Build.VERSION.RESOURCES_SDK_INT);

                //xml解析器的创建
                parser = assmgr.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
                assetError = false;
            } else {
                Slog.w(TAG, "Failed adding asset path:"+mArchiveSourcePath);
            }
        } catch (Exception e) {
            Slog.w(TAG, "Unable to read AndroidManifest.xml of "
                    + mArchiveSourcePath, e);
        }
        if (assetError) {
            if (assmgr != null) assmgr.close();
            mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
            return null;
        }
        String[] errorText = new String[1];
        Package pkg = null;
        Exception errorException = null;
        try {
            //真正的解析
            pkg = parsePackage(res, parser, flags, errorText);
        } catch (Exception e) {
            errorException = e;
            mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
        }


        if (pkg == null) {
            // If we are only parsing core apps, then a null with INSTALL_SUCCEEDED
            // just means to skip this app so don't make a fuss about it.
            if (!mOnlyCoreApps || mParseError != PackageManager.INSTALL_SUCCEEDED) {
                if (errorException != null) {
                    Slog.w(TAG, mArchiveSourcePath, errorException);
                } else {
                    Slog.w(TAG, mArchiveSourcePath + " (at "
                            + parser.getPositionDescription()
                            + "): " + errorText[0]);
                }
                if (mParseError == PackageManager.INSTALL_SUCCEEDED) {
                    mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                }
            }
            parser.close();
            assmgr.close();
            return null;
        }

        parser.close();
        assmgr.close();

        // Set code and resource paths
        pkg.mPath = destCodePath;
        pkg.mScanPath = mArchiveSourcePath;
        //pkg.applicationInfo.sourceDir = destCodePath;
        //pkg.applicationInfo.publicSourceDir = destRes;
        pkg.mSignatures = null;

        return pkg;
    }

其中,重载函数parsePackage是关键。

2.3 parsePackage方法的定义:


    private Package parsePackage(
        Resources res, XmlResourceParser parser, int flags, String[] outError)
        throws XmlPullParserException, IOException {

        //包名的解析        
        String pkgName = parsePackageName(parser, attrs, flags, outError);
        if (pkgName == null) {
            mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
            return null;
        }
        int type;

        if (mOnlyCoreApps) {
            boolean core = attrs.getAttributeBooleanValue(null, "coreApp", false);
            if (!core) {
                mParseError = PackageManager.INSTALL_SUCCEEDED;
                return null;
            }
        }

        //创建Package实例
        final Package pkg = new Package(pkgName);
        boolean foundApp = false;
        //获取资源属性
        TypedArray sa = res.obtainAttributes(attrs,
                com.android.internal.R.styleable.AndroidManifest);
        //获取versioncode,versionName
        pkg.mVersionCode = sa.getInteger(
                com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
        pkg.mVersionName = sa.getNonConfigurationString(
                com.android.internal.R.styleable.AndroidManifest_versionName, 0);
        if (pkg.mVersionName != null) {
            pkg.mVersionName = pkg.mVersionName.intern();
        }
        
        ......

        //AndroidManifest.xml清单文件的解析
        int outerDepth = parser.getDepth();
        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
                continue;
            }

            //app名称的获取
            String tagName = parser.getName();
            if (tagName.equals("application")) {
                if (foundApp) {
                    if (RIGID_PARSER) {
                        outError[0] = "<manifest> has more than one <application>";
                        mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                        return null;
                    } else {
                        Slog.w(TAG, "<manifest> has more than one <application>");
                        XmlUtils.skipCurrentTag(parser);
                        continue;
                    }
                }

                foundApp = true;
                //简析Application节点
                if (!parseApplication(pkg, res, parser, attrs, flags, outError)) {
                    return null;
                }
            } else if (tagName.equals("permission-group")) {
                //简析permission-group节点
                if (parsePermissionGroup(pkg, flags, res, parser, attrs, outError) == null) {
                    return null;
                }
            } else if (tagName.equals("permission")) {
                if (parsePermission(pkg, res, parser, attrs, outError) == null) {
                    return null;
                }
            } else if (tagName.equals("permission-tree")) {
                if (parsePermissionTree(pkg, res, parser, attrs, outError) == null) {
                    return null;
                }
            } else if (tagName.equals("uses-permission")) {
                sa = res.obtainAttributes(attrs,
                        com.android.internal.R.styleable.AndroidManifestUsesPermission);

                // Note: don't allow this value to be a reference to a resource
                // that may change.
                String name = sa.getNonResourceString(
                        com.android.internal.R.styleable.AndroidManifestUsesPermission_name);
                /* Not supporting optional permissions yet.
                boolean required = sa.getBoolean(
                        com.android.internal.R.styleable.AndroidManifestUsesPermission_required, true);
                */

                sa.recycle();

                if (name != null && !pkg.requestedPermissions.contains(name)) {
                    pkg.requestedPermissions.add(name.intern());
                    pkg.requestedPermissionsRequired.add(Boolean.TRUE);
                }

                XmlUtils.skipCurrentTag(parser);

            } else if (tagName.equals("uses-configuration")) {
                ConfigurationInfo cPref = new ConfigurationInfo();
                ......

            } else if (tagName.equals("uses-feature")) {
                FeatureInfo fi = new FeatureInfo();
                ......

            } else if (tagName.equals("uses-sdk")) {
                if (SDK_VERSION > 0) {
                    sa = res.obtainAttributes(attrs,
                            com.android.internal.R.styleable.AndroidManifestUsesSdk);

                    ......
                }

                XmlUtils.skipCurrentTag(parser);

            } else if (tagName.equals("supports-screens")) {
                sa = res.obtainAttributes(attrs,
                        com.android.internal.R.styleable.AndroidManifestSupportsScreens);

                ......
                
            } else if (tagName.equals("protected-broadcast")) {
                sa = res.obtainAttributes(attrs,
                        com.android.internal.R.styleable.AndroidManifestProtectedBroadcast);

                ......
                
            } else if (tagName.equals("instrumentation")) {
                if (parseInstrumentation(pkg, res, parser, attrs, outError) == null) {
                    return null;
                }
                
            } else if (tagName.equals("original-package")) {
                ......
                
            } else if (tagName.equals("adopt-permissions")) {
                sa = res.obtainAttributes(attrs,
                        com.android.internal.R.styleable.AndroidManifestOriginalPackage);

                ......
                
            } 
            ......
        }

        ......

        return pkg;
    }

可见,主要是进行了清单文件的简析,并进行Package实例化。

其中,Application是进行Application标签的解析,解析出Activity,Service等组件。

2.4 parseApplication代码分析:



    private boolean parseApplication(Package owner, Resources res,
            XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
        throws XmlPullParserException, IOException {

        //应用信息,,,应用图标,等的获取
        final ApplicationInfo ai = owner.applicationInfo;
        //包名
        final String pkgName = owner.applicationInfo.packageName;

        TypedArray sa = res.obtainAttributes(attrs,
                com.android.internal.R.styleable.AndroidManifestApplication);

        //应用名称
        String name = sa.getNonConfigurationString(
                com.android.internal.R.styleable.AndroidManifestApplication_name, 0);
        if (name != null) {
            ai.className = buildClassName(pkgName, name, outError);
            if (ai.className == null) {
                sa.recycle();
                mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                return false;
            }
        }

        String manageSpaceActivity = sa.getNonConfigurationString(
                com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity, 0);
        if (manageSpaceActivity != null) {
            ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity,
                    outError);
        }

        boolean allowBackup = sa.getBoolean(
                com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true);
        if (allowBackup) {
            ai.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;

            // backupAgent, killAfterRestore, and restoreAnyVersion are only relevant
            // if backup is possible for the given application.
            String backupAgent = sa.getNonConfigurationString(
                    com.android.internal.R.styleable.AndroidManifestApplication_backupAgent, 0);
            if (backupAgent != null) {
                ai.backupAgentName = buildClassName(pkgName, backupAgent, outError);
                if (DEBUG_BACKUP) {
                    Slog.v(TAG, "android:backupAgent = " + ai.backupAgentName
                            + " from " + pkgName + "+" + backupAgent);
                }

                if (sa.getBoolean(
                        com.android.internal.R.styleable.AndroidManifestApplication_killAfterRestore,
                        true)) {
                    ai.flags |= ApplicationInfo.FLAG_KILL_AFTER_RESTORE;
                }
                if (sa.getBoolean(
                        com.android.internal.R.styleable.AndroidManifestApplication_restoreAnyVersion,
                        false)) {
                    ai.flags |= ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
                }
            }
        }

        TypedValue v = sa.peekValue(
                com.android.internal.R.styleable.AndroidManifestApplication_label);
        if (v != null && (ai.labelRes=v.resourceId) == 0) {
            ai.nonLocalizedLabel = v.coerceToString();
        }

        //应用图标
        ai.icon = sa.getResourceId(
                com.android.internal.R.styleable.AndroidManifestApplication_icon, 0);
        ai.logo = sa.getResourceId(
                com.android.internal.R.styleable.AndroidManifestApplication_logo, 0);
        //应用主题
        ai.theme = sa.getResourceId(
                com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
        

        //其它属性
        ......
        ......

        final int innerDepth = parser.getDepth();

        int type;
        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
                continue;
            }

            String tagName = parser.getName();
            //简析activity
            if (tagName.equals("activity")) {
                Activity a = parseActivity(owner, res, parser, attrs, flags, outError, false,
                        hardwareAccelerated);
                if (a == null) {
                    mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                    return false;
                }

                owner.activities.add(a);

            } 
            //简析receiver
            else if (tagName.equals("receiver")) {
                Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true, false);
                if (a == null) {
                    mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                    return false;
                }

                owner.receivers.add(a);

            }
            //简析service
             else if (tagName.equals("service")) {
                Service s = parseService(owner, res, parser, attrs, flags, outError);
                if (s == null) {
                    mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                    return false;
                }

                owner.services.add(s);

            }

            //简析provider

             else if (tagName.equals("provider")) {
                Provider p = parseProvider(owner, res, parser, attrs, flags, outError);
                if (p == null) {
                    mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                    return false;
                }

                owner.providers.add(p);

            } 
            //简析其它属性
            。。。。。。

        }

        return true;
    }

可见,进行了activity,Service,Provider,Receiver等组件的简析,并且返回相应的组件的一个实例。例如,parseActivity方法返回一个解析成功的Activity实例。

现在,我们来看一下简析完成后,又做了什么工作,即scanPackageLI方法的实现原理。

2.5 scanPackageLI方法分析:

在“2.1 创建PackageParser实例”中,PackageParser函数的实现的最后,有scanPackageLI的调用。现在,来分析scanPackageLI的实现:


    private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
            int parseFlags, int scanMode, long currentTime) {

            ......

            // activity的添加

            N = pkg.activities.size();
            r = null;
            for (i=0; i<N; i++) {
                PackageParser.Activity a = pkg.activities.get(i);
                a.info.processName = fixProcessName(pkg.applicationInfo.processName,
                        a.info.processName, pkg.applicationInfo.uid);
                mActivities.addActivity(a, "activity");
                if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
                    if (r == null) {
                        r = new StringBuilder(256);
                    } else {
                        r.append(' ');
                    }
                    r.append(a.info.name);
                }
            }
            if (r != null) {
                if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, "  Activities: " + r);
            }

            ......
        }

        return pkg;
    }

这样,mActivity中就保存了所有的activity。

而mActivity的定义如下:

// All available activities, for your resolving pleasure.
final ActivityIntentResolver mActivities =
        new ActivityIntentResolver();

// All available receivers, for your resolving pleasure.
final ActivityIntentResolver mReceivers =
        new ActivityIntentResolver();

// All available services, for your resolving pleasure.
final ServiceIntentResolver mServices = new ServiceIntentResolver();

 至此,整个解析就完成了。简析完成后,诸如Activity,Service等组件都保存在了内存中,例如mActivity保存了所有的Activity的信息。


<think>我们正在分析Android 13中的PackageManagerServicePMS应用安装和卸载流程。根据引用,我们知道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: 解析APKPackageParserPMS->>PMS: 更新mPackages和packages.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接口实现) ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liranke

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值