Android窗口管理服务WindowManagerService对窗口的组织方式分析.docx

上传人:b****1 文档编号:2385446 上传时间:2023-05-03 格式:DOCX 页数:63 大小:407.21KB
下载 相关 举报
Android窗口管理服务WindowManagerService对窗口的组织方式分析.docx_第1页
第1页 / 共63页
Android窗口管理服务WindowManagerService对窗口的组织方式分析.docx_第2页
第2页 / 共63页
Android窗口管理服务WindowManagerService对窗口的组织方式分析.docx_第3页
第3页 / 共63页
Android窗口管理服务WindowManagerService对窗口的组织方式分析.docx_第4页
第4页 / 共63页
Android窗口管理服务WindowManagerService对窗口的组织方式分析.docx_第5页
第5页 / 共63页
Android窗口管理服务WindowManagerService对窗口的组织方式分析.docx_第6页
第6页 / 共63页
Android窗口管理服务WindowManagerService对窗口的组织方式分析.docx_第7页
第7页 / 共63页
Android窗口管理服务WindowManagerService对窗口的组织方式分析.docx_第8页
第8页 / 共63页
Android窗口管理服务WindowManagerService对窗口的组织方式分析.docx_第9页
第9页 / 共63页
Android窗口管理服务WindowManagerService对窗口的组织方式分析.docx_第10页
第10页 / 共63页
Android窗口管理服务WindowManagerService对窗口的组织方式分析.docx_第11页
第11页 / 共63页
Android窗口管理服务WindowManagerService对窗口的组织方式分析.docx_第12页
第12页 / 共63页
Android窗口管理服务WindowManagerService对窗口的组织方式分析.docx_第13页
第13页 / 共63页
Android窗口管理服务WindowManagerService对窗口的组织方式分析.docx_第14页
第14页 / 共63页
Android窗口管理服务WindowManagerService对窗口的组织方式分析.docx_第15页
第15页 / 共63页
Android窗口管理服务WindowManagerService对窗口的组织方式分析.docx_第16页
第16页 / 共63页
Android窗口管理服务WindowManagerService对窗口的组织方式分析.docx_第17页
第17页 / 共63页
Android窗口管理服务WindowManagerService对窗口的组织方式分析.docx_第18页
第18页 / 共63页
Android窗口管理服务WindowManagerService对窗口的组织方式分析.docx_第19页
第19页 / 共63页
Android窗口管理服务WindowManagerService对窗口的组织方式分析.docx_第20页
第20页 / 共63页
亲,该文档总共63页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

Android窗口管理服务WindowManagerService对窗口的组织方式分析.docx

《Android窗口管理服务WindowManagerService对窗口的组织方式分析.docx》由会员分享,可在线阅读,更多相关《Android窗口管理服务WindowManagerService对窗口的组织方式分析.docx(63页珍藏版)》请在冰点文库上搜索。

Android窗口管理服务WindowManagerService对窗口的组织方式分析.docx

Android窗口管理服务WindowManagerService对窗口的组织方式分析

Android窗口管理服务WindowManagerService对窗口的组织方式分析

我们知道,在Android系统中,Activity是以堆栈的形式组织在ActivityManagerService服务中的。

与Activity类似,Android系统中的窗口也是以堆栈的形式组织在WindowManagerService服务中的,其中,Z轴位置较低的窗口位于Z轴位置较高的窗口的下面。

在本文中,我们就详细分析WindowManagerService服务是如何以堆栈的形式来组织窗口的。

从前面一文可以知道,应用程序进程中的每一个Activity组件在Activity管理服务ActivityManagerService中都对应有一个ActivityRecord对象。

从前面一文又可以知道,Activity管理服务ActivityManagerService中每一个ActivityRecord对象在Window管理服务WindowManagerService中都对应有一个AppWindowToken对象。

此外,在输入法管理服务InputMethodManagerService中,每一个输入法窗口都对应有一个Binder对象,这个Binder对象在Window管理服务WindowManagerService又对应有一个WindowToken对象。

与输入法窗口类似,在壁纸管理服务WallpaperManagerService中,每一个壁纸窗口都对应有一个Binder对象,这个Binder对象在Window管理服务WindowManagerService也对应有一个WindowToken对象。

