Android U 自由窗口(浮窗)——补充

0 阅读5分钟

生命周期相关

这里还是以多任务中启动自由窗口为例

//进入多任务
01-20 10:36:00.892  1399  1399 I wm_on_restart_called: [77094127,com.android.launcher3.uioverrides.QuickstepLauncher,performRestart,0]
01-20 10:36:00.917  1399  1399 I wm_on_start_called: [77094127,com.android.launcher3.uioverrides.QuickstepLauncher,handleStartActivity,25]
01-20 10:36:00.920  1399  1399 I wm_on_resume_called: [77094127,com.android.launcher3.uioverrides.QuickstepLauncher,RESUME_ACTIVITY,0]
01-20 10:36:01.011  1399  1399 I wm_on_top_resumed_gained_called: [77094127,com.android.launcher3.uioverrides.QuickstepLauncher,topStateChangedWhenResumed]

//启动自由窗口
01-20 10:36:26.706  1399  1399 I wm_on_top_resumed_lost_called: [77094127,com.android.launcher3.uioverrides.QuickstepLauncher,topStateChangedWhenResumed]
01-20 10:36:26.736  2378  2378 I wm_on_stop_called: [180634051,com.android.messaging.ui.conversationlist.ConversationListActivity,handleRelaunchActivity,0]
01-20 10:36:26.756  2378  2378 I wm_on_destroy_called: [180634051,com.android.messaging.ui.conversationlist.ConversationListActivity,performDestroy,10]
01-20 10:36:26.930  2378  2378 I wm_on_create_called: [180634051,com.android.messaging.ui.conversationlist.ConversationListActivity,performCreate,64]
01-20 10:36:26.938  2378  2378 I wm_on_start_called: [180634051,com.android.messaging.ui.conversationlist.ConversationListActivity,handleStartActivity,0]
01-20 10:36:27.006  2378  2378 I wm_on_resume_called: [180634051,com.android.messaging.ui.conversationlist.ConversationListActivity,RESUME_ACTIVITY,53]
01-20 10:36:27.072  2378  2378 I wm_on_top_resumed_gained_called: [180634051,com.android.messaging.ui.conversationlist.ConversationListActivity,topStateChangedWhenResumed]

