WindowManagerService学习

一、WMS服务初始化过程

  • SystemServer中创建WMS

frameworks/base/services/java/com/android/server/SystemServer.java

private void startOtherServices() {
    ... ...
    WindowManagerService wm = null;
    wm = WindowManagerService.main(context, inputManager,
        mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
             !mFirstBoot, mOnlyCore, new PhoneWindowManager());
    ServiceManager.addService(Context.WINDOW_SERVICE, wm);
    ... ...
    wm.displayReady();
    ... ...
    wm.systemReady();

}
  • WindowManagerService.main

frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

  public static WindowManagerService main(final Context context, final InputManagerService im,
            final boolean haveInputMethods, final boolean showBootMsgs, final boolean onlyCore,
            WindowManagerPolicy policy) {
        //WMS 运行在"android.display"线程
        //DisplayThread 从Android 5.0开始,所有跟系统前景相关的操作都集中到这个线程类中。这个线程只能由WindowManager,DisplayManager和InputManager用来实时显示相关的快速操作。
        DisplayThread.getHandler().runWithScissors(() ->
                sInstance = new WindowManagerService(context, im, haveInputMethods, showBootMsgs,
                        onlyCore, policy), 0);
        return sInstance;
    }

frameworks/base/core/java/android/os/Handler.java

/**
* One example of where you might want to use this method is when you just
* set up a Handler thread and need to perform some initialization steps on
* it before continuing execution.
*/

  public final boolean runWithScissors(final Runnable r, long timeout) {
        if (r == null) {
            throw new IllegalArgumentException("runnable must not be null");
        }
        if (timeout < 0) {
            throw new IllegalArgumentException("timeout must be non-negative");
        }
        //如果当前线程和handler所在线程是同一线程,直接执行run
        if (Looper.myLooper() == mLooper) {
            r.run();
            return true;
        }
        //否者把这个runnable 放在handler 所在线程执行,当前线程等待直到这个runnable 执行完后被唤醒
        BlockingRunnable br = new BlockingRunnable(r);
        return br.postAndWait(this, timeout);
    }
private static final class BlockingRunnable implements Runnable {
  @Override
  public void run() {
        try {
             mTask.run();
        } finally {
             synchronized (this) {
                   mDone = true;
                   notifyAll();
               }
          }
     }

   public boolean postAndWait(Handler handler, long timeout) {
            if (!handler.post(this)) {
                return false;
            }

            synchronized (this) {
                if (timeout > 0) {
                    ... ...
                } else {
                    while (!mDone) {
                        try {
                            wait();
                        } catch (InterruptedException ex) {
                        }
                    }
                }
            }
            return true;
        }
}
  • WindowManagerService 构造函数
private WindowManagerService(Context context, InputManagerService inputManager,
            boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore,
            WindowManagerPolicy policy) {
            ... ...
            初始化PhoneWindowManager
            initPolicy();
 }
   private void initPolicy() {
       //运行在android.ui 线程
       UiThread.getHandler().runWithScissors(new Runnable() {
           @Override
           public void run() {
               WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
               //mPolicy为PhoneWindowManager
               mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
           }
       }, 0);
   }

这里跟前面一样使用Handler.runWithScissors, 由于WindowManagerService是在"android.display"线程中运行, 而mPolicy.init
在"android.ui"线程中运行,"android.display"线程等待mPolicy.init执行完再被唤醒。

  • wm.displayReady
public void displayReady() {
    for (Display display : mDisplays) {
        displayReady(display.getDisplayId());
    }

    synchronized(mWindowMap) {
        final DisplayContent displayContent = getDefaultDisplayContentLocked();
        if (mMaxUiWidth > 0) {
            displayContent.setMaxUiWidth(mMaxUiWidth);
        }
        readForcedDisplayPropertiesLocked(displayContent);
        mDisplayReady = true;
    }

    try {
        mActivityManager.updateConfiguration(null);
    } catch (RemoteException e) {
    }

    synchronized(mWindowMap) {
        mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_TOUCHSCREEN);
        configureDisplayPolicyLocked(getDefaultDisplayContentLocked());
    }

    try {
        mActivityManager.updateConfiguration(null);
    } catch (RemoteException e) {
    }

    updateCircularDisplayMaskIfNeeded();
}
  • wm.systemReady
