An overview of
We all know that the Activity is used to display interface, are set the View to the Window, in the end by WindowManagerService calling the underlying skia rendering engine or OpenGL | ES come true. Let’s summarize the steps first
-
Activity can not store any view, is handed over to the Window, Android PhoneWindow is the only implementation of the Window class
-
When you start the Activity, you go to the ActivityThread’s performLaunchActivity method, which executes attach. In attach, you create a PhoneWindow and get the mWindowManager, Namely WindowManagerImpl
-
Then we go to the Activity’s onCreate method, and we create a DecorView by setContentView(), which is actually calling PhoneWindow setContentView(), and at this point we create a DecorView. It just creates the View, Window, and Activity
-
After executing the ActivityThread’s handleResumeActivity method, which executes the Activity’s onResume method, It calls WindowManger addView(DecorView View), and actually WindowManger goes to WindowManagerImpl, and then goes to WindowManagerGlobal addView, Then go to root.setView of ViewRootImpl
-
Then it goes to the SystemServer process session.addTodisplay, and then to the WindowMangerService addWindow().
-
By the way, ViewRootImpl is not a View. It implements ViewParent, requestLayout, Invalidate, and so on. Any View or screen refresh will be given to ViewRootImpl.
-
The View inside the setContentView is given to the DecorView to add, and the DecorView is given to the Window
There are roughly three types of Windows
- System Window: such as Status Bar, Navigation Bar, caller id Window, lock screen Window, volume adjustment Window.
- Apply Windows: This includes all Windows created by the application itself (such as Windows on Acitivty), as well as Windows that the system is responsible for displaying before application
- A child Window must have a parent form that applies custom dialogs, such as PopWindow or Dialog
SetContentView (android10, android10, android10, android10
When an Activity is started, it goes to the performLaunchActivity method of the ActivityThread. See my previous article on opening the Activity process
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
// Create a new Activity object with Instrumentation
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if(r.state ! =null) { r.state.setClassLoader(cl); }}catch (Exception e) {
}
try {
// Instead of creating our Application, we get our Application from here.
// The real place to create it is the mInitialApplication inside the handleBindApplication
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if(activity ! =null) {
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if(r.overrideConfig ! =null) {
config.updateFrom(r.overrideConfig);
}
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
Window window = null;
if(r.mPendingRemoveWindow ! =null && r.mPreserveWindow) {
window = r.mPendingRemoveWindow;
r.mPendingRemoveWindow = null;
r.mPendingRemoveWindowManager = null;
}
appContext.setOuterContext(activity);
// Go to the attach method of the Activity
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); }}Copy the code
Let’s look at the Attach method and setContentView for our Activity
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor,
Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken) {
attachBaseContext(context);
// Initialize Window. PhoneWindow is the only implementation class of Window
mWindow = new PhoneWindow(this, window, activityConfigCallback);
mWindow.setWindowControllerCallback(this);
mWindow.setCallback(this);
//....
// Get WindowManager from PhoneWindow, and mWindowManager is really WindowManager IMPl
// WindowMangerImpl
mWindowManager = mWindow.getWindowManager();
public void setContentView(@LayoutRes int layoutResID) {
// Calls PhoneWindow setContentView
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
Copy the code
So let’s look at the setContentView for PhoneWindow
@Override
public void setContentView(int layoutResID) {
// before this happens.
if (mContentParent == null) {
// We initialize a DecorView. The DecorView is a View that inherits FrameLayout
installDecor();
} else if(! hasFeature(FEATURE_CONTENT_TRANSITIONS)) { mContentParent.removeAllViews(); }Copy the code
Then let’s look at the handleResumeActivity for ActivityThread
@Override
public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
String reason) {
// Execute the Activity's onResume method
final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
final Activity a = r.activity;
// Will go into this
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;
l.softInputMode |= forwardBit;
if (r.mPreserveWindow) {
a.mWindowAdded = true;
r.mPreserveWindow = false;
ViewRootImpl impl = decor.getViewRootImpl();
if(impl ! =null) { impl.notifyChildRebuilt(); }}// mVisibleFromClient defaults to true
if (a.mVisibleFromClient) {
// At this point mWindowAdded is false and has not been added yet, so it will go here
if(! a.mWindowAdded) {// Set mWindowAdded to true
a.mWindowAdded = true;
// Call the WindowManager addView() method
/ / WindowManagerGlobal addView ()
wm.addView(decor, l);
} else{ a.onWindowAttributesChanged(l); }}}else if(! willBeVisible) {if (localLOGV) Slog.v(TAG, "Launch " + r + " mStartedActivity set");
r.hideForNow = true;
}
if(! r.activity.mFinished && willBeVisible && r.activity.mDecor ! =null && !r.hideForNow) {
// omit the code
r.activity.mVisibleFromServer = true;
mNumVisibleActivities++;
if (r.activity.mVisibleFromClient) {
// Activity makeVisible at this time just let mDecor. SetVisibility (view.visible);
// Because window has already been added.r.activity.makeVisible(); }}Copy the code
As you can see, after the Activity’s onResume, it goes to Windows ManagerGlobal and adds the DecorView to the window. Then let’s look at the Windows ManagerGlobal addView method.
public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) {
// omit the code
ViewRootImpl root;
View panelParentView = null;
// omit the code
// Initialize ViewRootImpl
// ViewRootImpl is not a View, but it implements the ViewParent interface
// Call the ViewRootImpl method to refresh
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 {
// Place the DecorView inside the ViewRootImpl
root.setView(view, wparams, panelParentView);
} catch (RuntimeException e) {
throwe; }}}Copy the code
And then let’s take a look at the setView of view RotimPL
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
/ / to omit
// This is the binder mechanism, WindowMangerServiceres = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes, getHostVisibility(), mDisplay.getDisplayId(), mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mAttachInfo.mOutsets, mInputChannel); }}@UnsupportedAppUsage
public static IWindowSession getWindowSession(a) {
synchronized (WindowManagerGlobal.class) {
if (sWindowSession == null) {
try {
InputMethodManager.ensureDefaultInstanceForDefaultDisplayIfNecessary();
IWindowManager windowManager = getWindowManagerService();
The openSession method of WindowMangerService is actually called.
sWindowSession = windowManager.openSession(
new IWindowSessionCallback.Stub() {
@Override
public void onAnimatorScaleChanged(float scale) { ValueAnimator.setDurationScale(scale); }}); }catch (RemoteException e) {
throwe.rethrowFromSystemServer(); }}returnsWindowSession; }}Copy the code
And then if we look at the Session returned by openSession of WindowMangerService, the Session calls addToDisplay, and eventually calls addWindow of WindowMangerService, All that is left to be said is the WMS and the underlying drawing calls.
reference
Take a Window view of startActivity