WindowManager

1 Window、WindowManager 和 WMS

Window is an abstract class, and the specific implementation class is PhoneWindow, which manages View. WindowManager is an interface class, inherited from the interface ViewManager, it is used to manage Window, and its implementation class is WindowManagerImpl. If we want to add, update and delete Window (View), we can use WindowManager. WindowManager will hand over the specific work to WMS. WindowManager and WMS communicate across processes through Binder. WMS has many system services The API will not be exposed to WindowManager, which is somewhat similar to the relationship between ActivityManager and AMS.

The relationship between Window, WindowManager and WMS can be briefly represented by the following figure:

Relationship between Window, WindowManager and WMS

Window contains View and manages View. Window is represented by a dotted line because Window is an abstract concept used to describe a window. It does not really exist. The entity of Window is actually View. WindowManager is used to manage Window, and the functions provided by WindowManager will eventually be processed by WMS.

2 Associated classes of WindowManager

Here are the relevant classes:

public abstract class Window {
    
     }
public class PhoneWindow extends Window implements MenuBuilder.Callback {
    
     }

public interface WindowManager extends ViewManager {
    
     }
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 final class WindowManagerImpl implements WindowManager {
    
     
	private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
}

public final class WindowManagerGlobal {
    
     }

public class WindowManagerService extends IWindowManager.Stub
         implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
    
     }

Inheritance relationship of WMS

**WindowManager is an interface class that inherits from the interface ViewManager. Three methods are defined in ViewManager, which are used to add, update and delete View respectively. **As shown below:

// /frameworks/base/core/java/android/view/ViewManager.java
public interface ViewManager {
    
    
    public void addView(View view, ViewGroup.LayoutParams params);
    public void updateViewLayout(View view, ViewGroup.LayoutParams params);
    public void removeView(View view);
}

**WindowManager also inherits these methods, and the parameters passed in by these methods are all View types, indicating that Window exists in the form of View. While inheriting ViewManager, WindowManager adds many functions, including constants related to Window type and hierarchy, internal classes and some methods, two of which are added according to the characteristics of Window, **as shown below:

// /frameworks/base/core/java/android/view/WindowManager.java
public Display getDefaultDisplay();
public void removeViewImmediate(View view);

WindowManager.getDefaultDisplay()The method can know which screen the WindowManager instance has added the Window to, in other words, it is the screen (Display) managed by the WindowManager. WindowManager.removeViewImmediateThe method is fixed in this method to exchange the money back and execute it immediately View.onDetachedFromWindow()to complete the related destruction work of the incoming View.

**Window is an abstract class, and its concrete implementation class is PhoneWindow. The method will be called during the startup of the Activity ActivityThread.performLaunchActivity, and the method will be called in this method Activity.attach. PhoneWindow is Activity.attachcreated in the method. **As follows:

// /frameworks/base/core/java/android/app/Activity.java
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) {
    
    
          attachBaseContext(context);
  
          mFragments.attachHost(null /*parent*/);
  
          mWindow = new PhoneWindow(this, window); // 1
          ...
          mWindow.setWindowManager(
                  (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                  mToken, mComponent.flattenToString(),
                  (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0); // 2
          if (mParent != null) {
    
    
              mWindow.setContainer(mParent.getWindow());
          }
          mWindowManager = mWindow.getWindowManager();
          mCurrentConfig = config;
      }

PhoneWindow is created at Note 1, and the method is called at Note 2 PhoneWindow.setWindowManager, which is implemented in PhoneWindow's parent class Window. As follows:

// /frameworks/base/core/java/android/view/Window.java
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); // 1
    }
    mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this); // 2
}

If it is passed in WindowManager == null, the method will be called at Note 1 Context.getSystemService, and the service name Context.WINDOW_SERVICE(the value is window) will be passed in, which is specifically implemented in ContextImpl, as follows:

// /frameworks/base/core/java/android/app/ContextImpl.java
@Override
public Object getSystemService(String name) {
    
    
    return SystemServiceRegistry.getSystemService(this, name);
}

ContextImpl.getSystemServiceThe method is called in the method SystemServiceRegister.getSystemService:

// /frameworks/base/core/java/android/app/SystemServiceRegistry.java
private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
             new HashMap<String, ServiceFetcher<?>>();
private static final HashMap<Class<?>, String> SYSTEM_SERVICE_NAMES =
              new HashMap<Class<?>, String>();

public static Object getSystemService(ContextImpl ctx, String name) {
    
    
    ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
    return fetcher != null ? fetcher.getService(ctx) : null;
}

