AMS-WMS-APP间的匿名Binder:Token

Token

涉及的代码路径如下:

frameworks/base/services/core/java/com/android/server/am/
  --- ActivityManagerService.java
  --- ProcessRecord.java
  --- ActivityRecord.java
  --- ActivityResult.java
  --- ActivityStack.java
  --- ActivityStackSupervisor.java
  --- ActivityStarter.java
  --- TaskRecord.java 

frameworks/base/core/java/com/android/internal/policy/
	--- DecorView.java
	--- PhoneWindow.java

frameworks/base/core/java/android/view/
	--- WindowManager.java
 	--- View.java
	--- ViewManager.java
	--- ViewRootImpl.java
	--- Window.java
	--- Display.java
	--- WindowManagerImpl.java
	--- WindowManager.java
	--- WindowManagerGlobal.java
	--- IWindowManager.aidl

frameworks/base/services/core/java/com/android/server/wm/
	---WindowManagerService.java
	---AppWindowToken.java

kernel/drivers/staging/android/binder.c

整体流程图:在这里插入图片描述

红色箭头:跨进程
红色框 :Token是它的实体端
黄色框 :Token的Binder代理端,
所以这里WMS和AMS之间的Token其实指向的是同一个

1、token的创建

Activity的启动中会在AMS服务中构建一个ActivityRecord实例对象来标记Activity,Token是ActivityRecord的静态内部类

ActivityStarter.startActivityLocked(...)
		  ActivityRecord r = new ActivityRecord(callerApp,intent,aInfo,mSupervisor,...)
			appToken = new Token(this, service);
				static class Token extends IApplicationToken.Stub { 
					....
				}

interface IApplicationToken
{
    void windowsDrawn();
    void windowsVisible();
    void windowsGone();
    boolean keyDispatchingTimedOut(String reason);
    long getKeyDispatchingTimeout();
}

匿名Binder实体会传递给其他进程,其它进程拿到的是Token的代理端IApplicationToken.Stub.Proxy

