美文网首页Android开发
12 PackageManagerService

12 PackageManagerService

作者: 凤邪摩羯 | 来源:发表于2020-10-10 13:45 被阅读0次

1.概述

PackageManagerService(简称PKMS),是Android系统中核心服务之一,管理着所有跟package相关的工作,常见的比如安装、卸载应用。 PKMS服务也是通过binder进行通信,IPackageManager.aidl由工具转换后自动生成binder的服务端IPackageManager.Stub和客户端IPackageManager.Stub.Proxy,具体关系如图:

image.png
  • Binder服务端:PackageManagerService继承于IPackageManager.Stub;

  • Binder客户端:ApplicationPackageManager(简称APM)的成员变量mPM继承于IPackageManager.Stub.Proxy; 本身APM是继承于PackageManager对象。

Android系统启动过程中,一路启动到SystemServer后,便可以启动framework的各大服务,本文将介绍PKMS的启动过程

PKMS职责

  • 负责Android系统中Package的安装、升级、卸载

  • 对外提供统一的信息查询功能,其中包括查询系统中匹配某Intent的Activities、BroadCastReceivers或Services等

2. PKMS启动过程

image.png
  • scanPackageLI分析
image.png

PackageParser定了相当多的内部类,这些内部类的作用就是保存对应的信息。解析AndroidManifest.xml文件得到的信息由Package保存。从该类的成员变量可看出,和Android四大组件相关的信息分别由activites、receivers、providers、services保存。由于一个APK可声明多个组件,因此activites和receivers等均声明为ArrayList

3. 获取PKMS

image.png

4. 启动过程正涉及到的核心文件

文件 功能
/data/data/ App数据目录
/data/user/ App数据目录
/data/app/ App安装目录
/data/system/packages.xml 所有安装app信息
/data/system/packages-stopped.xml 所有强制停止app信息
/data/system/packages.list 所有安装app信息

Android系统有很多目录可以存放app,如下所示:

目录 App类别
/vendor/overlay 系统App
/system/framework 系统App
/system/priv-app 系统App
/system/app 系统App
/vendor/priv-app 系统App
/vendor/app 系统App
/oem/app 系统App
/data/app 普通App
/data/app-private 普通App

5 apk安装的卸载

5.1 apk安装方式

  • 安装系统APK和预置的APK(第一次开机时安装,没有安装界)

    PackageManagerService的构造中会扫描对应目录下的apk,完成安装

  • 网络下载应用安装――通过market应用完成,没有安装界面

    调用PackageManager的installPackage方法执行安装

  • ADB工具安装,没有安装界面

    /repo/system/core/adb/commandline.cpp中install_app方法,该方法调用pm_command通过send_shell_command方法将数据发送到手机端的adbd守护进程中,adbd在收到PC中Console发来的数据之后启动一个Shell,然后执行pm脚本(pm位于/system/bin目录下).

    pm脚本通过app_process执行pm.jar包的main函数(\system\framework\pm.jar) 对应源码: /repo/frameworks/base/cmds/pm/src/com/android/commands/pm/Pm.java

  • 第三方应用安装,有安装界面

5.2 apk 安装流程

  1. 将app复制到data/app目录下,扫描并解压安装包,并把dex文件(DVM字节码)保存到dalvik-cache目录,

  2. 在data/data目录下创建对应的应用数据目录.

  3. 解析apk的AndroidManifest.xml文件

  4. 显示快捷方式

image.png image.png

5.3 apk卸载流程

image.png

6 apk打包过程

image.png
image.png

6.1 aapt阶段

  • 使用aapt来打包res资源文件,生成R.java、resources.arsc和res文件(二进制 & 非二进制如res/raw和pic保持原样)

  • resources.arsc文件 resources.arsc这个文件记录了所有的应用程序资源目录的信息,包括每一个资源名称、类型、值、ID以及所配置的维度信息。我们可以将这个resources.arsc文件想象成是一个资源索引表,这个资源索引表在给定资源ID和设备配置信息的情况下,能够在应用程序的资源目录中快速地找到最匹配的资源

6.2 aidl阶段

AIDL (Android Interface Definition Language), Android接口定义语言,Android提供的IPC (Inter Process Communication,进程间通信)的一种独特实现。 这个阶段处理.aidl文件,生成对应的Java接口文件。

6.3 Java Compiler阶段

通过Java Compiler编译R.java、Java接口文件、Java源文件,生成.class文件。

6.4 dex阶段

通过dex命令,将.class文件和第三方库中的.class文件处理生成classes.dex。

6.5 apkbuilder阶段