static abstract interface ServiceFetcher<T> {
    
    
    T getService(ContextImpl ctx);
}

SYSTEM_SERVICE_FETCHERS is a HashMap type of data, which is used to store the name of the service, so Context.WINDOW_SERVICEwhat exactly does the incoming correspond to? Then look down:

// /frameworks/base/core/java/android/app/SystemServiceRegistry.java
private SystemServiceRegistry() {
    
     }

static {
    
    
    ...
    registerService(Context.WINDOW_SERVICE, WindowManager.class,
                    new CachedServiceFetcher<WindowManager>() {
    
    
                        @Override
                        public WindowManager createService(ContextImpl ctx) {
    
    
                            return new WindowManagerImpl(ctx); // 1
                        }});
    ...
}

private static <T> void registerService(String serviceName, Class<T> serviceClass,
                                        ServiceFetcher<T> serviceFetcher) {
    
    
    SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
    SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
}

Several methods are called in the static code block of SystemServieRegistry registerService. registerServiceThe method will store the name of the incoming service in SYSTEM_SERVICE_FETCHERS. It can be seen from Note 1 that the incoming Context.WINDOW_SERVICEcorresponds to WindowManagerImplthe instance, so it is concluded that Context.getSystemServicethe method gets WindowManagerImplthe instance. Go back to Window.setWindowManagerthe method and get the method at Note 1 WindowManagerImpl.createLocalWindowManager:

// /frameworks/base/core/java/android/view/WindowManagerImpl.java
public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
    
    
    return new WindowManagerImpl(mContext, parentWindow);
}

WindowManagerImpl.createLocalWindowManagerThe method is also created WindowManagerImpl. The difference is that WindowManagerImplthe Window that was created is passed in as a parameter when creating this time, so that WindowManagerImplit holds a reference to the Window and can operate on the Window. For example, adding a View in the middle of the Window will call the WindowManagerImpl.addViewmethod. As follows:

// /frameworks/base/core/java/android/view/WindowManagerImpl.java
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
    
    
    applyDefaultToken(params);
    mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow); // 1
}

The method is called at Note 1 WindowManagerGlobal.addView, and the last parameter mParentWindowis the Window mentioned above. It can be seen that although WindowManagerImpl is the implementation class of WindowManager, it does not implement any functions, but delegates the function implementation to it WindowManagerGlobal. What is used here is bridge mode. Let's take a look at WindowManagerImplhow to define when in WindowMangerGlobal, as follows:

// /frameworks/base/core/java/android/view/WindowManagerImpl.java
public final class WindowManagerImpl implements WindowManager {
    
    
    private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance(); // 1
    private final Context mContext;
    private final Window mParentWindow; // 2

    ...

    private WindowManagerImpl(Context context, Window parentWindow) {
    
    
        mContext = context;
        mParentWindow = parentWindow; // 3
    }
    ...
}

It can be seen in Note 1 that WindowManagerGlobalis a singleton, indicating that there is only one WindowManagerGlobalinstance of in a process. The code at Note 2 combined with the code at Note 3 shows WindowManagerImplwhich Window this instance will be a sub-Window of, which means that there may be multiple instances of WinodwManagerImpl in one process.

The following is the sequence diagram:

WindowManager timing diagram

PhoneWindow inherits from Window, and Window setWindowManageris associated with WindowManager through the method. WindowManager inherits from the interface ViewManager, and WindowManagerImpl is the implementation class of the WindowManager interface, but the specific functions will be entrusted to WindowManagerGlobal for implementation.

3 Window operation

WindowManager manages Window, such as adding, updating and deleting Window. For these operations, they are finally handled by WMS. The operation of the window is divided into two parts, one part is the WindowManager processing part, and the other part is the WMS processing part.

Window is divided into three categories, namely Application Window (application window), Sub Window (sub window), System Window (system window). The process of adding different types of windows will be different, but for the WMS processing part, add The process is basically the same, and WMS basically treats these three types of windows "equally":

Windows operation

3.1 Adding process of system window

Window is divided into three types, and the process of adding different types of Window is also different. Here we mainly talk about the process of adding system windows. The process of adding system windows will also vary according to different types. Here we mainly take the system window StatusBar as an example. StatusBar is an important part of SystemUI. Specifically, it refers to the system status bar, which is used to display information such as time, power and signal. .

First look at StatusBar.addStatusBarWindow()the method, which is responsible for adding a Window to the StatusBar, as shown below:

// /frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
private void addStatusBarWindow() {
    
    
    makeStatusBarView(); // 1
    mStatusBarWindowManager = Dependency.get(StatusBarWindowManager.class);
    mRemoteInputController = new RemoteInputController(mHeadsUpManager);
    mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight()); // 2
}

StatusBarView for construction at Note 1 . The method is called at Note 2 StatusBarWindowManager.add, and StatusBarthe view ( mStatusBarWindow) and StatusBarthe height of are passed in, StatusBarWindowManager.addthe method is as follows:

// /frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
public void add(View statusBarView, int barHeight) {
    
    
    mLp = new WindowManager.LayoutParams(
        ViewGroup.LayoutParams.MATCH_PARENT,
        barHeight,
        WindowManager.LayoutParams.TYPE_STATUS_BAR, // 1
        WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
        | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
        | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
        | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
        PixelFormat.TRANSLUCENT);
    mLp.token = new Binder();
    mLp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
    mLp.gravity = Gravity.TOP;
    mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
    mLp.setTitle("StatusBar");
    mLp.packageName = mContext.getPackageName();
    mStatusBarView = statusBarView;
    mBarHeight = barHeight;
    mWindowManager.addView(mStatusBarView, mLp); // 2
    mLpChanged = new WindowManager.LayoutParams();
    mLpChanged.copyFrom(mLp);
}

Firstly LayoutParamsconfigure StatusBarthe properties of the view by creating , including Width, Height, Type, Flag, Gravity, SoftInputModeetc. The key is in Note 1, which is set TYPE_STATUS_BAR, indicating that StatusBarthe window type of the view is the status bar. The method is called at Note 2 WindowManager.addView, addViewthe method is defined in WindowManagerthe parent class interface of ViewManager, and addViewthe method is WindowManagerImplimplemented in , as shown below:

// /frameworks/base/core/java/android/view/WindowManagerImpl.java
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
    
    
    applyDefaultToken(params);
    mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}

WindowManagerImpl.addViewThe type of the first parameter of the method is View, indicating that the window also Viewexists in the form of . WindowManagerImpl.addViewmethod calls WindowManagerGlobal.addViewthe method, as follows:

// /frameworks/base/core/java/android/view/WindowManagerGlobal.java
private final ArrayList<View> mViews = new ArrayList<View>();
private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();
private final ArrayList<WindowManager.LayoutParams> mParams =
    new ArrayList<WindowManager.LayoutParams>();

public void addView(View view, ViewGroup.LayoutParams params,
                    Display display, Window parentWindow) {
    
    
    ...
    final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
    if (parentWindow != null) {
    
    
        parentWindow.adjustLayoutParamsForSubWindow(wparams); // 1
    } 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;
        }
    }

    ViewRootImpl root;
    View panelParentView = null;

    synchronized (mLock) {
    
    
        ...
        root = new ViewRootImpl(view.getContext(), display); // 2
        view.setLayoutParams(wparams);
        mViews.add(view); // 3
        mRoots.add(root); // 4
        mParams.add(wparams); // 5
        try {
    
    
            root.setView(view, wparams, panelParentView); // 6
        } catch (RuntimeException e) {
    
    
            // BadTokenException or InvalidDisplayException, clean up.
            if (index >= 0) {
    
    
                removeViewLocked(index, true);
            }
            throw e;
        }
    }
}

Before introducing WindowManagerImpl.addViewthe method, we must first understand the 3 lists WindowManagerGlobalmaintained in and related to the operation. These 3 lists will be involved in the process of adding, updating and deleting windows. They are list ( ), layout parameter list ( ) and list ( ).WindowViewArrayList<View> mViewsArrayList<WindowManager.LayoutParams> mParamsViewRootImplArrayList<ViewRootImpl> mRoots

Next, analyze WindowManagerGlobal.addViewthe method, first checking the parameters view, paramsand . At Note 1, if the current window is a child window, the object of type of the child window will be adjusted accordingly displayaccording to the parent window . Save the added to the list at Note 3. Save the parameters of the window to the layout parameter list at Note 5. Created at Note 2 and assigned to , then stored in the list at Note 4 . In Note 6, the window and window parameters are set in via the method , it can be seen that the operation of adding a window is performed through .WindowManager.LayoutParamswparamsViewViewViewRootImplrootrootViewRootImplsetViewViewRootImplViewRootImpl

