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

1.startActivity Binder IPC流程图


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的中介


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捕抓当前画面,然后真实地呈现给观众。

更多相关文章

  1. 自定义圆形进度条的实现方式
  2. Android(安卓)屏幕窗口Log日志调试库 LogcatViewer
  3. Android中通过GPS或NetWork获取当前位置的经纬度
  4. Android异步加载获取网络数据(图片)
  5. Android(安卓)SharedPreferences详解
  6. Android(安卓)LruCache原理及使用(对象软引用不行,使用LRU算法)
  7. Android重学之查漏补缺——Context引起的内存泄露
  8. Android获取CPU,内存,磁盘使用率
  9. Android中接口(Interface)的简单使用

随机推荐

  1. Android传感器的使用总结
  2. Android内存管理机制之一:low memory kill
  3. Android触摸屏事件派发机制详解与源码分
  4. [android]命令行向虚拟机发短信打电话
  5. Android像素单位
  6. android:taskAffinity与android:finishOn
  7. Android使用Itext生成pdf文件
  8. Android实现多行文字的跑马灯效果(Realizi
  9. 奔五的人,准备学习iOS开发
  10. 剑桥大学研究人员称,Android的安全性堪忧