Android 窗口管理 - 窗口添加过程分析Client端

一、窗口的三种形式

  1. Activity:独立的页面窗口,拥有完整生命周期。这种是最常用的方式。
  2. Dialog:对话框形式的窗口,依赖Activity上下文。
java 复制代码
Dialog dlg = new Dialog(context);
dlg.addContentView(makeView(), new LayoutParams(300, 400));
dlg.setCancelable(true);
dlg.setCanceledOnTouchOutside(true);
dlg.setOnDismissListener(new DialogInterface.OnDismissListener() {
    @Override
    public void onDismiss(DialogInterface dialog) {
        Looper.myLooper().quit();
    }
});
dlg.setTitle("Not Looper.getMainLooper() check");
dlg.show();

3.View:通过WindowManager.addView直接添加到系统中。系统中有很多窗口就是通过这种方式添加到系统中的。比如状态栏,虚拟导航条,小圆点啥的。第三方app也可以通过这种方式添加浮动窗口。

二、核心接口

  1. App获取IWindowManager接口

    WindowManager是接口类, WindowManagerImpl是WindowManager的实现。WindowManagerGlobal相当于WindowManagerImpl内部的代理,它才是真正和WMS通过IWindowManager通信的类。获取IWindowManager的代码如下:

csharp 复制代码
WindowManagerGlobal.java

public static IWindowManager getWindowManagerService() {
    synchronized (WindowManagerGlobal.class) {
        if (sWindowManagerService == null) {
            sWindowManagerService = IWindowManager.Stub.asInterface(
                    ServiceManager.getService("window"));
            try {
                if (sWindowManagerService != null) {
                    ValueAnimator.setDurationScale(
                            sWindowManagerService.getCurrentAnimatorScale());
                    sUseBLASTAdapter = sWindowManagerService.useBLAST();
                }
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
        return sWindowManagerService;
    }
}
  1. App获取IWindowSession接口

    每个 App 进程都有一个公用的 IWindowSession,保存在 WindowManagerGlobal 中。可通过 adb shell dumpsys window s 查看所有 session,获取代码如下:

java 复制代码
    WindowManagerGlobal.java

    @UnsupportedAppUsage
    public static IWindowSession getWindowSession() {
        synchronized (WindowManagerGlobal.class) {
            if (sWindowSession == null) {
                try {
                    // Emulate the legacy behavior.  The global instance of InputMethodManager
                    // was instantiated here.
                    // TODO(b/116157766): Remove this hack after cleaning up @UnsupportedAppUsage
                    InputMethodManager.ensureDefaultInstanceForDefaultDisplayIfNecessary();
                    IWindowManager windowManager = getWindowManagerService();
                    sWindowSession = windowManager.openSession(
                            new IWindowSessionCallback.Stub() {
                                @Override
                                public void onAnimatorScaleChanged(float scale) {
                                    ValueAnimator.setDurationScale(scale);
                                }
                            });
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            }
            return sWindowSession;
        }
    }
  1. 窗口添加的核心实现

    窗口添加通过 IWindowSessionaddView 接口完成。添加时,App 需向 WMS 提供 IWindow 接口,使 WMS 能通过该接口通知 App 窗口状态的变化。

graph LR subgraph System_Server; WMS; end; subgraph App; View; Activity; Dialog; end; App --IWindowManager--> WMS; App --IWindowSession--> WMS; WMS --IWindow--> View;

从上图可以看出,App(client端)和WMS(Server端)双向通信通道建立完成。

三、窗口添加完整流程

  1. 以 addView 添加 View 为例
sequenceDiagram App->>Context: getSystemService Context->>SystemServiceRegistry:getSystemService: SystemServiceRegistry->>CachedServiceFetcher:getService CachedServiceFetcher->>WindowManagerImpl:new App->>WindowManagerImpl:addView WindowManagerImpl->>WindowManagerGlobal: addView WindowManagerGlobal->>WindowManagerGlobal:getWindowSession WindowManagerGlobal->>ViewRootImpl: new ViewRootImpl() ViewRootImpl->>ViewRootImpl: new IWindow() WindowManagerGlobal->>ViewRootImpl: setView ViewRootImpl->>IWindowSession: addToDisplayAsUser

addToDisplayAsUser通过bind调用到WMS完成了窗口的添加。

  1. Dialog 和 Activity 的窗口添加

    Dialog 和 Activity 的窗口添加流程稍复杂,二者均对应一个 Window 实例。Window 是对窗口公共属性(如标题、背景、菜单等)的抽象,PhoneWindow 是其具体实现。PhoneWindow 包含核心的 DecorView,而 DecorView 正是通过 WindowManager.addView 添加的 View。PhoneWindow 调用 generateDecor 时,会根据主题和特性加载不同的布局与属性。

sequenceDiagram Activity->>Activity: attach Activity->>PhoneWindow: new Activity->>PhoneWindow: setContentView ActivityThread->>Activity: handleResumeActivity Activity->>PhoneWindow: getDectorView PhoneWindow->>PhoneWindow: installDector PhoneWindow->>PhoneWindow: generateDecor Activity->>Activity: makeVisible Activity->>WindowManagerImpl: addView

WindowManagerImpl.addView 之后的流程与前文 addView 方式一致。

备注:以上代码分析以Android 14代码为准

相关推荐
千里马学框架1 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台1 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone1 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc1 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo1 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077001 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼1 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone1 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen1 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone1 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui