文章目录
- 一、WMS、View体系与SurfaceFlinger的关系
- 二、View体系
-
- 1)View整体框架
- 2)Activity、window、view的关系
- [3)View Tree](#3)View Tree)
- 4)view数据结构
- 5)UI显示的三要素
-
- 1、UI三要素对应的方法
- 2、View的draw方法
- 3、View的画板Surface
- 4、Android原生硬件绘制JAVA示例
- [6)View Animation](#6)View Animation)
- 三、WMS
-
- 1、WMS总体设计
-
- 1)WMS的设计思想
- 2)WMS的对外接口
- 3)WMS的启动与初始化
- 4)WMS的工作方式
- [5)Window Policy](#5)Window Policy)
- 2、窗口的添加过程
- 3、Surface管理
- 4、启动窗口和窗口动画
一、WMS、View体系与SurfaceFlinger的关系

这里的框图重点体现WMS、View和SF这几个主体,不会糅杂太多细节和分支,框架应该如此!
1)WMS是管理者;
2)View是生成者;
3)SF是消费者,也是硬件资源管理者;
WMS、View都属于上层使用者,在Android显示子系统 原理探索中 可以简单了解框架(逻辑的堆砌过于庞大),SF另起篇幅重点介绍。
二、View体系
几乎所有的APK应用程序的UI界面都是由view来描述,
1)View整体框架

1、可以看出View系统主要在JAVA层实现,绘图工具依赖natvie层的图形库;
2)Activity、window、view的关系

1)一个APP有多个Activity(Activity是一个粗略的UI界面显示和处理容器,占整个界面);
2)一个Activity界面有多个大大小小的Window窗口;
3)精细的窗口内容则是view,view才是UI内容真正的生产者,Activity和Window都是布局;
4)View是基本单元,派生出各式各样的图形效果Buttom/Menu/ImageView
/android/frameworks/base/core/java/android/view
/android/frameworks/base/core/java/android/widget/Button.java
/android/frameworks/base/core/java/android/widget/Toolbar.java
/android/frameworks/base/core/java/android/widget/ImageView.java
5)可以看到,Activity/WMS/view主要是JAVA实现,需要用到硬件资源才会进入到natvie;
3)View Tree

1、Android View System最终会构建出这样一个View Tree,记录在DisplayList (HWUI);
2、每一个View内容都应该是单独绘制,当界面需要更新时,只需更新变化的view;
4)view数据结构
View的结构非常庞大,抽取部分UI相关的举例说明
1.View
public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource {
//args
String VIEW_LOG_TAG = "View";
//function
setScrollBarSize(int scrollBarSize);
}
2、Bitmap : 用于存放像素数据(GPU/CPU生产的像素数据),比如Drawable以及它的众多子集
3.Drawable概念
Bitmap文件就可以说是Drawable,也是最简单的Drawable,只有图像数据本身,不带任何附加信息
一般而言,Drawable除了图形数据外,还封装了相关的操作函数-创建、销毁、简单的图形处理、绘制等
4.Drawable
public abstract class Drawable {
public interface Callback {
void invalidateDrawable(@NonNull Drawable who);
void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when);
void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what);
}
}
1、View中的UI属性



2、View的回调接口


3、View.invalidate
使当前UI界面判定无效,从而引起重绘动作,使新绘制的界面生效;

