APK安装流程详解3——PackageManager与PackageManagerService

移动开发 简书

APK安装流程系列文章整体内容如下:

本片文章的主要内容如下:

  • 1、PackageManager的具体实现类
  • 2、ApplicationPackageManager类
  • 3、IPackageManager类
  • 4、PackageMnager、IPackageManager与PackageManagerService
  • 5、PackageManagerService类简介
  • 6、ServiceManager与PackageManagerService关系
  • 7、总结

一、PackageManager的具体实现类

上面一篇文章介绍了PackageManager,我们知道PackageManager是一个抽象类,它里面很重要的方法都是抽象的,所以在具体执行的时候,肯定是他的实现子类,那么我们就来看下他具体实现类,上面一篇文章我们研究PackageManager类的时候,官网推荐获取PackageManager对象的方法是Context的Context#getPackageManager()方法,那我们来看下

1、Context#getPackageManager()

代码在 Context.java 322行

/** Return PackageManager instance to find global package information. */
    public abstract PackageManager getPackageManager();

我们知道Context是一个抽象类,而他的getPackageManager()也是抽象方法,我们知道Context的具体实现类是ContextImpl,那我们就去ContextImpl里面去看下

2、ContextImpl#getPackageManager()

代码在 ContextImpl.java 208行

@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;
    }

这个方法的内部流程大体上分为三个步骤如下:

  • 第一步 :判断mPackageManager是否为空,如果为空,则说明是的第一次调用,走第二步,如果不为空,则直接返回mPackageManager
  • 第二步 :能走到第二步,说明这是第一次调用,则调用ActivityThread的静态方法getPackageManager()获取一个IPackageManager对象
  • 第三步 :如果获取的IPackageManager对象不为空,则构造一个ApplicationPackageManager对象,而ApplicationPackageManager是PackageManager的子类,把mPackageManager指向ApplicationPackageManager,然后返回ApplicationPackageManager,也就是返回的ApplicationPackageManager

通过上面代码分析我们知道,在我们平时调用Context的getPackageManager()方法返回的是ApplicationPackageManager这个类。

在这个方法里面涉及到两个重要类:

  • 1、ActivityThread.getPackageManager()中的返回值IPackageManager类
  • 2、new ApplicationPackageManager(this, pm)中的ApplicationPackageManager类

下面我就依次研究下,首先看下ApplicationPackageManager类

二、ApplicationPackageManager类

ApplicationPackageManager.java源码地址

1、ApplicationPackageManager类简介

final class ApplicationPackageManager extends PackageManager {
    ...
}

通过源代码我们知道ApplicationPackageManager继承自PackageManager,而且这ApplicationPackageManager类不是抽象的,所以ApplicationPackageManager必然实现了PackageManager的所有抽象方法,而且ApplicationPackageManager是final的,所以它没有子类。

2、ApplicationPackageManager类的构造函数

ApplicationPackageManager就一个构造函数

代码在 ApplicationPackageManager.java 1123行

ApplicationPackageManager(ContextImpl context,
                              IPackageManager pm) {
        mContext = context;
        mPM = pm;
    }
  • 1、这个构造函数不是public所以,只能它的活动区域只有”包”内,而它的包是”android.app”,而且它的构造函数就一个,所以只有系统才能调用。
  • 2、两个入参,一个是ContextImpl,一个IPackageManager对象。关于IPackageManager对象,我们下面将仔细讲解。

3、ApplicationPackageManager类中对PackageManager的具体实现

我们首先来看和安装有关的几个方法

  • 1、public abstract void installPackage(Uri, IPackageInstallObserver, int,String)方法
  • 2、 public abstract void installPackageWithVerification(Uri,IPackageInstallObserver, int, String,Uri, ManifestDigest,ContainerEncryptionParams)方法
  • 3、public abstract void installPackageWithVerificationAndEncryption(Uri,IPackageInstallObserver, int, String, VerificationParams, ContainerEncryptionParams)方法
  • 4、 public abstract void installPackage(Uri,PackageInstallObserver,int, String)方法
  • 5、public abstract void installPackageWithVerification(Uri,PackageInstallObserver, int, String, Uri, ManifestDigest,ContainerEncryptionParams)方法
  • 6、public abstract void installPackageWithVerificationAndEncryption(Uri,PackageInstallObserver, int, String,VerificationParams, ContainerEncryptionParams)方法
  • 7、public abstract int installExistingPackage(String)方法

