In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-31 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article mainly introduces "what is the process of adding the Activity window of the Android10 principle mechanism series to the WMS process". In the daily operation, I believe that many people have doubts about what the Activity window of the Android10 principle mechanism series is added to the WMS process. Xiaobian consulted all kinds of materials and sorted out a simple and easy-to-use operation method. I hope it will be helpful for you to answer the doubt that "the Activity window of the Android10 principle mechanism series is added to the WMS process". Next, please follow the editor to study!
Preface
First, take a look at the layout hierarchy of an Android interface, and take a most intuitive look at it:
We can clearly see that the interface is divided into three parts: the top status bar (statusbar), the bottom navigation bar (navigationbar), and the application interface.
Digression:
To view the hierarchical structure of the layout, tools or approaches can be referred to below.
Android Studio:Tools- > Layout Inspector- > Select the process to view
SDK Tools:tools/hierarchyviewer.bat . However, the latest recommendation is to use tools/monitor.bat instead of a separate hierarchyviewer.bat;hierarchyviewer.bat. Prebuilts/devtools/tools also exists in the project directory.
The second part summarizes and summarizes the contents of the above two processes.
The third part of the Activity window addition process, tracking source code describes in detail the process of creating the Activity window and adding to the WMS process.
Due to the third part of tracking the source code, this process is relatively long, involves more, and is relatively boring. So put the summary into the second part first. In this way, if you have learned about the source code or this process, you can only look at the second part. Do not know, you can also have a general understanding through the second part, and then check the third part, if you encounter the unclear part, you can go back to the second part and compare and understand.
This article is also based on the Android10 source code.
If there is anything wrong or insufficient, you are welcome to give us your advice.
Summary and summary
The preface has already explained why the summary is put in front. Let's take a look at the details.
The second part mainly introduces the following contents:
Window types: introduction to window types
Several important classes: window creation adds some common classes to the WMS process to understand the relationship between them
Add Activity creation window to WMS Overview: briefly summarizes the process of creating Activity and adding to WMS
Some structure diagrams in Activity: the whole process, some class / structure relationships associated in Activity, it is necessary to understand this individual.
Passing Token to WMS:Token is a very important parameter that participates in the whole process. Here, the transmission process of Token in the process involved in this article is summarized separately.
Window Typ
/ / WindowManager.java public static class LayoutParams extends ViewGroup.LayoutParams implements Parcelable {public static final int FIRST_APPLICATION_WINDOW = 1; public static final int LAST_APPLICATION_WINDOW = 99; public static final int FIRST_SUB_WINDOW = 1000; public static final int LAST_SUB_WINDOW = 1999; public static final int FIRST_SYSTEM_WINDOW = 2000; public static final int LAST_SYSTEM_WINDOW = 2999 / / status bar public static final int TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW; / / search bar public static final int TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1; / / caller ID public static final int TYPE_PHONE = FIRST_SYSTEM_WINDOW+2; / / warning window, such as: low power warning public static final int TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3 / / Lock screen public static final int TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4; / / toast public static final int TYPE_TOAST = FIRST_SYSTEM_WINDOW+5; public static final int TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+6;// is displayed on all windows, covering / / incoming calls are preferred, even if public static final int TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW+7 in lock screen state / / input method window public static final int TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW+11; / / wallpaper public static final int TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW+13;}
Application window (1 ~ 99): FIRST_APPLICATION_WINDOW ~ LAST_APPLICATION_WINDOW. Corresponding to a token whose Activity,token needs to be set to Activity. Such as: Activity.
Child window (1000 ~ 1999): FIRST_SUB_WINDOW ~ LAST_SUB_WINDOW. There must be a parent window, and token needs to be set to the token of the parent window. Such as: PopupWindow, attached to Activity.
System window (2000 ~ 2999): FIRST_SYSTEM_WINDOW ~ LAST_SYSTEM_WINDOW. System-level Activity does not need to have a parent window, the application process generally does not have permission to create, only the system process can be created. Such as: the above lists some common system windows, status bar, incoming calls, toast, input method and so on.
Several important categories
The following classes are often seen later, and here we mainly look at their direct inheritance relationships, which are easier to understand later.
Public abstract class Window {} public class PhoneWindow extends Window implements MenuBuilder.Callback {} public interface WindowManagerPolicy extends WindowManagerPolicyConstants {} public class PhoneWindowManager implements WindowManagerPolicy {} public interface ViewManager {public void addView (View view, ViewGroup.LayoutParams params); public void updateViewLayout (View view, ViewGroup.LayoutParams params); public void removeView (View view);} public interface WindowManager extends ViewManager {} public final class WindowManagerImpl implements WindowManager {} / * * A window in the window manager. * / class WindowState extends WindowContainer implements WindowManagerPolicy.WindowState {}
Window is an abstract class, and Activity, Toast, Dialog, and so on are all rendered by Window.
PhoneWindow is the concrete implementation class of Window (almost the only implementation class).
WindowManager is an interface that inherits the interface ViewManager (ViewManager defines three operations: add, update, and remove).
WindowManagerImpl is the implementation class of WindowManager.
However, if you look at the three operations on ViewManager in WindowManagerImpl, you can see that these three implementations are ultimately done by WindowManagerGlobal.
WindowState maintains all the information in the window. WMS manages windows, saves state, and so on through WindowState.
Add Activity creation window to WMS Summary
This is the code process of tracking, which is summarized here to facilitate follow-up review and understanding. Red is the main node method.
/ / attach ()-performLaunchActivity ()-- activity.attach () / / created PhoneWindow (mWindow). MWindowManager saves the WindowManagerImpl created by setWindowManager () obtained from mWindow-mWindow.setWindowManager () / PhoneWindow creates WindowManagerImpl (mWindowManager) internally, and saves appToken and appName. / / onCreate ()-setContentView ()-- installDecor ()-- generateDecor () / / created DecorView (mDecor)-generateLayout () / / added the layout of activity as a child view (ViewGroup) to mDecor / / onResume ()-r.activity.makeVisible () / /-- wm.addView (mDecor,...) / / wm that is mWindowManager (WindowManagerImpl object)-WindowManagerGlobal.addView () / / created ViewRootImpl. AddView's view is the mWindow created in mDecor,ViewRootImpl (here is an IBinder, not in attach ())-ViewRootImpl.setView () / / openSession () creates Session (the proxy class for IWindowSession), and view is also mDecor. MView-Session.addToDisplay () / / enter the system_server process through Session from mDecor to ViewRootImpl-mService.addWindow () / enter WMS and execute the addWindow () add window
Attach phase:
An Activity creates a PhoneWindow object, and PhoneWindow creates a WindowManagerImpl through setWindowManager ().
That is, Activity corresponds to a PhoneWindow and gets a WindowManager (created by WindowManagerImpl,Window).
OnCreate phase:
The DecorView is created and the layout of activity is added to the DecorView.
OnResume phase:
The ViewRootImpl is created and finally entered into the system_server process by Session through setView (). Finally, addWindow is executed to add the window to WMS.
Some structural diagrams in Activity
The following is the summary of my study according to the understanding of the painting, convenient for myself to check at a glance.
(if there is anything wrong, thank you for your advice.)
Public final class WindowManagerImpl implements WindowManager {private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance ();} public final class WindowManagerGlobal {private static IWindowManager sWindowManagerService;//WMS client, private static IWindowSession sWindowSession;//Session private final ArrayList mViews = new ArrayList (); private final ArrayList mRoots = new ArrayList (); private final ArrayList mParams = new ArrayList ();}
An Activity corresponds to a PhoneWindow object. That is, each Activity corresponds to a Window (the specific implementation class is PhoneWindow).
A PhoneWindow holds an instance of DecorView, and DecorView is actually a FrameLayout, which is the root of all the View in the Activity (the topmost View).
A PhoneWindow has a WindowManagerImpl. WindowManagerImpl holds a singleton WindowManagerGlobal.
Pass Token to WMS
AMS creates an ActivityRecord for Activity when it starts. Please refer to the first startup process of the application of AMS.
Let's take a look at a few pieces of code about token in ActivityRecord:
Final class ActivityRecord extends ConfigurationContainer {final IApplicationToken.Stub appToken; / / window manager token / / TODO: Remove after unification AppWindowToken mAppWindowToken; ActivityRecord (ActivityTaskManagerService _ service, WindowProcessController _ caller,...) {appToken = new Token (this, _ intent);} void createAppWindowToken () {mAppWindowToken = createAppWindow (mAtmService.mWindowManager, appToken,...) } static class Token extends IApplicationToken.Stub {Token (ActivityRecord activity, Intent intent) {weakActivity = new WeakReference (activity); name = intent.getComponent (). FlattenToShortString ();}
The member variable appToken in ActivityRecord, which is very important, will be covered in many subsequent places.
There is an appToken in ActivityRecord, which is an IBinder (the inner class Token inherits the IApplicationToken interface). Token holds a weak reference to Activity internally.
In ActivityRecord, the AppWindowToken object is created and saved to mAppWindowToken through createAppWindow ().
MAppWindowToken: this appToken will be encapsulated in it. Path: ActivityStack.startActivityLocked ()-> ActivityRecord.createAppWindowToken (). AppWindowToken is a subclass of WindowToken. WindowToken can mark a window.
This appToken is passed to Activity as an argument in Activity.attach ().
Activity is saved to mToken.
It is then passed into Window (PhoneWindow) through Activity.attach ()-> mWindow.setWindowManager ().
Window is saved to mAppToken.
WindowManagerGlobal.addView ()-> Window.adjustLayoutParamsForSubWindow () is saved to the token variable in WindowManager.LayoutParams.
Finally, WindowManager.LayoutParams (where token is the appToken in ActivityRecord) is passed in ViewRootImpl.setView () as a parameter.
MWindowAttributes in ViewRootImpl copies WindowManager.LayoutParams and passes it into WMS through Session.addToDisplay () as a parameter for subsequent operations.
This is the whole process of adding a window (to addWindow ()) that appToken participates in and delivers.
How appToken participates in the addition of windows can be seen in more detail in the comments on 2.8:mService.addWindow () in part 3.
Activity window addition process
This article mainly introduces the creation of Window corresponding to Activity and the process of adding Window to WMS.
Activity window creation
During the first launch of the application of AMS, from clicking on the application icon to activity to create and execute onCreate (). The following part is the interception of the later part. If you don't know, you can refer to that article.
1.1:handleLaunchActivity ()
Here we start with handleLaunchActivity ().
/ / ActivityThread.java @ Override public Activity handleLaunchActivity (ActivityClientRecord r, PendingTransactionActions pendingActions, Intent customIntent) {... WindowManagerGlobal.initialize (); final Activity a = performLaunchActivity (r, customIntent);...} private Activity performLaunchActivity (ActivityClientRecord r, Intent customIntent) {. Try {java.lang.ClassLoader cl = appContext.getClassLoader (); activity = mInstrumentation.newActivity (cl, component.getClassName (), r.intent);} try {Application app = r.packageInfo.makeApplication (false, mInstrumentation); if (activity! = null) {Window window = null;... / / attach (), note this r.token. Reference 1.2 activity.attach (appContext, this, getInstrumentation (), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstances, config, r.referrer, r.voiceInteractor, window, r.configCallback, r.assistToken) If (r.isPersistable ()) {/ / callActivityOnCreate () finally executes the onCreate () method of activity. / / reference 1.4 mInstrumentation.callActivityOnCreate (activity, r.state, r.persistentState);} else {mInstrumentation.callActivityOnCreate (activity, r.state);}. Return activity;}
WindowManagerGlobal.initialize (); is the IBinder proxy class that gets WMS and is used to communicate with WMS. The code is not listed here.
The next thing to see is activity.attach (). Notice that the r.token passed in as a parameter attach () is an IBinder, from ActivityClientRecord, and simply identifies an Activity.
1.2:activity.attach ()
/ / Activity.java final void attach (Context context, ActivityThread aThread, Instrumentation instr, IBinder token,...) {. / / create PhoneWindow mWindow = new PhoneWindow (this, window, activityConfigCallback); / / create PhoneWindow / / set soft keyboard if (info.softInputMode! = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {mWindow.setSoftInputMode (info.softInputMode);} / token save to mToken. MToken = token;. / / mToken is passed to Window. Refer to mWindow.setWindowManager ((WindowManager) context.getSystemService (Context.WINDOW_SERVICE), mToken, mComponent.flattenToString (), (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED)! = 0); / / mWindowManager is the WindowManagerImpl created in setWindowManager (). MWindowManager = mWindow.getWindowManager ();...}
First, the Window corresponding to Activityd is created, which is the implementation class of PhoneWindow-Window. Then take a look at mWindow.setWindowManager ().
1.3:mWindow.setWindowManager ()
/ / Window.java public void setWindowManager (WindowManager wm, IBinder appToken, String appName, boolean hardwareAccelerated) {/ / ActivityClientRecord.token mAppToken = appToken; mAppName = appName; mHardwareAccelerated = hardwareAccelerated; if (wm = = null) {wm = (WindowManager) mContext.getSystemService (Context.WINDOW_SERVICE);} / create WindowManagerImpl. Note that mParentWindow in WindowManagerImpl is this, non-empty mWindowManager = ((WindowManagerImpl) wm) .createLocalWindowManager (this);}
Here you create the WindowManagerImpl object, which is the implementation class of WindowManager. And saved appToken, appName, mWindowManager.
With setWindowManager (), the WindowManager (WindowManagerImpl) is created for the Window (or PhoneWindow) setting.
1.4:setContentView ()
MInstrumentation.callActivityOnCreate () ends up with a call to onCreate () to Activity.
SetContentView () is executed for customizing Activity and setting layout. Let's take a look at this method directly.
/ / Activity.java public void setContentView (@ LayoutRes int layoutResID) {getWindow () .setContentView (layoutResID); / / initWindowDecorActionBar ();} public Window getWindow () {return mWindow;// is the PhoneWindow object} / / PhoneWindow.java / / This is the top-level view of the window, containing the window decor. Private DecorView mDecor; @ Override public void setContentView (int layoutResID) {/ / Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window / / decor, when theme attributes and the like are crystalized. Do not check the feature / / before this happens. If (mContentParent = = null) {installDecor (); / /} else if (! hasFeature (FEATURE_CONTENT_TRANSITIONS)) {mContentParent.removeAllViews ();} if (hasFeature (FEATURE_CONTENT_TRANSITIONS)) {final Scene newScene = Scene.getSceneForLayout (mContentParent, layoutResID, getContext ()); transitionTo (newScene);} else {mLayoutInflater.inflate (layoutResID, mContentParent) }.} private void installDecor () {mForceDecorInstall = false; if (mDecor = = null) {/ / generate DecorView, refer to 1.5 mDecor = generateDecor (- 1);.} else {mDecor.setWindow (this) } if (mContentParent = = null) {/ / layout is added to DecorView, refer to 1.5 mContentParent = generateLayout (mDecor); / / Set up decor part of UI to ignore fitsSystemWindows if appropriate. MDecor.makeOptionalFitsSystemWindows (); final DecorContentParent decorContentParent = (DecorContentParent) mDecor.findViewById (R.id.decor_content_parent); if (decorContentParent! = null) {} else {mTitleView = findViewById (R.id.title);}.}
Here we focus on the next two methods: mDecor = generateDecor (- 1); and mContentParent = generateLayout (mDecor);.
Let's take a look at their related code:
1.5:generateDecor () and generateLayout ()
Protected DecorView generateDecor (int featureId) {/ / System process doesn't have application context and in that case we need to directly use / / the context we have. Otherwise we want the application context, so we don't cling to the / / activity. Context context;... Return new DecorView (context, featureId, this, getAttributes ()); / /} public class DecorView extends FrameLayout implements RootViewSurfaceTaker, WindowCallbacks {} protected ViewGroup generateLayout (DecorView decor) {... MDecor.startChanging (); mDecor.onResourcesLoaded (mLayoutInflater, layoutResource); ViewGroup contentParent = (ViewGroup) findViewById (ID_ANDROID_CONTENT); MDecor.finishChanging (); return contentParent;} / / DecorView.java void onResourcesLoaded (LayoutInflater inflater, int layoutResource) {... MDecorCaptionView = createDecorCaptionView (inflater); final View root = inflater.inflate (layoutResource, null); if (mDecorCaptionView! = null) {if (mDecorCaptionView.getParent () = = null) {addView (mDecorCaptionView, new ViewGroup.LayoutParams (MATCH_PARENT, MATCH_PARENT));} mDecorCaptionView.addView (root, new ViewGroup.MarginLayoutParams (MATCH_PARENT, MATCH_PARENT)) } else {/ / Put it below the color views. AddView (root, 0, new ViewGroup.LayoutParams (MATCH_PARENT, MATCH_PARENT);} mContentRoot = (ViewGroup) root; initializeElevation ();}
A DecorView is created through generateDecor (). A DecorView is actually a FrameLayout.
Then, through generateLayout (), the layout of the activity is finally added to the DecorView as a ViewGroup.
As you can see above, activity is generated to execute onCreate (). In this process, activity generates the associated PhoneWindow, and then creates WindowManagerImpl and DecorView.
Let's take a look at the process of adding Window to WMS to see how these created objects are linked to form the structure diagram introduced at the beginning.
Add Window to the WMS process
During the first startup of AMS application, we mainly talk about onCreate. In fact, onResume is also in it. I will not explain it in detail here. List the relevant code again:
/ ActivityStackSupervisor.java: boolean realStartActivityLocked (ActivityRecord r, WindowProcessController proc, boolean andResume, boolean checkConfig) throws RemoteException {... Try {... Try {/ / 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),. / / Set desired final state. Final ActivityLifecycleItem lifecycleItem; if (andResume) {lifecycleItem = ResumeActivityItem.obtain (dc.isNextTransitionForward ());} else {lifecycleItem = PauseActivityItem.obtain ();} clientTransaction.setLifecycleStateRequest (lifecycleItem); / / Schedule transaction. MService.getLifecycleManager (). ScheduleTransaction (clientTransaction);.}}. Return true;}
The end result of execution through the LaunchActivityItem association is that the Activity of the application is created and attach () and onCreate () are executed. AndResume is true (the parameter passed in is true, you can refer to this code to move forward), and the final execution through ResumeActivityItem association is ActivityThread.handleResumeActivity ().
Here, from the perspective of ActivityThread.handleResumeActivity ().
2.1:ActivityThread.handleResumeActivity ()
/ / ActivityThread.java @ Override public void handleResumeActivity (IBinder token, boolean finalStateRequest, boolean isForward, String reason) {. / / TODO Push resumeArgs into the activity for consideration / / execute onStart ()-> onResume (). Reference 2.2 final ActivityClientRecord r = performResumeActivity (token, finalStateRequest, reason); final Activity a = r. Activity; if (r.window = = null & &! a.mFinished & & willBeVisible) {r.window = r.activity.getWindow (); View decor = r.window.getDecorView (); decor.setVisibility (View.INVISIBLE); ViewManager wm = a.getWindowManager (); WindowManager.LayoutParams l = r.window.getAttributes () A.mDecor = decor; l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;.}. / / The window is now visible if it has been added, we are not / / simply finishing, and we are not starting another activity. If (! r.activity.mFinished & & willBeVisible & & r.activity.mDecor! = null & &! r.hideForNow) {. R.activity.mVisibleFromServer = true; mNumVisibleActivities++; if (r.activity.mVisibleFromClient) {/ / reference 2.3 r.activity.makeVisible ();}}.}
Notice that View decor = r.window.getDecorView (); gets the DecorView object, and finally assigns the DecorView to the Activity through a.mDecor = decor;.
Here are two points:
PerformResumeActivity () r.activity.makeVisible ()
2.2:performResumeActivity ()
/ / ActivityThread.java @ VisibleForTesting public ActivityClientRecord performResumeActivity (IBinder token, boolean finalStateRequest, String reason) {final ActivityClientRecord r = mActivities.get (token); Try {r.activity.onStateNotSaved (); r.activity.mFragments.noteStateNotSaved ();... R.activity.performResume (r.startsNotResumed, reason); r.state = null; r.persistentState = null; r.setState (ON_RESUME); reportTopResumedActivityChanged (r, r.isTopResumedActivity, "topWhenResuming");} return r;} / / Activity.java final void performResume (boolean followedByPause, String reason) {performRestart (true / * start * /, reason); mInstrumentation.callActivityOnResume (this) } final void performRestart (boolean start, String reason) {mInstrumentation.callActivityOnRestart (this);} / / Instrumentation.java public void callActivityOnRestart (Activity activity) {activity.onRestart ();} public void callActivityOnResume (Activity activity) {activity.mResumed = true; activity.onResume ();...}
R.activity.performResume () in performResumeActivity () calls back the performResume () method of Activity. Finally, the onResume () method of Activity is executed.
PerformResume () calls performRestart () before executing onResume, and finally calls activity's onStart (). Here you can see that onStart () executes before onResume ().
2.3:r.activity.makeVisible ()
/ / Activity.java void makeVisible () {if (! mWindowAdded) {ViewManager wm = getWindowManager (); wm.addView (mDecor, getWindow (). GetAttributes ()); mWindowAdded = true;} mDecor.setVisibility (View.VISIBLE);} / WindowManagerImpl.java public final class WindowManagerImpl implements WindowManager {@ UnsupportedAppUsage private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance () @ Override public void addView (@ NonNull View view, @ NonNull ViewGroup.LayoutParams params) {applyDefaultToken (params); / / mParentWindow that is, the creation WindowManagerImpl is passed in. Reference 2.4 mGlobal.addView (view, params, mContext.getDisplay (), mParentWindow);}}
GetWindowManager () here gets the WindowManagerImpl object created by setWindowManager () when attach () mentioned earlier.
As mentioned earlier, the three operation definition implementations, such as addView (), end up in WindowManagerGlobal, as you can see here.
2.4:WindowManagerGlobal.addView ()
/ / WindowManagerGlobal @ UnsupportedAppUsage private final ArrayList mViews = new ArrayList (); @ UnsupportedAppUsage private final ArrayList mRoots = new ArrayList (); public void addView (View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) {. Final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params; if (parentWindow! = null) {/ / adjust the Window parameter, which sets the token in the / / reference 2.4.1 parentWindow.adjustLayoutParamsForSubWindow (wparams);}. ViewRootImpl root; View panelParentView = null; synchronized (mLock) {... Root = new ViewRootImpl (view.getContext (), display); view.setLayoutParams (wparams); mViews.add (view); mRoots.add (root); mParams.add (wparams); try {/ / set view and related parameters to ViewRootImpl. ViewRootImpl will add new windows to WMS, apply for Surface, draw work, and so on. / / reference 2.6root.setView (view, wparams, panelParentView);}.}} / / ViewRootImpl.java @ UnsupportedAppUsage final IWindowSession mWindowSession; public ViewRootImpl (Context context, Display display) {mContext = context; / / created Session (), reference 2.5mWindowSession = WindowManagerGlobal.getWindowSession (); mDisplay = display; mBasePackageName = context.getBasePackageName (); mThread = Thread.currentThread () MTargetSdkVersion = context.getApplicationInfo (). TargetSdkVersion; / / the mWindow here is not the PhoneWindow in the previous Activity, it is W extends IWindow.Stub mWindow = new W (this); mViewVisibility = View.GONE; / / create AttachInfo mAttachInfo = new View.AttachInfo (mWindowSession, mWindow, display, this, mHandler, this, context) ...} static class W extends IWindow.Stub {/ ViewRootImpl.java public final class ViewRootImpl implements ViewParent, / / View.java final static class AttachInfo {AttachInfo (IWindowSession session, IWindow window, Display display, ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer, Context context) {mSession = session; mWindow = window; mWindowToken = window.asBinder (); mDisplay = display; mViewRootImpl = viewRootImpl MHandler = handler; mRootCallbacks = effectPlayer; mTreeObserver = new ViewTreeObserver (context);}}
The main thing to see here is that the ViewRootImpl object is created. This class implements the necessary protocols between View and WindowManager.
Notice that mWindow = new W (this);, which inherits IWindow.Stub, is being created.
When the ViewRootImpl object is created, a mAttachInfo = View.AttachInfo () is created, and AttachInfo is a series of binding information. MWindowSession and mWindow are passed as parameters. Note that mWindowToken = window.asBinder (); when AttachInfo is created.
MWindowSession mentioned in the follow-up 2.5 Session 2.6 binder 2.7 that it is a Session object, a proxy class for IWindowSession, and a binder interface through which it can communicate with WMS.
MWindow here is the W object, and it is IWindow.Stub, which is created through new. Later, you can see that WMS will be passed in. It is the binder interface of WMS callback applications (communicating with applications).
MWindowToken, which is the IBinder object of W, is also the interface for WMS to communicate with the application.
After creating the ViewRootImpl object, WindowManagerGlobal saves View, ViewRootImpl, and LayoutParams to the corresponding ArrayList. As mentioned earlier, WindowManagerGlobal is a singleton, and there is only one application process. Finally, the View (in this case, DecorView) is passed into the ViewRootImpl through root.setView ().
2.4.1:adjustLayoutParamsForSubWindow ()
You saw earlier that mAppToken was passed in from Activity.
Here the mAppToken is set to the WindowManager.LayoutParams, and you can see that it is finally passed into the WMS to participate in the processing.
/ / Window.java void adjustLayoutParamsForSubWindow (WindowManager.LayoutParams wp) {CharSequence curTitle = wp.getTitle (); / / the child window in this article is the application window, so if you don't go here, learn about it. If (wp.type > = WindowManager.LayoutParams.FIRST_SUB_WINDOW & & wp.type = WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW & & wp.type requestLayout ()-> scheduleTraversals ()-> mTraversalRunnable- > doTraversal ()-> performTraversals ()-> host.dispatchAttachedToWindow (mAttachInfo, 0)-> View.dispatchAttachedToWindow ()-> ViewGroup.dispatchAttachedToWindow ().
AttachInfo that belongs to the same ViewGroup is the same.
/ / ViewGroup.java @ Override @ UnsupportedAppUsage void dispatchAttachedToWindow (AttachInfo info, int visibility) {mGroupFlags | = FLAG_PREVENT_DISPATCH_ATTACHED_TO_WINDOW; super.dispatchAttachedToWindow (info, visibility); mGroupFlags & = ~ FLAG_PREVENT_DISPATCH_ATTACHED_TO_WINDOW; final int count = mChildrenCount; final View [] children = mChildren; for (int I = 0; I
< count; i++) { final View child = children[i]; child.dispatchAttachedToWindow(info, combineVisibility(visibility, child.getVisibility())); } final int transientCount = mTransientIndices == null ? 0 : mTransientIndices.size(); for (int i = 0; i < transientCount; ++i) { View view = mTransientViews.get(i); view.dispatchAttachedToWindow(info, combineVisibility(visibility, view.getVisibility())); } } } 上述过程 performTraversals() 大致了解下:从上而下遍历视图树,每个View绘制自己,ViewGroup通知子View进行绘制。测量performMeasure() 执行布局performLayout() 绘制performDraw()。 Android绘制 重要的部分就在这里,需要了解的可以仔细研究下这个方法(performTraversals()),这里不作关注。 2.5:WindowManagerGlobal.getWindowSession() // WindowManagerGlobal.java @UnsupportedAppUsage public static IWindowSession getWindowSession() { synchronized (WindowManagerGlobal.class) { if (sWindowSession == null) { try { InputMethodManager.ensureDefaultInstanceForDefaultDisplayIfNecessary(); IWindowManager windowManager = getWindowManagerService(); //创建Session对象 sWindowSession = windowManager.openSession( new IWindowSessionCallback.Stub() { @Override public void onAnimatorScaleChanged(float scale) { ValueAnimator.setDurationScale(scale); } }); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } return sWindowSession; } } //WindowManagerService.java @Override public IWindowSession openSession(IWindowSessionCallback callback) { return new Session(this, callback); } 获取Sessiond对象,如果没有则通过 windowManager.openSession() 创建。Session是IWindowSession的代理类,然后返回给ViewRootImpl中的mWindowSession。 2.6:ViewRootImpl.setView() //ViewRootImpl.java public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) { synchronized (this) { if (mView == null) { mView = view; mWindowAttributes.copyFrom(attrs); ... // Schedule the first layout -before- adding to the window // manager, to make sure we do the relayout before receiving // any other events from the system. requestLayout();//TODO try { mOrigWindowType = mWindowAttributes.type; mAttachInfo.mRecomputeGlobalAttributes = true; collectViewAttributes(); //参考2.7,进入system_server进程 res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes, getHostVisibility(), mDisplay.getDisplayId(), mTmpFrame, mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel, mTempInsets); setFrame(mTmpFrame); } ... } } } res = mWindowSession.addToDisplay() :mWindowSession是上面返回的创建的Session, mWindowSession.addToDisplay() 即通过binder进入system_server进程,执行的Session.addToDisplay()。 mView即DecorView。 这里的mWindow是2.4中讲到的,是 W 继承IWindow.Stub。这是一个IBinder对象,在应用进程创建ViewRootImpl时被创建。 这里 mWindowSession.addToDisplay() 往后可以看到被传入到WMS。 2.7:Session.addToDisplay() //Session.java class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { final WindowManagerService mService; public Session(WindowManagerService service, IWindowSessionCallback callback) { mService = service; ... } @Override public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets, Rect outStableInsets, Rect outOutsets, DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel, InsetsState outInsetsState) { //参考2.8 return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, outFrame, outContentInsets, outStableInsets, outOutsets, outDisplayCutout, outInputChannel, outInsetsState); } } 进入WMS,添加Window。 2.8:mService.addWindow() 终于到最后WMS.addWindow(),这里完成窗口添加。可以仔细看下下面源码及注释,这个方法即使缩减了很多还是比较长,需要耐心。 //WindowManagerService.java public int addWindow(Session session, IWindow client, int seq, LayoutParams attrs, int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets, Rect outStableInsets, Rect outOutsets, DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel, InsetsState outInsetsState) { int[] appOp = new int[1]; //检查权限,无权限不能添加窗口 int res = mPolicy.checkAddPermission(attrs, appOp); if (res != WindowManagerGlobal.ADD_OKAY) { return res; } boolean reportNewConfig = false; WindowState parentWindow = null; ... final int type = attrs.type; synchronized (mGlobalLock) { ... //获取窗口要添加到的DisplayContent。即显示在哪个屏幕上 final DisplayContent displayContent = getDisplayContentOrCreate(displayId, attrs.token); if (displayContent == null) { Slog.w(TAG_WM, "Attempted to add window to a display that does not exist: " + displayId + ". Aborting."); return WindowManagerGlobal.ADD_INVALID_DISPLAY; } if (!displayContent.hasAccess(session.mUid)) { Slog.w(TAG_WM, "Attempted to add window to a display for which the application " + "does not have access: " + displayId + ". Aborting."); return WindowManagerGlobal.ADD_INVALID_DISPLAY; } if (mWindowMap.containsKey(client.asBinder())) { Slog.w(TAG_WM, "Window " + client + " is already added"); return WindowManagerGlobal.ADD_DUPLICATE_ADD; } //添加子窗口,父窗口必须存在。 if (type >= FIRST_SUB_WINDOW & & type = FIRST_SUB_WINDOW & & parentWindow.mAttrs.type = FIRST_APPLICATION_WINDOW & & rootType = FIRST_APPLICATION_WINDOW & & rootType
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.