将classes.dex、resources.arsc、res文件夹(res/raw资源被原装不动地打包进APK之外,其它的资源都会被编译或者处理)、Other Resources(assets文件夹)、AndroidManifest.xml打包成apk文件。 注意: res/raw和assets的相同点:

  • 两者目录下的文件在打包后会原封不动的保存在apk包中,不会被编译成二进制。 res/raw和assets的不同点:
  1. res/raw中的文件会被映射到R.java文件中,访问的时候直接使用资源ID即R.id.filename;assets文件夹下的文件不会被映射到R.java中,访问的时候需要AssetManager类。

  2. res/raw不可以有目录结构,而assets则可以有目录结构,也就是assets目录下可以再建立文件夹

6.6 Jarsigner阶段

对apk进行签名,可以进行Debug和Release 签名。

6.7 zipalign阶段

release mode 下使用 aipalign进行align,即对签名后的apk进行对齐处理。 Zipalign是一个android平台上整理APK文件的工具,它对apk中未压缩的数据进行4字节对齐,对齐后就可以使用mmap函数读取文件,可以像读取内存一样对普通文件进行操作。如果没有4字节对齐,就必须显式的读取,这样比较缓慢并且会耗费额外的内存。 在 Android SDK 中包含一个名为 “zipalign” 的工具,它能够对打包后的 app 进行优化。 其位于 SDK 的 build-tools 目录下, 例如: D:\Develop\Android\sdk\build-tools\23.0.2\zipalign.exe

7 系统服务的注册方式

  • 注意不是四大组件中的service

7.1. 概述

启动启动过程有采用过两种不同的方式来注册系统服务:

  • ServiceManager的addService()

  • SystemServiceManager的startService()

其核心都是向ServiceManager进程注册binder服务,但功能略有不同,下面从源码角度详加说明。

image.png

SystemServiceManager启动的地方

image.png

7.2. SM.addService方式

这里以InputManagerService服务为例, 说明这类服务的启动方式:

inputManager = new InputManagerService(context, null); //先创建服务对象
ServiceManager.addService(Context.INPUT_SERVICE, inputManager); //[见小节2.1]

7.2.1 SM.addService

[-> ServiceManager.java]

public static void addService(String name, IBinder service) {
     try {
          //
         getIServiceManager().addService(name, service, false);
         
         } catch (RemoteException e) {
         Log.e(TAG, "error in addService", e);
         }
}

7.2.2 SM.getIServiceManager

private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
//【见2.2.1】
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
return sServiceManager;
}

采用了单例模式获取ServiceManager getIServiceManager()返回的是ServiceManagerProxy(简称SMP)对象.

其中BinderInternal.getContextObject(), 等价于new BpBinder(0), handle=0意味着指向的是远程进程/system/bin/servicemanager中的ServiceManager服务.

7.2.2.1 asInterface

public abstract class ServiceManagerNative extends Binder implements IServiceManager {
​
 static public IServiceManager asInterface(IBinder obj) {
 if (obj == null) {
 return null;
 }
 IServiceManager in =
 (IServiceManager)obj.queryLocalInterface(descriptor);
 if (in != null) {
 return in;
 }
 //创建ServiceManagerProxy对象[见小节2.2.2]
 return new ServiceManagerProxy(obj);
 }
}

7.2.2.2 ServiceManagerProxy创建

class ServiceManagerProxy implements IServiceManager {
 private IBinder mRemote;

 public ServiceManagerProxy(IBinder remote) {
 mRemote = remote;
 }
 ...
}

可见, getIServiceManager()过程是获取一个用于跟远程ServiceManager服务(这个用于管理所有binder服务的大管家)进行通信的binder代理端.

7.2.3 SMP.addService

public void addService(String name, IBinder service, boolean allowIsolated) throws RemoteException {
 Parcel data = Parcel.obtain();
 Parcel reply = Parcel.obtain();
 data.writeInterfaceToken(IServiceManager.descriptor);
 data.writeString(name);
 data.writeStrongBinder(service);
 data.writeInt(allowIsolated ? 1 : 0);
 mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
 reply.recycle();
 data.recycle();
}

通过mRemote向将ADD_SERVICE_TRANSACTION的事件发送给ServiceManager. .

7.3. SSM.startService方式

通过这种方式启动的服务,有一个特点都是继承于SystemService对象, 这里以PowerManagerService为例来说明:

mSystemServiceManager = new SystemServiceManager(mSystemContext); 
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);

7.3.1 SSM初始化

public class SystemServiceManager {
 private final Context mContext;

 //接收lifecycle事件的服务
 private final ArrayList<SystemService> mServices = new ArrayList<SystemService>();

 public SystemServiceManager(Context context) {
 mContext = context;
 }

}

mSystemServiceManager只会创建一次,后续其他服务通过该方式启动,直接调用其startService()方法即可。

7.3.2 SSM.startService

