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

发布于:2021-11-29 01:17:36

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的传递

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

    【创建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


    【创建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中有三种窗口


      应用程序窗口,Anctivity/Dialog,需将token设置成Activity的token子窗口,PopupWindow,需将token设置成它所附着宿主窗口的token系统窗口 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;
    }
    }
    }

    【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);
    //以键值对形式保存到mTokenMap表中
    //mTokenMap中的token已经在在AMS->WMS时添加了
    if (addToken) {
    mTokenMap.put(attrs.token, token);
    }
    win.attach();
    //以键值对形式保存到mWindowMap表中
    mWindowMap.put(client.asBinder(), win);
    ...
    }


3、总结

相关推荐

最新更新

猜你喜欢