2、token的传递
  1. 【创建AMS的appToken】 Activity的启动过程中会在AMS中创建一个构建一个ActivityRecord实例对象来标记Activity,构造过程中会创建一个Token的Binder实体对象保存在ActivityRecord的appToken成员变量之中,见P1

  2. 【创建WMS的appToken】 AMS创建完Token之后会调用WMS服务的addAppToken()方法在WMS中构建一个AppWindowToken实例对象,然后将Token对象保存在它的appToken成员变量之中

    在Activity的启动过程中,AMS会调用startActivityLocked()方法向WMS服务传递Token实体对象

    ActivityStarter.startActivityUnchecked()--->
    	ActivityStack.startActivityLocked()--->
    		addConfigOverride()---->
    			mWindowManager.addAppToken()--->
    
    //[WindowManagerService.java]
        @Override
        public void addAppToken(...,IApplicationToken token,...) {
                ...
                //生成ActivityRecord在WMS中对应的AppWindowToken,见P2
                atoken = new AppWindowToken(this, token, voiceInteraction);
                ...
           		 	//如果没有Task, 就创建一个task, 并加入到stack中,
                //这里的task/stack都是与AMS中task/stack就一一对应的            	
                Task task = mTaskIdToTask.get(taskId);
                if (task == null) {
                  task = createTaskLocked(taskId, stackId, userId, atoken, taskBounds, config);
                }
                //将AppWindowToken加入到task中管理起来,见P3
                task.addAppToken(addPos, atoken, taskResizeMode, homeTask);
    						//加入到mTokenMap中,见P4
                mTokenMap.put(token.asBinder(), atoken);
        }
    

    作用

    WindowManagerService中AppWindowToken保存着ActivityManagerService的Binder对象,用来向AMS传递Window和按键的一些信息。另外的一个用处是作为 mTokenMap的key

  3. 【创建APP的token】 token将其代理通过AMS跨进程调用ActivityThread的scheduleLaunchActivity()方法传递到ActivityThread类中,然后将其保存在ActivityClientRecord、Activity、Window、WindowManager.LayoutParams的token成员变量中

    ActivityClientRecord

    attachApplicationLocked
       realStartActivityLocked
           app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken, );
    
    public final void scheduleLaunchActivity(Intent intent, IBinder token, ) {
               //生成App中的ActivityClientRecord
               ActivityClientRecord r = new ActivityClientRecord();
               r.token = token;  //将AMS中的token保存到 ActivityClientRecord中 见P5
    }
    

    Activity,调用它的attach()方法,见P6

    //[Activity.java]
       final void attach(..., IBinder token, ...) {
               ...
               mToken = token;
               ...
        }
    

    Window,调用它的setWindowManager()方法

    //[Window.java]
    
       public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
               boolean hardwareAccelerated) {
           mAppToken = appToken;//将Token的Binder代理端赋予Window的mAppToken成员变量,见P7
           mAppName = appName;
           mHardwareAccelerated = hardwareAccelerated
                   || SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
           if (wm == null) {
               wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
           }
           mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
       }
    //每一个Window对象都有一个mAppToken变量,dialog为空
    

    WindowManager.LayoutParams中有三种窗口

    1. 应用程序窗口,Anctivity/Dialog,需将token设置成Activity的token
    2. 子窗口,PopupWindow,需将token设置成它所附着宿主窗口的token
    3. 系统窗口 Toast/输入法
    WindowManagerImpl.addView()--->
    WindowManagerGlobal.addView()--->
    Window--->adjustLayoutParamsForSubWindow
    见P8
    //[Window.java]
       void adjustLayoutParamsForSubWindow(WindowManager.LayoutParams wp) {
    		/*
    			判断窗口类型是不是子窗口
    		*/
    		if (wp.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
                   wp.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
               if (wp.token == null) {
                   View decor = peekDecorView();
                   if (decor != null) {
    										//LayoutParams的token设置为W本地Binder对象
                       wp.token = decor.getWindowToken();
                   }
               }
    			...
           } else if (wp.type >= WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW &&
                   wp.type <= WindowManager.LayoutParams.LAST_SYSTEM_WINDOW) {
      			//当是系统窗口时token为null
    				...
           } else {
           	/*
           		最后一种类型,通常为Activity的窗口类型
           		则设置token为当前窗口的IApplicationToken.Proxy代理对象,
           		否则设置为父窗口的IApplicationToken.Proxy代理对象
           	*/
               if (wp.token == null) {
                   wp.token = mContainer == null ? mAppToken : mContainer.mAppToken;
               }
           }
       }
    
  4. 【App与WMS使用token通信】 Window通过windowManager跨进程调用WMS的addWindow()对添加activity的窗口进行管理,此过程中携带token的Binder代理 (WindowState中的token)

    ViewRootImpl.setView()--->
    	mWindowSession.addToDisplay()--->
    		Session.addToDisplay()--->
    			WMS.addWindow()--->
    
    //[WindowManagerService.java]
        public int addWindow(..., IWindow client, WindowManager.LayoutParams attrs, ...) {
    			//这里的client为IWindow的代理对象,用于WMS和Activity进行通信
    			...
    			//根据attrs.token从mWindowMap中取出应用程序窗口在WMS服务中的描述符WindowState
                WindowToken token = mTokenMap.get(attrs.token);
                AppWindowToken atoken = null;
    			//为Activity窗口创建WindowState对象,见P9
                WindowState win = new WindowState(this, session, client, token,
                        attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
    			//以键值对<IWindow.Proxy/Token,WindowToken>形式保存到mTokenMap表中
          //mTokenMap中的token已经在在AMS->WMS时添加了
                if (addToken) {
                    mTokenMap.put(attrs.token, token);
                }
                win.attach();
    			//以键值对<IWindow的代理对象,WindowState>形式保存到mWindowMap表中
                mWindowMap.put(client.asBinder(), win);
    			...
    	}
    
3、总结

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Qi T

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值