5)UI显示的三要素
UI三要素指的是UI尺寸大小、位置和内容
1、UI三要素对应的方法
1.UI尺寸大小、位置和内容对应的处理方法
/android/frameworks/base/core/java/android/view/ViewRootImpl.java
performMeasure() //计算View对象在UI界面上的绘图区域大小
performLayout() //计算View对象在UI界面上的绘图位置
performDraw() //绘制UI
2.performDraw()
/android/frameworks/base/core/java/android/view/ViewRootImpl.java
--draw(fullRedrawNeeded, usingAsyncReport && mSyncBuffer);
----Surface surface = mSurface; //画板
----mAttachInfo.mThreadedRenderer.invalidateRoot(); //硬件绘制(OpenGLRenderer 即使用GPU绘制)
/android/frameworks/base/core/java/android/view/ThreadedRenderer.java
------draw()
/android/frameworks/base/core/java/android/view/ViewRootImpl.java
----drawSoftware(surface, mAttachInfo, xOffset, yOffset) //软件绘制
3.使用软件绘制drawSoftware
/android/frameworks/base/core/java/android/view/ViewRootImpl.java
----drawSoftware()
------canvas = mSurface.lockCanvas(dirty); //先取得一个Canvas对象,在此基础上作图
------canvas.translate(-xoff, -yoff); //坐标转换
------mView.draw(canvas); //由顶层元素开始遍历绘制
/android/frameworks/base/core/java/android/view/Surface.java
------surface.unlockCanvasAndPost(canvas); //绘制完毕,释放Canvas并"提交结果"
--------unlockSwCanvasAndPost(canvas);
----------nativeUnlockCanvasAndPost(mLockedObject, canvas);
/android/frameworks/base/core/jni/android_view_Surface.cpp
------------canvas.setBuffer(nullptr, ADATASPACE_UNKNOWN);
------------surface->unlockAndPost();
/android/frameworks/native/libs/gui/Surface.cpp
--------------mLockedBuffer->unlockAsync(&fd);
--------------queueBuffer(mLockedBuffer.get(), fd);
1)注意软件绘制由于是CPU处理,因此是同步操作;
2)Canvas是一个绘图工具,应用程序只需要调用它的接口即可完成图形的绘制,绘制的原理涉及到图形库,这里不展开
4.使用硬件绘制流程(简单了解)
cursor - 如何调用到 GL 库
/android/frameworks/base/core/java/android/view/ThreadedRenderer.java
ThreadedRenderer.draw() (Java)
↓
/android/frameworks/base/graphics/java/android/graphics/HardwareRenderer.java
syncAndDrawFrame() (继承自 HardwareRenderer)
↓ [JNI 调用]
/android/frameworks/base/libs/hwui/renderthread/RenderProxy.cpp
RenderProxy.syncAndDrawFrame() (Native)
↓
CanvasContext.draw() (在 RenderThread 中)
↓
OpenGLRenderer.draw()
↓
glDrawArrays() / glDrawElements() (OpenGL ES API)
↓
Mesa3D
↓
Panfrost 驱动
↓
GPU 硬件 (通过 DRM/KMS)
1)注意硬件绘制由于是GPU处理,CPU不会等待GPU处理完成,因此是异步操作;
2)各个view的绘图任务交由ThreadedRenderer线程统一处理,它会收集绘图任务,最终发给GPU统一处理;
3)既然是异步,CPU如何得知GPU渲染完成?通过Fence驱动机制 同步
在现代设备上,几乎都能支持硬件绘制,我们重点看硬件绘制和硬件GPU渲染!
2、View的draw方法

/android/frameworks/base/core/java/android/view/View.java
draw(Canvas canvas) //没有fading的情况
--drawBackground(canvas); //绘制背景
--onDraw(canvas); //绘制内容,调用派生类的重载方法
/android/frameworks/base/core/java/android/widget/ImageView.java
----canvas.clipRect(); //没有占满整个父view,则需要裁剪
----canvas.translate(mPaddingLeft, mPaddingTop); //裁剪后进行坐标转换 确定相对位置
----mDrawable.draw(canvas);
--dispatchDraw(canvas); //绘制子对象
--onDrawForeground(canvas);
--drawDefaultFocusHighlight(canvas);
3、View的画板Surface
1)Surface的数据来源有哪些?

Surface是一块空白内存,谁来填充?可以是OpenGL 、Skia等等图形引擎
1.Window Type
/android/frameworks/native/libs/nativewindow/include/system/window.h
enum {
/* Buffers will be queued by EGL via eglSwapBuffers after being filled using
* OpenGL ES.
*/
NATIVE_WINDOW_API_EGL = 1, //表示Surface数据由GL库填充
/* Buffers will be queued after being filled using the CPU */
NATIVE_WINDOW_API_CPU = 2, //表示Surface数据由CPU构造填充
/* Buffers will be queued by Stagefright after being filled by a video
* decoder. The video decoder can either be a software or hardware decoder.
*/
NATIVE_WINDOW_API_MEDIA = 3, //表示Surface数据由video decoder硬件构造填充
/* Buffers will be queued by the the camera HAL.*/
NATIVE_WINDOW_API_CAMERA = 4, //表示Surface数据由camera构造填充
};
2)Canva与Surface

