没有合适的资源?快使用搜索试试~ 我知道了~
深入理解WindowManagerService笔记
需积分: 9 1 下载量 54 浏览量
2022-07-19
14:36:27
上传
评论
收藏 8.23MB PDF 举报
温馨提示
试读
123页
深入理解WindowManagerService笔记
资源详情
资源评论
资源推荐
深
⼊
理
解
WindowManagerService
1
深
⼊
理
解
WindowManagerService
资
料
<<
深
⼊
理
解
安
卓
系
统
三
>>-WindowManagerService
篇
初
识
WindowManagerService
开
篇
SampleWindow
public class SampleWindow {
public static void main(String[] args) {
try {
new SampleWindow().Run();
} catch (Exception e) {
e.printStackTrace();
}
}
// IWindowSession
是
客
户
端
向
WMS
请
求
窗
⼝
操
作
的
中
间
代
理
,
并
且
是
进
程
唯
⼀
的
IWindowSession mSession = null;
// InputChannel
是
窗
⼝
接
受
⽤
户
输
⼊
事
件
的
管
道
。
在
第
5
章
中
将对
其
进
⾏
详
细
探
讨
InputChannel mInputChannel = new InputChannel();
资
料
初
识
WindowManagerService
开
篇
SampleWindow
总
结
在
客
户
端
创
建
⼀个
窗
⼝
的
步
骤
WMS
的
诞
⽣
WMS
重
要
成
员
addWindow&removeWindow
WindowToken
addWindowToken
ActivityRecord
WindowState
理
解
窗
⼝
的
显
⽰
次
序
主
序
,
⼦
序
和
窗
⼝
类
型
通
过
主
序
与
⼦
序
确
定
窗
⼝
的
次
序
窗
⼝
的
布
局
relayoutWindow
performLayoutAndPlaceSurfacesLocked()
requestTraversal
requestTraversalLocked
performLayoutAndPlaceSurfacesLockedLoop
performLayoutAndPlaceSurfacesLockedInner
深
⼊
理
解
窗
⼝
布
局
的
原
理
检
查
窗
⼝
布
局
结
果
PhoneWindowManager#beginPostLayoutPolicyLw
PhoneWindowManager#applyPostLayoutPolicyLw
PhoneWindowManager#finishPostLayoutPolicyLw()
关
于
DisplayContent
布
局
的
⼩
结
WMS
的
动
画
系
统
Choreographer
SampleAnimation
WindowAnimator
分
析
WindowAnimator
的
组
成
WindowAnimator#animateLocked
深
⼊
理
解
窗
⼝
动
画
深
⼊
理
解
WindowManagerService
2
//
下
⾯
三个
Rect
保
存
了
窗
⼝
的
布
局
结
果
。
其
中
mFrame
表
⽰
了
窗
⼝
在
屏
幕
上
的
位
置
与
尺⼨
Rect mInsets = new Rect();
Rect mFrame = new Rect();
Rect mVisibleInsets = new Rect();
Configuration mConfig = new Configuration();
//
窗
⼝
的
surface
,
在
次
Surface
上
进
⾏
的
绘
制
都
将
在
此
窗
⼝
上
显
⽰
出
来
Surface mSurface = new Surface();
//
⽤
于
在
窗
⼝
上
急性
绘
图
的
画
刷
Paint mPaint = new Paint();
//
添
加
窗
⼝
所
需
的
令
牌
,
在
4。2
节
将
详
细
描
述
Ibinder mToken = new Binder();
//
⼀个
窗
⼝
对
象
,
本
例
厌
⾷
了
如
何
将
此
窗
⼝
添
加
到
WMS
中
,
并
在
其
上
进
⾏
绘
制
操
作
MyWindow mWindow = new MyWindow();
// WindowManager.LayoutParams
定
义
窗
⼝
的
布
局属
性
,
包
括
位
置
、
尺⼨
以
及
窗
⼝
类
型
WindowManager.LayoutParams mLp = new LayoutParams();
Choreographer mChoreographer = null;
// Inputhandler
⽤
于从
InputChannel
接
收
按
键
事
件
并
作
出
响
应
Handler mInputhandler = null;
boolean mContinueAnime = true;
public void Run() throws Exception {
Looper.prepare();
//
获
取
WMS
服
务
IWindowManager wms = IWindowManager.Stub.asInterface(ServiceManager.getService(Context.WINDOW_SERVICE));
//
通
过
WindowManagerGlobal
获
取
进
程
唯
⼀
的
IWindowSession
实
例
。
它
将
⽤
于
向
WMS
//
发
送
请
求
。
注
意
这
个
函
数
在
较
早
的
Android
版
本
(
4。1
)
位
于
ViewRootImpl
类
中
mSession = WindowManagerGlobal.getWinodwSession(Looper.myLooper());
//
获
取
屏
幕
分
辨
率
IDisplayManager dm = IDisplayManager.Stub.asInterface(ServiceManager.getService(Context.DISPLAY_SERVICE));
DisplayInfo di = dm.getDisplaInfo(Display.DEFAULT_DISPLAY);
Point scrnSize = new Point(di.appWidth, di.appHeight);
//
初
始
化
WindowManager.LayoutParams
initLayoutParams(scrnSize);
//
将
新
窗
⼝
添
加
到
WMS
installWindow(wms);
//
初
始
化
Choreographer
的
实
例
,
此
实
例
为
线
程
唯
⼀
。
这
个
类
的
⽤
法
与
Handler
//
类
似
,
不
过
它
总
是
在
VSYC
同
时
回
调
,
所
以
次
Handler
更
适
合
做
动
画
的
循
环
器
mChoreographer = Choregrapher.getInstance();
//
开
始
处
理
第
⼀
帧
的
动
画
scheduleNextFrame();
//
当
前
线
程
陷
⼊
消
息
循
环
,
查
到
Looper.quit()
Looper.loop();
//
标
记
要
不
要
继续绘
制
动
画
帧
mContinueAnime = false;
//
卸
载
当
前
window
uninstallWindow(wms);
}
public void initLayoutParams(Point screenSize) {
//
标
记
即
将
安
装
的
窗
⼝
类
型
为
SYSTEM_ALERT
,
这
将
使
得
窗
⼝
的
ZOrder
顺
序
⽐
较
靠
前
mLp.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
mLp.setTitle("SampleWindow");
//
设
定
窗
⼝
的
左
上
⾓
坐
标
以
及
⾼
度
和
宽
度
mLp.gravity = Gravity.LEFT | Gravity.TOP;
mLp.x = screenSize.x / 4;
mLp.y = screenSize.y / 4;
mLp.width = screenSize.x / 2;
mLp.height = screenSize.y / 2;
//
和
输
⼊
事
件
相
关
的
Flag
,
希
望
当
输
⼊
事
件
发
⽣
在
此
窗
⼝
之
外
时
,
其
他
窗
⼝
也
可
以
接
收
输
⼊
事
件
mLp.flags = mLp.flags | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
}
public void installWindow(IWindowManager wms) throws Exception {
//
⾸
先
向
WMS
声
明
⼀个
Token
,
任何
⼀个
Window
都
需
要
⾪
属
于
⼀个
特
定
类
型
的
Token
wms.addWindowToken(mToken, WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
//
设
置
窗
⼝
所
⾪
属
的
Token
mLp.token = mToken;
//
通
过
IWindowSession
将
窗
⼝
安
装
进
WMS
,
注
意
,
此
时
仅仅
是
安
装
到
WMS
,
本
例
的
Window
//
⽬
前
仍
然
没
有有
效
的
Surface
。
不
过
,
经
过
这
个
调
⽤
后
,
mInputChannel
已
经
可
以
⽤
来
接
收
输
⼊
事
件
了
mSession.add(mWindow, 0, mLp, View.VISIBLE, mInsets, mInputChannel);
//
通
过
IWindownSession
要
求
WMS
对
本
窗
⼝
进
⾏
重
新
布
局
,
经
过
这
个
操
作
后
,
WMS
将
会
为
窗
⼝
创
建
⼀
块
⽤
于
绘
制
的
Surface
并
保
存
在
参
数
// msurface
中
。
同
时
,
这
个
Surface
被
WMS
放
置
在
Layoutprams
所
指
定
的
位
置
上
mSession.relayout(mWindow, 0, mLp, mLp.width, mLp.height, View.VISIBLE, 0, mFrame, mInsets, mVisibleInsets, mConfig, mSurface);
if (!mSurface.isValid()) {
throw new RuntimeException("Failed creating Surface.");
}
//
基
于
WMS
返
回
的
InoputChannel
创
建
⼀个
Handler
,
⽤
于
监
听
输
⼊
事
件
// mInputHandlery
⼀
旦
被
创
建
,
就
已
经
在
监
听
输
⼊
事
件
了
mInputhandler = new InputHandler(mInputChannel, Looper.myLooper());
深
⼊
理
解
WindowManagerService
3
}
public void uninstallWindow(IWindowManager wms) throws Exception {
//
从
WMS
处
卸
载
窗
⼝
mSession.remove(mWindow);
//
从
WMS
处
移
除
之
前
添
加
的
Token
wms.removeWindowToken(mToken);
}
public void scheduleNextFrame() {
//
要
求
在
显
⽰
系
统
刷
新
下⼀
帧
回
调
mFrameRender,
注
意
,
只
回
调
⼀
次
mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mFrameRender, null);
}
//
这
个
Runnable
对
象
⽤
于
在
窗
⼝
上
描
绘
⼀
帧
public Runnable mFrameRender = new Runnable() {
@Override
public void run() {
try {
//
获
取
当
前
时
间
戳
long time = mChoreographer.getFrameTime() % 1000;
//
绘
图
if (mSurface.isValid()) {
Canvas canvas = mSurface.lockCanvas(null);
canvas.drawColor(Color.DKGRAY);
canvas.drawRect(2 * mLp.width * time / 1000 - mLp.width, 0, 2 * mLp.width * time / 1000, mLp.height, mPaint);
mSurface.unlockCanvasAndPost(canvas);
mSession.finishDrawing(mWindow);
}
if (mContinueAnime) scheduleNextFrame();
} catch (Exception e) {
e.printStackTrace();
}
}
};
//
定
义⼀个
类
继
承
InputEventReceiver,
⽤
于
在
其
onInputEvent
函
数
中
接
收
窗
⼝
的
输
⼊
事
件
class InputHandler extends InputEventReceiver {
Looper mLooper = null;
public InputHandler(InputChannel inputChannel, Looper looper) {
super(intputChannel, looper);
mLooper = looper;
}
@Override
public void onInputEvent(InputEvent event) {
if (event instanceof MotionEvent) {
MotionEvent me = (MotionEvent) event;
if (me.getAction() == MotionEvent.ACTION_UP) {
//
退
出
程
序
mLooper.quit();
}
}
super.onInputEvent(event);
}
}
//
实
现
⼀个
继
承
⾃
IWindow.Stub
的
类
MyWindow
class MyWindow extends IWindow.Stub {
//
保
持
默
认
的
实
现
即
可
}
}
总
结
在
客
户
端
创
建
⼀个
窗
⼝
的
步
骤
1.
获
取
IWindowSession
和
WMS
实
例
.
客
户
端
可
以
通
过
IWindowSession
向
WMS
发
送
请
求
.
2.
创
建
并
初
始
化
WindowManager.LayoutParams.
注
意
这
⾥
是
WindowManager
下
的
LayoutParams,
它
继
承
⾃
ViewGroup.LayoutParams,
并
扩
展
了
⼀
些
窗
⼝
相
关
的
属
性
.
其
中
最
重
要
的
是
type
属
性
.
这
个
属
性
描
述
了
窗
⼝
的
类
型
,
⼆
窗
⼝
类
型
正
是
WMS
对
多
个
窗
⼝
进
⾏
ZOrder
排
序
的
依
据
.
3.
向
WMS
添
加
⼀个
窗
⼝
令
牌
(WindowToken).
本
章
后
续
将
分
析
窗
⼝
令
牌
的
概
念
,
⽬
前
读
者
只
要
知
道
,
敞
⼝
令
牌
描
述
了
⼀个
显
⽰
⾏
为
,
并
且
WMS
要
求每
个
窗
⼝
必
须
⾪
属
于
某
⼀个
显
⽰
令
牌
.
深
⼊
理
解
WindowManagerService
4
4.
向
WMS
添
加
⼀个
窗
⼝
.
必
须
在
LayoutParams
中
指
明
此
窗
⼝
所
⾪
属
于
窗
⼝
令
牌
,
否
则
在
某
些
情
况
下
添
加
操
作会
失
败
.
在
SampleWindow
中
,
不
设
置
令
牌
也
可
以
成
功
完
成
添
加
操
作
,
因
为
窗
⼝
的
类
型
呗
设
为
TYPE_SYSTEM_ALERT,
它
是
系
统
窗
⼝
的
⼀
种
.
⽽
对
于
系
统
窗
⼝
,WMS
会
⾃
动
为
其
创
建
令
牌
,
故
⽆
需
客
户
端
操
⼼
.
此
话
题
会
在
后
⽂
进
⾏
具
体
讨论
.
5.
向
WMS
申
请
对
窗
⼝
进
⾏
重
新
布
局
(relayout).
所
谓
的
重
新
布
局
,
就
是
根
据
窗
⼝
新
的
属
性
去
调
整
其
Surface
相
关
的
属
性
,
或
者
重
新
创
建
⼀个
Surface(
例
如
窗
⼝
尺⼨
变
化
导
致
之
前
的
Surface
不
满
⾜
要
求
).
向
WMS
添
加
⼀个
窗
⼝
之
后
,
其
仅仅
是
将
它
在
WMS
中
进
⾏
注
册
⽽
已
,
窗
⼝
之
后
就
可
以
随
时
进
⾏
绘
制
⼯
作
了
.
WMS
的
诞
⽣
三个
阶
段
:
1.
创
建
实
例
2.
初
始
化
显
⽰
信
息
3.
处
理
systemReady
通
知
SystemServer.java
public void run() {
WindowManagerService wm = null; // WindowManagerService
...
try {
wm = WindowManagerService.main(context, power, display, inputManager,
uiHandler, wmHandler,
factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL,
!firstBoot, onlyCore);
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
}
...
try {
// 2.
初
始
化
显
⽰
信
息
wm.displayReady();
} catch (Throwable e) {
reportWtf("making display ready", e);
}
...
try {
// 3.
通
知
WMS
,
系
统
的
初
始
化
⼯
作
完
成
wm.systemReady();
} catch (Throwable e) {
reportWtf("making Window Manager Service ready", e);
}
}
WindowManagerService.java#main
public static WindowManagerService main(final Context context,
final PowerManagerService pm, final DisplayManagerService dm,
final InputManagerService im,
final Handler uiHandler, final Handler wmHandler,
final boolean haveInputMethods, final boolean showBootMsgs,
final boolean onlyCore) {
final WindowManagerService[] holder = new WindowManagerService[1];
//
通
过
由
SystemServer
未
WMS
创
建
的
Handler
新
建
⼀个
WindowManagerServcie
对
象
//
此
handle
运
⾏
再
⼀个
名
为
mWindowanagerde HandlerThread
中
wmHandler.runWithScissors(new Runnable() {
@Override
public void run() {
holder[0] = new WindowManagerService(context, pm, dm, im,
uiHandler, haveInputMethods, showBootMsgs, onlyCore);
}
}, 0);
return holder[0];
}
Handler.java
深
⼊
理
解
WindowManagerService
5
public final boolean runWithScissors(final Runnable r, long timeout) {
if (r == null) {
throw new IllegalArgumentException("runnable must not be null");
}
if (timeout < 0) {
throw new IllegalArgumentException("timeout must be non-negative");
}
if (Looper.myLooper() == mLooper) {
r.run();
return true;
}
BlockingRunnable br = new BlockingRunnable(r);
return br.postAndWait(this, timeout);
}
BlockingRunnable
private static final class BlockingRunnable implements Runnable {
private final Runnable mTask;
private boolean mDone;
public BlockingRunnable(Runnable task) {
mTask = task;
}
@Override
public void run() {
try {
mTask.run();
} finally {
synchronized (this) {
mDone = true;
notifyAll();
}
}
}
public boolean postAndWait(Handler handler, long timeout) {
if (!handler.post(this)) {
return false;
}
synchronized (this) {
if (timeout > 0) {
final long expirationTime = SystemClock.uptimeMillis() + timeout;
while (!mDone) {
long delay = expirationTime - SystemClock.uptimeMillis();
if (delay <= 0) {
return false; // timeout
}
try {
wait(delay);
} catch (InterruptedException ex) {
}
}
} else {
while (!mDone) {
try {
wait();
} catch (InterruptedException ex) {
}
}
}
}
return true;
}
}
private WindowManagerService(Context context, PowerManagerService pm,
DisplayManagerService displayManager, InputManagerService inputManager,
Handler uiHandler,
boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) {
剩余122页未读,继续阅读
赵健zj
- 粉丝: 2226
- 资源: 42
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0