那我们就依次来看下

3.1、public abstract void installPackage(Uri, IPackageInstallObserver, int,String)方法

代码在 ApplicationPackageManager.java) 1335行

@Override
    public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,String installerPackageName) {
        // 第一步
        final VerificationParams verificationParams = new VerificationParams(null, null,
                null, VerificationParams.NO_UID, null);
        // 第二步
        installCommon(packageURI, new LegacyPackageInstallObserver(observer), flags,
                installerPackageName, verificationParams, null);
    }

这个方法内部主要分为两块

  • 第一步,构造VerificationParams对象
  • 第二步,调用installCommon(Uri,PackageInstallObserver, int, String, int)方法

那我们就来看下installCommon(Uri,PackageInstallObserver, int, String, int)方法

代码在 ApplicationPackageManager.java) 1388行

private void installCommon(Uri packageURI,PackageInstallObserver observer, int flags, String installerPackageName, int userId) {
        // 第一步
        if (!"file".equals(packageURI.getScheme())) {
            throw new UnsupportedOperationException("Only file:// URIs are supported");
        }
        // 第二步
        final String originPath = packageURI.getPath();
        try {
            // 第三步
            mPM.installPackageAsUser(originPath, observer.getBinder(), flags, installerPackageName,
                    userId);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

通过上面代码我们知道,方法内部主要分为三个部分,如下:

  • 第一步,scheme判断,如果非”file”则抛异常,因为只支持file格式的URI
  • 第二步,获取相应的路径
  • 第三步,调用IPackageMnager的installPackageAsUser(String, IPackageInstallObserver2,int, String, int)方法

所以我们总结下就是:

public abstract void installPackage(Uri, IPackageInstallObserver, int,String)方法其内部本质是调用的IPackageManager的nstallPackageAsUser(String, IPackageInstallObserver2,int, String, int)

3.2、 public abstract void installPackageWithVerification(Uri,IPackageInstallObserver, int, String,Uri, ManifestDigest,ContainerEncryptionParams)方法

代码在 ApplicationPackageManager.java) 1344行

@Override
    public void installPackageWithVerificationAndEncryption(Uri packageURI,IPackageInstallObserver observer, int flags, String installerPackageName,VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
        installCommon(packageURI, new LegacyPackageInstallObserver(observer), flags,
                installerPackageName, verificationParams, encryptionParams);
    }

我们发现这个方法内部其实也是调用的是installCommon(Uri,PackageInstallObserver, int, String, int)方法,通过上面的内容我们知道,所以我们可以说

public abstract void installPackageWithVerification(Uri,IPackageInstallObserver, int, String,Uri, ManifestDigest,ContainerEncryptionParams)方法其内部本质也是 调用的IPackageManager的installPackageAsUser(String, IPackageInstallObserver2,int, String, int)方法

3.3、 public abstract void installPackageWithVerificationAndEncryption(Uri,IPackageInstallObserver, int, String, VerificationParams, ContainerEncryptionParams)方法

代码在 ApplicationPackageManager.java) 1353行

@Override
    public void installPackageWithVerificationAndEncryption(Uri packageURI,
            IPackageInstallObserver observer, int flags, String installerPackageName,
            VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
        installCommon(packageURI, new LegacyPackageInstallObserver(observer), flags,
                installerPackageName, verificationParams, encryptionParams);
    }

我们发现这个方法内部其实也是调用的是installCommon(Uri,PackageInstallObserver, int, String, int)方法,通过上面的内容我们知道,所以我们可以说

public abstract void installPackageWithVerificationAndEncryption(Uri,IPackageInstallObserver, int, String, VerificationParams, ContainerEncryptionParams)方法其内部本质也是 调用的IPackageManager的installPackageAsUser(String, IPackageInstallObserver2,int, String, int)方法