public void systemReady() {
    mPolicy.systemReady();
    //TaskSnapshotController android O 新增, 当app token不可见时对当前task截图并放在缓存中,系统应用可以得到代表当前task状态的截图,并在他们自己的进程中绘制
    //当这个task可见后,显示starting window 时用这个截图的内容,可以使应用转换更加敏捷
    mTaskSnapshotController.systemReady();
}

WMS初始化过程涉及进程关系如下:
(图片来源^^: http://gityuan.com/2017/01/08/windowmanger/

WMS_Thread.PNG

二、关于Token

AMS中的Token是Binder对象,用于跨进程标识同一个Activity对象。WMS中的WindowToken用来标识与一个Activity对应的所有窗口。

1. Token 定义和创建

/frameworks/base/services/core/java/com/android/server/am/ActivityRecord.java

    static class Token extends IApplicationToken.Stub {
        private final WeakReference<ActivityRecord> weakActivity;

        Token(ActivityRecord activity) {
            weakActivity = new WeakReference<>(activity);
        }
        //获取ActivityRecord 对象
        private static ActivityRecord tokenToActivityRecordLocked(Token token) {
            if (token == null) {
                return null;
            }
            ActivityRecord r = token.weakActivity.get();
            if (r == null || r.getStack() == null) {
                return null;
            }
            return r;
        }

    }
    ... ...

    ActivityRecord(ActivityManagerService _service, ProcessRecord _caller,...{
        ... ...
        appToken = new Token(this, service);
    }

2. Token对象传递
  • (1)在启动一个Activity时会调用 ActivityStack 的startActivityLocked,在这里面调用 addAppToken 将AMS的Token 对象传递给WMS,然后WMS 根据这个Token对象创建 AppWindowToken。
  • (2)接下来ASS调用scheduleLaunchActivity将token传给应用端的ActivityThread,此时应用端得到token的代理对象。
  • (3)Activity Resume过程中,添加视图时ViewRootImpl.setView会调用WMS.addWindow将应用端的token代理对象传给WMS,此时WMS得到token的Binder对象。

/frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

    final void startActivityLocked(ActivityRecord r, boolean newTask, boolean keepCurTransition,
            ActivityOptions options) {
        ... ...
        if (!newTask) {
            // If starting in an existing task, find where that is...
            boolean startIt = true;
            for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
                task = mTaskHistory.get(taskNdx);
                if (task.getTopActivity() == null) {
                    // All activities in task are finishing.
                    continue;
                }
                if (task == r.task) {
                    // Here it is!  Now, if this is not yet visible to the
                    // user, then just add it without starting; it will
                    // get started when the user navigates back to it.
                    if (!startIt) {
                        task.addActivityToTop(r);
                        r.putInHistory();
                        addConfigOverride(r, task);
                        ... ...
                }
            }
        }
    void addConfigOverride(ActivityRecord r, TaskRecord task) {
        final Rect bounds = task.updateOverrideConfigurationFromLaunchBounds();
        // TODO: VI deal with activity
        mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
                r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
                (r.info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0, r.userId, r.info.configChanges,
                task.voiceSession != null, r.mLaunchTaskBehind, bounds, task.mOverrideConfig,
                task.mResizeMode, r.isAlwaysFocusable(), task.isHomeTask(),
                r.appInfo.targetSdkVersion, r.mRotationAnimationHint);
        r.taskConfigOverride = task.mOverrideConfig;
    }
  • AMS跨Binder调用应用进程的scheduleLaunchActivity()将Token传递给上层应用进程,这时候应用端得到的是Token 代理对象。
    final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
            boolean andResume, boolean checkConfig) throws RemoteException {
            ... ...
            //app.thread 是 IApplicationThread 对象,服务端为应用进程中的ApplicationThread 
            app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
                    new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage,
                    task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
                    newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
           ... ...
    }
  • 应用端添加窗口调用的ViewRootImpl的setView,跨进程将token对象再传给WMS服务,这时候应用端传的是Token 代理对象,
    WMS服务端得到的却是Token对象,这样就跟之前AMS addAppToken时传过来的Token是同一个对象了。

/frameworks/base/core/java/android/view/ViewRootImpl.java

    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
        ... ...
        //mWindowSession IWindowSession对象,服务端是WMS中的 Session,在addToDisplay调用WMS的addWindow
        res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
            getHostVisibility(), mDisplay.getDisplayId(),
            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
            mAttachInfo.mOutsets, mInputChannel);
        ... ...
    }

