1.      IApplicationToken初始化:

        IApplicationToken.aidl的服务端IApplicationToken.Stub的对象在ActivityRecord中定义持有。在ActivityRecord初始化的时候同时做初始化。正常一个activity对应一个activityrecord对象同时对应一个appwindowtoken对象。android 8.0 appwindowtoken通过初始化AppWindowContainerController对象后,通过AppWindowContainerController对象的createAppWindow对象。同时会将ActivityRecord持有的ApplicationToken.stub对象传给AppWindowToken对象。android 10.0是直接初始化。这样AppWindowToken和ActivityRecord同时持有ApplicationToken.stub对象appToken。AppWindowToken初始化后,会执行父类的构造函数

super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true, dc,                false /* ownerCanManageAppTokens */);
WindowToken(WindowManagerService service, IBinder _token, int type, boolean persistOnEmpty,            DisplayContent dc, boolean ownerCanManageAppTokens) {        mService = service;        token = _token;        windowType = type;        mPersistOnEmpty = persistOnEmpty;        mOwnerCanManageAppTokens = ownerCanManageAppTokens;        onDisplayChanged(dc);    }

 

   构造函数里面会执行onDisplayChanged方法,执行DisplayContent的reParentWindowToken方法,里面会把这个_token和AppWindowToken对象放到它的mTokenMap中

mTokenMap.put(binder, token);

 

       具体这个DisplayContent怎么初始化,干啥的,后面文章再讲。现在知道它是个统管。

 

         当activity启动的时候,10.0的版本ATMS中是通过LaunchActivityItem,启动应用端的activity。在ActivityStackSupervisor的realStartActivityLocked方法中有这样一段代码,下面这个代码段,获取了r.appToken,就是上面创建的appToken,传入。通过LaunchActivityItem带入到应用端。

// Create activity launch transaction.                final ClientTransaction clientTransaction = ClientTransaction.obtain(                        proc.getThread(), r.appToken);                final DisplayContent dc = r.getDisplay().mDisplayContent;                clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),                        System.identityHashCode(r), r.info,                        // TODO: Have this take the merged configuration instead of separate global                        // and override configs.                        mergedConfiguration.getGlobalConfiguration(),                        mergedConfiguration.getOverrideConfiguration(), r.compat,                        r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),                        r.icicle, r.persistentState, results, newIntents,                        dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(),                                r.assistToken));                // Set desired final stat

 

 

       LaunchActivityItem的execute方法,会调用ActivityThread的handleLaunchActivity方法。里面构建ActivityClientRecord(应用端的ActivityRecord),ActivityRecord的appToken就在里面,ActivityThread.handleLaunchActivity调用preformLaunchActivity,之后调用到了调用Activity.attach方法,同时将ActivityClientRecord对象传入,将appToken给Activity的mToken。这个时候客户端的activityrecord持有的apptoken和activity持有的mToken是同一个token

       在ActivityThread执行handleResumeActivity的时候,会执行wm.addview,这个wm是从activity获取的mWindowManager 对象,mWindowManager 是WindowManager的实例,Windowmanager继承自ViewManager,从Windowmanager.java的注释上看,它是app和window manager沟通的桥梁。那么这个wm是在哪里初始化的?在执行activity的attach的时候 ,会创建一个Activity的持有的Window的实例mWindow对象,具体实现是PhoneWindow。代码:mWindow = new PhoneWindow(this, window, activityConfigCallback);  这个时候初始化好mWindow后开始执行mWindow的 setWindowManager 方法:

public void setWindowManager(WindowManager wm, IBinder appToken, String appName,            boolean hardwareAccelerated) {        mAppToken = appToken;        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);    }

 

 这个时候就在mWindow里面创建好了mWindowmanager对象实例是WindowmanagerImpl. 同时activity里面执行        mWindowManager = mWindow.getWindowManager();  那么自此这个wm对象来历已经清楚了,是Activity持有的mWindow里面初始化好后返回给Activity,同时Activity用mWindowManager 保存,供使用。

        回到刚刚那个wm.addview里面参数一个decor,一个l,这两个都是解析的activity布局文件获取的。暂时不做分析,后面会专门写一篇相关文档分析。这边只要知道把activity要显示的布局decor和参数l带过去了。addview实际执行的应该就是刚刚那个WindowManagerImpl里面。addview有下面这段代码:

if (parentWindow != null) {            parentWindow.adjustLayoutParamsForSubWindow(wparams);        } else {            // If there's no parent, then hardware acceleration for this view is            // set from the application's hardware acceleration setting.            final Context context = view.getContext();            if (context != null                    && (context.getApplicationInfo().flags                            & ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) {                wparams.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;            }        }

 

  由于这个parentWindow是刚刚activity里面创建的mWindow对象,所以走的if条件。adjustLayoutParamsForSubWindow方法,里面先判断窗口的type类型,作为activity,走的下面这个:

} else {            if (wp.token == null) {                wp.token = mContainer == null ? mAppToken : mContainer.mAppToken;            }            if ((curTitle == null || curTitle.length() == 0)                    && mAppName != null) {                wp.setTitle(mAppName);            }        }

 

这段代码会把mAppToken给LayoutParams对象的token。这个mAppToken就是之前讲的Activity的mToken,在PhoneWindow初始化的时候给它的。后面就是初始化ViewRootImpl:

root = new ViewRootImpl(view.getContext(), display);            view.setLayoutParams(wparams);            mViews.add(view);            mRoots.add(root);            mParams.add(wparams);            // do this last because it fires off messages to start doing things            try {                root.setView(view, wparams, panelParentView);

 

  这边执行完后会把viewrootimpl放到mRoots数组里面,同时会执行setView方法,里面会带入view和wparams。

这个setview方法重点关注下下面这个代码:

res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,getHostVisibility(), mDisplay.getDisplayId(),mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mAttachInfo.mOutsets, mInputChannel);

 

这里面传入的参数mWidowAttributes,这里addToDisplay是在Session.java里面执行的,这里面会执行到Wms的addWidow方法,这里面有几行关键的代码:

WindowToken token = displayContent.getWindowToken(                    hasParent ? parentWindow.mAttrs.token : attrs.token);

 

这里的attrs.token就是刚刚addview的时候赋值的,通过displayContent.getWindowToken方法获取到WindowToken,里面参数即是实际上ActivityRecord里面的mAppToken。这个displayContent后面文章会写,看下这个getWindowToken方法

WindowToken getWindowToken(IBinder binder) {        return mTokenMap.get(binder);    }

那这个就很明显了,会获取到之前存储的对应的AppWindowToken。那么这个时候就可以传入token,初始化对应的WindowState了,并且把windowstate设置为AppWindowToken的子WindowToken:win.mToken.addWindow(win);

final WindowState win = new WindowState(this, session, client, token, parentWindow,                    appOp[0], seq, attrs, viewVisibility, session.mUid,                    session.mCanAddInternalSystemWindow);

 

至此,IApplicationToken在初始化到WindowState创建过程中的作用和关系阐明清楚了。应该说它是一个activity的几个重要的文件中的重要的标识。

 

更多相关文章

  1. android学习资料与资源记录
  2. Android应用程序组件Content Provider在应用程序之间共享数据的
  3. Android(安卓)面试题(经典)
  4. appt命令检测Apk信息的方法
  5. android通用适配器
  6. android实时监听网络状态并在断网的情况下打开网络设置
  7. 〖Android〗arm-linux-androideabi-gdb报 libpython2.6.so.1.0:
  8. Android中的几种网络请求方式
  9. 使用googleMap获取api方法

随机推荐

  1. SpringBoot使用前缀树过滤敏感词的方法实
  2. SpringBoot使用前缀树过滤敏感词的方法实
  3. 学绘画如何入门?绘画新手入门教程
  4. 5G时代,中国招标采购网如何推动大数据招投
  5. 华纳小陈z18788371515
  6. 怎么学绘画透视?透视画法教程
  7. 用云服务器如何搭建ftp?
  8. Eclipse阿里云镜像源配置
  9. CentOS系统如何使用YUM命令方便快捷安装N
  10. 你了解可预测COVID-19病例峰值的新算法嘛