3.4、 public abstract void installPackage(Uri,PackageInstallObserver,int, String)方法

代码在 ApplicationPackageManager.java) 1362行

@Override
    public void installPackage(Uri packageURI, PackageInstallObserver observer,int flags, String installerPackageName) {
        // 第一步
        final VerificationParams verificationParams = new VerificationParams(null, null,
                null, VerificationParams.NO_UID, null);
        // 第二步
        installCommon(packageURI, observer, flags, installerPackageName, verificationParams, null);
    }

这个方法内部主要分为两块

  • 第一步,构造VerificationParams对象
  • 第二步,调用installCommon(Uri,PackageInstallObserver, int, String, int)方法

所以我们可以说

public abstract void installPackage(Uri,PackageInstallObserver,int, String)方法其内部本质也是 调用的IPackageManager的installPackageAsUser(String, IPackageInstallObserver2,int, String, int)方法

3.5、public abstract void installPackageWithVerification(Uri,PackageInstallObserver, int, String, Uri, ManifestDigest,ContainerEncryptionParams)方法

代码在 ApplicationPackageManager.java) 1370行

@Override
    public void installPackageWithVerification(Uri packageURI,PackageInstallObserver observer, int flags, String installerPackageName,Uri verificationURI, ManifestDigest manifestDigest,ContainerEncryptionParams encryptionParams) {
        // 第一步
        final VerificationParams verificationParams = new VerificationParams(verificationURI, null,null, VerificationParams.NO_UID, manifestDigest);
        // 第二步
        installCommon(packageURI, observer, flags, installerPackageName, verificationParams,
                encryptionParams);

这个方法内部主要分为两块

  • 第一步,构造VerificationParams对象
  • 第二步,调用installCommon(Uri,PackageInstallObserver, int, String, int)方法

所以我们可以说

public abstract void installPackageWithVerification(Uri,PackageInstallObserver, int, String, Uri, ManifestDigest,ContainerEncryptionParams)方法其内部本质也是 调用的IPackageManager的installPackageAsUser(String, IPackageInstallObserver2,int, String, int)方法

3.6、public abstract void installPackageWithVerificationAndEncryption(Uri,PackageInstallObserver, int, String,VerificationParams, ContainerEncryptionParams)方法

代码在 ApplicationPackageManager.java) 1380行

@Override
    public void installPackageWithVerificationAndEncryption(Uri packageURI,PackageInstallObserver observer, int flags, String installerPackageName,VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
        installCommon(packageURI, observer, flags, installerPackageName, verificationParams,
                encryptionParams);
    }

我们发现这个方法内部其实也是调用的是installCommon(Uri,PackageInstallObserver, int, String, int)方法,通过上面的内容我们知道,所以我们可以说

public abstract void installPackageWithVerificationAndEncryption(Uri,PackageInstallObserver, int, String,VerificationParams, ContainerEncryptionParams)方法其内部本质也是 调用的IPackageManager的installPackageAsUser(String, IPackageInstallObserver2,int, String, int)方法

3.6、public abstract int installExistingPackage(String)方法

代码在 ApplicationPackageManager.java) 147行

@Override
    public int installExistingPackage(String packageName)
            throws NameNotFoundException {
        try {
            // 第一步
            int res = mPM.installExistingPackageAsUser(packageName, UserHandle.myUserId());
            // 第二步
            if (res == INSTALL_FAILED_INVALID_URI) {
                throw new NameNotFoundException("Package " + packageName + " doesn't exist");
            }
            return res;
        } catch (RemoteException e) {
            // 第三步
            // Should never happen!
            throw new NameNotFoundException("Package " + packageName + " doesn't exist");
        }
    }

我们把这个方法内内部代码大体上分为3块如下:

  • 第一步:首先调用IPackageMnager的installExistingPackageAsUser(String,int)方法,并将返回值赋值给res
  • 第二步:如果res等于INSTALL_FAILED_INVALID_URI,则表示是无用的URI,并抛异常
  • 第三步:如果走到这一步,则说明,在调用IPackageMnager的installExistingPackageAsUser(String,int)方法的时候抛RemoteException异常,则抛出异常说明。