public <T extends SystemService> T startService(Class<T> serviceClass) {
    final String name = serviceClass.getName();

    //保证要启动的服务是继承于SystemService,否则抛出异常
    if (!SystemService.class.isAssignableFrom(serviceClass)) {
        throw new RuntimeException(...);
    }

    final T service;
    try {
        Constructor<T> constructor = serviceClass.getConstructor(Context.class);
        //通过反射创建目标服务类的对象
        service = constructor.newInstance(mContext);
    } catch (Exception ex) {
        ...
    }
    //将该服务添加到mServices
    mServices.add(service);

    try {
        //执行服务的onStart过程 
        service.onStart();
    } catch (RuntimeException ex) {
        ...
    }
    return service;
}

mSystemServiceManager.startService(xxx.class) 功能主要:

  1. 创建xxx类的对象,执行该对象的构造函数;

  2. 将该对象添加到mSystemServiceManager的成员变量mServices;

  3. 调用该对象的onStart();

看到这并没有看到服务是如何注册到ServiceManager, 这里继续以PowerManagerService为例,其实是在onStart()完成.

7.3.2.1 onStart

public void onStart() {
    //[见小节3.2.2]
    publishBinderService(Context.POWER_SERVICE, new BinderService());
    publishLocalService(PowerManagerInternal.class, new LocalService());

    Watchdog.getInstance().addMonitor(this);
    Watchdog.getInstance().addThread(mHandler);
}

PowerManagerService定义了一个内部类BinderService, 继承于IPowerManager.Stub服务. 再调用publishBinderService来注册服务.

7.3.2.2 publishBinderService

public abstract class SystemService {
    protected final void publishBinderService(String name, IBinder service) {
        publishBinderService(name, service, false);
    }

    protected final void publishBinderService(String name, IBinder service, boolean allowIsolated) {
        ServiceManager.addService(name, service, allowIsolated);
    }
}

到此可见, 采用该方式真正注册服务的过程,同样也是采用ServiceManager.addService方式.

通过这种方式启动的服务, 都是继承于SystemService类, 那么这种方式启动的服务有什么特殊之处吗? 答应就是startBootPhase的过程:

7.3.3 SSM.startBootPhase

public void startBootPhase(final int phase) {
    mCurrentPhase = phase;

    final int serviceLen = mServices.size();
    for (int i = 0; i < serviceLen; i++) {
        final SystemService service = mServices.get(i);
        try {
            service.onBootPhase(mCurrentPhase);
        } catch (Exception ex) {
            ...
    }
}

所有通过该方式注册的继承于SystemService的服务,都会被添加到mServices. 该方法会根据当前系统启动到不同的阶段, 则回调所有服务onBootPhase()方法

  • BootPhase

系统开机启动过程, 当执行到system_server进程时, 将启动过程划分了几个阶段, 定义在SystemService.java文件

public static final int PHASE_WAIT_FOR_DEFAULT_DISPLAY = 100; 
public static final int PHASE_LOCK_SETTINGS_READY = 480;
public static final int PHASE_SYSTEM_SERVICES_READY = 500;
public static final int PHASE_ACTIVITY_MANAGER_READY = 550;
public static final int PHASE_THIRD_PARTY_APPS_CAN_START = 600;
public static final int PHASE_BOOT_COMPLETED = 1000;

这些阶段跟系统服务大致的顺序图,如下:

image.png

PHASE_BOOT_COMPLETED=1000,该阶段是发生在Boot完成和home应用启动完毕, 对于系统服务更倾向于监听该阶段,而非监听广播ACTION_BOOT_COMPLETED

7.4. 总结

方式1. ServiceManager.addService():

  • 功能:向ServiceManager注册该服务.

  • 特点:服务往往直接或间接继承于Binder服务;

  • 举例:input, window, package;

方式2. SystemServiceManager.startService:

  • 功能:

    • 创建服务对象;

    • 执行该服务的onStart()方法;该方法会执行上面的SM.addService();

    • 根据启动到不同的阶段会回调onBootPhase()方法;

    • 另外,还有多用户模式下用户状态的改变也会有回调方法;例如onStartUser();

  • 特点:服务往往自身或内部类继承于SystemService;

  • 举例:power, activity;

两种方式真正注册服务的过程都会调用到ServiceManager.addService()方法. 对于方式2多了一个服务对象创建以及 根据不同启动阶段采用不同的动作的过程。可以理解为方式2比方式1的功能更丰富。

8 参考

https://www.jianshu.com/p/2afddb959b67
https://www.jianshu.com/p/f2afa66f1547
https://www.jianshu.com/p/033e6a9a3d7c

相关文章

网友评论

    本文标题:12 PackageManagerService

    本文链接:https://www.haomeiwen.com/subject/jghjyktx.html