在Window管理服务WindowManagerService中,无论是AppWindowToken对象,还是WindowToken对象,它们都是用来描述一组有着相同令牌的窗口的,每一个窗口都是通过一个WindowState对象来描述的。

例如,一个Activity组件窗口可能有一个启动窗口(StartingWindow),还有若干个子窗口,那么这些窗口就会组成一组,并且都是以Activity组件在Window管理服务WindowManagerService中所对应的AppWindowToken对象为令牌的。

从抽象的角度来看,就是在Window管理服务WindowManagerService中,每一个令牌(AppWindowToken或者WindowToken)都是用来描述一组窗口(WindowState)的,并且每一个窗口的子窗口也是与它同属于一个组,即都有着相同的令牌。

上述的窗口组织方式如图1所示:

其中,ActivityStack是在ActivityManagerService服务中创建的,TokenList和WindowStack是在WindowManagerService中创建的,而BinderforIM和BinderforWP分别是在InputMethodManagerService服务和WallpaperManagerService服务中创建的,用来描述一个输入法窗口和一个壁纸窗口。

图1中的对象的对应关系如下所示:

1.ActivityRecord-J对应于AppWindowToken-J,后者描述的一组窗口是{WindowState-A,WindowState-B,WindowState-B-1},其中,WindowState-B-1是WindowState-B的子窗口。

2.ActivityRecord-K对应于AppWindowToken-K,后者描述的一组窗口是{WindowState-C,WindowState-C-1,WindowState-D,WindowState-D-1},其中,WindowState-C-1是WindowState-C的子窗口,WindowState-D-1是WindowState-D的子窗口。

3.ActivityRecord-N对应于AppWindowToken-N,后者描述的一组窗口是{WindowState-E},其中,WindowState-E是系统当前激活的Activity窗口。

4.BinderforIM对应于WindowToken-I,后者描述的一组窗口是{WindowState-I},其中,WindowState-I是WindowState-E的输入法窗口。

5.BinderforWP对应于WindowToken-W,后者描述的一组窗口是{WindowState-W},其中,WindowState-W是WindowState-E的壁纸窗口。

从图1还可以知道,WindowStack中的WindowState是按照它们所描述的窗口的Z轴位置从低到高排列的。

以上就是WindowManagerService服务组织系统中的窗口的抽象模型,接下来我们将分析AppWindowToken、WindowToken和WindowState的一些增加、移动和删除等操作,以便可以对这个抽象模型有一个更深刻的认识。

1.增加AppWindowToken

从前面一文可以知道,一个Activity组件在启动的过程中,ActivityManagerService服务会调用调用WindowManagerService类的成员函数addAppToken来为它增加一个AppWindowToken,如下所示:

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

publicclassWindowManagerServiceextendsIWindowManager.Stub

implementsWatchdog.Monitor{

......

/**

*MappingfromatokenIBindertoaWindowTokenobject.

*/

finalHashMapmTokenMap=

newHashMap();

/**

*ThesametokensasmTokenMap,storedinalistforefficientiteration

*overthem.

*/

finalArrayListmTokenList=newArrayList();

......

/**

*Z-ordered(bottom-mostfirst)listofallapplicationtokens,for

*controllingtheorderingofwindowsindifferentapplications.This

*containsWindowTokenobjects.

*/

finalArrayListmAppTokens=newArrayList();

......

publicvoidaddAppToken(intaddPos,IApplicationTokentoken,

intgroupId,intrequestedOrientation,booleanfullscreen){

......

synchronized(mWindowMap){

AppWindowTokenwtoken=findAppWindowToken(token.asBinder());

if(wtoken!

=null){

......

return;

}

wtoken=newAppWindowToken(token);

......

mAppTokens.add(addPos,wtoken);

......

mTokenMap.put(token.asBinder(),wtoken);

mTokenList.add(wtoken);

......

}

}

......

}

这个函数定义在文件frameworks/base/services/java/com/android/server/WindowManagerService.java中。

WindowManagerService类有三个成员变量mTokenMap、mTokenList和mAppTokens,它们都是用来描述系统中的窗口的。

