Android 12系统源码_窗口管理(四)RootWindowContainer简介

前言

在Android 12中,RootWindowContainer是一个重要的类,它是WindowManagerService的主要组成部分之一,它是一个管理窗口的容器,其主要作用是管理整个系统中所有窗口的层级关系和布局。它负责跟踪和管理所有窗口,包括应用程序窗口、系统窗口、通知窗口和浮动窗口等。

RootWindowContainer还负责管理窗口的生命周期,包括创建、销毁和显示窗口。它会在窗口被添加或删除时更新窗口的层级关系,以确保所有窗口都能正确地显示在屏幕上。

此外,RootWindowContainer还负责处理多个屏幕和显示设备的情况,以确保多个窗口正确地显示在不同的屏幕上。

一、RootWindowContainer的创建

1、RootWindowContainer是在WindowManagerService的构造方法中被创建的。

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

public class WindowManagerService extends IWindowManager.Stub
        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
        
    //屏幕设备窗口的根容器管理者
    RootWindowContainer mRoot;

    private WindowManagerService(Context context, InputManagerService inputManager,
                                 boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy,
                                 ActivityTaskManagerService atm, DisplayWindowSettingsProvider
                                         displayWindowSettingsProvider, Supplier<SurfaceControl.Transaction> transactionFactory,
                                 Supplier<Surface> surfaceFactory,
                                 Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {
        ...代码省略...
        mRoot = new RootWindowContainer(this);
		...代码省略...
	}
}

二、RootWindowContainer类定义

1、RootWindowContainerd的源码位置如下所示。

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

class RootWindowContainer extends WindowContainer<DisplayContent>
        implements DisplayManager.DisplayListener {
        
        private final Handler mHandler;
        // Only a separate transaction until we separate the apply surface changes
		// transaction from the global transaction.
		private final SurfaceControl.Transaction mDisplayTransaction;
		/** The token acquirer to put root tasks on the displays to sleep */
   	 	final ActivityTaskManagerInternal.SleepTokenAcquirer mDisplayOffTokenAcquirer;
	    ActivityTaskManagerService mService;
	    ActivityTaskSupervisor mTaskSupervisor;

       RootWindowContainer(WindowManagerService service) {
        super(service);
        mDisplayTransaction = service.mTransactionFactory.get();
        mHandler = new MyHandler(service.mH.getLooper());
        mService = service.mAtmService;
        mTaskSupervisor = mService.mTaskSupervisor;
        mTaskSupervisor.mRootWindowContainer = this;
        mDisplayOffTokenAcquirer = mService.new SleepTokenAcquirerImpl(DISPLAY_OFF_SLEEP_TOKEN_TAG);
    }
  }

2、RootWindowContainerd类的主要属性如下所示。