通过上面的方法,大家有没有发现什么规律,对了就是ApplicationPackageManager实现的PackageManager的抽象方法,其内部都是调用其内部变量mPm即IPackageManager类来实现的,大家可自行去看下,并验证下。

4、总结

ApplicationPackageManager 中关于PackageManager的具体实现,其实是调用IPackageManager来是实现的。

那IPackageManager是什么东西,那我们来研究下

三、IPackageManager类

首先,我们先来看下上面代码涉及到的ActivityThread.getPackageManager()方法内部是怎么实现的

(一)、ActivityThread的静态方法getPackageManager()

关于ActivityThread我们会在后续的Android系统中的启动流程中详细讲解。

代码在 ActivityThread.java 1669行

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;
    }

这个方法的内部流程大体上分为三个步骤如下:

  • 第一步 :判断sPackageManager是否为空,如果为空,则说明是的第一次调用,走第二步,如果不为空,则直接返回sPackageManager
  • 第二步 :能走到第二步,说明这是第一次调用,则调用ServiceManager的getService(String)方法获取一个IBinder对象
  • 第三步 :通过调用IPackageManager.Stub.asInterface(IBinder);获取一个sPackageManager对象

咦,上面代码好熟悉啊,这不是明显的AIDL啊,这里涉及到Binder知识,可以参考我的Binder文章 Android跨进程通信IPC之6——Binder框架 和关于AIDL文章 Android跨进程通信IPC之11——AIDL

(二)、IPackageManager.aidl

IPackageManager.aidl源码地址

IPackageManager的AIDL结构如下:

IPackageManager的结构.png

里面涉及IIterface、IPackageManager、IPackageManager.Stub、IPackageManager.Stub.Proxy这几类:

  • IPackageManager接口继承自IIterface.java接口。在IIterface.java接口定义了方法asBinder(),其作用是将IPackageManager转换成IBinder对象。
  • IPackageManager.Stub是IPackageManager接口的的一个内部类,Stub类实现了IBinder和IPackageManager接口。
    • IPackageManager.Stub定义了asInterface(IBinder)方法;该方法将IBinder对象转换成IPackageManager类型的对象,返回的是IPackageManager.Stub.Proxy对象
    • IPackageManager.Stub类重写了Binder类的onTransact()方法;该方法根据命令类型,处理数据传输。
    • IPackageManager.Stub类实现了asBinder()方法,该方法直接返回IPackageManager.Stub对象。
    • IPackageManager.Stub类并未实现IPackageManager实现的方法。
  • IPackageManager.Stub类有一个内部类Proxy,其中Proxy类实现了IPackageManager接口
    • IPackageManager.Stub类的内部类Proxy持有一个mRemote对象,该对象是对IPackageManager.Stub的引用。
    • IPackageManager.Stub类的内部类Proxy实现了IPackageManager的方法,这些方法通过mRemote调用Binder中的transact()方法,最终调用IPackageManager.Stub的onTransact()方法处理。
    • IPackageManager.Stub类的内部类Proxy也实现了IInterface.java中定义的asBinder方法,该方法返回的是mRemote

四、PackageMnager、IPackageManager与PackageManagerService

(一)、ApplicationPackageManager和PackageManagerService在IPackageManager的角色

在上面分析ContextImpl的getPackageManager()方法里面,我们知道

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

而在ActivityThread的静态方法getPackageManager()里面

sPackageManager = IPackageManager.Stub.asInterface(b);

所以我们可以在ApplicationPackageManager里面的mPM其实就是 IPackageManager.Stub内部类Proxy对象。那对应的IPackageManager.Stub是什么?对了就是PackageManagerService.java。为什么是它因为如下:

public class PackageManagerService extends IPackageManager.Stub {
   ...
}

代码在 PackageManagerService.java

所以总结如下图

image.png