3)View向SF索要画板过程

4、Android原生硬件绘制JAVA示例
/android/frameworks/base/tests/HwAccelerationTest/src/com/android/test/hwui/HardwareCanvasSurfaceViewActivity.java
案例是用的SurfaceView.java的流程。这个流程和实际上从ViewRootImpl.java中通过performDraw的流程类似
6)View Animation
Android的三种动画(帧动画、View动画、属性动画):https://juejin.cn/post/7556911205157748746
动画的本质是时间和图像的关系
Transformation :交互
Interpolator : 内插程序
/android/frameworks/base/core/java/android/view/animation
/android/frameworks/base/core/java/android/view/animation/Animation.java
View与Animation的交互

三、WMS
1、WMS总体设计
1)WMS是显示框架中唯一不依赖硬件,纯软件实现的模块,重点是管理窗口的层级和属性 - 简单理解操控窗口的XYZ轴,既然是管理,必然和其它GUI显示相关的组件 密切相关;
2)WMS并不是必须的,比如开机动画是不依赖WMS的,只依赖SurfaceFlinger和OpenGL-ES;
3)WMS的逻辑十分庞大和复杂,要完全掌握几乎不现实,先把握住框架才是首要任务;
1)WMS的设计思想

1)可以看到WMS是统筹各个GUI组件的作用,打个比方:
SurfaceFlinger是摄像机、View系统是演员、InputManagerService是用户给系统传达命令的通讯设备、AMS是剧本、而WMS则是导演,根据用户的意图和既定的剧本来演绎 "舞台剧";
2)WMS不需要实际干活(操作硬件),而是根据各种信息 指导 各个组件干活,因此它的逻辑是相当复杂;
3)从计算机I/O系统的角度来看,WMS至少要完成以下两个功能
1、全局的窗口管理 - 窗口的添加和删除
1)设置启动窗口、设置窗口动画、窗口大小计算、窗口层级
2、全局的事件管理派发(input),事件来自于IMS;
4)窗口类型
1、Application Window - 应用程序自身的Activity
2、System Window - 系统状态栏、壁纸等
3、Sub Window - 点击Menu出现的应用程序菜单
2)WMS的对外接口
/android/frameworks/base/core/java/android/view/IWindowManager.aidl
AIDL工具会将aidl转化为IWindowManager.java
1)接口功能 - 获取屏幕尺寸、锁定屏幕、截取屏幕等
IWindowSession openSession(in IWindowSessionCallback callback); //与WMS建立一个Session连接
void getInitialDisplaySize(int displayId, out Point size);
void addWindowToken(IBinder token, int type, int displayId, in Bundle options);
void setForcedDisplayDensityForUser(int displayId, int density, int userId);
3)WMS的启动与初始化
1、WMS与其它服务一样,由SystemServer启动
/android/frameworks/base/services/java/com/android/server/SystemServer.java
import com.android.server.wm.WindowManagerService;
public void run {
wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
ServiceManager.addService(Context.WINDOW_SERVICE, wm, DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
}
2. WindowManagerService
/android/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
public class WindowMangerService extends IWindowManager.Stub implements WindowManagerPolicy.WindowManagerFuncs {
}
3.WindowManagerService构造函数 - 极其庞大
private WindowManagerService(Context context, InputManagerService inputManager,
boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy,
ActivityTaskManagerService atm, DisplayWindowSettingsProvider
displayWindowSettingsProvider, Supplier<SurfaceControl.Transaction> transactionFactory,
Supplier<Surface> surfaceFactory,
Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {
1.与众多服务关联起来
mInputManager = inputManager;
mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
mSurfaceControlFactory = surfaceControlFactory;
mPolicy = policy; //窗口策略
LocalServices.addService(WindowManagerPolicy.class, mPolicy);
mAnimator = new WindowAnimator(this); //窗口动画
mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
mKeyguardDisableHandler = KeyguardDisableHandler.create(mContext, mPolicy, mH); //键盘-SystemUi
mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
mActivityManager = ActivityManager.getService();
}
4)WMS的工作方式

1、给WMS服务发送消息
1.消息发送
mH.sendMessage()
2.WMS处理消息
/android/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
public void handleMessage(Message msg) {
}
2、WMS、AMS和Activity的aidl通信

/android/frameworks/base/core/java/android/app/IActivityManager.aidl
/android/frameworks/base/core/java/android/view/IWindowSession.aidl
/android/frameworks/base/core/java/android/view/IWindow.aidl
/android/frameworks/base/core/java/android/view/IWindowManager.aidl

5)Window Policy
1.作用是根据不同的产品形态(Phone/Tablet/TV/车载)来 选用不同的窗口组合
2.Window Policy有四个相关的类:WindowManagerPolicy、PhoneWindowManager、PolicyManager、Policy
3.
/android/frameworks/base/services/core/java/com/android/server/policy/WindowManagerPolicy.java
/android/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
/android/frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java