class RootWindowContainer extends WindowContainer<DisplayContent>
        implements DisplayManager.DisplayListener {
    private static final String TAG = TAG_WITH_CLASS_NAME ? "RootWindowContainer" : TAG_WM;

    private static final int SET_SCREEN_BRIGHTNESS_OVERRIDE = 1;
    private static final int SET_USER_ACTIVITY_TIMEOUT = 2;
    static final String TAG_TASKS = TAG + POSTFIX_TASKS;
    static final String TAG_STATES = TAG + POSTFIX_STATES;
    private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;

    private Object mLastWindowFreezeSource = null;
    private Session mHoldScreen = null;
    private float mScreenBrightnessOverride = PowerManager.BRIGHTNESS_INVALID_FLOAT;
    private long mUserActivityTimeout = -1;
    private boolean mUpdateRotation = false;
    // Following variables are for debugging screen wakelock only.
    // Last window that requires screen wakelock
    WindowState mHoldScreenWindow = null;
    // Last window that obscures all windows below
    WindowState mObscuringWindow = null;
    // Only set while traversing the default display based on its content.
    // Affects the behavior of mirroring on secondary displays.
    private boolean mObscureApplicationContentOnSecondaryDisplays = false;

    private boolean mSustainedPerformanceModeEnabled = false;
    private boolean mSustainedPerformanceModeCurrent = false;

    // During an orientation change, we track whether all windows have rendered
    // at the new orientation, and this will be false from changing orientation until that occurs.
    // For seamless rotation cases this always stays true, as the windows complete their orientation
    // changes 1 by 1 without disturbing global state.
    boolean mOrientationChangeComplete = true;
    boolean mWallpaperActionPending = false;

    private final Handler mHandler;

    //关闭系统弹窗的原因
    private String mCloseSystemDialogsReason;

    // The ID of the display which is responsible for receiving display-unspecified key and pointer
    // events.
    //最顶部获取焦点的屏幕设备对象id
    private int mTopFocusedDisplayId = INVALID_DISPLAY;

    // Map from the PID to the top most app which has a focused window of the process.
    //以进程号为key,ActivityRecord为value,存储了当前应用最上层获取焦点的窗口
    final ArrayMap<Integer, ActivityRecord> mTopFocusedAppByProcess = new ArrayMap<>();

    // Only a separate transaction until we separate the apply surface changes
    // transaction from the global transaction.
    //屏幕设备对应的事务
    private final SurfaceControl.Transaction mDisplayTransaction;

    // The tag for the token to put root tasks on the displays to sleep.
    private static final String DISPLAY_OFF_SLEEP_TOKEN_TAG = "Display-off";

    /** The token acquirer to put root tasks on the displays to sleep */
    final ActivityTaskManagerInternal.SleepTokenAcquirer mDisplayOffTokenAcquirer;

    /**
     * The modes which affect which tasks are returned when calling
     * {@link RootWindowContainer#anyTaskForId(int)}.
     */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({
            MATCH_ATTACHED_TASK_ONLY,
            MATCH_ATTACHED_TASK_OR_RECENT_TASKS,
            MATCH_ATTACHED_TASK_OR_RECENT_TASKS_AND_RESTORE
    })
    public @interface AnyTaskForIdMatchTaskMode {
    }

    // Match only tasks that are attached to the hierarchy
    static final int MATCH_ATTACHED_TASK_ONLY = 0;
    // Match either attached tasks, or in the recent tasks if the tasks are detached
    static final int MATCH_ATTACHED_TASK_OR_RECENT_TASKS = 1;
    // Match either attached tasks, or in the recent tasks, restoring it to the provided task id
    static final int MATCH_ATTACHED_TASK_OR_RECENT_TASKS_AND_RESTORE = 2;

    ActivityTaskManagerService mService;
    ActivityTaskSupervisor mTaskSupervisor;
    WindowManagerService mWindowManager;
    DisplayManager mDisplayManager;
    private DisplayManagerInternal mDisplayManagerInternal;

    /** Reference to default display so we can quickly look it up. */
    private DisplayContent mDefaultDisplay;
    private final SparseArray<IntArray> mDisplayAccessUIDs = new SparseArray<>();

    /** The current user */
    int mCurrentUser;
    /** Root task id of the front root task when user switched, indexed by userId. */
    SparseIntArray mUserRootTaskInFront = new SparseIntArray(2);

    /**
     * A list of tokens that cause the top activity to be put to sleep.
     * They are used by components that may hide and block interaction with underlying
     * activities.
     */
    final SparseArray<SleepToken> mSleepTokens = new SparseArray<>();

    // The default minimal size that will be used if the activity doesn't specify its minimal size.
    // It will be calculated when the default display gets added.
    int mDefaultMinSizeOfResizeableTaskDp = -1;

    // Whether tasks have moved and we need to rank the tasks before next OOM scoring
    private boolean mTaskLayersChanged = true;
    private int mTmpTaskLayerRank;
    private final RankTaskLayersRunnable mRankTaskLayersRunnable = new RankTaskLayersRunnable();

    private boolean mTmpBoolean;
    private RemoteException mTmpRemoteException;

    private String mDestroyAllActivitiesReason;
    private final Runnable mDestroyAllActivitiesRunnable = new Runnable() {
        @Override
        public void run() {
            synchronized (mService.mGlobalLock) {
                try {
                    mTaskSupervisor.beginDeferResume();

                    final PooledConsumer c = PooledLambda.obtainConsumer(
                            RootWindowContainer::destroyActivity, RootWindowContainer.this,
                            PooledLambda.__(ActivityRecord.class));
                    forAllActivities(c);
                    c.recycle();
                } finally {
                    mTaskSupervisor.endDeferResume();
                    resumeFocusedTasksTopActivities();
                }
            }
        }

    };

    private final FindTaskResult mTmpFindTaskResult = new FindTaskResult();

    static class FindTaskResult implements Function<Task, Boolean> {
        ActivityRecord mIdealRecord;
        ActivityRecord mCandidateRecord;

        private int mActivityType;
        private String mTaskAffinity;
        private Intent mIntent;
        private ActivityInfo mInfo;
        private ComponentName cls;
        private int userId;
        private boolean isDocument;
        private Uri documentData;

        void init(int activityType, String taskAffinity, Intent intent, ActivityInfo info) {
            mActivityType = activityType;
            mTaskAffinity = taskAffinity;
            mIntent = intent;
            mInfo = info;
            mIdealRecord = null;
            mCandidateRecord = null;
        }

        /**
         * Returns the top activity in any existing task matching the given Intent in the input
         * result. Returns null if no such task is found.
         */
        void process(WindowContainer parent) {
            cls = mIntent.getComponent();
            if (mInfo.targetActivity != null) {
                cls = new ComponentName(mInfo.packageName, mInfo.targetActivity);
            }
            userId = UserHandle.getUserId(mInfo.applicationInfo.uid);
            isDocument = mIntent != null & mIntent.isDocument();
            // If documentData is non-null then it must match the existing task data.
            documentData = isDocument ? mIntent.getData() : null;

            ProtoLog.d(WM_DEBUG_TASKS, "Looking for task of %s in %s", mInfo,
                    parent);
            parent.forAllLeafTasks(this);
        }

        @Override
        public Boolean apply(Task task) {
            if (!ConfigurationContainer.isCompatibleActivityType(mActivityType,
                    task.getActivityType())) {
                ProtoLog.d(WM_DEBUG_TASKS, "Skipping task: (mismatch activity/task) %s", task);
                return false;
            }

            if (task.voiceSession != null) {
                // We never match voice sessions; those always run independently.
                ProtoLog.d(WM_DEBUG_TASKS, "Skipping %s: voice session", task);
                return false;
            }
            if (task.mUserId != userId) {
                // Looking for a different task.
                ProtoLog.d(WM_DEBUG_TASKS, "Skipping %s: different user", task);
                return false;
            }

            if (matchingCandidate(task)) {
                return true;
            }

            // Looking for the embedded tasks (if any)
            return !task.isLeafTaskFragment() && task.forAllLeafTaskFragments(
                    this::matchingCandidate);
        }

        boolean matchingCandidate(TaskFragment taskFragment) {
            final Task task = taskFragment.asTask();
            if (task == null) {
                return false;
            }

            // Overlays should not be considered as the task's logical top activity.
            // Activities of the tasks that embedded from this one should not be used.
            final ActivityRecord r = task.getTopNonFinishingActivity(false /* includeOverlays */,
                    false /* includingEmbeddedTask */);

            if (r == null || r.finishing || r.mUserId != userId
                    || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
                ProtoLog.d(WM_DEBUG_TASKS, "Skipping %s: mismatch root %s", task, r);
                return false;
            }
            if (!ConfigurationContainer.isCompatibleActivityType(r.getActivityType(),
                    mActivityType)) {
                ProtoLog.d(WM_DEBUG_TASKS, "Skipping %s: mismatch activity type", task);
                return false;
            }

            final Intent taskIntent = task.intent;
            final Intent affinityIntent = task.affinityIntent;
            final boolean taskIsDocument;
            final Uri taskDocumentData;
            if (taskIntent != null && taskIntent.isDocument()) {
                taskIsDocument = true;
                taskDocumentData = taskIntent.getData();
            } else if (affinityIntent != null && affinityIntent.isDocument()) {
                taskIsDocument = true;
                taskDocumentData = affinityIntent.getData();
            } else {
                taskIsDocument = false;
                taskDocumentData = null;
            }

            ProtoLog.d(WM_DEBUG_TASKS, "Comparing existing cls=%s /aff=%s to new cls=%s /aff=%s",
                    r.getTask().rootAffinity, mIntent.getComponent().flattenToShortString(),
                    mInfo.taskAffinity, (task.realActivity != null
                            ? task.realActivity.flattenToShortString() : ""));
            // TODO Refactor to remove duplications. Check if logic can be simplified.
            if (task.realActivity != null && task.realActivity.compareTo(cls) == 0
                    && Objects.equals(documentData, taskDocumentData)) {
                ProtoLog.d(WM_DEBUG_TASKS, "Found matching class!");
                //dump();
                ProtoLog.d(WM_DEBUG_TASKS, "For Intent %s bringing to top: %s", mIntent, r.intent);
                mIdealRecord = r;
                return true;
            } else if (affinityIntent != null && affinityIntent.getComponent() != null
                    && affinityIntent.getComponent().compareTo(cls) == 0 &&
                    Objects.equals(documentData, taskDocumentData)) {
                ProtoLog.d(WM_DEBUG_TASKS, "Found matching class!");
                ProtoLog.d(WM_DEBUG_TASKS, "For Intent %s bringing to top: %s", mIntent, r.intent);
                mIdealRecord = r;
                return true;
            } else if (!isDocument && !taskIsDocument
                    && mIdealRecord == null && mCandidateRecord == null
                    && task.rootAffinity != null) {
                if (task.rootAffinity.equals(mTaskAffinity)) {
                    ProtoLog.d(WM_DEBUG_TASKS, "Found matching affinity candidate!");
                    // It is possible for multiple tasks to have the same root affinity especially
                    // if they are in separate root tasks. We save off this candidate, but keep
                    // looking to see if there is a better candidate.
                    mCandidateRecord = r;
                }
            } else {
                ProtoLog.d(WM_DEBUG_TASKS, "Not a match: %s", task);
            }

            return false;
        }
    }

    private final Consumer<WindowState> mCloseSystemDialogsConsumer = w -> {
        if (w.mHasSurface) {
            try {
                w.mClient.closeSystemDialogs(mCloseSystemDialogsReason);
            } catch (RemoteException e) {
            }
        }
    };

    private static final Consumer<WindowState> sRemoveReplacedWindowsConsumer = w -> {
        final ActivityRecord activity = w.mActivityRecord;
        if (activity != null) {
            activity.removeReplacedWindowIfNeeded(w);
        }
    };
}