成员变量mTokenMap指向的是一个HashMap,它里面保存的是一系列的WindowToken对象,每一个WindowToken对象都是用来描述一个窗口的,并且是以描述这些窗口的一个Binder对象的IBinder接口为键值的。

例如,对于Activity组件类型的窗口来说,它们分别是以用来描述它们的一个ActivityRecord对象的IBinder接口保存在成员变量mTokenMap所指向的一个HashMap中的。

成员变量mTokenList指向的是一个ArrayList,它里面保存的也是一系列WindowToken对象,这些WindowToken对象与保存在成员变量mTokenMap所指向的一个HashMap中的WindowToken对象是一样的。

成员变量mTokenMap和成员变量mTokenList的区别就在于,前者在给定一个IBinder接口的情况下,可以迅速指出是否存在一个对应的WindowToken对象,而后者可以迅速遍历WindowManagerService服务中的WindowToken对象。

成员变量mAppTokens指向的也是一个ArrayList,不过它里面保存的是一系列AppWindowToken对象,每一个AppWindowToken对象都是用来描述一个Activity组件窗口的,而这些AppWindowToken对象是以它们描述的窗口的Z轴坐标由小到大保存在这个ArrayList中的,这样我们就可以通过这个ArrayList来从上到下或者从下到上地遍历系统中的所有Activity组件窗口。

由于这些AppWindowToken对象所描述的Activity组件窗口也是一个窗口,并且AppWindowToken类是从WindowToken继承下来的,因此,这些AppWindowToken对象还会同时被保存在成员变量mTokenMap所指向的一个HashMap和成员变量mTokenList所指向的一个ArrayList中。

理解了WindowManagerService类的这三个成员变量的含义之后,它的成员函数addAppToken的实现就好理解了,其中,参数token指向的便是用来描述正在启动的Activity组件所对应的一个ActivityRecord对象,而参数addPos用来描述该Activity组件在堆栈中的位置,这个位置同时也是接下来要创建的AppWindowToken对象在WindowManagerService类的mTokenList所描述的一个ArrayList中的位置。

WindowManagerService类的成员函数addAppToken首先调用另外一个成员函数findAppWindowToken来在成员变量mTokenMap所描述的一个HashMap检查是否已经存在一个AppWindowToken。

如果已经存在的话,那么WindowManagerService类的成员函数addAppToken就什么也不做就返回了,否则的话,就会使用参数token来创建一个AppWindowToken对象,并且会将该AppWindowToken对象分别保存在WindowManagerService类的成员变量mTokenMap、mTokenList和mAppTokens中。

2.删除AppWindowToken

删除AppWindowToken是通过调用WindowManagerService类的成员函数removeAppTokensLocked来实现的,如下所示:

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

publicclassWindowManagerServiceextendsIWindowManager.Stub

implementsWatchdog.Monitor{

......

privatevoidremoveAppTokensLocked(Listtokens){

//XXXThisshouldbedonemoreefficiently!

//(takeadvantageofthefactthatbothlistsshouldbe

//orderedinthesameway.)

intN=tokens.size();

for(inti=0;i

IBindertoken=tokens.get(i);

finalAppWindowTokenwtoken=findAppWindowToken(token);

if(!

mAppTokens.remove(wtoken)){

......

i--;

N--;

}

}

}

......

}

这个函数定义在文件frameworks/base/services/java/com/android/server/WindowManagerService.java中。

WindowManagerService类的成员函数removeAppTokensLocked可以同时删除一组AppWindowToken对象。

参数tokens所描述的是一个IBinder接口列表,与这些IBinder接口所对应的AppWindowToken对象就是接下来要删除的。

WindowManagerService类的成员函数removeAppTokensLocked通过一个for循环来依次调用另外一个成员函数findAppWindowToken,以便可以找到保存在列表tokens中的每一个IBinder接口所对应的AppWindowToken对象,然后将该AppWindowToken对象从WindowManagerService类的成员变量mAppTokens所描述的一个ArrayList中删除。

注意,WindowManagerService类的成员函数removeAppTokensLocked是在内部使用的,它只是把一个AppWindowToken对象从成员变量mAppTokens中删除,而没有从另外两个成员变量mTokenMap和mTokenList中删除。

3.移动AppWindowToken至指定位置

