Android中APP、AMS、WMS的Binder IPC

APP、AMS、WMS的IPC是一个极其值得深入研究的过程。下面通过非常常见的startActivity来解析APP、AMS、WMS进程之间的通信过程。

1.startActivity Binder IPC流程图

Android中APP、AMS、WMS的Binder IPC_第1张图片
ServiceManager,AMS,WMS,SurfaceFlinger都是android系统服务,在前面《从底层看android5.0启动过程》一文中已经解析过,不清楚的可先浏览该文章。在android系统启动完毕后,这些系统服务也随之开启了。

2.APP与AMS间的Binder IPC

2.1.APP启动Activity

当APP内部Activity.startActivity(),当启动一个Activity,APP需要和AMS通信,所以APP需要向ServiceManager查询AMS的Binder引用。下面分析关键源码体会该过程,Activity.startActivity()主线程经过辗转最终调用Instrumentation.execStartActivity(),其关键源码如下

public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
            //获取AMS引用并调用AMS.startActiviy()
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
        }
        return null;
    }

2.2.APP获取AMS的Binder引用

APP主线程执行ActivityManagerNative.getDefault()获取的就是一个AMS的Binder引用,其关键源码如下

public abstract class ActivityManagerNative extends Binder implements IActivityManager {
//...
 private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            //向ServiceManager获取AMS的Binder引用
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            //类型转换,如果是本进程的其他类获取Binder引用,则不需要通过Binder Driver可直 //接获得Binder引用,得到的IActivityManager是AMS
            //如果是其他进程,得到的IActivityManager是ActivityManagerProxy,双方
            //通过Binder Driver通信
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };
//...

ActivityManagerNative只是一个抽象类,IActivityManager接口实际上是由ActivityManagerNative子类AMS实现的。
上一篇文章《AMS管理四大组件》已经解析过AMS向ServiceManager登记了“域名”为“activity”的Binder。因此上述的逻辑主要是获取AMS的Binder引用,由于是不同进程间通信,asInterface转化为ActivityManagerProxy类型,ActivityManagerProxy.startActvity通过Binder Driver作为中介,最终调用的是AMS.startActvity.

2.3.AMS启动Activity

接下来由AMS线程执行AMS.startActivity(),其主要源码如下

public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {

        public final int startActivity(...) {
        return startActivityAsUser(...);
    }
}

2.4.APP的ActivityThread启动Activity

最终辗转执行ActivityThread.startActivity()。Activity分别经历onCreate->onStart->onResume三个状态迁移。其中onResume是当界面即将可见时才调用。

3.APP与WMS间的Binder IPC

3.1.应用窗口添加到系统

在handleResumeActivity阶段会把应用窗口添加到系统,首先会对窗口设置一系列的属性,最终调用WindowMangerImpl.addView()把DecorView添加到系统中,主要源码如下

final void handleResumeActivity(IBinder token,
            boolean clearHide, boolean isForward, boolean reallyResume) {
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();
        mSomeActivitiesChanged = true;

        // 这个函数最终将调用Activity.onResume
        ActivityClientRecord r = performResumeActivity(token, clearHide);
        //...
        if (r.window == null && !a.mFinished && willBeVisible) {
                r.window = r.activity.getWindow();
                //DecorView是Activity整棵View树的最外围
                View decor = r.window.getDecorView();
                decor.setVisibility(View.INVISIBLE);
                //得到的是WindowMangerImpl对象
                ViewManager wm = a.getWindowManager();
                //获取窗口属性
                WindowManager.LayoutParams l = r.window.getAttributes();
                a.mDecor = decor;
                //窗口类型
                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
                l.softInputMode |= forwardBit;
                if (a.mVisibleFromClient) {
                    a.mWindowAdded = true;
                    wm.addView(decor, l);//将窗口添加到WMS中
                }
       //...

主线程ActivityThread执行WindowMangerImpl.addView(),这个过程肯定也会涉及到Binder IPC,下面重点分析。

3.2.ViewRootImpl是整棵View树和WMS的中介

Android中APP、AMS、WMS的Binder IPC_第2张图片
WindowMangerImpl其实仅仅是WindowManagerGlobal的一个代理类,而且WindowManagerGlobal是一个全局单例对象存在着,UI主线程执行WindowManagerGlobal.addView()方法,会创建一个ViewRootImpl对象作为中介,ViewRootImpl就是应用程序和WMS 的Binder IPC关键,其源码如下

 public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow) {
             ViewRootImpl root;
        View panelParentView = null;

       //...
        root = new ViewRootImpl(view.getContext(), display);

        view.setLayoutParams(wparams);
        mViews.add(view);
        mRoots.add(root);
        mParams.add(wparams);     
        // do this last because it fires off messages to start doing things
        try {
            root.setView(view, wparams, panelParentView);
        //...
     }

3.3.追踪APP主线程获取的WMS的引用

ViewRootImpl构造函数会调用getWindowSession(),getWindowSession()通过getWindowManagerService()获取到了WMS对象,因此可以确定APP主线程获取的WMS的Binder引用是在getWindowManagerService()方法中,在该方法中,调用ServiceManager.getService(“window”),来获取域名为“window”的Bindr引用,也就是WMS的引用。获取到WMS的引用后,会打开一个Seesion连接,用于APP进程和WMS进程之间的通信。在其关键源码如下

 public ViewRootImpl(Context context, Display display) {
        mContext = context;
        //打开一个Seesion,用于于WMS连接
        mWindowSession = WindowManagerGlobal.getWindowSession();
 }

 public static IWindowSession getWindowSession() {
        synchronized (WindowManagerGlobal.class) {
            if (sWindowSession == null) {
                try {
                    InputMethodManager imm = InputMethodManager.getInstance();
                    //获取WindowManagerService
                    IWindowManager windowManager = getWindowManagerService();
                    //打开一个Session连接,用于与WMS连接
                    sWindowSession = windowManager.openSession(
                            new IWindowSessionCallback.Stub() {
                                @Override
                                public void onAnimatorScaleChanged(float scale) {
                                    ValueAnimator.setDurationScale(scale);
                                }
                            },
                            imm.getClient(), imm.getInputContext());
                    ValueAnimator.setDurationScale(windowManager.getCurrentAnimatorScale());
                } catch (RemoteException e) {
                    Log.e(TAG, "Failed to open window session", e);
                }
            }
            return sWindowSession;
        }
    }

public static IWindowManager getWindowManagerService() {
        synchronized (WindowManagerGlobal.class) {
            if (sWindowManagerService == null) {
                sWindowManagerService = IWindowManager.Stub.asInterface(
                        ServiceManager.getService("window"));
            }
            return sWindowManagerService;
        }
    }

4.4.session会话addWindow

ViewRootImpl.setView利用Session来发起一个添加窗口的服务,在Session的addToDisplay方法中,通过AMS.addWindow正式发起添加窗口的服务请求。其源码如下

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
  //调用Session接口
  res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(),
                            mAttachInfo.mContentInsets, mInputChannel);    
}
final class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {  

public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
            int viewVisibility, int displayId, Rect outContentInsets,
            InputChannel outInputChannel) {
        return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
                outContentInsets, outInputChannel);
    }

}

addWindow会对该窗口进行权限检查,判断窗口类型,调整窗口属性以及分配层机值等操作,最终由“摄像机”SurfaceFlinger捕抓当前画面,然后真实地呈现给观众。

你可能感兴趣的:(源码,android)