2、窗口的添加过程
1.以SystemUI的Notification窗口为例
/android/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java
public class NotificationShadeWindowControllerImpl {
attach() //Adds the notification shade view to the window manager.
/android/frameworks/base/core/java/android/view/WindowManagerImpl.java
--mWindowManager.addView(mNotificationShadeView, LayoutParams);
/android/frameworks/base/core/java/android/view/WindowManagerGlobal.java
----mGlobal.addView()
/android/frameworks/base/core/java/android/view/ViewRootImpl.java
------root = new ViewRootImpl(view.getContext(), display);
------root.setView(view, wparams, panelParentView, userId);
--------requestLayout(); //发起layout请求
/android/frameworks/base/core/java/android/view/WindowlessWindowManager.java
--------mWindowSession.addToDisplayAsUser()
/android/frameworks/base/services/core/java/com/android/server/wm/Session.java
----------mService.addWindow()
/android/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
------------parentWindow = windowForClientLocked(null, attrs.token, false);//寻找父窗口
------------WindowState win = new WindowState(); //生成一个WindowState来管理窗口
------------displayPolicy.adjustWindowParamsLw(win, win.mAttrs); //调整window属性
------------win.mToken.addWindow(win);
------------displayPolicy.addWindowLw(win, attrs);
}
3、Surface管理
WMS需要向SF申请Surface,并交由应用程序进行绘制
1)Surface实现重点

2)Surface关系图

3)Surface的创建
1.Surface的创建
/android/frameworks/base/core/java/android/view/ViewRootImpl.java
public final Surface mSurface = new Surface();
private final SurfaceControl mSurfaceControl = new SurfaceControl();
/android/frameworks/base/core/java/android/view/ViewRootImpl.java
performTraversals()
--relayoutWindow(params, viewVisibility, insetsPending);
/android/frameworks/base/services/core/java/com/android/server/wm/Session.java
----mWindowSession.relayout(mWindow, params, mSurfaceControl, ...)
/android/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
-----mService.relayoutWindow()
-------createSurfaceControl(outSurfaceControl, result, win, winAnimator);
/android/frameworks/base/services/core/java/com/android/server/wm/WindowStateAnimator.java
---------surfaceController = winAnimator.createSurfaceLocked();
/android/frameworks/base/core/jni/android_view_SurfaceControl.cpp
nativeCreate()
--client->createSurface()
2.Surface的业务操作
nativeCreateTransaction()
nativeApplyTransaction()
4、启动窗口和窗口动画
为了更好的体验,用户程序的窗口切换 可以添加在它们之间增加 启动窗口和窗口动画,让其过渡效果更加顺滑
1.启动窗口的添加与销毁
/android/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
addWindow()
/android/frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java
--activity.attachStartingWindow(win);
2.窗口动画
/android/frameworks/base/core/java/android/view/View.java
public void startAnimation(Animation animation) {
animation.setStartTime(Animation.START_ON_FIRST_FRAME);
setAnimation(animation);
invalidateParentCaches();
invalidate(true);
}
/android/frameworks/base/services/core/java/com/android/server/wm/WindowAnimator.java