移动AppWindowToken至指定位置是通过调用WindowManagerService类的成员函数moveAppToken来实现的,如下所示:

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

publicclassWindowManagerServiceextendsIWindowManager.Stub

implementsWatchdog.Monitor{

......

publicvoidmoveAppToken(intindex,IBindertoken){

if(!

checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,

"moveAppToken()")){

thrownewSecurityException("RequiresMANAGE_APP_TOKENSpermission");

}

synchronized(mWindowMap){

......

finalAppWindowTokenwtoken=findAppWindowToken(token);

if(wtoken==null||!

mAppTokens.remove(wtoken)){

......

return;

}

mAppTokens.add(index,wtoken);

......

finallongorigId=Binder.clearCallingIdentity();

......

if(tmpRemoveAppWindowsLocked(wtoken)){

......

reAddAppWindowsLocked(findWindowOffsetLocked(index),wtoken);

......

updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);

mLayoutNeeded=true;

performLayoutAndPlaceSurfacesLocked();

}

Binder.restoreCallingIdentity(origId);

}

}

......

}

这个函数定义在文件frameworks/base/services/java/com/android/server/WindowManagerService.java中。

参数token描述的是要移动的AppWindowToken对象所对应的一个IBinder接口,而参数index描述的是该AppWindowToken对象要移动到的位置。

注意,移动一个AppWindowToken对象到指定的位置是需要android.Manifest.permission.MANAGE_APP_TOKENS权限的。

WindowManagerService类的成员函数moveAppToken首先找到与参数token所对应的AppWindowToken对象,并且将该AppWindowToken对象从WindowManagerService类的成员变量mAppTokens所描述的一个ArrayList中移除,这样做的目的是为了接下来可以将该AppWindowToken对象移动至该ArrayList中的指定位置上,即参数index所描述的位置上。

注意,上述操作只是将参数token所对应的AppWindowToken对象移动到了WindowManagerService类的成员变量mAppTokens所描述的一个ArrayList的指定位置上,接下来还需要同时将与该AppWindowToken对象所对应的WindowState对象移动至WindowManagerService服务内部的一个WindowState堆栈合适位置上去。

移动对应的WindowState对象的操作同样也是分两步执行的:

第一步先调用WindowManagerService类的成员函数tmpRemoveAppWindowsLocked来将这些WindowState对象从原来的WindowState堆栈位置移除;第二步再调用WindowManagerService类的成员函数reAddAppWindowsLocked来将这些WindowState对象插入到WindowState堆栈的合适位置去。

对应的WindowState对象被移动到的合适位置是通过调用WindowManagerService类的成员函数findWindowOffsetLocked来获得的,它的实现如下所示:

[java]viewplaincopy在CODE上查看代码片派生到我的代码片

publicclassWindowManagerServiceextendsIWindowManager.Stub

implementsWatchdog.Monitor{

......

/**

*Z-ordered(bottom-mostfirst)listofallWindowobjects.

*/

finalArrayListmWindows=newArrayList();

......

privateintfindWindowOffsetLocked(inttokenPos){

finalintNW=mWindows.size();

if(tokenPos>=mAppTokens.size()){

inti=NW;

while(i>0){

i--;

WindowStatewin=mWindows.get(i);

if(win.getAppToken()!

=null){

returni+1;

}

}

}

while(tokenPos>0){

//Findthefirstapptokenbelowthenewpositionthathas

//awindowdisplayed.

finalAppWindowTokenwtoken=mAppTokens.get(tokenPos-1);

......

if(wtoken.sendingToBottom){

......

tokenPos--;

continue;

}

inti=wtoken.windows.size();

while(i>0){

i--;

WindowStatewin=wtoken.windows.get(i);

intj=win.mChildWindows.size();

while(j>0){

j--;

WindowStatecwin=win.mChildWindows.get(j);

if(cwin.mSubLayer>=0){

for(intpos=NW-1;pos>=0;pos--){

if(mWindows.get(pos)==cwin){

......

returnpos+1;

}

}

}

}

for(intpos=NW-1;pos>=0;pos--){

if(mWindows.get(pos)==win){

......

returnpos+1;

}

}

}

tokenPos--;

}

return0;

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 高中教育 > 高考

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2