3、RootWindowContainerd类的主要方法如下所示。

class RootWindowContainer extends WindowContainer<DisplayContent>
        implements DisplayManager.DisplayListener {
        
    // 当窗口焦点发生变化的时候,更新窗口焦点的变化 add by syl
    boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
        Log.d("SystemBar", "RootWindowContainer_updateFocusedWindowLocked");
        mTopFocusedAppByProcess.clear();
        boolean changed = false;
        int topFocusedDisplayId = INVALID_DISPLAY;
        for (int i = mChildren.size() - 1; i >= 0; --i) {
            final DisplayContent dc = mChildren.get(i);
            changed |= dc.updateFocusedWindowLocked(mode, updateInputWindows, topFocusedDisplayId);
            final WindowState newFocus = dc.mCurrentFocus;
            if (newFocus != null) {
                final int pidOfNewFocus = newFocus.mSession.mPid;
                if (mTopFocusedAppByProcess.get(pidOfNewFocus) == null) {
                    mTopFocusedAppByProcess.put(pidOfNewFocus, newFocus.mActivityRecord);
                }
                if (topFocusedDisplayId == INVALID_DISPLAY) {
                    topFocusedDisplayId = dc.getDisplayId();
                }
            } else if (topFocusedDisplayId == INVALID_DISPLAY && dc.mFocusedApp != null) {
                // The top-most display that has a focused app should still be the top focused
                // display even when the app window is not ready yet (process not attached or
                // window not added yet).
                topFocusedDisplayId = dc.getDisplayId();
            }
        }
        if (topFocusedDisplayId == INVALID_DISPLAY) {
            topFocusedDisplayId = DEFAULT_DISPLAY;
        }
        if (mTopFocusedDisplayId != topFocusedDisplayId) {
            mTopFocusedDisplayId = topFocusedDisplayId;
            mWmService.mInputManager.setFocusedDisplay(topFocusedDisplayId);
            mWmService.mPolicy.setTopFocusedDisplay(topFocusedDisplayId);
            mWmService.mAccessibilityController.setFocusedDisplay(topFocusedDisplayId);
            ProtoLog.d(WM_DEBUG_FOCUS_LIGHT, "New topFocusedDisplayId=%d", topFocusedDisplayId);
        }
        return changed;
    }
 }

你可能感兴趣的:(Framework12源码,android,frameworks)