[Android] Activity Window WMS source code relationship process

1. Class diagram relationship

system_server_AMS class diagram_1:
Insert picture description here
Activity_Window_ related class diagram:
Insert picture description here
system_server_AMS class diagram_2:
Insert picture description here
overall class diagram:
Insert picture description here

flow chart:
Insert picture description here

2. Related concepts

1. ActivityThread: is the main thread class of the application. All APK programs have and only one ActivityThread. The entry of the program is the static main() function of this class.
Activity: Activity contains a Window, which is in the attach method of Activity Create a window by calling new PhoneWindow();
2. PhoneWindow: inherits the Window class, wraps a FrameLayout to a certain extent, and provides a set of general window operation interfaces, including a DecorView
3. View: the most basic UI Component, which represents a rectangular area on the screen;
4. DecorView: This class is a subclass of FrameLayout and is an internal class in PhoneWindow. Decor in English is Decoration, which means "decoration". DecorView is to modify the ordinary FrameLayout, such as adding a general Title bar and responding to specific key messages. ;
5. Window: Represents the top-level window, the display of the management interface and the response to events; each Activity will create a PhoneWindow object, which is the interface between the Activity and the entire View system. This class provides a set of common windows (Window) Operating API, the window here is only on the program level. The window managed by WMS is not a Window class, but a View or ViewGroup class, which generally refers to the DecorView class, that is, a DecorView is a window managed by WmS. Window is an abstract type.
6, WindowManager: an interface, inherited from ViewManager. The window manager of the application process; there is an implementation WindowManagerImpl; it is
mainly used to manage some state, attributes, view addition, deletion, update, window order, message collection and processing of the window.
7. ViewRootImpl: interact with the global window manager through the IWindowSession interface: interface control and message response; when WMS manages the client window, the client needs to be notified to perform certain operations, which are done through asynchronous messages

Three, steps

Step1:
When the Activity is started, the system_server process passes through the scheduleLaunchActivit() of the AMS (ActivityManagerService) remote agent ApplicationThreadProxy (ie the Binder of the application process, IApplicationThread), marking SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION, and the underlying binder driver starts the application process XXXActivity to the inside of the ActivityThread of the application process. The onTransact of the parent class ApplicationNative of the class ApplicationThread, and then to scheduleLaunchActivity().
Step2:
The scheduleLaunchActivity of ApplicationThread: through sendMessage(H.LAUNCH_ACTIVITY, r), the H processing of the ActivityThread sent to the UI thread is handleLaunchActivity:
ActivityThread.java:

public final class ActivityThread {
    
    
      private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
    
    
        // Initialize before creating the activity
        WindowManagerGlobal.initialize();
        Activity a = performLaunchActivity(r, customIntent);
        if (a != null) {
    
    
            r.createdConfig = new Configuration(mConfiguration);
            reportSizeConfigurations(r);
            Bundle oldState = r.state;
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
        ...
        } 
    }
}

Among them, WindowManagerGlobal.initialize; is the remote agent IWindowManager that first fetches WMS (WindowManagerService)

WindowManagerGlobal.java:

public final class WindowManagerGlobal {
    
    
    public static void initialize() {
    
    
        getWindowManagerService();
    }
    public static IWindowManager getWindowManagerService() {
    
    
        synchronized (WindowManagerGlobal.class) {
    
    
            if (sWindowManagerService == null) {
    
    
                sWindowManagerService = IWindowManager.Stub.asInterface(
                        ServiceManager.getService("window"));
                try {
    
    
                    sWindowManagerService = getWindowManagerService();
                    ValueAnimator.setDurationScale(sWindowManagerService.getCurrentAnimatorScale());
                } catch (RemoteException e) {
    
    
                    throw e.rethrowFromSystemServer();
                }
            }
            return sWindowManagerService;
        }
    }
}

Activity a = performLaunchActivity(r, customIntent); Use ClassLoader to load XXXActivity, which will create ContextImpl, if Application has not been started, will first create Applicaition and onCreate, and then call XXXActivity attach();
In attach: will create Change the corresponding window of the activity, which is PhoneWindow, and the association between phoneWindow and WindowManagerImpl:
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) {
    
    
        attachBaseContext(context);
        mFragments.attachHost(null /*parent*/);
        mWindow = new PhoneWindow(this, window);
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
        mMainThread = aThread;
        mInstrumentation = instr;
        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        if (mParent != null) {
    
    
            mWindow.setContainer(mParent.getWindow());
        }
        mWindowManager = mWindow.getWindowManager();
        mCurrentConfig = config;
}

Among them: (WindowManager)context.getSystemService(Context.WINDOW_SERVICE) gets WindowManagerImpl:
here will go to ContextImpl.getSystemService:

class ContextImpl extends Context {
    
       
  @Override
    public Object getSystemService(String name) {
    
    
        return SystemServiceRegistry.getSystemService(this, name);
    }
}

SystemServiceRegistry:

final class SystemServiceRegistry {
    
    
  public static Object getSystemService(ContextImpl ctx, String name) {
    
    
        ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
        return fetcher != null ? fetcher.getService(ctx) : null;
    }
  private static final HashMap<Class<?>, String> SYSTEM_SERVICE_NAMES =
            new HashMap<Class<?>, String>();
    private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
            new HashMap<String, ServiceFetcher<?>>();
    private static int sServiceCacheSize;
    static {
    
    
        registerService(Context.ACCESSIBILITY_SERVICE, AccessibilityManager.class,
                new CachedServiceFetcher<AccessibilityManager>() {
    
    
            @Override
            public AccessibilityManager createService(ContextImpl ctx) {
    
    
                return AccessibilityManager.getInstance(ctx);
            }});
    registerService(Context.WINDOW_SERVICE, WindowManager.class,
                new CachedServiceFetcher<WindowManager>() {
    
    
            @Override
            public WindowManager createService(ContextImpl ctx) {
    
    
                return new WindowManagerImpl(ctx);
            }});
}

The return is new WindowManagerImpl(ctx); In the performLaunchActivity function, after attaching, continue to call mInstrumentation.callActivityOnCreate to implement the onCreate of XXXActivity. At this time, everyone will write setContentView(R.layout.xxx)
Step3:
Activity.setContentView():
Will call getWindow().setContentView(layoutResID), which is setContentView in PhoneWindow class: mainly create DecorView mDecor(This is the top-level view of the window, containing the window decor) in PhoneWindow, and then find android from mDecor. R.id.content: mContentParent(ViewGroup), then add the View set by the activity to mContentParent.addView(view, params);

public void setContentView(@LayoutRes int layoutResID) {
    
    
        getWindow().setContentView(layoutResID);
        initWindowDecorActionBar();
}

PhoneWindow:

public class PhoneWindow extends Window implements MenuBuilder.Callback {
    
    
  public void setContentView(int layoutResID) {
    
    
        
        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);
        }
        mContentParent.requestApplyInsets();
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
    
    
            cb.onContentChanged();
        }
        mContentParentExplicitlySet = true;
    }
}

Step4:
After the ActivitThread.handleLaunchActivity function completes performLaunchActivity, go to the handleResumeActivity function, and display start r = performResumeActivity(token, clearHide, reason); to go onResume of XXXActivity.
Then the window type will be set for the corresponding window of the Activity: **l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION, **WMS is to operate on the window, each activity corresponds to a window, Framework will define several window types, such as System Window, Application Window, Child Window, etc. The type here is very important. Without this, the window cannot display it.
Then it will call to ViewManager wm = a.getWindowManager();wm.addView(decor, l); to WindowManagerImpl.addView:
ActivityThread:

final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
    
    
        ActivityClientRecord r = mActivities.get(token);
        ...
        r = performResumeActivity(token, clearHide, reason);
        ...
            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();
                    }
                }
                if (a.mVisibleFromClient && !a.mWindowAdded) {
    
    
                    a.mWindowAdded = true;
                    wm.addView(decor, l);
                }
             ...
    }

Step5:
WindowManagerImpl's addView is called to WindowManagerGlobal.getInstance()'s addView:
This function will create root = new ViewRootImpl(view.getContext(), display); and then save to mRoots.add(root) and
then call to root.setView( view, wparams, panelParentView);

public final class WindowManagerImpl implements WindowManager {
    
    
    private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
    @Override
    public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
    
    
        applyDefaultToken(params);
        mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
    }
}

public final class WindowManagerGlobal {
    
    
    public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) {
    
    
        ...
        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);
        }
        // do this last because it fires off messages to start doing things
        try {
    
    
            root.setView(view, wparams, panelParentView);
        } catch (RuntimeException e) {
    
    
           
        }
    }
}

Step6:
ViewRootImpl.setView(): In
this function, IWindowSession mWindowSession and remote WMS Seesion objects are obtained through WindowManagerGloabl, and mWindowSession.addToDisplay is performed to the Session of the system_server process.

public final class ViewRootImpl implements ViewParent, View.AttachInfo.Callbacks, ThreadedRenderer.HardwareDrawCallbacks {
    
    
    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
    
    
        synchronized (this) {
    
    
                ....
                try {
    
    
                    res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(),
                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                            mAttachInfo.mOutsets, mInputChannel);
                }            
            }
        ...
    }
}

This mWindowSession is

public static IWindowSession getWindowSession() {
    
    
        synchronized (WindowManagerGlobal.class) {
    
    
            if (sWindowSession == null) {
    
    
                try {
    
    
                    InputMethodManager imm = InputMethodManager.getInstance();
                    IWindowManager windowManager = getWindowManagerService();
                    sWindowSession = windowManager.openSession(
                            new IWindowSessionCallback.Stub() {
    
    
                                @Override
                                public void onAnimatorScaleChanged(float scale) {
    
    
                                    ValueAnimator.setDurationScale(scale);
                                }
                            },
                            imm.getClient(), imm.getInputContext());
                } catch (RemoteException e) {
    
    
                    throw e.rethrowFromSystemServer();
                }
            }
            return sWindowSession;
        }
    }

Call the openSession method of WindowManagerService:

public class WindowManagerService extends IWindowManager.Stub implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
    
    
   @Override
    public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client, IInputContext inputContext) {
    
    
        if (client == null) throw new IllegalArgumentException("null client");
        if (inputContext == null) throw new IllegalArgumentException("null inputContext");
        Session session = new Session(this, callback, client, inputContext);
        return session;
    }
}

Guess you like

Origin blog.csdn.net/sinat_36955332/article/details/108488674