Android开发经验谈Android技术知识Android开发

AMS架构设计和源码分析

2020-07-28  本文已影响0人  Joker_Wan

1 AMS简介

1.1 什么是AMS

AMS(ActivityManagerService)是系统的引导服务,应用进程的启动、切换和调度、四大组件的启动和管理都需要AMS的支持。


1.2 组件与AMS的通信方式

Activity 调用 AMS 代理对象 ActivityManagerProxy 通过 Bander 机制与 ActivityManagerNative 通信,ActivityManagerNative 继续调用其子类 ActivityManagerService 完成通信。为何要用 Bander 机制通信呢?因为 Activity 和 ActivityManagerProxy 都在 App进程,而ActivityManagerNative 和 ActivityManagerService 在 AMS进程(系统进程),这里涉及到两个进程之间的通信。

1.3 AMS体系化关系图

AMP(ActivityManagerProxy) 与 AMN(ActivityManagerNative) 实现了远程代理模式:AMP 和 AMN 是运行在两个进程的,AMP 是 Client 端,AMN 则是 Server 端,而 Server 端中具体的功能都是由 AMN 的子类 AMS 来实现的。AMN 又实现了 Binder 类,这样 AMP 和 AMS 就可以通过Binder来进行进程间通信。

ActivityManager是一个和 AMS 相关联的类,它主要对运行中的 Activity 进行管理,这些管理工作并不是由 ActivityManager 来处理的,而是交由 AMS 来处理,ActivityManager 中的方法会通过 AMN 的 getDefault 方法来得到 AMP ,通过 AMP 就可以和 AMN 进行通信,而 AMN 是一个抽象类,它会将功能交由它的子类 AMS 来处理,因此,AMP 就是 AMS 的代理类。除了ActivityManager,其他想要与 AMS 进行通信的类都需要通过 AMP,如下图所示:

2 AMS-startService源码分析(基于 Android 7.0 源码)

发起进程调用AMP-startService,经过binder驱动,最终调用系统进程AMS-startService,详细过程如下图:

一般我们在 Activity 中启动一个服务代码如下

startService(Intent(this,TestService::class.java))

查看startService的实现,发现调用的是 ContextWrapper 中的 startService 方法

public class ContextWrapper extends Context {

    @UnsupportedAppUsage
    Context mBase;

    public ContextWrapper(Context base) {
        mBase = base;
    }
    
    ...

    @Override
    public ComponentName startService(Intent service) {
        return mBase.startService(service);
    }
    
    ...
}

ContextWrapper 中的 startService 方法调用 mBase的 startService 方法,那么mBase是什么呢,mBase 是同样继承 Context 的 ContextImpl类,可以看出这里用到了装饰者模式,调用方只需要关注ContextWrapper类,并不需要关注 ContextImpl 类的 startService 的具体实现,当ContextImpl 类的 startService 实现改动时对调用 ContextWrapper 中的 startService 的类是无感知的,并不需要改动调用方的代码。

继续跟进 ContextImpl 的 startService 代码

    public ComponentName startService(Intent service) {
        warnIfCallingFromSystemProcess();
        return startServiceCommon(service, false, mUser);
    }

其中又调用了 startServiceCommon(service, false, mUser)

    private ComponentName startServiceCommon(Intent service, UserHandle user) {
        try {
        
            // 省略部分代码...
            
            ComponentName cn = ActivityManagerNative.getDefault().startService(
                mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                            getContentResolver()), getOpPackageName(), user.getIdentifier());
                            
            // 省略部分代码...
            
            return cn;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

startServiceCommon 方法中会调用 AMN 的 getDefault 来获取 AMS 的代理类 AMP。接着调用了 AMP 的 startService 方法,先来查看 AMN 的getDefault方法

 static public IActivityManager getDefault() {
        return gDefault.get();
    }
    private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            // 注释1
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            // 注释2
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }+
    };
}

getDefault 方法调用了gDefault的 get 方法,gDefault 是一个Singleton类。注释1处得到名为activity的 Service 引用,也就是IBinder 类型的 AMS 的引用。接着在注释2处将它封装成 AMP 类型对象,并将它保存到 gDefault 中,此后调用 AMN 的 getDefault 方法就会直接获得 AMS 的代理对象 AMP。asInterface 方法实现如下

static public IActivityManager asInterface(IBinder obj) {
    if (obj == null) {
        return null;
    }
    IActivityManager in =
        (IActivityManager)obj.queryLocalInterface(descriptor);
    if (in != null) {
        return in;
    }
    return new ActivityManagerProxy(obj);
}

我们继续看下 AMP 的构造方法

class ActivityManagerProxy implements IActivityManager {

    public ActivityManagerProxy(IBinder remote) {
        mRemote = remote;
    }
    
    // 省略部分代码...
 }
 

AMP 的构造方法中将 AMS 的引用赋值给变量mRemote ,这样在 AMP 中就可以使用 AMS 了。其中 IActivityManager 是一个接口,AMN 和 AMP 都实现了这个接口,用于实现代理模式和 Binder 通信。接着继续看 AMP 的 startService 方法

    public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, String callingPackage, int userId) throws RemoteException
    {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        service.writeToParcel(data, 0);
        data.writeString(resolvedType);
        data.writeString(callingPackage);
        data.writeInt(userId);
        // 注释1
        mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);
        reply.readException();
        ComponentName res = ComponentName.readFromParcel(reply);
        data.recycle();
        reply.recycle();
        return res;
    }

首先会将传入的参数写入到 Parcel 类型的 data 中。在注释1处,通过IBinder 类型对象 mRemote(AMS的引用)向服务端的 AMS 发送一个START_SERVICE_TRANSACTION 类型的进程间通信请求。那么服务端AMS就会从 Binder 线程池中读取我们客户端发来的数据,最终会调用 AMN 的onTransact 方法

   @Override
   public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
           throws RemoteException {
       switch (code) {
       
       // 省略部分代码...
       
       case START_SERVICE_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            IBinder b = data.readStrongBinder();
            IApplicationThread app = ApplicationThreadNative.asInterface(b);
            Intent service = Intent.CREATOR.createFromParcel(data);
            String resolvedType = data.readString();
            String callingPackage = data.readString();
            int userId = data.readInt();
            // 注释1
            ComponentName cn = startService(app, service, resolvedType, callingPackage, userId);
            reply.writeNoException();
            ComponentName.writeToParcel(cn, reply);
            return true;
        }
        
        // 省略部分代码...
   }

onTransact中注释1处会调用 AMS 的 startService 方法

    public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, String callingPackage, int userId)
            throws TransactionTooLargeException {
        
        // 省略部分代码...

        if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
                "startService: " + service + " type=" + resolvedType);
        synchronized(this) {
        
            // 省略部分代码...
        
            ComponentName res = mServices.startServiceLocked(caller, service,
                    resolvedType, callingPid, callingUid, callingPackage, userId);
            Binder.restoreCallingIdentity(origId);
            return res;
        }
    }

后面就是 AMS 处理 startService 的内容了,这里暂不讲解,有兴趣的同学可以继续深入。

上一篇下一篇

猜你喜欢

热点阅读