文档章节

创建窗口的过程涉及的 IPC (Binder)

lightUp
 lightUp
发布于 2016/04/13 14:37
字数 837
阅读 36
收藏 0

[ContextImpl](https://github.com/ziv-zh/platform_frameworks_base/blob/master/core/java/android/app/ContextImpl.java  )

 

[ActivityThread] (https://github.com/ziv-zh/platform_frameworks_base/blob/master/core/java/android/app/ContextImpl.java )

 

Binder 相关

[IBinder](https://github.com/ziv-zh/platform_frameworks_base/blob/master/core/java/android/os/IBinder.java ) binder 服务端(Stub)要实现的

 

[Binder](https://github.com/ziv-zh/platform_frameworks_base/blob/master/core/java/android/os/Binder.java )默认的 binder 服务端实现

 

[IInterface](https://github.com/ziv-zh/platform_frameworks_base/blob/master/core/java/android/os/IInterface.java )binder 客户端(proxy)要实现的,一般 aidl 自动生成

 

关于 token:

token 都是 IBinder 对象,用于 IPC ;

 

1,Activity(和 Window,如果 window 对象关联了一个 activity 的话) 中的 token 是由 AmS 创建的 ActivityRecord,用于 activity 通知 AmS 状态变化;

 

2,ViewRoot 的 W 对象 mWindow,是有 ViewRoot 创建的,传递给 WmS,用于 WmS 通知 ViewRoot 状态变化:

WmS --> mWindow(Binder) --> mHandler(ViewRootHandler), 移步下面 " ViewRootImpl 的 mWindow 是如何传递给 WmS 的"

 

3,各种 XXXManager(比如WindowManager、ActivityManager)是一种 service 的封装,内部有对应service 的 Binder 对象;

 

 

[IWindow.aidl]: https://github.com/android/platform_frameworks_base/blob/master/core/java/android/view/IWindow.aidl  API back to a client window that the Window Manager uses to inform it of interesting things happening.

[IWindowSession.aidl] https://github.com/android/platform_frameworks_base/blob/master/core/java/android/view/IWindow.aidl  System private per-application interface to the window manager.

 

 

 ViewRootImpl 的mWindow(W,Binder 的子类) 是如何传递给 WmS 的

1,Activity 创建完会创建 Window,并给 window 设置 contentView,这个过程中会创建 decorView;

2,Activity 准备好通知 AmS,AmS 判断状态后最终调用 Activity 的 makeVisible(..),此方法中调用 WindowManager(会调用WindowManagerGlobal的 addView) 的 addView(..)展示 view;

3,在 addView 方法中进行检查并并创建 ViewRootImpl 对象,最终调用 ViewRootImpl 的 setView 方法,在此方法中会把 mWindow 这个 binder  通过 mWindowSession 注册给 WmS;

 

ps: mWindowSession 是 WmS 提供的一个 Binder 对象(所以使用时要处理 RemoteException),从 WindowManagerGlobal 的方法中可以看出;

ps: mAttachInfo 是在 ViewRootImpl 的构造方法中创建的,并在 setView 方法中设置一些其他的变量(比如 mRootView),

并且在 ViewRootImpl 的 'void dispatchAttachedToWindow(AttachInfo info, int visibility)' 方法把 mAttatchedInfo 传递给 view;

 

ViewRootImpl.java:

final IWindowSession mWindowSession;
...
final W mWindow;
...
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
    synchronized (this) {
    ...
    try {
        mOrigWindowType = mWindowAttributes.type;
        mAttachInfo.mRecomputeGlobalAttributes = true;
        collectViewAttributes();
        res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                getHostVisibility(), mDisplay.getDisplayId(),
                mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                mAttachInfo.mOutsets, mInputChannel);
    } catch (RemoteException e) {
    ...
    
}

 

WindowManagerGlobal.java:

    ...
    
    public static IWindowManager getWindowManagerService() {
        synchronized (WindowManagerGlobal.class) {
            if (sWindowManagerService == null) {
                sWindowManagerService = IWindowManager.Stub.asInterface(
                        ServiceManager.getService("window"));
                try {
                    sWindowManagerService = getWindowManagerService();
                    ValueAnimator.setDurationScale(sWindowManagerService.getCurrentAnimatorScale());
                } catch (RemoteException e) {
                    Log.e(TAG, "Failed to get WindowManagerService, cannot set animator scale", e);
                }
            }
            return sWindowManagerService;
        }
    }
    
    public static IWindowSession getWindowSession() {
        synchronized (WindowManagerGlobal.class) {
            if (sWindowSession == null) {
                try {
                    InputMethodManager imm = InputMethodManager.getInstance();
                    IWindowManager windowManager = getWindowManagerService();
                    sWindowSession = windowManager.openSession(
                            new IWindowSessionCallback.Stub() {
                                @Override
                                public void onAnimatorScaleChanged(float scale) {
                                    ValueAnimator.setDurationScale(scale);
                                }
                            },
                            imm.getClient(), imm.getInputContext());
                } catch (RemoteException e) {
                    Log.e(TAG, "Failed to open window session", e);
                }
            }
            return sWindowSession;
        }
    }
   
    
    public void addView(View view, ViewGroup.LayoutParams params,
        Display display, Window parentWindow) {
            ...
        
            final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
            if (parentWindow != null) {
                parentWindow.adjustLayoutParamsForSubWindow(wparams);
            } else {
                // If there's no parent, then hardware acceleration for this view is
                // set from the application's hardware acceleration setting.
                final Context context = view.getContext();
                if (context != null
                        && (context.getApplicationInfo().flags
                                & ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
                    wparams.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
                }
            }
        
            ViewRootImpl root;
            View panelParentView = null;
        
            synchronized (mLock) {
                // Start watching for system property changes.
                if (mSystemPropertyUpdater == null) {
                    mSystemPropertyUpdater = new Runnable() {
                        @Override public void run() {
                            synchronized (mLock) {
                                for (int i = mRoots.size() - 1; i >= 0; --i) {
                                    mRoots.get(i).loadSystemProperties();
                                }
                            }
                        }
                    };
                    SystemProperties.addChangeCallback(mSystemPropertyUpdater);
                }
        
                int index = findViewLocked(view, false);
                if (index >= 0) {
                    if (mDyingViews.contains(view)) {
                        // Don't wait for MSG_DIE to make it's way through root's queue.
                        mRoots.get(index).doDie();
                    } else {
                        throw new IllegalStateException("View " + view
                                + " has already been added to the window manager.");
                    }
                    // The previous removeView() had not completed executing. Now it has.
                }
        
                // If this is a panel window, then find the window it is being
                // attached to for future reference.
                if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
                        wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
                    final int count = mViews.size();
                    for (int i = 0; i < count; i++) {
                        if (mRoots.get(i).mWindow.asBinder() == wparams.token) {
                            panelParentView = mViews.get(i);
                        }
                    }
                }
        
                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);
            } catch (RuntimeException e) {
                // BadTokenException or InvalidDisplayException, clean up.
                synchronized (mLock) {
                    final int index = findViewLocked(view, false);
                    if (index >= 0) {
                        removeViewLocked(index, true);
                    }
                }
                throw e;
            }
    }
    
    ...

 

© 著作权归作者所有

共有 人打赏支持
lightUp
粉丝 10
博文 242
码字总数 287936
作品 0
杭州
程序员
私信 提问
我眼中的Android Framework

在开发中我们会遇到各种各样的非常奇怪的问题,有些问题是百思不得骑姐。其实这些问题大都是因为我们不了解安卓内部运行原理,知其所以然才是我们的目的。—前言 任何控制类程序都有一个入口...

墨镜猫
2017/01/05
0
0
Android 通信篇 -- 深入剖析Binder原理

Binder 概述 Binder 是一种进程间通信机制,基于开源的 OpenBinder 实现;OpenBinder 起初由 Be Inc. 开发,后由 Plam Inc. 接手。从字面上来解释 Binder 有胶水、粘合剂的意思,顾名思义就是...

DeepCoder_Marco
2018/09/05
0
0
Android窗口系统第二篇---Window的添加过程

以前写过客户端Window的创建过程,大概是这样子的。我们一开始从Thread中的handleLaunchActivity方法开始分析,首先加载Activity的字节码文件,利用反射的方式创建一个Activity对象,调用Act...

LooperJing
2017/11/08
0
0
Android进程间通信机制Binder应用层分析

概述 学姐今天复习了下Android进程间通信方式,打算从基本概念、使用原因、基本使用、原理分析几个方面来讲讲。 想要对进程间通信方式有个相对全面的了解,就先从几个比较重要的概念IPC、AID...

xingjm8511
2016/06/23
44
0
安卓framework开发的初理解

概述 其实我们写的App并不是一个完整的程序。我们写的只是一个套件组,就是一堆Activity,Service等等的组件。这个套件组给Framework框架组合在一起才是一个完整的程序。在这里先说一个概念,...

天王盖地虎626
01/11
0
0

没有更多内容

加载失败,请刷新页面

加载更多

centos7 安装maven

进入指定目录 cd /usr/local/src/ 下载maven 包 # 打开这个地址选中自己需要的版本补齐后面的地址,再复制到SSH去执行wget http://mirrors.hust.edu.cn/apache/maven/maven-3/ 解压改名 ...

Elson
23分钟前
3
0
推荐一个开源数据库迁移神器SQLines

Windows64位版 SQLines提供开源工具,帮助你在数据库之间,传输数据,转换数据库schema (DDL),视图,存储过程,包,函数,触发器,查询,SQL脚本,嵌入式SQL和数据库API 链接: https://pan...

Benz001
25分钟前
9
0
面试前必知Redis面试题—缓存雪崩+穿透+缓存与数据库双写一致问题

今天来分享一下Redis几道常见的面试题: 如何解决缓存雪崩? 如何解决缓存穿透? 如何保证缓存与数据库双写时一致的问题? 一、缓存雪崩 1.1什么是缓存雪崩? 回顾一下我们为什么要用缓存(Re...

我最喜欢三大框架
26分钟前
3
0
composer 很慢怎么办?

关于 Composer 的详细安装使用,详见之前的文章:在 PHP 中安装、使用 Composer 包管理工具 Composer 在国内不管是更新还是安装等都有一个「慢」的问题,有的时候真的很煎熬。 因此我们一般会...

whoru
39分钟前
2
0
ffmpeg提取音频文件

问题 从特定的mp3音频文件中,提取一部分作为新的mp3文件 ffmpeg ffmpeg -i a.mp3 -ss 00:25:00 -to 00:28:20 -acodec copy b.mp3 -i输入的文件 -ss从指定时间点开始提取 -to到指定时间点结...

亚林瓜子
47分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部