/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

    public int addWindow(Session session, IWindow client, int seq,
            WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
            Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
            InputChannel outInputChannel) {
            ... ...
            WindowToken token = mTokenMap.get(attrs.token);
            ... ...
    }

三、StartingWindow

  • 点击应用图标时,启动应用Activity之前,WMS会先启动一个窗口StartingWindow用于过度。
startingwindow.jpg
  • StartingWindow启动流程
Startingwindow.png
  • StartingWindow关闭流程
StartingWindowEnd.png

四、Activity窗口创建流程

AMS.png
  1. 启动一个Activity时调用startActivityLocked

/frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

    final void startActivityLocked(ActivityRecord r, boolean newTask, boolean keepCurTransition,
            ActivityOptions options) {
        TaskRecord rTask = r.task;
        final int taskId = rTask.taskId;
        // mLaunchTaskBehind tasks get placed at the back of the task stack.
        if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
            insertTaskAtTop(rTask, r);
            //(1)将要打开Activity所在的task移到顶部
            mWindowManager.moveTaskToTop(taskId);
        }
        TaskRecord task = null;
        if (!newTask) {
            // If starting in an existing task, find where that is...
            boolean startIt = true;
            for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
                ... ...
                if (task == r.task) {
                    if (!startIt) {
                        if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to task "
                                + task, new RuntimeException("here").fillInStackTrace());
                        task.addActivityToTop(r);
                        r.putInHistory();
                        //(2)在这里调用addAppToken 创建AppWindowToken对象
                        addConfigOverride(r, task);
                        if (VALIDATE_TOKENS) {
                            validateAppTokensLocked();
                        }
                        ActivityOptions.abort(options);
                        return;
                    }
                    }
                    break;
                } else if (task.numFullscreen > 0) {
                    startIt = false;
                }
            }
        }

        ... ...
        if (!isHomeStack() || numActivities() > 0) {
            // We want to show the starting preview window if we are
            // switching to a new task, or the next activity's process is
            // not currently running.
            boolean showStartingIcon = newTask;
            ProcessRecord proc = r.app;
            if (proc == null) {
                proc = mService.mProcessNames.get(r.processName, r.info.applicationInfo.uid);
            }
            if (proc == null || proc.thread == null) {
                showStartingIcon = true;
            }
            if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                    "Prepare open transition: starting " + r);
            if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
                mWindowManager.prepareAppTransition(TRANSIT_NONE, keepCurTransition);
                mNoAnimActivities.add(r);
            } else {
                //(3)设置Activity切换动画类型,发送一个APP_TRANSITION_TIMEOUT的5s超时消息。
                mWindowManager.prepareAppTransition(newTask
                        ? r.mLaunchTaskBehind
                                ? TRANSIT_TASK_OPEN_BEHIND
                                : TRANSIT_TASK_OPEN
                        : TRANSIT_ACTIVITY_OPEN, keepCurTransition);
                mNoAnimActivities.remove(r);
            }
            addConfigOverride(r, task);
            ... ...
            if (r.mLaunchTaskBehind) {
                //(4)设置Activity可见性,什么情况下mLaunchTaskBehind???
                mWindowManager.setAppVisibility(r.appToken, true);
                ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
            } else if (SHOW_APP_STARTING_PREVIEW && doShow) {
                ActivityRecord prev = r.task.topRunningActivityWithStartingWindowLocked();
                ... ...
                //(5)显示StartingWindow
                r.showStartingWindow(prev, showStartingIcon);
            }
        } 
        ... ...
    }
  • 下面依次介绍WMS 中的(1)~(5)

/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

