Android应用程序键盘(Keyboard)消息处理机制分析(四)
上接:Android应用程序键盘(Keyboard)消息处理机制分析(三)
----
4.应用程序注销键盘消息接收通道的过程分析
当Activity窗口创建时,它会向InputManager注册键盘消息接收通道,而当Activity窗口销毁时,它就会向InputManager注销前面注册的键盘消息接收通道了,本节内容就来看看应用程序注销键盘消息接收通道的过程。
当我们按下键盘上的Back键时,当前**的Activity窗口就会被失去焦点,但是这时候它还没有被销毁,它的状态被设置为Stopped;当新的Activity窗口即将要显示时,它会通知WindowManagerService,这时候WindowManagerService就会处理当前处理Stopped状态的Activity窗口了,要执行的操作就是销毁它们了,在销毁的时候,就会注销它们之前所注册的键盘消息接收通道。
新的Activity窗口通知WindowManagerService它即将要显示的过程比较复杂,但是它与我们本节要介绍的内容不是很相关,因此,这里就略过大部过程了,我们从ActvitiyRecord的windowsVisible函数开始分析。注意,这里的ActivityRecord是新的Activity窗口在ActivityManangerService的代表,而那些处于Stopped状态的Activity窗口
会放在ActivityStack类的一个等待可见的mWaitingVisibleActivities列表里面,事实于,对于那些Stopped状态的Activity窗口来说,它们是等待销毁,而不是等待可见。
像前面一样,我们先来看一张应用程序注销键盘消息接收通道的过程的序列图,然后根据这个序列图来详细分析互一个步骤:
Step 1. ActivityRecord.windowsVisible
这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityRecord.java文件中:
- classActivityRecordextendsIApplicationToken.Stub{
- ......
- booleannowVisible;//isthisactivity'swindowvisible?
- booleanidle;//hastheactivitygoneidle?
- ......
- publicvoidwindowsVisible(){
- synchronized(service){
- ......
- if(!nowVisible){
- nowVisible=true;
- if(!idle){
- .......
- }else{
- //Ifthisactivitywasalreadyidle,thenwenowneedto
- //makesureweperformthefullstopofanyactivities
- //thatarewaitingtodoso.Thisisbecausewewon't
- //dothatwhiletheyarestillwaitingforthisoneto
- //becomevisible.
- finalintN=stack.mWaitingVisibleActivities.size();
- if(N>0){
- for(inti=0;i<N;i++){
- ActivityRecordr=(ActivityRecord)
- stack.mWaitingVisibleActivities.get(i);
- r.waitingVisible=false;
- ......
- }
- stack.mWaitingVisibleActivities.clear();
- Messagemsg=Message.obtain();
- msg.what=ActivityStack.IDLE_NOW_MSG;
- stack.mHandler.sendMessage(msg);
- }
- }
- ......
- }
- }
- }
- ......
- }
- finalintN=stack.mWaitingVisibleActivities.size();
- if(N>0){
- for(inti=0;i<N;i++){
- ActivityRecordr=(ActivityRecord)
- stack.mWaitingVisibleActivities.get(i);
- r.waitingVisible=false;
- ......
- }
- stack.mWaitingVisibleActivities.clear();
- Messagemsg=Message.obtain();
- msg.what=ActivityStack.IDLE_NOW_MSG;
- stack.mHandler.sendMessage(msg);
- }
Step 2. ActivityStack.activityIdleInternal
这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityStack.java文件中:
- publicclassActivityStack{
- ......
- finalvoidactivityIdleInternal(IBindertoken,booleanfromTimeout,
- Configurationconfig){
- ......
- ArrayList<ActivityRecord>stops=null;
- ......
- intNS=0;
- ......
- synchronized(mService){
- ......
- //Atomicallyretrievealloftheotherthingstodo.
- stops=processStoppingActivitiesLocked(true);
- NS=stops!=null?stops.size():0;
- ......
- }
- inti;
- ......
- //Stopanyactivitiesthatarescheduledtodosobuthavebeen
- //waitingforthenextonetostart.
- for(i=0;i<NS;i++){
- ActivityRecordr=(ActivityRecord)stops.get(i);
- synchronized(mService){
- if(r.finishing){
- finishCurrentActivityLocked(r,FINISH_IMMEDIATELY);
- }else{
- ......
- }
- }
- }
- ......
- }
- ......
- }
Step 3.ActivityStack.finishCurrentActivityLocked
这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityStack.java文件中:
- publicclassActivityStack{
- ......
- privatefinalActivityRecordfinishCurrentActivityLocked(ActivityRecordr,
- intmode){
- ......
- returnfinishCurrentActivityLocked(r,index,mode);
- }
- privatefinalActivityRecordfinishCurrentActivityLocked(ActivityRecordr,
- intindex,intmode){
- ......
- //makesuretherecordiscleanedoutofotherplaces.
- mStoppingActivities.remove(r);
- mWaitingVisibleActivities.remove(r);
- ......
- finalActivityStateprevState=r.state;
- r.state=ActivityState.FINISHING;
- if(mode==FINISH_IMMEDIATELY
- ||prevState==ActivityState.STOPPED
- ||prevState==ActivityState.INITIALIZING){
- //Ifthisactivityisalreadystopped,wecanjustfinish
- //itrightnow.
- returndestroyActivityLocked(r,true)?null:r;
- }else{
- ......
- }
- returnr;
- }
- ......
- }
Step 4.ActivityStack.destroyActivityLocked
这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityStack.java文件中:
- publicclassActivityStack{
- ......
- finalbooleandestroyActivityLocked(ActivityRecordr,
- booleanremoveFromApp){
- ......
- booleanremovedFromHistory=false;
- ......
- finalbooleanhadApp=r.app!=null;
- if(hadApp){
- ......
- try{
- ......
- r.app.thread.scheduleDestroyActivity(r,r.finishing,
- r.configChangeFlags);
- }catch(Exceptione){
- ......
- }
- ......
- }else{
- ......
- }
- ......
- returnremovedFromHistory;
- }
- ......
- }
- r.app.thread.scheduleDestroyActivity(r,r.finishing,
- r.configChangeFlags);
Step 5.ApplicationThread.scheduleDestroyActivity
这个函数定义在frameworks/base/core/java/android/app/ActivityThread.java文件中:
- publicfinalclassActivityThread{
- ......
- privatefinalclassApplicationThreadextendsApplicationThreadNative{
- ......
- publicfinalvoidscheduleDestroyActivity(IBindertoken,booleanfinishing,
- intconfigChanges){
- queueOrSendMessage(H.DESTROY_ACTIVITY,token,finishing?1:0,
- configChanges);
- }
- ......
- }
- ......
- }
Step 6.ActivityThread.handleDestroyActivity
这个函数定义在frameworks/base/core/java/android/app/ActivityThread.java文件中:
- publicfinalclassActivityThread{
- ......
- privatefinalvoidhandleDestroyActivity(IBindertoken,booleanfinishing,
- intconfigChanges,booleangetNonConfigInstance){
- ......
- ActivityClientRecordr=performDestroyActivity(token,finishing,
- configChanges,getNonConfigInstance);
- if(r!=null){
- WindowManagerwm=r.activity.getWindowManager();
- Viewv=r.activity.mDecor;
- if(v!=null){
- ......
- if(r.activity.mWindowAdded){
- wm.removeViewImmediate(v);
- }
- ......
- }
- ......
- }
- ......
- }
- ......
- }
Step 7.LocalWindowManager.removeViewImmediate
这个函数定义在frameworks/base/core/java/android/view/Window.java文件中:
- publicabstractclassWindow{
- ......
- privateclassLocalWindowManagerimplementsWindowManager{
- ......
- publicfinalvoidremoveViewImmediate(Viewview){
- mWindowManager.removeViewImmediate(view);
- }
- ......
- privatefinalWindowManagermWindowManager;
- }
- ......
- }
Step 8.WndowManagerImpl.removeViewImmediate
这个函数定义在frameworks/base/core/java/android/view/WindowManagerImpl.java文件中:
- publicclassWindowManagerImplimplementsWindowManager{
- ......
- publicvoidremoveViewImmediate(Viewview){
- synchronized(this){
- intindex=findViewLocked(view,true);
- ViewRootroot=mRoots[index];
- ......
- root.die(true);
- ......
- }
- }
- ......
- }
Step 9. ViewRoot.die
这个函数定义在frameworks/base/core/java/android/view/ViewRoot.java文件中:
- publicfinalclassViewRootextendsHandlerimplementsViewParent,
- View.AttachInfo.Callbacks{
- ......
- publicvoiddie(booleanimmediate){
- if(immediate){
- doDie();
- }else{
- ......
- }
- }
- ......
- }
Step 10.ViewRoot.doDie
这个函数定义在frameworks/base/core/java/android/view/ViewRoot.java文件中:
- publicfinalclassViewRootextendsHandlerimplementsViewParent,
- View.AttachInfo.Callbacks{
- ......
- voiddoDie(){
- ......
- synchronized(this){
- ......
- if(mAdded){
- mAdded=false;
- dispatchDetachedFromWindow();
- }
- }
- }
- ......
- }
Step 11.ViewRoot.ispatchDetachedFromWindow
这个函数定义在frameworks/base/core/java/android/view/ViewRoot.java文件中:
- publicfinalclassViewRootextendsHandlerimplementsViewParent,
- View.AttachInfo.Callbacks{
- ......
- voiddispatchDetachedFromWindow(){
- ......
- if(mInputChannel!=null){
- if(mInputQueueCallback!=null){
- ......
- }else{
- InputQueue.unregisterInputChannel(mInputChannel);
- }
- }
- try{
- sWindowSession.remove(mWindow);
- }catch(RemoteExceptione){
- }
- ......
- }
- ......
- }
我们先来看注销注册在应用程序这一侧的Client端InputChannel,然后再回过头来分析注销注册在InputManager这一侧的Server端InputChannel。
Step 12.InputQueue.unregisterInputChannel
这个函数定义在frameworks/base/core/java/android/view/InputQueue.java文件中:
- publicfinalclassInputQueue{
- ......
- publicstaticvoidunregisterInputChannel(InputChannelinputChannel){
- ......
- synchronized(sLock){
- ......
- nativeUnregisterInputChannel(inputChannel);
- }
- }
- ......
- }
Step 13.InputQueue.nativeUnregisterInputChannel
这个函数定义在frameworks/base/core/jni/android_view_InputQueue.cpp文件中:
- staticvoidandroid_view_InputQueue_nativeUnregisterInputChannel(JNIEnv*env,jclassclazz,
- jobjectinputChannelObj){
- status_tstatus=gNativeInputQueue.unregisterInputChannel(env,inputChannelObj);
- ......
- }
Step 14.NativeInputQueue.unregisterInputChannel
这个函数定义在frameworks/base/core/jni/android_view_InputQueue.cpp文件中:
- status_tNativeInputQueue::unregisterInputChannel(JNIEnv*env,jobjectinputChannelObj){
- sp<InputChannel>inputChannel=android_view_InputChannel_getInputChannel(env,
- inputChannelObj);
- ......
- {//acquirelock
- AutoMutex_l(mLock);
- ssize_tconnectionIndex=getConnectionIndex(inputChannel);
- ......
- sp<Connection>connection=mConnectionsByReceiveFd.valueAt(connectionIndex);
- mConnectionsByReceiveFd.removeItemsAt(connectionIndex);
- connection->status=Connection::STATUS_ZOMBIE;
- connection->looper->removeFd(inputChannel->getReceivePipeFd());
- env->DeleteGlobalRef(connection->inputHandlerObjGlobal);
- connection->inputHandlerObjGlobal=NULL;
- ......
- }//releaselock
- ......
- returnOK;
- }
- ssize_tconnectionIndex=getConnectionIndex(inputChannel);
- ......
- sp<Connection>connection=mConnectionsByReceiveFd.valueAt(connectionIndex);
- mConnectionsByReceiveFd.removeItemsAt(connectionIndex);
- connection->looper->removeFd(inputChannel->getReceivePipeFd());
最后将Connection对象中的回调对象inputHandlerOjbGlobal对象删除:
- env->DeleteGlobalRef(connection->inputHandlerObjGlobal);
- connection->inputHandlerObjGlobal=NULL;
注册在应用程序这一侧的Client端InputChannel被注销以后,回到前面的Step 11中,我们继续分析注销注册在InputManager这一侧的Server端InputChannel。
Step 15. WindowManagerService.Session.remove
这个函数定义在frameworks/base/services/java/com/android/server/WindowManagerService.java文件中:
- publicclassWindowManagerServiceextendsIWindowManager.Stub
- implementsWatchdog.Monitor{
- ......
- privatefinalclassSessionextendsIWindowSession.Stub
- implementsIBinder.DeathRecipient{
- ......
- publicvoidremove(IWindowwindow){
- removeWindow(this,window);
- }
- ......
- }
- ......
- }
这个函数只是简单地调用其外部类WindowManagerService的removeWindow函数来进一步执行操作。
Step 16.WindowManagerService.removeWindow
这个函数定义在frameworks/base/services/java/com/android/server/WindowManagerService.java文件中:
- publicclassWindowManagerServiceextendsIWindowManager.Stub
- implementsWatchdog.Monitor{
- ......
- publicvoidremoveWindow(Sessionsession,IWindowclient){
- synchronized(mWindowMap){
- WindowStatewin=windowForClientLocked(session,client,false);
- if(win==null){
- return;
- }
- removeWindowLocked(session,win);
- }
- }
- ......
- }
回忆一下前面我们在分析应用程序注册键盘消息管道的过程时,在Step 11(WindowManagerService.addWindow)中,WindowManagerService为这个即将要**的Activity窗口创建了一个WindowState对象win,创建的时候,使用了从ViewRoot中传过来的两个参数,分别是一个Session对象session和一个IWindow对象client。
在这个函数中,ViewRoot传过来的两个参数session和client和上面说的两个参数是一致的,因此,这个函数首先通过参数session和client得到一个WindowState对象win,然后调用removeWindowLocked来把它从WindowManagerService删除。
Step 17.WindowManagerService.removeWindowLocked
这个函数定义在frameworks/base/services/java/com/android/server/WindowManagerService.java文件中:
- publicclassWindowManagerServiceextendsIWindowManager.Stub
- implementsWatchdog.Monitor{
- ......
- publicvoidremoveWindowLocked(Sessionsession,WindowStatewin){
- ......
- win.disposeInputChannel();
- ......
- }
- ......
- }
Step 18. WindowState.disposeInputChannel
这个函数定义在frameworks/base/services/java/com/android/server/WindowManagerService.java文件中:
- publicclassWindowManagerServiceextendsIWindowManager.Stub
- implementsWatchdog.Monitor{
- ......
- privatefinalclassWindowStateimplementsWindowManagerPolicy.WindowState{
- ......
- voiddisposeInputChannel(){
- if(mInputChannel!=null){
- mInputManager.unregisterInputChannel(mInputChannel);
- mInputChannel.dispose();
- mInputChannel=null;
- }
- }
- ......
- }
- ......
- }
Step 19. InputManager.unregisterInputChannel
这个函数定义在frameworks/base/services/java/com/android/server/InputManager.java文件中:
- publicclassInputManager{
- ......
- publicvoidunregisterInputChannel(InputChannelinputChannel){
- ......
- nativeUnregisterInputChannel(inputChannel);
- }
- ......
- }
Step 20.InputManager.nativeUnregisterInputChannel
这个函数定义在frameworks/base/services/jni/com_android_server_InputManager.cpp文件中:
- staticvoidandroid_server_InputManager_nativeUnregisterInputChannel(JNIEnv*env,jclassclazz,
- jobjectinputChannelObj){
- ......
- sp<InputChannel>inputChannel=android_view_InputChannel_getInputChannel(env,
- inputChannelObj);
- ......
- status_tstatus=gNativeInputManager->unregisterInputChannel(env,inputChannel);
- ......
- }
Step 21.NativeInputManager.unregisterInputChannel
这个函数定义在frameworks/base/services/jni/com_android_server_InputManager.cpp文件中:
- status_tNativeInputManager::unregisterInputChannel(JNIEnv*env,
- constsp<InputChannel>&inputChannel){
- ......
- returnmInputManager->getDispatcher()->unregisterInputChannel(inputChannel);
- }
Step 22.InputDispatcher.unregisterInputChannel
这个函数定义在frameworks/base/libs/ui/InputDispatcher.cpp文件中:
- status_tInputDispatcher::unregisterInputChannel(constsp<InputChannel>&inputChannel){
- ......
- {//acquirelock
- AutoMutex_l(mLock);
- ssize_tconnectionIndex=getConnectionIndexLocked(inputChannel);
- ......
- sp<Connection>connection=mConnectionsByReceiveFd.valueAt(connectionIndex);
- mConnectionsByReceiveFd.removeItemsAt(connectionIndex);
- ......
- mLooper->removeFd(inputChannel->getReceivePipeFd());
- .....
- }//releaselock
- ......
- returnOK;
- }
- ssize_tconnectionIndex=getConnectionIndexLocked(inputChannel);
- ......
- sp<Connection>connection=mConnectionsByReceiveFd.valueAt(connectionIndex);
- mConnectionsByReceiveFd.removeItemsAt(connectionIndex);
这样,应用程序注销键盘消息接收通道的过程就分析完成了,整个应用程序键盘消息处理机制也分析完成了,这是一个比较复杂的过程,要完全理解它还需要花费一些努力和时间,不过,理解了这个过程之后,对Android应用程序框架层的理解就更进一步了。