AMS架构设计和源码分析

作者: Joker_Wan | 来源:发表于2020-07-28 18:22 被阅读0次

    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体系化关系图

    • IActivityManager 继承 IInterface
    • Binder 继承 IBinder
    • ActivityManagerService 继承 ActivityManagerNative
    • ActivityManagerProxy 是抽象类 ActivityManagerNative 的内部类,ActivityManagerProxy 与抽象类 ActivityManagerNative 都实现IActivityManager

    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 的内容了,这里暂不讲解,有兴趣的同学可以继续深入。

    相关文章

      网友评论

        本文标题:AMS架构设计和源码分析

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