(1) moveTaskToTop

    public void moveTaskToTop(int taskId) {
        final long origId = Binder.clearCallingIdentity();
        try {
            synchronized(mWindowMap) {
                Task task = mTaskIdToTask.get(taskId);
                if (task == null) {
                    // Normal behavior, addAppToken will be called next and task will be created.
                    return;
                }
                final TaskStack stack = task.mStack;
                final DisplayContent displayContent = task.getDisplayContent();
                //将该task所属的栈 移至display的顶部
                displayContent.moveStack(stack, true);
                if (displayContent.isDefaultDisplay) {
                    final TaskStack homeStack = displayContent.getHomeStack();
                    if (homeStack != stack) {
                        // 将home移到display的底部                
                        displayContent.moveStack(homeStack, false);
                    }
                }
                //将task移到栈顶
                stack.moveTaskToTop(task);
                if (mAppTransition.isTransitionSet()) {
                    task.setSendingToBottom(false);
                }
                //更新窗口布局
                moveStackWindowsLocked(displayContent);
            }
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
    }

(2) addAppToken

    @Override
    public void addAppToken(int addPos, IApplicationToken token, int taskId, int stackId,
            int requestedOrientation, boolean fullscreen, boolean showForAllUsers, int userId,
            int configChanges, boolean voiceInteraction, boolean launchTaskBehind,
            Rect taskBounds, Configuration config, int taskResizeMode, boolean alwaysFocusable,
            boolean homeTask, int targetSdkVersion, int rotationAnimationHint) {
        ... ...

        synchronized(mWindowMap) {
            AppWindowToken atoken = findAppWindowToken(token.asBinder());
            if (atoken != null) {
                Slog.w(TAG_WM, "Attempted to add existing app token: " + token);
                return;
            }
            //创建AppWindowToken
            atoken = new AppWindowToken(this, token, voiceInteraction);
            atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
            atoken.appFullscreen = fullscreen;
            atoken.showForAllUsers = showForAllUsers;
            atoken.targetSdk = targetSdkVersion;
            atoken.requestedOrientation = requestedOrientation;
            atoken.layoutConfigChanges = (configChanges &
                    (ActivityInfo.CONFIG_SCREEN_SIZE | ActivityInfo.CONFIG_ORIENTATION)) != 0;
            atoken.mLaunchTaskBehind = launchTaskBehind;
            atoken.mAlwaysFocusable = alwaysFocusable;
            if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addAppToken: " + atoken
                    + " to stack=" + stackId + " task=" + taskId + " at " + addPos);
            atoken.mRotationAnimationHint = rotationAnimationHint;
            //找到或者创建所在task
            Task task = mTaskIdToTask.get(taskId);
            if (task == null) {
                task = createTaskLocked(taskId, stackId, userId, atoken, taskBounds, config);
            }
            task.addAppToken(addPos, atoken, taskResizeMode, homeTask);
            //将AppWindowToken对象添加到mTokenMap中
            mTokenMap.put(token.asBinder(), atoken);

            // Application tokens start out hidden.
            atoken.hidden = true;
            atoken.hiddenRequested = true;
        }
    }

(3) prepareAppTransition 设置Activity动画的类型和超时处理,真正执行动画要在Activity Resumed状态时,WMS 的executeAppTransition中。

    boolean prepareAppTransitionLocked(int transit, boolean alwaysKeepCurrent) {
        if (!isTransitionSet() || mNextAppTransition == TRANSIT_NONE) {
            // Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0 时设为TRANSIT_NONE
            setAppTransition(transit);
        } else if (!alwaysKeepCurrent) {
            if (transit == TRANSIT_TASK_OPEN && isTransitionEqual(TRANSIT_TASK_CLOSE)) {
                // newTask时将mNextAppTransition设为TRANSIT_TASK_OPEN
                setAppTransition(transit);
            } else if (transit == TRANSIT_ACTIVITY_OPEN
                    && isTransitionEqual(TRANSIT_ACTIVITY_CLOSE)) {
                // 将mNextAppTransition设为TRANSIT_ACTIVITY_OPEN
                setAppTransition(transit);
            }
        }
        boolean prepared = prepare();
        if (isTransitionSet()) {
            //5秒后被执行,是用来强制前面所设置的Activity组件切换动画要在5秒之内执行完成的,否则的话,WindowManagerService服务就会认为该切换动画执行超时了。
            mService.mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
            mService.mH.sendEmptyMessageDelayed(H.APP_TRANSITION_TIMEOUT, APP_TRANSITION_TIMEOUT_MS);
        }
        return prepared;
    }