所以结合上面的知识在结合PackageManager、ApplicationPackageManager和PackageManagerService总结如下:

  • IPackageManager负责通信 。IPackageManager接口类中定义了很多业务方法,但是由于安全等方面的考虑,Android对外(即SDK)提供的仅仅是一个子集,该子集被封装在抽象类PackageManager中。客户端一般通过Context的getPackageManager函数返回一个类型为PackageManager的对象,该对象的实际类型是PackageManager的子类ApplicationPackageManager。ApplicationPackageManager并没有直接参与Binder通信,而是通过mPM成员变量指向了一个IPackageManager.Stub.Proxy类型的对象
  • AIDL中的Binder服务端是 PackageManagerService ,因为PackageManagerService继承自IPackageManager.Stub。由于IPackageManager.Stub类从Binder派生,所以PackageManagerService将作为服务端参与Binder通信。
  • AIDL中的Binder客户端是 ApplicationPackageManager中成员变量mPM ,因为mPM内部指向的是IPackageManager.Stub.Proxy

整体流程的Binder结构大致如下:

image.png

(二)、获取Client的过程

从上面的图中我们知道通过AIDL结束,Client通过PackageManagerService去快进程调用Server端的Stub,底层依然是依靠Binder机制进行机制,Client获取PackageManangerService的代理对象过程:

获取Client的过程.png

通过一层层的封装,Client调用PackageManagerService的过程最终是通过IPackageManager.Stub.Proxy类对象进行方法调用的

(三)、在”安装”的角色与分工

一图以示之,如下:

安装中的角色.png

(四)、另类的理解

我们用一个类比举例:

假设你是一个公司的商务负责人,正在和客户商谈事务,在涉及公司的具体业务的同事,你要请示你的老板,你需要给你老板打电话,交流商务谈判的具体细节,这里面,你就是应用进程里面的ApplicationPackageManager,IPackageManager就是你们的通信工具——电话,你老板就是SystemServer进程里面的PackageManagerService,你的电话就是IPackageManager.Stub.Proxy,老板的电话是IPackageManager.Stub。IPackageManager其实就是一个具体业务场景下的数据交换的工具而已。

那下面我们就来简单的介绍一下PackageManagerService

五、PackageManagerService类简介

PackageManagerService源码地址

这个类一共16811行,一万多行,我对谷歌的安卓团队也是醉了。我要想把这个类讲清楚,估计至少要20W字,我就简单说下吧,希望大家理解

(一)、PackageManagerService概述与演化史

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

PackageManagerService演化史

如下图:

PackageManagerService演化史.png

建议有件下载到电脑上查看

(二)、PackageManagerService类

PackageManagerService继承自IPackageManager.Stub,Stub类从Binder派生,因此PackageManagerService将作为服务端参与Binder通信。

1、重要的成员支持类

  • PackageParser
    这个类主要用于解析APK,解析其AndroidManifest.xml文件得到package的所有信息。补充一下:PackageParser.Package这个类用于容纳解析出的信息。
  • Settings
    这个类表示它服务处理设置和读取包的各种状态,它是动态的,比如userId,shareUser、permission、signature以及origPackg相关信息。安装 包即install package其实就从要安装的的package中抽取信息更新Settings中的内容,特别的是Settings针对shareUser和origPackage做了特别的关照。另外,为了加速启动速度,Settings的内容会写入/data/system/packages.xml、packages-backup.xml和packages.list,下次启动时会直接载入。
  • Installer :这个类协助安装过程,更多的是将针对文件/路径的操作放在c和cpp里面去实现,真正的工作是由install承担的,Install只是通过named socket “installd” 连接 install,使用简单的cmd-respond协议只会intall完成工作,在其”install”命令中可以看到,其实只是创建了/data/data/目录而已。

2、重要的成员变量

  • final PackageInstallerService mInstallerService
    PackageInstallService实例,一个应用的安装时间比较长,Android就是用PackageInstallerService来管理应用的安装过程。在构造函数的最后创建。
  • final Installer mInstaller
    被@GuardedBy 注解标记,它是Install的实例,用于和Demon进行install交互。实际上系统上进行APK格式转换、建立数据目录等工作,都是install进程来完成的。
  • final Settings mSettings
    Setting的实例,保存一些PackageManagner动态设置信息
  • final ArrayMap mPackages
    是被@GuardedBy注解标记的,代表系统已经安装的package
  • final private ArrayMap mExpectingBetter
    被升级过的应用列表
  • final SparseArray<hashset> mSystemPermissions</hashset :系统权限的集合
  • final HashMap mSharedLibraries :当前已知的共享库
  • final boolean mOnlyCore :用于判断是否只扫描系统库
  • final ActivityIntentResolver mActivities :所有已知的Activity用于与其对应的Intent一一对应
  • final ActivityIntentResolver mReceivers :所有已知的Receiver用于与其对应的Intent一一对应
  • final ServiceIntentResolver mServices :所有已知的Service用于与其对应的Intent一一对应
  • final ProviderIntentResolver mProviders :所有已知的provider用于与其对应的Intent一一对应

