Activity的窗口对象创建过程

基于android 7.0代码,分析Activity的窗口对象创建过程。

  之前在《Activity运行上下文的创建过程》中,再创建Activity应用程序的运行上下文时,是会对activity对象进行初始化的,对activity进行初始化时通过Activity.attach接口完成的,当时我们只是重点关注着activity运行上下文的创建过程,其实还进行了其他的相关工作,例如Activity的窗口创建工作。下面,来看看Activity的窗口对象的创建过程。

Activity.attach
    new PhoneWindow
        new Window
    Window.setWindowControllerCallback
    Window.setCallback
    Window.setOnWindowDismissedCallback
    Window.setWindowManager
        WindowManagerImpl.createLocalWindowManager
            new WindowManagerImpl

1. Activity.attach

[===>frameworks\base\core\java\android\app\Activity.java]

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory2,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks2,
        Window.OnWindowDismissedCallback, WindowControllerCallback {
    ...

    private Window mWindow;

    private WindowManager mWindowManager;

    ...

    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) {
        ...

        mWindow = new PhoneWindow(this, window);
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
        ...

        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;
    }

    ...
}

  函数首先会创建类型为PhoneWindow的对象保存在Activity成员变量mWindow中,随后就调用PhoneWindow的成员函数setWindowControllerCallback、setCallback、setOnWindowDismissedCallback和setWindowManager来设置回调和窗口管理器。
  PhoneWindow类本身是没有这些接口的,是从父类Window继承下来的。

2. PhoneWindow.PhoneWindow

[===>frameworks\base\core\java\com\android\internal\policy\PhoneWindow.java]

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

    // This is the top-level view of the window, containing the window decor.
    private DecorView mDecor;

    ...

    public PhoneWindow(Context context) {
        super(context);
        mLayoutInflater = LayoutInflater.from(context);
    }

    /**
     * Constructor for main window of an activity.
     */
    public PhoneWindow(Context context, Window preservedWindow) {
        this(context);
        // Only main activity windows use decor context, all the other windows depend on whatever
        // context that was given to them.
        mUseDecorContext = true;
        if (preservedWindow != null) {
            mDecor = (DecorView) preservedWindow.getDecorView();
            mElevation = preservedWindow.getElevation();
            mLoadElevation = false;
            mForceDecorInstall = true;
            // If we're preserving window, carry over the app token from the preserved
            // window, as we'll be skipping the addView in handleResumeActivity(), and
            // the token will not be updated as for a new window.
            getAttributes().token = preservedWindow.getAttributes().token;
        }
        // Even though the device doesn't support picture-in-picture mode,
        // an user can force using it through developer options.
        boolean forceResizable = Settings.Global.getInt(context.getContentResolver(),
                DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES, 0) != 0;
        mSupportsPictureInPicture = forceResizable || context.getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_PICTURE_IN_PICTURE);
    }

    ...
}

3. Window.Window

[===>frameworks\base\core\java\android\view\Window.java]

public abstract class Window {
    ...

    private final Context mContext;

    ...

    public Window(Context context) {
        mContext = context;
        mFeatures = mLocalFeatures = getDefaultFeatures(context);
    }

    ...
}

  Window构造函数的实现很简单,只是初始化了其成员变量mContext。从前面的调用可以知道context描述的是正在启动的activity组件,将其保存在mContext中,这样Window类就可以通过mContext来访问与activity相关的资源了。

  回到Activity.attach中,接下来就会调用mWindow从父类Window那继承下来的setWindowControllerCallback来设置WindowControllerCallback回调。(这个回调和android 7.0多任务窗口有关)

public abstract class Window {
    ...

    private Callback mCallback;
    private OnWindowDismissedCallback mOnWindowDismissedCallback;
    private WindowControllerCallback mWindowControllerCallback;

    ...

    /** @hide */
    public final void setWindowControllerCallback(WindowControllerCallback wccb) {
        mWindowControllerCallback = wccb;
    }

    ...
}

  可以知道,正在启动的activity组件将它自己所实现的WindowControllerCallback接口设置到与它关联PhoneWindow对象父类Window的成员变量mWindowControllerCallback中。(Activity类实现了Window.WindowControllerCallback接口)

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory2,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks2,
        Window.OnWindowDismissedCallback, WindowControllerCallback {
    ...
}

  同样的,接下来又将正在启动的activity组件所实现的Callback接口和OnWindowDismissedCallback分别设置到与它关联PhoneWindow对象父类Window的成员变量mCallback和mOnWindowDismissedCallback中。这两个接口分别于事件传递和窗口消失有关。

  这一步执行完成之后,回到Activity类的成员函数attach中,接下来就会继续调用前面所创建的PhoneWindow对象从父类Window继承下来的成员函数setWindowManager来设置应用程序窗口的本地窗口管理器。

4. Window.setWindowManager

[===>frameworks\base\core\java\android\view\Window.java]

public abstract class Window {
    ...

    private WindowManager mWindowManager;
    private IBinder mAppToken;
    private String mAppName;
    private boolean mHardwareAccelerated;

    ...

    /**
     * Set the window manager for use by this Window to, for example,
     * display panels.  This is not used for displaying the
     * Window itself -- that must be done by the client.
     *
     * @param wm The window manager for adding new windows.
     */
    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);
        }
        mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
    }

    ...
}    

  参数appToken用来描述当前正在处理的窗口是与哪一个Activity组件关联的,它是一个Binder代理对象,引用了在ActivityManagerService这一侧所创建的一个类型为ActivityRecord的Binder本地对象。每一个启动起来了的Activity组件在ActivityManagerService这一侧,都有一个对应的ActivityRecord对象,用来描述该Activity组件的运行状态。这个Binder代理对象会被保存在Window类的成员变量mAppToken中,这样当前正在处理的窗口就可以知道与它所关联的Activity组件是什么。
  参数appName用来描述当前正在处理的窗口所关联的Activity组件的名称,这个名称会被保存在Window类的成员变量mAppName中。
  mWindowManager用来描述正在处理窗口的窗口管理器。从前面的调用过程可以知道, 这里传进来的参数wm的值等于null,这里会首先获取到WindowManager服务,然后强制转换成WindowManagerImpl类型,随后再调用WindowManagerImpl类的接口createLocalWindowManager来设置窗口管理器。

5. WindowManagerImpl.createLocalWindowManager

6. new WindowManagerImpl

[===>frameworks\base\core\java\android\view\WindowManagerImpl.java]

public final class WindowManagerImpl implements WindowManager {
    private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
    private final Display mDisplay;
    private final Window mParentWindow;

    ...

    private WindowManagerImpl(Display display, Window parentWindow) {
        mDisplay = display;
        mParentWindow = parentWindow;
    }

    public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
        return new WindowManagerImpl(mDisplay, parentWindow);
    }

    ...
}

  很显然,这里只是new了并且返回一个WindowManagerImpl对象给调用者,即最终会被设置到正在启动activity组件的mWindowManager对象中。我们知道WindowManagerImpl实现WindowManager接口,因此就可以通过它来管理应用程序窗口。

  至此,我们就分析完成一个Activity组件所关联的应用程序窗口对象的创建过程了。

你可能感兴趣的:(Android,Framework)