(4)后面再说 ,(5)StartingWindow流程图见第三部分

startActivityLocked 主要完成了以下工作:
(1).将activity所在task移到顶部
(2).创建WindowToken并加到 WindowToken列表中
(3).设置activity切换动画的相关参数
(4).开启startingWindow

  1. Activity 进入onCreate和onResume阶段会调用到 ActivityStack.resumeTopActivityInnerLocked
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
 ... ... 
        //如果目标进程已存在onResume,否则onCreate
        if (next.app != null && next.app.thread != null) {
            if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next
                    + " stopped=" + next.stopped + " visible=" + next.visible);

            // If the previous activity is translucent, force a visibility update of
            // the next activity, so that it's added to WM's opening app list, and
            // transition animation can be set up properly.
            // For example, pressing Home button with a translucent activity in focus.
            // Launcher is already visible in this case. If we don't add it to opening
            // apps, maybeUpdateTransitToWallpaper() will fail to identify this as a
            // TRANSIT_WALLPAPER_OPEN animation, and run some funny animation.
            final boolean lastActivityTranslucent = lastStack != null
                    && (!lastStack.mFullscreen
                    || (lastStack.mLastPausedActivity != null
                    && !lastStack.mLastPausedActivity.fullscreen));

            //如果目标activity不可见之前的activity是半透明的, 那么使窗口可见
            if (!next.visible || next.stopped || lastActivityTranslucent) {
                mWindowManager.setAppVisibility(next.appToken, true);
            }
            ... ...
            try {
                ... ...

                // Well the app will no longer be stopped.
                // Clear app token stopped state in window manager if needed.
                mWindowManager.notifyAppResumed(next.appToken, next.stopped, allowSavedSurface);

                EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,
                        System.identityHashCode(next), next.task.taskId, next.shortComponentName);

                next.sleeping = false;
                mService.showUnsupportedZoomDialogIfNeededLocked(next);
                mService.showAskCompatModeDialogLocked(next);
                next.app.pendingUiClean = true;
                next.app.forceProcessStateUpTo(mService.mTopProcessState);
                next.clearOptionsLocked();
                //activity进入onResume
                next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
                        mService.isNextTransitionForward(), resumeAnimOptions);

                mStackSupervisor.checkReadyForSleepLocked();

                if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed " + next);
            } 

        } else {
            // Whoops, need to restart this activity!
            if (!next.hasBeenLaunched) {
                next.hasBeenLaunched = true;
            } else {
                if (SHOW_APP_STARTING_PREVIEW) {
                    next.showStartingWindow(null, true);
                }
                if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
            }
            if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
            //activity 进入attach 和onCreate流程
            mStackSupervisor.startSpecificActivityLocked(next, true, true);
        }

        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
        return true;
    }

第一次启动进入onCreate流程,跨进程调用应用端ActivityThread.handleLaunchActivity

    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
        ... ... 
        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);
            ... ... 
        }
    }

WindowManagerGlobal 用于应用端和WMS通信,服务端是Session,WindowManagerGlobal.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;
        }
    }

得到WMS 服务代理对象

再回到ActivityThread.handleLaunchActivity 函数,调用performLaunchActivity