ViewRootImplThere are many responsibilities, mainly the following:

  • Viewthe root of the tree and manage Viewthe tree;
  • Triggered Viewmeasurement, layout and drawing;
  • A transit point for input events;
  • management Surface;
  • Responsible for WMSinter-process communication with ;

After understanding ViewRootImplthe responsibilities, let's look at ViewRootImpl.setViewthe method:

// /frameworks/base/core/java/android/view/ViewRootImpl.java
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
    
    
    synchronized (this) {
    
    
        ...
            try {
    
    
                mOrigWindowType = mWindowAttributes.type;
                mAttachInfo.mRecomputeGlobalAttributes = true;
                collectViewAttributes();
                res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                                                  getHostVisibility(), mDisplay.getDisplayId(), 
                                                  mAttachInfo.mContentInsets, 
                                                  mAttachInfo.mStableInsets, 
                                                  mAttachInfo.mOutsets, mInputChannel);
            } 
        ...
}

In the method, the method ViewRootImpl.setViewis mainly called , which is of type. It is an object, used for inter-process communication, and is the agent of the terminal. Its implementation of the terminal is that the previous code logic is run in the local process, and the method is Run in the process ( process) where is as follows:mWindowSession.addToDisplaymWindowSessionIWindowSessionBinderIWindowSessionClientServerSessionSession.addToDisplayWMSsystem_server

ViewRootImpl

As can be seen from the above figure, the local process ViewRootImplwants WMSto communicate with Session, so Sessionwhy is it included in WMS? Then look down Session.addToDisplaythe method, as follows:

// /frameworks/base/telecomm/java/android/telecom/Logging/Session.java
@Override
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
                        int viewVisibility, int displayId, Rect outContentInsets, 
                        Rect outStableInsets, Rect outOutsets, InputChannel outInputChannel) {
    
    
    return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
                              outContentInsets, outStableInsets, outOutsets, outInputChannel);
}

Session.addToDisplayThe method is called in the method , WMS.addWindowand itself is Sessionpassed in as a parameter. Each application process will correspond to one Session, WMSwhich will be used ArrayListto save these Session, which is why is WMSincluded in the above figure Session. In this way, the remaining work is handed over WMSto , WMSwhich will allocate the added window Surfaceand determine the display order of the windows. It can be seen that the canvas is responsible for displaying the interface Surface, not the window itself. will pass the s WMSit manages to the , which will be blended and drawn to the screen.SurfaceSurfaceFlingerSurfaceFlingerSurface

The following is StatusBarthe sequence diagram of the adding process of the system window:

StatusBar timing diagram

3.2 ActivityAddition process

No matter what kind of window it is, its adding process WMSis basically similar in the processing part, but there are some differences in permissions and window display order. However, WindowManagerthe processing part will be different. Take the most typical application window Activityas an example. ActivityDuring the startup process, if Activitythe process where is located does not exist, a new process will be created. After the new process is created, an instance representing the main thread will run ActivityThread, ActivityThreadwhich manages the thread of the current application process, which is Activityobviously used in the startup process of , when the interface needs to interact with the user, ActivityThread.handleResumeActivitythe method will be called, as shown below:

// /frameworks/base/core/java/android/app/ActivityThread.java
final void handleResumeActivity(IBinder token,
                                boolean clearHide, boolean isForward, boolean reallyResume, 
                                int seq, String reason) {
    
    
    ...
    r = performResumeActivity(token, clearHide, reason); // 1
        ...
        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(); // 2
            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();
                }
            }
            if (a.mVisibleFromClient) {
    
    
                if (!a.mWindowAdded) {
    
    
                    a.mWindowAdded = true;
                    wm.addView(decor, l); // 3
                } else {
    
    
                    a.onWindowAttributesChanged(l);
                }
            }

           ...
               
}

The method at comment 1 performResumeActivitywill eventually call Activity.onResumethe method. ViewManagerThe object of type is obtained at Note 2 wm, the method is called at Note 3 ViewManager.addView, and addViewthe method is WindowManagerImplimplemented in , and the subsequent process StatusBarhas been described in the process of adding the system window above, the only thing that needs to be noted is ViewManager.addViewthe first step of the method The first parameter is DecorView, which indicates that Activitythe window will contain DecorView.

3.3 WinodowThe update process

WindowThe update process for Windowis similar to the add process for . The method needs to be called ViewManager.updateViewLayout, updateViewLayoutwhich WindowManagerImplis implemented in , and WindowManagerImpl.updateViewLayoutthe method will be called in WindowManagerGlobal.updateViewLayoutthe method, as follows:

// /frameworks/base/core/java/android/view/WindowManagerGlobal.java
public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
    
    
    if (view == null) {
    
    
        throw new IllegalArgumentException("view must not be null");
    }
    if (!(params instanceof WindowManager.LayoutParams)) {
    
    
        throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
    }

    final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params;

    view.setLayoutParams(wparams); // 1

    synchronized (mLock) {
    
    
        int index = findViewLocked(view, true); // 2
        ViewRootImpl root = mRoots.get(index); // 3
        mParams.remove(index); // 4
        mParams.add(index, wparams); // 5
        root.setLayoutParams(wparams, false); // 6
    }
}

1Set the updated parameters at the comment Viewto , 2get the index of the window to be updated in Viewthe list at the comment , obtain the window according to the index in the list at the 3comment , use the comment and the comment to update the layout parameter list, and call the method at the comment to The updated parameters are set into . method calls the method at the end, as follows:ViewRootImplViewRootImpl456ViewRootImpl.setLayoutParamsViewRootImplViewRootImpl.setLayoutParamsViewRootImpl.scheduleTraveesals

// /frameworks/base/core/java/android/view/ViewRootImpl.java
void scheduleTraversals() {
    
    
    if (!mTraversalScheduled) {
    
    
        mTraversalScheduled = true;
        mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
        mChoreographer.postCallback(
            Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null); // 1
        if (!mUnbufferedInputDispatch) {
    
    
            scheduleConsumeBatchedInput();
        }
        notifyRendererOfFramePending();
        pokeDrawLockIfNeeded();
    }
}

1The translation at the comment Choreographeris "dance guide", which is used to receive VSyncthe signal of the display system and control the execution of some operations when the next frame is rendered. Choreographer.postCallbackmethod is used to initiate the added callback, which will be executed when the next frame is rendered. This added callback refers to the type 1at the annotation , as follows:cmTraversalRunnable

// /frameworks/base/core/java/android/view/ViewRootImpl.java
final class TraversalRunnable implements Runnable {
    
    
    @Override
    public void run() {
    
    
        doTraversal();
    }
}

TraversalRunnable.run()Call the method in the method as doTraversal()follows:

// /frameworks/base/core/java/android/view/ViewRootImpl.java
void doTraversal() {
    
    
    if (mTraversalScheduled) {
    
    
        mTraversalScheduled = false;
        mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);

        if (mProfile) {
    
    
            Debug.startMethodTracing("ViewAncestor");
        }

        performTraversals();

        if (mProfile) {
    
    
            Debug.stopMethodTracing();
            mProfile = false;
        }
    }
}

In doTraversalthe method, the method is called performTraversals(), performTraversals()which makes the workflow of ViewTreestart View, as follows:

// /frameworks/base/core/java/android/view/ViewRootImpl.java
private void performTraversals() {
    
    
        try {
    
    
            ...
            relayoutResult = relayoutWindow(params, viewVisibility, insetsPending); // 1
			...
        } catch (RemoteException e) {
    
    
        }

        if (!mStopped) {
    
    
            ...
            int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);
            int childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height);
            performMeasure(childWidthMeasureSpec, childHeightMeasureSpec); // 2
        }
            
	...
    final boolean didLayout = layoutRequested && (!mStopped || mReportNextDraw);
    if (didLayout) {
    
    
        performLayout(lp, mWidth, mHeight); // 3
		,,,
    }

    ...
    boolean cancelDraw = mAttachInfo.mTreeObserver.dispatchOnPreDraw() || !isViewVisible;

    if (!cancelDraw && !newSurface) {
    
    
        if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
    
    
            for (int i = 0; i < mPendingTransitions.size(); ++i) {
    
    
                mPendingTransitions.get(i).startChangingAnimations();
            }
            mPendingTransitions.clear();
        }

        performDraw(); // 4
    } 
    ...
}

The method at Note 1 relayoutWindowwill call IWindowSessionthe relayoutmethod to update Windowthe view, which is the same as the principle in 3.1, and the method will be called WMSeventually relayoutWindow. In addition, the method will call the , , and methods performTraversalsat Notes 2, 3, and 4 respectively , and they will call the , and methods inside them , which completes the workflow of . The view is updated in the method , and the workflow in is executed , thus completing the update of .performMeasureperformLayoutperformDrawViewmeasurelayoutdrawViewperformTraversalsWindowWindowViewWindow

Guess you like

Origin blog.csdn.net/xingyu19911016/article/details/128518822