发现 启动自由窗口时底层activity(launcher3)不会进行pause。 一般来说当一个应用resume,那么当前应用就会走pause流程,我们这里launcher3为什么没有走pause呢?我们简单跟踪一下流程。 代码路径:frameworks/base/services/core/java/com/android/server/wm/TaskFragment.java

    final boolean resumeTopActivity(ActivityRecord prev, ActivityOptions options,
            boolean deferPause) {
            ......
            boolean pausing = !deferPause && taskDisplayArea.pauseBackTasks(next);

先看这个resume流程,这会去判断是否需要pause。 这里deferPause的值是通过Task.resumeTopActivityUncheckedLocked方法中传递过来的,其值为false,因此!deferPause为true。 next指的是要启动的activity(我们这里是ConversationListActivity)。

代码路径:frameworks/base/services/core/java/com/android/server/wm/TaskDisplayArea.java

    /**
     * Pause all activities in either all of the root tasks or just the back root tasks. This is
     * done before resuming a new activity and to make sure that previously active activities are
     * paused in root tasks that are no longer visible or in pinned windowing mode. This does not
     * pause activities in visible root tasks, so if an activity is launched within the same root
     * task, hen we should explicitly pause that root task's top activity.
     *
     * @param resuming    The resuming activity.
     * @return {@code true} if any activity was paused as a result of this call.
     */
    boolean pauseBackTasks(ActivityRecord resuming) {
        final int[] someActivityPaused = {0};
        forAllLeafTasks(leafTask -> {
            // Check if the direct child resumed activity in the leaf task needed to be paused if
            // the leaf task is not a leaf task fragment.
            //task fragment场景,暂不关注
            if (!leafTask.isLeafTaskFragment()) {
                final ActivityRecord top = topRunningActivity();
                final ActivityRecord resumedActivity = leafTask.getResumedActivity();
                if (resumedActivity != null && top.getTaskFragment() != leafTask) {
                    // Pausing the resumed activity because it is occluded by other task fragment.
                    if (leafTask.startPausing(false /* uiSleeping*/, resuming, "pauseBackTasks")) {
                        someActivityPaused[0]++;
                    }
                }
            }
            
            //遍历所有leafTask节点,即最底端Task节点
            leafTask.forAllLeafTaskFragments((taskFrag) -> {
                final ActivityRecord resumedActivity = taskFrag.getResumedActivity();
                //判断当前taskFrag是否有存在resumed的Activity,并且即将启动的Activity不能resumed
                if (resumedActivity != null && !taskFrag.canBeResumed(resuming)) {
                     //暂停当前存在resumed的Activity
                    if (taskFrag.startPausing(false /* uiSleeping*/, resuming, "pauseBackTasks")) {
                        //记录暂停的Activity
                        someActivityPaused[0]++;
                    }
                }
            }, true /* traverseTopToBottom */);
        }, true /* traverseTopToBottom */);
        return someActivityPaused[0] > 0;
    }

这个方法会遍历TaskDisplayArea下的所有leafTask节点,即最底端Task节点

  1. 判断当前Task的Activity是否存在resumed状态,且即将启动的Activity不能被resumed
  2. 暂停当前存在resumed的Activity,若暂停成功,给参数someActivityPaused计数

如下图圈的task节点是会遍历的task节点。 在这里插入图片描述 在该界面当我们点击启动自由窗口后开始条件判断resumedActivity != null && !taskFrag.canBeResumed(resuming)taskFrag.getResumedActivity()获取此时是resumed状态的task,当遍历到桌面Task时,由于我们要从多任务进入到自由窗口,而此时多任务界面为resumed状态,存在resumed状态的Activity,因此参数resumedActivity不为空。 这里resumedActivity != null为true,再来看看!taskFrag.canBeResumed(resuming)其中参数resuming指的是即将启动的Activity(ConversationListActivity)。

代码路径:frameworks/base/services/core/java/com/android/server/wm/TaskFragment.java

    /**
     * Returns {@code true} is the activity in this TaskFragment can be resumed.
     *
     * @param starting The currently starting activity or {@code null} if there is none.
     */
    boolean canBeResumed(@Nullable ActivityRecord starting) {
        // No need to resume activity in TaskFragment that is not visible.
        return isTopActivityFocusable()
                && getVisibility(starting) == TASK_FRAGMENT_VISIBILITY_VISIBLE;
    }

isTopActivityFocusable()判断顶部Activity是否可聚焦,一般为true,这里主要关注getVisibility(starting)方法,通样传递starting即将启动的的Activity (ConversationListActivity)。

    /**
     * Returns the visibility state of this TaskFragment.
     *
     * @param starting The currently starting activity or null if there is none.
     */
    @TaskFragmentVisibility
    int getVisibility(ActivityRecord starting) {
        ......
        //根据上述代码流程,这里this指的是桌面task,因此此时getParent获取的是桌面task的task
        final WindowContainer<?> parent = getParent();
        ......
        // This TaskFragment is only considered visible if all its parent TaskFragments are
        // considered visible, so check the visibility of all ancestor TaskFragment first.
        
        //判断parent是否是task或者TaskFragment
        if (parent.asTaskFragment() != null) {
            //递归调用getVisibility,直到parent为TaskDisplayArea(不是task)为止。
            //其目的是为了能够遍历到TaskDisplayArea下所有task节点
            final int parentVisibility = parent.asTaskFragment().getVisibility(starting);
            if (parentVisibility == TASK_FRAGMENT_VISIBILITY_INVISIBLE) {
                // Can't be visible if parent isn't visible
                return TASK_FRAGMENT_VISIBILITY_INVISIBLE;
            } else if (parentVisibility == TASK_FRAGMENT_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT) {
                // Parent is behind a translucent container so the highest visibility this container
                // can get is that.
                gotTranslucentFullscreen = true;
            }
        }
        
        final List<TaskFragment> adjacentTaskFragments = new ArrayList<>();
        //逆序遍历parent下的task,即优先最前台,从大到小遍历
        for (int i = parent.getChildCount() - 1; i >= 0; --i) {
            final WindowContainer other = parent.getChildAt(i);
            if (other == null) continue;

            //判断other是否是运行中的Activity
            final boolean hasRunningActivities = hasRunningActivity(other);
            //other和this相同则中断循环,做后续处理
            if (other == this) {
                ......
                // Should be visible if there is no other fragment occluding it, unless it doesn't
                // have any running activities, not starting one and not home stack.
                shouldBeVisible = hasRunningActivities
                        || (starting != null && starting.isDescendantOf(this))
                        || isActivityTypeHome();
                break;
            }

            if (!hasRunningActivities) {
                continue;
            }

            //根据other的WindowingMode判断返回值
            final int otherWindowingMode = other.getWindowingMode();
            if (otherWindowingMode == WINDOWING_MODE_FULLSCREEN) {
                if (isTranslucent(other, starting)) {
                    // Can be visible behind a translucent fullscreen TaskFragment.
                    gotTranslucentFullscreen = true;
                    continue;
                }
                return TASK_FRAGMENT_VISIBILITY_INVISIBLE;
            } else if (otherWindowingMode == WINDOWING_MODE_MULTI_WINDOW
                    && other.matchParentBounds()) {
                if (isTranslucent(other, starting)) {
                    // Can be visible behind a translucent TaskFragment.
                    gotTranslucentFullscreen = true;
                    continue;
                }
                // Multi-window TaskFragment that matches parent bounds would occlude other children
                return TASK_FRAGMENT_VISIBILITY_INVISIBLE;
            }

            ......

        }
        
        if (!shouldBeVisible) {
            return TASK_FRAGMENT_VISIBILITY_INVISIBLE;
        }
        
        // Lastly - check if there is a translucent fullscreen TaskFragment on top.
        return gotTranslucentFullscreen
                ? TASK_FRAGMENT_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT
                : TASK_FRAGMENT_VISIBILITY_VISIBLE;
    }

简单来说这个方法就是判断当前启动之后的activity的WindowingMode如果不是WINDOWING_MODE_FULLSCREEN或者WINDOWING_MODE_MULTI_WINDOW那么就返回TASK_FRAGMENT_VISIBILITY_VISIBLE,使后台应用可见,不进入到pause流程。

因此启动自由窗口时底层activity(launcher3)不会进行pause。