/android/frameworks/base/core/java/android/app/ActivityThread.java

    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");

        ActivityInfo aInfo = r.activityInfo;
        if (r.packageInfo == null) {
            //创建LoadedApk对象
            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                    Context.CONTEXT_INCLUDE_CODE);
        }
        //创建ComponentName 对象
        ComponentName component = r.intent.getComponent();
        if (component == null) {
            component = r.intent.resolveActivity(
                mInitialApplication.getPackageManager());
            r.intent.setComponent(component);
        }

        if (r.activityInfo.targetActivity != null) {
            component = new ComponentName(r.activityInfo.packageName,
                    r.activityInfo.targetActivity);
        }

        Activity activity = null;
        try {
            //反射创建Activity对象
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
            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) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to instantiate activity " + component
                    + ": " + e.toString(), e);
            }
        }

        try {
            //创建Application 对象
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);

            if (activity != null) {
                Context appContext = createBaseContextForActivity(r, activity);
                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;
                }
                //调用activity.attach
                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);

                if (customIntent != null) {
                    activity.mIntent = customIntent;
                }
                r.lastNonConfigurationInstances = null;
                activity.mStartedActivity = false;
                int theme = r.activityInfo.getThemeResource();
                if (theme != 0) {
                    activity.setTheme(theme);
                }

                activity.mCalled = false;
                //这里回调Activity.onCreate
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                ... ...
                if (!r.activity.mFinished) {
                    activity.mCalled = false;
                    //回调Activity.onPostCreate,onPostCreate Activity view 初始化完毕后调用,可以用来得到Activity中view的高宽等
                    if (r.isPersistable()) {
                        mInstrumentation.callActivityOnPostCreate(activity, r.state,
                                r.persistentState);
                    } else {
                        mInstrumentation.callActivityOnPostCreate(activity, r.state);
                    }
                }
            }

        return activity;
    }

performLaunchActivity 函数中主要创建了LoadedApk、ComponentName、Activity对象,
并回调onCreate 和 onResume.

  • Activity.attach
    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*/);
        //创建PhoneWindow 对象,继承Window ,成员变量W,作为服务端 和WMS 通信
        mWindow = new PhoneWindow(this, window);
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
        if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
            mWindow.setSoftInputMode(info.softInputMode);
        }
        if (info.uiOptions != 0) {
            mWindow.setUiOptions(info.uiOptions);
        }
        mUiThread = Thread.currentThread();//得到ui 主线程

        mMainThread = aThread; //获取ActivityThread 对象
        mInstrumentation = instr;
        mToken = token;
        mIdent = ident;
        mApplication = application;
        mIntent = intent;
        mReferrer = referrer;
        mComponent = intent.getComponent();
        mActivityInfo = info;
        mTitle = title;
        mParent = parent;
        mEmbeddedID = id;
        mLastNonConfigurationInstances = lastNonConfigurationInstances;
        if (voiceInteractor != null) {
            if (lastNonConfigurationInstances != null) {
                mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
            } else {
                mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
                        Looper.myLooper());
            }
        }
        //获得WindowManagerImpl对象
        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;
    }

attach 函数中主要初始化各种变量:

  • PhoneWindow
  • ActivityThread
  • mUiThread
  • mToken
  • Window的WindowManagerImpl

再回到ActivityThread.handleLaunchActivity 函数,调用ActivityThread.handleResumeActivity

final void handleResumeActivity(IBinder token,
            boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
        ... ...
        //回调onResume
        r = performResumeActivity(token, clearHide, reason);

        ... ...
            if (r.window == null && !a.mFinished && willBeVisible) {
                ... ...
                if (a.mVisibleFromClient && !a.mWindowAdded) {
                    a.mWindowAdded = true;
                    //添加DecorView
                    wm.addView(decor, l);
                }

            // If the window has already been added, but during resume
            // we started another activity, then don't yet make the
            // window visible.
            } else if (!willBeVisible) {
                if (localLOGV) Slog.v(
                    TAG, "Launch " + r + " mStartedActivity set");
                r.hideForNow = true;
            }

            // Get rid of anything left hanging around.
            cleanUpPendingRemoveWindows(r, false /* force */);

            // 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) {
                ... ...
                //添加视图
                if (r.activity.mVisibleFromClient) {
                    r.activity.makeVisible();
                }
            }

            ... ...

            // Tell the activity manager we have resumed.
            if (reallyResume) {
                try {
                    ActivityManagerNative.getDefault().activityResumed(token);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            }

        } 
        ... ...
    }

  1. performResumeActivity回调onResume
  2. 添加DecorView
  3. r.activity.makeVisible()添加视图
  4. ActivityManagerNative.getDefault().activityResumed 通知AMS activty已经resumed
  • Activity.makeVisible
    void makeVisible() {
        if (!mWindowAdded) {
            ViewManager wm = getWindowManager();
            wm.addView(mDecor, getWindow().getAttributes());
            mWindowAdded = true;
        }
        mDecor.setVisibility(View.VISIBLE);
    }

