当前位置: 首页 > news >正文

辽宁省住房城乡建设厅网站站长之家站长工具综合查询

辽宁省住房城乡建设厅网站,站长之家站长工具综合查询,网站建设开发怎么选专业,重庆网站建设报价在安卓源码的设计中#xff0c;将将屏幕分为了37层#xff0c;不同的窗口将在不同的层级中显示。 对这一块的概念以及相关源码做了详细分析#xff0c;整理出以下几篇。 【Android 13源码分析】WindowContainer窗口层级-1-初识窗口层级树 【Android 13源码分析】WindowCon…在安卓源码的设计中将将屏幕分为了37层不同的窗口将在不同的层级中显示。 对这一块的概念以及相关源码做了详细分析整理出以下几篇。 【Android 13源码分析】WindowContainer窗口层级-1-初识窗口层级树 【Android 13源码分析】WindowContainer窗口层级-2-构建流程 【Android 13源码分析】WindowContainer窗口层级-3-实例分析 【Android 13源码分析】WindowContainer窗口层级-4-Surface树 当前为第三篇以应用窗口和系统窗口2大类型窗口的挂载为例介绍窗口是如何挂载到层级树中的。 这篇看完对AOSP中整个窗口树就有了比较完整的了解。 1. 应用窗口挂载 应用启动流程中会触发ActivityRecordTaskWindowState的创建与挂载其中WindowState的处理上在addWindow流程。 ActivityTaskManagerService::startActivityActivityTaskManagerService::startActivityAsUserActivityTaskManagerService::startActivityAsUserActivityStartController::obtainStarterActivityStarter::executeActivityStarter::executeRequest -- 构建 ActivityRecord --2.2.1 创建ActivityRecordActivityStarter::startActivityUncheckedActivityStarter::startActivityInner -- 2.2.2 关键函数startActivityInnerActivityStarter::getOrCreateRootTask -- 2.2.2.1 创建或者拿到TaskActivityStarter::setNewTask -- 2.2.2.2 将task与activityRecord 绑定RootWindowContainer::resumeFocusedTasksTopActivities --2.2.2.3 显示ActivityaddWindow流程调用链 WindowManagerImpl::addView --- 创建ViewRootImplWindowManagerGlobal::addView ViewRootImpl::setView --- 与WMS通信 addViewSession.addToDisplayAsUserWindowManagerService::addWindowWindowState::init -- WindowState的创建WindowToken::addWindow -- WindowState的挂载1.1 ActivityRecord的创建 启动流程开始的时候会执行到ActivityStarter::executeRequest在这个方法里会创建一个ActivityRecord # ActivityStarterprivate int executeRequest(Request request) {......final ActivityRecord r new ActivityRecord.Builder(mService).setCaller(callerApp).setLaunchedFromPid(callingPid).setLaunchedFromUid(callingUid).setLaunchedFromPackage(callingPackage).setLaunchedFromFeature(callingFeatureId).setIntent(intent).setResolvedType(resolvedType).setActivityInfo(aInfo).setConfiguration(mService.getGlobalConfiguration()).setResultTo(resultRecord).setResultWho(resultWho).setRequestCode(requestCode).setComponentSpecified(request.componentSpecified).setRootVoiceInteraction(voiceSession ! null).setActivityOptions(checkedOptions).setSourceRecord(sourceRecord).build();......// 继续执行startActivityUncheckedmLastStartActivityResult startActivityUnchecked(r, sourceRecord, voiceSession,request.voiceInteractor, startFlags, true /* doResume */, checkedOptions,inTask, inTaskFragment, restrictedBgActivity, intentGrants);......}tips: ActivityRecord的构造方法会创建一个Token,这个token就是阅读源码经常看到看到代表activity的那个token。 1.2 Task的创建与挂载 流程开始会执行到ActivityStarter::startActivityInner方法在这里会执行ActivityStarter::getOrCreateRootTask方法来创建获取一个Task 调用链如下 ActivityStarter::getOrCreateRootTaskRootWindowContainer::getOrCreateRootTaskRootWindowContainer::getOrCreateRootTaskTaskDisplayArea::getOrCreateRootTaskTaskDisplayArea::getOrCreateRootTaskTask::Build ---创建Task主流程代码 # ActivityStarterprivate Task getOrCreateRootTask(ActivityRecord r, int launchFlags, Task task,ActivityOptions aOptions) {final boolean onTop (aOptions null || !aOptions.getAvoidMoveToFront()) !mLaunchTaskBehind;final Task sourceTask mSourceRecord ! null ? mSourceRecord.getTask() : null;return mRootWindowContainer.getOrCreateRootTask(r, aOptions, task, sourceTask, onTop,mLaunchParams, launchFlags);}// onTop 表示是否要移到到当前栈顶那肯定是要的新启动的Activity当前要再最上面这里 aOptions 为null所以为true// sourceTask 表示从哪里启动的当前launch所在的Task 就是sourceTask# RootWindowContainerTask getOrCreateRootTask(Nullable ActivityRecord r, Nullable ActivityOptions options,Nullable Task candidateTask, boolean onTop) {return getOrCreateRootTask(r, options, candidateTask, null /* sourceTask */, onTop,null /* launchParams */, 0 /* launchFlags */);}Task getOrCreateRootTask(Nullable ActivityRecord r,Nullable ActivityOptions options, Nullable Task candidateTask,Nullable Task sourceTask, boolean onTop,Nullable LaunchParamsController.LaunchParams launchParams, int launchFlags) {......final int activityType resolveActivityType(r, options, candidateTask);if (taskDisplayArea ! null) {if (canLaunchOnDisplay(r, taskDisplayArea.getDisplayId())) {// 重点*1. 传递到TaskDisplayAreareturn taskDisplayArea.getOrCreateRootTask(r, options, candidateTask,sourceTask, launchParams, launchFlags, activityType, onTop);} else {taskDisplayArea null;}}......}// 经过同名调用后逻辑进入到 TaskDisplayArea# TaskDisplayAreaTask getOrCreateRootTask(int windowingMode, int activityType, boolean onTop,Nullable Task candidateTask, Nullable Task sourceTask,Nullable ActivityOptions options, int launchFlags) {if(....) {// 拿到之前创建的Taskreturn candidateTask.getRootTask();}......// 第一次显示所以是新建Taskreturn new Task.Builder(mAtmService).setWindowingMode(windowingMode).setActivityType(activityType).setOnTop(onTop).setParent(this) // 主要这个this被设置为Parent。所以直接挂载到了DefaultTaskDisplayArea下.setSourceTask(sourceTask).setActivityOptions(options).setLaunchFlags(launchFlags).build();}// 看方法名是获取或创建Task, 这边是新启动的Activity所以需要创建Task。如果是以默认启动方式打开应用内的另一个Activity就走的是上面的 return candidateTask.getRootTask();接下来就是真正触发Task的创建。// 另外设置的parent就是层级结构树应用所在的名为“DefaultTaskDisplayArea”的TaskDisplayArea# Task# Task.BuilderTask build() {if (mParent ! null mParent instanceof TaskDisplayArea) {validateRootTask((TaskDisplayArea) mParent);}if (mActivityInfo null) {mActivityInfo new ActivityInfo();mActivityInfo.applicationInfo new ApplicationInfo();}mUserId UserHandle.getUserId(mActivityInfo.applicationInfo.uid);mTaskAffiliation mTaskId;mLastTimeMoved System.currentTimeMillis();mNeverRelinquishIdentity true;mCallingUid mActivityInfo.applicationInfo.uid;mCallingPackage mActivityInfo.packageName;mResizeMode mActivityInfo.resizeMode;mSupportsPictureInPicture mActivityInfo.supportsPictureInPicture();if (mActivityOptions ! null) {mRemoveWithTaskOrganizer mActivityOptions.getRemoveWithTaskOranizer();}// 重点* 1. 创建taskfinal Task task buildInner();task.mHasBeenVisible mHasBeenVisible;// Set activity type before adding the root task to TaskDisplayArea, so home task can// be cached, see TaskDisplayArea#addRootTaskReferenceIfNeeded().if (mActivityType ! ACTIVITY_TYPE_UNDEFINED) {task.setActivityType(mActivityType);}// 重点* 2. 入栈 这里的 mOnTop为trueif (mParent ! null) {if (mParent instanceof Task) {final Task parentTask (Task) mParent;parentTask.addChild(task, mOnTop ? POSITION_TOP : POSITION_BOTTOM,(mActivityInfo.flags FLAG_SHOW_FOR_ALL_USERS) ! 0);} else {mParent.addChild(task, mOnTop ? POSITION_TOP : POSITION_BOTTOM);}}// Set windowing mode after attached to display area or it abort silently.if (mWindowingMode ! WINDOWING_MODE_UNDEFINED) {task.setWindowingMode(mWindowingMode, true /* creating */);}// 返回return task;}// 创建Task buildInner() {return new Task(mAtmService, mTaskId, mIntent, mAffinityIntent, mAffinity,mRootAffinity, mRealActivity, mOrigActivity, mRootWasReset, mAutoRemoveRecents,mAskedCompatMode, mUserId, mEffectiveUid, mLastDescription, mLastTimeMoved,mNeverRelinquishIdentity, mLastTaskDescription, mLastSnapshotData,mTaskAffiliation, mPrevAffiliateTaskId, mNextAffiliateTaskId, mCallingUid,mCallingPackage, mCallingFeatureId, mResizeMode, mSupportsPictureInPicture,mRealActivitySuspended, mUserSetupComplete, mMinWidth, mMinHeight,mActivityInfo, mVoiceSession, mVoiceInteractor, mCreatedByOrganizer,mLaunchCookie, mDeferTaskAppear, mRemoveWithTaskOrganizer);}小结 最后描述一下最后创建的2个重点部分 看到通过buildInner 创建了一个task而buildInner 也很简单粗暴通过各个变量直接new Task 对象。mParent 不为null 是 因为在创建的时候 setParentthis,当前的这个this就是 getDefaultTaskDisplayArea返回的也就是应用Activity存在的DefaultTaskDisplayArea。 在 RootWindowContainer::getOrCreateRootTask 体现。 注意log里的 #17 的这个Task与前面的层级结构树新增的Task,是对应的上的。而且this DefaultTaskDisplayArea 说明也确实是往DefaultTaskDisplayArea里添加了。 1.3 ActivityRecord的挂载 调用链 ActivityStarer::setNewTask ActivityStarer::addOrReparentStartingActivity 主流程代码 # ActivityStarerprivate void setNewTask(Task taskToAffiliate) {// 为truefinal boolean toTop !mLaunchTaskBehind !mAvoidMoveToFront;// 就是mTargetRootTask,也就是刚刚创建的Taskfinal Task task mTargetRootTask.reuseOrCreateTask(mNewTaskInfo ! null ? mNewTaskInfo : mStartActivity.info,mNewTaskIntent ! null ? mNewTaskIntent : mIntent, mVoiceSession,mVoiceInteractor, toTop, mStartActivity, mSourceRecord, mOptions);task.mTransitionController.collectExistenceChange(task);// ActivityRecord的挂载addOrReparentStartingActivity(task, setTaskFromReuseOrCreateNewTask);// 需要注意这里的日志打印ProtoLog.v(WM_DEBUG_TASKS, Starting new activity %s in new task %s,mStartActivity, mStartActivity.getTask());// mLaunchTaskBehind 为false所以taskToAffiliate 为null if (taskToAffiliate ! null) {mStartActivity.setTaskToAffiliateWith(taskToAffiliate);}}这里的task 和mTargetRootTask是同一个对象 进源码跟到流程也是一样。 然后进入 addOrReparentStartingActivity # ActivityStarerprivate void addOrReparentStartingActivity(NonNull Task task, String reason) {// newParent task 都是刚刚创建的TaskTaskFragment newParent task;......if (mStartActivity.getTaskFragment() null|| mStartActivity.getTaskFragment() newParent) {// 重点 将 ActivityRecord挂在到新创建的Task中并且是顶部newParent.addChild(mStartActivity, POSITION_TOP);} else {mStartActivity.reparent(newParent, newParent.getChildCount() /* top */, reason);}}这里的逻辑设计到的Task就是上一步创建的TaskmStartActivity则是“电话”在之前逻辑创建的ActivityRecord. setNewTask的堆栈信息如下 另外这段逻辑里有个ProtoLog打印日志如下 1.4 WindowState的创建与挂载 WindowManagerService::addWindowWindowState::init -- WindowState的创建WindowToken::addWindow -- WindowState的挂载# WindowManagerServicepublic int addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility,int displayId, int requestUserId, InsetsVisibilities requestedVisibilities,InputChannel outInputChannel, InsetsState outInsetsState,InsetsSourceControl[] outActiveControls) {......// token处理// 创建WindowStatefinal WindowState win new WindowState(this, session, client, token, parentWindow,appOp[0], attrs, viewVisibility, session.mUid, userId,session.mCanAddInternalSystemWindow);......// 7. 窗口添加进容器win.attach();......win.mToken.addWindow(win);......}win.mToken窗口的token是ActyivityRecord# ActivityRecordOverridevoid addWindow(WindowState w) {super.addWindow(w);......}直接调用其父类方法ActivityRecord是WindowToken# WindowTokenvoid addWindow(final WindowState win) {ProtoLog.d(WM_DEBUG_FOCUS,addWindow: win%s Callers%s, win, Debug.getCallers(5));if (win.isChildWindow()) {// Child windows are added to their parent windows.return;}// This token is created from WindowContext and the client requests to addView now, create a// surface for this token.// 真正添加进子容器调用的是WindowContainer的方法if (!mChildren.contains(win)) {ProtoLog.v(WM_DEBUG_ADD_REMOVE, Adding %s to %s, win, this);// 定义在WindowContainer中其实就是挂载到父容器下了addChild(win, mWindowComparator);mWmService.mWindowsChanged true;// TODO: Should we also be setting layout needed here and other places?}}2. 系统窗口挂载 2.1 WindowToken,WindowState的创建与挂载 public int addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility,int displayId, int requestUserId, InsetsVisibilities requestedVisibilities,InputChannel outInputChannel, InsetsState outInsetsState,InsetsSourceControl[] outActiveControls) {......// 系统应用获取不到tokenWindowToken token displayContent.getWindowToken(hasParent ? parentWindow.mAttrs.token : attrs.token);......if (token null) {......} else {final IBinder binder attrs.token ! null ? attrs.token : client.asBinder();token new WindowToken.Builder(this, binder, type).setDisplayContent(displayContent).setOwnerCanManageAppTokens(session.mCanAddInternalSystemWindow).setRoundedCornerOverlay(isRoundedCornerOverlay).build();}}// 创建WindowStatefinal WindowState win new WindowState(this, session, client, token, parentWindow,appOp[0], attrs, viewVisibility, session.mUid, userId,session.mCanAddInternalSystemWindow);......// 窗口添加进容器win.attach();......win.mToken.addWindow(win);......WindowState的创建和应用窗口一样区别在与WindowToken系统窗口执行addWindow方法是没有token的所以会执行创建逻辑。 在创建的时候会根据窗口类型选择挂载的层级。 2.2 WindowToken的挂载 WMS::addWindowWindowToken::initDisplayContent::addWindowTokenmTokenMap::put -- 存入mTokenMapDisplayContent::findAreaForToken -- 找到对应的层级DisplayContent::findAreaForWindowTypeDisplayAreaPolicyBuilder.Result::findAreaForWindowTypeRootDisplayArea::findAreaForWindowTypeInLayer -- 在 mAreaForLayer中根据type查找对应的位置DisplayArea.Tokens::addChild -- 挂载WindowToken的构造方法如下 # WindowTokenprotected WindowToken(WindowManagerService service, IBinder _token, int type,boolean persistOnEmpty, DisplayContent dc, boolean ownerCanManageAppTokens,boolean roundedCornerOverlay, boolean fromClientToken, Nullable Bundle options) {super(service);token _token;windowType type;......if (dc ! null) {// 添加tokendc.addWindowToken(token, this);}}创建WindowToken的时候会由DisplayContent执行挂载逻辑 # DisplayContentDisplayAreaPolicy mDisplayAreaPolicy;void addWindowToken(IBinder binder, WindowToken token) {......// 放入集合mTokenMap.put(binder, token);if (token.asActivityRecord() null) {......// 找到对应的位置挂载final DisplayArea.Tokens da findAreaForToken(token).asTokens();da.addChild(token);}}DisplayArea findAreaForToken(WindowToken windowToken) {// 根据type查找return findAreaForWindowType(windowToken.getWindowType(), windowToken.mOptions,windowToken.mOwnerCanManageAppTokens, windowToken.mRoundedCornerOverlay);}DisplayArea findAreaForWindowType(int windowType, Bundle options,boolean ownerCanManageAppToken, boolean roundedCornerOverlay) {// 应用类型if (windowType FIRST_APPLICATION_WINDOW windowType LAST_APPLICATION_WINDOW) {return mDisplayAreaPolicy.getTaskDisplayArea(options);}// 输入法窗口if (windowType TYPE_INPUT_METHOD || windowType TYPE_INPUT_METHOD_DIALOG) {return getImeContainer();}// 其他类型return mDisplayAreaPolicy.findAreaForWindowType(windowType, options,ownerCanManageAppToken, roundedCornerOverlay);}状态栏不属于应用窗口走后面的逻辑DisplayAreaPolicy是个接口真正的实现是DisplayAreaPolicyBuilder的内部类Result # DisplayAreaPolicyBuilderstatic class Result extends DisplayAreaPolicy {final BiFunctionInteger, Bundle, RootDisplayArea mSelectRootForWindowFunc;......Overridepublic DisplayArea.Tokens findAreaForWindowType(int type, Bundle options,boolean ownerCanManageAppTokens, boolean roundedCornerOverlay) {return mSelectRootForWindowFunc.apply(type, options).findAreaForWindowTypeInLayer(type,ownerCanManageAppTokens, roundedCornerOverlay);}......}mSelectRootForWindowFunc是一个存放RootDisplayArea的map所以后续逻辑在RootDisplayArea中// 根据type 找到在容器树的位置 如果是应用或者输入法都走不到这# RootDisplayArea// 这个就是层级树的private DisplayArea.Tokens[] mAreaForLayer;NullableDisplayArea.Tokens findAreaForWindowTypeInLayer(int windowType, boolean ownerCanManageAppTokens,boolean roundedCornerOverlay) {// 获取到typeint windowLayerFromType mWmService.mPolicy.getWindowLayerFromTypeLw(windowType,ownerCanManageAppTokens, roundedCornerOverlay);if (windowLayerFromType APPLICATION_LAYER) {throw new IllegalArgumentException(There shouldnt be WindowToken on APPLICATION_LAYER);}// 根据type查找对应的位置return mAreaForLayer[windowLayerFromType];} getWindowLayerFromTypeLw会根据type找到对应的层级返回一个int。 然后根据这个值去mAreaForLayer拿到对应的DisplayArea.Tokens将系统窗口的WindowToken挂载进去 mAreaForLayer其实就是开始构建层级树的那个集合。 2.2.1 mAreaForLayer的赋值 在开机构建窗口层级树的逻辑最后会执行到RootDisplayArea::onHierarchyBuilt将层级树的集合传递出去。 # DisplayAreaPolicyBuilder.HierarchyBuilderprivate final RootDisplayArea mRoot;private void build(Nullable ListHierarchyBuilder displayAreaGroupHierarchyBuilders) {......// 层级树的构建// 通知根节点已经完成了所有DisplayArea的添加 将displayAreaForLayer保存在RootDisplayArea成员变量roomAreaForLayer中供后面逻辑使用mRoot.onHierarchyBuilt(mFeatures, displayAreaForLayer, featureAreas);}RootDisplayArea下的mAreaForLayer变量赋值 # RootDisplayAreaprivate DisplayArea.Tokens[] mAreaForLayer;void onHierarchyBuilt(ArrayListFeature features, DisplayArea.Tokens[] areaForLayer,MapFeature, ListDisplayAreaWindowContainer featureToDisplayAreas) {if (mHasBuiltHierarchy) {throw new IllegalStateException(Root should only build the hierarchy once);}mHasBuiltHierarchy true;mFeatures Collections.unmodifiableList(features);// 赋值mAreaForLayer areaForLayer;mFeatureToDisplayAreas featureToDisplayAreas;}所以mAreaForLayer保存了层级树各个层级的对象因此根据index可以获取到对应的DisplayArea.Tokens并执行系统窗口WindowToken的挂载。
http://www.hkea.cn/news/14557858/

