侧边栏壁纸
博主头像
慢行的骑兵博主等级

贪多嚼不烂,欲速则不达

  • 累计撰写 27 篇文章
  • 累计创建 27 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

Pms整体了解

慢行的骑兵
2021-10-25 / 0 评论 / 0 点赞 / 105 阅读 / 2,401 字
  • 之前整理过一篇笔记,是从原理和源码角度来了解pms。该篇笔记是整体了解来梳理一下pms(以了解,应付面试为主);

一.概述

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

01.package_manager_service

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

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

  • Pms的启动过程在之前一篇已经中以及整理过;

1.PMS职责

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

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

2.获取PMS

02.get_pkms

3.Servicemanager

  • 系统中几乎所有的服务获取方式都是通过ServiceManager;
  • 大量的服务是向ServiceManager注册的,注册好之后就可以通过ServiceManager获取;
  • ServiceManager只是一个壳,真正的ServiceManager在c++层;

二.Android系统服务的注册方式

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

  • ServiceManager的addService()
  • SystemServiceManager的startService()

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

03.servicemanager

  • SystemServiceManager启动的地方

04.SystemServer启动

1.SM.addService方式

[-> ServiceManager.java]

public static void addService(String name, IBinder service) {
    try {
        // [见小节1.2 和 1.3]
        getIServiceManager().addService(name, service, false);
    } catch (RemoteException e) {
        Log.e(TAG, "error in addService", e);
    }
}

2 SM.getIServiceManager

[-> ServiceManager.java]

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

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

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

2.1 asInterface

[-> ServiceManagerNative.java]

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]
        return new ServiceManagerProxy(obj);
    }
}

2.2 ServiceManagerProxy创建

[-> ServiceManagerNative.java ::ServiceManagerProxy]

class ServiceManagerProxy implements IServiceManager {
    private IBinder mRemote;
    
    public ServiceManagerProxy(IBinder remote) {
        mRemote = remote;
    }
    ...
}

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

2.3 SMP.addService

[-> ServiceManagerNative.java ::ServiceManagerProxy]

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;

3.SSM.startService方式

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

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

3.1 SSM初始化

[-> SystemServiceManager.java]

public class SystemServiceManager {
    private final Context mContext;
    
    //接收lifecycle事件的服务
    private final ArrayList<SystemService> mServices = new ArrayList<SystemService>();
    
    public SystemServiceManager(Context context) {
        mContext = context;
    }
    
}

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

3.2 SSM.startService

[-> SystemServiceManager.java]

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()完成.

3.2.1 onStart

[-> PowerManagerService.java]

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来注册服务;

3.2.2 publishBinderService

[-> SystemService.java]

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的过程:

3.3 SSM.startBootPhase

[–>SystemServiceManager.java]

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()方法;

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

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

05.system_server_boot_process

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

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的功能更丰富。

  • 这部分内容的学习,大致的流程明白了,对做手机厂商的工作 ,上手会比较快些;

三.Pms的启动过程

  • 了解即可

  • Pms的构造方法非常复杂,大体流程如下

06.pkms_start

四.Apk的安装与卸载

  • 了解即可

1.安装方式

  • 安装系统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

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

2.安装过程

  1. 将app复制到data/app目录下,扫描并解压安装包,并把dex文件(DVM字节码)保存到dalvik-cache目录;
  2. 在data/data目录下创建对应的应用数据目录;
  3. 解析apk的AndroidManifest.xml文;
  4. 显示快捷方式;

07.apk_install1

08.apk_install2

3.卸载

09.apk_delete

五.Apk的打包流程

10.apk_dabao

必须会,非常重要

1.资源打包(通过aapt)形成一个resource目录并且形成一个.R文件;
2.通过java build将.R文件,源码,Aidl(通过aidl的工具生成java文件)产生.class文件;
3.将.class文件经过dex的转换,转换成dex文件;
4.经过apkbuilder程序,把资源(步骤1的)和其它资源混合打成一个apk的包;
5.通过签名,然后才能进行安装;

六.静默安装的大体流程

  • 没啥作用,了解即可,应付面试;

  • 实现方式

    • 参考应用市场的方案,获取PackageManager,调用installPackage方法进行安装;
    • 调用adb服务,调用install命令进行安装;
  • 实现方案注意事项,必须添加sharedUserId=“android.uid.system”,这里就存在一个需要厂家签名(难点,一般人拿不到)文件的问题

    • 方案一需要拷贝源码中的aidl文件和Java类
    • 厂家签名文件是属于机密,比较难获取
  • 智能安装

    • 省略了自己点击确定的步骤,通过辅助服务模拟用户点击来实现智能安装,而vivo和oppo手机还需要输入密码,最终是调用PackageManager的installPackage方法;
0

评论区