调用WindowManagerImpl 的 addView方法,然后再调用WindowManagerGlobal.addView

  • WindowManagerGlobal.addView

/frameworks/base/core/java/android/view/WindowManagerGlobal.java

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

/frameworks/base/core/java/android/view/ViewRootImpl.java

    public ViewRootImpl(Context context, Display display) {
        mContext = context;
        mWindowSession = WindowManagerGlobal.getWindowSession();// WMS 的Session对象的代理端
        mDisplay = display;
        mBasePackageName = context.getBasePackageName();
        mThread = Thread.currentThread();
        ... ...
        mWindow = new W(this);//W是服务端用于跟WMS 的WindowState 通信
        ... ...
        mChoreographer = Choreographer.getInstance();
    }

初始化mWindowSession 和 mWindow,建立应用和WMS之间的通信。

session.PNG
  • WindowManagerGlobal.getWindowSession

/frameworks/base/core/java/android/view/WindowManagerGlobal.java

    public static IWindowSession getWindowSession() {
        synchronized (WindowManagerGlobal.class) {
            if (sWindowSession == null) {
                try {
                    InputMethodManager imm = InputMethodManager.getInstance();
                    IWindowManager windowManager = getWindowManagerService();
                    //sWindowSession 静态变量,一个应用进程中所有ViewRootImpl 对象中mWindowSession 都引用相同对象,用于和WMS通信
                    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;
        }
    }

跨进程调用WMS的openSession

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

应用端得到Session的代理对象

  • 回到WindowManagerGlobal.addView中的ViewRootImpl.setView
    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
        ... ... 
            try {

                res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                    getHostVisibility(), mDisplay.getDisplayId(),
                    mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                    mAttachInfo.mOutsets, mInputChannel);
            } 
        ... ... 
                   
    }
  • Session.addToDisplay直接调用WMS的addWindow
    /android/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
    public int addWindow(Session session, IWindow client, int seq,
            WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
            Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
            InputChannel outInputChannel) {
            ... ...
            //创建WindowState 对象
            WindowState win = new WindowState(this, session, client, token,
                    attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
            ... ...
            //调整窗口属性,例如截图窗口不能获得焦点
            mPolicy.adjustWindowParamsLw(win.mAttrs);
            ... ...
            win.attach();
            //以IWindow 代理对象作为key值
            mWindowMap.put(client.asBinder(), win);
            ... ...

            boolean focusChanged = false;
            if (win.canReceiveKeys()) {
                //如果能接受key事件,更新窗口焦点
                focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
                        false /*updateInputWindows*/);
                if (focusChanged) {
                    imMayMove = false;
                }
            }

    }