六、ServiceManager与PackageManagerService关系

(一)、ServiceManager回顾

ServiceManager顾名思义是Service的管理,该类具有一个HashMap持有一个已经注册的Servce,并提供相应的方法以便Framework层的调用。如入发现某个Service未注册,并会通过ServiceManagerNative.java这个Service获取。其中ServiceManager的UML类图如下:

ServiceManager的UML类图.png

ServiceManager提供的public方法都是静态方法,这些方法实现大同小异。这里以getService(String)方法实现为例进行说明,其代码如下:

代码在 ServiceManager.java 49行

public static IBinder getService(String name) {
    try {
        IBinder service = sCache.get(name);
        if (service != null) {
            return service;
        } else {
            return getIServiceManager().getService(name);
        }
    } catch (RemoteException e) {
        Log.e(TAG, "error in getService", e);
    }
    return null;
}

其中mRemote是一个ServiceNativeManager对象。从上述实现我们发现,getService方法在执行的过程中,可能会调用ServiceManager类中getIServiceManager()中用于创建ServieManagerNative对象,其代码如下:

代码在 ServiceManager.java 33行

private static IServiceManager getIServiceManager() {
    if (sServiceManager != null) {
        return sServiceManager;
    }
    // Find the service manager
    sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
    return sServiceManager;
}

其中ServiceManagerNative.asInterface(XXX)方法,该方法实际返回IServiceManager对象,其实实际上一个ServiceManagerNative.Proxy对象。ServiceManagerNative.java中addService(),getService()都是native方法,最终会调用service_manager.c类中方法,关于这块可以参考 Android跨进程通信IPC之6——Binder框架

(二)、PackageManagerService注册

在Android启动的过程中,会启动SystemServer进行。在SystemServer启动的过程中,会调用PackageManagerService的main()函数来初始化一个PackageManagerService对象。其中main()实现如下:

public static PackageManagerService main(Context context, Installer installer,boolean factoryTest, boolean onlyCore) {
    PackageManagerService m = new PackageManagerService(context, installer,factoryTest, onlyCore);
    ServiceManager.addService("package", m);
    return m;
}

上面说了半天,那PackageManagerService是何时启动的?下面就让我们来详细了解下

七、总结

本片文章主要讲解了PackageManager与PackageManagerService的关系,PackageManagerService事实上是一个binder(PackageManagerService继承自IPackageManager.Stub,而IPackageManager.Stub继承自Binder),Client端通过获取PackageManagerService的服务代理对象IPackageManager.Stub.Proxy,Proxy和Stub都实现了IPackageManager接口,Client调用了Proxy中的接口和方法,通过Proxy中的BinderProxy对象传递经过Binder驱动调用服务端的Binder中的方法,即Stub中的接口实现,PackageManagerService是Stub的子类,Stub中的接口方法在子类中具体实现,如下图:

总结.png

Binder框架如下:

IPackageManager的Binder框架.png

上一篇文章 APK安装流程详解2——PackageManager简介

下一篇文章 APK安装流程详解4——安装中关于so库的哪些事

简书稿源:简书 (源链) | 关于 | 阅读提示

本站遵循[CC BY-NC-SA 4.0]。如您有版权、意见投诉等问题,请通过eMail联系我们处理。
酷辣虫 » 移动开发 » APK安装流程详解3——PackageManager与PackageManagerService

喜欢 (0)or分享给?

专业 x 专注 x 聚合 x 分享 CC BY-NC-SA 4.0

使用声明 | 英豪名录