相关文章:

  • 邯郸网站建设方案wordpress相同的cms
  • 网站维护推广怎么做网站模板拍卖
  • 山西省住房和建设厅网站网页制作素材软件有哪些
  • 网站建设课程设计报告总结wordpress上传大图
  • 中国联通网站备案管理系统温州网站推广有哪些方法
  • 网站开发 访问速度慢wordpress自动加文章tittle
  • 有哪些文本封面做的好的网站六站合一的优势
  • 国内最好用的免费建站平台手机商城系统开发
  • 电子商务网站建设课件苏州哪里做网站
  • 宁波网站设计相信荣胜网络做网站软件 手机
  • 多用户商城系统是什么做网站优化给业务员提成
  • 自己做的网站怎样链接数据库免费追剧的app下载
  • 网站里面的超链接怎么做晋城市 制作网站
  • 制作个人免费网站展示设计网页装wordpress
  • 微信服务号菜单链接网站怎么做的wordpress commer
  • 做注册任务的网站有哪些网站设计的标准
  • 站长之家站长工具综合查询wordpress菜单选项
  • 网站开发是程序员吗盗版系统网站怎么建立
  • 桂林网站建设找骏程免费发布信息的网站
  • 做运动户外的网站都有哪些网页设计与网站建设...
  • 茶类网站建设方案百度信息流怎么投放
  • 在北京做兼职哪个网站好郑州营销型网站建设哪家好
  • 常州app网站在线做数据图的网站有哪些问题
  • 网站建设的报价方案wordpress用户系统插件
  • 网站内容优化做网站有哪些注意事项
  • 免费制作二维码网站发外链的平台有哪些
  • 西安网站建设公司有哪些wordpress添加标签云
  • 网页设计制作手机网站wordpress素材类主题
  • 学院网站建设项目范围变更申请表工业设计公司怎么收费
  • 微信制作宣传网站有哪些内容sem推广培训