/frameworks/base/services/core/java/com/android/server/wm/WindowState.java

    WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
           WindowState attachedWindow, int appOp, int seq, WindowManager.LayoutParams a,
           int viewVisibility, final DisplayContent displayContent) {
        mService = service;
        mSession = s;//Session Binder 对象的服务端
        mClient = c;//W Binder 对象的客户端
        mAppOp = appOp;
        mToken = token;
        mOwnerUid = s.mUid;
        ... ...
        mContext = mService.mContext;
        //应用死掉后回调DeathRecipient
        DeathRecipient deathRecipient = new DeathRecipient();
        mSeq = seq;
        mEnforceSizeCompat = (mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0;
        if (WindowManagerService.localLOGV) Slog.v(
            TAG, "Window " + this + " client=" + c.asBinder()
            + " token=" + token + " (" + mAttrs.token + ")" + " params=" + a);
        try {
            //c在应用进程
            c.asBinder().linkToDeath(deathRecipient, 0);
        } 

     }

    void attach() {
        if (WindowManagerService.localLOGV) Slog.v(
            TAG, "Attaching " + this + " token=" + mToken
            + ", list=" + mToken.windows);
        mSession.windowAddedLocked();
    }
    void windowAddedLocked() {
        if (mSurfaceSession == null) {
            if (WindowManagerService.localLOGV) Slog.v(
                TAG_WM, "First window added to " + this + ", creating SurfaceSession");
            mSurfaceSession = new SurfaceSession();
            if (SHOW_TRANSACTIONS) Slog.i(
                    TAG_WM, "  NEW SURFACE SESSION " + mSurfaceSession);
            //将当前Session对象添加到WMS Sessions 列表中
            mService.mSessions.add(this);
            if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) {
                mService.dispatchNewAnimatorScaleLocked(this);
            }
        }
        mNumWindow++;
    }
  • WMS.updateFocusedWindowLocked
    boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
        //计算当前获得focus的窗口
        WindowState newFocus = computeFocusedWindowLocked();
        ... ...

            int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);

            if (imWindowChanged && oldFocus != mInputMethodWindow) {
                // Focus of the input method window changed. Perform layout if needed.
                if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
                    mWindowPlacerLocked.performLayoutLockedInner(displayContent, true /*initial*/,
                            updateInputWindows);
                    focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
                } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
                    // Client will do the layout, but we need to assign layers
                    // for handleNewWindowLocked() below.
                    mLayersController.assignLayersLocked(displayContent.getWindowList());
                }
            }

            if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
                // The change in focus caused us to need to do a layout.  Okay.
                displayContent.layoutNeeded = true;
                if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
                    //焦点改变重新计算窗口大小
                    mWindowPlacerLocked.performLayoutLockedInner(displayContent, true /*initial*/,
                            updateInputWindows);
                }
            }
       }

/android/frameworks/base/services/core/java/com/android/server/wm/WindowSurfacePlacer.java

   final void performLayoutLockedInner(final DisplayContent displayContent,
           boolean initial, boolean updateInputWindows) {
       ... ...
       //设置屏幕大小
       mService.mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mService.mRotation,
               mService.mCurConfiguration.uiMode);
        ... ...

        for (i = topAttached; i >= 0; i--) {
            final WindowState win = windows.get(i);

            if (win.mLayoutAttached) {
                ... ...
                    win.mLayoutNeeded = false;
                    win.prelayout();
                    //计算各层窗口大小
                    mService.mPolicy.layoutWindowLw(win, win.mAttachedWindow);
                    win.mLayoutSeq = seq;
                }
            } else if (win.mAttrs.type == TYPE_DREAM) {
                attachedBehindDream = behindDream;
            }
        }
        ... ...
        //执行清理工作
        mService.mPolicy.finishLayoutLw();
        mService.mH.sendEmptyMessage(UPDATE_DOCKED_STACK_DIVIDER);
    }
  • 总结

Activity窗口启动流程

  1. 调用startActivity进入Activity生命周期之前主要完成了以下工作:

(1).将activity所在task移到顶部

(2).创建WindowToken并加到 WindowToken列表中

(3).设置activity切换动画的相关参数

(4).开启startingWindow

  1. 进入Activity的attach、onCreate、onResume

(1) 创建LoadedApk、ComponentName、Activity对象

(2) 在attach 函数中初始化变量:PhoneWindow, ActivityThread, mUiThread, mToken, Window的WindowManagerImpl

(3) 执行performResumeActivity,回调onResume,添加DecorView, r.activity.makeVisible()添加视图

(4)创建 ViewRootImpl对象,ViewRootImpl中创建IWindow的服务端对象和IWindowSession的代理对象,用于应用和WMS之前通信,一个应用进程中所有ViewRootImpl 对象中的IWindowSession代理对象都引用相同对象。

(5)最后调用WMS.addWindow 计算和添加窗口。

五、主要类关系图

all.PNG

参考博客

  1. http://gityuan.com/2017/01/08/windowmanger/
  2. http://blog.csdn.net/guoqifa29/article/details/46819377
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,290评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,399评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,021评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,034评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,412评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,651评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,902评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,605评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,339评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,586评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,076评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,400评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,060评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,851评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,685评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,595评论 2 270

推荐阅读更多精彩内容